Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / soltools / mkdepend / main.c
blob438db70f8e3e8e06af18a6657bb783df613c725d
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 <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 * makefile);
120 struct inclist inclist[ MAXFILES ],
121 *inclistp = inclist;
123 static 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 static char *startat = "# DO NOT DELETE";
131 static int width = 78;
132 static 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 static boolean native_win_slashes = FALSE;
166 int main(int argc, char **argv)
168 char **fp = filelist;
169 char **incp = includedirs;
170 char *p;
171 struct inclist *ip;
172 char *makefile = NULL;
173 struct filepointer *filecontent;
174 struct pair *psymp = predefs;
175 char *endmarker = NULL;
176 char *defincdir = NULL;
177 struct IncludesCollection* incCollection;
179 ProgramName = argv[0];
181 while (psymp->p_name)
183 hash_define(psymp->p_name, psymp->p_value, &maininclist);
184 psymp++;
186 if (argc == 2 && argv[1][0] == '@') {
187 struct stat ast;
188 int afd;
189 char *args;
190 char **nargv;
191 int nargc;
192 char quotechar = '\0';
194 nargc = 1;
195 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
196 fatalerr("cannot open \"%s\"\n", argv[1]+1);
197 (void)fstat(afd, &ast);
198 args = (char *)malloc(ast.st_size + 1);
199 if ((ast.st_size = read(afd, args, (size_t) ast.st_size)) < 0)
200 fatalerr("failed to read %s\n", argv[1]+1);
201 args[ast.st_size] = '\0';
202 close(afd);
203 for (p = args; *p; p++) {
204 if (quotechar) {
205 if (quotechar == '\\'
206 || (*p == quotechar && p[-1] != '\\'))
207 quotechar = '\0';
208 continue;
210 switch (*p) {
211 case '\\':
212 case '"':
213 case '\'':
214 quotechar = *p;
215 break;
216 case ' ':
217 case '\n':
218 *p = '\0';
219 if (p > args && p[-1])
220 nargc++;
221 break;
224 if (p[-1])
225 nargc++;
226 nargv = (char **)malloc(nargc * sizeof(char *));
227 nargv[0] = argv[0];
228 argc = 1;
229 for (p = args; argc < nargc; p += strlen(p) + 1)
230 if (*p) nargv[argc++] = p;
231 argv = nargv;
233 for(argc--, argv++; argc; argc--, argv++) {
234 /* if looking for endmarker then check before parsing */
235 if (endmarker && strcmp (endmarker, *argv) == 0) {
236 endmarker = NULL;
237 continue;
239 if (**argv != '-') {
240 /* treat +thing as an option for C++ */
241 if (endmarker && **argv == '+')
242 continue;
243 *fp++ = argv[0];
244 continue;
246 switch(argv[0][1]) {
247 case '-':
248 endmarker = &argv[0][2];
249 if (endmarker[0] == '\0') endmarker = "--";
250 break;
251 case 'D':
252 if (argv[0][2] == '\0') {
253 argv++;
254 argc--;
256 for (p=argv[0] + 2; *p ; p++)
257 if (*p == '=') {
258 *p = ' ';
259 break;
261 define(argv[0] + 2, &maininclist);
262 break;
263 case 'I':
264 if (incp >= includedirs + MAXDIRS)
265 fatalerr("Too many -I flags.\n");
266 *incp++ = argv[0]+2;
267 if (**(incp-1) == '\0') {
268 *(incp-1) = *(++argv);
269 argc--;
271 break;
272 case 'Y':
273 defincdir = argv[0]+2;
274 break;
275 /* do not use if endmarker processing */
276 case 'a':
277 if (endmarker) break;
278 append = TRUE;
279 break;
280 case 'w':
281 if (endmarker) break;
282 if (argv[0][2] == '\0') {
283 argv++;
284 argc--;
285 width = atoi(argv[0]);
286 } else
287 width = atoi(argv[0]+2);
288 break;
289 case 'n':
290 // Use "-n" switch to generate dependencies with windows-native slash style
291 native_win_slashes = TRUE;
292 break;
293 case 'o':
294 if (endmarker) break;
295 if (argv[0][2] == '\0') {
296 argv++;
297 argc--;
298 objsuffix = argv[0];
299 } else
300 objsuffix = argv[0]+2;
301 break;
302 case 'p':
303 if (endmarker) break;
304 if (argv[0][2] == '\0') {
305 argv++;
306 argc--;
307 objprefix = argv[0];
308 } else
309 objprefix = argv[0]+2;
310 break;
311 case 'v':
312 if (endmarker) break;
313 verbose = TRUE;
314 #ifdef DEBUG
315 if (argv[0][2])
316 _debugmask = atoi(argv[0]+2);
317 #endif
318 break;
319 case 's':
320 if (endmarker) break;
321 startat = argv[0]+2;
322 if (*startat == '\0') {
323 startat = *(++argv);
324 argc--;
326 if (*startat != '#')
327 fatalerr("-s flag's value should start %s\n",
328 "with '#'.");
329 break;
330 case 'f':
331 if (endmarker) break;
332 makefile = argv[0]+2;
333 if (*makefile == '\0') {
334 makefile = *(++argv);
335 argc--;
337 break;
339 case 'm':
340 warn_multiple = TRUE;
341 break;
343 /* Ignore -O, -g so we can just pass ${CFLAGS} to
344 makedepend
346 case 'O':
347 case 'g':
348 break;
349 default:
350 if (endmarker) break;
351 warning("ignoring option %s\n", argv[0]);
355 convert_slashes(objprefix);
356 objprefix = append_slash(objprefix);
358 if (!defincdir) {
359 #ifdef PREINCDIR
360 if (incp >= includedirs + MAXDIRS)
361 fatalerr("Too many -I flags.\n");
362 *incp++ = PREINCDIR;
363 #endif
364 if (incp >= includedirs + MAXDIRS)
365 fatalerr("Too many -I flags.\n");
366 *incp++ = INCLUDEDIR;
367 #ifdef POSTINCDIR
368 if (incp >= includedirs + MAXDIRS)
369 fatalerr("Too many -I flags.\n");
370 *incp++ = POSTINCDIR;
371 #endif
372 } else if (*defincdir) {
373 if (incp >= includedirs + MAXDIRS)
374 fatalerr("Too many -I flags.\n");
375 *incp++ = defincdir;
378 redirect(makefile);
381 * catch signals.
383 #ifdef USGISH
384 /* should really reset SIGINT to SIG_IGN if it was. */
385 #ifdef SIGHUP
386 signal (SIGHUP, catch);
387 #endif
388 signal (SIGINT, catch);
389 #ifdef SIGQUIT
390 signal (SIGQUIT, catch);
391 #endif
392 signal (SIGILL, catch);
393 #ifdef SIGBUS
394 signal (SIGBUS, catch);
395 #endif
396 signal (SIGSEGV, catch);
397 #ifdef SIGSYS
398 signal (SIGSYS, catch);
399 #endif
400 signal (SIGFPE, catch);
401 #else
402 sig_act.sa_handler = catch;
403 #ifdef _POSIX_SOURCE
404 sigemptyset(&sig_act.sa_mask);
405 sigaddset(&sig_act.sa_mask, SIGINT);
406 sigaddset(&sig_act.sa_mask, SIGQUIT);
407 #ifdef SIGBUS
408 sigaddset(&sig_act.sa_mask, SIGBUS);
409 #endif
410 sigaddset(&sig_act.sa_mask, SIGILL);
411 sigaddset(&sig_act.sa_mask, SIGSEGV);
412 sigaddset(&sig_act.sa_mask, SIGHUP);
413 sigaddset(&sig_act.sa_mask, SIGPIPE);
414 #ifdef SIGSYS
415 sigaddset(&sig_act.sa_mask, SIGSYS);
416 #endif
417 #else
418 sig_act.sa_mask = ((1<<(SIGINT -1))
419 |(1<<(SIGQUIT-1))
420 #ifdef SIGBUS
421 |(1<<(SIGBUS-1))
422 #endif
423 |(1<<(SIGILL-1))
424 |(1<<(SIGSEGV-1))
425 |(1<<(SIGHUP-1))
426 |(1<<(SIGPIPE-1))
427 #ifdef SIGSYS
428 |(1<<(SIGSYS-1))
429 #endif
431 #endif /* _POSIX_SOURCE */
432 sig_act.sa_flags = 0;
433 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
434 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
435 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
436 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
437 #ifdef SIGBUS
438 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
439 #endif
440 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
441 #ifdef SIGSYS
442 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
443 #endif
444 #endif /* USGISH */
447 * now peruse through the list of files.
449 incCollection = create_IncludesCollection();
451 for(fp=filelist; *fp; fp++) {
452 struct symhash *includes;
453 filecontent = getfile(*fp);
454 ip = newinclude(*fp, (char *)NULL);
456 includes = hash_copy( maininclist );
457 find_includes(filecontent, ip, ip, 0, FALSE, incCollection, includes);
458 hash_free( includes );
460 freefile(filecontent);
461 recursive_pr_include(ip, ip->i_file, base_name(*fp));
462 if (printed)
463 fwrite("\n\n", 2, 1, stdout);
464 recursive_pr_dummy(ip, ip->i_file);
465 inc_clean();
467 if (printed)
468 printf("\n");
470 delete_IncludesCollection(incCollection);
472 exit(0);
475 struct filepointer *getfile(char *file)
477 int fd;
478 struct filepointer *content;
479 struct stat st;
480 off_t size_backup;
481 ssize_t bytes_read;
482 unsigned malloc_size;
484 content = (struct filepointer *)malloc(sizeof(struct filepointer));
485 if ((fd = open(file, O_RDONLY)) < 0) {
486 warning("makedepend: Cannot open file \"%s\"\n", file);
487 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
488 *content->f_p = '\0';
489 return content;
491 (void)fstat(fd, &st);
493 size_backup = st.st_size;
494 malloc_size = size_backup;
495 /* Since off_t usually is larger than unsigned, need to test for
496 * truncation.
498 if ( (off_t)malloc_size != size_backup )
500 close( fd );
501 warning("makedepend: File \"%s\" is too large.\n", file);
502 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
503 *content->f_p = '\0';
504 return content;
507 content->f_base = (char *)malloc(malloc_size+1);
508 if (content->f_base == NULL)
509 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file);
510 if ((bytes_read = read(fd, content->f_base, malloc_size)) < 0)
511 if ( st.st_mode & S_IFREG )
512 fatalerr("makedepend: Failed to read file \"%s\"\n", file);
514 close(fd);
515 content->f_len = bytes_read+1;
516 content->f_p = content->f_base;
517 content->f_end = content->f_base + bytes_read;
518 *content->f_end = '\0';
519 content->f_line = 0;
520 return content;
523 void freefile(struct filepointer *fp)
525 free(fp->f_base);
526 free(fp);
529 char *copy(char *str)
531 char *p = (char *)malloc(strlen(str) + 1);
533 strcpy(p, str);
534 return p;
537 int match(char *str, char **list)
539 int i;
541 for (i=0; *list; i++, list++)
542 if (strcmp(str, *list) == 0)
543 return i;
544 return -1;
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(struct filepointer *filep)
553 char *p, /* walking pointer */
554 *eof, /* end of file pointer */
555 *bol; /* beginning of line pointer */
556 int lineno; /* line number */
558 p = filep->f_p;
559 eof = filep->f_end;
560 if (p >= eof)
561 return (char *)NULL;
562 lineno = filep->f_line;
564 for(bol = p--; ++p < eof; ) {
565 if (*p == '/' && *(p+1) == '*') { /* consume comments */
566 *p++ = ' ';
567 *p++ = ' ';
568 while (*p) {
569 if (*p == '*' && *(p+1) == '/') {
570 *p++ = ' ';
571 *p = ' ';
572 break;
574 else if (*p == '\n')
575 lineno++;
576 *p++ = ' ';
578 continue;
580 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
581 *p++ = ' ';
582 *p++ = ' ';
583 while (*p && *p != '\n')
584 *p++ = ' ';
585 if ( *p == '\n' )
586 p--;
587 lineno++;
588 continue;
590 else if (*p == '\\') {
591 if (*(p+1) == '\n') {
592 *p = ' ';
593 *(p+1) = ' ';
594 lineno++;
597 else if (*p == '\n') {
598 lineno++;
599 if (*bol == '#') {
600 char *cp;
602 *p++ = '\0';
603 /* punt lines with just # (yacc generated) */
604 for (cp = bol+1;
605 *cp && (*cp == ' ' || *cp == '\t'); cp++);
606 if (*cp) goto done;
608 bol = p+1;
611 if (*bol != '#')
612 bol = NULL;
613 done:
614 filep->f_p = p;
615 filep->f_line = lineno;
616 return bol;
620 * Strip the file name down to what we want to see in the Makefile.
621 * It will have objprefix and objsuffix around it.
623 char *base_name(char *file)
625 char *p;
627 file = copy(file);
628 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
630 if (*p == '.')
631 *p = '\0';
633 while (p > file) {
634 if ( *p == '/' || *p == '\\') {
635 file = p + 1;
636 break;
638 p--;
640 return file;
643 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
644 int rename (char *from, char *to)
646 (void) unlink (to);
647 if (link (from, to) == 0) {
648 unlink (from);
649 return 0;
650 } else {
651 return -1;
654 #endif /* USGISH */
656 void redirect(char *makefile)
658 FILE *fdout;
659 fdout = makefile ? freopen(makefile, "wb", stdout) : NULL; // binary mode please
660 if (fdout == NULL)
661 fatalerr("cannot open \"%s\"\n", makefile ? makefile : "<NULL>");
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 void warning(char *msg, ...)
676 #ifdef DEBUG_MKDEPEND
677 va_list args;
678 fprintf(stderr, "%s: warning: ", ProgramName);
679 va_start(args, msg);
680 vfprintf(stderr, msg, args);
681 va_end(args);
682 #else
683 (void)msg;
684 #endif /* DEBUG_MKDEPEND */
687 void warning1(char *msg, ...)
689 #ifdef DEBUG_MKDEPEND
690 va_list args;
691 va_start(args, msg);
692 vfprintf(stderr, msg, args);
693 va_end(args);
694 #else
695 (void)msg;
696 #endif /* DEBUG_MKDEPEND */
699 void convert_slashes(char *path)
701 #if defined (_WIN32)
703 * Convert backslashes to slashes
705 char *ptr;
706 if (native_win_slashes) {
707 for (ptr = (char*)path; *ptr; ++ptr)
708 if (*ptr == '/')
709 *ptr = '\\';
710 } else {
711 for (ptr = (char*)path; *ptr; ++ptr)
712 if (*ptr == '\\')
713 *ptr = '/';
715 #else
716 (void)path;
717 #endif
720 char* append_slash(char *path)
722 char *new_string;
723 const char cLastChar = path[strlen(path) - 1];
724 if (cLastChar == '/' || cLastChar == '\\') {
725 new_string = path;
726 } else {
727 new_string = (char*)malloc(sizeof(char) * (strlen(path) + 2));
728 strcpy(new_string, path);
729 if (native_win_slashes)
730 strcat(new_string, "\\");
731 else
732 strcat(new_string, "/");
734 return new_string;
737 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */