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)
85 #define OBJSUFFIX ".obj"
86 #define INCLUDEDIR "."
88 char *directives
[] = {
108 #include "imakemdep.h" /* from config sources */
111 /******* function declarations ********/
112 /******* added by -Wall project *******/
113 void redirect(char * line
, char * makefile
);
115 struct inclist inclist
[ MAXFILES
],
118 struct symhash
*maininclist
= NULL
;
120 char *filelist
[ MAXFILES
];
121 char *includedirs
[ MAXDIRS
+ 1 ];
122 char *notdotdot
[ MAXDIRS
];
123 char *objprefix
= "";
124 char *objsuffix
= OBJSUFFIX
;
125 char *startat
= "# DO NOT DELETE";
127 boolean append
= FALSE
;
128 boolean printed
= FALSE
;
129 boolean verbose
= FALSE
;
130 boolean show_where_not
= FALSE
;
131 boolean warn_multiple
= FALSE
; /* Warn on multiple includes of same file */
134 #ifdef SIGNALRETURNSINT
143 fatalerr ("got signal %d\n", sig
);
146 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(OS2) || defined(Lynx_22)
151 #ifndef _POSIX_SOURCE
152 #define sigaction sigvec
153 #define sa_handler sv_handler
154 #define sa_mask sv_mask
155 #define sa_flags sv_flags
157 struct sigaction sig_act
;
160 boolean native_win_slashes
= FALSE
;
166 register char **fp
= filelist
;
167 register char **incp
= includedirs
;
169 register struct inclist
*ip
;
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);
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 */
275 if (endmarker
) break;
279 if (endmarker
) break;
280 if (argv
[0][2] == '\0') {
283 width
= atoi(argv
[0]);
285 width
= atoi(argv
[0]+2);
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 /* fatalerr("unknown opt = %s\n", argv[0]); */
350 warning("ignoring option %s\n", argv
[0]);
354 convert_slashes(objprefix
);
355 objprefix
= append_slash(objprefix
);
359 if (incp
>= includedirs
+ MAXDIRS
)
360 fatalerr("Too many -I flags.\n");
363 if (incp
>= includedirs
+ MAXDIRS
)
364 fatalerr("Too many -I flags.\n");
365 *incp
++ = INCLUDEDIR
;
367 if (incp
>= includedirs
+ MAXDIRS
)
368 fatalerr("Too many -I flags.\n");
369 *incp
++ = POSTINCDIR
;
371 } else if (*defincdir
) {
372 if (incp
>= includedirs
+ MAXDIRS
)
373 fatalerr("Too many -I flags.\n");
377 redirect(startat
, makefile
);
383 /* should really reset SIGINT to SIG_IGN if it was. */
385 signal (SIGHUP
, catch);
387 signal (SIGINT
, catch);
389 signal (SIGQUIT
, catch);
391 signal (SIGILL
, catch);
393 signal (SIGBUS
, catch);
395 signal (SIGSEGV
, catch);
397 signal (SIGSYS
, catch);
399 signal (SIGFPE
, catch);
401 sig_act
.sa_handler
= catch;
403 sigemptyset(&sig_act
.sa_mask
);
404 sigaddset(&sig_act
.sa_mask
, SIGINT
);
405 sigaddset(&sig_act
.sa_mask
, SIGQUIT
);
407 sigaddset(&sig_act
.sa_mask
, SIGBUS
);
409 sigaddset(&sig_act
.sa_mask
, SIGILL
);
410 sigaddset(&sig_act
.sa_mask
, SIGSEGV
);
411 sigaddset(&sig_act
.sa_mask
, SIGHUP
);
412 sigaddset(&sig_act
.sa_mask
, SIGPIPE
);
414 sigaddset(&sig_act
.sa_mask
, SIGSYS
);
417 sig_act
.sa_mask
= ((1<<(SIGINT
-1))
430 #endif /* _POSIX_SOURCE */
431 sig_act
.sa_flags
= 0;
432 sigaction(SIGHUP
, &sig_act
, (struct sigaction
*)0);
433 sigaction(SIGINT
, &sig_act
, (struct sigaction
*)0);
434 sigaction(SIGQUIT
, &sig_act
, (struct sigaction
*)0);
435 sigaction(SIGILL
, &sig_act
, (struct sigaction
*)0);
437 sigaction(SIGBUS
, &sig_act
, (struct sigaction
*)0);
439 sigaction(SIGSEGV
, &sig_act
, (struct sigaction
*)0);
441 sigaction(SIGSYS
, &sig_act
, (struct sigaction
*)0);
446 * now peruse through the list of files.
448 incCollection
= create_IncludesCollection();
450 for(fp
=filelist
; *fp
; fp
++) {
451 struct symhash
*includes
;
452 filecontent
= getfile(*fp
);
453 ip
= newinclude(*fp
, (char *)NULL
);
455 includes
= hash_copy( maininclist
);
456 find_includes(filecontent
, ip
, ip
, 0, FALSE
, incCollection
, includes
);
457 hash_free( includes
);
459 freefile(filecontent
);
460 recursive_pr_include(ip
, ip
->i_file
, base_name(*fp
));
466 delete_IncludesCollection(incCollection
);
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 ( (off_t
)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
);
726 void fatalerr(char *msg
, ...)
729 fprintf(stderr
, "%s: error: ", ProgramName
);
731 vfprintf(stderr
, msg
, args
);
736 void warning(char *msg
, ...)
738 #ifdef DEBUG_MKDEPEND
740 fprintf(stderr
, "%s: warning: ", ProgramName
);
742 vfprintf(stderr
, msg
, args
);
746 #endif /* DEBUG_MKDEPEND */
749 void warning1(char *msg
, ...)
751 #ifdef DEBUG_MKDEPEND
754 vfprintf(stderr
, msg
, args
);
758 #endif /* DEBUG_MKDEPEND */
761 void convert_slashes(path
)
764 #if defined (WNT) || defined(OS2)
766 * Convert backslashes to slashes
769 if (native_win_slashes
) {
770 for (ptr
= (char*)path
; *ptr
; ++ptr
)
774 for (ptr
= (char*)path
; *ptr
; ++ptr
)
783 char* append_slash(path
)
787 if ((path
[strlen(path
) - 1] == '/') || (path
[strlen(path
) - 1] == '\\')) {
790 new_string
= (char*)malloc(sizeof(char) * (strlen(path
) + 2));
791 strcpy(new_string
, path
);
792 if (native_win_slashes
)
793 strcat(new_string
, "\\");
795 strcat(new_string
, "/");