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 * line
, 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
;
170 register char **fp
= filelist
;
171 register char **incp
= includedirs
;
173 register struct inclist
*ip
;
174 char *makefile
= NULL
;
175 struct filepointer
*filecontent
;
176 struct pair
*psymp
= predefs
;
177 char *endmarker
= NULL
;
178 char *defincdir
= NULL
;
179 struct IncludesCollection
* incCollection
;
181 ProgramName
= argv
[0];
183 while (psymp
->p_name
)
185 hash_define(psymp
->p_name
, psymp
->p_value
, &maininclist
);
188 if (argc
== 2 && argv
[1][0] == '@') {
194 char quotechar
= '\0';
197 if ((afd
= open(argv
[1]+1, O_RDONLY
)) < 0)
198 fatalerr("cannot open \"%s\"\n", argv
[1]+1);
200 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 */
279 if (endmarker
) break;
283 if (endmarker
) break;
284 if (argv
[0][2] == '\0') {
287 width
= atoi(argv
[0]);
289 width
= atoi(argv
[0]+2);
292 // Use "-n" switch to generate dependencies with windows-native slash style
293 native_win_slashes
= TRUE
;
296 if (endmarker
) break;
297 if (argv
[0][2] == '\0') {
302 objsuffix
= argv
[0]+2;
305 if (endmarker
) break;
306 if (argv
[0][2] == '\0') {
311 objprefix
= argv
[0]+2;
314 if (endmarker
) break;
318 _debugmask
= atoi(argv
[0]+2);
322 if (endmarker
) break;
324 if (*startat
== '\0') {
329 fatalerr("-s flag's value should start %s\n",
333 if (endmarker
) break;
334 makefile
= argv
[0]+2;
335 if (*makefile
== '\0') {
336 makefile
= *(++argv
);
342 warn_multiple
= TRUE
;
345 /* Ignore -O, -g so we can just pass ${CFLAGS} to
352 if (endmarker
) break;
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
));
465 fwrite("\n\n", 2, 1, stdout
);
466 recursive_pr_dummy(ip
, ip
->i_file
);
472 delete_IncludesCollection(incCollection
);
477 struct filepointer
*getfile(file
)
481 struct filepointer
*content
;
487 content
= (struct filepointer
*)malloc(sizeof(struct filepointer
));
488 if ((fd
= open(file
, O_RDONLY
)) < 0) {
489 warning("makedepend: Cannot open file \"%s\"\n", file
);
490 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
491 *content
->f_p
= '\0';
496 size_backup
= st
.st_size
;
497 malloc_size
= size_backup
;
498 /* Since off_t is larger than size_t, need to test for
501 if ( (off_t
)malloc_size
!= size_backup
)
504 warning("makedepend: File \"%s\" size larger than can fit in size_t. Cannot allocate memory for contents.\n", file
);
505 content
->f_p
= content
->f_base
= content
->f_end
= (char *)malloc(1);
506 *content
->f_p
= '\0';
510 content
->f_base
= (char *)malloc(malloc_size
+1);
511 if (content
->f_base
== NULL
)
512 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file
);
513 if ((bytes_read
= read(fd
, content
->f_base
, malloc_size
)) < 0)
514 if ( st
.st_mode
& S_IFREG
)
515 fatalerr("makedepend: Failed to read file \"%s\"\n", file
);
518 content
->f_len
= bytes_read
+1;
519 content
->f_p
= content
->f_base
;
520 content
->f_end
= content
->f_base
+ bytes_read
;
521 *content
->f_end
= '\0';
527 struct filepointer
*fp
;
536 register char *p
= (char *)malloc(strlen(str
) + 1);
543 register char *str
, **list
;
547 for (i
=0; *list
; i
++, list
++)
548 if (strcmp(str
, *list
) == 0)
554 * Get the next line. We only return lines beginning with '#' since that
555 * is all this program is ever interested in.
557 char *get_line(filep
)
558 register struct filepointer
*filep
;
560 register char *p
, /* walking pointer */
561 *eof
, /* end of file pointer */
562 *bol
; /* beginning of line pointer */
563 register int lineno
; /* line number */
568 return((char *)NULL
);
569 lineno
= filep
->f_line
;
571 for(bol
= p
--; ++p
< eof
; ) {
572 if (*p
== '/' && *(p
+1) == '*') { /* consume comments */
573 *p
++ = ' ', *p
++ = ' ';
575 if (*p
== '*' && *(p
+1) == '/') {
576 *p
++ = ' ', *p
= ' ';
585 else if (*p
== '/' && *(p
+1) == '/') { /* consume comments */
586 *p
++ = ' ', *p
++ = ' ';
587 while (*p
&& *p
!= '\n')
594 else if (*p
== '\\') {
595 if (*(p
+1) == '\n') {
601 else if (*p
== '\n') {
607 /* punt lines with just # (yacc generated) */
609 *cp
&& (*cp
== ' ' || *cp
== '\t'); cp
++);
619 filep
->f_line
= lineno
;
624 * Strip the file name down to what we want to see in the Makefile.
625 * It will have objprefix and objsuffix around it.
627 char *base_name(file
)
633 for(p
=file
+strlen(file
); p
>file
&& *p
!= '.'; p
--) ;
639 if ( *p
== '/' || *p
== '\\') {
648 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
649 int rename (from
, to
)
653 if (link (from
, to
) == 0) {
662 void redirect(line
, makefile
)
667 fdout
= freopen(makefile
, "wb", stdout
); // binary mode please
669 fatalerr("cannot open \"%s\"\n", makefile
);
672 // don't need any of that nonsense
676 char backup
[ BUFSIZ
],
678 boolean found
= FALSE
;
682 * if makefile is "-" then let it pour onto stdout.
684 if (makefile
&& *makefile
== '-' && *(makefile
+1) == '\0')
688 * use a default makefile is not specified.
691 if (stat("Makefile", &st
) == 0)
692 makefile
= "Makefile";
693 else if (stat("makefile", &st
) == 0)
694 makefile
= "makefile";
696 fatalerr("[mM]akefile is not present\n");
700 if ((fdin
= fopen(makefile
, "r")) == NULL
)
701 fatalerr("cannot open \"%s\"\n", makefile
);
702 sprintf(backup
, "%s.bak", makefile
);
707 if (rename(makefile
, backup
) < 0)
708 fatalerr("cannot rename %s to %s\n", makefile
, backup
);
710 if ((fdin
= fopen(backup
, "r")) == NULL
)
711 fatalerr("cannot open \"%s\"\n", backup
);
713 if ((fdout
= freopen(makefile
, "w", stdout
)) == NULL
)
714 fatalerr("cannot open \"%s\"\n", backup
);
716 while (!found
&& fgets(buf
, BUFSIZ
, fdin
)) {
717 if (*buf
== '#' && strncmp(line
, buf
, len
) == 0)
723 warning("Adding new delimiting line \"%s\" and dependencies...\n",
725 puts(line
); /* same as fputs(fdout); but with newline */
727 while (fgets(buf
, BUFSIZ
, fdin
)) {
732 #if defined(USGISH) || defined(USE_CHMOD)
733 chmod(makefile
, st
.st_mode
);
735 fchmod(fileno(fdout
), st
.st_mode
);
741 void fatalerr(char *msg
, ...)
744 fprintf(stderr
, "%s: error: ", ProgramName
);
746 vfprintf(stderr
, msg
, args
);
751 void warning(char *msg
, ...)
753 #ifdef DEBUG_MKDEPEND
755 fprintf(stderr
, "%s: warning: ", ProgramName
);
757 vfprintf(stderr
, msg
, args
);
761 #endif /* DEBUG_MKDEPEND */
764 void warning1(char *msg
, ...)
766 #ifdef DEBUG_MKDEPEND
769 vfprintf(stderr
, msg
, args
);
773 #endif /* DEBUG_MKDEPEND */
776 void convert_slashes(path
)
781 * Convert backslashes to slashes
784 if (native_win_slashes
) {
785 for (ptr
= (char*)path
; *ptr
; ++ptr
)
789 for (ptr
= (char*)path
; *ptr
; ++ptr
)
798 char* append_slash(path
)
802 if ((path
[strlen(path
) - 1] == '/') || (path
[strlen(path
) - 1] == '\\')) {
805 new_string
= (char*)malloc(sizeof(char) * (strlen(path
) + 2));
806 strcpy(new_string
, path
);
807 if (native_win_slashes
)
808 strcat(new_string
, "\\");
810 strcat(new_string
, "/");
815 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */