bnc#887230: sd_export_ooxml1: Add unittest
[LibreOffice.git] / soltools / mkdepend / main.c
blobb8b84b4534763389f3f8204153570d8ea4ba2484
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>
81 #ifdef MINIX
82 #define USE_CHMOD 1
83 #endif
85 #ifdef DEBUG
86 int _debugmask;
87 #endif
89 static char *ProgramName;
91 #define OBJSUFFIX ".obj"
92 #define INCLUDEDIR "."
94 char *directives[] = {
95 "if",
96 "ifdef",
97 "ifndef",
98 "else",
99 "endif",
100 "define",
101 "undef",
102 "include",
103 "line",
104 "pragma",
105 "error",
106 "ident",
107 "sccs",
108 "elif",
109 "eject",
110 NULL
113 #define MAKEDEPEND
114 #include "imakemdep.h" /* from config sources */
115 #undef MAKEDEPEND
117 /******* function declarations ********/
118 /******* added by -Wall project *******/
119 static void redirect(char * makefile);
121 struct inclist inclist[ MAXFILES ];
122 struct inclist *inclistp = inclist;
124 static struct symhash *maininclist = NULL;
126 static char *filelist[ MAXFILES ];
127 char *includedirs[ MAXDIRS + 1 ];
128 char *objprefix = "";
129 char *objsuffix = OBJSUFFIX;
130 static char *startat = "# DO NOT DELETE";
131 boolean printed = FALSE;
132 boolean verbose = FALSE;
133 boolean show_where_not = FALSE;
134 boolean warn_multiple = FALSE; /* Warn on multiple includes of same file */
136 static
137 #ifdef SIGNALRETURNSINT
139 #else
140 void
141 #endif
142 catch (int sig)
144 fflush (stdout);
145 fatalerr ("got signal %d\n", sig);
148 #if (defined(i386) && defined(SYSV)) || defined(_WIN32)
149 #define USGISH
150 #endif
152 #ifndef USGISH
153 #ifndef _POSIX_SOURCE
154 #define sigaction sigvec
155 #define sa_handler sv_handler
156 #define sa_mask sv_mask
157 #define sa_flags sv_flags
158 #endif
159 static struct sigaction sig_act;
160 #endif /* USGISH */
162 static boolean native_win_slashes = FALSE;
164 int main(int argc, char **argv)
166 char **fp = filelist;
167 char **incp = includedirs;
168 char *p;
169 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);
182 psymp++;
184 if (argc == 2 && argv[1][0] == '@') {
185 struct stat ast;
186 int afd;
187 char *args;
188 char **nargv;
189 int nargc;
190 char quotechar = '\0';
192 nargc = 1;
193 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
194 fatalerr("cannot open \"%s\"\n", argv[1]+1);
195 (void)fstat(afd, &ast);
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';
200 close(afd);
201 for (p = args; *p; p++) {
202 if (quotechar) {
203 if (quotechar == '\\'
204 || (*p == quotechar && p[-1] != '\\'))
205 quotechar = '\0';
206 continue;
208 switch (*p) {
209 case '\\':
210 case '"':
211 case '\'':
212 quotechar = *p;
213 break;
214 case ' ':
215 case '\n':
216 *p = '\0';
217 if (p > args && p[-1])
218 nargc++;
219 break;
222 if (p[-1])
223 nargc++;
224 nargv = (char **)malloc(nargc * sizeof(char *));
225 nargv[0] = argv[0];
226 argc = 1;
227 for (p = args; argc < nargc; p += strlen(p) + 1)
228 if (*p) nargv[argc++] = p;
229 argv = nargv;
231 for(argc--, argv++; argc; argc--, argv++) {
232 /* if looking for endmarker then check before parsing */
233 if (endmarker && strcmp (endmarker, *argv) == 0) {
234 endmarker = NULL;
235 continue;
237 if (**argv != '-') {
238 /* treat +thing as an option for C++ */
239 if (endmarker && **argv == '+')
240 continue;
241 *fp++ = argv[0];
242 continue;
244 switch(argv[0][1]) {
245 case '-':
246 endmarker = &argv[0][2];
247 if (endmarker[0] == '\0') endmarker = "--";
248 break;
249 case 'D':
250 if (argv[0][2] == '\0') {
251 argv++;
252 argc--;
254 for (p=argv[0] + 2; *p ; p++)
255 if (*p == '=') {
256 *p = ' ';
257 break;
259 define(argv[0] + 2, &maininclist);
260 break;
261 case 'I':
262 if (incp >= includedirs + MAXDIRS)
263 fatalerr("Too many -I flags.\n");
264 *incp++ = argv[0]+2;
265 if (**(incp-1) == '\0') {
266 *(incp-1) = *(++argv);
267 argc--;
269 break;
270 case 'Y':
271 defincdir = argv[0]+2;
272 break;
273 /* do not use if endmarker processing */
274 case 'a':
275 break;
276 case 'w':
277 if (endmarker) break;
278 if (argv[0][2] == '\0') {
279 argv++;
280 argc--;
282 break;
283 case 'n':
284 // Use "-n" switch to generate dependencies with windows-native slash style
285 native_win_slashes = TRUE;
286 break;
287 case 'o':
288 if (endmarker) break;
289 if (argv[0][2] == '\0') {
290 argv++;
291 argc--;
292 objsuffix = argv[0];
293 } else
294 objsuffix = argv[0]+2;
295 break;
296 case 'p':
297 if (endmarker) break;
298 if (argv[0][2] == '\0') {
299 argv++;
300 argc--;
301 objprefix = argv[0];
302 } else
303 objprefix = argv[0]+2;
304 break;
305 case 'v':
306 if (endmarker) break;
307 verbose = TRUE;
308 #ifdef DEBUG
309 if (argv[0][2])
310 _debugmask = atoi(argv[0]+2);
311 #endif
312 break;
313 case 's':
314 if (endmarker) break;
315 startat = argv[0]+2;
316 if (*startat == '\0') {
317 startat = *(++argv);
318 argc--;
320 if (*startat != '#')
321 fatalerr("-s flag's value should start %s\n",
322 "with '#'.");
323 break;
324 case 'f':
325 if (endmarker) break;
326 makefile = argv[0]+2;
327 if (*makefile == '\0') {
328 makefile = *(++argv);
329 argc--;
331 break;
333 case 'm':
334 warn_multiple = TRUE;
335 break;
337 /* Ignore -O, -g so we can just pass ${CFLAGS} to
338 makedepend
340 case 'O':
341 case 'g':
342 break;
343 default:
344 if (endmarker) break;
345 warning("ignoring option %s\n", argv[0]);
349 convert_slashes(objprefix);
350 objprefix = append_slash(objprefix);
352 if (!defincdir) {
353 #ifdef PREINCDIR
354 if (incp >= includedirs + MAXDIRS)
355 fatalerr("Too many -I flags.\n");
356 *incp++ = PREINCDIR;
357 #endif
358 if (incp >= includedirs + MAXDIRS)
359 fatalerr("Too many -I flags.\n");
360 *incp++ = INCLUDEDIR;
361 #ifdef POSTINCDIR
362 if (incp >= includedirs + MAXDIRS)
363 fatalerr("Too many -I flags.\n");
364 *incp++ = POSTINCDIR;
365 #endif
366 } else if (*defincdir) {
367 if (incp >= includedirs + MAXDIRS)
368 fatalerr("Too many -I flags.\n");
369 *incp++ = defincdir;
372 redirect(makefile);
375 * catch signals.
377 #ifdef USGISH
378 /* should really reset SIGINT to SIG_IGN if it was. */
379 #ifdef SIGHUP
380 signal (SIGHUP, catch);
381 #endif
382 signal (SIGINT, catch);
383 #ifdef SIGQUIT
384 signal (SIGQUIT, catch);
385 #endif
386 signal (SIGILL, catch);
387 #ifdef SIGBUS
388 signal (SIGBUS, catch);
389 #endif
390 signal (SIGSEGV, catch);
391 #ifdef SIGSYS
392 signal (SIGSYS, catch);
393 #endif
394 signal (SIGFPE, catch);
395 #else
396 sig_act.sa_handler = catch;
397 #ifdef _POSIX_SOURCE
398 sigemptyset(&sig_act.sa_mask);
399 sigaddset(&sig_act.sa_mask, SIGINT);
400 sigaddset(&sig_act.sa_mask, SIGQUIT);
401 #ifdef SIGBUS
402 sigaddset(&sig_act.sa_mask, SIGBUS);
403 #endif
404 sigaddset(&sig_act.sa_mask, SIGILL);
405 sigaddset(&sig_act.sa_mask, SIGSEGV);
406 sigaddset(&sig_act.sa_mask, SIGHUP);
407 sigaddset(&sig_act.sa_mask, SIGPIPE);
408 #ifdef SIGSYS
409 sigaddset(&sig_act.sa_mask, SIGSYS);
410 #endif
411 #else
412 sig_act.sa_mask = ((1<<(SIGINT -1))
413 |(1<<(SIGQUIT-1))
414 #ifdef SIGBUS
415 |(1<<(SIGBUS-1))
416 #endif
417 |(1<<(SIGILL-1))
418 |(1<<(SIGSEGV-1))
419 |(1<<(SIGHUP-1))
420 |(1<<(SIGPIPE-1))
421 #ifdef SIGSYS
422 |(1<<(SIGSYS-1))
423 #endif
425 #endif /* _POSIX_SOURCE */
426 sig_act.sa_flags = 0;
427 sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
428 sigaction(SIGINT, &sig_act, (struct sigaction *)0);
429 sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
430 sigaction(SIGILL, &sig_act, (struct sigaction *)0);
431 #ifdef SIGBUS
432 sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
433 #endif
434 sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
435 #ifdef SIGSYS
436 sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
437 #endif
438 #endif /* USGISH */
441 * now peruse through the list of files.
443 incCollection = create_IncludesCollection();
445 for(fp=filelist; *fp; fp++) {
446 struct symhash *includes;
447 filecontent = getfile(*fp);
448 ip = newinclude(*fp, (char *)NULL);
450 includes = hash_copy( maininclist );
451 find_includes(filecontent, ip, ip, 0, FALSE, incCollection, includes);
452 hash_free( includes );
454 freefile(filecontent);
455 recursive_pr_include(ip, ip->i_file, base_name(*fp));
456 if (printed)
457 fwrite("\n\n", 2, 1, stdout);
458 recursive_pr_dummy(ip, ip->i_file);
459 inc_clean();
461 if (printed)
462 printf("\n");
464 delete_IncludesCollection(incCollection);
466 exit(0);
469 struct filepointer *getfile(char *file)
471 int fd;
472 struct filepointer *content;
473 struct stat st;
474 off_t size_backup;
475 ssize_t bytes_read;
476 unsigned malloc_size;
478 content = (struct filepointer *)malloc(sizeof(struct filepointer));
479 if ((fd = open(file, O_RDONLY)) < 0) {
480 warning("makedepend: Cannot open file \"%s\"\n", file);
481 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
482 *content->f_p = '\0';
483 return content;
485 (void)fstat(fd, &st);
487 size_backup = st.st_size;
488 malloc_size = size_backup;
489 /* Since off_t usually is larger than unsigned, need to test for
490 * truncation.
492 if ( (off_t)malloc_size != size_backup )
494 close( fd );
495 warning("makedepend: File \"%s\" is too large.\n", file);
496 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
497 *content->f_p = '\0';
498 return content;
501 content->f_base = (char *)malloc(malloc_size+1);
502 if (content->f_base == NULL)
503 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file);
504 if ((bytes_read = read(fd, content->f_base, malloc_size)) < 0)
505 if ( st.st_mode & S_IFREG )
506 fatalerr("makedepend: Failed to read file \"%s\"\n", file);
508 close(fd);
509 content->f_p = content->f_base;
510 content->f_end = content->f_base + bytes_read;
511 *content->f_end = '\0';
512 content->f_line = 0;
513 return content;
516 void freefile(struct filepointer *fp)
518 free(fp->f_base);
519 free(fp);
522 char *copy(char const *str)
524 char *p = (char *)malloc(strlen(str) + 1);
525 assert(p); // Don't handle OOM conditions
526 strcpy(p, str);
527 return p;
530 int match(char const *str, char **list)
532 int i;
534 for (i=0; *list; i++, list++)
535 if (strcmp(str, *list) == 0)
536 return i;
537 return -1;
541 * Get the next line. We only return lines beginning with '#' since that
542 * is all this program is ever interested in.
544 char *get_line(struct filepointer *filep)
546 char *p, /* walking pointer */
547 *eof, /* end of file pointer */
548 *bol; /* beginning of line pointer */
549 int lineno; /* line number */
551 p = filep->f_p;
552 eof = filep->f_end;
553 if (p >= eof)
554 return (char *)NULL;
555 lineno = filep->f_line;
557 for(bol = p--; ++p < eof; ) {
558 if (*p == '/' && *(p+1) == '*') { /* consume comments */
559 *p++ = ' ';
560 *p++ = ' ';
561 while (*p) {
562 if (*p == '*' && *(p+1) == '/') {
563 *p++ = ' ';
564 *p = ' ';
565 break;
567 else if (*p == '\n')
568 lineno++;
569 *p++ = ' ';
571 continue;
573 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
574 *p++ = ' ';
575 *p++ = ' ';
576 while (*p && *p != '\n')
577 *p++ = ' ';
578 if ( *p == '\n' )
579 p--;
580 lineno++;
581 continue;
583 else if (*p == '\\') {
584 if (*(p+1) == '\n') {
585 *p = ' ';
586 *(p+1) = ' ';
587 lineno++;
590 else if (*p == '\n') {
591 lineno++;
592 if (*bol == '#') {
593 char *cp;
595 *p++ = '\0';
596 /* punt lines with just # (yacc generated) */
597 for (cp = bol+1;
598 *cp && (*cp == ' ' || *cp == '\t'); cp++);
599 if (*cp) goto done;
601 bol = p+1;
604 if (*bol != '#')
605 bol = NULL;
606 done:
607 filep->f_p = p;
608 filep->f_line = lineno;
609 return bol;
613 * Strip the file name down to what we want to see in the Makefile.
614 * It will have objprefix and objsuffix around it.
616 char *base_name(char *file)
618 char *p;
620 file = copy(file);
621 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
623 if (*p == '.')
624 *p = '\0';
626 while (p > file) {
627 if ( *p == '/' || *p == '\\') {
628 file = p + 1;
629 break;
631 p--;
633 return file;
636 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
637 int rename (char *from, char *to)
639 (void) unlink (to);
640 if (link (from, to) == 0) {
641 unlink (from);
642 return 0;
643 } else {
644 return -1;
647 #endif /* USGISH */
649 void redirect(char *makefile)
651 FILE *fdout;
652 fdout = makefile ? freopen(makefile, "wb", stdout) : NULL; // binary mode please
653 if (fdout == NULL)
654 fatalerr("cannot open \"%s\"\n", makefile ? makefile : "<NULL>");
657 #if defined __GNUC__
658 __attribute__ ((format (printf, 1, 2)))
659 #endif
660 void fatalerr(char *msg, ...)
662 va_list args;
663 fprintf(stderr, "%s: error: ", ProgramName);
664 va_start(args, msg);
665 vfprintf(stderr, msg, args);
666 va_end(args);
667 exit (1);
670 #if defined __GNUC__
671 __attribute__ ((format (printf, 1, 2)))
672 #endif
673 void warning(char const *msg, ...)
675 #ifdef DEBUG_MKDEPEND
676 va_list args;
677 fprintf(stderr, "%s: warning: ", ProgramName);
678 va_start(args, msg);
679 vfprintf(stderr, msg, args);
680 va_end(args);
681 #else
682 (void)msg;
683 #endif /* DEBUG_MKDEPEND */
686 #if defined __GNUC__
687 __attribute__ ((format (printf, 1, 2)))
688 #endif
689 void warning1(char const *msg, ...)
691 #ifdef DEBUG_MKDEPEND
692 va_list args;
693 va_start(args, msg);
694 vfprintf(stderr, msg, args);
695 va_end(args);
696 #else
697 (void)msg;
698 #endif /* DEBUG_MKDEPEND */
701 void convert_slashes(char *path)
703 #if defined (_WIN32)
705 * Convert backslashes to slashes
707 char *ptr;
708 if (native_win_slashes) {
709 for (ptr = (char*)path; *ptr; ++ptr)
710 if (*ptr == '/')
711 *ptr = '\\';
712 } else {
713 for (ptr = (char*)path; *ptr; ++ptr)
714 if (*ptr == '\\')
715 *ptr = '/';
717 #else
718 (void)path;
719 #endif
722 char* append_slash(char *path)
724 char *new_string;
725 const char cLastChar = path[strlen(path) - 1];
726 if (cLastChar == '/' || cLastChar == '\\') {
727 new_string = path;
728 } else {
729 new_string = (char*)malloc(sizeof(char) * (strlen(path) + 2));
730 assert(new_string); // Don't handle OOM conditions
731 strcpy(new_string, path);
732 if (native_win_slashes)
733 strcat(new_string, "\\");
734 else
735 strcat(new_string, "/");
737 return new_string;
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */