1 /* $XConsortium: main.c,v 1.84 94/11/30 16:10:44 kaleb Exp $ */
2 /* $XFree86: xc/config/makedepend/main.c,v 3.4 1995/07/15 14:53:49 dawes Exp $ */
5 Copyright (c) 1993, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
30 #if defined(FREEBSD) || defined(MACOSX)
31 #include <sys/types.h>
35 #ifdef _MSC_VER /* Define ssize_t */
38 #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
46 typedef __int64 ssize_t
;
48 typedef _W64
int ssize_t
;
56 #define sigvec sigvector
59 #ifdef X_POSIX_C_SOURCE
60 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
62 #undef _POSIX_C_SOURCE
64 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
73 #if NeedVarargsPrototypes
87 #define OBJSUFFIX ".obj"
88 #define INCLUDEDIR "."
90 char *directives
[] = {
110 #include "imakemdep.h" /* from config sources */
113 /******* function declarations ********/
114 /******* added by -Wall project *******/
115 void freefile(struct filepointer
* fp
);
116 void redirect(char * line
, char * makefile
);
118 struct inclist inclist
[ MAXFILES
],
121 struct symhash
*maininclist
= NULL
;
123 char *filelist
[ MAXFILES
];
124 char *includedirs
[ MAXDIRS
+ 1 ];
125 char *notdotdot
[ MAXDIRS
];
126 char *objprefix
= "";
127 char *objsuffix
= OBJSUFFIX
;
128 char *startat
= "# DO NOT DELETE";
130 boolean append
= FALSE
;
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
146 fatalerr ("got signal %d\n", sig
);
149 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(OS2) || defined(Lynx_22)
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 struct sigaction sig_act
;
163 boolean native_win_slashes
= FALSE
;
169 register char **fp
= filelist
;
170 register char **incp
= includedirs
;
172 register struct inclist
*ip
;
173 char *makefile
= NULL
;
174 struct filepointer
*filecontent
;
175 struct pair
*psymp
= predefs
;
176 char *endmarker
= NULL
;
177 char *defincdir
= NULL
;
178 struct IncludesCollection
* incCollection
;
180 ProgramName
= argv
[0];
182 while (psymp
->p_name
)
184 hash_define(psymp
->p_name
, psymp
->p_value
, &maininclist
);
187 if (argc
== 2 && argv
[1][0] == '@') {
193 char quotechar
= '\0';
196 if ((afd
= open(argv
[1]+1, O_RDONLY
)) < 0)
197 fatalerr("cannot open \"%s\"\n", argv
[1]+1);
199 args
= (char *)malloc(ast
.st_size
+ 1);
200 if ((ast
.st_size
= read(afd
, args
, (size_t) ast
.st_size
)) < 0)
201 fatalerr("failed to read %s\n", argv
[1]+1);
202 args
[ast
.st_size
] = '\0';
204 for (p
= args
; *p
; p
++) {
206 if (quotechar
== '\\' ||
207 (*p
== quotechar
&& p
[-1] != '\\'))
220 if (p
> args
&& p
[-1])
227 nargv
= (char **)malloc(nargc
* sizeof(char *));
230 for (p
= args
; argc
< nargc
; p
+= strlen(p
) + 1)
231 if (*p
) nargv
[argc
++] = p
;
234 for(argc
--, argv
++; argc
; argc
--, argv
++) {
235 /* if looking for endmarker then check before parsing */
236 if (endmarker
&& strcmp (endmarker
, *argv
) == 0) {
241 /* treat +thing as an option for C++ */
242 if (endmarker
&& **argv
== '+')
249 endmarker
= &argv
[0][2];
250 if (endmarker
[0] == '\0') endmarker
= "--";
253 if (argv
[0][2] == '\0') {
257 for (p
=argv
[0] + 2; *p
; p
++)
262 define(argv
[0] + 2, &maininclist
);
265 if (incp
>= includedirs
+ MAXDIRS
)
266 fatalerr("Too many -I flags.\n");
268 if (**(incp
-1) == '\0') {
269 *(incp
-1) = *(++argv
);
274 defincdir
= argv
[0]+2;
276 /* do not use if endmarker processing */
278 if (endmarker
) break;
282 if (endmarker
) break;
283 if (argv
[0][2] == '\0') {
286 width
= atoi(argv
[0]);
288 width
= atoi(argv
[0]+2);
291 // Use "-n" switch to generate dependencies with windows-native slash style
292 native_win_slashes
= TRUE
;
295 if (endmarker
) break;
296 if (argv
[0][2] == '\0') {
301 objsuffix
= argv
[0]+2;
304 if (endmarker
) break;
305 if (argv
[0][2] == '\0') {
310 objprefix
= argv
[0]+2;
313 if (endmarker
) break;
317 _debugmask
= atoi(argv
[0]+2);
321 if (endmarker
) break;
323 if (*startat
== '\0') {
328 fatalerr("-s flag's value should start %s\n",
332 if (endmarker
) break;
333 makefile
= argv
[0]+2;
334 if (*makefile
== '\0') {
335 makefile
= *(++argv
);
341 warn_multiple
= TRUE
;
344 /* Ignore -O, -g so we can just pass ${CFLAGS} to
351 if (endmarker
) break;
352 /* fatalerr("unknown opt = %s\n", argv[0]); */
353 warning("ignoring option %s\n", argv
[0]);
357 convert_slashes(objprefix
);
358 objprefix
= append_slash(objprefix
);
362 if (incp
>= includedirs
+ MAXDIRS
)
363 fatalerr("Too many -I flags.\n");
366 if (incp
>= includedirs
+ MAXDIRS
)
367 fatalerr("Too many -I flags.\n");
368 *incp
++ = INCLUDEDIR
;
370 if (incp
>= includedirs
+ MAXDIRS
)
371 fatalerr("Too many -I flags.\n");
372 *incp
++ = POSTINCDIR
;
374 } else if (*defincdir
) {
375 if (incp
>= includedirs
+ MAXDIRS
)
376 fatalerr("Too many -I flags.\n");
380 redirect(startat
, makefile
);
386 /* should really reset SIGINT to SIG_IGN if it was. */
388 signal (SIGHUP
, catch);
390 signal (SIGINT
, catch);
392 signal (SIGQUIT
, catch);
394 signal (SIGILL
, catch);
396 signal (SIGBUS
, catch);
398 signal (SIGSEGV
, catch);
400 signal (SIGSYS
, catch);
402 signal (SIGFPE
, catch);
404 sig_act
.sa_handler
= catch;
406 sigemptyset(&sig_act
.sa_mask
);
407 sigaddset(&sig_act
.sa_mask
, SIGINT
);
408 sigaddset(&sig_act
.sa_mask
, SIGQUIT
);
410 sigaddset(&sig_act
.sa_mask
, SIGBUS
);
412 sigaddset(&sig_act
.sa_mask
, SIGILL
);
413 sigaddset(&sig_act
.sa_mask
, SIGSEGV
);
414 sigaddset(&sig_act
.sa_mask
, SIGHUP
);
415 sigaddset(&sig_act
.sa_mask
, SIGPIPE
);
417 sigaddset(&sig_act
.sa_mask
, SIGSYS
);
420 sig_act
.sa_mask
= ((1<<(SIGINT
-1))
433 #endif /* _POSIX_SOURCE */
434 sig_act
.sa_flags
= 0;
435 sigaction(SIGHUP
, &sig_act
, (struct sigaction
*)0);
436 sigaction(SIGINT
, &sig_act
, (struct sigaction
*)0);
437 sigaction(SIGQUIT
, &sig_act
, (struct sigaction
*)0);
438 sigaction(SIGILL
, &sig_act
, (struct sigaction
*)0);
440 sigaction(SIGBUS
, &sig_act
, (struct sigaction
*)0);
442 sigaction(SIGSEGV
, &sig_act
, (struct sigaction
*)0);
444 sigaction(SIGSYS
, &sig_act
, (struct sigaction
*)0);
449 * now peruse through the list of files.
451 incCollection
= create_IncludesCollection();
453 for(fp
=filelist
; *fp
; fp
++) {
454 struct symhash
*includes
;
455 filecontent
= getfile(*fp
);
456 ip
= newinclude(*fp
, (char *)NULL
);
458 includes
= hash_copy( maininclist
);
459 find_includes(filecontent
, ip
, ip
, 0, FALSE
, incCollection
, includes
);
460 hash_free( includes
);
462 freefile(filecontent
);
463 recursive_pr_include(ip
, ip
->i_file
, base_name(*fp
));
471 struct filepointer
*getfile(file
)
475 struct filepointer
*content
;
481 content
= (struct filepointer
*)malloc(sizeof(struct filepointer
));
482 if ((fd
= open(file
, O_RDONLY
)) < 0) {
483 warning("makedepend: Cannot open file \"%s\"\n", file
);
484 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
485 *content
->f_p
= '\0';
490 size_backup
= st
.st_size
;
491 malloc_size
= size_backup
;
492 /* Since off_t is larger than size_t, need to test for
495 if ( malloc_size
!= size_backup
)
498 warning("makedepend: File \"%s\" size larger than can fit in size_t. Cannot allocate memory for contents.\n", file
);
499 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
500 *content
->f_p
= '\0';
504 content
->f_base
= (char *)malloc(malloc_size
+1);
505 if (content
->f_base
== NULL
)
506 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file
);
507 if ((bytes_read
= read(fd
, content
->f_base
, malloc_size
)) < 0)
508 if ( st
.st_mode
& S_IFREG
)
509 fatalerr("makedepend: Failed to read file \"%s\"\n", file
);
512 content
->f_len
= bytes_read
+1;
513 content
->f_p
= content
->f_base
;
514 content
->f_end
= content
->f_base
+ bytes_read
;
515 *content
->f_end
= '\0';
521 struct filepointer
*fp
;
530 register char *p
= (char *)malloc(strlen(str
) + 1);
537 register char *str
, **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(filep
)
552 register struct filepointer
*filep
;
554 register char *p
, /* walking pointer */
555 *eof
, /* end of file pointer */
556 *bol
; /* beginning of line pointer */
557 register int lineno
; /* line number */
562 return((char *)NULL
);
563 lineno
= filep
->f_line
;
565 for(bol
= p
--; ++p
< eof
; ) {
566 if (*p
== '/' && *(p
+1) == '*') { /* consume comments */
567 *p
++ = ' ', *p
++ = ' ';
569 if (*p
== '*' && *(p
+1) == '/') {
570 *p
++ = ' ', *p
= ' ';
579 else if (*p
== '/' && *(p
+1) == '/') { /* consume comments */
580 *p
++ = ' ', *p
++ = ' ';
581 while (*p
&& *p
!= '\n')
588 else if (*p
== '\\') {
589 if (*(p
+1) == '\n') {
595 else if (*p
== '\n') {
601 /* punt lines with just # (yacc generated) */
603 *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++);
613 filep
->f_line
= lineno
;
618 * Strip the file name down to what we want to see in the Makefile.
619 * It will have objprefix and objsuffix around it.
621 char *base_name(file
)
627 for(p
=file
+strlen(file
); p
>file
&& *p
!= '.'; p
--) ;
633 if ( *p
== '/' || *p
== '\\') {
642 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
643 int rename (from
, to
)
647 if (link (from
, to
) == 0) {
656 void redirect(line
, makefile
)
662 char backup
[ BUFSIZ
],
664 boolean found
= FALSE
;
668 * if makefile is "-" then let it pour onto stdout.
670 if (makefile
&& *makefile
== '-' && *(makefile
+1) == '\0')
674 * use a default makefile is not specified.
677 if (stat("Makefile", &st
) == 0)
678 makefile
= "Makefile";
679 else if (stat("makefile", &st
) == 0)
680 makefile
= "makefile";
682 fatalerr("[mM]akefile is not present\n");
686 if ((fdin
= fopen(makefile
, "r")) == NULL
)
687 fatalerr("cannot open \"%s\"\n", makefile
);
688 sprintf(backup
, "%s.bak", makefile
);
690 #if defined(WIN32) || defined(OS2)
693 if (rename(makefile
, backup
) < 0)
694 fatalerr("cannot rename %s to %s\n", makefile
, backup
);
695 #if defined(WIN32) || defined(OS2)
696 if ((fdin
= fopen(backup
, "r")) == NULL
)
697 fatalerr("cannot open \"%s\"\n", backup
);
699 if ((fdout
= freopen(makefile
, "w", stdout
)) == NULL
)
700 fatalerr("cannot open \"%s\"\n", backup
);
702 while (!found
&& fgets(buf
, BUFSIZ
, fdin
)) {
703 if (*buf
== '#' && strncmp(line
, buf
, len
) == 0)
709 warning("Adding new delimiting line \"%s\" and dependencies...\n",
711 puts(line
); /* same as fputs(fdout); but with newline */
713 while (fgets(buf
, BUFSIZ
, fdin
)) {
718 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
719 chmod(makefile
, st
.st_mode
);
721 fchmod(fileno(fdout
), st
.st_mode
);
725 #if NeedVarargsPrototypes
726 int fatalerr(char *msg
, ...)
729 int fatalerr(msg
,x1
,x2
,x3
,x4
,x5
,x6
,x7
,x8
,x9
)
733 #if NeedVarargsPrototypes
736 fprintf(stderr
, "%s: error: ", ProgramName
);
737 #if NeedVarargsPrototypes
739 vfprintf(stderr
, msg
, args
);
742 fprintf(stderr
, msg
,x1
,x2
,x3
,x4
,x5
,x6
,x7
,x8
,x9
);
747 #if NeedVarargsPrototypes
748 int warning(char *msg
, ...)
751 int warning(msg
,x1
,x2
,x3
,x4
,x5
,x6
,x7
,x8
,x9
)
755 #ifdef DEBUG_MKDEPEND
756 #if NeedVarargsPrototypes
759 fprintf(stderr
, "%s: warning: ", ProgramName
);
760 #if NeedVarargsPrototypes
762 vfprintf(stderr
, msg
, args
);
765 fprintf(stderr
, msg
,x1
,x2
,x3
,x4
,x5
,x6
,x7
,x8
,x9
);
767 #endif /* DEBUG_MKDEPEND */
771 #if NeedVarargsPrototypes
772 void warning1(char *msg
, ...)
775 void warning1(msg
,x1
,x2
,x3
,x4
,x5
,x6
,x7
,x8
,x9
)
779 #ifdef DEBUG_MKDEPEND
780 #if NeedVarargsPrototypes
783 vfprintf(stderr
, msg
, args
);
786 fprintf(stderr
, msg
,x1
,x2
,x3
,x4
,x5
,x6
,x7
,x8
,x9
);
788 #endif /* DEBUG_MKDEPEND */
791 void convert_slashes(path
)
794 #if defined (WNT) || defined(OS2)
796 * Convert backslashes to slashes
799 if (native_win_slashes
) {
800 for (ptr
= (char*)path
; *ptr
; ++ptr
)
804 for (ptr
= (char*)path
; *ptr
; ++ptr
)
811 char* append_slash(path
)
814 char *ptr
, *new_string
;
815 if ((path
[strlen(path
) - 1] == '/') || (path
[strlen(path
) - 1] == '\\')) {
818 new_string
= (char*)malloc(sizeof(char) * (strlen(path
) + 2));
819 strcpy(new_string
, path
);
820 if (native_win_slashes
)
821 strcat(new_string
, "\\");
823 strcat(new_string
, "/");