bump product version to 4.1.6.2
[LibreOffice.git] / soltools / mkdepend / main.c
blob149bae1e62da3d73cda7a27c2151a3dd7a1938a3
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 $ */
4 /*
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>
33 #include <sys/stat.h>
34 #endif
36 #ifdef _WIN32
37 #include <io.h>
38 #endif
40 #ifdef _MSC_VER /* Define ssize_t */
42 #if !defined(_W64)
43 #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
44 #define _W64 __w64
45 #else
46 #define _W64
47 #endif
48 #endif
50 #ifdef _WIN64
51 typedef __int64 ssize_t;
52 #else
53 typedef _W64 int ssize_t;
54 #endif
56 #endif
58 #include "def.h"
59 #include <string.h>
60 #ifdef hpux
61 #define sigvec sigvector
62 #endif /* hpux */
64 #ifdef X_POSIX_C_SOURCE
65 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
66 #include <signal.h>
67 #undef _POSIX_C_SOURCE
68 #else
69 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
70 #include <signal.h>
71 #else
72 #define _POSIX_SOURCE
73 #include <signal.h>
74 #undef _POSIX_SOURCE
75 #endif
76 #endif
78 #include <stdarg.h>
80 #ifdef MINIX
81 #define USE_CHMOD 1
82 #endif
84 #ifdef DEBUG
85 int _debugmask;
86 #endif
88 char *ProgramName;
90 #define OBJSUFFIX ".obj"
91 #define INCLUDEDIR "."
93 char *directives[] = {
94 "if",
95 "ifdef",
96 "ifndef",
97 "else",
98 "endif",
99 "define",
100 "undef",
101 "include",
102 "line",
103 "pragma",
104 "error",
105 "ident",
106 "sccs",
107 "elif",
108 "eject",
109 NULL
112 #define MAKEDEPEND
113 #include "imakemdep.h" /* from config sources */
114 #undef MAKEDEPEND
116 /******* function declarations ********/
117 /******* added by -Wall project *******/
118 void redirect(char * line, char * makefile );
120 struct inclist inclist[ MAXFILES ],
121 *inclistp = inclist;
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";
131 int width = 78;
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 */
138 static
139 #ifdef SIGNALRETURNSINT
141 #else
142 void
143 #endif
144 catch (int sig)
146 fflush (stdout);
147 fatalerr ("got signal %d\n", sig);
150 #if (defined(i386) && defined(SYSV)) || defined(WIN32)
151 #define USGISH
152 #endif
154 #ifndef USGISH
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
160 #endif
161 struct sigaction sig_act;
162 #endif /* USGISH */
164 boolean native_win_slashes = FALSE;
166 int main(argc, argv)
167 int argc;
168 char **argv;
170 register char **fp = filelist;
171 register char **incp = includedirs;
172 register char *p;
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);
186 psymp++;
188 if (argc == 2 && argv[1][0] == '@') {
189 struct stat ast;
190 int afd;
191 char *args;
192 char **nargv;
193 int nargc;
194 char quotechar = '\0';
196 nargc = 1;
197 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
198 fatalerr("cannot open \"%s\"\n", argv[1]+1);
199 fstat(afd, &ast);
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';
204 close(afd);
205 for (p = args; *p; p++) {
206 if (quotechar) {
207 if (quotechar == '\\'
208 || (*p == quotechar && p[-1] != '\\'))
209 quotechar = '\0';
210 continue;
212 switch (*p) {
213 case '\\':
214 case '"':
215 case '\'':
216 quotechar = *p;
217 break;
218 case ' ':
219 case '\n':
220 *p = '\0';
221 if (p > args && p[-1])
222 nargc++;
223 break;
226 if (p[-1])
227 nargc++;
228 nargv = (char **)malloc(nargc * sizeof(char *));
229 nargv[0] = argv[0];
230 argc = 1;
231 for (p = args; argc < nargc; p += strlen(p) + 1)
232 if (*p) nargv[argc++] = p;
233 argv = nargv;
235 for(argc--, argv++; argc; argc--, argv++) {
236 /* if looking for endmarker then check before parsing */
237 if (endmarker && strcmp (endmarker, *argv) == 0) {
238 endmarker = NULL;
239 continue;
241 if (**argv != '-') {
242 /* treat +thing as an option for C++ */
243 if (endmarker && **argv == '+')
244 continue;
245 *fp++ = argv[0];
246 continue;
248 switch(argv[0][1]) {
249 case '-':
250 endmarker = &argv[0][2];
251 if (endmarker[0] == '\0') endmarker = "--";
252 break;
253 case 'D':
254 if (argv[0][2] == '\0') {
255 argv++;
256 argc--;
258 for (p=argv[0] + 2; *p ; p++)
259 if (*p == '=') {
260 *p = ' ';
261 break;
263 define(argv[0] + 2, &maininclist);
264 break;
265 case 'I':
266 if (incp >= includedirs + MAXDIRS)
267 fatalerr("Too many -I flags.\n");
268 *incp++ = argv[0]+2;
269 if (**(incp-1) == '\0') {
270 *(incp-1) = *(++argv);
271 argc--;
273 break;
274 case 'Y':
275 defincdir = argv[0]+2;
276 break;
277 /* do not use if endmarker processing */
278 case 'a':
279 if (endmarker) break;
280 append = TRUE;
281 break;
282 case 'w':
283 if (endmarker) break;
284 if (argv[0][2] == '\0') {
285 argv++;
286 argc--;
287 width = atoi(argv[0]);
288 } else
289 width = atoi(argv[0]+2);
290 break;
291 case 'n':
292 // Use "-n" switch to generate dependencies with windows-native slash style
293 native_win_slashes = TRUE;
294 break;
295 case 'o':
296 if (endmarker) break;
297 if (argv[0][2] == '\0') {
298 argv++;
299 argc--;
300 objsuffix = argv[0];
301 } else
302 objsuffix = argv[0]+2;
303 break;
304 case 'p':
305 if (endmarker) break;
306 if (argv[0][2] == '\0') {
307 argv++;
308 argc--;
309 objprefix = argv[0];
310 } else
311 objprefix = argv[0]+2;
312 break;
313 case 'v':
314 if (endmarker) break;
315 verbose = TRUE;
316 #ifdef DEBUG
317 if (argv[0][2])
318 _debugmask = atoi(argv[0]+2);
319 #endif
320 break;
321 case 's':
322 if (endmarker) break;
323 startat = argv[0]+2;
324 if (*startat == '\0') {
325 startat = *(++argv);
326 argc--;
328 if (*startat != '#')
329 fatalerr("-s flag's value should start %s\n",
330 "with '#'.");
331 break;
332 case 'f':
333 if (endmarker) break;
334 makefile = argv[0]+2;
335 if (*makefile == '\0') {
336 makefile = *(++argv);
337 argc--;
339 break;
341 case 'm':
342 warn_multiple = TRUE;
343 break;
345 /* Ignore -O, -g so we can just pass ${CFLAGS} to
346 makedepend
348 case 'O':
349 case 'g':
350 break;
351 default:
352 if (endmarker) break;
353 warning("ignoring option %s\n", argv[0]);
357 convert_slashes(objprefix);
358 objprefix = append_slash(objprefix);
360 if (!defincdir) {
361 #ifdef PREINCDIR
362 if (incp >= includedirs + MAXDIRS)
363 fatalerr("Too many -I flags.\n");
364 *incp++ = PREINCDIR;
365 #endif
366 if (incp >= includedirs + MAXDIRS)
367 fatalerr("Too many -I flags.\n");
368 *incp++ = INCLUDEDIR;
369 #ifdef POSTINCDIR
370 if (incp >= includedirs + MAXDIRS)
371 fatalerr("Too many -I flags.\n");
372 *incp++ = POSTINCDIR;
373 #endif
374 } else if (*defincdir) {
375 if (incp >= includedirs + MAXDIRS)
376 fatalerr("Too many -I flags.\n");
377 *incp++ = defincdir;
380 redirect(startat, makefile);
383 * catch signals.
385 #ifdef USGISH
386 /* should really reset SIGINT to SIG_IGN if it was. */
387 #ifdef SIGHUP
388 signal (SIGHUP, catch);
389 #endif
390 signal (SIGINT, catch);
391 #ifdef SIGQUIT
392 signal (SIGQUIT, catch);
393 #endif
394 signal (SIGILL, catch);
395 #ifdef SIGBUS
396 signal (SIGBUS, catch);
397 #endif
398 signal (SIGSEGV, catch);
399 #ifdef SIGSYS
400 signal (SIGSYS, catch);
401 #endif
402 signal (SIGFPE, catch);
403 #else
404 sig_act.sa_handler = catch;
405 #ifdef _POSIX_SOURCE
406 sigemptyset(&sig_act.sa_mask);
407 sigaddset(&sig_act.sa_mask, SIGINT);
408 sigaddset(&sig_act.sa_mask, SIGQUIT);
409 #ifdef SIGBUS
410 sigaddset(&sig_act.sa_mask, SIGBUS);
411 #endif
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);
416 #ifdef SIGSYS
417 sigaddset(&sig_act.sa_mask, SIGSYS);
418 #endif
419 #else
420 sig_act.sa_mask = ((1<<(SIGINT -1))
421 |(1<<(SIGQUIT-1))
422 #ifdef SIGBUS
423 |(1<<(SIGBUS-1))
424 #endif
425 |(1<<(SIGILL-1))
426 |(1<<(SIGSEGV-1))
427 |(1<<(SIGHUP-1))
428 |(1<<(SIGPIPE-1))
429 #ifdef SIGSYS
430 |(1<<(SIGSYS-1))
431 #endif
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);
439 #ifdef SIGBUS
440 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
441 #endif
442 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
443 #ifdef SIGSYS
444 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
445 #endif
446 #endif /* USGISH */
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));
464 if (printed)
465 fwrite("\n\n", 2, 1, stdout);
466 recursive_pr_dummy(ip, ip->i_file);
467 inc_clean();
469 if (printed)
470 printf("\n");
472 delete_IncludesCollection(incCollection);
474 exit(0);
477 struct filepointer *getfile(file)
478 char *file;
480 register int fd;
481 struct filepointer *content;
482 struct stat st;
483 off_t size_backup;
484 ssize_t bytes_read;
485 size_t malloc_size;
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';
492 return(content);
494 fstat(fd, &st);
496 size_backup = st.st_size;
497 malloc_size = size_backup;
498 /* Since off_t is larger than size_t, need to test for
499 * truncation.
501 if ( (off_t)malloc_size != size_backup )
503 close( fd );
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';
507 return(content);
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);
517 close(fd);
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';
522 content->f_line = 0;
523 return(content);
526 void freefile(fp)
527 struct filepointer *fp;
529 free(fp->f_base);
530 free(fp);
533 char *copy(str)
534 register char *str;
536 register char *p = (char *)malloc(strlen(str) + 1);
538 strcpy(p, str);
539 return(p);
542 int match(str, list)
543 register char *str, **list;
545 register int i;
547 for (i=0; *list; i++, list++)
548 if (strcmp(str, *list) == 0)
549 return(i);
550 return(-1);
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 */
565 p = filep->f_p;
566 eof = filep->f_end;
567 if (p >= eof)
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++ = ' ';
574 while (*p) {
575 if (*p == '*' && *(p+1) == '/') {
576 *p++ = ' ', *p = ' ';
577 break;
579 else if (*p == '\n')
580 lineno++;
581 *p++ = ' ';
583 continue;
585 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
586 *p++ = ' ', *p++ = ' ';
587 while (*p && *p != '\n')
588 *p++ = ' ';
589 if ( *p == '\n' )
590 p--;
591 lineno++;
592 continue;
594 else if (*p == '\\') {
595 if (*(p+1) == '\n') {
596 *p = ' ';
597 *(p+1) = ' ';
598 lineno++;
601 else if (*p == '\n') {
602 lineno++;
603 if (*bol == '#') {
604 register char *cp;
606 *p++ = '\0';
607 /* punt lines with just # (yacc generated) */
608 for (cp = bol+1;
609 *cp && (*cp == ' ' || *cp == '\t'); cp++);
610 if (*cp) goto done;
612 bol = p+1;
615 if (*bol != '#')
616 bol = NULL;
617 done:
618 filep->f_p = p;
619 filep->f_line = lineno;
620 return(bol);
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)
628 register char *file;
630 register char *p;
632 file = copy(file);
633 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
635 if (*p == '.')
636 *p = '\0';
638 while (p > file) {
639 if ( *p == '/' || *p == '\\') {
640 file = p + 1;
641 break;
643 p--;
645 return(file);
648 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
649 int rename (from, to)
650 char *from, *to;
652 (void) unlink (to);
653 if (link (from, to) == 0) {
654 unlink (from);
655 return 0;
656 } else {
657 return -1;
660 #endif /* USGISH */
662 void redirect(line, makefile)
663 char *line,
664 *makefile;
666 FILE *fdout;
667 fdout = freopen(makefile, "wb", stdout); // binary mode please
668 if (fdout == NULL)
669 fatalerr("cannot open \"%s\"\n", makefile);
670 (void) line;
672 // don't need any of that nonsense
673 #if 0
674 struct stat st;
675 FILE *fdin, *fdout;
676 char backup[ BUFSIZ ],
677 buf[ BUFSIZ ];
678 boolean found = FALSE;
679 int len;
682 * if makefile is "-" then let it pour onto stdout.
684 if (makefile && *makefile == '-' && *(makefile+1) == '\0')
685 return;
688 * use a default makefile is not specified.
690 if (!makefile) {
691 if (stat("Makefile", &st) == 0)
692 makefile = "Makefile";
693 else if (stat("makefile", &st) == 0)
694 makefile = "makefile";
695 else
696 fatalerr("[mM]akefile is not present\n");
698 else
699 stat(makefile, &st);
700 if ((fdin = fopen(makefile, "r")) == NULL)
701 fatalerr("cannot open \"%s\"\n", makefile);
702 sprintf(backup, "%s.bak", makefile);
703 unlink(backup);
704 #if defined(WIN32)
705 fclose(fdin);
706 #endif
707 if (rename(makefile, backup) < 0)
708 fatalerr("cannot rename %s to %s\n", makefile, backup);
709 #if defined(WIN32)
710 if ((fdin = fopen(backup, "r")) == NULL)
711 fatalerr("cannot open \"%s\"\n", backup);
712 #endif
713 if ((fdout = freopen(makefile, "w", stdout)) == NULL)
714 fatalerr("cannot open \"%s\"\n", backup);
715 len = strlen(line);
716 while (!found && fgets(buf, BUFSIZ, fdin)) {
717 if (*buf == '#' && strncmp(line, buf, len) == 0)
718 found = TRUE;
719 fputs(buf, fdout);
721 if (!found) {
722 if (verbose)
723 warning("Adding new delimiting line \"%s\" and dependencies...\n",
724 line);
725 puts(line); /* same as fputs(fdout); but with newline */
726 } else if (append) {
727 while (fgets(buf, BUFSIZ, fdin)) {
728 fputs(buf, fdout);
731 fflush(fdout);
732 #if defined(USGISH) || defined(USE_CHMOD)
733 chmod(makefile, st.st_mode);
734 #else
735 fchmod(fileno(fdout), st.st_mode);
736 #endif /* USGISH */
737 fclose(fdin);
738 #endif
741 void fatalerr(char *msg, ...)
743 va_list args;
744 fprintf(stderr, "%s: error: ", ProgramName);
745 va_start(args, msg);
746 vfprintf(stderr, msg, args);
747 va_end(args);
748 exit (1);
751 void warning(char *msg, ...)
753 #ifdef DEBUG_MKDEPEND
754 va_list args;
755 fprintf(stderr, "%s: warning: ", ProgramName);
756 va_start(args, msg);
757 vfprintf(stderr, msg, args);
758 va_end(args);
759 #else
760 (void)msg;
761 #endif /* DEBUG_MKDEPEND */
764 void warning1(char *msg, ...)
766 #ifdef DEBUG_MKDEPEND
767 va_list args;
768 va_start(args, msg);
769 vfprintf(stderr, msg, args);
770 va_end(args);
771 #else
772 (void)msg;
773 #endif /* DEBUG_MKDEPEND */
776 void convert_slashes(path)
777 char* path;
779 #if defined (WNT)
781 * Convert backslashes to slashes
783 char *ptr;
784 if (native_win_slashes) {
785 for (ptr = (char*)path; *ptr; ++ptr)
786 if (*ptr == '/')
787 *ptr = '\\';
788 } else {
789 for (ptr = (char*)path; *ptr; ++ptr)
790 if (*ptr == '\\')
791 *ptr = '/';
793 #else
794 (void)path;
795 #endif
798 char* append_slash(path)
799 char* path;
801 char *new_string;
802 if ((path[strlen(path) - 1] == '/') || (path[strlen(path) - 1] == '\\')) {
803 new_string = path;
804 } else {
805 new_string = (char*)malloc(sizeof(char) * (strlen(path) + 2));
806 strcpy(new_string, path);
807 if (native_win_slashes)
808 strcat(new_string, "\\");
809 else
810 strcat(new_string, "/");
812 return new_string;
815 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */