3
0

mkdep.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * Originally by Linus Torvalds.
  3. * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
  4. *
  5. * Usage: mkdep cflags -- file ...
  6. *
  7. * Read source files and output makefile dependency lines for them.
  8. * I make simple dependency lines for #include <*.h> and #include "*.h".
  9. * I also find instances of CONFIG_FOO and generate dependencies
  10. * like include/config/foo.h.
  11. *
  12. * 1 August 1999, Michael Elizabeth Chastain, <mec@shout.net>
  13. * - Keith Owens reported a bug in smart config processing. There used
  14. * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO",
  15. * so that the file would not depend on CONFIG_FOO because the file defines
  16. * this symbol itself. But this optimization is bogus! Consider this code:
  17. * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here
  18. * the definition is inactivated, but I still used it. It turns out this
  19. * actually happens a few times in the kernel source. The simple way to
  20. * fix this problem is to remove this particular optimization.
  21. *
  22. * 2.3.99-pre1, Andrew Morton <andrewm@uow.edu.au>
  23. * - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that
  24. * missing source files are noticed, rather than silently ignored.
  25. *
  26. * 2.4.2-pre3, Keith Owens <kaos@ocs.com.au>
  27. * - Accept cflags followed by '--' followed by filenames. mkdep extracts -I
  28. * options from cflags and looks in the specified directories as well as the
  29. * defaults. Only -I is supported, no attempt is made to handle -idirafter,
  30. * -isystem, -I- etc.
  31. */
  32. #include <ctype.h>
  33. #include <fcntl.h>
  34. #include <limits.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <unistd.h>
  39. #include <sys/fcntl.h>
  40. #include <sys/mman.h>
  41. #include <sys/stat.h>
  42. #include <sys/types.h>
  43. char depname[512];
  44. int hasdep;
  45. struct path_struct {
  46. int len;
  47. char *buffer;
  48. };
  49. struct path_struct *path_array;
  50. int paths;
  51. /* Current input file */
  52. static const char *g_filename;
  53. /*
  54. * This records all the configuration options seen.
  55. * In perl this would be a hash, but here it's a long string
  56. * of values separated by newlines. This is simple and
  57. * extremely fast.
  58. */
  59. char * str_config = NULL;
  60. int size_config = 0;
  61. int len_config = 0;
  62. static void
  63. do_depname(void)
  64. {
  65. if (!hasdep) {
  66. hasdep = 1;
  67. if (g_filename) {
  68. /* Source file (*.[cS]) */
  69. printf("%s:", depname);
  70. printf(" %s", g_filename);
  71. } else {
  72. /* header file (*.h) */
  73. printf("dep_%s +=", depname);
  74. }
  75. }
  76. }
  77. /*
  78. * Grow the configuration string to a desired length.
  79. * Usually the first growth is plenty.
  80. */
  81. void grow_config(int len)
  82. {
  83. while (len_config + len > size_config) {
  84. if (size_config == 0)
  85. size_config = 2048;
  86. str_config = realloc(str_config, size_config *= 2);
  87. if (str_config == NULL)
  88. { perror("malloc config"); exit(1); }
  89. }
  90. }
  91. /*
  92. * Lookup a value in the configuration string.
  93. */
  94. int is_defined_config(const char * name, int len)
  95. {
  96. const char * pconfig;
  97. const char * plast = str_config + len_config - len;
  98. for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
  99. if (pconfig[ -1] == '\n'
  100. && pconfig[len] == '\n'
  101. && !memcmp(pconfig, name, len))
  102. return 1;
  103. }
  104. return 0;
  105. }
  106. /*
  107. * Add a new value to the configuration string.
  108. */
  109. void define_config(const char * name, int len)
  110. {
  111. grow_config(len + 1);
  112. memcpy(str_config+len_config, name, len);
  113. len_config += len;
  114. str_config[len_config++] = '\n';
  115. }
  116. /*
  117. * Clear the set of configuration strings.
  118. */
  119. void clear_config(void)
  120. {
  121. len_config = 0;
  122. define_config("", 0);
  123. }
  124. /*
  125. * This records all the precious .h filenames. No need for a hash,
  126. * it's a long string of values enclosed in tab and newline.
  127. */
  128. char * str_precious = NULL;
  129. int size_precious = 0;
  130. int len_precious = 0;
  131. /*
  132. * Grow the precious string to a desired length.
  133. * Usually the first growth is plenty.
  134. */
  135. void grow_precious(int len)
  136. {
  137. while (len_precious + len > size_precious) {
  138. if (size_precious == 0)
  139. size_precious = 2048;
  140. str_precious = realloc(str_precious, size_precious *= 2);
  141. if (str_precious == NULL)
  142. { perror("malloc"); exit(1); }
  143. }
  144. }
  145. /*
  146. * Add a new value to the precious string.
  147. */
  148. void define_precious(const char * filename)
  149. {
  150. int len = strlen(filename);
  151. grow_precious(len + 4);
  152. *(str_precious+len_precious++) = '\t';
  153. memcpy(str_precious+len_precious, filename, len);
  154. len_precious += len;
  155. memcpy(str_precious+len_precious, " \\\n", 3);
  156. len_precious += 3;
  157. }
  158. /*
  159. * Handle an #include line.
  160. */
  161. void handle_include(int start, const char * name, int len)
  162. {
  163. struct path_struct *path;
  164. int i;
  165. if (len == 14 && !memcmp(name, "include/config.h", len))
  166. return;
  167. if (len >= 7 && !memcmp(name, "config/", 7))
  168. define_config(name+7, len-7-2);
  169. for (i = start, path = path_array+start; i < paths; ++i, ++path) {
  170. memcpy(path->buffer+path->len, name, len);
  171. path->buffer[path->len+len] = '\0';
  172. if (access(path->buffer, F_OK) == 0) {
  173. do_depname();
  174. printf(" \\\n %s $(dep_%s)", path->buffer, path->buffer);
  175. return;
  176. }
  177. }
  178. }
  179. /*
  180. * Add a path to the list of include paths.
  181. */
  182. void add_path(const char * name)
  183. {
  184. struct path_struct *path;
  185. char resolved_path[PATH_MAX+1];
  186. const char *name2;
  187. if (strcmp(name, ".")) {
  188. name2 = realpath(name, resolved_path);
  189. if (!name2) {
  190. fprintf(stderr, "realpath(%s) failed, %m\n", name);
  191. exit(1);
  192. }
  193. }
  194. else {
  195. name2 = "";
  196. }
  197. path_array = realloc(path_array, (++paths)*sizeof(*path_array));
  198. if (!path_array) {
  199. fprintf(stderr, "cannot expand path_arry\n");
  200. exit(1);
  201. }
  202. path = path_array+paths-1;
  203. path->len = strlen(name2);
  204. path->buffer = malloc(path->len+1+256+1);
  205. if (!path->buffer) {
  206. fprintf(stderr, "cannot allocate path buffer\n");
  207. exit(1);
  208. }
  209. strcpy(path->buffer, name2);
  210. if (path->len && *(path->buffer+path->len-1) != '/') {
  211. *(path->buffer+path->len) = '/';
  212. *(path->buffer+(++(path->len))) = '\0';
  213. }
  214. }
  215. /*
  216. * Record the use of a CONFIG_* word.
  217. */
  218. void use_config(const char * name, int len)
  219. {
  220. char *pc;
  221. int i;
  222. pc = path_array[paths-1].buffer + path_array[paths-1].len;
  223. memcpy(pc, "config/", 7);
  224. pc += 7;
  225. for (i = 0; i < len; i++) {
  226. char c = name[i];
  227. if (isupper((int)c)) c = tolower((int)c);
  228. if (c == '_') c = '/';
  229. pc[i] = c;
  230. }
  231. pc[len] = '\0';
  232. if (is_defined_config(pc, len))
  233. return;
  234. define_config(pc, len);
  235. do_depname();
  236. printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer);
  237. }
  238. /*
  239. * Macros for stunningly fast map-based character access.
  240. * __buf is a register which holds the current word of the input.
  241. * Thus, there is one memory access per sizeof(unsigned long) characters.
  242. */
  243. #if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \
  244. || defined(__arm__)
  245. #define LE_MACHINE
  246. #endif
  247. #ifdef LE_MACHINE
  248. #define next_byte(x) (x >>= 8)
  249. #define current ((unsigned char) __buf)
  250. #else
  251. #define next_byte(x) (x <<= 8)
  252. #define current (__buf >> 8*(sizeof(unsigned long)-1))
  253. #endif
  254. #define GETNEXT { \
  255. next_byte(__buf); \
  256. if ((unsigned long) next % sizeof(unsigned long) == 0) { \
  257. if (next >= end) \
  258. break; \
  259. __buf = * (unsigned long *) next; \
  260. } \
  261. next++; \
  262. }
  263. /*
  264. * State machine macros.
  265. */
  266. #define CASE(c,label) if (current == c) goto label
  267. #define NOTCASE(c,label) if (current != c) goto label
  268. /*
  269. * Yet another state machine speedup.
  270. */
  271. #define MAX2(a,b) ((a)>(b)?(a):(b))
  272. #define MIN2(a,b) ((a)<(b)?(a):(b))
  273. #define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
  274. #define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
  275. /*
  276. * The state machine looks for (approximately) these Perl regular expressions:
  277. *
  278. * m|\/\*.*?\*\/|
  279. * m|\/\/.*|
  280. * m|'.*?'|
  281. * m|".*?"|
  282. * m|#\s*include\s*"(.*?)"|
  283. * m|#\s*include\s*<(.*?>"|
  284. * m|#\s*(?define|undef)\s*CONFIG_(\w*)|
  285. * m|(?!\w)CONFIG_|
  286. *
  287. * About 98% of the CPU time is spent here, and most of that is in
  288. * the 'start' paragraph. Because the current characters are
  289. * in a register, the start loop usually eats 4 or 8 characters
  290. * per memory read. The MAX5 and MIN5 tests dispose of most
  291. * input characters with 1 or 2 comparisons.
  292. */
  293. void state_machine(const char * map, const char * end)
  294. {
  295. const char * next = map;
  296. const char * map_dot;
  297. unsigned long __buf = 0;
  298. for (;;) {
  299. start:
  300. GETNEXT
  301. __start:
  302. if (current > MAX5('/','\'','"','#','C')) goto start;
  303. if (current < MIN5('/','\'','"','#','C')) goto start;
  304. CASE('/', slash);
  305. CASE('\'', squote);
  306. CASE('"', dquote);
  307. CASE('#', pound);
  308. CASE('C', cee);
  309. goto start;
  310. /* // */
  311. slash_slash:
  312. GETNEXT
  313. CASE('\n', start);
  314. NOTCASE('\\', slash_slash);
  315. GETNEXT
  316. goto slash_slash;
  317. /* / */
  318. slash:
  319. GETNEXT
  320. CASE('/', slash_slash);
  321. NOTCASE('*', __start);
  322. slash_star_dot_star:
  323. GETNEXT
  324. __slash_star_dot_star:
  325. NOTCASE('*', slash_star_dot_star);
  326. GETNEXT
  327. NOTCASE('/', __slash_star_dot_star);
  328. goto start;
  329. /* '.*?' */
  330. squote:
  331. GETNEXT
  332. CASE('\'', start);
  333. NOTCASE('\\', squote);
  334. GETNEXT
  335. goto squote;
  336. /* ".*?" */
  337. dquote:
  338. GETNEXT
  339. CASE('"', start);
  340. NOTCASE('\\', dquote);
  341. GETNEXT
  342. goto dquote;
  343. /* #\s* */
  344. pound:
  345. GETNEXT
  346. CASE(' ', pound);
  347. CASE('\t', pound);
  348. CASE('i', pound_i);
  349. CASE('d', pound_d);
  350. CASE('u', pound_u);
  351. goto __start;
  352. /* #\s*i */
  353. pound_i:
  354. GETNEXT NOTCASE('n', __start);
  355. GETNEXT NOTCASE('c', __start);
  356. GETNEXT NOTCASE('l', __start);
  357. GETNEXT NOTCASE('u', __start);
  358. GETNEXT NOTCASE('d', __start);
  359. GETNEXT NOTCASE('e', __start);
  360. goto pound_include;
  361. /* #\s*include\s* */
  362. pound_include:
  363. GETNEXT
  364. CASE(' ', pound_include);
  365. CASE('\t', pound_include);
  366. map_dot = next;
  367. CASE('"', pound_include_dquote);
  368. CASE('<', pound_include_langle);
  369. goto __start;
  370. /* #\s*include\s*"(.*)" */
  371. pound_include_dquote:
  372. GETNEXT
  373. CASE('\n', start);
  374. NOTCASE('"', pound_include_dquote);
  375. handle_include(0, map_dot, next - map_dot - 1);
  376. goto start;
  377. /* #\s*include\s*<(.*)> */
  378. pound_include_langle:
  379. GETNEXT
  380. CASE('\n', start);
  381. NOTCASE('>', pound_include_langle);
  382. handle_include(1, map_dot, next - map_dot - 1);
  383. goto start;
  384. /* #\s*d */
  385. pound_d:
  386. GETNEXT NOTCASE('e', __start);
  387. GETNEXT NOTCASE('f', __start);
  388. GETNEXT NOTCASE('i', __start);
  389. GETNEXT NOTCASE('n', __start);
  390. GETNEXT NOTCASE('e', __start);
  391. goto pound_define_undef;
  392. /* #\s*u */
  393. pound_u:
  394. GETNEXT NOTCASE('n', __start);
  395. GETNEXT NOTCASE('d', __start);
  396. GETNEXT NOTCASE('e', __start);
  397. GETNEXT NOTCASE('f', __start);
  398. goto pound_define_undef;
  399. /*
  400. * #\s*(define|undef)\s*CONFIG_(\w*)
  401. *
  402. * this does not define the word, because it could be inside another
  403. * conditional (#if 0). But I do parse the word so that this instance
  404. * does not count as a use. -- mec
  405. */
  406. pound_define_undef:
  407. GETNEXT
  408. CASE(' ', pound_define_undef);
  409. CASE('\t', pound_define_undef);
  410. NOTCASE('C', __start);
  411. GETNEXT NOTCASE('O', __start);
  412. GETNEXT NOTCASE('N', __start);
  413. GETNEXT NOTCASE('F', __start);
  414. GETNEXT NOTCASE('I', __start);
  415. GETNEXT NOTCASE('G', __start);
  416. GETNEXT NOTCASE('_', __start);
  417. map_dot = next;
  418. pound_define_undef_CONFIG_word:
  419. GETNEXT
  420. if (isalnum(current) || current == '_')
  421. goto pound_define_undef_CONFIG_word;
  422. goto __start;
  423. /* \<CONFIG_(\w*) */
  424. cee:
  425. if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_'))
  426. goto start;
  427. GETNEXT NOTCASE('O', __start);
  428. GETNEXT NOTCASE('N', __start);
  429. GETNEXT NOTCASE('F', __start);
  430. GETNEXT NOTCASE('I', __start);
  431. GETNEXT NOTCASE('G', __start);
  432. GETNEXT NOTCASE('_', __start);
  433. map_dot = next;
  434. cee_CONFIG_word:
  435. GETNEXT
  436. if (isalnum(current) || current == '_')
  437. goto cee_CONFIG_word;
  438. use_config(map_dot, next - map_dot - 1);
  439. goto __start;
  440. }
  441. }
  442. /*
  443. * Generate dependencies for one file.
  444. */
  445. void do_depend(const char * filename)
  446. {
  447. int mapsize;
  448. int pagesizem1 = getpagesize()-1;
  449. int fd;
  450. struct stat st;
  451. char * map;
  452. fd = open(filename, O_RDONLY);
  453. if (fd < 0) {
  454. perror(filename);
  455. return;
  456. }
  457. fstat(fd, &st);
  458. if (st.st_size == 0) {
  459. fprintf(stderr,"%s is empty\n",filename);
  460. close(fd);
  461. return;
  462. }
  463. mapsize = st.st_size;
  464. mapsize = (mapsize+pagesizem1) & ~pagesizem1;
  465. map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
  466. if ((long) map == -1) {
  467. perror("mkdep: mmap");
  468. close(fd);
  469. return;
  470. }
  471. if ((unsigned long) map % sizeof(unsigned long) != 0)
  472. {
  473. fprintf(stderr, "do_depend: map not aligned\n");
  474. exit(1);
  475. }
  476. hasdep = 0;
  477. clear_config();
  478. state_machine(map, map+st.st_size);
  479. if (hasdep) {
  480. puts("");
  481. }
  482. munmap(map, mapsize);
  483. close(fd);
  484. }
  485. /*
  486. * Generate dependencies for all files.
  487. */
  488. int main(int argc, char **argv)
  489. {
  490. int len;
  491. const char *hpath;
  492. hpath = getenv("TOPDIR");
  493. if (!hpath) {
  494. fputs("mkdep: TOPDIR not set in environment. "
  495. "Don't bypass the top level Makefile.\n", stderr);
  496. return 1;
  497. }
  498. add_path("."); /* for #include "..." */
  499. while (++argv, --argc > 0) {
  500. if (strncmp(*argv, "-I", 2) == 0) {
  501. if (*((*argv)+2)) {
  502. add_path((*argv)+2);
  503. }
  504. else {
  505. ++argv;
  506. --argc;
  507. add_path(*argv);
  508. }
  509. }
  510. else if (strcmp(*argv, "--") == 0) {
  511. break;
  512. }
  513. }
  514. add_path(hpath); /* must be last entry, for config files */
  515. while (--argc > 0) {
  516. const char * filename = *++argv;
  517. g_filename = 0;
  518. len = strlen(filename);
  519. memcpy(depname, filename, len+1);
  520. if (len > 2 && filename[len-2] == '.') {
  521. if (filename[len-1] == 'c' || filename[len-1] == 'S') {
  522. depname[len-1] = 'o';
  523. g_filename = filename;
  524. }
  525. }
  526. do_depend(filename);
  527. }
  528. if (len_precious) {
  529. *(str_precious+len_precious) = '\0';
  530. printf(".PRECIOUS:%s\n", str_precious);
  531. }
  532. return 0;
  533. }