sd: keep a non-owning pointer to the OverridingShell
[LibreOffice.git] / soltools / mkdepend / main.c
blobcf06e9797d941a05bcf1607e8fb14cb07baa9a33
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))
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 <assert.h>
60 #include <string.h>
61 #ifdef hpux
62 #define sigvec sigvector
63 #endif /* hpux */
65 #ifdef X_POSIX_C_SOURCE
66 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
67 #include <signal.h>
68 #undef _POSIX_C_SOURCE
69 #else
70 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
71 #include <signal.h>
72 #else
73 #define _POSIX_SOURCE
74 #include <signal.h>
75 #undef _POSIX_SOURCE
76 #endif
77 #endif
79 #include <stdarg.h>
80 #include <stdlib.h>
82 #ifdef MINIX
83 #define USE_CHMOD 1
84 #endif
86 #if OSL_DEBUG_LEVEL >= 2
87 int _debugmask;
88 #endif
90 static char *ProgramName;
92 #define OBJSUFFIX ".obj"
93 #define INCLUDEDIR "."
95 char *directives[] = {
96 "if",
97 "ifdef",
98 "ifndef",
99 "else",
100 "endif",
101 "define",
102 "undef",
103 "include",
104 "line",
105 "pragma",
106 "error",
107 "ident",
108 "sccs",
109 "elif",
110 "eject",
111 NULL
114 #define MAKEDEPEND
115 #include "imakemdep.h" /* from config sources */
116 #undef MAKEDEPEND
118 /******* function declarations ********/
119 /******* added by -Wall project *******/
120 static void redirect(char * makefile);
122 struct inclist inclist[ MAXFILES ];
123 struct inclist *inclistp = inclist;
125 static struct symhash *maininclist = NULL;
127 static char *filelist[ MAXFILES ];
128 char *includedirs[ MAXDIRS + 1 ];
129 char *objprefix = "";
130 char *objsuffix = OBJSUFFIX;
131 static char *startat = "# DO NOT DELETE";
132 boolean printed = FALSE;
133 boolean verbose = FALSE;
134 boolean show_where_not = FALSE;
135 boolean warn_multiple = FALSE; /* Warn on multiple includes of same file */
137 static
138 #ifdef SIGNALRETURNSINT
140 #else
141 void
142 #endif
143 catch (int sig)
145 fflush (stdout);
146 fatalerr ("got signal %d\n", sig);
149 #if (defined(i386) && defined(SYSV)) || defined(_WIN32)
150 #define USGISH
151 #endif
153 #ifndef USGISH
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
159 #endif
160 static struct sigaction sig_act;
161 #endif /* USGISH */
163 static boolean native_win_slashes = FALSE;
165 int main(int argc, char **argv)
167 char **fp = filelist;
168 char **incp = includedirs;
169 char *p;
170 struct inclist *ip;
171 char *makefile = NULL;
172 struct filepointer *filecontent;
173 struct pair *psymp = predefs;
174 char *endmarker = NULL;
175 char *defincdir = NULL;
176 struct IncludesCollection* incCollection;
178 ProgramName = argv[0];
180 while (psymp->p_name)
182 hash_define(psymp->p_name, psymp->p_value, &maininclist);
183 psymp++;
185 if (argc == 2 && argv[1][0] == '@') {
186 struct stat ast;
187 int afd;
188 char *args;
189 char **nargv;
190 int nargc;
191 char quotechar = '\0';
193 nargc = 1;
194 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
195 fatalerr("cannot open \"%s\"\n", argv[1]+1);
196 (void)fstat(afd, &ast);
197 args = (char *)malloc(ast.st_size + 1);
198 if (args == NULL) {
199 abort();
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 break;
280 case 'w':
281 if (endmarker) break;
282 if (argv[0][2] == '\0') {
283 argv++;
284 argc--;
286 break;
287 case 'n':
288 // Use "-n" switch to generate dependencies with windows-native slash style
289 native_win_slashes = TRUE;
290 break;
291 case 'o':
292 if (endmarker) break;
293 if (argv[0][2] == '\0') {
294 argv++;
295 argc--;
296 objsuffix = argv[0];
297 } else
298 objsuffix = argv[0]+2;
299 break;
300 case 'p':
301 if (endmarker) break;
302 if (argv[0][2] == '\0') {
303 argv++;
304 argc--;
305 objprefix = argv[0];
306 } else
307 objprefix = argv[0]+2;
308 break;
309 case 'v':
310 if (endmarker) break;
311 verbose = TRUE;
312 #if OSL_DEBUG_LEVEL >= 2
313 if (argv[0][2])
314 _debugmask = atoi(argv[0]+2);
315 #endif
316 break;
317 case 's':
318 if (endmarker) break;
319 startat = argv[0]+2;
320 if (*startat == '\0') {
321 startat = *(++argv);
322 argc--;
324 if (*startat != '#')
325 fatalerr("-s flag's value should start %s\n",
326 "with '#'.");
327 break;
328 case 'f':
329 if (endmarker) break;
330 makefile = argv[0]+2;
331 if (*makefile == '\0') {
332 makefile = *(++argv);
333 argc--;
335 break;
337 case 'm':
338 warn_multiple = TRUE;
339 break;
341 /* Ignore -O, -g so we can just pass ${CFLAGS} to
342 makedepend
344 case 'O':
345 case 'g':
346 break;
347 default:
348 if (endmarker) break;
349 warning("ignoring option %s\n", argv[0]);
353 convert_slashes(objprefix);
354 objprefix = append_slash(objprefix);
356 if (!defincdir) {
357 #ifdef PREINCDIR
358 if (incp >= includedirs + MAXDIRS)
359 fatalerr("Too many -I flags.\n");
360 *incp++ = PREINCDIR;
361 #endif
362 if (incp >= includedirs + MAXDIRS)
363 fatalerr("Too many -I flags.\n");
364 *incp++ = INCLUDEDIR;
365 #ifdef POSTINCDIR
366 if (incp >= includedirs + MAXDIRS)
367 fatalerr("Too many -I flags.\n");
368 *incp++ = POSTINCDIR;
369 #endif
370 } else if (*defincdir) {
371 if (incp >= includedirs + MAXDIRS)
372 fatalerr("Too many -I flags.\n");
373 *incp++ = defincdir;
376 redirect(makefile);
379 * catch signals.
381 #ifdef USGISH
382 /* should really reset SIGINT to SIG_IGN if it was. */
383 #ifdef SIGHUP
384 signal (SIGHUP, catch);
385 #endif
386 signal (SIGINT, catch);
387 #ifdef SIGQUIT
388 signal (SIGQUIT, catch);
389 #endif
390 signal (SIGILL, catch);
391 #ifdef SIGBUS
392 signal (SIGBUS, catch);
393 #endif
394 signal (SIGSEGV, catch);
395 #ifdef SIGSYS
396 signal (SIGSYS, catch);
397 #endif
398 signal (SIGFPE, catch);
399 #else
400 sig_act.sa_handler = catch;
401 #ifdef _POSIX_SOURCE
402 sigemptyset(&sig_act.sa_mask);
403 sigaddset(&sig_act.sa_mask, SIGINT);
404 sigaddset(&sig_act.sa_mask, SIGQUIT);
405 #ifdef SIGBUS
406 sigaddset(&sig_act.sa_mask, SIGBUS);
407 #endif
408 sigaddset(&sig_act.sa_mask, SIGILL);
409 sigaddset(&sig_act.sa_mask, SIGSEGV);
410 sigaddset(&sig_act.sa_mask, SIGHUP);
411 sigaddset(&sig_act.sa_mask, SIGPIPE);
412 #ifdef SIGSYS
413 sigaddset(&sig_act.sa_mask, SIGSYS);
414 #endif
415 #else
416 sig_act.sa_mask = ((1<<(SIGINT -1))
417 |(1<<(SIGQUIT-1))
418 #ifdef SIGBUS
419 |(1<<(SIGBUS-1))
420 #endif
421 |(1<<(SIGILL-1))
422 |(1<<(SIGSEGV-1))
423 |(1<<(SIGHUP-1))
424 |(1<<(SIGPIPE-1))
425 #ifdef SIGSYS
426 |(1<<(SIGSYS-1))
427 #endif
429 #endif /* _POSIX_SOURCE */
430 sig_act.sa_flags = 0;
431 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
432 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
433 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
434 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
435 #ifdef SIGBUS
436 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
437 #endif
438 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
439 #ifdef SIGSYS
440 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
441 #endif
442 #endif /* USGISH */
445 * now peruse through the list of files.
447 incCollection = create_IncludesCollection();
449 for(fp=filelist; *fp; fp++) {
450 struct symhash *includes;
451 filecontent = getfile(*fp);
452 ip = newinclude(*fp, (char *)NULL);
454 includes = hash_copy( maininclist );
455 find_includes(filecontent, ip, ip, 0, FALSE, incCollection, includes);
456 hash_free( includes );
458 freefile(filecontent);
459 recursive_pr_include(ip, ip->i_file, base_name(*fp));
460 if (printed)
461 fwrite("\n\n", 2, 1, stdout);
462 recursive_pr_dummy(ip, ip->i_file);
463 inc_clean();
465 if (printed)
466 printf("\n");
468 delete_IncludesCollection(incCollection);
470 exit(0);
473 struct filepointer *getfile(char *file)
475 int fd;
476 struct filepointer *content;
477 struct stat st;
478 off_t size_backup;
479 ssize_t bytes_read;
480 unsigned malloc_size;
482 content = (struct filepointer *)malloc(sizeof(struct filepointer));
483 if ((fd = open(file, O_RDONLY)) < 0) {
484 warning("makedepend: Cannot open file \"%s\"\n", file);
485 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
486 *content->f_p = '\0';
487 return content;
489 (void)fstat(fd, &st);
491 size_backup = st.st_size;
492 malloc_size = size_backup;
493 /* Since off_t usually is larger than unsigned, need to test for
494 * truncation.
496 if ( (off_t)malloc_size != size_backup )
498 close( fd );
499 warning("makedepend: File \"%s\" is too large.\n", file);
500 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
501 *content->f_p = '\0';
502 return content;
505 content->f_base = (char *)malloc(malloc_size+1);
506 if (content->f_base == NULL)
507 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file);
508 if ((bytes_read = read(fd, content->f_base, malloc_size)) < 0)
509 if ( st.st_mode & S_IFREG )
510 fatalerr("makedepend: Failed to read file \"%s\"\n", file);
512 close(fd);
513 content->f_p = content->f_base;
514 content->f_end = content->f_base + bytes_read;
515 *content->f_end = '\0';
516 content->f_line = 0;
517 return content;
520 void freefile(struct filepointer *fp)
522 free(fp->f_base);
523 free(fp);
526 char *copy(char const *str)
528 char *p = (char *)malloc(strlen(str) + 1);
529 assert(p); // Don't handle OOM conditions
530 strcpy(p, str);
531 return p;
534 int match(char const *str, char **list)
536 int i;
538 for (i=0; *list; i++, list++)
539 if (strcmp(str, *list) == 0)
540 return i;
541 return -1;
545 * Get the next line. We only return lines beginning with '#' since that
546 * is all this program is ever interested in.
548 char *get_line(struct filepointer *filep)
550 char *p, /* walking pointer */
551 *eof, /* end of file pointer */
552 *bol; /* beginning of line pointer */
553 int lineno; /* line number */
555 p = filep->f_p;
556 eof = filep->f_end;
557 if (p >= eof)
558 return (char *)NULL;
559 lineno = filep->f_line;
561 for(bol = p--; ++p < eof; ) {
562 if (*p == '/' && *(p+1) == '*') { /* consume comments */
563 *p++ = ' ';
564 *p++ = ' ';
565 while (*p) {
566 if (*p == '*' && *(p+1) == '/') {
567 *p++ = ' ';
568 *p = ' ';
569 break;
571 else if (*p == '\n')
572 lineno++;
573 *p++ = ' ';
575 continue;
577 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
578 *p++ = ' ';
579 *p++ = ' ';
580 while (*p && *p != '\n')
581 *p++ = ' ';
582 if ( *p == '\n' )
583 p--;
584 lineno++;
585 continue;
587 else if (*p == '\\') {
588 if (*(p+1) == '\n') {
589 *p = ' ';
590 *(p+1) = ' ';
591 lineno++;
594 else if (*p == '\n') {
595 lineno++;
596 if (*bol == '#') {
597 char *cp;
599 *p++ = '\0';
600 /* punt lines with just # (yacc generated) */
601 for (cp = bol+1;
602 *cp && (*cp == ' ' || *cp == '\t'); cp++);
603 if (*cp) goto done;
605 bol = p+1;
608 if (*bol != '#')
609 bol = NULL;
610 done:
611 filep->f_p = p;
612 filep->f_line = lineno;
613 return bol;
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)
622 char *p;
624 file = copy(file);
625 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
627 if (*p == '.')
628 *p = '\0';
630 while (p > file) {
631 if ( *p == '/' || *p == '\\') {
632 file = p + 1;
633 break;
635 p--;
637 return file;
640 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
641 int rename (char *from, char *to)
643 (void) unlink (to);
644 if (link (from, to) == 0) {
645 unlink (from);
646 return 0;
647 } else {
648 return -1;
651 #endif /* USGISH */
653 void redirect(char *makefile)
655 FILE *fdout;
656 fdout = makefile ? freopen(makefile, "wb", stdout) : NULL; // binary mode please
657 if (fdout == NULL)
658 fatalerr("cannot open \"%s\"\n", makefile ? makefile : "<NULL>");
661 #if defined __GNUC__
662 __attribute__ ((format (printf, 1, 2)))
663 #endif
664 void fatalerr(char *msg, ...)
666 va_list args;
667 fprintf(stderr, "%s: error: ", ProgramName);
668 va_start(args, msg);
669 vfprintf(stderr, msg, args);
670 va_end(args);
671 exit (1);
674 #if defined __GNUC__
675 __attribute__ ((format (printf, 1, 2)))
676 #endif
677 void warning(char const *msg, ...)
679 #ifdef DEBUG_MKDEPEND
680 va_list args;
681 fprintf(stderr, "%s: warning: ", ProgramName);
682 va_start(args, msg);
683 vfprintf(stderr, msg, args);
684 va_end(args);
685 #else
686 (void)msg;
687 #endif /* DEBUG_MKDEPEND */
690 #if defined __GNUC__
691 __attribute__ ((format (printf, 1, 2)))
692 #endif
693 void warning1(char const *msg, ...)
695 #ifdef DEBUG_MKDEPEND
696 va_list args;
697 va_start(args, msg);
698 vfprintf(stderr, msg, args);
699 va_end(args);
700 #else
701 (void)msg;
702 #endif /* DEBUG_MKDEPEND */
705 void convert_slashes(char *path)
707 #if defined (_WIN32)
709 * Convert backslashes to slashes
711 char *ptr;
712 if (native_win_slashes) {
713 for (ptr = (char*)path; *ptr; ++ptr)
714 if (*ptr == '/')
715 *ptr = '\\';
716 } else {
717 for (ptr = (char*)path; *ptr; ++ptr)
718 if (*ptr == '\\')
719 *ptr = '/';
721 #else
722 (void)path;
723 #endif
726 char* append_slash(char *path)
728 char *new_string;
729 const char cLastChar = path[strlen(path) - 1];
730 if (cLastChar == '/' || cLastChar == '\\') {
731 new_string = path;
732 } else {
733 new_string = (char*)malloc(sizeof(char) * (strlen(path) + 2));
734 assert(new_string); // Don't handle OOM conditions
735 strcpy(new_string, path);
736 if (native_win_slashes)
737 strcat(new_string, "\\");
738 else
739 strcat(new_string, "/");
741 return new_string;
744 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */