summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
author"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-09-12 12:33:27 +0000
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-09-12 12:33:27 +0000
commit5e60dc4a209b053e8fe5170bd143173941c4634c (patch)
tree43f8c3bf33914c701b2224b218d2ed21078ef2ea /scripts
parentba50217281e9265aa5935d184f698204143e765f (diff)
downloadbusybox-w32-5e60dc4a209b053e8fe5170bd143173941c4634c.tar.gz
busybox-w32-5e60dc4a209b053e8fe5170bd143173941c4634c.tar.bz2
busybox-w32-5e60dc4a209b053e8fe5170bd143173941c4634c.zip
new my scripts/mm_mkdep, dependences work now
Diffstat (limited to 'scripts')
-rw-r--r--scripts/bb_mkdep.c855
-rw-r--r--scripts/mkdep.c628
-rw-r--r--scripts/split-include.c226
3 files changed, 855 insertions, 854 deletions
diff --git a/scripts/bb_mkdep.c b/scripts/bb_mkdep.c
new file mode 100644
index 000000000..408397332
--- /dev/null
+++ b/scripts/bb_mkdep.c
@@ -0,0 +1,855 @@
1/*
2 * Another dependences for Makefile mashine generator
3 *
4 * Copyright (C) 2005 by Vladimir Oleynik <dzo@simtreas.ru>
5 *
6 * This programm do
7 * 1) find #define KEY VALUE or #undef KEY from include/config.h
8 * 2) save include/config/key*.h if changed after previous usage
9 * 3) recursive scan from "./" *.[ch] files, but skip scan include/config/...
10 * 4) find #include "*.h" and KEYs using, if not as #define and #undef
11 * 5) generate depend to stdout
12 * path/file.o: include/config/key*.h found_include_*.h
13 * path/inc.h: include/config/key*.h found_included_include_*.h
14 * This programm do not generate dependences for #include <...>
15 *
16 * Options:
17 * -I local_include_path (include`s paths, default: LOCAL_INCLUDE_PATH)
18 * -d (don`t generate depend)
19 * -w (show warning if include files not found)
20 * -k include/config (default: INCLUDE_CONFIG_PATH)
21 * -c include/config.h (configs, default: INCLUDE_CONFIG_KEYS_PATH)
22*/
23
24#define LOCAL_INCLUDE_PATH "include"
25#define INCLUDE_CONFIG_PATH LOCAL_INCLUDE_PATH"/config"
26#define INCLUDE_CONFIG_KEYS_PATH LOCAL_INCLUDE_PATH"/config.h"
27
28#define _GNU_SOURCE
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/mman.h>
32#include <getopt.h>
33#include <dirent.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <stdarg.h>
38#include <unistd.h>
39#include <errno.h>
40#include <fcntl.h>
41
42typedef struct BB_KEYS {
43 char *keyname;
44 const char *value;
45 char *stored_path;
46 int checked;
47 struct BB_KEYS *next;
48} bb_key_t;
49
50
51/* partial and simplify libbb routine */
52
53void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
54char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
55
56/* stolen from libbb as is */
57typedef struct llist_s {
58 char *data;
59 struct llist_s *link;
60} llist_t;
61llist_t *llist_add_to(llist_t *old_head, char *new_item);
62void *xrealloc(void *p, size_t size);
63void *xmalloc(size_t size);
64char *bb_xstrdup(const char *s);
65char *bb_simplify_path(const char *path);
66
67/* for lexical analyzier */
68static bb_key_t *key_top;
69
70static void parse_inc(const char *include, const char *fname);
71static void parse_conf_opt(char *opt, const char *val, size_t rsz);
72
73#define CHECK_ONLY 0
74#define MAKE_NEW 1
75static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new);
76
77#define yy_error_d(s) bb_error_d("%s:%d hmm, %s", fname, line, s)
78
79/* state */
80#define S 0 /* start state */
81#define STR '"' /* string */
82#define CHR '\'' /* char */
83#define REM '*' /* block comment */
84#define POUND '#' /* # */
85#define I 'i' /* #include preprocessor`s directive */
86#define D 'd' /* #define preprocessor`s directive */
87#define U 'u' /* #undef preprocessor`s directive */
88#define LI 'I' /* #include "... */
89#define DK 'K' /* #define KEY... (config mode) */
90#define DV 'V' /* #define KEY "... or #define KEY '... */
91#define NLC 'n' /* \+\n */
92#define ANY '?' /* skip unparsed . */
93
94/* [A-Z_a-z] */
95#define ID(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_')
96/* [A-Z_a-z0-9] */
97#define ISALNUM(c) (ID(c) || (c >= '0' && c <= '9'))
98
99#define getc1() do { c = (optr >= oend) ? EOF : *optr++; } while(0)
100#define ungetc1() optr--
101
102#define put_id(c) do { if(id_len == mema_id) \
103 id = xrealloc(id, mema_id += 16); \
104 id[id_len++] = c; } while(0)
105
106/* stupid C lexical analizator */
107static void c_lex(const char *fname, int flg_config_include)
108{
109 int c = EOF; /* stupid initialize */
110 int prev_state = EOF;
111 int called;
112 int state;
113 int line;
114 static size_t mema_id;
115 char *id = xmalloc(mema_id=128); /* fist allocate */
116 size_t id_len = 0; /* stupid initialize */
117 char *val = NULL;
118 unsigned char *optr, *oend;
119 unsigned char *start = NULL; /* stupid initialize */
120
121 int fd;
122 char *map;
123 int mapsize;
124 {
125 /* stolen from mkdep by Linus Torvalds */
126 int pagesizem1 = getpagesize() - 1;
127 struct stat st;
128
129 fd = open(fname, O_RDONLY);
130 if(fd < 0) {
131 perror(fname);
132 return;
133 }
134 fstat(fd, &st);
135 if (st.st_size == 0)
136 bb_error_d("%s is empty", fname);
137 mapsize = st.st_size;
138 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
139 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
140 if ((long) map == -1)
141 bb_error_d("%s: mmap: %m", fname);
142
143 /* hereinafter is my */
144 optr = (unsigned char *)map;
145 oend = optr + st.st_size;
146 }
147
148 line = 1;
149 called = state = S;
150
151 for(;;) {
152 if(state == LI || state == DV) {
153 /* store "include.h" or config mode #define KEY "|'..."|' */
154 put_id(0);
155 if(state == LI) {
156 parse_inc(id, fname);
157 } else {
158 /*
159 if(val[0] == '\0')
160 yy_error_d("expected value");
161 */
162 parse_conf_opt(id, val, (optr - start));
163 }
164 state = S;
165 }
166 if(prev_state != state) {
167 prev_state = state;
168 getc1();
169 }
170
171 /* [ \t]+ eat first space */
172 while(c == ' ' || c == '\t')
173 getc1();
174
175 if(c == '\\') {
176 getc1();
177 if(c == '\n') {
178 /* \\\n eat continued */
179 line++;
180 prev_state = NLC;
181 continue;
182 }
183 ungetc1();
184 c = '\\';
185 }
186
187 if(state == S) {
188 while(c <= ' ' && c != EOF) {
189 /* <S>[\000- ]+ */
190 if(c == '\n')
191 line++;
192 getc1();
193 }
194 if(c == EOF) {
195 /* <S><<EOF>> */
196 munmap(map, mapsize);
197 close(fd);
198 return;
199 }
200 if(c == '/') {
201 /* <S>/ */
202 getc1();
203 if(c == '/') {
204 /* <S>"//"[^\n]* */
205 do getc1(); while(c != '\n' && c != EOF);
206 } else if(c == '*') {
207 /* <S>[/][*] */
208 called = S;
209 state = REM;
210 }
211 /* eat <S>/ */
212 } else if(c == '#') {
213 /* <S>\"|\'|# */
214 start = optr - 1;
215 state = c;
216 } else if(c == STR || c == CHR) {
217 /* <S>\"|\'|# */
218 val = NULL;
219 called = S;
220 state = c;
221 } else if(ISALNUM(c)) {
222 /* <S>[A-Z_a-z0-9] */
223 id_len = 0;
224 do {
225 /* <S>[A-Z_a-z0-9]+ */
226 put_id(c);
227 getc1();
228 } while(ISALNUM(c));
229 put_id(0);
230 find_already(key_top, id, CHECK_ONLY);
231 } else {
232 /* <S>. */
233 prev_state = ANY;
234 }
235 continue;
236 }
237 if(state == REM) {
238 for(;;) {
239 /* <REM>[^*]+ */
240 while(c != '*') {
241 if(c == '\n') {
242 /* <REM>\n */
243 if(called != S)
244 yy_error_d("unexpected newline");
245 line++;
246 } else if(c == EOF)
247 yy_error_d("unexpected EOF");
248 getc1();
249 }
250 /* <REM>[*] */
251 getc1();
252 if(c == '/') {
253 /* <REM>[*][/] */
254 state = called;
255 break;
256 }
257 }
258 continue;
259 }
260 if(state == STR || state == CHR) {
261 for(;;) {
262 /* <STR,CHR>\n|<<EOF>> */
263 if(c == '\n' || c == EOF)
264 yy_error_d("unterminating");
265 if(c == '\\') {
266 /* <STR,CHR>\\ */
267 getc1();
268 if(c != '\\' && c != '\n' && c != state) {
269 /* another usage \ in str or char */
270 if(c == EOF)
271 yy_error_d("unexpected EOF");
272 if(val)
273 put_id(c);
274 continue;
275 }
276 /* <STR,CHR>\\[\\\n] or <STR>\\\" or <CHR>\\\' */
277 /* eat 2 char */
278 if(c == '\n')
279 line++;
280 else if(val)
281 put_id(c);
282 } else if(c == state) {
283 /* <STR>\" or <CHR>\' */
284 if(called == DV)
285 put_id(c);
286 state = called;
287 break;
288 } else if(val)
289 put_id(c);
290 /* <STR,CHR>. */
291 getc1();
292 }
293 continue;
294 }
295
296 /* begin preprocessor states */
297 if(c == EOF)
298 yy_error_d("unexpected EOF");
299 if(c == '/') {
300 /* <#.*>/ */
301 getc1();
302 if(c == '/')
303 yy_error_d("detect // in preprocessor line");
304 if(c == '*') {
305 /* <#.*>[/][*] */
306 called = state;
307 state = REM;
308 continue;
309 }
310 /* hmm, #.*[/] */
311 yy_error_d("strange preprocessor line");
312 }
313 if(state == '#') {
314 static const char * const preproc[] = {
315 "define", "undef", "include", ""
316 };
317 const char * const *str_type;
318
319 id_len = 0;
320 while(ISALNUM(c)) {
321 put_id(c);
322 getc1();
323 }
324 put_id(0);
325 for(str_type = preproc; (state = **str_type); str_type++) {
326 if(*id == state && strcmp(id, *str_type) == 0)
327 break;
328 }
329 /* to S if another #directive */
330 ungetc1();
331 id_len = 0; /* common for save */
332 continue;
333 }
334 if(state == I) {
335 if(c == STR) {
336 /* <I>\" */
337 val = id;
338 state = STR;
339 called = LI;
340 continue;
341 }
342 /* another (may be wrong) #include ... */
343 ungetc1();
344 state = S;
345 continue;
346 }
347 if(state == D || state == U) {
348 while(ISALNUM(c)) {
349 if(flg_config_include) {
350 /* save KEY from #"define"|"undef" ... */
351 put_id(c);
352 }
353 getc1();
354 }
355 if(!flg_config_include) {
356 state = S;
357 } else {
358 if(!id_len)
359 yy_error_d("expected identificator");
360 put_id(0);
361 if(state == U) {
362 parse_conf_opt(id, NULL, (optr - start));
363 state = S;
364 } else {
365 /* D -> DK */
366 state = DK;
367 }
368 }
369 ungetc1();
370 continue;
371 }
372 if(state == DK) {
373 /* #define (config mode) */
374 val = id + id_len;
375 if(c == STR || c == CHR) {
376 /* define KEY "... or define KEY '... */
377 put_id(c);
378 called = DV;
379 state = c;
380 continue;
381 }
382 while(ISALNUM(c)) {
383 put_id(c);
384 getc1();
385 }
386 ungetc1();
387 state = DV;
388 continue;
389 }
390 }
391}
392
393
394static void show_usage(void) __attribute__ ((noreturn));
395static void show_usage(void)
396{
397 bb_error_d("Usage: [-I local_include_path] [-dw] "
398 "[-k path_for_store_keys] [-s skip_file]");
399}
400
401static const char *kp;
402static llist_t *Iop;
403static bb_key_t *Ifound;
404static int noiwarning;
405static llist_t *configs;
406
407static bb_key_t *find_already(bb_key_t *k, const char *nk, int flg_save_new)
408{
409 bb_key_t *cur;
410
411 for(cur = k; cur; cur = cur->next) {
412 if(strcmp(cur->keyname, nk) == 0) {
413 cur->checked = 1;
414 return NULL;
415 }
416 }
417 if(flg_save_new == CHECK_ONLY)
418 return NULL;
419 cur = xmalloc(sizeof(bb_key_t));
420 cur->keyname = bb_xstrdup(nk);
421 cur->checked = 1;
422 cur->next = k;
423 return cur;
424}
425
426static int store_include_fullpath(char *p_i, bb_key_t *li)
427{
428 struct stat st;
429 int ok = 0;
430
431 if(stat(p_i, &st) == 0) {
432 li->stored_path = bb_simplify_path(p_i);
433 ok = 1;
434 }
435 free(p_i);
436 return ok;
437}
438
439static void parse_inc(const char *include, const char *fname)
440{
441 bb_key_t *li;
442 char *p_i;
443 llist_t *lo;
444
445 if((li = find_already(Ifound, include, MAKE_NEW)) == NULL)
446 return;
447 Ifound = li;
448 if(include[0] != '/') {
449 /* relative */
450 int w;
451 const char *p;
452
453 p_i = strrchr(fname, '/');
454 if(p_i == NULL) {
455 p = ".";
456 w = 1;
457 } else {
458 w = (p_i-fname);
459 p = fname;
460 }
461 p_i = bb_asprint("%.*s/%s", w, p, include);
462 if(store_include_fullpath(p_i, li))
463 return;
464 }
465 for(lo = Iop; lo; lo = lo->link) {
466 p_i = bb_asprint("%s/%s", lo->data, include);
467 if(store_include_fullpath(p_i, li))
468 return;
469 }
470 li->stored_path = NULL;
471 if(noiwarning)
472 fprintf(stderr, "%s: Warning: #include \"%s\" not found in specified paths\n", fname, include);
473}
474
475static void parse_conf_opt(char *opt, const char *val, size_t recordsz)
476{
477 bb_key_t *cur = find_already(key_top, opt, MAKE_NEW);
478
479 if(cur != NULL) {
480 /* new key, check old key if present after previous usage */
481 char *s, *p;
482 struct stat st;
483 int fd;
484 int cmp_ok = 0;
485 static char *record_buf;
486 static char *r_cmp;
487 static size_t r_sz;
488
489 recordsz += 2; /* \n\0 */
490 if(recordsz > r_sz) {
491 record_buf = xrealloc(record_buf, r_sz=recordsz);
492 r_cmp = xrealloc(r_cmp, recordsz);
493 }
494 s = record_buf;
495 if(val)
496 sprintf(s, "#define %s%s%s\n", opt, (*val ? " " : ""), val);
497 else
498 sprintf(s, "#undef %s\n", opt);
499 /* may be short count " " */
500 recordsz = strlen(s);
501 /* key converting [A-Z] -> [a-z] */
502 for(p = opt; *p; p++) {
503 if(*p >= 'A' && *p <= 'Z')
504 *p = *p - 'A' + 'a';
505 if(*p == '_')
506 *p = '/';
507 }
508 p = bb_asprint("%s/%s.h", kp, opt);
509 cur->stored_path = opt = p;
510 while(*++p) {
511 /* Auto-create directories. */
512 if (*p == '/') {
513 *p = '\0';
514 if (stat(opt, &st) != 0 && mkdir(opt, 0755) != 0)
515 bb_error_d("mkdir(%s): %m", opt);
516 *p = '/';
517 }
518 }
519 if(stat(opt, &st) == 0) {
520 /* found */
521 if(st.st_size == recordsz) {
522 fd = open(opt, O_RDONLY);
523 if(fd < 0 || read(fd, r_cmp, recordsz) != recordsz)
524 bb_error_d("%s: %m", opt);
525 close(fd);
526 cmp_ok = memcmp(s, r_cmp, recordsz) == 0;
527 }
528 }
529 if(!cmp_ok) {
530 fd = open(opt, O_WRONLY|O_CREAT|O_TRUNC, 0644);
531 if(fd < 0 || write(fd, s, recordsz) != recordsz)
532 bb_error_d("%s: %m", opt);
533 close(fd);
534 }
535 /* store only */
536 cur->checked = 0;
537 if(val) {
538 if(*val == '\0') {
539 cur->value = "";
540 } else {
541 cur->value = bb_xstrdup(val);
542 }
543 } else {
544 cur->value = NULL;
545 }
546 key_top = cur;
547 } else {
548 /* present already */
549 for(cur = key_top; cur; cur = cur->next) {
550 if(strcmp(cur->keyname, opt) == 0) {
551 cur->checked = 0;
552 if(cur->value == NULL && val == NULL)
553 return;
554 if((cur->value == NULL && val != NULL) ||
555 (cur->value != NULL && val == NULL) ||
556 strcmp(cur->value, val))
557 fprintf(stderr, "Warning: redefined %s\n", opt);
558 return;
559 }
560 }
561 }
562}
563
564static int show_dep(int first, bb_key_t *k, const char *a)
565{
566 bb_key_t *cur;
567
568 for(cur = k; cur; cur = cur->next) {
569 if(cur->checked && cur->stored_path) {
570 if(first) {
571 const char *ext;
572
573 if(*a == '.' && a[1] == '/')
574 a += 2;
575 ext = strrchr(a, '.');
576 if(ext && ext[1] == 'c' && ext[2] == '\0') {
577 /* *.c -> *.o */
578 printf("\n%.*s.o:", (ext - a), a);
579 } else {
580 printf("\n%s:", a);
581 }
582 first = 0;
583 } else {
584 printf(" \\\n ");
585 }
586 printf(" %s", cur->stored_path);
587 }
588 cur->checked = 0;
589 }
590 return first;
591}
592
593static llist_t *files;
594
595static llist_t *filter_chd(const char *fe, const char *p, llist_t *pdirs)
596{
597 const char *e;
598 struct stat st;
599 char *fp;
600 char *afp;
601 llist_t *cfl;
602
603 if (*fe == '.')
604 return NULL;
605 fp = bb_asprint("%s/%s", p, fe);
606 if(stat(fp, &st)) {
607 fprintf(stderr, "Warning: stat(%s): %m", fp);
608 free(fp);
609 return NULL;
610 }
611 afp = bb_simplify_path(fp);
612 if(S_ISDIR(st.st_mode)) {
613 if(strcmp(kp, afp) == 0) {
614 /* is autogenerated to kp/key* by previous usage */
615 free(afp);
616 free(fp);
617 /* drop scan kp/ directory */
618 return NULL;
619 }
620 free(afp);
621 return llist_add_to(pdirs, fp);
622 }
623 if(!S_ISREG(st.st_mode)) {
624 /* hmm, is device! */
625 free(afp);
626 free(fp);
627 return NULL;
628 }
629 e = strrchr(fe, '.');
630 if(e == NULL || !((e[1]=='c' || e[1]=='h') && e[2]=='\0')) {
631 /* direntry is not directory or *.[ch] */
632 free(afp);
633 free(fp);
634 return NULL;
635 }
636 for(cfl = configs; cfl; cfl = cfl->link) {
637 if(cfl->data && strcmp(cfl->data, afp) == 0) {
638 /* parse configs.h */
639 free(afp);
640 c_lex(fp, 1);
641 free(fp);
642 free(cfl->data);
643 cfl->data = NULL;
644 return NULL;
645 }
646 }
647 free(fp);
648 /* direntry is *.[ch] regular file */
649 files = llist_add_to(files, afp);
650 return NULL;
651}
652
653static void scan_dir_find_ch_files(char *p)
654{
655 llist_t *dirs;
656 llist_t *d_add;
657 llist_t *d;
658 struct dirent *de;
659 DIR *dir;
660
661 dirs = llist_add_to(NULL, p);
662 /* emulate recursive */
663 while(dirs) {
664 d_add = NULL;
665 while(dirs) {
666 dir = opendir(dirs->data);
667 if (dir == NULL)
668 fprintf(stderr, "Warning: opendir(%s): %m", dirs->data);
669 while ((de = readdir(dir)) != NULL) {
670 d = filter_chd(de->d_name, dirs->data, d_add);
671 if(d)
672 d_add = d;
673 }
674 closedir(dir);
675 if(dirs->data != p)
676 free(dirs->data);
677 d = dirs;
678 dirs = dirs->link;
679 free(d);
680 }
681 dirs = d_add;
682 }
683}
684
685int main(int argc, char **argv)
686{
687 int generate_dep = 1;
688 char *s;
689 int i;
690 llist_t *fl;
691
692 while ((i = getopt(argc, argv, "I:c:dk:w")) > 0) {
693 switch(i) {
694 case 'I':
695 Iop = llist_add_to(Iop, optarg);
696 break;
697 case 'c':
698 s = bb_simplify_path(optarg);
699 configs = llist_add_to(configs, s);
700 break;
701 case 'd':
702 generate_dep = 0;
703 break;
704 case 'k':
705 if(kp)
706 bb_error_d("Hmm, why multiple -k?");
707 kp = bb_simplify_path(optarg);
708 break;
709 case 'w':
710 noiwarning = 1;
711 break;
712 default:
713 show_usage();
714 }
715 }
716 if(argc > optind)
717 show_usage();
718
719 /* defaults */
720 if(kp == NULL)
721 kp = bb_simplify_path(INCLUDE_CONFIG_PATH);
722 if(Iop == NULL)
723 Iop = llist_add_to(Iop, LOCAL_INCLUDE_PATH);
724 if(configs == NULL) {
725 s = bb_simplify_path(INCLUDE_CONFIG_KEYS_PATH);
726 configs = llist_add_to(configs, s);
727 }
728 scan_dir_find_ch_files(".");
729
730 for(fl = files; fl; fl = fl->link) {
731 c_lex(fl->data, 0);
732 if(generate_dep) {
733 i = show_dep(1, Ifound, fl->data);
734 i = show_dep(i, key_top, fl->data);
735 if(i == 0)
736 putchar('\n');
737 }
738 }
739 return 0;
740}
741
742void bb_error_d(const char *s, ...)
743{
744 va_list p;
745
746 va_start(p, s);
747 vfprintf(stderr, s, p);
748 va_end(p);
749 putc('\n', stderr);
750 exit(1);
751}
752
753
754void *xmalloc(size_t size)
755{
756 void *p = malloc(size);
757
758 if(p == NULL)
759 bb_error_d("memory exhausted");
760 return p;
761}
762
763void *xrealloc(void *p, size_t size) {
764 p = realloc(p, size);
765 if(p == NULL)
766 bb_error_d("memory exhausted");
767 return p;
768}
769
770char *bb_asprint(const char *format, ...)
771{
772 va_list p;
773 int r;
774 char *out;
775
776 va_start(p, format);
777 r = vasprintf(&out, format, p);
778 va_end(p);
779
780 if (r < 0)
781 bb_error_d("bb_asprint: %m");
782 return out;
783}
784
785llist_t *llist_add_to(llist_t *old_head, char *new_item)
786{
787 llist_t *new_head;
788
789 new_head = xmalloc(sizeof(llist_t));
790 new_head->data = new_item;
791 new_head->link = old_head;
792
793 return(new_head);
794}
795
796char *bb_xstrdup(const char *s)
797{
798 char *r = strdup(s);
799 if(r == NULL)
800 bb_error_d("memory exhausted");
801 return r;
802}
803
804char *bb_simplify_path(const char *path)
805{
806 char *s, *start, *p;
807
808 if (path[0] == '/')
809 start = bb_xstrdup(path);
810 else {
811 static char *pwd;
812
813 if(pwd == NULL) {
814 /* is not libbb, but this program have not chdir() */
815 unsigned path_max = 512;
816 char *cwd = xmalloc (path_max);
817#define PATH_INCR 32
818 while (getcwd (cwd, path_max) == NULL) {
819 if(errno != ERANGE)
820 bb_error_d("getcwd: %m");
821 path_max += PATH_INCR;
822 cwd = xrealloc (cwd, path_max);
823 }
824 pwd = cwd;
825 }
826 start = bb_asprint("%s/%s", pwd, path);
827 }
828 p = s = start;
829
830 do {
831 if (*p == '/') {
832 if (*s == '/') { /* skip duplicate (or initial) slash */
833 continue;
834 } else if (*s == '.') {
835 if (s[1] == '/' || s[1] == 0) { /* remove extra '.' */
836 continue;
837 } else if ((s[1] == '.') && (s[2] == '/' || s[2] == 0)) {
838 ++s;
839 if (p > start) {
840 while (*--p != '/'); /* omit previous dir */
841 }
842 continue;
843 }
844 }
845 }
846 *++p = *s;
847 } while (*++s);
848
849 if ((p == start) || (*p != '/')) { /* not a trailing slash */
850 ++p; /* so keep last character */
851 }
852 *p = 0;
853
854 return start;
855}
diff --git a/scripts/mkdep.c b/scripts/mkdep.c
deleted file mode 100644
index ae3cc74e0..000000000
--- a/scripts/mkdep.c
+++ /dev/null
@@ -1,628 +0,0 @@
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
33#include <ctype.h>
34#include <fcntl.h>
35#include <limits.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40
41#include <sys/fcntl.h>
42#include <sys/mman.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45
46
47
48char depname[512];
49int hasdep;
50
51struct path_struct {
52 int len;
53 char *buffer;
54};
55struct path_struct *path_array;
56int paths;
57
58
59/* Current input file */
60static const char *g_filename;
61
62/*
63 * This records all the configuration options seen.
64 * In perl this would be a hash, but here it's a long string
65 * of values separated by newlines. This is simple and
66 * extremely fast.
67 */
68char * str_config = NULL;
69int size_config = 0;
70int len_config = 0;
71
72static void
73do_depname(void)
74{
75 if (!hasdep) {
76 hasdep = 1;
77 if (g_filename) {
78 /* Source file (*.[cS]) */
79 printf("%s:", depname);
80 printf(" %s", g_filename);
81 } else {
82 /* header file (*.h) */
83 printf("dep_%s +=", depname);
84 }
85 }
86}
87
88/*
89 * Grow the configuration string to a desired length.
90 * Usually the first growth is plenty.
91 */
92void grow_config(int len)
93{
94 while (len_config + len > size_config) {
95 if (size_config == 0)
96 size_config = 2048;
97 str_config = realloc(str_config, size_config *= 2);
98 if (str_config == NULL)
99 { perror("malloc config"); exit(1); }
100 }
101}
102
103
104
105/*
106 * Lookup a value in the configuration string.
107 */
108int is_defined_config(const char * name, int len)
109{
110 const char * pconfig;
111 const char * plast = str_config + len_config - len;
112 for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
113 if (pconfig[ -1] == '\n'
114 && pconfig[len] == '\n'
115 && !memcmp(pconfig, name, len))
116 return 1;
117 }
118 return 0;
119}
120
121
122
123/*
124 * Add a new value to the configuration string.
125 */
126void define_config(const char * name, int len)
127{
128 grow_config(len + 1);
129
130 memcpy(str_config+len_config, name, len);
131 len_config += len;
132 str_config[len_config++] = '\n';
133}
134
135
136
137/*
138 * Clear the set of configuration strings.
139 */
140void clear_config(void)
141{
142 len_config = 0;
143 define_config("", 0);
144}
145
146
147
148/*
149 * This records all the precious .h filenames. No need for a hash,
150 * it's a long string of values enclosed in tab and newline.
151 */
152char * str_precious = NULL;
153int size_precious = 0;
154int len_precious = 0;
155
156
157
158/*
159 * Grow the precious string to a desired length.
160 * Usually the first growth is plenty.
161 */
162void grow_precious(int len)
163{
164 while (len_precious + len > size_precious) {
165 if (size_precious == 0)
166 size_precious = 2048;
167 str_precious = realloc(str_precious, size_precious *= 2);
168 if (str_precious == NULL)
169 { perror("malloc"); exit(1); }
170 }
171}
172
173
174
175/*
176 * Add a new value to the precious string.
177 */
178void define_precious(const char * filename)
179{
180 int len = strlen(filename);
181 grow_precious(len + 4);
182 *(str_precious+len_precious++) = '\t';
183 memcpy(str_precious+len_precious, filename, len);
184 len_precious += len;
185 memcpy(str_precious+len_precious, " \\\n", 3);
186 len_precious += 3;
187}
188
189
190
191/*
192 * Handle an #include line.
193 */
194void handle_include(int start, const char * name, int len)
195{
196 struct path_struct *path;
197 int i;
198
199 if (len == 14 && !memcmp(name, "include/config.h", len))
200 return;
201
202 if (len >= 7 && !memcmp(name, "config/", 7))
203 define_config(name+7, len-7-2);
204
205 for (i = start, path = path_array+start; i < paths; ++i, ++path) {
206 memcpy(path->buffer+path->len, name, len);
207 path->buffer[path->len+len] = '\0';
208 if (access(path->buffer, F_OK) == 0) {
209 do_depname();
210 printf(" \\\n %s $(dep_%s)", path->buffer, path->buffer);
211 return;
212 }
213 }
214
215}
216
217
218
219/*
220 * Add a path to the list of include paths.
221 */
222void add_path(const char * name)
223{
224 struct path_struct *path;
225 char resolved_path[PATH_MAX+1];
226 const char *name2;
227
228 if (strcmp(name, ".")) {
229 name2 = realpath(name, resolved_path);
230 if (!name2) {
231 fprintf(stderr, "realpath(%s) failed, %m\n", name);
232 exit(1);
233 }
234 }
235 else {
236 name2 = "";
237 }
238
239 path_array = realloc(path_array, (++paths)*sizeof(*path_array));
240 if (!path_array) {
241 fprintf(stderr, "cannot expand path_arry\n");
242 exit(1);
243 }
244
245 path = path_array+paths-1;
246 path->len = strlen(name2);
247 path->buffer = malloc(path->len+1+256+1);
248 if (!path->buffer) {
249 fprintf(stderr, "cannot allocate path buffer\n");
250 exit(1);
251 }
252 strcpy(path->buffer, name2);
253 if (path->len && *(path->buffer+path->len-1) != '/') {
254 *(path->buffer+path->len) = '/';
255 *(path->buffer+(++(path->len))) = '\0';
256 }
257}
258
259
260
261/*
262 * Record the use of a CONFIG_* word.
263 */
264void use_config(const char * name, int len)
265{
266 char *pc;
267 int i;
268
269 pc = path_array[paths-1].buffer + path_array[paths-1].len;
270 memcpy(pc, "config/", 7);
271 pc += 7;
272
273 for (i = 0; i < len; i++) {
274 char c = name[i];
275 if (isupper((int)c)) c = tolower((int)c);
276 if (c == '_') c = '/';
277 pc[i] = c;
278 }
279 pc[len] = '\0';
280
281 if (is_defined_config(pc, len))
282 return;
283
284 define_config(pc, len);
285
286 do_depname();
287 printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer);
288}
289
290
291
292/*
293 * Macros for stunningly fast map-based character access.
294 * __buf is a register which holds the current word of the input.
295 * Thus, there is one memory access per sizeof(unsigned long) characters.
296 */
297
298#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \
299 || defined(__arm__)
300#define LE_MACHINE
301#endif
302
303#ifdef LE_MACHINE
304#define next_byte(x) (x >>= 8)
305#define current ((unsigned char) __buf)
306#else
307#define next_byte(x) (x <<= 8)
308#define current (__buf >> 8*(sizeof(unsigned long)-1))
309#endif
310
311#define GETNEXT { \
312 next_byte(__buf); \
313 if ((unsigned long) next % sizeof(unsigned long) == 0) { \
314 if (next >= end) \
315 break; \
316 __buf = * (unsigned long *) next; \
317 } \
318 next++; \
319}
320
321/*
322 * State machine macros.
323 */
324#define CASE(c,label) if (current == c) goto label
325#define NOTCASE(c,label) if (current != c) goto label
326
327/*
328 * Yet another state machine speedup.
329 */
330#define MAX2(a,b) ((a)>(b)?(a):(b))
331#define MIN2(a,b) ((a)<(b)?(a):(b))
332#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
333#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
334
335
336
337/*
338 * The state machine looks for (approximately) these Perl regular expressions:
339 *
340 * m|\/\*.*?\*\/|
341 * m|\/\/.*|
342 * m|'.*?'|
343 * m|".*?"|
344 * m|#\s*include\s*"(.*?)"|
345 * m|#\s*include\s*<(.*?>"|
346 * m|#\s*(?define|undef)\s*CONFIG_(\w*)|
347 * m|(?!\w)CONFIG_|
348 *
349 * About 98% of the CPU time is spent here, and most of that is in
350 * the 'start' paragraph. Because the current characters are
351 * in a register, the start loop usually eats 4 or 8 characters
352 * per memory read. The MAX5 and MIN5 tests dispose of most
353 * input characters with 1 or 2 comparisons.
354 */
355void state_machine(const char * map, const char * end)
356{
357 const char * next = map;
358 const char * map_dot;
359 unsigned long __buf = 0;
360
361 for (;;) {
362start:
363 GETNEXT
364__start:
365 if (current > MAX5('/','\'','"','#','C')) goto start;
366 if (current < MIN5('/','\'','"','#','C')) goto start;
367 CASE('/', slash);
368 CASE('\'', squote);
369 CASE('"', dquote);
370 CASE('#', pound);
371 CASE('C', cee);
372 goto start;
373
374/* // */
375slash_slash:
376 GETNEXT
377 CASE('\n', start);
378 NOTCASE('\\', slash_slash);
379 GETNEXT
380 goto slash_slash;
381
382/* / */
383slash:
384 GETNEXT
385 CASE('/', slash_slash);
386 NOTCASE('*', __start);
387slash_star_dot_star:
388 GETNEXT
389__slash_star_dot_star:
390 NOTCASE('*', slash_star_dot_star);
391 GETNEXT
392 NOTCASE('/', __slash_star_dot_star);
393 goto start;
394
395/* '.*?' */
396squote:
397 GETNEXT
398 CASE('\'', start);
399 NOTCASE('\\', squote);
400 GETNEXT
401 goto squote;
402
403/* ".*?" */
404dquote:
405 GETNEXT
406 CASE('"', start);
407 NOTCASE('\\', dquote);
408 GETNEXT
409 goto dquote;
410
411/* #\s* */
412pound:
413 GETNEXT
414 CASE(' ', pound);
415 CASE('\t', pound);
416 CASE('i', pound_i);
417 CASE('d', pound_d);
418 CASE('u', pound_u);
419 goto __start;
420
421/* #\s*i */
422pound_i:
423 GETNEXT NOTCASE('n', __start);
424 GETNEXT NOTCASE('c', __start);
425 GETNEXT NOTCASE('l', __start);
426 GETNEXT NOTCASE('u', __start);
427 GETNEXT NOTCASE('d', __start);
428 GETNEXT NOTCASE('e', __start);
429 goto pound_include;
430
431/* #\s*include\s* */
432pound_include:
433 GETNEXT
434 CASE(' ', pound_include);
435 CASE('\t', pound_include);
436 map_dot = next;
437 CASE('"', pound_include_dquote);
438 CASE('<', pound_include_langle);
439 goto __start;
440
441/* #\s*include\s*"(.*)" */
442pound_include_dquote:
443 GETNEXT
444 CASE('\n', start);
445 NOTCASE('"', pound_include_dquote);
446 handle_include(0, map_dot, next - map_dot - 1);
447 goto start;
448
449/* #\s*include\s*<(.*)> */
450pound_include_langle:
451 GETNEXT
452 CASE('\n', start);
453 NOTCASE('>', pound_include_langle);
454 handle_include(1, map_dot, next - map_dot - 1);
455 goto start;
456
457/* #\s*d */
458pound_d:
459 GETNEXT NOTCASE('e', __start);
460 GETNEXT NOTCASE('f', __start);
461 GETNEXT NOTCASE('i', __start);
462 GETNEXT NOTCASE('n', __start);
463 GETNEXT NOTCASE('e', __start);
464 goto pound_define_undef;
465
466/* #\s*u */
467pound_u:
468 GETNEXT NOTCASE('n', __start);
469 GETNEXT NOTCASE('d', __start);
470 GETNEXT NOTCASE('e', __start);
471 GETNEXT NOTCASE('f', __start);
472 goto pound_define_undef;
473
474/*
475 * #\s*(define|undef)\s*CONFIG_(\w*)
476 *
477 * this does not define the word, because it could be inside another
478 * conditional (#if 0). But I do parse the word so that this instance
479 * does not count as a use. -- mec
480 */
481pound_define_undef:
482 GETNEXT
483 CASE(' ', pound_define_undef);
484 CASE('\t', pound_define_undef);
485
486 NOTCASE('C', __start);
487 GETNEXT NOTCASE('O', __start);
488 GETNEXT NOTCASE('N', __start);
489 GETNEXT NOTCASE('F', __start);
490 GETNEXT NOTCASE('I', __start);
491 GETNEXT NOTCASE('G', __start);
492 GETNEXT NOTCASE('_', __start);
493
494 map_dot = next;
495pound_define_undef_CONFIG_word:
496 GETNEXT
497 if (isalnum(current) || current == '_')
498 goto pound_define_undef_CONFIG_word;
499 goto __start;
500
501/* \<CONFIG_(\w*) */
502cee:
503 if (next >= map+2 && (isalnum((int)next[-2]) || next[-2] == '_'))
504 goto start;
505 GETNEXT NOTCASE('O', __start);
506 GETNEXT NOTCASE('N', __start);
507 GETNEXT NOTCASE('F', __start);
508 GETNEXT NOTCASE('I', __start);
509 GETNEXT NOTCASE('G', __start);
510 GETNEXT NOTCASE('_', __start);
511
512 map_dot = next;
513cee_CONFIG_word:
514 GETNEXT
515 if (isalnum(current) || current == '_')
516 goto cee_CONFIG_word;
517 use_config(map_dot, next - map_dot - 1);
518 goto __start;
519 }
520}
521
522
523
524/*
525 * Generate dependencies for one file.
526 */
527void do_depend(const char * filename)
528{
529 int mapsize;
530 int pagesizem1 = getpagesize()-1;
531 int fd;
532 struct stat st;
533 char * map;
534
535 fd = open(filename, O_RDONLY);
536 if (fd < 0) {
537 perror(filename);
538 return;
539 }
540
541 fstat(fd, &st);
542 if (st.st_size == 0) {
543 fprintf(stderr,"%s is empty\n",filename);
544 close(fd);
545 return;
546 }
547
548 mapsize = st.st_size;
549 mapsize = (mapsize+pagesizem1) & ~pagesizem1;
550 map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
551 if ((long) map == -1) {
552 perror("mkdep: mmap");
553 close(fd);
554 return;
555 }
556 if ((unsigned long) map % sizeof(unsigned long) != 0)
557 {
558 fprintf(stderr, "do_depend: map not aligned\n");
559 exit(1);
560 }
561
562 hasdep = 0;
563 clear_config();
564 state_machine(map, map+st.st_size);
565 if (hasdep) {
566 puts("");
567 }
568
569 munmap(map, mapsize);
570 close(fd);
571}
572
573
574
575/*
576 * Generate dependencies for all files.
577 */
578int main(int argc, char **argv)
579{
580 int len;
581 const char *hpath;
582
583 hpath = getenv("TOPDIR");
584 if (!hpath) {
585 fputs("mkdep: TOPDIR not set in environment. "
586 "Don't bypass the top level Makefile.\n", stderr);
587 return 1;
588 }
589
590 add_path("."); /* for #include "..." */
591
592 while (++argv, --argc > 0) {
593 if (strncmp(*argv, "-I", 2) == 0) {
594 if (*((*argv)+2)) {
595 add_path((*argv)+2);
596 }
597 else {
598 ++argv;
599 --argc;
600 add_path(*argv);
601 }
602 }
603 else if (strcmp(*argv, "--") == 0) {
604 break;
605 }
606 }
607
608 add_path(hpath); /* must be last entry, for config files */
609
610 while (--argc > 0) {
611 const char * filename = *++argv;
612 g_filename = 0;
613 len = strlen(filename);
614 memcpy(depname, filename, len+1);
615 if (len > 2 && filename[len-2] == '.') {
616 if (filename[len-1] == 'c' || filename[len-1] == 'S') {
617 depname[len-1] = 'o';
618 g_filename = filename;
619 }
620 }
621 do_depend(filename);
622 }
623 if (len_precious) {
624 *(str_precious+len_precious) = '\0';
625 printf(".PRECIOUS:%s\n", str_precious);
626 }
627 return 0;
628}
diff --git a/scripts/split-include.c b/scripts/split-include.c
deleted file mode 100644
index 624a0d62b..000000000
--- a/scripts/split-include.c
+++ /dev/null
@@ -1,226 +0,0 @@
1/*
2 * split-include.c
3 *
4 * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
5 * This is a C version of syncdep.pl by Werner Almesberger.
6 *
7 * This program takes autoconf.h as input and outputs a directory full
8 * of one-line include files, merging onto the old values.
9 *
10 * Think of the configuration options as key-value pairs. Then there
11 * are five cases:
12 *
13 * key old value new value action
14 *
15 * KEY-1 VALUE-1 VALUE-1 leave file alone
16 * KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file
17 * KEY-3 - VALUE-3 write VALUE-3 into file
18 * KEY-4 VALUE-4 - write an empty file
19 * KEY-5 (empty) - leave old empty file alone
20 */
21
22#include <sys/stat.h>
23#include <sys/types.h>
24
25#include <ctype.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32
33#define ERROR_EXIT(strExit) \
34 { \
35 const int errnoSave = errno; \
36 fprintf(stderr, "%s: ", str_my_name); \
37 errno = errnoSave; \
38 perror((strExit)); \
39 exit(1); \
40 }
41
42
43
44int main(int argc, const char * argv [])
45{
46 const char * str_my_name;
47 const char * str_file_autoconf;
48 const char * str_dir_config;
49
50 FILE * fp_config;
51 FILE * fp_target;
52 FILE * fp_find;
53
54 int buffer_size;
55
56 char * line;
57 char * old_line;
58 char * list_target;
59 char * ptarget;
60
61 struct stat stat_buf;
62
63 /* Check arg count. */
64 if (argc != 3)
65 {
66 fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
67 exit(1);
68 }
69
70 str_my_name = argv[0];
71 str_file_autoconf = argv[1];
72 str_dir_config = argv[2];
73
74 /* Find a buffer size. */
75 if (stat(str_file_autoconf, &stat_buf) != 0)
76 ERROR_EXIT(str_file_autoconf);
77 buffer_size = 2 * stat_buf.st_size + 4096;
78
79 /* Allocate buffers. */
80 if ( (line = malloc(buffer_size)) == NULL
81 || (old_line = malloc(buffer_size)) == NULL
82 || (list_target = malloc(buffer_size)) == NULL )
83 ERROR_EXIT(str_file_autoconf);
84
85 /* Open autoconfig file. */
86 if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
87 ERROR_EXIT(str_file_autoconf);
88
89 /* Make output directory if needed. */
90 if (stat(str_dir_config, &stat_buf) != 0)
91 {
92 if (mkdir(str_dir_config, 0755) != 0)
93 ERROR_EXIT(str_dir_config);
94 }
95
96 /* Change to output directory. */
97 if (chdir(str_dir_config) != 0)
98 ERROR_EXIT(str_dir_config);
99
100 /* Put initial separator into target list. */
101 ptarget = list_target;
102 *ptarget++ = '\n';
103
104 /* Read config lines. */
105 while (fgets(line, buffer_size, fp_config))
106 {
107 const char * str_config;
108 int is_same;
109 int itarget;
110
111 if (line[0] != '#')
112 continue;
113 if ((str_config = strstr(line, "CONFIG_")) == NULL)
114 continue;
115
116 /* Make the output file name. */
117 str_config += sizeof("CONFIG_") - 1;
118 for (itarget = 0; !isspace(str_config[itarget]); itarget++)
119 {
120 char c = str_config[itarget];
121 if (isupper(c)) c = tolower(c);
122 if (c == '_') c = '/';
123 ptarget[itarget] = c;
124 }
125 ptarget[itarget++] = '.';
126 ptarget[itarget++] = 'h';
127 ptarget[itarget++] = '\0';
128
129 /* Check for existing file. */
130 is_same = 0;
131 if ((fp_target = fopen(ptarget, "r")) != NULL)
132 {
133 fgets(old_line, buffer_size, fp_target);
134 if (fclose(fp_target) != 0)
135 ERROR_EXIT(ptarget);
136 if (!strcmp(line, old_line))
137 is_same = 1;
138 }
139
140 if (!is_same)
141 {
142 /* Auto-create directories. */
143 int islash;
144 for (islash = 0; islash < itarget; islash++)
145 {
146 if (ptarget[islash] == '/')
147 {
148 ptarget[islash] = '\0';
149 if (stat(ptarget, &stat_buf) != 0
150 && mkdir(ptarget, 0755) != 0)
151 ERROR_EXIT( ptarget );
152 ptarget[islash] = '/';
153 }
154 }
155
156 /* Write the file. */
157 if ((fp_target = fopen(ptarget, "w" )) == NULL)
158 ERROR_EXIT(ptarget);
159 fputs(line, fp_target);
160 if (ferror(fp_target) || fclose(fp_target) != 0)
161 ERROR_EXIT(ptarget);
162 }
163
164 /* Update target list */
165 ptarget += itarget;
166 *(ptarget-1) = '\n';
167 }
168
169 /*
170 * Close autoconfig file.
171 * Terminate the target list.
172 */
173 if (fclose(fp_config) != 0)
174 ERROR_EXIT(str_file_autoconf);
175 *ptarget = '\0';
176
177 /*
178 * Fix up existing files which have no new value.
179 * This is Case 4 and Case 5.
180 *
181 * I re-read the tree and filter it against list_target.
182 * This is crude. But it avoids data copies. Also, list_target
183 * is compact and contiguous, so it easily fits into cache.
184 *
185 * Notice that list_target contains strings separated by \n,
186 * with a \n before the first string and after the last.
187 * fgets gives the incoming names a terminating \n.
188 * So by having an initial \n, strstr will find exact matches.
189 */
190
191 fp_find = popen("find * -type f -name \"*.h\" -print", "r");
192 if (fp_find == 0)
193 ERROR_EXIT( "find" );
194
195 line[0] = '\n';
196 while (fgets(line+1, buffer_size, fp_find))
197 {
198 if (strstr(list_target, line) == NULL)
199 {
200 /*
201 * This is an old file with no CONFIG_* flag in autoconf.h.
202 */
203
204 /* First strip the \n. */
205 line[strlen(line)-1] = '\0';
206
207 /* Grab size. */
208 if (stat(line+1, &stat_buf) != 0)
209 ERROR_EXIT(line);
210
211 /* If file is not empty, make it empty and give it a fresh date. */
212 if (stat_buf.st_size != 0)
213 {
214 if ((fp_target = fopen(line+1, "w")) == NULL)
215 ERROR_EXIT(line);
216 if (fclose(fp_target) != 0)
217 ERROR_EXIT(line);
218 }
219 }
220 }
221
222 if (pclose(fp_find) != 0)
223 ERROR_EXIT("find");
224
225 return 0;
226}