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 // turns the cygwin name format into a usable windos filename.
143 char *translate_cygwin(char *fname)
145 if (!strncmp(fname, "/cygdrive/", 10)) {
146 int oldlen = strlen(fname);
147 char *newprefix = (char *)malloc(oldlen); // at least long enough.
148 newprefix[0] = fname[10];
151 strncat(newprefix, fname + 11, oldlen - 11 + 1); // one extra for null char.
152 printf("translate cygwin: new filename is %s\n", newprefix);
153 return newprefix; // ignoring mem leak here. cannot be helped for quicky fix.
157 /* fatty boombalatty, and wrong idea here.
159 // adds any subdirectories under dirname into the list of
160 // include directories, so we can get a whole hierarchies set of
162 void add_subdirs(char *dirname, char ** &incp)
164 directory dir(dirname);
165 string_array subdirs = dir.directories();
166 for (int i = 0; i < subdirs.length(); i++) {
167 istring curr = istring(dirname) + "/" + subdirs[i];
168 // add the current subdirectory.
169 if (incp >= includedirs + MAXDIRS)
170 fatalerr("Too many -I flags.\n");
171 *incp++ = strdup(curr.s());
172 printf((istring("added ") + curr + "\n").s());
173 add_subdirs(curr.s(), incp);
178 int main(int argc, char **argv)
180 register char **fp = filelist;
181 register char **incp = includedirs;
182 register char **excp = excludedirs;
184 register struct inclist *ip;
185 char *makefile = NULL;
186 struct filepointer *filecontent;
187 struct symtab *psymp = predefs;
188 char *endmarker = NULL;
189 char *defincdir = NULL;
191 ProgramName = argv[0];
193 while (psymp->s_name)
195 define2(psymp->s_name, psymp->s_value, &maininclist);
198 if (argc == 2 && argv[1][0] == '@') {
204 char quotechar = '\0';
207 if ((afd = open(translate_cygwin(argv[1]+1), O_RDONLY)) < 0)
208 fatalerr("cannot open \"%s\"\n", translate_cygwin(argv[1]+1));
210 args = (char *)malloc(ast.st_size + 2);
211 if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
212 fatalerr("failed to read %s\n", argv[1]+1);
213 args[ast.st_size] = '\n';
214 args[ast.st_size + 1] = '\0';
216 for (p = args; *p; p++) {
218 if (quotechar == '\\' ||
219 (*p == quotechar && p[-1] != '\\'))
232 if (p > args && p[-1])
239 nargv = (char **)malloc(nargc * sizeof(char *));
242 for (p = args; argc < nargc; p += strlen(p) + 1)
243 if (*p) nargv[argc++] = p;
246 for(argc--, argv++; argc; argc--, argv++) {
247 /* if looking for endmarker then check before parsing */
248 if (endmarker && strcmp (endmarker, *argv) == 0) {
253 /* treat +thing as an option for C++ */
254 if (endmarker && **argv == '+')
261 endmarker = &argv[0][2];
262 if (endmarker[0] == '\0') endmarker = (char *)"--";
265 if (argv[0][2] == '\0') {
269 for (p=argv[0] + 2; *p ; p++)
274 define(argv[0] + 2, &maininclist);
281 if (endmarker) break;
282 if (argv[0][2] == '\0') {
285 envinclude = getenv(argv[0]);
286 } else envinclude = getenv(argv[0]+2);
287 if (!envinclude) break;
288 prevdir = envinclude;
289 delim = (char*)strchr(envinclude, ';');
292 if (incp >= includedirs + MAXDIRS) fatalerr("Too many Include directories.\n");
297 delim = (char*)strchr(delim, ';');
302 //fprintf(stderr, "adding Xclude %s\n", argv[0]+2);
303 // add a directory to the exclusions list.
304 if (excp >= excludedirs + MAXDIRS)
305 fatalerr("Too many -X flags.\n");
307 if (**(excp-1) == '\0') {
308 // fix the prior entry, but don't incremement yet; we'll do that
309 // on the include list instead.
310 *(excp-1) = *(argv + 1);
312 if (incp >= includedirs + MAXDIRS)
313 fatalerr("Too many -I flags via -X.\n");
315 if (**(incp-1) == '\0') {
316 *(incp-1) = *(++argv);
321 if (incp >= includedirs + MAXDIRS)
322 fatalerr("Too many -I flags.\n");
324 if (**(incp-1) == '\0') {
325 *(incp-1) = *(++argv);
328 /// add_subdirs(*(incp-1), incp);
331 defincdir = argv[0]+2;
333 /* do not use if endmarker processing */
335 if (endmarker) break;
339 if (endmarker) break;
340 if (argv[0][2] == '\0') {
343 width = atoi(argv[0]);
345 width = atoi(argv[0]+2);
348 if (endmarker) break;
349 if (argv[0][2] == '\0') {
354 objsuffix = argv[0]+2;
357 if (endmarker) break;
358 if (argv[0][2] == '\0') {
363 objprefix = argv[0]+2;
364 objprefix = translate_cygwin(objprefix);
367 if (endmarker) break;
371 _debugmask = atoi(argv[0]+2);
375 if (endmarker) break;
377 if (*startat == '\0') {
382 fatalerr("-s flag's value should start %s\n",
386 if (endmarker) break;
387 makefile = argv[0]+2;
388 if (*makefile == '\0') {
389 makefile = *(++argv);
394 warn_multiple = true;
397 /* Ignore -O, -g so we can just pass ${CFLAGS} to
404 if (endmarker) break;
405 /* fatalerr("unknown opt = %s\n", argv[0]); */
406 warning("ignoring option %s\n", argv[0]);
413 if (incp >= includedirs + MAXDIRS)
414 fatalerr("Too many -I flags.\n");
418 if (incp >= includedirs + MAXDIRS)
419 fatalerr("Too many -I flags.\n");
420 *incp++ = INCLUDEDIR;
423 if (incp >= includedirs + MAXDIRS)
424 fatalerr("Too many -I flags.\n");
425 *incp++ = POSTINCDIR;
427 } else if (*defincdir) {
428 if (incp >= includedirs + MAXDIRS)
429 fatalerr("Too many -I flags.\n");
433 redirect(startat, makefile);
439 /* should really reset SIGINT to SIG_IGN if it was. */
441 signal (SIGHUP, c_catch);
443 signal (SIGINT, c_catch);
445 signal (SIGQUIT, c_catch);
447 signal (SIGILL, c_catch);
449 signal (SIGBUS, c_catch);
451 signal (SIGSEGV, c_catch);
453 signal (SIGSYS, c_catch);
456 sig_act.sa_handler = c_catch;
458 sigemptyset(&sig_act.sa_mask);
459 sigaddset(&sig_act.sa_mask, SIGINT);
460 sigaddset(&sig_act.sa_mask, SIGQUIT);
462 sigaddset(&sig_act.sa_mask, SIGBUS);
464 sigaddset(&sig_act.sa_mask, SIGILL);
465 sigaddset(&sig_act.sa_mask, SIGSEGV);
466 sigaddset(&sig_act.sa_mask, SIGHUP);
467 sigaddset(&sig_act.sa_mask, SIGPIPE);
469 sigaddset(&sig_act.sa_mask, SIGSYS);
472 sig_act.sa_mask = ((1<<(SIGINT -1))
485 #endif /* _POSIX_SOURCE */
486 sig_act.sa_flags = 0;
487 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
488 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
489 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
490 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
492 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
494 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
496 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
501 * now peruse through the list of files.
503 for(fp=filelist; *fp; fp++) {
504 filecontent = getfile(*fp);
505 ip = newinclude(*fp, (char *)NULL);
507 find_includes(filecontent, ip, ip, 0, false);
508 freefile(filecontent);
509 recursive_pr_include(ip, ip->i_file, base_name(*fp));
518 struct filepointer *getfile(char *file)
521 struct filepointer *content;
524 content = (struct filepointer *)malloc(sizeof(struct filepointer));
525 content->f_name = strdup(translate_cygwin(file));
526 if ((fd = open(file, O_RDONLY)) < 0) {
527 warning("cannot open \"%s\"\n", translate_cygwin(file));
528 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
529 *content->f_p = '\0';
533 content->f_base = (char *)malloc(st.st_size+1);
534 if (content->f_base == NULL)
535 fatalerr("cannot allocate mem\n");
536 if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
537 fatalerr("failed to read %s\n", translate_cygwin(file));
539 content->f_len = st.st_size+1;
540 content->f_p = content->f_base;
541 content->f_end = content->f_base + st.st_size;
542 *content->f_end = '\0';
547 void freefile(struct filepointer *fp)
554 char *copy(register char *str)
556 register char *p = (char *)malloc(strlen(str) + 1);
562 int match(register const char *str, register const char **list)
566 for (i=0; *list; i++, list++)
567 if (strcmp(str, *list) == 0)
573 * Get the next line. We only return lines beginning with '#' since that
574 * is all this program is ever interested in.
576 char *getline(register struct filepointer *filep)
578 register char *p, /* walking pointer */
579 *eof, /* end of file pointer */
580 *bol; /* beginning of line pointer */
581 register int lineno; /* line number */
584 //// if (p >= eof) return NULL;
585 lineno = filep->f_line;
588 // p is always pointing at the "beginning of a line" when we start this loop.
589 // this means that we must start considering the stuff on that line as
590 // being a useful thing to look at.
591 for (p = filep->f_p; p < eof; p++) {
592 if (bol > p) fatalerr("somehow bol got ahead of p.");
593 if (*p == '/' && *(p+1) == '*') {
594 /* consume C-style comments */
595 *p++ = ' '; *p++ = ' '; // skip the two we've already seen.
597 if (*p == '*' && *(p+1) == '/') {
598 *p++ = ' '; *p = ' ';
599 // skip one of these last two, let the loop skip the next.
601 } else if (*p == '\n') lineno++;
602 p++; // skip the current character.
605 } else if (*p == '/' && *(p+1) == '/') {
606 /* consume C++-style comments */
607 *p++ = ' '; *p++ = ' '; // skip the comment characters.
608 while (p < eof && (*p != '\n') ) *p++ = ' ';
609 // we scan until we get to the end of line.
610 ///no count, since we'll see it again. lineno++;
611 p--; // skip back to just before \n.
612 continue; // let the loop skip past the eol that we saw.
613 } else if (*p == '\\') {
614 // handle an escape character.
615 if (*(p+1) == '\n') {
616 // we modify the stream so we consider the line correctly.
621 } else if (*p == '\n') {
622 // we've finally reached the end of the line.
624 *p = '\0'; // set the end of line to be a end of string now.
626 // it's not at the same position as the end of line, so it's worth
628 while ( (bol < p) && ((*bol == ' ') || (*bol == '\t')) ) bol++;
629 ////fprintf(stderr, "%s: %s\n", filep->f_name, bol);
633 /* punt lines with just # (yacc generated) */
634 for (cp = bol+1; *cp && (*cp == ' ' || *cp == '\t'); cp++) {}
635 if (*cp) { p++; goto done; }
638 // this is a failure now. we reset the beginning of line.
642 if (*bol != '#') bol = NULL;
645 filep->f_line = lineno;
650 * Strip the file name down to what we want to see in the Makefile.
651 * It will have objprefix and objsuffix around it.
653 char *base_name(register char *file)
658 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
665 #if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__EMX__)
666 int rename(char *from, char *to)
669 if (link (from, to) == 0) {
678 void redirect(char *line, char *makefile)
682 char backup[ BUFSIZ ],
688 * if makefile is "-" then let it pour onto stdout.
690 if (makefile && *makefile == '-' && *(makefile+1) == '\0')
694 * use a default makefile is not specified.
697 if (stat("Makefile", &st) == 0)
698 makefile = (char *)"Makefile";
699 else if (stat("makefile", &st) == 0)
700 makefile = (char *)"makefile";
702 fatalerr("[mM]akefile is not present\n");
706 if ((fdin = fopen(translate_cygwin(makefile), "r")) == NULL)
707 fatalerr("cannot open \"%s\"\n", translate_cygwin(makefile));
708 sprintf(backup, "%s.bak", makefile);
710 #if defined(WIN32) || defined(__EMX__) || defined(__OS2__)
713 if (rename(translate_cygwin(makefile), translate_cygwin(backup)) < 0)
714 fatalerr("cannot rename %s to %s\n", translate_cygwin(makefile), translate_cygwin(backup));
715 #if defined(WIN32) || defined(__EMX__) || defined(__OS2__)
716 if ((fdin = fopen(translate_cygwin(backup), "r")) == NULL)
717 fatalerr("cannot open \"%s\"\n", translate_cygwin(backup));
719 if ((fdout = freopen(translate_cygwin(makefile), "w", stdout)) == NULL)
720 fatalerr("cannot open \"%s\"\n", translate_cygwin(backup));
721 len = int(strlen(line));
722 while (!found && fgets(buf, BUFSIZ, fdin)) {
723 if (*buf == '#' && strncmp(line, buf, len) == 0)
729 warning("Adding new delimiting line \"%s\" and dependencies...\n",
731 puts(line); /* same as fputs(fdout); but with newline */
733 while (fgets(buf, BUFSIZ, fdin)) {
738 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
739 chmod(makefile, st.st_mode);
741 fchmod(fileno(fdout), st.st_mode);
745 #if NeedVarargsPrototypes
746 void fatalerr(const char *msg, ...)
749 void fatalerr(char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
752 #if NeedVarargsPrototypes
755 fprintf(stderr, "%s: error: ", ProgramName);
756 #if NeedVarargsPrototypes
758 vfprintf(stderr, msg, args);
761 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
766 #if NeedVarargsPrototypes
767 void warning(const char *msg, ...)
770 void warning(const char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
773 #if NeedVarargsPrototypes
776 fprintf(stderr, "%s: warning: ", ProgramName);
777 #if NeedVarargsPrototypes
779 vfprintf(stderr, msg, args);
782 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
786 #if NeedVarargsPrototypes
787 void warning1(const char *msg, ...)
790 void warning1(const char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
793 #if NeedVarargsPrototypes
796 vfprintf(stderr, msg, args);
799 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);