1 /* $XConsortium: main.c,v 1.84 94/11/30 16:10:44 kaleb Exp $ */
2 /* $XFree86: xc/config/makedepend/main.c,v 3.3 1995/01/28 15:41:03 dawes Exp $ */
5 Copyright (c) 1993, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
31 #pragma warning(disable : 4996)
45 #define sigvec sigvector
48 #ifdef X_POSIX_C_SOURCE
49 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
51 #undef _POSIX_C_SOURCE
53 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
62 #if NeedVarargsPrototypes
76 const char *directives[] = {
97 #include "imakemdep.h" /* from config sources */
100 struct inclist inc_list[ MAXFILES ], *inclistp = inc_list, maininclist;
102 char *filelist[ MAXFILES ];
103 char *includedirs[ MAXDIRS + 1 ];
104 char *excludedirs[ MAXDIRS + 1 ];
105 char *notdotdot[ MAXDIRS ];
106 char *objprefix = (char *)"";
107 char *objsuffix = (char *)".obj"; /* OBJSUFFIX; */
108 char *startat = (char *)"# DO NOT DELETE";
111 bool printed = false;
112 bool verbose = false;
113 bool show_where_not = false;
114 bool warn_multiple = false; /* Warn on multiple includes of same file */
117 #ifdef SIGNALRETURNSINT
125 fatalerr ((char *)"got signal %d\n", sig);
128 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__EMX__) || defined(__OS2__)
133 #ifndef _POSIX_SOURCE
134 #define sigaction sigvec
135 #define sa_handler sv_handler
136 #define sa_mask sv_mask
137 #define sa_flags sv_flags
139 struct sigaction sig_act;
142 /* fatty boombalatty, and wrong idea here.
144 // adds any subdirectories under dirname into the list of
145 // include directories, so we can get a whole hierarchies set of
147 void add_subdirs(char *dirname, char ** &incp)
149 directory dir(dirname);
150 string_array subdirs = dir.directories();
151 for (int i = 0; i < subdirs.length(); i++) {
152 istring curr = istring(dirname) + "/" + subdirs[i];
153 // add the current subdirectory.
154 if (incp >= includedirs + MAXDIRS)
155 fatalerr("Too many -I flags.\n");
156 *incp++ = strdup(curr.s());
157 printf((istring("added ") + curr + "\n").s());
158 add_subdirs(curr.s(), incp);
163 int main(int argc, char **argv)
165 register char **fp = filelist;
166 register char **incp = includedirs;
167 register char **excp = excludedirs;
169 register struct inclist *ip;
170 char *makefile = NULL;
171 struct filepointer *filecontent;
172 struct symtab *psymp = predefs;
173 char *endmarker = NULL;
174 char *defincdir = NULL;
176 ProgramName = argv[0];
178 while (psymp->s_name)
180 define2(psymp->s_name, psymp->s_value, &maininclist);
183 if (argc == 2 && argv[1][0] == '@') {
189 char quotechar = '\0';
192 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
193 fatalerr("cannot open \"%s\"\n", argv[1]+1);
195 args = (char *)malloc(ast.st_size + 2);
196 if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
197 fatalerr("failed to read %s\n", argv[1]+1);
198 args[ast.st_size] = '\n';
199 args[ast.st_size + 1] = '\0';
201 for (p = args; *p; p++) {
203 if (quotechar == '\\' ||
204 (*p == quotechar && p[-1] != '\\'))
217 if (p > args && p[-1])
224 nargv = (char **)malloc(nargc * sizeof(char *));
227 for (p = args; argc < nargc; p += strlen(p) + 1)
228 if (*p) nargv[argc++] = p;
231 for(argc--, argv++; argc; argc--, argv++) {
232 /* if looking for endmarker then check before parsing */
233 if (endmarker && strcmp (endmarker, *argv) == 0) {
238 /* treat +thing as an option for C++ */
239 if (endmarker && **argv == '+')
246 endmarker = &argv[0][2];
247 if (endmarker[0] == '\0') endmarker = (char *)"--";
250 if (argv[0][2] == '\0') {
254 for (p=argv[0] + 2; *p ; p++)
259 define(argv[0] + 2, &maininclist);
266 if (endmarker) break;
267 if (argv[0][2] == '\0') {
270 envinclude = getenv(argv[0]);
271 } else envinclude = getenv(argv[0]+2);
272 if (!envinclude) break;
273 prevdir = envinclude;
274 delim = (char*)strchr(envinclude, ';');
277 if (incp >= includedirs + MAXDIRS) fatalerr("Too many Include directories.\n");
282 delim = (char*)strchr(delim, ';');
287 //fprintf(stderr, "adding Xclude %s\n", argv[0]+2);
288 // add a directory to the exclusions list.
289 if (excp >= excludedirs + MAXDIRS)
290 fatalerr("Too many -X flags.\n");
292 if (**(excp-1) == '\0') {
293 // fix the prior entry, but don't incremement yet; we'll do that
294 // on the include list instead.
295 *(excp-1) = *(argv + 1);
297 if (incp >= includedirs + MAXDIRS)
298 fatalerr("Too many -I flags via -X.\n");
300 if (**(incp-1) == '\0') {
301 *(incp-1) = *(++argv);
306 if (incp >= includedirs + MAXDIRS)
307 fatalerr("Too many -I flags.\n");
309 if (**(incp-1) == '\0') {
310 *(incp-1) = *(++argv);
313 /// add_subdirs(*(incp-1), incp);
316 defincdir = argv[0]+2;
318 /* do not use if endmarker processing */
320 if (endmarker) break;
324 if (endmarker) break;
325 if (argv[0][2] == '\0') {
328 width = atoi(argv[0]);
330 width = atoi(argv[0]+2);
333 if (endmarker) break;
334 if (argv[0][2] == '\0') {
339 objsuffix = argv[0]+2;
342 if (endmarker) break;
343 if (argv[0][2] == '\0') {
348 objprefix = argv[0]+2;
351 if (endmarker) break;
355 _debugmask = atoi(argv[0]+2);
359 if (endmarker) break;
361 if (*startat == '\0') {
366 fatalerr("-s flag's value should start %s\n",
370 if (endmarker) break;
371 makefile = argv[0]+2;
372 if (*makefile == '\0') {
373 makefile = *(++argv);
378 warn_multiple = true;
381 /* Ignore -O, -g so we can just pass ${CFLAGS} to
388 if (endmarker) break;
389 /* fatalerr("unknown opt = %s\n", argv[0]); */
390 warning("ignoring option %s\n", argv[0]);
396 if (incp >= includedirs + MAXDIRS)
397 fatalerr("Too many -I flags.\n");
401 if (incp >= includedirs + MAXDIRS)
402 fatalerr("Too many -I flags.\n");
403 *incp++ = INCLUDEDIR;
406 if (incp >= includedirs + MAXDIRS)
407 fatalerr("Too many -I flags.\n");
408 *incp++ = POSTINCDIR;
410 } else if (*defincdir) {
411 if (incp >= includedirs + MAXDIRS)
412 fatalerr("Too many -I flags.\n");
416 redirect(startat, makefile);
422 /* should really reset SIGINT to SIG_IGN if it was. */
424 signal (SIGHUP, c_catch);
426 signal (SIGINT, c_catch);
428 signal (SIGQUIT, c_catch);
430 signal (SIGILL, c_catch);
432 signal (SIGBUS, c_catch);
434 signal (SIGSEGV, c_catch);
436 signal (SIGSYS, c_catch);
439 sig_act.sa_handler = c_catch;
441 sigemptyset(&sig_act.sa_mask);
442 sigaddset(&sig_act.sa_mask, SIGINT);
443 sigaddset(&sig_act.sa_mask, SIGQUIT);
445 sigaddset(&sig_act.sa_mask, SIGBUS);
447 sigaddset(&sig_act.sa_mask, SIGILL);
448 sigaddset(&sig_act.sa_mask, SIGSEGV);
449 sigaddset(&sig_act.sa_mask, SIGHUP);
450 sigaddset(&sig_act.sa_mask, SIGPIPE);
452 sigaddset(&sig_act.sa_mask, SIGSYS);
455 sig_act.sa_mask = ((1<<(SIGINT -1))
468 #endif /* _POSIX_SOURCE */
469 sig_act.sa_flags = 0;
470 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
471 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
472 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
473 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
475 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
477 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
479 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
484 * now peruse through the list of files.
486 for(fp=filelist; *fp; fp++) {
487 filecontent = getfile(*fp);
488 ip = newinclude(*fp, (char *)NULL);
490 find_includes(filecontent, ip, ip, 0, false);
491 freefile(filecontent);
492 recursive_pr_include(ip, ip->i_file, base_name(*fp));
501 struct filepointer *getfile(char *file)
504 struct filepointer *content;
507 content = (struct filepointer *)malloc(sizeof(struct filepointer));
508 content->f_name = strdup(file);
509 if ((fd = open(file, O_RDONLY)) < 0) {
510 warning("cannot open \"%s\"\n", file);
511 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
512 *content->f_p = '\0';
516 content->f_base = (char *)malloc(st.st_size+1);
517 if (content->f_base == NULL)
518 fatalerr("cannot allocate mem\n");
519 if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
520 fatalerr("failed to read %s\n", file);
522 content->f_len = st.st_size+1;
523 content->f_p = content->f_base;
524 content->f_end = content->f_base + st.st_size;
525 *content->f_end = '\0';
530 void freefile(struct filepointer *fp)
537 char *copy(register char *str)
539 register char *p = (char *)malloc(strlen(str) + 1);
545 int match(register const char *str, register const char **list)
549 for (i=0; *list; i++, list++)
550 if (strcmp(str, *list) == 0)
556 * Get the next line. We only return lines beginning with '#' since that
557 * is all this program is ever interested in.
559 char *getline(register struct filepointer *filep)
561 register char *p, /* walking pointer */
562 *eof, /* end of file pointer */
563 *bol; /* beginning of line pointer */
564 register int lineno; /* line number */
567 //// if (p >= eof) return NULL;
568 lineno = filep->f_line;
571 // p is always pointing at the "beginning of a line" when we start this loop.
572 // this means that we must start considering the stuff on that line as
573 // being a useful thing to look at.
574 for (p = filep->f_p; p < eof; p++) {
575 if (bol > p) fatalerr("somehow bol got ahead of p.");
576 if (*p == '/' && *(p+1) == '*') {
577 /* consume C-style comments */
578 *p++ = ' '; *p++ = ' '; // skip the two we've already seen.
580 if (*p == '*' && *(p+1) == '/') {
581 *p++ = ' '; *p = ' ';
582 // skip one of these last two, let the loop skip the next.
584 } else if (*p == '\n') lineno++;
585 p++; // skip the current character.
588 } else if (*p == '/' && *(p+1) == '/') {
589 /* consume C++-style comments */
590 *p++ = ' '; *p++ = ' '; // skip the comment characters.
591 while (p < eof && (*p != '\n') ) *p++ = ' ';
592 // we scan until we get to the end of line.
593 ///no count, since we'll see it again. lineno++;
594 p--; // skip back to just before \n.
595 continue; // let the loop skip past the eol that we saw.
596 } else if (*p == '\\') {
597 // handle an escape character.
598 if (*(p+1) == '\n') {
599 // we modify the stream so we consider the line correctly.
604 } else if (*p == '\n') {
605 // we've finally reached the end of the line.
607 *p = '\0'; // set the end of line to be a end of string now.
609 // it's not at the same position as the end of line, so it's worth
611 while ( (bol < p) && ((*bol == ' ') || (*bol == '\t')) ) bol++;
612 ////fprintf(stderr, "%s: %s\n", filep->f_name, bol);
616 /* punt lines with just # (yacc generated) */
617 for (cp = bol+1; *cp && (*cp == ' ' || *cp == '\t'); cp++) {}
618 if (*cp) { p++; goto done; }
621 // this is a failure now. we reset the beginning of line.
625 if (*bol != '#') bol = NULL;
628 filep->f_line = lineno;
633 * Strip the file name down to what we want to see in the Makefile.
634 * It will have objprefix and objsuffix around it.
636 char *base_name(register char *file)
641 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
648 #if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__EMX__)
649 int rename(char *from, char *to)
652 if (link (from, to) == 0) {
661 void redirect(char *line, char *makefile)
665 char backup[ BUFSIZ ],
671 * if makefile is "-" then let it pour onto stdout.
673 if (makefile && *makefile == '-' && *(makefile+1) == '\0')
677 * use a default makefile is not specified.
680 if (stat("Makefile", &st) == 0)
681 makefile = (char *)"Makefile";
682 else if (stat("makefile", &st) == 0)
683 makefile = (char *)"makefile";
685 fatalerr("[mM]akefile is not present\n");
689 if ((fdin = fopen(makefile, "r")) == NULL)
690 fatalerr("cannot open \"%s\"\n", makefile);
691 sprintf(backup, "%s.bak", makefile);
693 #if defined(WIN32) || defined(__EMX__) || defined(__OS2__)
696 if (rename(makefile, backup) < 0)
697 fatalerr("cannot rename %s to %s\n", makefile, backup);
698 #if defined(WIN32) || defined(__EMX__) || defined(__OS2__)
699 if ((fdin = fopen(backup, "r")) == NULL)
700 fatalerr("cannot open \"%s\"\n", backup);
702 if ((fdout = freopen(makefile, "w", stdout)) == NULL)
703 fatalerr("cannot open \"%s\"\n", backup);
704 len = int(strlen(line));
705 while (!found && fgets(buf, BUFSIZ, fdin)) {
706 if (*buf == '#' && strncmp(line, buf, len) == 0)
712 warning("Adding new delimiting line \"%s\" and dependencies...\n",
714 puts(line); /* same as fputs(fdout); but with newline */
716 while (fgets(buf, BUFSIZ, fdin)) {
721 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
722 chmod(makefile, st.st_mode);
724 fchmod(fileno(fdout), st.st_mode);
728 #if NeedVarargsPrototypes
729 void fatalerr(const char *msg, ...)
732 void fatalerr(char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
735 #if NeedVarargsPrototypes
738 fprintf(stderr, "%s: error: ", ProgramName);
739 #if NeedVarargsPrototypes
741 vfprintf(stderr, msg, args);
744 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
749 #if NeedVarargsPrototypes
750 void warning(const char *msg, ...)
753 void warning(const char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
756 #if NeedVarargsPrototypes
759 fprintf(stderr, "%s: warning: ", ProgramName);
760 #if NeedVarargsPrototypes
762 vfprintf(stderr, msg, args);
765 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
769 #if NeedVarargsPrototypes
770 void warning1(const char *msg, ...)
773 void warning1(const char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
776 #if NeedVarargsPrototypes
779 vfprintf(stderr, msg, args);
782 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);