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)
90 static char *ProgramName
;
92 #define OBJSUFFIX ".obj"
93 #define INCLUDEDIR "."
95 char *directives
[] = {
115 #include "imakemdep.h" /* from config sources */
118 /******* function declarations ********/
119 /******* added by -Wall project *******/
120 static void redirect(char * makefile
);
122 struct inclist inclist
[ MAXFILES
];
123 struct inclist
*inclistp
= inclist
;
125 static struct symhash
*maininclist
= NULL
;
127 static char *filelist
[ MAXFILES
];
128 char *includedirs
[ MAXDIRS
+ 1 ];
129 char *objprefix
= "";
130 char *objsuffix
= OBJSUFFIX
;
131 static char *startat
= "# DO NOT DELETE";
132 boolean printed
= FALSE
;
133 boolean verbose
= FALSE
;
134 boolean show_where_not
= FALSE
;
135 boolean warn_multiple
= FALSE
; /* Warn on multiple includes of same file */
138 #ifdef SIGNALRETURNSINT
146 fatalerr ("got signal %d\n", sig
);
149 #if (defined(i386) && defined(SYSV)) || defined(_WIN32)
154 #ifndef _POSIX_SOURCE
155 #define sigaction sigvec
156 #define sa_handler sv_handler
157 #define sa_mask sv_mask
158 #define sa_flags sv_flags
160 static struct sigaction sig_act
;
163 static boolean native_win_slashes
= FALSE
;
165 int main(int argc
, char **argv
)
167 char **fp
= filelist
;
168 char **incp
= includedirs
;
171 char *makefile
= NULL
;
172 struct filepointer
*filecontent
;
173 struct pair
*psymp
= predefs
;
174 char *endmarker
= NULL
;
175 char *defincdir
= NULL
;
176 struct IncludesCollection
* incCollection
;
178 ProgramName
= argv
[0];
180 while (psymp
->p_name
)
182 hash_define(psymp
->p_name
, psymp
->p_value
, &maininclist
);
185 if (argc
== 2 && argv
[1][0] == '@') {
191 char quotechar
= '\0';
194 if ((afd
= open(argv
[1]+1, O_RDONLY
)) < 0)
195 fatalerr("cannot open \"%s\"\n", argv
[1]+1);
196 (void)fstat(afd
, &ast
);
197 args
= (char *)malloc(ast
.st_size
+ 1);
201 if ((ast
.st_size
= read(afd
, args
, (size_t) ast
.st_size
)) < 0)
202 fatalerr("failed to read %s\n", argv
[1]+1);
203 args
[ast
.st_size
] = '\0';
205 for (p
= args
; *p
; p
++) {
207 if (quotechar
== '\\'
208 || (*p
== quotechar
&& p
[-1] != '\\'))
221 if (p
> args
&& p
[-1])
228 nargv
= (char **)malloc(nargc
* sizeof(char *));
231 for (p
= args
; argc
< nargc
; p
+= strlen(p
) + 1)
232 if (*p
) nargv
[argc
++] = p
;
235 for(argc
--, argv
++; argc
; argc
--, argv
++) {
236 /* if looking for endmarker then check before parsing */
237 if (endmarker
&& strcmp (endmarker
, *argv
) == 0) {
242 /* treat +thing as an option for C++ */
243 if (endmarker
&& **argv
== '+')
250 endmarker
= &argv
[0][2];
251 if (endmarker
[0] == '\0') endmarker
= "--";
254 if (argv
[0][2] == '\0') {
258 for (p
=argv
[0] + 2; *p
; p
++)
263 define(argv
[0] + 2, &maininclist
);
266 if (incp
>= includedirs
+ MAXDIRS
)
267 fatalerr("Too many -I flags.\n");
269 if (**(incp
-1) == '\0') {
270 *(incp
-1) = *(++argv
);
275 defincdir
= argv
[0]+2;
277 /* do not use if endmarker processing */
281 if (endmarker
) break;
282 if (argv
[0][2] == '\0') {
288 // Use "-n" switch to generate dependencies with windows-native slash style
289 native_win_slashes
= TRUE
;
292 if (endmarker
) break;
293 if (argv
[0][2] == '\0') {
298 objsuffix
= argv
[0]+2;
301 if (endmarker
) break;
302 if (argv
[0][2] == '\0') {
307 objprefix
= argv
[0]+2;
310 if (endmarker
) break;
314 _debugmask
= atoi(argv
[0]+2);
318 if (endmarker
) break;
320 if (*startat
== '\0') {
325 fatalerr("-s flag's value should start %s\n",
329 if (endmarker
) break;
330 makefile
= argv
[0]+2;
331 if (*makefile
== '\0') {
332 makefile
= *(++argv
);
338 warn_multiple
= TRUE
;
341 /* Ignore -O, -g so we can just pass ${CFLAGS} to
348 if (endmarker
) break;
349 warning("ignoring option %s\n", argv
[0]);
353 convert_slashes(objprefix
);
354 objprefix
= append_slash(objprefix
);
358 if (incp
>= includedirs
+ MAXDIRS
)
359 fatalerr("Too many -I flags.\n");
362 if (incp
>= includedirs
+ MAXDIRS
)
363 fatalerr("Too many -I flags.\n");
364 *incp
++ = INCLUDEDIR
;
366 if (incp
>= includedirs
+ MAXDIRS
)
367 fatalerr("Too many -I flags.\n");
368 *incp
++ = POSTINCDIR
;
370 } else if (*defincdir
) {
371 if (incp
>= includedirs
+ MAXDIRS
)
372 fatalerr("Too many -I flags.\n");
382 /* should really reset SIGINT to SIG_IGN if it was. */
384 signal (SIGHUP
, catch);
386 signal (SIGINT
, catch);
388 signal (SIGQUIT
, catch);
390 signal (SIGILL
, catch);
392 signal (SIGBUS
, catch);
394 signal (SIGSEGV
, catch);
396 signal (SIGSYS
, catch);
398 signal (SIGFPE
, catch);
400 sig_act
.sa_handler
= catch;
402 sigemptyset(&sig_act
.sa_mask
);
403 sigaddset(&sig_act
.sa_mask
, SIGINT
);
404 sigaddset(&sig_act
.sa_mask
, SIGQUIT
);
406 sigaddset(&sig_act
.sa_mask
, SIGBUS
);
408 sigaddset(&sig_act
.sa_mask
, SIGILL
);
409 sigaddset(&sig_act
.sa_mask
, SIGSEGV
);
410 sigaddset(&sig_act
.sa_mask
, SIGHUP
);
411 sigaddset(&sig_act
.sa_mask
, SIGPIPE
);
413 sigaddset(&sig_act
.sa_mask
, SIGSYS
);
416 sig_act
.sa_mask
= ((1<<(SIGINT
-1))
429 #endif /* _POSIX_SOURCE */
430 sig_act
.sa_flags
= 0;
431 sigaction(SIGHUP
, &sig_act
, (struct sigaction
*)0);
432 sigaction(SIGINT
, &sig_act
, (struct sigaction
*)0);
433 sigaction(SIGQUIT
, &sig_act
, (struct sigaction
*)0);
434 sigaction(SIGILL
, &sig_act
, (struct sigaction
*)0);
436 sigaction(SIGBUS
, &sig_act
, (struct sigaction
*)0);
438 sigaction(SIGSEGV
, &sig_act
, (struct sigaction
*)0);
440 sigaction(SIGSYS
, &sig_act
, (struct sigaction
*)0);
445 * now peruse through the list of files.
447 incCollection
= create_IncludesCollection();
449 for(fp
=filelist
; *fp
; fp
++) {
450 struct symhash
*includes
;
451 filecontent
= getfile(*fp
);
452 ip
= newinclude(*fp
, (char *)NULL
);
454 includes
= hash_copy( maininclist
);
455 find_includes(filecontent
, ip
, ip
, 0, FALSE
, incCollection
, includes
);
456 hash_free( includes
);
458 freefile(filecontent
);
459 recursive_pr_include(ip
, ip
->i_file
, base_name(*fp
));
461 fwrite("\n\n", 2, 1, stdout
);
462 recursive_pr_dummy(ip
, ip
->i_file
);
468 delete_IncludesCollection(incCollection
);
473 struct filepointer
*getfile(char *file
)
476 struct filepointer
*content
;
480 unsigned malloc_size
;
482 content
= (struct filepointer
*)malloc(sizeof(struct filepointer
));
483 if ((fd
= open(file
, O_RDONLY
)) < 0) {
484 warning("makedepend: Cannot open file \"%s\"\n", file
);
485 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
486 *content
->f_p
= '\0';
489 (void)fstat(fd
, &st
);
491 size_backup
= st
.st_size
;
492 malloc_size
= size_backup
;
493 /* Since off_t usually is larger than unsigned, need to test for
496 if ( (off_t
)malloc_size
!= size_backup
)
499 warning("makedepend: File \"%s\" is too large.\n", file
);
500 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
501 *content
->f_p
= '\0';
505 content
->f_base
= (char *)malloc(malloc_size
+1);
506 if (content
->f_base
== NULL
)
507 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file
);
508 if ((bytes_read
= read(fd
, content
->f_base
, malloc_size
)) < 0)
509 if ( st
.st_mode
& S_IFREG
)
510 fatalerr("makedepend: Failed to read file \"%s\"\n", file
);
513 content
->f_p
= content
->f_base
;
514 content
->f_end
= content
->f_base
+ bytes_read
;
515 *content
->f_end
= '\0';
520 void freefile(struct filepointer
*fp
)
526 char *copy(char const *str
)
528 char *p
= (char *)malloc(strlen(str
) + 1);
529 assert(p
); // Don't handle OOM conditions
534 int match(char const *str
, char **list
)
538 for (i
=0; *list
; i
++, list
++)
539 if (strcmp(str
, *list
) == 0)
545 * Get the next line. We only return lines beginning with '#' since that
546 * is all this program is ever interested in.
548 char *get_line(struct filepointer
*filep
)
550 char *p
, /* walking pointer */
551 *eof
, /* end of file pointer */
552 *bol
; /* beginning of line pointer */
553 int lineno
; /* line number */
559 lineno
= filep
->f_line
;
561 for(bol
= p
--; ++p
< eof
; ) {
562 if (*p
== '/' && *(p
+1) == '*') { /* consume comments */
566 if (*p
== '*' && *(p
+1) == '/') {
577 else if (*p
== '/' && *(p
+1) == '/') { /* consume comments */
580 while (*p
&& *p
!= '\n')
587 else if (*p
== '\\') {
588 if (*(p
+1) == '\n') {
594 else if (*p
== '\n') {
600 /* punt lines with just # (yacc generated) */
602 *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++);
612 filep
->f_line
= lineno
;
617 * Strip the file name down to what we want to see in the Makefile.
618 * It will have objprefix and objsuffix around it.
620 char *base_name(char *file
)
625 for(p
=file
+strlen(file
); p
>file
&& *p
!= '.'; p
--) ;
631 if ( *p
== '/' || *p
== '\\') {
640 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
641 int rename (char *from
, char *to
)
644 if (link (from
, to
) == 0) {
653 void redirect(char *makefile
)
656 fdout
= makefile
? freopen(makefile
, "wb", stdout
) : NULL
; // binary mode please
658 fatalerr("cannot open \"%s\"\n", makefile
? makefile
: "<NULL>");
662 __attribute__ ((format (printf
, 1, 2)))
664 void fatalerr(char *msg
, ...)
667 fprintf(stderr
, "%s: error: ", ProgramName
);
669 vfprintf(stderr
, msg
, args
);
675 __attribute__ ((format (printf
, 1, 2)))
677 void warning(char const *msg
, ...)
679 #ifdef DEBUG_MKDEPEND
681 fprintf(stderr
, "%s: warning: ", ProgramName
);
683 vfprintf(stderr
, msg
, args
);
687 #endif /* DEBUG_MKDEPEND */
691 __attribute__ ((format (printf
, 1, 2)))
693 void warning1(char const *msg
, ...)
695 #ifdef DEBUG_MKDEPEND
698 vfprintf(stderr
, msg
, args
);
702 #endif /* DEBUG_MKDEPEND */
705 void convert_slashes(char *path
)
709 * Convert backslashes to slashes
712 if (native_win_slashes
) {
713 for (ptr
= (char*)path
; *ptr
; ++ptr
)
717 for (ptr
= (char*)path
; *ptr
; ++ptr
)
726 char* append_slash(char *path
)
729 const char cLastChar
= path
[strlen(path
) - 1];
730 if (cLastChar
== '/' || cLastChar
== '\\') {
733 new_string
= (char*)malloc(sizeof(char) * (strlen(path
) + 2));
734 assert(new_string
); // Don't handle OOM conditions
735 strcpy(new_string
, path
);
736 if (native_win_slashes
)
737 strcat(new_string
, "\\");
739 strcat(new_string
, "/");
744 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */