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]);
412 if (incp >= includedirs + MAXDIRS)
413 fatalerr("Too many -I flags.\n");
417 if (incp >= includedirs + MAXDIRS)
418 fatalerr("Too many -I flags.\n");
419 *incp++ = INCLUDEDIR;
422 if (incp >= includedirs + MAXDIRS)
423 fatalerr("Too many -I flags.\n");
424 *incp++ = POSTINCDIR;
426 } else if (*defincdir) {
427 if (incp >= includedirs + MAXDIRS)
428 fatalerr("Too many -I flags.\n");
432 redirect(startat, makefile);
438 /* should really reset SIGINT to SIG_IGN if it was. */
440 signal (SIGHUP, c_catch);
442 signal (SIGINT, c_catch);
444 signal (SIGQUIT, c_catch);
446 signal (SIGILL, c_catch);
448 signal (SIGBUS, c_catch);
450 signal (SIGSEGV, c_catch);
452 signal (SIGSYS, c_catch);
455 sig_act.sa_handler = c_catch;
457 sigemptyset(&sig_act.sa_mask);
458 sigaddset(&sig_act.sa_mask, SIGINT);
459 sigaddset(&sig_act.sa_mask, SIGQUIT);
461 sigaddset(&sig_act.sa_mask, SIGBUS);
463 sigaddset(&sig_act.sa_mask, SIGILL);
464 sigaddset(&sig_act.sa_mask, SIGSEGV);
465 sigaddset(&sig_act.sa_mask, SIGHUP);
466 sigaddset(&sig_act.sa_mask, SIGPIPE);
468 sigaddset(&sig_act.sa_mask, SIGSYS);
471 sig_act.sa_mask = ((1<<(SIGINT -1))
484 #endif /* _POSIX_SOURCE */
485 sig_act.sa_flags = 0;
486 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
487 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
488 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
489 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
491 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
493 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
495 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
500 * now peruse through the list of files.
502 for(fp=filelist; *fp; fp++) {
503 filecontent = getfile(*fp);
504 ip = newinclude(*fp, (char *)NULL);
506 find_includes(filecontent, ip, ip, 0, false);
507 freefile(filecontent);
508 recursive_pr_include(ip, ip->i_file, base_name(*fp));
517 struct filepointer *getfile(char *file)
520 struct filepointer *content;
523 content = (struct filepointer *)malloc(sizeof(struct filepointer));
524 content->f_name = strdup(translate_cygwin(file));
525 if ((fd = open(file, O_RDONLY)) < 0) {
526 warning("cannot open \"%s\"\n", translate_cygwin(file));
527 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
528 *content->f_p = '\0';
532 content->f_base = (char *)malloc(st.st_size+1);
533 if (content->f_base == NULL)
534 fatalerr("cannot allocate mem\n");
535 if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
536 fatalerr("failed to read %s\n", translate_cygwin(file));
538 content->f_len = st.st_size+1;
539 content->f_p = content->f_base;
540 content->f_end = content->f_base + st.st_size;
541 *content->f_end = '\0';
546 void freefile(struct filepointer *fp)
553 char *copy(register char *str)
555 register char *p = (char *)malloc(strlen(str) + 1);
561 int match(register const char *str, register const char **list)
565 for (i=0; *list; i++, list++)
566 if (strcmp(str, *list) == 0)
572 * Get the next line. We only return lines beginning with '#' since that
573 * is all this program is ever interested in.
575 char *getline(register struct filepointer *filep)
577 register char *p, /* walking pointer */
578 *eof, /* end of file pointer */
579 *bol; /* beginning of line pointer */
580 register int lineno; /* line number */
583 //// if (p >= eof) return NULL;
584 lineno = filep->f_line;
587 // p is always pointing at the "beginning of a line" when we start this loop.
588 // this means that we must start considering the stuff on that line as
589 // being a useful thing to look at.
590 for (p = filep->f_p; p < eof; p++) {
591 if (bol > p) fatalerr("somehow bol got ahead of p.");
592 if (*p == '/' && *(p+1) == '*') {
593 /* consume C-style comments */
594 *p++ = ' '; *p++ = ' '; // skip the two we've already seen.
596 if (*p == '*' && *(p+1) == '/') {
597 *p++ = ' '; *p = ' ';
598 // skip one of these last two, let the loop skip the next.
600 } else if (*p == '\n') lineno++;
601 p++; // skip the current character.
604 } else if (*p == '/' && *(p+1) == '/') {
605 /* consume C++-style comments */
606 *p++ = ' '; *p++ = ' '; // skip the comment characters.
607 while (p < eof && (*p != '\n') ) *p++ = ' ';
608 // we scan until we get to the end of line.
609 ///no count, since we'll see it again. lineno++;
610 p--; // skip back to just before \n.
611 continue; // let the loop skip past the eol that we saw.
612 } else if (*p == '\\') {
613 // handle an escape character.
614 if (*(p+1) == '\n') {
615 // we modify the stream so we consider the line correctly.
620 } else if (*p == '\n') {
621 // we've finally reached the end of the line.
623 *p = '\0'; // set the end of line to be a end of string now.
625 // it's not at the same position as the end of line, so it's worth
627 while ( (bol < p) && ((*bol == ' ') || (*bol == '\t')) ) bol++;
628 ////fprintf(stderr, "%s: %s\n", filep->f_name, bol);
632 /* punt lines with just # (yacc generated) */
633 for (cp = bol+1; *cp && (*cp == ' ' || *cp == '\t'); cp++) {}
634 if (*cp) { p++; goto done; }
637 // this is a failure now. we reset the beginning of line.
641 if (*bol != '#') bol = NULL;
644 filep->f_line = lineno;
649 * Strip the file name down to what we want to see in the Makefile.
650 * It will have objprefix and objsuffix around it.
652 char *base_name(register char *file)
657 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
664 #if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__EMX__)
665 int rename(char *from, char *to)
668 if (link (from, to) == 0) {
677 void redirect(char *line, char *makefile)
681 char backup[ BUFSIZ ],
687 * if makefile is "-" then let it pour onto stdout.
689 if (makefile && *makefile == '-' && *(makefile+1) == '\0')
693 * use a default makefile is not specified.
696 if (stat("Makefile", &st) == 0)
697 makefile = (char *)"Makefile";
698 else if (stat("makefile", &st) == 0)
699 makefile = (char *)"makefile";
701 fatalerr("[mM]akefile is not present\n");
705 if ((fdin = fopen(translate_cygwin(makefile), "r")) == NULL)
706 fatalerr("cannot open \"%s\"\n", translate_cygwin(makefile));
707 sprintf(backup, "%s.bak", makefile);
709 #if defined(WIN32) || defined(__EMX__) || defined(__OS2__)
712 if (rename(translate_cygwin(makefile), translate_cygwin(backup)) < 0)
713 fatalerr("cannot rename %s to %s\n", translate_cygwin(makefile), translate_cygwin(backup));
714 #if defined(WIN32) || defined(__EMX__) || defined(__OS2__)
715 if ((fdin = fopen(translate_cygwin(backup), "r")) == NULL)
716 fatalerr("cannot open \"%s\"\n", translate_cygwin(backup));
718 if ((fdout = freopen(translate_cygwin(makefile), "w", stdout)) == NULL)
719 fatalerr("cannot open \"%s\"\n", translate_cygwin(backup));
720 len = int(strlen(line));
721 while (!found && fgets(buf, BUFSIZ, fdin)) {
722 if (*buf == '#' && strncmp(line, buf, len) == 0)
728 warning("Adding new delimiting line \"%s\" and dependencies...\n",
730 puts(line); /* same as fputs(fdout); but with newline */
732 while (fgets(buf, BUFSIZ, fdin)) {
737 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
738 chmod(makefile, st.st_mode);
740 fchmod(fileno(fdout), st.st_mode);
744 #if NeedVarargsPrototypes
745 void fatalerr(const char *msg, ...)
748 void fatalerr(char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
751 #if NeedVarargsPrototypes
754 fprintf(stderr, "%s: error: ", ProgramName);
755 #if NeedVarargsPrototypes
757 vfprintf(stderr, msg, args);
760 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
765 #if NeedVarargsPrototypes
766 void warning(const char *msg, ...)
769 void warning(const char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
772 #if NeedVarargsPrototypes
775 fprintf(stderr, "%s: warning: ", ProgramName);
776 #if NeedVarargsPrototypes
778 vfprintf(stderr, msg, args);
781 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
785 #if NeedVarargsPrototypes
786 void warning1(const char *msg, ...)
789 void warning1(const char *msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
792 #if NeedVarargsPrototypes
795 vfprintf(stderr, msg, args);
798 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);