1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* $XConsortium: main.c,v 1.84 94/11/30 16:10:44 kaleb Exp $ */
3 /* $XFree86: xc/config/makedepend/main.c,v 3.4 1995/07/15 14:53:49 dawes Exp $ */
6 Copyright (c) 1993, 1994 X Consortium
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of the X Consortium shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings
27 in this Software without prior written authorization from the X Consortium.
31 #if defined(FREEBSD) || defined(MACOSX)
32 #include <sys/types.h>
40 #ifdef _MSC_VER /* Define ssize_t */
43 #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86))
51 typedef __int64 ssize_t
;
53 typedef _W64
int ssize_t
;
62 #define sigvec sigvector
65 #ifdef X_POSIX_C_SOURCE
66 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
68 #undef _POSIX_C_SOURCE
70 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
89 static char *ProgramName
;
91 #define OBJSUFFIX ".obj"
92 #define INCLUDEDIR "."
94 char *directives
[] = {
114 #include "imakemdep.h" /* from config sources */
117 /******* function declarations ********/
118 /******* added by -Wall project *******/
119 static void redirect(char * makefile
);
121 struct inclist inclist
[ MAXFILES
];
122 struct inclist
*inclistp
= inclist
;
124 static struct symhash
*maininclist
= NULL
;
126 static char *filelist
[ MAXFILES
];
127 char *includedirs
[ MAXDIRS
+ 1 ];
128 char *objprefix
= "";
129 char *objsuffix
= OBJSUFFIX
;
130 static char *startat
= "# DO NOT DELETE";
131 boolean printed
= FALSE
;
132 boolean verbose
= FALSE
;
133 boolean show_where_not
= FALSE
;
134 boolean warn_multiple
= FALSE
; /* Warn on multiple includes of same file */
137 #ifdef SIGNALRETURNSINT
145 fatalerr ("got signal %d\n", sig
);
148 #if (defined(i386) && defined(SYSV)) || defined(_WIN32)
153 #ifndef _POSIX_SOURCE
154 #define sigaction sigvec
155 #define sa_handler sv_handler
156 #define sa_mask sv_mask
157 #define sa_flags sv_flags
159 static struct sigaction sig_act
;
162 static boolean native_win_slashes
= FALSE
;
164 int main(int argc
, char **argv
)
166 char **fp
= filelist
;
167 char **incp
= includedirs
;
170 char *makefile
= NULL
;
171 struct filepointer
*filecontent
;
172 struct pair
*psymp
= predefs
;
173 char *endmarker
= NULL
;
174 char *defincdir
= NULL
;
175 struct IncludesCollection
* incCollection
;
177 ProgramName
= argv
[0];
179 while (psymp
->p_name
)
181 hash_define(psymp
->p_name
, psymp
->p_value
, &maininclist
);
184 if (argc
== 2 && argv
[1][0] == '@') {
190 char quotechar
= '\0';
193 if ((afd
= open(argv
[1]+1, O_RDONLY
)) < 0)
194 fatalerr("cannot open \"%s\"\n", argv
[1]+1);
195 (void)fstat(afd
, &ast
);
196 args
= (char *)malloc(ast
.st_size
+ 1);
197 if ((ast
.st_size
= read(afd
, args
, (size_t) ast
.st_size
)) < 0)
198 fatalerr("failed to read %s\n", argv
[1]+1);
199 args
[ast
.st_size
] = '\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
= "--";
250 if (argv
[0][2] == '\0') {
254 for (p
=argv
[0] + 2; *p
; p
++)
259 define(argv
[0] + 2, &maininclist
);
262 if (incp
>= includedirs
+ MAXDIRS
)
263 fatalerr("Too many -I flags.\n");
265 if (**(incp
-1) == '\0') {
266 *(incp
-1) = *(++argv
);
271 defincdir
= argv
[0]+2;
273 /* do not use if endmarker processing */
277 if (endmarker
) break;
278 if (argv
[0][2] == '\0') {
284 // Use "-n" switch to generate dependencies with windows-native slash style
285 native_win_slashes
= TRUE
;
288 if (endmarker
) break;
289 if (argv
[0][2] == '\0') {
294 objsuffix
= argv
[0]+2;
297 if (endmarker
) break;
298 if (argv
[0][2] == '\0') {
303 objprefix
= argv
[0]+2;
306 if (endmarker
) break;
310 _debugmask
= atoi(argv
[0]+2);
314 if (endmarker
) break;
316 if (*startat
== '\0') {
321 fatalerr("-s flag's value should start %s\n",
325 if (endmarker
) break;
326 makefile
= argv
[0]+2;
327 if (*makefile
== '\0') {
328 makefile
= *(++argv
);
334 warn_multiple
= TRUE
;
337 /* Ignore -O, -g so we can just pass ${CFLAGS} to
344 if (endmarker
) break;
345 warning("ignoring option %s\n", argv
[0]);
349 convert_slashes(objprefix
);
350 objprefix
= append_slash(objprefix
);
354 if (incp
>= includedirs
+ MAXDIRS
)
355 fatalerr("Too many -I flags.\n");
358 if (incp
>= includedirs
+ MAXDIRS
)
359 fatalerr("Too many -I flags.\n");
360 *incp
++ = INCLUDEDIR
;
362 if (incp
>= includedirs
+ MAXDIRS
)
363 fatalerr("Too many -I flags.\n");
364 *incp
++ = POSTINCDIR
;
366 } else if (*defincdir
) {
367 if (incp
>= includedirs
+ MAXDIRS
)
368 fatalerr("Too many -I flags.\n");
378 /* should really reset SIGINT to SIG_IGN if it was. */
380 signal (SIGHUP
, catch);
382 signal (SIGINT
, catch);
384 signal (SIGQUIT
, catch);
386 signal (SIGILL
, catch);
388 signal (SIGBUS
, catch);
390 signal (SIGSEGV
, catch);
392 signal (SIGSYS
, catch);
394 signal (SIGFPE
, catch);
396 sig_act
.sa_handler
= catch;
398 sigemptyset(&sig_act
.sa_mask
);
399 sigaddset(&sig_act
.sa_mask
, SIGINT
);
400 sigaddset(&sig_act
.sa_mask
, SIGQUIT
);
402 sigaddset(&sig_act
.sa_mask
, SIGBUS
);
404 sigaddset(&sig_act
.sa_mask
, SIGILL
);
405 sigaddset(&sig_act
.sa_mask
, SIGSEGV
);
406 sigaddset(&sig_act
.sa_mask
, SIGHUP
);
407 sigaddset(&sig_act
.sa_mask
, SIGPIPE
);
409 sigaddset(&sig_act
.sa_mask
, SIGSYS
);
412 sig_act
.sa_mask
= ((1<<(SIGINT
-1))
425 #endif /* _POSIX_SOURCE */
426 sig_act
.sa_flags
= 0;
427 sigaction(SIGHUP
, &sig_act
, (struct sigaction
*)0);
428 sigaction(SIGINT
, &sig_act
, (struct sigaction
*)0);
429 sigaction(SIGQUIT
, &sig_act
, (struct sigaction
*)0);
430 sigaction(SIGILL
, &sig_act
, (struct sigaction
*)0);
432 sigaction(SIGBUS
, &sig_act
, (struct sigaction
*)0);
434 sigaction(SIGSEGV
, &sig_act
, (struct sigaction
*)0);
436 sigaction(SIGSYS
, &sig_act
, (struct sigaction
*)0);
441 * now peruse through the list of files.
443 incCollection
= create_IncludesCollection();
445 for(fp
=filelist
; *fp
; fp
++) {
446 struct symhash
*includes
;
447 filecontent
= getfile(*fp
);
448 ip
= newinclude(*fp
, (char *)NULL
);
450 includes
= hash_copy( maininclist
);
451 find_includes(filecontent
, ip
, ip
, 0, FALSE
, incCollection
, includes
);
452 hash_free( includes
);
454 freefile(filecontent
);
455 recursive_pr_include(ip
, ip
->i_file
, base_name(*fp
));
457 fwrite("\n\n", 2, 1, stdout
);
458 recursive_pr_dummy(ip
, ip
->i_file
);
464 delete_IncludesCollection(incCollection
);
469 struct filepointer
*getfile(char *file
)
472 struct filepointer
*content
;
476 unsigned malloc_size
;
478 content
= (struct filepointer
*)malloc(sizeof(struct filepointer
));
479 if ((fd
= open(file
, O_RDONLY
)) < 0) {
480 warning("makedepend: Cannot open file \"%s\"\n", file
);
481 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
482 *content
->f_p
= '\0';
485 (void)fstat(fd
, &st
);
487 size_backup
= st
.st_size
;
488 malloc_size
= size_backup
;
489 /* Since off_t usually is larger than unsigned, need to test for
492 if ( (off_t
)malloc_size
!= size_backup
)
495 warning("makedepend: File \"%s\" is too large.\n", file
);
496 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
497 *content
->f_p
= '\0';
501 content
->f_base
= (char *)malloc(malloc_size
+1);
502 if (content
->f_base
== NULL
)
503 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file
);
504 if ((bytes_read
= read(fd
, content
->f_base
, malloc_size
)) < 0)
505 if ( st
.st_mode
& S_IFREG
)
506 fatalerr("makedepend: Failed to read file \"%s\"\n", file
);
509 content
->f_p
= content
->f_base
;
510 content
->f_end
= content
->f_base
+ bytes_read
;
511 *content
->f_end
= '\0';
516 void freefile(struct filepointer
*fp
)
522 char *copy(char const *str
)
524 char *p
= (char *)malloc(strlen(str
) + 1);
525 assert(p
); // Don't handle OOM conditions
530 int match(char const *str
, char **list
)
534 for (i
=0; *list
; i
++, list
++)
535 if (strcmp(str
, *list
) == 0)
541 * Get the next line. We only return lines beginning with '#' since that
542 * is all this program is ever interested in.
544 char *get_line(struct filepointer
*filep
)
546 char *p
, /* walking pointer */
547 *eof
, /* end of file pointer */
548 *bol
; /* beginning of line pointer */
549 int lineno
; /* line number */
555 lineno
= filep
->f_line
;
557 for(bol
= p
--; ++p
< eof
; ) {
558 if (*p
== '/' && *(p
+1) == '*') { /* consume comments */
562 if (*p
== '*' && *(p
+1) == '/') {
573 else if (*p
== '/' && *(p
+1) == '/') { /* consume comments */
576 while (*p
&& *p
!= '\n')
583 else if (*p
== '\\') {
584 if (*(p
+1) == '\n') {
590 else if (*p
== '\n') {
596 /* punt lines with just # (yacc generated) */
598 *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++);
608 filep
->f_line
= lineno
;
613 * Strip the file name down to what we want to see in the Makefile.
614 * It will have objprefix and objsuffix around it.
616 char *base_name(char *file
)
621 for(p
=file
+strlen(file
); p
>file
&& *p
!= '.'; p
--) ;
627 if ( *p
== '/' || *p
== '\\') {
636 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
637 int rename (char *from
, char *to
)
640 if (link (from
, to
) == 0) {
649 void redirect(char *makefile
)
652 fdout
= makefile
? freopen(makefile
, "wb", stdout
) : NULL
; // binary mode please
654 fatalerr("cannot open \"%s\"\n", makefile
? makefile
: "<NULL>");
658 __attribute__ ((format (printf
, 1, 2)))
660 void fatalerr(char *msg
, ...)
663 fprintf(stderr
, "%s: error: ", ProgramName
);
665 vfprintf(stderr
, msg
, args
);
671 __attribute__ ((format (printf
, 1, 2)))
673 void warning(char const *msg
, ...)
675 #ifdef DEBUG_MKDEPEND
677 fprintf(stderr
, "%s: warning: ", ProgramName
);
679 vfprintf(stderr
, msg
, args
);
683 #endif /* DEBUG_MKDEPEND */
687 __attribute__ ((format (printf
, 1, 2)))
689 void warning1(char const *msg
, ...)
691 #ifdef DEBUG_MKDEPEND
694 vfprintf(stderr
, msg
, args
);
698 #endif /* DEBUG_MKDEPEND */
701 void convert_slashes(char *path
)
705 * Convert backslashes to slashes
708 if (native_win_slashes
) {
709 for (ptr
= (char*)path
; *ptr
; ++ptr
)
713 for (ptr
= (char*)path
; *ptr
; ++ptr
)
722 char* append_slash(char *path
)
725 const char cLastChar
= path
[strlen(path
) - 1];
726 if (cLastChar
== '/' || cLastChar
== '\\') {
729 new_string
= (char*)malloc(sizeof(char) * (strlen(path
) + 2));
730 assert(new_string
); // Don't handle OOM conditions
731 strcpy(new_string
, path
);
732 if (native_win_slashes
)
733 strcat(new_string
, "\\");
735 strcat(new_string
, "/");
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */