diff options
| 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 |
| commit | 5e60dc4a209b053e8fe5170bd143173941c4634c (patch) | |
| tree | 43f8c3bf33914c701b2224b218d2ed21078ef2ea /scripts | |
| parent | ba50217281e9265aa5935d184f698204143e765f (diff) | |
| download | busybox-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.c | 855 | ||||
| -rw-r--r-- | scripts/mkdep.c | 628 | ||||
| -rw-r--r-- | scripts/split-include.c | 226 |
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 | |||
| 42 | typedef 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 | |||
| 53 | void bb_error_d(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); | ||
| 54 | char * bb_asprint(const char *format, ...) __attribute__ ((format (printf, 1, 2))); | ||
| 55 | |||
| 56 | /* stolen from libbb as is */ | ||
| 57 | typedef struct llist_s { | ||
| 58 | char *data; | ||
| 59 | struct llist_s *link; | ||
| 60 | } llist_t; | ||
| 61 | llist_t *llist_add_to(llist_t *old_head, char *new_item); | ||
| 62 | void *xrealloc(void *p, size_t size); | ||
| 63 | void *xmalloc(size_t size); | ||
| 64 | char *bb_xstrdup(const char *s); | ||
| 65 | char *bb_simplify_path(const char *path); | ||
| 66 | |||
| 67 | /* for lexical analyzier */ | ||
| 68 | static bb_key_t *key_top; | ||
| 69 | |||
| 70 | static void parse_inc(const char *include, const char *fname); | ||
| 71 | static void parse_conf_opt(char *opt, const char *val, size_t rsz); | ||
| 72 | |||
| 73 | #define CHECK_ONLY 0 | ||
| 74 | #define MAKE_NEW 1 | ||
| 75 | static 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 */ | ||
| 107 | static 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 | |||
| 394 | static void show_usage(void) __attribute__ ((noreturn)); | ||
| 395 | static 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 | |||
| 401 | static const char *kp; | ||
| 402 | static llist_t *Iop; | ||
| 403 | static bb_key_t *Ifound; | ||
| 404 | static int noiwarning; | ||
| 405 | static llist_t *configs; | ||
| 406 | |||
| 407 | static 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 | |||
| 426 | static 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 | |||
| 439 | static 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 | |||
| 475 | static 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 | |||
| 564 | static 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 | |||
| 593 | static llist_t *files; | ||
| 594 | |||
| 595 | static 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 | |||
| 653 | static 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 | |||
| 685 | int 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 | |||
| 742 | void 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 | |||
| 754 | void *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 | |||
| 763 | void *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 | |||
| 770 | char *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 | |||
| 785 | llist_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 | |||
| 796 | char *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 | |||
| 804 | char *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 | |||
| 48 | char depname[512]; | ||
| 49 | int hasdep; | ||
| 50 | |||
| 51 | struct path_struct { | ||
| 52 | int len; | ||
| 53 | char *buffer; | ||
| 54 | }; | ||
| 55 | struct path_struct *path_array; | ||
| 56 | int paths; | ||
| 57 | |||
| 58 | |||
| 59 | /* Current input file */ | ||
| 60 | static 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 | */ | ||
| 68 | char * str_config = NULL; | ||
| 69 | int size_config = 0; | ||
| 70 | int len_config = 0; | ||
| 71 | |||
| 72 | static void | ||
| 73 | do_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 | */ | ||
| 92 | void 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 | */ | ||
| 108 | int 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 | */ | ||
| 126 | void 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 | */ | ||
| 140 | void 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 | */ | ||
| 152 | char * str_precious = NULL; | ||
| 153 | int size_precious = 0; | ||
| 154 | int len_precious = 0; | ||
| 155 | |||
| 156 | |||
| 157 | |||
| 158 | /* | ||
| 159 | * Grow the precious string to a desired length. | ||
| 160 | * Usually the first growth is plenty. | ||
| 161 | */ | ||
| 162 | void 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 | */ | ||
| 178 | void 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 | */ | ||
| 194 | void 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 | */ | ||
| 222 | void 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 | */ | ||
| 264 | void 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 | */ | ||
| 355 | void 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 (;;) { | ||
| 362 | start: | ||
| 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 | /* // */ | ||
| 375 | slash_slash: | ||
| 376 | GETNEXT | ||
| 377 | CASE('\n', start); | ||
| 378 | NOTCASE('\\', slash_slash); | ||
| 379 | GETNEXT | ||
| 380 | goto slash_slash; | ||
| 381 | |||
| 382 | /* / */ | ||
| 383 | slash: | ||
| 384 | GETNEXT | ||
| 385 | CASE('/', slash_slash); | ||
| 386 | NOTCASE('*', __start); | ||
| 387 | slash_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 | /* '.*?' */ | ||
| 396 | squote: | ||
| 397 | GETNEXT | ||
| 398 | CASE('\'', start); | ||
| 399 | NOTCASE('\\', squote); | ||
| 400 | GETNEXT | ||
| 401 | goto squote; | ||
| 402 | |||
| 403 | /* ".*?" */ | ||
| 404 | dquote: | ||
| 405 | GETNEXT | ||
| 406 | CASE('"', start); | ||
| 407 | NOTCASE('\\', dquote); | ||
| 408 | GETNEXT | ||
| 409 | goto dquote; | ||
| 410 | |||
| 411 | /* #\s* */ | ||
| 412 | pound: | ||
| 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 */ | ||
| 422 | pound_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* */ | ||
| 432 | pound_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*"(.*)" */ | ||
| 442 | pound_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*<(.*)> */ | ||
| 450 | pound_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 */ | ||
| 458 | pound_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 */ | ||
| 467 | pound_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 | */ | ||
| 481 | pound_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; | ||
| 495 | pound_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*) */ | ||
| 502 | cee: | ||
| 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; | ||
| 513 | cee_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 | */ | ||
| 527 | void 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 | */ | ||
| 578 | int 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 | |||
| 44 | int 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 | } | ||
