1 /* $Xorg: main.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */
4 Copyright (c) 1993, 1994, 1998 The Open Group
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
27 /* $XFree86: xc/config/makedepend/main.c,v 3.32 2003/03/26 20:43:48 tsi Exp $ */
31 #define sigvec sigvector
34 #ifdef X_POSIX_C_SOURCE
35 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
37 #undef _POSIX_C_SOURCE
39 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
58 /* #define DEBUG_DUMP */
60 #define DBG_PRINT(file, fmt, args) fprintf(file, fmt, args)
62 #define DBG_PRINT(file, fmt, args) /* empty */
65 #define DASH_INC_PRE "#include \""
66 #define DASH_INC_POST "\""
70 char *directives
[] = {
92 #include "imakemdep.h" /* from config sources */
95 struct inclist inclist
[ MAXFILES
],
97 *inclistnext
= inclist
,
100 static char *filelist
[ MAXFILES
];
101 char *includedirs
[ MAXDIRS
+ 1 ],
102 **includedirsnext
= includedirs
;
103 char *notdotdot
[ MAXDIRS
];
104 static int cmdinc_count
= 0;
105 static char *cmdinc_list
[ 2 * MAXINCFILES
];
106 char *objprefix
= "";
107 char *objsuffix
= OBJSUFFIX
;
108 static char *startat
= "# DO NOT DELETE";
110 static boolean append
= FALSE
;
111 boolean printed
= FALSE
;
112 boolean verbose
= FALSE
;
113 boolean show_where_not
= FALSE
;
114 /* Warn on multiple includes of same file */
115 boolean warn_multiple
= FALSE
;
117 static void setfile_cmdinc(struct filepointer
*filep
, long count
, char **list
);
118 static void redirect(char *line
, char *makefile
);
121 #ifdef SIGNALRETURNSINT
129 fatalerr ("got signal %d\n", sig
);
132 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__UNIXOS2__) || defined(Lynx_22) || defined(__CYGWIN__)
138 #define sigaction sigvec
139 #define sa_handler sv_handler
140 #define sa_mask sv_mask
141 #define sa_flags sv_flags
143 struct sigaction sig_act
;
147 main(int argc
, char *argv
[])
149 char **fp
= filelist
;
150 char **incp
= includedirs
;
153 char *makefile
= NULL
;
154 struct filepointer
*filecontent
;
155 struct symtab
*psymp
= predefs
;
156 char *endmarker
= NULL
;
157 char *defincdir
= NULL
;
158 char **undeflist
= NULL
;
159 int numundefs
= 0, i
;
160 register char offset
;
162 ProgramName
= argv
[0];
164 while (psymp
->s_name
)
166 define2(psymp
->s_name
, psymp
->s_value
, &maininclist
);
169 if (argc
== 2 && argv
[1][0] == '@') {
175 char quotechar
= '\0';
178 if ((afd
= open(argv
[1]+1, O_RDONLY
)) < 0)
179 fatalerr("cannot open \"%s\"\n", argv
[1]+1);
181 args
= (char *)malloc(ast
.st_size
+ 1);
182 if ((ast
.st_size
= read(afd
, args
, ast
.st_size
)) < 0)
183 fatalerr("failed to read %s\n", argv
[1]+1);
184 args
[ast
.st_size
] = '\0';
186 for (p
= args
; *p
; p
++) {
188 if (quotechar
== '\\' ||
189 (*p
== quotechar
&& p
[-1] != '\\'))
202 if (p
> args
&& p
[-1])
209 nargv
= (char **)malloc(nargc
* sizeof(char *));
212 for (p
= args
; argc
< nargc
; p
+= strlen(p
) + 1)
213 if (*p
) nargv
[argc
++] = p
;
216 for(argc
--, argv
++; argc
; argc
--, argv
++) {
217 /* if looking for endmarker then check before parsing */
218 if (endmarker
&& strcmp (endmarker
, *argv
) == 0) {
223 /* treat +thing as an option for C++ */
224 if (endmarker
&& **argv
== '+')
231 endmarker
= &argv
[0][2];
232 if (endmarker
[0] == '\0') endmarker
= "--";
236 if (argv
[0][2] == '\0') {
241 /* offset +1 here since first def letter
244 for (p
= argv
[0] + offset
+ 1; *p
; p
++)
249 define(argv
[0] + offset
, &maininclist
);
252 if (incp
>= includedirs
+ MAXDIRS
)
253 fatalerr("Too many -I flags.\n");
255 if (**(incp
-1) == '\0') {
256 *(incp
-1) = *(++argv
);
261 /* Undef's override all -D's so save them up */
264 undeflist
= malloc(sizeof(char *));
266 undeflist
= realloc(undeflist
,
267 numundefs
* sizeof(char *));
269 if (argv
[0][2] == '\0') {
274 undeflist
[numundefs
- 1] = argv
[0] + offset
;
277 defincdir
= argv
[0]+2;
279 /* do not use if endmarker processing */
281 if (endmarker
) break;
285 if (endmarker
) break;
286 if (argv
[0][2] == '\0') {
289 width
= atoi(argv
[0]);
291 width
= atoi(argv
[0]+2);
294 if (endmarker
) break;
295 if (argv
[0][2] == '\0') {
300 objsuffix
= argv
[0]+2;
303 if (endmarker
) break;
304 if (argv
[0][2] == '\0') {
309 objprefix
= argv
[0]+2;
312 if (endmarker
) break;
316 _debugmask
= atoi(argv
[0]+2);
320 if (endmarker
) break;
322 if (*startat
== '\0') {
327 fatalerr("-s flag's value should start %s\n",
331 if (endmarker
) break;
332 makefile
= argv
[0]+2;
333 if (*makefile
== '\0') {
334 makefile
= *(++argv
);
340 warn_multiple
= TRUE
;
343 /* Ignore -O, -g so we can just pass ${CFLAGS} to
350 if (strcmp(&argv
[0][1],"include") == 0) {
353 fatalerr("option -include is a "
354 "missing its parameter\n");
355 if (cmdinc_count
>= MAXINCFILES
)
356 fatalerr("Too many -include flags.\n");
359 buf
= malloc(strlen(DASH_INC_PRE
) +
361 strlen(DASH_INC_POST
) + 1);
363 fatalerr("out of memory at "
364 "-include string\n");
365 cmdinc_list
[2 * cmdinc_count
+ 0] = argv
[0];
366 cmdinc_list
[2 * cmdinc_count
+ 1] = buf
;
370 /* intentional fall through */
372 if (endmarker
) break;
373 /* fatalerr("unknown opt = %s\n", argv[0]); */
374 warning("ignoring option %s\n", argv
[0]);
377 /* Now do the undefs from the command line */
378 for (i
= 0; i
< numundefs
; i
++)
379 undefine(undeflist
[i
], &maininclist
);
385 if (incp
>= includedirs
+ MAXDIRS
)
386 fatalerr("Too many -I flags.\n");
391 char *emxinc
= getenv("C_INCLUDE_PATH");
392 /* can have more than one component */
395 beg
= (char*)strdup(emxinc
);
397 end
= (char*)strchr(beg
,';');
399 if (incp
>= includedirs
+ MAXDIRS
)
400 fatalerr("Too many include dirs\n");
407 #else /* !__UNIXOS2__, does not use INCLUDEDIR at all */
408 if (incp
>= includedirs
+ MAXDIRS
)
409 fatalerr("Too many -I flags.\n");
410 *incp
++ = INCLUDEDIR
;
414 if (incp
>= includedirs
+ MAXDIRS
)
415 fatalerr("Too many -I flags.\n");
416 *incp
++ = EXTRAINCDIR
;
420 if (incp
>= includedirs
+ MAXDIRS
)
421 fatalerr("Too many -I flags.\n");
422 *incp
++ = POSTINCDIR
;
424 } else if (*defincdir
) {
425 if (incp
>= includedirs
+ MAXDIRS
)
426 fatalerr("Too many -I flags.\n");
430 redirect(startat
, makefile
);
436 /* should really reset SIGINT to SIG_IGN if it was. */
438 signal (SIGHUP
, catch);
440 signal (SIGINT
, catch);
442 signal (SIGQUIT
, catch);
444 signal (SIGILL
, catch);
446 signal (SIGBUS
, catch);
448 signal (SIGSEGV
, catch);
450 signal (SIGSYS
, catch);
453 sig_act
.sa_handler
= catch;
454 #if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
455 sigemptyset(&sig_act
.sa_mask
);
456 sigaddset(&sig_act
.sa_mask
, SIGINT
);
457 sigaddset(&sig_act
.sa_mask
, SIGQUIT
);
459 sigaddset(&sig_act
.sa_mask
, SIGBUS
);
461 sigaddset(&sig_act
.sa_mask
, SIGILL
);
462 sigaddset(&sig_act
.sa_mask
, SIGSEGV
);
463 sigaddset(&sig_act
.sa_mask
, SIGHUP
);
464 sigaddset(&sig_act
.sa_mask
, SIGPIPE
);
466 sigaddset(&sig_act
.sa_mask
, SIGSYS
);
469 sig_act
.sa_mask
= ((1<<(SIGINT
-1))
482 #endif /* _POSIX_SOURCE */
483 sig_act
.sa_flags
= 0;
484 sigaction(SIGHUP
, &sig_act
, (struct sigaction
*)0);
485 sigaction(SIGINT
, &sig_act
, (struct sigaction
*)0);
486 sigaction(SIGQUIT
, &sig_act
, (struct sigaction
*)0);
487 sigaction(SIGILL
, &sig_act
, (struct sigaction
*)0);
489 sigaction(SIGBUS
, &sig_act
, (struct sigaction
*)0);
491 sigaction(SIGSEGV
, &sig_act
, (struct sigaction
*)0);
493 sigaction(SIGSYS
, &sig_act
, (struct sigaction
*)0);
498 * now peruse through the list of files.
500 for(fp
=filelist
; *fp
; fp
++) {
501 DBG_PRINT(stderr
,"file: %s\n",*fp
);
502 filecontent
= getfile(*fp
);
503 setfile_cmdinc(filecontent
, cmdinc_count
, cmdinc_list
);
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
));
518 * eliminate \r chars from file
521 elim_cr(char *buf
, int sz
)
524 for (i
= wp
= 0; i
<sz
; i
++) {
536 struct filepointer
*content
;
539 content
= (struct filepointer
*)malloc(sizeof(struct filepointer
));
540 content
->f_name
= file
;
541 if ((fd
= open(file
, O_RDONLY
)) < 0) {
542 warning("cannot open \"%s\"\n", file
);
543 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
544 *content
->f_p
= '\0';
548 content
->f_base
= (char *)malloc(st
.st_size
+1);
549 if (content
->f_base
== NULL
)
550 fatalerr("cannot allocate mem\n");
551 if ((st
.st_size
= read(fd
, content
->f_base
, st
.st_size
)) < 0)
552 fatalerr("failed to read %s\n", file
);
554 st
.st_size
= elim_cr(content
->f_base
,st
.st_size
);
557 content
->f_len
= st
.st_size
+1;
558 content
->f_p
= content
->f_base
;
559 content
->f_end
= content
->f_base
+ st
.st_size
;
560 *content
->f_end
= '\0';
562 content
->cmdinc_count
= 0;
563 content
->cmdinc_list
= NULL
;
564 content
->cmdinc_line
= 0;
569 setfile_cmdinc(struct filepointer
* filep
, long count
, char** list
)
571 filep
->cmdinc_count
= count
;
572 filep
->cmdinc_list
= list
;
573 filep
->cmdinc_line
= 0;
577 freefile(struct filepointer
*fp
)
583 char *copy(char *str
)
585 char *p
= (char *)malloc(strlen(str
) + 1);
592 match(char *str
, char **list
)
596 for (i
=0; *list
; i
++, list
++)
597 if (strcmp(str
, *list
) == 0)
603 * Get the next line. We only return lines beginning with '#' since that
604 * is all this program is ever interested in.
606 char *getnextline(struct filepointer
*filep
)
608 char *p
, /* walking pointer */
609 *eof
, /* end of file pointer */
610 *bol
; /* beginning of line pointer */
611 int lineno
; /* line number */
612 boolean whitespace
= FALSE
;
615 * Fake the "-include" line files in form of #include to the
616 * start of each file.
618 if (filep
->cmdinc_line
< filep
->cmdinc_count
) {
619 char *inc
= filep
->cmdinc_list
[2 * filep
->cmdinc_line
+ 0];
620 char *buf
= filep
->cmdinc_list
[2 * filep
->cmdinc_line
+ 1];
621 filep
->cmdinc_line
++;
622 sprintf(buf
,"%s%s%s",DASH_INC_PRE
,inc
,DASH_INC_POST
);
623 DBG_PRINT(stderr
,"%s\n",buf
);
630 return((char *)NULL
);
631 lineno
= filep
->f_line
;
633 for (bol
= p
--; ++p
< eof
; ) {
634 if ((bol
== p
) && ((*p
== ' ') || (*p
== '\t')))
636 /* Consume leading white-spaces for this line */
637 while (((p
+1) < eof
) && ((*p
== ' ') || (*p
== '\t')))
645 if (*p
== '/' && (p
+1) < eof
&& *(p
+1) == '*') {
646 /* Consume C comments */
649 while (p
< eof
&& *p
) {
650 if (*p
== '*' && (p
+1) < eof
&& *(p
+1) == '/') {
661 else if (*p
== '/' && (p
+1) < eof
&& *(p
+1) == '/') {
662 /* Consume C++ comments */
665 while (p
< eof
&& *p
) {
666 if (*p
== '\\' && (p
+1) < eof
&&
671 else if (*p
== '?' && (p
+3) < eof
&&
681 break; /* to process end of line */
686 else if (*p
== '\\' && (p
+1) < eof
&& *(p
+1) == '\n') {
687 /* Consume backslash line terminations */
692 else if (*p
== '?' && (p
+3) < eof
&&
693 *(p
+1) == '?' && *(p
+2) == '/' && *(p
+3) == '\n') {
694 /* Consume trigraph'ed backslash line terminations */
701 else if (*p
== '\n') {
707 /* punt lines with just # (yacc generated) */
709 *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++);
720 if (bol
&& whitespace
) {
721 warning("%s: non-portable whitespace encountered at line %d\n",
722 filep
->f_name
, lineno
);
725 filep
->f_line
= lineno
;
728 DBG_PRINT(stderr
,"%s\n",bol
);
734 * Strip the file name down to what we want to see in the Makefile.
735 * It will have objprefix and objsuffix around it.
737 char *base_name(char *file
)
742 for(p
=file
+strlen(file
); p
>file
&& *p
!= '.'; p
--) ;
749 #if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__UNIXOS2__) && !defined(clipper) && !defined(__clipper__)
750 int rename (char *from
, char *to
)
753 if (link (from
, to
) == 0) {
763 redirect(char *line
, char *makefile
)
767 char backup
[ BUFSIZ
],
769 boolean found
= FALSE
;
773 * if makefile is "-" then let it pour onto stdout.
775 if (makefile
&& *makefile
== '-' && *(makefile
+1) == '\0') {
781 * use a default makefile is not specified.
784 if (stat("Makefile", &st
) == 0)
785 makefile
= "Makefile";
786 else if (stat("makefile", &st
) == 0)
787 makefile
= "makefile";
789 fatalerr("[mM]akefile is not present\n");
793 if ((fdin
= fopen(makefile
, "r")) == NULL
)
794 fatalerr("cannot open \"%s\"\n", makefile
);
795 sprintf(backup
, "%s.bak", makefile
);
797 #if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
800 if (rename(makefile
, backup
) < 0)
801 fatalerr("cannot rename %s to %s\n", makefile
, backup
);
802 #if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
803 if ((fdin
= fopen(backup
, "r")) == NULL
)
804 fatalerr("cannot open \"%s\"\n", backup
);
806 if ((fdout
= freopen(makefile
, "w", stdout
)) == NULL
)
807 fatalerr("cannot open \"%s\"\n", backup
);
809 while (!found
&& fgets(buf
, BUFSIZ
, fdin
)) {
810 if (*buf
== '#' && strncmp(line
, buf
, len
) == 0)
816 warning("Adding new delimiting line \"%s\" and dependencies...\n",
818 puts(line
); /* same as fputs(fdout); but with newline */
820 while (fgets(buf
, BUFSIZ
, fdin
)) {
825 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
826 chmod(makefile
, st
.st_mode
);
828 fchmod(fileno(fdout
), st
.st_mode
);
833 fatalerr(char *msg
, ...)
836 fprintf(stderr
, "%s: error: ", ProgramName
);
838 vfprintf(stderr
, msg
, args
);
844 warning(char *msg
, ...)
847 fprintf(stderr
, "%s: warning: ", ProgramName
);
849 vfprintf(stderr
, msg
, args
);
854 warning1(char *msg
, ...)
858 vfprintf(stderr
, msg
, args
);