scan_includes.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. #include <getopt.h>
  6. void usage(void) {
  7. printf("Usage: scan_includes [-h] [-s] filename\n"
  8. "-h, --help\n"
  9. " Print usage and exit\n"
  10. "-s, --strict\n"
  11. " Fail if a file cannot be read\n");
  12. }
  13. struct Options {
  14. bool help;
  15. bool strict;
  16. };
  17. struct Options Options = {0};
  18. void scan_file(char* filename) {
  19. FILE *f = fopen(filename, "rb");
  20. if (!f) {
  21. if (Options.strict) {
  22. fprintf(stderr, "Could not open file: '%s'\n", filename);
  23. exit(1);
  24. } else {
  25. return;
  26. }
  27. }
  28. fseek(f, 0, SEEK_END);
  29. long size = ftell(f);
  30. rewind(f);
  31. char *buffer = malloc(size + 1);
  32. char *orig = buffer;
  33. size = fread(buffer, 1, size, f);
  34. buffer[size] = '\0';
  35. fclose(f);
  36. for (; buffer && (buffer - orig < size); buffer++) {
  37. bool is_include = false;
  38. bool is_incbin = false;
  39. switch (*buffer) {
  40. case ';':
  41. buffer = strchr(buffer, '\n');
  42. if (!buffer) {
  43. fprintf(stderr, "%s: no newline at end of file\n", filename);
  44. break;
  45. }
  46. break;
  47. case '"':
  48. buffer++;
  49. buffer = strchr(buffer, '"');
  50. if (!buffer) {
  51. fprintf(stderr, "%s: unterminated string\n", filename);
  52. break;
  53. }
  54. buffer++;
  55. break;
  56. case 'i':
  57. case 'I':
  58. if ((strncmp(buffer, "INCBIN", 6) == 0) || (strncmp(buffer, "incbin", 6) == 0)) {
  59. is_incbin = true;
  60. } else if ((strncmp(buffer, "INCLUDE", 7) == 0) || (strncmp(buffer, "include", 7) == 0)) {
  61. is_include = true;
  62. }
  63. if (is_incbin || is_include) {
  64. buffer = strchr(buffer, '"');
  65. if (!buffer) {
  66. break;
  67. }
  68. buffer++;
  69. int length = strcspn(buffer, "\"");
  70. char *include = malloc(length + 1);
  71. strncpy(include, buffer, length);
  72. include[length] = '\0';
  73. printf("%s ", include);
  74. if (is_include) {
  75. scan_file(include);
  76. }
  77. free(include);
  78. buffer = strchr(buffer, '"');
  79. }
  80. break;
  81. }
  82. if (!buffer) {
  83. break;
  84. }
  85. }
  86. free(orig);
  87. }
  88. int main(int argc, char* argv[]) {
  89. int i = 0;
  90. struct option long_options[] = {
  91. {"strict", no_argument, 0, 's'},
  92. {"help", no_argument, 0, 'h'},
  93. {0}
  94. };
  95. int opt = -1;
  96. while ((opt = getopt_long(argc, argv, "sh", long_options, &i)) != -1) {
  97. switch (opt) {
  98. case 's':
  99. Options.strict = true;
  100. break;
  101. case 'h':
  102. Options.help = true;
  103. break;
  104. default:
  105. usage();
  106. exit(1);
  107. break;
  108. }
  109. }
  110. argc -= optind;
  111. argv += optind;
  112. if (Options.help) {
  113. usage();
  114. return 0;
  115. }
  116. if (argc < 1) {
  117. usage();
  118. exit(1);
  119. }
  120. scan_file(argv[0]);
  121. return 0;
  122. }