blob: 73057ae73d939ebda8554f678c47c724689a32bf [file] [log] [blame]
Adam Tkacfded0782008-03-22 11:20:54 +00001/* $XConsortium: main.c,v 1.84 94/11/30 16:10:44 kaleb Exp $ */
2/*
3
4Copyright (c) 1993, 1994 X Consortium
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of the X Consortium shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from the X Consortium.
26
27*/
28
29#include "def.h"
30#ifdef hpux
31#define sigvec sigvector
32#endif /* hpux */
33
34#ifdef X_POSIX_C_SOURCE
35#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
36#include <signal.h>
37#undef _POSIX_C_SOURCE
38#else
39#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
40#include <signal.h>
41#else
42#define _POSIX_SOURCE
43#include <signal.h>
44#undef _POSIX_SOURCE
45#endif
46#endif
47
48#if NeedVarargsPrototypes
49#include <stdarg.h>
50#endif
51
52#ifdef DEBUG
53int _debugmask;
54#endif
55
56char *ProgramName;
57
58char *directives[] = {
59 "if",
60 "ifdef",
61 "ifndef",
62 "else",
63 "endif",
64 "define",
65 "undef",
66 "include",
67 "line",
68 "pragma",
69 "error",
70 "ident",
71 "sccs",
72 "elif",
73 "eject",
74 NULL
75};
76
77struct symtab predefs[] = { {NULL, NULL} };
78
79struct inclist inclist[ MAXFILES ],
80 *inclistp = inclist,
81 maininclist;
82
83char *filelist[ MAXFILES ];
84char *includedirs[ MAXDIRS + 1 ];
85char *notdotdot[ MAXDIRS ];
86char *objprefix = "";
87char *objsuffix = ".o";
88int width = 78;
89boolean append = FALSE;
90boolean printed = FALSE;
91boolean verbose = FALSE;
92boolean show_where_not = FALSE;
93boolean warn_multiple = FALSE; /* Warn on multiple includes of same file */
94
95static
96#ifdef SIGNALRETURNSINT
97int
98#else
99void
100#endif
101catch (sig)
102 int sig;
103{
104 fflush (stdout);
105 fatalerr ("got signal %d\n", sig);
106}
107
108#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__nextstep__)
109#define USGISH
110#endif
111
112#ifndef USGISH
113#ifndef _POSIX_SOURCE
114#define sigaction sigvec
115#define sa_handler sv_handler
116#define sa_mask sv_mask
117#define sa_flags sv_flags
118#endif
119struct sigaction sig_act;
120#endif /* USGISH */
121
122main(argc, argv)
123 int argc;
124 char **argv;
125{
126 register char **fp = filelist;
127 register char **incp = includedirs;
128 register char *p;
129 register struct inclist *ip;
130 char *makefile = NULL;
131 struct filepointer *filecontent;
132 struct symtab *psymp = predefs;
133 char *endmarker = NULL;
134 char *defincdir = NULL;
135
136 ProgramName = argv[0];
137
138 while (psymp->s_name)
139 {
140 define2(psymp->s_name, psymp->s_value, &maininclist);
141 psymp++;
142 }
143 if (argc == 2 && argv[1][0] == '@') {
144 struct stat ast;
145 int afd;
146 char *args;
147 char **nargv;
148 int nargc;
149 char quotechar = '\0';
150
151 nargc = 1;
152 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
153 fatalerr("cannot open \"%s\"\n", argv[1]+1);
154 fstat(afd, &ast);
155 args = (char *)malloc(ast.st_size + 1);
156 if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
157 fatalerr("failed to read %s\n", argv[1]+1);
158 args[ast.st_size] = '\0';
159 close(afd);
160 for (p = args; *p; p++) {
161 if (quotechar) {
162 if (quotechar == '\\' ||
163 (*p == quotechar && p[-1] != '\\'))
164 quotechar = '\0';
165 continue;
166 }
167 switch (*p) {
168 case '\\':
169 case '"':
170 case '\'':
171 quotechar = *p;
172 break;
173 case ' ':
174 case '\n':
175 *p = '\0';
176 if (p > args && p[-1])
177 nargc++;
178 break;
179 }
180 }
181 if (p[-1])
182 nargc++;
183 nargv = (char **)malloc(nargc * sizeof(char *));
184 nargv[0] = argv[0];
185 argc = 1;
186 for (p = args; argc < nargc; p += strlen(p) + 1)
187 if (*p) nargv[argc++] = p;
188 argv = nargv;
189 }
190 for(argc--, argv++; argc; argc--, argv++) {
191 /* if looking for endmarker then check before parsing */
192 if (endmarker && strcmp (endmarker, *argv) == 0) {
193 endmarker = NULL;
194 continue;
195 }
196 if (**argv != '-') {
197 /* treat +thing as an option for C++ */
198 if (endmarker && **argv == '+')
199 continue;
200 *fp++ = argv[0];
201 continue;
202 }
203 switch(argv[0][1]) {
204 case '-':
205 endmarker = &argv[0][2];
206 if (endmarker[0] == '\0') endmarker = "--";
207 break;
208 case 'D':
209 {
210 int offset = 2;
211 if (argv[0][2] == '\0') {
212 argv++;
213 argc--;
214 offset = 0;
215 }
216 for (p=argv[0] + offset; *p ; p++)
217 if (*p == '=') {
218 *p = ' ';
219 break;
220 }
221 define(argv[0] + offset, &maininclist);
222 break;
223 }
224 case 'I':
225 if (incp >= includedirs + MAXDIRS)
226 fatalerr("Too many -I flags.\n");
227 *incp++ = argv[0]+2;
228 if (**(incp-1) == '\0') {
229 *(incp-1) = *(++argv);
230 argc--;
231 }
232 break;
233 case 'Y':
234 defincdir = argv[0]+2;
235 break;
236 /* do not use if endmarker processing */
237 case 'a':
238 if (endmarker) break;
239 append = TRUE;
240 break;
241 case 'w':
242 if (endmarker) break;
243 if (argv[0][2] == '\0') {
244 argv++;
245 argc--;
246 width = atoi(argv[0]);
247 } else
248 width = atoi(argv[0]+2);
249 break;
250 case 'o':
251 if (endmarker) break;
252 if (argv[0][2] == '\0') {
253 argv++;
254 argc--;
255 objsuffix = argv[0];
256 } else
257 objsuffix = argv[0]+2;
258 break;
259 case 'p':
260 if (endmarker) break;
261 if (argv[0][2] == '\0') {
262 argv++;
263 argc--;
264 objprefix = argv[0];
265 } else
266 objprefix = argv[0]+2;
267 break;
268 case 'v':
269 if (endmarker) break;
270 verbose = TRUE;
271#ifdef DEBUG
272 if (argv[0][2])
273 _debugmask = atoi(argv[0]+2);
274#endif
275 break;
276 case 'm':
277 warn_multiple = TRUE;
278 break;
279
280 /* Ignore -O, -g so we can just pass ${CFLAGS} to
281 makedepend
282 */
283 case 'O':
284 case 'g':
285 break;
286 default:
287 if (endmarker) break;
288 /* fatalerr("unknown opt = %s\n", argv[0]); */
289 warning("ignoring option %s\n", argv[0]);
290 }
291 }
292 if (!defincdir) {
293 } else if (*defincdir) {
294 if (incp >= includedirs + MAXDIRS)
295 fatalerr("Too many -I flags.\n");
296 *incp++ = defincdir;
297 }
298
299 /*
300 * catch signals.
301 */
302#ifdef USGISH
303/* should really reset SIGINT to SIG_IGN if it was. */
304#ifdef SIGHUP
305 signal (SIGHUP, catch);
306#endif
307 signal (SIGINT, catch);
308#ifdef SIGQUIT
309 signal (SIGQUIT, catch);
310#endif
311 signal (SIGILL, catch);
312#ifdef SIGBUS
313 signal (SIGBUS, catch);
314#endif
315 signal (SIGSEGV, catch);
316#ifdef SIGSYS
317 signal (SIGSYS, catch);
318#endif
319#else
320 sig_act.sa_handler = catch;
321#ifdef _POSIX_SOURCE
322 sigemptyset(&sig_act.sa_mask);
323 sigaddset(&sig_act.sa_mask, SIGINT);
324 sigaddset(&sig_act.sa_mask, SIGQUIT);
325#ifdef SIGBUS
326 sigaddset(&sig_act.sa_mask, SIGBUS);
327#endif
328 sigaddset(&sig_act.sa_mask, SIGILL);
329 sigaddset(&sig_act.sa_mask, SIGSEGV);
330 sigaddset(&sig_act.sa_mask, SIGHUP);
331 sigaddset(&sig_act.sa_mask, SIGPIPE);
332#ifdef SIGSYS
333 sigaddset(&sig_act.sa_mask, SIGSYS);
334#endif
335#else
336 sig_act.sa_mask = ((1<<(SIGINT -1))
337 |(1<<(SIGQUIT-1))
338#ifdef SIGBUS
339 |(1<<(SIGBUS-1))
340#endif
341 |(1<<(SIGILL-1))
342 |(1<<(SIGSEGV-1))
343 |(1<<(SIGHUP-1))
344 |(1<<(SIGPIPE-1))
345#ifdef SIGSYS
346 |(1<<(SIGSYS-1))
347#endif
348 );
349#endif /* _POSIX_SOURCE */
350 sig_act.sa_flags = 0;
351 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
352 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
353 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
354 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
355#ifdef SIGBUS
356 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
357#endif
358 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
359#ifdef SIGSYS
360 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
361#endif
362#endif /* USGISH */
363
364 /*
365 * now peruse through the list of files.
366 */
367 for(fp=filelist; *fp; fp++) {
368 char *base = base_name(*fp);
369 char *depfile = (char *)malloc(strlen(base) + 3);
370 sprintf(depfile,"%s.d",base);
371 if (!freopen(depfile, "wb", stdout))
372 fatalerr("cannot open \"%s\"\n", depfile);
373 free(depfile);
374 free(base);
375 printed = FALSE;
376 filecontent = getfile(*fp);
377 ip = newinclude(*fp, (char *)NULL);
378
379 find_includes(filecontent, ip, ip, 0, TRUE);
380 freefile(filecontent);
381 recursive_pr_include(ip, ip->i_file, base_name(*fp));
382 inc_clean();
383 if (printed)
384 printf("\n");
385 }
386 exit(0);
387}
388
389struct filepointer *getfile(file)
390 char *file;
391{
392 register int fd;
393 struct filepointer *content;
394 struct stat st;
395
396 content = (struct filepointer *)malloc(sizeof(struct filepointer));
397 if ((fd = open(file, O_RDONLY)) < 0) {
398 warning("cannot open \"%s\"\n", file);
399 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
400 *content->f_p = '\0';
401 return(content);
402 }
403 fstat(fd, &st);
404 content->f_base = (char *)malloc(st.st_size+1);
405 if (content->f_base == NULL)
406 fatalerr("cannot allocate mem\n");
407 if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
408 fatalerr("failed to read %s\n", file);
409 close(fd);
410 content->f_len = st.st_size+1;
411 content->f_p = content->f_base;
412 content->f_end = content->f_base + st.st_size;
413 *content->f_end = '\0';
414 content->f_line = 0;
415 return(content);
416}
417
418freefile(fp)
419 struct filepointer *fp;
420{
421 free(fp->f_base);
422 free(fp);
423}
424
425char *copy(str)
426 register char *str;
427{
428 register char *p = (char *)malloc(strlen(str) + 1);
429
430 strcpy(p, str);
431 return(p);
432}
433
434match(str, list)
435 register char *str, **list;
436{
437 register int i;
438
439 for (i=0; *list; i++, list++)
440 if (strcmp(str, *list) == 0)
441 return(i);
442 return(-1);
443}
444
445/*
446 * Get the next line. We only return lines beginning with '#' since that
447 * is all this program is ever interested in.
448 */
449char *getline(filep)
450 register struct filepointer *filep;
451{
452 register char *p, /* walking pointer */
453 *eof, /* end of file pointer */
454 *bol; /* beginning of line pointer */
455 register lineno; /* line number */
456
457 p = filep->f_p;
458 eof = filep->f_end;
459 if (p >= eof)
460 return((char *)NULL);
461 lineno = filep->f_line;
462
463 for(bol = p--; ++p < eof; ) {
464 if (*p == '/' && *(p+1) == '*') { /* consume comments */
465 *p++ = ' ', *p++ = ' ';
466 while (*p) {
467 if (*p == '*' && *(p+1) == '/') {
468 *p++ = ' ', *p = ' ';
469 break;
470 }
471 else if (*p == '\n')
472 lineno++;
473 *p++ = ' ';
474 }
475 continue;
476 }
477 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
478 *p++ = ' ', *p++ = ' ';
479 while (*p && *p != '\n')
480 *p++ = ' ';
481 p--; /* go back to before newline */
482 lineno++;
483 continue;
484 }
485 else if (*p == '\\') {
486 if (*(p+1) == '\n') {
487 *p = ' ';
488 *(p+1) = ' ';
489 lineno++;
490 }
491 }
492 else if (*p == '\n') {
493 lineno++;
494 if (*bol == '#') {
495 register char *cp;
496
497 *p++ = '\0';
498 /* punt lines with just # (yacc generated) */
499 for (cp = bol+1;
500 *cp && (*cp == ' ' || *cp == '\t'); cp++);
501 if (*cp) goto done;
502 }
503 bol = p+1;
504 }
505 }
506 if (*bol != '#')
507 bol = NULL;
508done:
509 filep->f_p = p;
510 filep->f_line = lineno;
511 return(bol);
512}
513
514/*
515 * Strip the file name down to what we want to see in the Makefile.
516 * It will have objprefix and objsuffix around it.
517 */
518char *base_name(file)
519 register char *file;
520{
521 register char *p;
522
523 for(p=file+strlen(file); p>file && *p != '/' && *p != '\\'; p--) ;
524 if (p>file) p++;
525 file = copy(p);
526 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
527
528 if (*p == '.')
529 *p = '\0';
530 return(file);
531}
532
533
534#if NeedVarargsPrototypes
535fatalerr(char *msg, ...)
536#else
537/*VARARGS*/
538fatalerr(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
539 char *msg;
540#endif
541{
542#if NeedVarargsPrototypes
543 va_list args;
544#endif
545 fprintf(stderr, "%s: error: ", ProgramName);
546#if NeedVarargsPrototypes
547 va_start(args, msg);
548 vfprintf(stderr, msg, args);
549 va_end(args);
550#else
551 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
552#endif
553 exit (1);
554}
555
556#if NeedVarargsPrototypes
557warning(char *msg, ...)
558#else
559/*VARARGS0*/
560warning(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
561 char *msg;
562#endif
563{
564#if NeedVarargsPrototypes
565 va_list args;
566#endif
567 fprintf(stderr, "%s: warning: ", ProgramName);
568#if NeedVarargsPrototypes
569 va_start(args, msg);
570 vfprintf(stderr, msg, args);
571 va_end(args);
572#else
573 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
574#endif
575}
576
577#if NeedVarargsPrototypes
578warning1(char *msg, ...)
579#else
580/*VARARGS0*/
581warning1(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
582 char *msg;
583#endif
584{
585#if NeedVarargsPrototypes
586 va_list args;
587 va_start(args, msg);
588 vfprintf(stderr, msg, args);
589 va_end(args);
590#else
591 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
592#endif
593}