forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / development / build / makedepend / main.c
blobac16e8155e27456ba24679f6f4c710d4082945be
1 /* $Xorg: main.c,v 1.3 2000/08/17 19:41:51 cpqbld Exp $ */
2 /*
4 Copyright (c) 1993, 1994, 1998 The Open Group
6 All Rights Reserved.
8 The above copyright notice and this permission notice shall be included in
9 all copies or substantial portions of the Software.
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 Except as contained in this notice, the name of The Open Group shall not be
19 used in advertising or otherwise to promote the sale, use or other dealings
20 in this Software without prior written authorization from The Open Group.
23 /* $XFree86: xc/config/makedepend/main.c,v 3.22 2001/07/25 15:04:40 dawes Exp $ */
25 #include "def.h"
26 #ifdef hpux
27 #define sigvec sigvector
28 #endif /* hpux */
30 #ifdef X_POSIX_C_SOURCE
31 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
32 #include <signal.h>
33 #undef _POSIX_C_SOURCE
34 #else
35 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
36 #include <signal.h>
37 #else
38 #define _POSIX_SOURCE
39 #include <signal.h>
40 #undef _POSIX_SOURCE
41 #endif
42 #endif
44 #include <stdarg.h>
46 #ifdef MINIX
47 #define USE_CHMOD 1
48 #endif
50 #ifdef DEBUG
51 int _debugmask;
52 #endif
54 char *ProgramName;
56 char *directives[] = {
57 "if",
58 "ifdef",
59 "ifndef",
60 "else",
61 "endif",
62 "define",
63 "undef",
64 "include",
65 "line",
66 "pragma",
67 "error",
68 "ident",
69 "sccs",
70 "elif",
71 "eject",
72 "warning",
73 "include_next",
74 NULL
77 #define MAKEDEPEND
78 #include "imakemdep.h" /* from config sources */
79 #undef MAKEDEPEND
81 struct inclist inclist[ MAXFILES ],
82 *inclistp = inclist,
83 *inclistnext = inclist,
84 maininclist;
86 char *filelist[ MAXFILES ];
87 char *includedirs[ MAXDIRS + 1 ],
88 **includedirsnext = includedirs;
89 char *notdotdot[ MAXDIRS ];
90 char *objprefix = "";
91 char *objsuffix = OBJSUFFIX;
92 char *startat = "# DO NOT DELETE";
93 int width = 78;
94 boolean append = FALSE;
95 boolean printed = FALSE;
96 boolean verbose = FALSE;
97 boolean show_where_not = FALSE;
98 boolean warn_multiple = FALSE; /* Warn on multiple includes of same file */
100 static void redirect(char *line, char *makefile);
102 static
103 #ifdef SIGNALRETURNSINT
105 #else
106 void
107 #endif
108 catch (int sig)
110 fflush (stdout);
111 fatalerr ("got signal %d\n", sig);
114 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__EMX__) || defined(Lynx_22) || defined(__CYGWIN__)
115 #define USGISH
116 #endif
118 #ifndef USGISH
119 #ifdef X_NOT_POSIX
120 #define sigaction sigvec
121 #define sa_handler sv_handler
122 #define sa_mask sv_mask
123 #define sa_flags sv_flags
124 #endif
125 struct sigaction sig_act;
126 #endif /* USGISH */
129 main(int argc, char *argv[])
131 char **fp = filelist;
132 char **incp = includedirs;
133 char *p;
134 struct inclist *ip;
135 char *makefile = NULL;
136 struct filepointer *filecontent;
137 struct symtab *psymp = predefs;
138 char *endmarker = NULL;
139 char *defincdir = NULL;
140 char **undeflist = NULL;
141 int numundefs = 0, i;
143 ProgramName = argv[0];
145 while (psymp->s_name)
147 define2(psymp->s_name, psymp->s_value, &maininclist);
148 psymp++;
150 if (argc == 2 && argv[1][0] == '@') {
151 struct stat ast;
152 int afd;
153 char *args;
154 char **nargv;
155 int nargc;
156 char quotechar = '\0';
158 nargc = 1;
159 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
160 fatalerr("cannot open \"%s\"\n", argv[1]+1);
161 fstat(afd, &ast);
162 args = (char *)malloc(ast.st_size + 1);
163 if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
164 fatalerr("failed to read %s\n", argv[1]+1);
165 args[ast.st_size] = '\0';
166 close(afd);
167 for (p = args; *p; p++) {
168 if (quotechar) {
169 if (quotechar == '\\' ||
170 (*p == quotechar && p[-1] != '\\'))
171 quotechar = '\0';
172 continue;
174 switch (*p) {
175 case '\\':
176 case '"':
177 case '\'':
178 quotechar = *p;
179 break;
180 case ' ':
181 case '\n':
182 *p = '\0';
183 if (p > args && p[-1])
184 nargc++;
185 break;
188 if (p[-1])
189 nargc++;
190 nargv = (char **)malloc(nargc * sizeof(char *));
191 nargv[0] = argv[0];
192 argc = 1;
193 for (p = args; argc < nargc; p += strlen(p) + 1)
194 if (*p) nargv[argc++] = p;
195 argv = nargv;
197 for(argc--, argv++; argc; argc--, argv++) {
198 /* if looking for endmarker then check before parsing */
199 if (endmarker && strcmp (endmarker, *argv) == 0) {
200 endmarker = NULL;
201 continue;
203 if (**argv != '-') {
204 /* treat +thing as an option for C++ */
205 if (endmarker && **argv == '+')
206 continue;
207 *fp++ = argv[0];
208 continue;
210 switch(argv[0][1]) {
211 case '-':
212 endmarker = &argv[0][2];
213 if (endmarker[0] == '\0') endmarker = "--";
214 break;
215 case 'D':
216 if (argv[0][2] == '\0') {
217 argv++;
218 argc--;
220 for (p=argv[0] + 2; *p ; p++)
221 if (*p == '=') {
222 *p = ' ';
223 break;
225 define(argv[0] + 2, &maininclist);
226 break;
227 case 'I':
228 if (incp >= includedirs + MAXDIRS)
229 fatalerr("Too many -I flags.\n");
230 *incp++ = argv[0]+2;
231 if (**(incp-1) == '\0') {
232 *(incp-1) = *(++argv);
233 argc--;
235 break;
236 case 'U':
237 /* Undef's override all -D's so save them up */
238 numundefs++;
239 if (numundefs == 1)
240 undeflist = malloc(sizeof(char *));
241 else
242 undeflist = realloc(undeflist,
243 numundefs * sizeof(char *));
244 if (argv[0][2] == '\0') {
245 argv++;
246 argc--;
248 undeflist[numundefs - 1] = argv[0] + 2;
249 break;
250 case 'Y':
251 defincdir = argv[0]+2;
252 break;
253 /* do not use if endmarker processing */
254 case 'a':
255 if (endmarker) break;
256 append = TRUE;
257 break;
258 case 'w':
259 if (endmarker) break;
260 if (argv[0][2] == '\0') {
261 argv++;
262 argc--;
263 width = atoi(argv[0]);
264 } else
265 width = atoi(argv[0]+2);
266 break;
267 case 'o':
268 if (endmarker) break;
269 if (argv[0][2] == '\0') {
270 argv++;
271 argc--;
272 objsuffix = argv[0];
273 } else
274 objsuffix = argv[0]+2;
275 break;
276 case 'p':
277 if (endmarker) break;
278 if (argv[0][2] == '\0') {
279 argv++;
280 argc--;
281 objprefix = argv[0];
282 } else
283 objprefix = argv[0]+2;
284 break;
285 case 'v':
286 if (endmarker) break;
287 verbose = TRUE;
288 #ifdef DEBUG
289 if (argv[0][2])
290 _debugmask = atoi(argv[0]+2);
291 #endif
292 break;
293 case 's':
294 if (endmarker) break;
295 startat = argv[0]+2;
296 if (*startat == '\0') {
297 startat = *(++argv);
298 argc--;
300 if (*startat != '#')
301 fatalerr("-s flag's value should start %s\n",
302 "with '#'.");
303 break;
304 case 'f':
305 if (endmarker) break;
306 makefile = argv[0]+2;
307 if (*makefile == '\0') {
308 makefile = *(++argv);
309 argc--;
311 break;
313 case 'm':
314 warn_multiple = TRUE;
315 break;
317 /* Ignore -O, -g so we can just pass ${CFLAGS} to
318 makedepend
320 case 'O':
321 case 'g':
322 break;
323 default:
324 if (endmarker) break;
325 /* fatalerr("unknown opt = %s\n", argv[0]); */
326 warning("ignoring option %s\n", argv[0]);
329 /* Now do the undefs from the command line */
330 for (i = 0; i < numundefs; i++)
331 undefine(undeflist[i], &maininclist);
332 if (numundefs > 0)
333 free(undeflist);
335 if (!defincdir) {
336 #ifdef PREINCDIR
337 if (incp >= includedirs + MAXDIRS)
338 fatalerr("Too many -I flags.\n");
339 *incp++ = PREINCDIR;
340 #endif
341 #ifdef __EMX__
343 char *emxinc = getenv("C_INCLUDE_PATH");
344 /* can have more than one component */
345 if (emxinc) {
346 char *beg, *end;
347 beg= (char*)strdup(emxinc);
348 for (;;) {
349 end = (char*)strchr(beg,';');
350 if (end) *end = 0;
351 if (incp >= includedirs + MAXDIRS)
352 fatalerr("Too many include dirs\n");
353 *incp++ = beg;
354 if (!end) break;
355 beg = end+1;
359 #else /* !__EMX__, does not use INCLUDEDIR at all */
360 if (incp >= includedirs + MAXDIRS)
361 fatalerr("Too many -I flags.\n");
362 *incp++ = INCLUDEDIR;
363 #endif
365 #ifdef EXTRAINCDIR
366 if (incp >= includedirs + MAXDIRS)
367 fatalerr("Too many -I flags.\n");
368 *incp++ = EXTRAINCDIR;
369 #endif
371 #ifdef POSTINCDIR
372 if (incp >= includedirs + MAXDIRS)
373 fatalerr("Too many -I flags.\n");
374 *incp++ = POSTINCDIR;
375 #endif
376 } else if (*defincdir) {
377 if (incp >= includedirs + MAXDIRS)
378 fatalerr("Too many -I flags.\n");
379 *incp++ = defincdir;
382 redirect(startat, makefile);
385 * catch signals.
387 #ifdef USGISH
388 /* should really reset SIGINT to SIG_IGN if it was. */
389 #ifdef SIGHUP
390 signal (SIGHUP, catch);
391 #endif
392 signal (SIGINT, catch);
393 #ifdef SIGQUIT
394 signal (SIGQUIT, catch);
395 #endif
396 signal (SIGILL, catch);
397 #ifdef SIGBUS
398 signal (SIGBUS, catch);
399 #endif
400 signal (SIGSEGV, catch);
401 #ifdef SIGSYS
402 signal (SIGSYS, catch);
403 #endif
404 #else
405 sig_act.sa_handler = catch;
406 #if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
407 sigemptyset(&sig_act.sa_mask);
408 sigaddset(&sig_act.sa_mask, SIGINT);
409 sigaddset(&sig_act.sa_mask, SIGQUIT);
410 #ifdef SIGBUS
411 sigaddset(&sig_act.sa_mask, SIGBUS);
412 #endif
413 sigaddset(&sig_act.sa_mask, SIGILL);
414 sigaddset(&sig_act.sa_mask, SIGSEGV);
415 sigaddset(&sig_act.sa_mask, SIGHUP);
416 sigaddset(&sig_act.sa_mask, SIGPIPE);
417 #ifdef SIGSYS
418 sigaddset(&sig_act.sa_mask, SIGSYS);
419 #endif
420 #else
421 sig_act.sa_mask = ((1<<(SIGINT -1))
422 |(1<<(SIGQUIT-1))
423 #ifdef SIGBUS
424 |(1<<(SIGBUS-1))
425 #endif
426 |(1<<(SIGILL-1))
427 |(1<<(SIGSEGV-1))
428 |(1<<(SIGHUP-1))
429 |(1<<(SIGPIPE-1))
430 #ifdef SIGSYS
431 |(1<<(SIGSYS-1))
432 #endif
434 #endif /* _POSIX_SOURCE */
435 sig_act.sa_flags = 0;
436 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
437 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
438 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
439 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
440 #ifdef SIGBUS
441 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
442 #endif
443 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
444 #ifdef SIGSYS
445 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
446 #endif
447 #endif /* USGISH */
450 * now peruse through the list of files.
452 for(fp=filelist; *fp; fp++) {
453 filecontent = getfile(*fp);
454 ip = newinclude(*fp, (char *)NULL);
456 find_includes(filecontent, ip, ip, 0, FALSE);
457 freefile(filecontent);
458 recursive_pr_include(ip, ip->i_file, base_name(*fp));
459 inc_clean();
461 if (printed)
462 printf("\n");
463 return 0;
466 #ifdef __EMX__
468 * eliminate \r chars from file
470 static int
471 elim_cr(char *buf, int sz)
473 int i,wp;
474 for (i= wp = 0; i<sz; i++) {
475 if (buf[i] != '\r')
476 buf[wp++] = buf[i];
478 return wp;
480 #endif
482 struct filepointer *
483 getfile(char *file)
485 int fd;
486 struct filepointer *content;
487 struct stat st;
489 content = (struct filepointer *)malloc(sizeof(struct filepointer));
490 if ((fd = open(file, O_RDONLY)) < 0) {
491 warning("cannot open \"%s\"\n", file);
492 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
493 *content->f_p = '\0';
494 return(content);
496 fstat(fd, &st);
497 content->f_base = (char *)malloc(st.st_size+1);
498 if (content->f_base == NULL)
499 fatalerr("cannot allocate mem\n");
500 if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
501 fatalerr("failed to read %s\n", file);
502 #ifdef __EMX__
503 st.st_size = elim_cr(content->f_base,st.st_size);
504 #endif
505 close(fd);
506 content->f_len = st.st_size+1;
507 content->f_p = content->f_base;
508 content->f_end = content->f_base + st.st_size;
509 *content->f_end = '\0';
510 content->f_line = 0;
511 return(content);
514 void
515 freefile(struct filepointer *fp)
517 free(fp->f_base);
518 free(fp);
521 char *copy(char *str)
523 char *p = (char *)malloc(strlen(str) + 1);
525 strcpy(p, str);
526 return(p);
530 match(char *str, char **list)
532 int i;
534 for (i=0; *list; i++, list++)
535 if (strcmp(str, *list) == 0)
536 return(i);
537 return(-1);
541 * Get the next line. We only return lines beginning with '#' since that
542 * is all this program is ever interested in.
544 char *getnextline(struct filepointer *filep)
546 char *p, /* walking pointer */
547 *eof, /* end of file pointer */
548 *bol; /* beginning of line pointer */
549 int lineno; /* line number */
551 p = filep->f_p;
552 eof = filep->f_end;
553 if (p >= eof)
554 return((char *)NULL);
555 lineno = filep->f_line;
557 for(bol = p--; ++p < eof; ) {
558 if (*p == '/' && *(p+1) == '*') { /* consume comments */
559 *p++ = ' ', *p++ = ' ';
560 while (*p) {
561 if (*p == '*' && *(p+1) == '/') {
562 *p++ = ' ', *p = ' ';
563 break;
565 else if (*p == '\n')
566 lineno++;
567 *p++ = ' ';
569 continue;
571 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
572 *p++ = ' ', *p++ = ' ';
573 while (*p && *p != '\n')
574 *p++ = ' ';
575 if (*p == '\n') --p;
576 continue;
578 else if (*p == '\\') {
579 if (*(p+1) == '\n') {
580 *p = ' ';
581 *(p+1) = ' ';
582 lineno++;
585 else if (*p == '\n') {
586 lineno++;
587 if (*bol == '#') {
588 char *cp;
590 *p++ = '\0';
591 /* punt lines with just # (yacc generated) */
592 for (cp = bol+1;
593 *cp && (*cp == ' ' || *cp == '\t'); cp++);
594 if (*cp) goto done;
595 --p;
597 bol = p+1;
600 if (*bol != '#')
601 bol = NULL;
602 done:
603 filep->f_p = p;
604 filep->f_line = lineno;
605 return(bol);
609 * Strip the file name down to what we want to see in the Makefile.
610 * It will have objprefix and objsuffix around it.
612 char *base_name(char *file)
614 char *p;
616 file = copy(file);
617 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
619 if (*p == '.')
620 *p = '\0';
621 return(file);
624 #if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__EMX__) && !defined(clipper) && !defined(__clipper__)
625 int rename (char *from, char *to)
627 (void) unlink (to);
628 if (link (from, to) == 0) {
629 unlink (from);
630 return 0;
631 } else {
632 return -1;
635 #endif /* USGISH */
637 void
638 redirect(char *line, char *makefile)
640 struct stat st;
641 FILE *fdin, *fdout;
642 char backup[ BUFSIZ ],
643 buf[ BUFSIZ ];
644 boolean found = FALSE;
645 int len;
648 * if makefile is "-" then let it pour onto stdout.
650 if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
651 puts(line);
652 return;
656 * use a default makefile is not specified.
658 if (!makefile) {
659 if (stat("Makefile", &st) == 0)
660 makefile = "Makefile";
661 else if (stat("makefile", &st) == 0)
662 makefile = "makefile";
663 else
664 fatalerr("[mM]akefile is not present\n");
666 else
667 stat(makefile, &st);
668 if ((fdin = fopen(makefile, "r")) == NULL)
669 fatalerr("cannot open \"%s\"\n", makefile);
670 sprintf(backup, "%s.bak", makefile);
671 unlink(backup);
672 #if defined(WIN32) || defined(__EMX__) || defined(__CYGWIN__)
673 fclose(fdin);
674 #endif
675 if (rename(makefile, backup) < 0)
676 fatalerr("cannot rename %s to %s\n", makefile, backup);
677 #if defined(WIN32) || defined(__EMX__) || defined(__CYGWIN__)
678 if ((fdin = fopen(backup, "r")) == NULL)
679 fatalerr("cannot open \"%s\"\n", backup);
680 #endif
681 if ((fdout = freopen(makefile, "w", stdout)) == NULL)
682 fatalerr("cannot open \"%s\"\n", backup);
683 len = strlen(line);
684 while (!found && fgets(buf, BUFSIZ, fdin)) {
685 if (*buf == '#' && strncmp(line, buf, len) == 0)
686 found = TRUE;
687 fputs(buf, fdout);
689 if (!found) {
690 if (verbose)
691 warning("Adding new delimiting line \"%s\" and dependencies...\n",
692 line);
693 puts(line); /* same as fputs(fdout); but with newline */
694 } else if (append) {
695 while (fgets(buf, BUFSIZ, fdin)) {
696 fputs(buf, fdout);
699 fflush(fdout);
700 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
701 chmod(makefile, st.st_mode);
702 #else
703 fchmod(fileno(fdout), st.st_mode);
704 #endif /* USGISH */
707 void
708 fatalerr(char *msg, ...)
710 va_list args;
711 fprintf(stderr, "%s: error: ", ProgramName);
712 va_start(args, msg);
713 vfprintf(stderr, msg, args);
714 va_end(args);
715 exit (1);
718 void
719 warning(char *msg, ...)
721 va_list args;
722 fprintf(stderr, "%s: warning: ", ProgramName);
723 va_start(args, msg);
724 vfprintf(stderr, msg, args);
725 va_end(args);
728 void
729 warning1(char *msg, ...)
731 va_list args;
732 va_start(args, msg);
733 vfprintf(stderr, msg, args);
734 va_end(args);