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 | /* cleaned and adapted for Chameleon by cparm */␊ |
76 | ␊ |
77 | #include <sys/types.h>␊ |
78 | #include <sys/stat.h>␊ |
79 | #include <stdio.h>␊ |
80 | #include <stdlib.h>␊ |
81 | #include <string.h>␊ |
82 | #include <unistd.h>␊ |
83 | #include <fcntl.h>␊ |
84 | ␊ |
85 | #define LINESIZE 65536 // NeXT_MOD␊ |
86 | ␊ |
87 | #define OUTLINELEN 79␊ |
88 | #define IObuffer 50000␊ |
89 | #define SALUTATION "# Dependencies for File:"␊ |
90 | #define SALUTATIONLEN (sizeof SALUTATION - 1)␊ |
91 | #define OLDSALUTATION "# DO NOT DELETE THIS LINE"␊ |
92 | #define OLDSALUTATIONLEN (sizeof OLDSALUTATION - 1)␊ |
93 | ␊ |
94 | static char file_array[IObuffer]; /* read file and store crunched names */␊ |
95 | static char dep_line[LINESIZE]; /* line being processed */␊ |
96 | static char dot_o[LINESIZE]; /* <foo.o>: prefix */␊ |
97 | static char *path_component[100]; /* stores components for a path while being␊ |
98 | crunched */␊ |
99 | ␊ |
100 | static struct dep { /* stores paths that a file depends on */␊ |
101 | int len;␊ |
102 | char *str;␊ |
103 | } dep_files[1000];␊ |
104 | static int dep_file_index;␊ |
105 | ␊ |
106 | static int qsort_strcmp(struct dep *a, struct dep *b)␊ |
107 | {␊ |
108 | extern int strcmp();␊ |
109 | return strcmp(a->str, b->str);␊ |
110 | }␊ |
111 | ␊ |
112 | static char *outfile = (char *) 0; /* generate dependency file */␊ |
113 | static FILE *out;␊ |
114 | ␊ |
115 | static char *makefile = (char *) 0; /* user supplied makefile name */␊ |
116 | static char *real_mak_name; /* actual makefile name (if not supplied) */␊ |
117 | static char shadow_mak_name[LINESIZE]; /* changes done here then renamed */␊ |
118 | static FILE *mak; /* for reading makefile */␊ |
119 | static FILE *makout; /* for writing shadow */␊ |
120 | static char makbuf[LINESIZE]; /* one line buffer for makefile */␊ |
121 | static struct stat makstat; /* stat of makefile for time comparisons */␊ |
122 | static int mak_eof = 0; /* eof seen on makefile */␊ |
123 | ␊ |
124 | static int delete = 0; /* -d delete dependency file */␊ |
125 | static int debug = 0;␊ |
126 | static int D_contents = 0; /* print file contents */␊ |
127 | static int D_depend = 0; /* print dependency processing info */␊ |
128 | static int D_make = 0; /* print makefile processing info */␊ |
129 | static int D_open = 0; /* print after succesful open */␊ |
130 | static int D_time = 0; /* print time comparison info */␊ |
131 | static int force = 1; /* always update dependency info */␊ |
132 | static int update = 0; /* it's ok if the -m file does not exist */␊ |
133 | static int verbose = 0; /* tell me something */␊ |
134 | static int expunge = 0; /* first flush dependency stuff from makefile */␊ |
135 | ␊ |
136 | ␊ |
137 | static char *name;␊ |
138 | static int read_dep(register char *file);␊ |
139 | static void save_dot_o(void);␊ |
140 | static void parse_dep(void);␊ |
141 | static void output_dep(FILE *out);␊ |
142 | static FILE *find_mak(char *file);␊ |
143 | static FILE *temp_mak(void);␊ |
144 | static void scan_mak(FILE *, FILE *, char *);␊ |
145 | static void expunge_mak(register FILE *makin, register FILE *makout);␊ |
146 | static void skip_mak(register FILE *makin, register FILE *makout);␊ |
147 | static void finish_mak(FILE *, FILE *);␊ |
148 | ␊ |
149 | int main(int argc, register char **argv)␊ |
150 | {␊ |
151 | int size;␊ |
152 | ␊ |
153 | name = *argv;␊ |
154 | {␊ |
155 | register char *cp =name;␊ |
156 | while (*cp) if (*cp++ == '/') name = cp;␊ |
157 | }␊ |
158 | ␊ |
159 | for ( argv++ ; --argc ; argv++ )␊ |
160 | {␊ |
161 | ␊ |
162 | register char *token = *argv;␊ |
163 | if (*token++ != '-' || !*token)␊ |
164 | break;␊ |
165 | else␊ |
166 | {␊ |
167 | register int flag;␊ |
168 | for ( ; (flag = *token++) ; )␊ |
169 | {␊ |
170 | switch (flag)␊ |
171 | {␊ |
172 | case 'd':␊ |
173 | delete++;␊ |
174 | break;␊ |
175 | case 'f':␊ |
176 | force++;␊ |
177 | break;␊ |
178 | case 'u':␊ |
179 | update++;␊ |
180 | case 'm':␊ |
181 | makefile = *++argv;␊ |
182 | if (--argc < 0) goto usage;␊ |
183 | break;␊ |
184 | case 'o':␊ |
185 | outfile = *++argv;␊ |
186 | if (--argc < 0) goto usage;␊ |
187 | break;␊ |
188 | case 'v':␊ |
189 | verbose++;␊ |
190 | break;␊ |
191 | case 'x':␊ |
192 | expunge++;␊ |
193 | break;␊ |
194 | case 'D':␊ |
195 | for ( ; (flag = *token++) ; )␊ |
196 | switch (flag)␊ |
197 | {␊ |
198 | case 'c':␊ |
199 | D_contents++;␊ |
200 | break;␊ |
201 | case 'd':␊ |
202 | D_depend++;␊ |
203 | break;␊ |
204 | case 'm':␊ |
205 | D_make++;␊ |
206 | break;␊ |
207 | case 'o':␊ |
208 | D_open++;␊ |
209 | break;␊ |
210 | case 't':␊ |
211 | D_time++;␊ |
212 | break;␊ |
213 | case 'D':␊ |
214 | debug++;␊ |
215 | break;␊ |
216 | default:␊ |
217 | goto letters;␊ |
218 | ␊ |
219 | }␊ |
220 | goto newtoken;␊ |
221 | default:␊ |
222 | goto usage;␊ |
223 | }␊ |
224 | letters: ;␊ |
225 | }␊ |
226 | }␊ |
227 | newtoken: ;␊ |
228 | }␊ |
229 | ␊ |
230 | if (!expunge && argc < 1) goto usage;␊ |
231 | if ((int) outfile && (int) makefile) /* not both */␊ |
232 | goto usage;␊ |
233 | ␊ |
234 | if ((int) outfile)␊ |
235 | {␊ |
236 | /*␊ |
237 | * NeXT_MOD, For SGS stuff, in case still linked to master version␊ |
238 | */␊ |
239 | unlink(outfile);␊ |
240 | ␊ |
241 | if ((out = fopen(outfile, "w")) == NULL)␊ |
242 | {␊ |
243 | fprintf(stderr, "%s: outfile = \"%s\" ", name, outfile);␊ |
244 | perror("fopen");␊ |
245 | fflush(stdout), fflush(stderr);␊ |
246 | exit(1);␊ |
247 | }␊ |
248 | else if (D_open)␊ |
249 | printf("%s: opened outfile \"%s\"\n", name, outfile);␊ |
250 | }␊ |
251 | else if ((mak = find_mak(makefile)))␊ |
252 | {␊ |
253 | makout = temp_mak();␊ |
254 | out = makout;␊ |
255 | if (expunge)␊ |
256 | expunge_mak(mak, makout);␊ |
257 | else␊ |
258 | skip_mak(mak, makout);␊ |
259 | }␊ |
260 | else if (mak_eof && /* non existent file == mt file */␊ |
261 | (int)(makout = temp_mak()))␊ |
262 | { /* but we need to be able */␊ |
263 | out = makout; /* to write here */␊ |
264 | }␊ |
265 | else if (makefile)␊ |
266 | {␊ |
267 | fprintf(stderr, "%s: makefile \"%s\" can not be opened or stat'ed\n",␊ |
268 | name, makefile);␊ |
269 | exit(2);␊ |
270 | }␊ |
271 | ␊ |
272 | for (; argc--; argv++)␊ |
273 | {␊ |
274 | dep_file_index = 0;␊ |
275 | ␊ |
276 | if ((size = read_dep(*argv)))␊ |
277 | {␊ |
278 | ␊ |
279 | save_dot_o();␊ |
280 | if (D_depend) printf("%s: dot_o = \"%s\"\n", name, dot_o);␊ |
281 | ␊ |
282 | parse_dep();␊ |
283 | if (mak) scan_mak(mak, makout, dot_o);␊ |
284 | if (out) output_dep(out);␊ |
285 | ␊ |
286 | if (delete)␊ |
287 | unlink(*argv);␊ |
288 | }␊ |
289 | }␊ |
290 | ␊ |
291 | if (mak) finish_mak(mak, makout);␊ |
292 | rename(shadow_mak_name, real_mak_name);␊ |
293 | exit(0);␊ |
294 | usage:␊ |
295 | fprintf(stderr, "usage: md -f -Dcdmot -m makefile -o outputfile -v <file1> ... <filen>\n");␊ |
296 | exit(1);␊ |
297 | return 1;␊ |
298 | }␊ |
299 | ␊ |
300 | ␊ |
301 | static int read_dep(register char *file)␊ |
302 | {␊ |
303 | register int fd;␊ |
304 | register int size;␊ |
305 | struct stat statbuf;␊ |
306 | ␊ |
307 | if ((fd = open(file, 0)) < 0)␊ |
308 | {␊ |
309 | fprintf(stderr, "%s: file = \"%s\" ", name, file);␊ |
310 | perror("open");␊ |
311 | fflush(stdout), fflush(stderr);␊ |
312 | return 0;␊ |
313 | }␊ |
314 | if (D_open)␊ |
315 | printf("%s: opened dependency file \"%s\"\n", name, file);␊ |
316 | ␊ |
317 | if (fstat(fd, &statbuf) < 0)␊ |
318 | {␊ |
319 | fprintf(stderr, "%s: file = \"%s\" ", name, file);␊ |
320 | perror("stat");␊ |
321 | fflush(stdout), fflush(stderr);␊ |
322 | goto out;␊ |
323 | }␊ |
324 | switch(statbuf.st_mode & S_IFMT)␊ |
325 | {␊ |
326 | case S_IFREG:␊ |
327 | if (D_time)␊ |
328 | printf("%s: file time = %ld\n", name, statbuf.st_mtime);␊ |
329 | ␊ |
330 | if (statbuf.st_size > IObuffer)␊ |
331 | {␊ |
332 | fprintf(stderr, "%s: file \"%s\" tooo big for IObuffer\n",␊ |
333 | name, file);␊ |
334 | goto out;␊ |
335 | } else if (force)␊ |
336 | break;␊ |
337 | else if ((int) mak && statbuf.st_mtime < makstat.st_mtime)␊ |
338 | {␊ |
339 | if (verbose || D_time)␊ |
340 | fprintf(stderr, "%s: skipping \"%s\" %ld < %ld \"%s\"\n",␊ |
341 | name, file, statbuf.st_mtime, makstat.st_mtime,␊ |
342 | real_mak_name);␊ |
343 | goto out;␊ |
344 | } else /* >= =>ok */␊ |
345 | break;␊ |
346 | case S_IFDIR:␊ |
347 | case S_IFLNK:␊ |
348 | case S_IFCHR:␊ |
349 | case S_IFBLK:␊ |
350 | case S_IFSOCK:␊ |
351 | default:␊ |
352 | fprintf(stderr, "%s: bad mode: 0%o on \"%s\"\n",␊ |
353 | name, statbuf.st_mode, file);␊ |
354 | fflush(stdout), fflush(stderr);␊ |
355 | goto out;␊ |
356 | }␊ |
357 | ␊ |
358 | if ((size = read(fd, file_array, sizeof (file_array))) < 0)␊ |
359 | {␊ |
360 | fprintf(stderr, "%s: file = \"%s\" ", name, file);␊ |
361 | perror("read");␊ |
362 | fflush(stdout), fflush(stderr);␊ |
363 | goto out;␊ |
364 | }␊ |
365 | file_array[size] = 0;␊ |
366 | ␊ |
367 | if (close(fd) < 0)␊ |
368 | {␊ |
369 | fprintf(stderr, "%s: file = \"%s\" ", name, file);␊ |
370 | perror("close");␊ |
371 | fflush(stdout), fflush(stderr);␊ |
372 | return 0;␊ |
373 | }␊ |
374 | ␊ |
375 | if (D_depend && D_contents)␊ |
376 | printf("file_array: \"%s\"\n", file_array);␊ |
377 | return size;␊ |
378 | out: ;␊ |
379 | close(fd);␊ |
380 | return 0;␊ |
381 | }␊ |
382 | ␊ |
383 | static void save_dot_o(void)␊ |
384 | {␊ |
385 | register char *cp = file_array;␊ |
386 | register char *svp = dot_o;␊ |
387 | register int c;␊ |
388 | ␊ |
389 | while ((*svp++ = (c = *cp++)) && c != ':');␊ |
390 | *svp = 0;␊ |
391 | }␊ |
392 | ␊ |
393 | static void parse_dep(void)␊ |
394 | {␊ |
395 | register char *lp = file_array;␊ |
396 | register int c;␊ |
397 | ␊ |
398 | while (*lp)␊ |
399 | {␊ |
400 | register char *tlp = lp;␊ |
401 | register char *cp = dep_line;␊ |
402 | register int i = 0;␊ |
403 | int abspath = 0;␊ |
404 | char oldc;␊ |
405 | char *oldcp;␊ |
406 | ␊ |
407 | /* get a line to process */␊ |
408 | while ((c = *lp++) && c != '\n')␊ |
409 | {␊ |
410 | if (c == '\\')␊ |
411 | lp++; /* skip backslash newline */␊ |
412 | else␊ |
413 | *cp++ = c;␊ |
414 | }␊ |
415 | if (!c)␊ |
416 | break;␊ |
417 | *cp = 0;␊ |
418 | cp = dep_line;␊ |
419 | lp[-1] = 0;␊ |
420 | /* skip .o file name */␊ |
421 | while ((c = *cp++) && c != ':'); if (!c) continue;␊ |
422 | next_filename:␊ |
423 | i = 0;␊ |
424 | abspath = 0;␊ |
425 | while ((c = *cp) && (c == ' ' || c == '\t')) cp++; if (!c) continue;␊ |
426 | ␊ |
427 | /* canonicalization processing */␊ |
428 | ␊ |
429 | /* initial / is remembered */␊ |
430 | if (c == '/')␊ |
431 | abspath++;␊ |
432 | ␊ |
433 | while (c && c != ' ' && c != '\t')␊ |
434 | {␊ |
435 | if (D_depend) printf("i = %d going \"%s\"\n", i, cp);␊ |
436 | /* kill \'s */␊ |
437 | while ((c = *cp) && c == '/') cp++; if (!c) break;␊ |
438 | path_component[i] = cp;␊ |
439 | /* swallow chars till next / or null */␊ |
440 | while ((c = *cp++) && c != '/' && c != ' ' && c != '\t');␊ |
441 | if (c) cp[-1]=0;/* end component C style */␊ |
442 | ␊ |
443 | /* ignore . */;␊ |
444 | if (!strcmp(path_component[i], "."))␊ |
445 | ; /* if "component" != .. */␊ |
446 | else /* don't reduce /component/.. to nothing */␊ |
447 | i++; /* there could be symbolic links! */␊ |
448 | }␊ |
449 | /* reassemble components */␊ |
450 | oldc = c; /* save c */␊ |
451 | oldcp = cp; /* save cp */␊ |
452 | cp = tlp; /* overwrite line in buffer */␊ |
453 | if (abspath)␊ |
454 | *cp++ = '/';␊ |
455 | for (c=0; c<i; c++) {register char *ccp = path_component[c];␊ |
456 | while ((*cp++ = *ccp++));␊ |
457 | *--cp = '/';␊ |
458 | cp++;␊ |
459 | }␊ |
460 | *--cp = 0;␊ |
461 | ␊ |
462 | c=dep_file_index++;␊ |
463 | dep_files[c].str = tlp;␊ |
464 | dep_files[c].len = cp - tlp;␊ |
465 | if (D_depend)␊ |
466 | printf("%s: dep_file[%d] = \"%s\" Len %ld\n",␊ |
467 | name, dep_file_index - 1, tlp, (long)(cp - tlp));␊ |
468 | tlp = cp + 1;␊ |
469 | if (oldc)␊ |
470 | {␊ |
471 | cp = oldcp;␊ |
472 | goto next_filename;␊ |
473 | }␊ |
474 | }␊ |
475 | }␊ |
476 | ␊ |
477 | static void output_dep(FILE *out)␊ |
478 | {␊ |
479 | register int j;␊ |
480 | register int size = 1000;␊ |
481 | register int dot_o_len = strlen(dot_o);␊ |
482 | register struct dep *dp = dep_files;␊ |
483 | int written = 0;␊ |
484 | ␊ |
485 | if (D_depend && debug)␊ |
486 | for(j = 0; j < dep_file_index; j++)␊ |
487 | {␊ |
488 | printf("dep_files[%d] = %s\n", j, dep_files[j].str);␊ |
489 | }␊ |
490 | typedef int (*qsort_strcmp_fixer)(const void *, const void *);␊ |
491 | ␊ |
492 | int (*qsort_strcmp_fix)(const void *, const void *) = (qsort_strcmp_fixer)qsort_strcmp;␊ |
493 | ␊ |
494 | qsort(dep_files, dep_file_index, sizeof (struct dep), qsort_strcmp_fix);␊ |
495 | ␊ |
496 | if (D_depend && debug)␊ |
497 | for(j = 0; j < dep_file_index; j++)␊ |
498 | {␊ |
499 | printf("dep_files[%d] = %s\n", j, dep_files[j].str);␊ |
500 | }␊ |
501 | ␊ |
502 | fprintf(out, "%s %s", SALUTATION, dot_o);␊ |
503 | for(j = 0; j < dep_file_index; j++, dp++)␊ |
504 | {␊ |
505 | register int len = dp->len;␊ |
506 | register char *str = dp->str;␊ |
507 | if (j && len == (dp-1)->len && !strcmp(str, (dp-1)->str))␊ |
508 | continue;␊ |
509 | written++;␊ |
510 | if (size + len + 1 > OUTLINELEN)␊ |
511 | {␊ |
512 | fprintf(out, "\n%s %s", dot_o, str);␊ |
513 | size = dot_o_len + len + 1;␊ |
514 | }␊ |
515 | else␊ |
516 | {␊ |
517 | fprintf(out, " %s", str);␊ |
518 | size += len + 1;␊ |
519 | }␊ |
520 | }␊ |
521 | fprintf(out, "\n");␊ |
522 | if (verbose)␊ |
523 | fprintf(stdout, "%s: \"%s\" %d => %d\n", name, dot_o, dep_file_index, written);␊ |
524 | }␊ |
525 | ␊ |
526 | /* process makefile */␊ |
527 | static FILE *find_mak(char *file)␊ |
528 | {␊ |
529 | FILE *mak;␊ |
530 | ␊ |
531 | if ((int) file)␊ |
532 | {␊ |
533 | if ((mak = fopen(file, "r")) != NULL)␊ |
534 | {␊ |
535 | real_mak_name = file;␊ |
536 | }␊ |
537 | else if (update)␊ |
538 | {␊ |
539 | mak_eof = 1;␊ |
540 | real_mak_name = file;␊ |
541 | return NULL;␊ |
542 | }␊ |
543 | else␊ |
544 | {␊ |
545 | fprintf(stderr, "%s: file = \"%s\" ", name, file);␊ |
546 | perror("fopen");␊ |
547 | fflush(stdout), fflush(stderr);␊ |
548 | return NULL;␊ |
549 | }␊ |
550 | }␊ |
551 | else␊ |
552 | {␊ |
553 | if ((mak = fopen("makefile", "r")) != NULL)␊ |
554 | {␊ |
555 | real_mak_name = "makefile";␊ |
556 | }␊ |
557 | else if ((mak = fopen("Makefile", "r")) != NULL)␊ |
558 | {␊ |
559 | real_mak_name = "Makefile";␊ |
560 | }␊ |
561 | else return NULL;␊ |
562 | }␊ |
563 | ␊ |
564 | if (fstat(fileno(mak), &makstat) < 0)␊ |
565 | {␊ |
566 | fprintf(stderr, "%s: file = \"%s\" ", name, real_mak_name);␊ |
567 | perror("stat");␊ |
568 | fflush(stdout), fflush(stderr);␊ |
569 | return NULL;␊ |
570 | }␊ |
571 | if (D_open)␊ |
572 | printf("%s: opened makefile \"%s\"\n", name, real_mak_name);␊ |
573 | if (D_time)␊ |
574 | printf("%s: makefile time = %ld\n", name, makstat.st_mtime);␊ |
575 | ␊ |
576 | return mak;␊ |
577 | }␊ |
578 | ␊ |
579 | static FILE *temp_mak(void)␊ |
580 | {␊ |
581 | FILE *mak;␊ |
582 | ␊ |
583 | strlcpy(shadow_mak_name, real_mak_name, sizeof(shadow_mak_name));␊ |
584 | strlcat(shadow_mak_name, ".md", sizeof(shadow_mak_name));␊ |
585 | ␊ |
586 | /*␊ |
587 | * For SGS stuff, in case still linked to master version␊ |
588 | */␊ |
589 | unlink(shadow_mak_name);␊ |
590 | if ((mak = fopen(shadow_mak_name, "w")) == NULL)␊ |
591 | {␊ |
592 | fprintf(stderr, "%s: file = \"%s\" ", name, shadow_mak_name);␊ |
593 | perror("fopen");␊ |
594 | fflush(stdout), fflush(stderr);␊ |
595 | return NULL;␊ |
596 | }␊ |
597 | if (D_open)␊ |
598 | printf("%s: opened makefile.md \"%s\"\n", name, shadow_mak_name);␊ |
599 | ␊ |
600 | return mak;␊ |
601 | }␊ |
602 | ␊ |
603 | static void skip_mak(register FILE *makin, register FILE *makout)␊ |
604 | {␊ |
605 | register int len = SALUTATIONLEN;␊ |
606 | ␊ |
607 | if (D_make)␊ |
608 | printf("skipping in \"%s\" ", real_mak_name);␊ |
609 | ␊ |
610 | while (fgets(makbuf, LINESIZE, makin) != NULL)␊ |
611 | {␊ |
612 | if (D_make && D_contents)␊ |
613 | printf("%s: \"%s\"\n", real_mak_name, makbuf);␊ |
614 | if (strncmp(makbuf, SALUTATION, len))␊ |
615 | {␊ |
616 | fputs(makbuf, makout);␊ |
617 | }␊ |
618 | else␊ |
619 | break;␊ |
620 | }␊ |
621 | mak_eof = feof(makin);␊ |
622 | if (mak_eof)␊ |
623 | fclose(makin);␊ |
624 | if (D_make)␊ |
625 | printf("eof = %d str = \"%s\"", mak_eof, makbuf);␊ |
626 | }␊ |
627 | ␊ |
628 | static void expunge_mak(register FILE *makin, register FILE *makout)␊ |
629 | {␊ |
630 | register int len = SALUTATIONLEN;␊ |
631 | register int oldlen = OLDSALUTATIONLEN;␊ |
632 | ␊ |
633 | if (D_make)␊ |
634 | printf("expunging in \"%s\" ", real_mak_name);␊ |
635 | ␊ |
636 | while (fgets(makbuf, LINESIZE, makin) != NULL)␊ |
637 | {␊ |
638 | if (D_make && D_contents)␊ |
639 | printf("%s: \"%s\"\n", real_mak_name, makbuf);␊ |
640 | if (! strncmp(makbuf, SALUTATION, len) ||␊ |
641 | ! strncmp(makbuf, OLDSALUTATION, oldlen))␊ |
642 | break;␊ |
643 | else␊ |
644 | fputs(makbuf, makout);␊ |
645 | }␊ |
646 | mak_eof = 1;␊ |
647 | if (mak_eof)␊ |
648 | fclose(makin);␊ |
649 | if (D_make)␊ |
650 | printf("eof = %d str = \"%s\"", mak_eof, makbuf);␊ |
651 | }␊ |
652 | ␊ |
653 | static void␊ |
654 | scan_mak(FILE *makin, FILE *makout, char *file)␊ |
655 | {␊ |
656 | register char *cp = &makbuf[SALUTATIONLEN+1];␊ |
657 | register int len = strlen(file);␊ |
658 | register int ret;␊ |
659 | ␊ |
660 | if (D_make)␊ |
661 | printf("scanning in \"%s\" for \"%s\"\n", real_mak_name, file);␊ |
662 | ␊ |
663 | do {␊ |
664 | if (mak_eof) /* don't scan any more */␊ |
665 | return;␊ |
666 | ␊ |
667 | ret = strncmp(cp, file, len);␊ |
668 | if (D_make)␊ |
669 | printf("saw \"%s\" ret = %d\n", cp, ret);␊ |
670 | ␊ |
671 | if (ret < 0) { /* skip forward till match or greater */␊ |
672 | fputs(makbuf, makout); /* line we're looking at */␊ |
673 | while (fgets(makbuf, LINESIZE, makin) != NULL)␊ |
674 | {␊ |
675 | if (strncmp(makbuf, SALUTATION, SALUTATIONLEN))␊ |
676 | {␊ |
677 | fputs(makbuf, makout);␊ |
678 | }␊ |
679 | else␊ |
680 | break;␊ |
681 | }␊ |
682 | mak_eof = feof(makin);␊ |
683 | ␊ |
684 | if (mak_eof)␊ |
685 | fclose(makin);␊ |
686 | ␊ |
687 | continue;␊ |
688 | }␊ |
689 | else if (ret == 0)␊ |
690 | { /* flush match */␊ |
691 | while (fgets(makbuf, LINESIZE, makin) != NULL)␊ |
692 | {␊ |
693 | if (strncmp(makbuf, SALUTATION, SALUTATIONLEN))␊ |
694 | {␊ |
695 | ; /* flush old stuff */␊ |
696 | }␊ |
697 | else␊ |
698 | break;␊ |
699 | }␊ |
700 | mak_eof = feof(makin);␊ |
701 | if (mak_eof)␊ |
702 | fclose(makin);␊ |
703 | break;␊ |
704 | }␊ |
705 | else␊ |
706 | { /* no luck this time */␊ |
707 | break;␊ |
708 | }␊ |
709 | } while (1);␊ |
710 | }␊ |
711 | ␊ |
712 | static void␊ |
713 | finish_mak(FILE *makin, FILE *makout)␊ |
714 | {␊ |
715 | if (mak_eof) /* don't scan any more */␊ |
716 | return;␊ |
717 | ␊ |
718 | if (D_make)␊ |
719 | printf("finishing in \"%s\"\n", real_mak_name);␊ |
720 | ␊ |
721 | fputs(makbuf, makout); /* line we're looking at */␊ |
722 | while (fgets(makbuf, LINESIZE, makin) != NULL)␊ |
723 | {␊ |
724 | fputs(makbuf, makout);␊ |
725 | }␊ |
726 | }␊ |
727 | |