]>
Commit | Line | Data |
---|---|---|
316670eb A |
1 | /* ************************************************************************ *\ |
2 | * * | |
3 | * File: md.c * | |
4 | * * | |
5 | * Updates makefiles from the .n dependency files generated by the * | |
6 | * -MD option to "cc" (and "cpp"). * | |
7 | * * | |
8 | * Abstract: * | |
9 | * * | |
10 | * Basically, "md" does two things: * | |
11 | * 1) It processes the raw dependency files produced by the cpp -MD * | |
12 | * option. There is one line in the file for every #include * | |
13 | * encountered, but there are repeats and patterns like * | |
14 | * .../dir1/../dir2 appear which should reduce to .../dir2 * | |
15 | * Md canonicalizes and flushes repeats from the dependency * | |
16 | * list. It also sorts the file names and "fills" them to a 78 * | |
17 | * character line. * | |
18 | * 2) Md also updates the makefile directly with the dependency * | |
19 | * information, so the .d file can be thrown away (-- -d option) * | |
20 | * This is done to save space. Md assumes that dependency * | |
21 | * information in the makefile is sorted by .o file name and it * | |
22 | * procedes to merge in (add/or replace [as appropriate]) the new * | |
23 | * dependency lines that it has generated. For time effeciency, * | |
24 | * Md assumes that any .d files it is given that were created * | |
25 | * before the creation date of the "makefile" were processed * | |
26 | * already. It ignores them unless the force flag (-f) is given. * | |
27 | * * | |
28 | * Arguments: * | |
29 | * * | |
30 | * -d delete the .d file after it is processed * | |
31 | * -f force an update of the dependencies in the makefile * | |
32 | * even though the makefile is more recent than the .n file * | |
33 | * (This implies that md has been run already.) * | |
34 | * -m specify the makefile to be upgraded. The defaults are * | |
35 | * "makefile" and then "Makefile". * | |
36 | * -u like -m above, but the file will be created if necessary * | |
37 | * -o specify an output file for the dependencies other than a * | |
38 | * makefile * | |
39 | * -v set the verbose flag * | |
40 | * -x expunge old dependency info from makefile * | |
41 | * -D subswitch for debugging. can be followed by any of * | |
42 | * "c", "d", "m", "o", "t", "D" meaning: * | |
43 | * c show file contents * | |
44 | * d show new dependency crunching * | |
45 | * m show generation of makefile * | |
46 | * o show files being opened * | |
47 | * t show time comparisons * | |
48 | * D show very low level debugging * | |
49 | * * | |
50 | * Author: Robert V. Baron * | |
51 | * Copyright (c) 1986 by Robert V. Baron * | |
52 | * * | |
53 | * HISTORY * | |
54 | * 29-Apr-87 Robert Baron (rvb) at Carnegie-Mellon University | |
55 | * If specified -u file does not exist, assume it is empty and | |
56 | * generate one. As a sanity check, it must be possible to create | |
57 | * the output file. | |
58 | * Also, generalized fix below to handle any case of . as a | |
59 | * file name. | |
60 | * | |
61 | * 25-Mar-87 Mary Thompson (mrt) at Carnegie Mellon | |
62 | * Fixed up pathnamecanonicalization to recognize .// and | |
63 | * drop the second / as well. mmax cpp generates this form. | |
64 | * | |
65 | * 6-Jan-87 Robert Baron (rvb) at Carnegie-Mellon University | |
66 | * Fixed up pathname canonicalization to that ../../, etc would be | |
67 | * handled correctly. | |
68 | * Also made "force" on by default. | |
69 | * | |
70 | * 16-Mar-86 Robert Baron (rvb) at Carnegie-Mellon University | |
71 | * Created 4/16/86 * | |
72 | * * | |
73 | \* ************************************************************************ */ | |
74 | ||
75 | ||
76 | #include <sys/types.h> | |
77 | #include <sys/stat.h> | |
78 | #include <stdio.h> | |
79 | #include <stdlib.h> | |
80 | #include <string.h> | |
81 | ||
82 | #define LINESIZE 65536 // NeXT_MOD | |
83 | ||
84 | #define OUTLINELEN 79 | |
85 | #define IObuffer 50000 | |
86 | #define SALUTATION "# Dependencies for File:" | |
87 | #define SALUTATIONLEN (sizeof SALUTATION - 1) | |
88 | #define OLDSALUTATION "# DO NOT DELETE THIS LINE" | |
89 | #define OLDSALUTATIONLEN (sizeof OLDSALUTATION - 1) | |
90 | ||
91 | char file_array[IObuffer]; /* read file and store crunched names */ | |
92 | char dep_line[LINESIZE]; /* line being processed */ | |
93 | char dot_o[LINESIZE]; /* <foo.o>: prefix */ | |
94 | char *path_component[100]; /* stores components for a path while being | |
95 | crunched */ | |
96 | ||
97 | struct dep { /* stores paths that a file depends on */ | |
98 | int len; | |
99 | char *str; | |
100 | } dep_files[1000]; | |
101 | int dep_file_index; | |
102 | ||
103 | qsort_strcmp(a, b) | |
104 | struct dep *a, *b; | |
105 | { | |
106 | extern int strcmp(); | |
107 | return strcmp(a->str, b->str); | |
108 | } | |
109 | ||
110 | char *outfile = (char *) 0; /* generate dependency file */ | |
111 | FILE *out; | |
112 | ||
113 | char *makefile = (char *) 0; /* user supplied makefile name */ | |
114 | char *real_mak_name; /* actual makefile name (if not supplied) */ | |
115 | char shadow_mak_name[LINESIZE]; /* changes done here then renamed */ | |
116 | FILE *mak; /* for reading makefile */ | |
117 | FILE *makout; /* for writing shadow */ | |
118 | char makbuf[LINESIZE]; /* one line buffer for makefile */ | |
119 | struct stat makstat; /* stat of makefile for time comparisons */ | |
120 | int mak_eof = 0; /* eof seen on makefile */ | |
121 | FILE *find_mak(), *temp_mak(); | |
122 | ||
123 | int delete = 0; /* -d delete dependency file */ | |
124 | int debug = 0; | |
125 | int D_contents = 0; /* print file contents */ | |
126 | int D_depend = 0; /* print dependency processing info */ | |
127 | int D_make = 0; /* print makefile processing info */ | |
128 | int D_open = 0; /* print after succesful open */ | |
129 | int D_time = 0; /* print time comparison info */ | |
130 | int force = 1; /* always update dependency info */ | |
131 | int update = 0; /* it's ok if the -m file does not exist */ | |
132 | int verbose = 0; /* tell me something */ | |
133 | int expunge = 0; /* first flush dependency stuff from makefile */ | |
134 | ||
135 | ||
136 | char *name; | |
137 | ||
138 | static void scan_mak(FILE *, FILE *, char *); | |
139 | static void finish_mak(FILE *, FILE *); | |
140 | ||
141 | main(argc,argv) | |
142 | register char **argv; | |
143 | { | |
144 | int size; | |
145 | ||
146 | name = *argv; | |
147 | {register char *cp =name; | |
148 | while (*cp) if (*cp++ == '/') name = cp; | |
149 | } | |
150 | ||
151 | for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; | |
152 | if (*token++ != '-' || !*token) | |
153 | break; | |
154 | else { register int flag; | |
155 | for ( ; flag = *token++ ; ) { | |
156 | switch (flag) { | |
157 | case 'd': | |
158 | delete++; | |
159 | break; | |
160 | case 'f': | |
161 | force++; | |
162 | break; | |
163 | case 'u': | |
164 | update++; | |
165 | case 'm': | |
166 | makefile = *++argv; | |
167 | if (--argc < 0) goto usage; | |
168 | break; | |
169 | case 'o': | |
170 | outfile = *++argv; | |
171 | if (--argc < 0) goto usage; | |
172 | break; | |
173 | case 'v': | |
174 | verbose++; | |
175 | break; | |
176 | case 'x': | |
177 | expunge++; | |
178 | break; | |
179 | case 'D': | |
180 | for ( ; flag = *token++ ; ) | |
181 | switch (flag) { | |
182 | case 'c': | |
183 | D_contents++; | |
184 | break; | |
185 | case 'd': | |
186 | D_depend++; | |
187 | break; | |
188 | case 'm': | |
189 | D_make++; | |
190 | break; | |
191 | case 'o': | |
192 | D_open++; | |
193 | break; | |
194 | case 't': | |
195 | D_time++; | |
196 | break; | |
197 | case 'D': | |
198 | debug++; | |
199 | break; | |
200 | default: | |
201 | goto letters; | |
202 | } | |
203 | goto newtoken; | |
204 | default: | |
205 | goto usage; | |
206 | } | |
207 | letters: ; | |
208 | } | |
209 | } | |
210 | newtoken: ; | |
211 | } | |
212 | ||
213 | if (!expunge && argc < 1) goto usage; | |
214 | if ((int) outfile && (int) makefile) /* not both */ | |
215 | goto usage; | |
216 | ||
217 | if ((int) outfile) { | |
218 | /* | |
219 | * NeXT_MOD, For SGS stuff, in case still linked to master version | |
220 | */ | |
221 | unlink(outfile); | |
222 | ||
223 | if ((out = fopen(outfile, "w")) == NULL) { | |
224 | fprintf(stderr, "%s: outfile = \"%s\" ", name, outfile); | |
225 | perror("fopen"); | |
226 | fflush(stdout), fflush(stderr); | |
227 | exit(1); | |
228 | } else if (D_open) | |
229 | printf("%s: opened outfile \"%s\"\n", name, outfile); | |
230 | } else if (mak = find_mak(makefile)) { | |
231 | makout = temp_mak(); | |
232 | out = makout; | |
233 | if (expunge) | |
234 | expunge_mak(mak, makout); | |
235 | else | |
236 | skip_mak(mak, makout); | |
237 | } else if (mak_eof && /* non existent file == mt file */ | |
238 | (int)(makout = temp_mak())) { /* but we need to be able */ | |
239 | out = makout; /* to write here */ | |
240 | } else if (makefile) { | |
241 | fprintf(stderr, "%s: makefile \"%s\" can not be opened or stat'ed\n", | |
242 | name, makefile); | |
243 | exit(2); | |
244 | } | |
245 | ||
246 | for (; argc--; argv++) { | |
247 | dep_file_index = 0; | |
248 | ||
249 | if (size = read_dep(*argv)) { | |
250 | ||
251 | save_dot_o(); | |
252 | if (D_depend) printf("%s: dot_o = \"%s\"\n", name, dot_o); | |
253 | ||
254 | parse_dep(); | |
255 | if (mak) scan_mak(mak, makout, dot_o); | |
256 | if (out) output_dep(out); | |
257 | ||
258 | if (delete) | |
259 | unlink(*argv); | |
260 | } | |
261 | } | |
262 | ||
263 | if (mak) finish_mak(mak, makout); | |
264 | rename(shadow_mak_name, real_mak_name); | |
265 | exit(0); | |
266 | usage: | |
267 | fprintf(stderr, "usage: md -f -Dcdmot -m makefile -o outputfile -v <file1> ... <filen>\n"); | |
268 | exit(1); | |
269 | } | |
270 | ||
271 | ||
272 | read_dep(file) | |
273 | register char *file; | |
274 | { | |
275 | register int fd; | |
276 | register int size; | |
277 | struct stat statbuf; | |
278 | ||
279 | if ((fd = open(file, 0)) < 0) { | |
280 | fprintf(stderr, "%s: file = \"%s\" ", name, file); | |
281 | perror("open"); | |
282 | fflush(stdout), fflush(stderr); | |
283 | return 0; | |
284 | } | |
285 | if (D_open) | |
286 | printf("%s: opened dependency file \"%s\"\n", name, file); | |
287 | ||
288 | if (fstat(fd, &statbuf) < 0) { | |
289 | fprintf(stderr, "%s: file = \"%s\" ", name, file); | |
290 | perror("stat"); | |
291 | fflush(stdout), fflush(stderr); | |
292 | goto out; | |
293 | } | |
294 | switch(statbuf.st_mode & S_IFMT) { | |
295 | case S_IFREG: | |
296 | if (D_time) | |
297 | printf("%s: file time = %d\n", name, statbuf.st_mtime); | |
298 | ||
299 | if (statbuf.st_size > IObuffer) { | |
300 | fprintf(stderr, "%s: file \"%s\" tooo big for IObuffer\n", | |
301 | name, file); | |
302 | goto out; | |
303 | } else if (force) | |
304 | break; | |
305 | else if ((int) mak && statbuf.st_mtime < makstat.st_mtime) { | |
306 | if (verbose || D_time) | |
307 | fprintf(stderr, "%s: skipping \"%s\" %d < %d \"%s\"\n", | |
308 | name, file, statbuf.st_mtime, makstat.st_mtime, | |
309 | real_mak_name); | |
310 | goto out; | |
311 | } else /* >= =>ok */ | |
312 | break; | |
313 | case S_IFDIR: | |
314 | case S_IFLNK: | |
315 | case S_IFCHR: | |
316 | case S_IFBLK: | |
317 | case S_IFSOCK: | |
318 | default: | |
319 | fprintf(stderr, "%s: bad mode: 0%o on \"%s\"\n", | |
320 | name, statbuf.st_mode, file); | |
321 | fflush(stdout), fflush(stderr); | |
322 | goto out; | |
323 | } | |
324 | ||
325 | if ((size = read(fd, file_array, sizeof (file_array))) < 0) { | |
326 | fprintf(stderr, "%s: file = \"%s\" ", name, file); | |
327 | perror("read"); | |
328 | fflush(stdout), fflush(stderr); | |
329 | goto out; | |
330 | } | |
331 | file_array[size] = 0; | |
332 | ||
333 | if (close(fd) < 0) { | |
334 | fprintf(stderr, "%s: file = \"%s\" ", name, file); | |
335 | perror("close"); | |
336 | fflush(stdout), fflush(stderr); | |
337 | return 0; | |
338 | } | |
339 | ||
340 | if (D_depend && D_contents) | |
341 | printf("file_array: \"%s\"\n", file_array); | |
342 | return size; | |
343 | out: ; | |
344 | close(fd); | |
345 | return 0; | |
346 | } | |
347 | ||
348 | save_dot_o() | |
349 | { | |
350 | register char *cp = file_array; | |
351 | register char *svp = dot_o; | |
352 | register int c; | |
353 | ||
354 | while ((*svp++ = (c = *cp++)) && c != ':'); | |
355 | *svp = 0; | |
356 | } | |
357 | ||
358 | parse_dep() | |
359 | { | |
360 | register char *lp = file_array; | |
361 | register int c; | |
362 | ||
363 | while (*lp) {register char *tlp = lp; | |
364 | register char *cp = dep_line; | |
365 | register int i = 0; | |
366 | int abspath = 0; | |
367 | char oldc; | |
368 | char *oldcp; | |
369 | ||
370 | /* get a line to process */ | |
371 | while ((c = *lp++) && c != '\n') | |
372 | { | |
373 | if (c == '\\') | |
374 | lp++; /* skip backslash newline */ | |
375 | else | |
376 | *cp++ = c; | |
377 | } | |
378 | if (!c) | |
379 | break; | |
380 | *cp = 0; | |
381 | cp = dep_line; | |
382 | lp[-1] = 0; | |
383 | /* skip .o file name */ | |
384 | while ((c = *cp++) && c != ':'); if (!c) continue; | |
385 | next_filename: | |
386 | i = 0; | |
387 | abspath = 0; | |
388 | while ((c = *cp) && (c == ' ' || c == '\t')) cp++; if (!c) continue; | |
389 | ||
390 | /* canonicalization processing */ | |
391 | ||
392 | /* initial / is remembered */ | |
393 | if (c == '/') | |
394 | abspath++; | |
395 | ||
396 | while (c && c != ' ' && c != '\t') { | |
397 | if (D_depend) printf("i = %d going \"%s\"\n", i, cp); | |
398 | /* kill \'s */ | |
399 | while ((c = *cp) && c == '/') cp++; if (!c) break; | |
400 | path_component[i] = cp; | |
401 | /* swallow chars till next / or null */ | |
402 | while ((c = *cp++) && c != '/' && c != ' ' && c != '\t'); | |
403 | if (c) cp[-1]=0;/* end component C style */ | |
404 | ||
405 | /* ignore . */; | |
406 | if (!strcmp(path_component[i], ".")) | |
407 | ; /* if "component" != .. */ | |
408 | else /* don't reduce /component/.. to nothing */ | |
409 | i++; /* there could be symbolic links! */ | |
410 | } | |
411 | /* reassemble components */ | |
412 | oldc = c; /* save c */ | |
413 | oldcp = cp; /* save cp */ | |
414 | cp = tlp; /* overwrite line in buffer */ | |
415 | if (abspath) | |
416 | *cp++ = '/'; | |
417 | for (c=0; c<i; c++) {register char *ccp = path_component[c]; | |
418 | while (*cp++ = *ccp++); | |
419 | *--cp = '/'; | |
420 | cp++; | |
421 | } | |
422 | *--cp = 0; | |
423 | ||
424 | c=dep_file_index++; | |
425 | dep_files[c].str = tlp; | |
426 | dep_files[c].len = cp - tlp; | |
427 | if (D_depend) | |
428 | printf("%s: dep_file[%d] = \"%s\" Len %d\n", | |
429 | name, dep_file_index - 1, tlp, cp - tlp); | |
430 | tlp = cp + 1; | |
431 | if (oldc) | |
432 | { | |
433 | cp = oldcp; | |
434 | goto next_filename; | |
435 | } | |
436 | } | |
437 | } | |
438 | ||
439 | output_dep(out) | |
440 | FILE *out; | |
441 | { | |
442 | register int j; | |
443 | register int size = 1000; | |
444 | register int dot_o_len = strlen(dot_o); | |
445 | register struct dep *dp = dep_files; | |
446 | int written = 0; | |
447 | ||
448 | if (D_depend && debug) | |
449 | for(j = 0; j < dep_file_index; j++) { | |
450 | printf("dep_files[%d] = %s\n", j, dep_files[j].str); | |
451 | } | |
452 | ||
453 | qsort(dep_files, dep_file_index, sizeof (struct dep), qsort_strcmp); | |
454 | ||
455 | if (D_depend && debug) | |
456 | for(j = 0; j < dep_file_index; j++) { | |
457 | printf("dep_files[%d] = %s\n", j, dep_files[j].str); | |
458 | } | |
459 | ||
460 | fprintf(out, "%s %s", SALUTATION, dot_o); | |
461 | for(j = 0; j < dep_file_index; j++, dp++) | |
462 | {register int len = dp->len; | |
463 | register char *str = dp->str; | |
464 | if (j && len == (dp-1)->len && !strcmp(str, (dp-1)->str)) | |
465 | continue; | |
466 | written++; | |
467 | if (size + len + 1 > OUTLINELEN) { | |
468 | fprintf(out, "\n%s %s", dot_o, str); | |
469 | size = dot_o_len + len + 1; | |
470 | } else { | |
471 | fprintf(out, " %s", str); | |
472 | size += len + 1; | |
473 | } | |
474 | } | |
475 | fprintf(out, "\n"); | |
476 | if (verbose) | |
477 | fprintf(stdout, "%s: \"%s\" %d => %d\n", name, dot_o, dep_file_index, written); | |
478 | } | |
479 | ||
480 | /* process makefile */ | |
481 | FILE * | |
482 | find_mak(file) | |
483 | char *file; | |
484 | { | |
485 | FILE *mak; | |
486 | ||
487 | if ((int) file) { | |
488 | if ((mak = fopen(file, "r")) != NULL) { | |
489 | real_mak_name = file; | |
490 | } else if (update) { | |
491 | mak_eof = 1; | |
492 | real_mak_name = file; | |
493 | return NULL; | |
494 | } else { | |
495 | fprintf(stderr, "%s: file = \"%s\" ", name, file); | |
496 | perror("fopen"); | |
497 | fflush(stdout), fflush(stderr); | |
498 | return NULL; | |
499 | } | |
500 | } else { | |
501 | if ((mak = fopen("makefile", "r")) != NULL) { | |
502 | real_mak_name = "makefile"; | |
503 | } else if ((mak = fopen("Makefile", "r")) != NULL) { | |
504 | real_mak_name = "Makefile"; | |
505 | } else return NULL; | |
506 | } | |
507 | ||
508 | if (fstat(fileno(mak), &makstat) < 0) { | |
509 | fprintf(stderr, "%s: file = \"%s\" ", name, real_mak_name); | |
510 | perror("stat"); | |
511 | fflush(stdout), fflush(stderr); | |
512 | return NULL; | |
513 | } | |
514 | if (D_open) | |
515 | printf("%s: opened makefile \"%s\"\n", name, real_mak_name); | |
516 | if (D_time) | |
517 | printf("%s: makefile time = %d\n", name, makstat.st_mtime); | |
518 | ||
519 | return mak; | |
520 | } | |
521 | ||
522 | FILE * | |
523 | temp_mak() | |
524 | { | |
525 | FILE *mak; | |
526 | ||
527 | strcpy(shadow_mak_name, real_mak_name); | |
528 | strcat(shadow_mak_name, ".md"); | |
529 | ||
530 | /* | |
531 | * For SGS stuff, in case still linked to master version | |
532 | */ | |
533 | unlink(shadow_mak_name); | |
534 | if ((mak = fopen(shadow_mak_name, "w")) == NULL) { | |
535 | fprintf(stderr, "%s: file = \"%s\" ", name, shadow_mak_name); | |
536 | perror("fopen"); | |
537 | fflush(stdout), fflush(stderr); | |
538 | return NULL; | |
539 | } | |
540 | if (D_open) | |
541 | printf("%s: opened makefile.md \"%s\"\n", name, shadow_mak_name); | |
542 | ||
543 | return mak; | |
544 | } | |
545 | ||
546 | skip_mak(makin, makout) | |
547 | register FILE *makin, *makout; | |
548 | { | |
549 | register int len = SALUTATIONLEN; | |
550 | ||
551 | if (D_make) | |
552 | printf("skipping in \"%s\" ", real_mak_name); | |
553 | ||
554 | while (fgets(makbuf, LINESIZE, makin) != NULL) { | |
555 | if (D_make && D_contents) | |
556 | printf("%s: \"%s\"\n", real_mak_name, makbuf); | |
557 | if (strncmp(makbuf, SALUTATION, len)) { | |
558 | fputs(makbuf, makout); | |
559 | } else | |
560 | break; | |
561 | } | |
562 | mak_eof = feof(makin); | |
563 | if (mak_eof) | |
564 | fclose(makin); | |
565 | if (D_make) | |
566 | printf("eof = %d str = \"%s\"", mak_eof, makbuf); | |
567 | } | |
568 | ||
569 | expunge_mak(makin, makout) | |
570 | register FILE *makin, *makout; | |
571 | { | |
572 | register int len = SALUTATIONLEN; | |
573 | register int oldlen = OLDSALUTATIONLEN; | |
574 | ||
575 | if (D_make) | |
576 | printf("expunging in \"%s\" ", real_mak_name); | |
577 | ||
578 | while (fgets(makbuf, LINESIZE, makin) != NULL) { | |
579 | if (D_make && D_contents) | |
580 | printf("%s: \"%s\"\n", real_mak_name, makbuf); | |
581 | if (! strncmp(makbuf, SALUTATION, len) || | |
582 | ! strncmp(makbuf, OLDSALUTATION, oldlen)) | |
583 | break; | |
584 | else | |
585 | fputs(makbuf, makout); | |
586 | } | |
587 | mak_eof = 1; | |
588 | if (mak_eof) | |
589 | fclose(makin); | |
590 | if (D_make) | |
591 | printf("eof = %d str = \"%s\"", mak_eof, makbuf); | |
592 | } | |
593 | ||
594 | static void | |
595 | scan_mak(FILE *makin, FILE *makout, char *file) | |
596 | { | |
597 | register char *cp = &makbuf[SALUTATIONLEN+1]; | |
598 | register int len = strlen(file); | |
599 | register int ret; | |
600 | ||
601 | if (D_make) | |
602 | printf("scanning in \"%s\" for \"%s\"\n", real_mak_name, file); | |
603 | ||
604 | do { | |
605 | if (mak_eof) /* don't scan any more */ | |
606 | return; | |
607 | ||
608 | ret = strncmp(cp, file, len); | |
609 | if (D_make) | |
610 | printf("saw \"%s\" ret = %d\n", cp, ret); | |
611 | ||
612 | if (ret < 0) { /* skip forward till match or greater */ | |
613 | fputs(makbuf, makout); /* line we're looking at */ | |
614 | while (fgets(makbuf, LINESIZE, makin) != NULL) { | |
615 | if (strncmp(makbuf, SALUTATION, SALUTATIONLEN)) { | |
616 | fputs(makbuf, makout); | |
617 | } else | |
618 | break; | |
619 | } | |
620 | mak_eof = feof(makin); | |
621 | if (mak_eof) | |
622 | fclose(makin); | |
623 | continue; | |
624 | } else if (ret == 0) { /* flush match */ | |
625 | while (fgets(makbuf, LINESIZE, makin) != NULL) { | |
626 | if (strncmp(makbuf, SALUTATION, SALUTATIONLEN)) { | |
627 | ; /* flush old stuff */ | |
628 | } else | |
629 | break; | |
630 | } | |
631 | mak_eof = feof(makin); | |
632 | if (mak_eof) | |
633 | fclose(makin); | |
634 | break; | |
635 | } else { /* no luck this time */ | |
636 | break; | |
637 | } | |
638 | } while (1); | |
639 | } | |
640 | ||
641 | static void | |
642 | finish_mak(FILE *makin, FILE *makout) | |
643 | { | |
644 | if (mak_eof) /* don't scan any more */ | |
645 | return; | |
646 | ||
647 | if (D_make) | |
648 | printf("finishing in \"%s\"\n", real_mak_name); | |
649 | ||
650 | fputs(makbuf, makout); /* line we're looking at */ | |
651 | while (fgets(makbuf, LINESIZE, makin) != NULL) { | |
652 | fputs(makbuf, makout); | |
653 | } | |
654 | } |