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)) && _MSC_VER >= 1300
51 typedef __int64 ssize_t
;
53 typedef _W64
int ssize_t
;
61 #define sigvec sigvector
64 #ifdef X_POSIX_C_SOURCE
65 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
67 #undef _POSIX_C_SOURCE
69 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
90 #define OBJSUFFIX ".obj"
91 #define INCLUDEDIR "."
93 char *directives
[] = {
113 #include "imakemdep.h" /* from config sources */
116 /******* function declarations ********/
117 /******* added by -Wall project *******/
118 void redirect(char * makefile
);
120 struct inclist inclist
[ MAXFILES
],
123 struct symhash
*maininclist
= NULL
;
125 char *filelist
[ MAXFILES
];
126 char *includedirs
[ MAXDIRS
+ 1 ];
127 char *notdotdot
[ MAXDIRS
];
128 char *objprefix
= "";
129 char *objsuffix
= OBJSUFFIX
;
130 char *startat
= "# DO NOT DELETE";
132 boolean append
= FALSE
;
133 boolean printed
= FALSE
;
134 boolean verbose
= FALSE
;
135 boolean show_where_not
= FALSE
;
136 boolean warn_multiple
= FALSE
; /* Warn on multiple includes of same file */
139 #ifdef SIGNALRETURNSINT
147 fatalerr ("got signal %d\n", sig
);
150 #if (defined(i386) && defined(SYSV)) || defined(WIN32)
155 #ifndef _POSIX_SOURCE
156 #define sigaction sigvec
157 #define sa_handler sv_handler
158 #define sa_mask sv_mask
159 #define sa_flags sv_flags
161 struct sigaction sig_act
;
164 boolean native_win_slashes
= FALSE
;
166 int main(int argc
, char **argv
)
168 char **fp
= filelist
;
169 char **incp
= includedirs
;
172 char *makefile
= NULL
;
173 struct filepointer
*filecontent
;
174 struct pair
*psymp
= predefs
;
175 char *endmarker
= NULL
;
176 char *defincdir
= NULL
;
177 struct IncludesCollection
* incCollection
;
179 ProgramName
= argv
[0];
181 while (psymp
->p_name
)
183 hash_define(psymp
->p_name
, psymp
->p_value
, &maininclist
);
186 if (argc
== 2 && argv
[1][0] == '@') {
192 char quotechar
= '\0';
195 if ((afd
= open(argv
[1]+1, O_RDONLY
)) < 0)
196 fatalerr("cannot open \"%s\"\n", argv
[1]+1);
197 (void)fstat(afd
, &ast
);
198 args
= (char *)malloc(ast
.st_size
+ 1);
199 if ((ast
.st_size
= read(afd
, args
, (size_t) ast
.st_size
)) < 0)
200 fatalerr("failed to read %s\n", argv
[1]+1);
201 args
[ast
.st_size
] = '\0';
203 for (p
= args
; *p
; p
++) {
205 if (quotechar
== '\\'
206 || (*p
== quotechar
&& p
[-1] != '\\'))
219 if (p
> args
&& p
[-1])
226 nargv
= (char **)malloc(nargc
* sizeof(char *));
229 for (p
= args
; argc
< nargc
; p
+= strlen(p
) + 1)
230 if (*p
) nargv
[argc
++] = p
;
233 for(argc
--, argv
++; argc
; argc
--, argv
++) {
234 /* if looking for endmarker then check before parsing */
235 if (endmarker
&& strcmp (endmarker
, *argv
) == 0) {
240 /* treat +thing as an option for C++ */
241 if (endmarker
&& **argv
== '+')
248 endmarker
= &argv
[0][2];
249 if (endmarker
[0] == '\0') endmarker
= "--";
252 if (argv
[0][2] == '\0') {
256 for (p
=argv
[0] + 2; *p
; p
++)
261 define(argv
[0] + 2, &maininclist
);
264 if (incp
>= includedirs
+ MAXDIRS
)
265 fatalerr("Too many -I flags.\n");
267 if (**(incp
-1) == '\0') {
268 *(incp
-1) = *(++argv
);
273 defincdir
= argv
[0]+2;
275 /* do not use if endmarker processing */
277 if (endmarker
) break;
281 if (endmarker
) break;
282 if (argv
[0][2] == '\0') {
285 width
= atoi(argv
[0]);
287 width
= atoi(argv
[0]+2);
290 // Use "-n" switch to generate dependencies with windows-native slash style
291 native_win_slashes
= TRUE
;
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 (endmarker
) break;
351 warning("ignoring option %s\n", argv
[0]);
355 convert_slashes(objprefix
);
356 objprefix
= append_slash(objprefix
);
360 if (incp
>= includedirs
+ MAXDIRS
)
361 fatalerr("Too many -I flags.\n");
364 if (incp
>= includedirs
+ MAXDIRS
)
365 fatalerr("Too many -I flags.\n");
366 *incp
++ = INCLUDEDIR
;
368 if (incp
>= includedirs
+ MAXDIRS
)
369 fatalerr("Too many -I flags.\n");
370 *incp
++ = POSTINCDIR
;
372 } else if (*defincdir
) {
373 if (incp
>= includedirs
+ MAXDIRS
)
374 fatalerr("Too many -I flags.\n");
384 /* should really reset SIGINT to SIG_IGN if it was. */
386 signal (SIGHUP
, catch);
388 signal (SIGINT
, catch);
390 signal (SIGQUIT
, catch);
392 signal (SIGILL
, catch);
394 signal (SIGBUS
, catch);
396 signal (SIGSEGV
, catch);
398 signal (SIGSYS
, catch);
400 signal (SIGFPE
, catch);
402 sig_act
.sa_handler
= catch;
404 sigemptyset(&sig_act
.sa_mask
);
405 sigaddset(&sig_act
.sa_mask
, SIGINT
);
406 sigaddset(&sig_act
.sa_mask
, SIGQUIT
);
408 sigaddset(&sig_act
.sa_mask
, SIGBUS
);
410 sigaddset(&sig_act
.sa_mask
, SIGILL
);
411 sigaddset(&sig_act
.sa_mask
, SIGSEGV
);
412 sigaddset(&sig_act
.sa_mask
, SIGHUP
);
413 sigaddset(&sig_act
.sa_mask
, SIGPIPE
);
415 sigaddset(&sig_act
.sa_mask
, SIGSYS
);
418 sig_act
.sa_mask
= ((1<<(SIGINT
-1))
431 #endif /* _POSIX_SOURCE */
432 sig_act
.sa_flags
= 0;
433 sigaction(SIGHUP
, &sig_act
, (struct sigaction
*)0);
434 sigaction(SIGINT
, &sig_act
, (struct sigaction
*)0);
435 sigaction(SIGQUIT
, &sig_act
, (struct sigaction
*)0);
436 sigaction(SIGILL
, &sig_act
, (struct sigaction
*)0);
438 sigaction(SIGBUS
, &sig_act
, (struct sigaction
*)0);
440 sigaction(SIGSEGV
, &sig_act
, (struct sigaction
*)0);
442 sigaction(SIGSYS
, &sig_act
, (struct sigaction
*)0);
447 * now peruse through the list of files.
449 incCollection
= create_IncludesCollection();
451 for(fp
=filelist
; *fp
; fp
++) {
452 struct symhash
*includes
;
453 filecontent
= getfile(*fp
);
454 ip
= newinclude(*fp
, (char *)NULL
);
456 includes
= hash_copy( maininclist
);
457 find_includes(filecontent
, ip
, ip
, 0, FALSE
, incCollection
, includes
);
458 hash_free( includes
);
460 freefile(filecontent
);
461 recursive_pr_include(ip
, ip
->i_file
, base_name(*fp
));
463 fwrite("\n\n", 2, 1, stdout
);
464 recursive_pr_dummy(ip
, ip
->i_file
);
470 delete_IncludesCollection(incCollection
);
475 struct filepointer
*getfile(char *file
)
478 struct filepointer
*content
;
482 unsigned malloc_size
;
484 content
= (struct filepointer
*)malloc(sizeof(struct filepointer
));
485 if ((fd
= open(file
, O_RDONLY
)) < 0) {
486 warning("makedepend: Cannot open file \"%s\"\n", file
);
487 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
488 *content
->f_p
= '\0';
491 (void)fstat(fd
, &st
);
493 size_backup
= st
.st_size
;
494 malloc_size
= size_backup
;
495 /* Since off_t usually is larger than unsigned, need to test for
498 if ( (off_t
)malloc_size
!= size_backup
)
501 warning("makedepend: File \"%s\" is too large.\n", file
);
502 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
503 *content
->f_p
= '\0';
507 content
->f_base
= (char *)malloc(malloc_size
+1);
508 if (content
->f_base
== NULL
)
509 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file
);
510 if ((bytes_read
= read(fd
, content
->f_base
, malloc_size
)) < 0)
511 if ( st
.st_mode
& S_IFREG
)
512 fatalerr("makedepend: Failed to read file \"%s\"\n", file
);
515 content
->f_len
= bytes_read
+1;
516 content
->f_p
= content
->f_base
;
517 content
->f_end
= content
->f_base
+ bytes_read
;
518 *content
->f_end
= '\0';
523 void freefile(struct filepointer
*fp
)
529 char *copy(char *str
)
531 char *p
= (char *)malloc(strlen(str
) + 1);
537 int match(char *str
, char **list
)
541 for (i
=0; *list
; i
++, list
++)
542 if (strcmp(str
, *list
) == 0)
548 * Get the next line. We only return lines beginning with '#' since that
549 * is all this program is ever interested in.
551 char *get_line(struct filepointer
*filep
)
553 char *p
, /* walking pointer */
554 *eof
, /* end of file pointer */
555 *bol
; /* beginning of line pointer */
556 int lineno
; /* line number */
562 lineno
= filep
->f_line
;
564 for(bol
= p
--; ++p
< eof
; ) {
565 if (*p
== '/' && *(p
+1) == '*') { /* consume comments */
566 *p
++ = ' ', *p
++ = ' ';
568 if (*p
== '*' && *(p
+1) == '/') {
569 *p
++ = ' ', *p
= ' ';
578 else if (*p
== '/' && *(p
+1) == '/') { /* consume comments */
579 *p
++ = ' ', *p
++ = ' ';
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>");
661 void fatalerr(char *msg
, ...)
664 fprintf(stderr
, "%s: error: ", ProgramName
);
666 vfprintf(stderr
, msg
, args
);
671 void warning(char *msg
, ...)
673 #ifdef DEBUG_MKDEPEND
675 fprintf(stderr
, "%s: warning: ", ProgramName
);
677 vfprintf(stderr
, msg
, args
);
681 #endif /* DEBUG_MKDEPEND */
684 void warning1(char *msg
, ...)
686 #ifdef DEBUG_MKDEPEND
689 vfprintf(stderr
, msg
, args
);
693 #endif /* DEBUG_MKDEPEND */
696 void convert_slashes(char *path
)
700 * Convert backslashes to slashes
703 if (native_win_slashes
) {
704 for (ptr
= (char*)path
; *ptr
; ++ptr
)
708 for (ptr
= (char*)path
; *ptr
; ++ptr
)
717 char* append_slash(char *path
)
720 const char cLastChar
= path
[strlen(path
) - 1];
721 if (cLastChar
== '/' || cLastChar
== '\\') {
724 new_string
= (char*)malloc(sizeof(char) * (strlen(path
) + 2));
725 strcpy(new_string
, path
);
726 if (native_win_slashes
)
727 strcat(new_string
, "\\");
729 strcat(new_string
, "/");
734 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */