merge the formfield patch from ooo-build
[ooovba.git] / soltools / mkdepend / main.c
blob7295a5d3f046f87223f35623a7e022168214a1da
1 /* $XConsortium: main.c,v 1.84 94/11/30 16:10:44 kaleb Exp $ */
2 /* $XFree86: xc/config/makedepend/main.c,v 3.4 1995/07/15 14:53:49 dawes Exp $ */
3 /*
5 Copyright (c) 1993, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
30 #if defined(FREEBSD) || defined(MACOSX)
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #endif
35 #ifdef _MSC_VER /* Define ssize_t */
37 #if !defined(_W64)
38 #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
39 #define _W64 __w64
40 #else
41 #define _W64
42 #endif
43 #endif
45 #ifdef _WIN64
46 typedef __int64 ssize_t;
47 #else
48 typedef _W64 int ssize_t;
49 #endif
51 #endif
53 #include "def.h"
54 #include <string.h>
55 #ifdef hpux
56 #define sigvec sigvector
57 #endif /* hpux */
59 #ifdef X_POSIX_C_SOURCE
60 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
61 #include <signal.h>
62 #undef _POSIX_C_SOURCE
63 #else
64 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
65 #include <signal.h>
66 #else
67 #define _POSIX_SOURCE
68 #include <signal.h>
69 #undef _POSIX_SOURCE
70 #endif
71 #endif
73 #if NeedVarargsPrototypes
74 #include <stdarg.h>
75 #endif
77 #ifdef MINIX
78 #define USE_CHMOD 1
79 #endif
81 #ifdef DEBUG
82 int _debugmask;
83 #endif
85 char *ProgramName;
87 #define OBJSUFFIX ".obj"
88 #define INCLUDEDIR "."
90 char *directives[] = {
91 "if",
92 "ifdef",
93 "ifndef",
94 "else",
95 "endif",
96 "define",
97 "undef",
98 "include",
99 "line",
100 "pragma",
101 "error",
102 "ident",
103 "sccs",
104 "elif",
105 "eject",
106 NULL
109 #define MAKEDEPEND
110 #include "imakemdep.h" /* from config sources */
111 #undef MAKEDEPEND
113 /******* function declarations ********/
114 /******* added by -Wall project *******/
115 void freefile(struct filepointer * fp);
116 void redirect(char * line, char * makefile );
118 struct inclist inclist[ MAXFILES ],
119 *inclistp = inclist;
121 struct symhash *maininclist = NULL;
123 char *filelist[ MAXFILES ];
124 char *includedirs[ MAXDIRS + 1 ];
125 char *notdotdot[ MAXDIRS ];
126 char *objprefix = "";
127 char *objsuffix = OBJSUFFIX;
128 char *startat = "# DO NOT DELETE";
129 int width = 78;
130 boolean append = FALSE;
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 (sig)
143 int sig;
145 fflush (stdout);
146 fatalerr ("got signal %d\n", sig);
149 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(OS2) || defined(Lynx_22)
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 struct sigaction sig_act;
161 #endif /* USGISH */
163 boolean native_win_slashes = FALSE;
165 int main(argc, argv)
166 int argc;
167 char **argv;
169 register char **fp = filelist;
170 register char **incp = includedirs;
171 register char *p;
172 register struct inclist *ip;
173 char *makefile = NULL;
174 struct filepointer *filecontent;
175 struct pair *psymp = predefs;
176 char *endmarker = NULL;
177 char *defincdir = NULL;
178 struct IncludesCollection* incCollection;
180 ProgramName = argv[0];
182 while (psymp->p_name)
184 hash_define(psymp->p_name, psymp->p_value, &maininclist);
185 psymp++;
187 if (argc == 2 && argv[1][0] == '@') {
188 struct stat ast;
189 int afd;
190 char *args;
191 char **nargv;
192 int nargc;
193 char quotechar = '\0';
195 nargc = 1;
196 if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
197 fatalerr("cannot open \"%s\"\n", argv[1]+1);
198 fstat(afd, &ast);
199 args = (char *)malloc(ast.st_size + 1);
200 if ((ast.st_size = read(afd, args, (size_t) ast.st_size)) < 0)
201 fatalerr("failed to read %s\n", argv[1]+1);
202 args[ast.st_size] = '\0';
203 close(afd);
204 for (p = args; *p; p++) {
205 if (quotechar) {
206 if (quotechar == '\\' ||
207 (*p == quotechar && p[-1] != '\\'))
208 quotechar = '\0';
209 continue;
211 switch (*p) {
212 case '\\':
213 case '"':
214 case '\'':
215 quotechar = *p;
216 break;
217 case ' ':
218 case '\n':
219 *p = '\0';
220 if (p > args && p[-1])
221 nargc++;
222 break;
225 if (p[-1])
226 nargc++;
227 nargv = (char **)malloc(nargc * sizeof(char *));
228 nargv[0] = argv[0];
229 argc = 1;
230 for (p = args; argc < nargc; p += strlen(p) + 1)
231 if (*p) nargv[argc++] = p;
232 argv = nargv;
234 for(argc--, argv++; argc; argc--, argv++) {
235 /* if looking for endmarker then check before parsing */
236 if (endmarker && strcmp (endmarker, *argv) == 0) {
237 endmarker = NULL;
238 continue;
240 if (**argv != '-') {
241 /* treat +thing as an option for C++ */
242 if (endmarker && **argv == '+')
243 continue;
244 *fp++ = argv[0];
245 continue;
247 switch(argv[0][1]) {
248 case '-':
249 endmarker = &argv[0][2];
250 if (endmarker[0] == '\0') endmarker = "--";
251 break;
252 case 'D':
253 if (argv[0][2] == '\0') {
254 argv++;
255 argc--;
257 for (p=argv[0] + 2; *p ; p++)
258 if (*p == '=') {
259 *p = ' ';
260 break;
262 define(argv[0] + 2, &maininclist);
263 break;
264 case 'I':
265 if (incp >= includedirs + MAXDIRS)
266 fatalerr("Too many -I flags.\n");
267 *incp++ = argv[0]+2;
268 if (**(incp-1) == '\0') {
269 *(incp-1) = *(++argv);
270 argc--;
272 break;
273 case 'Y':
274 defincdir = argv[0]+2;
275 break;
276 /* do not use if endmarker processing */
277 case 'a':
278 if (endmarker) break;
279 append = TRUE;
280 break;
281 case 'w':
282 if (endmarker) break;
283 if (argv[0][2] == '\0') {
284 argv++;
285 argc--;
286 width = atoi(argv[0]);
287 } else
288 width = atoi(argv[0]+2);
289 break;
290 case 'n':
291 // Use "-n" switch to generate dependencies with windows-native slash style
292 native_win_slashes = TRUE;
293 break;
294 case 'o':
295 if (endmarker) break;
296 if (argv[0][2] == '\0') {
297 argv++;
298 argc--;
299 objsuffix = argv[0];
300 } else
301 objsuffix = argv[0]+2;
302 break;
303 case 'p':
304 if (endmarker) break;
305 if (argv[0][2] == '\0') {
306 argv++;
307 argc--;
308 objprefix = argv[0];
309 } else
310 objprefix = argv[0]+2;
311 break;
312 case 'v':
313 if (endmarker) break;
314 verbose = TRUE;
315 #ifdef DEBUG
316 if (argv[0][2])
317 _debugmask = atoi(argv[0]+2);
318 #endif
319 break;
320 case 's':
321 if (endmarker) break;
322 startat = argv[0]+2;
323 if (*startat == '\0') {
324 startat = *(++argv);
325 argc--;
327 if (*startat != '#')
328 fatalerr("-s flag's value should start %s\n",
329 "with '#'.");
330 break;
331 case 'f':
332 if (endmarker) break;
333 makefile = argv[0]+2;
334 if (*makefile == '\0') {
335 makefile = *(++argv);
336 argc--;
338 break;
340 case 'm':
341 warn_multiple = TRUE;
342 break;
344 /* Ignore -O, -g so we can just pass ${CFLAGS} to
345 makedepend
347 case 'O':
348 case 'g':
349 break;
350 default:
351 if (endmarker) break;
352 /* fatalerr("unknown opt = %s\n", argv[0]); */
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 inc_clean();
466 if (printed)
467 printf("\n");
468 exit(0);
471 struct filepointer *getfile(file)
472 char *file;
474 register int fd;
475 struct filepointer *content;
476 struct stat st;
477 off_t size_backup;
478 ssize_t bytes_read;
479 size_t malloc_size;
481 content = (struct filepointer *)malloc(sizeof(struct filepointer));
482 if ((fd = open(file, O_RDONLY)) < 0) {
483 warning("makedepend: Cannot open file \"%s\"\n", file);
484 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
485 *content->f_p = '\0';
486 return(content);
488 fstat(fd, &st);
490 size_backup = st.st_size;
491 malloc_size = size_backup;
492 /* Since off_t is larger than size_t, need to test for
493 * truncation.
495 if ( malloc_size != size_backup )
497 close( fd );
498 warning("makedepend: File \"%s\" size larger than can fit in size_t. Cannot allocate memory for contents.\n", file);
499 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
500 *content->f_p = '\0';
501 return(content);
504 content->f_base = (char *)malloc(malloc_size+1);
505 if (content->f_base == NULL)
506 fatalerr("makedepend: Cannot allocate memory to process file \"%s\"\n", file);
507 if ((bytes_read = read(fd, content->f_base, malloc_size)) < 0)
508 if ( st.st_mode & S_IFREG )
509 fatalerr("makedepend: Failed to read file \"%s\"\n", file);
511 close(fd);
512 content->f_len = bytes_read+1;
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(fp)
521 struct filepointer *fp;
523 free(fp->f_base);
524 free(fp);
527 char *copy(str)
528 register char *str;
530 register char *p = (char *)malloc(strlen(str) + 1);
532 strcpy(p, str);
533 return(p);
536 int match(str, list)
537 register char *str, **list;
539 register 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(filep)
552 register struct filepointer *filep;
554 register char *p, /* walking pointer */
555 *eof, /* end of file pointer */
556 *bol; /* beginning of line pointer */
557 register int lineno; /* line number */
559 p = filep->f_p;
560 eof = filep->f_end;
561 if (p >= eof)
562 return((char *)NULL);
563 lineno = filep->f_line;
565 for(bol = p--; ++p < eof; ) {
566 if (*p == '/' && *(p+1) == '*') { /* consume comments */
567 *p++ = ' ', *p++ = ' ';
568 while (*p) {
569 if (*p == '*' && *(p+1) == '/') {
570 *p++ = ' ', *p = ' ';
571 break;
573 else if (*p == '\n')
574 lineno++;
575 *p++ = ' ';
577 continue;
579 else if (*p == '/' && *(p+1) == '/') { /* consume comments */
580 *p++ = ' ', *p++ = ' ';
581 while (*p && *p != '\n')
582 *p++ = ' ';
583 if ( *p == '\n' )
584 p--;
585 lineno++;
586 continue;
588 else if (*p == '\\') {
589 if (*(p+1) == '\n') {
590 *p = ' ';
591 *(p+1) = ' ';
592 lineno++;
595 else if (*p == '\n') {
596 lineno++;
597 if (*bol == '#') {
598 register char *cp;
600 *p++ = '\0';
601 /* punt lines with just # (yacc generated) */
602 for (cp = bol+1;
603 *cp && (*cp == ' ' || *cp == '\t'); cp++);
604 if (*cp) goto done;
606 bol = p+1;
609 if (*bol != '#')
610 bol = NULL;
611 done:
612 filep->f_p = p;
613 filep->f_line = lineno;
614 return(bol);
618 * Strip the file name down to what we want to see in the Makefile.
619 * It will have objprefix and objsuffix around it.
621 char *base_name(file)
622 register char *file;
624 register char *p;
626 file = copy(file);
627 for(p=file+strlen(file); p>file && *p != '.'; p--) ;
629 if (*p == '.')
630 *p = '\0';
632 while (p > file) {
633 if ( *p == '/' || *p == '\\') {
634 file = p + 1;
635 break;
637 p--;
639 return(file);
642 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
643 int rename (from, to)
644 char *from, *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(line, makefile)
657 char *line,
658 *makefile;
660 struct stat st;
661 FILE *fdin, *fdout;
662 char backup[ BUFSIZ ],
663 buf[ BUFSIZ ];
664 boolean found = FALSE;
665 int len;
668 * if makefile is "-" then let it pour onto stdout.
670 if (makefile && *makefile == '-' && *(makefile+1) == '\0')
671 return;
674 * use a default makefile is not specified.
676 if (!makefile) {
677 if (stat("Makefile", &st) == 0)
678 makefile = "Makefile";
679 else if (stat("makefile", &st) == 0)
680 makefile = "makefile";
681 else
682 fatalerr("[mM]akefile is not present\n");
684 else
685 stat(makefile, &st);
686 if ((fdin = fopen(makefile, "r")) == NULL)
687 fatalerr("cannot open \"%s\"\n", makefile);
688 sprintf(backup, "%s.bak", makefile);
689 unlink(backup);
690 #if defined(WIN32) || defined(OS2)
691 fclose(fdin);
692 #endif
693 if (rename(makefile, backup) < 0)
694 fatalerr("cannot rename %s to %s\n", makefile, backup);
695 #if defined(WIN32) || defined(OS2)
696 if ((fdin = fopen(backup, "r")) == NULL)
697 fatalerr("cannot open \"%s\"\n", backup);
698 #endif
699 if ((fdout = freopen(makefile, "w", stdout)) == NULL)
700 fatalerr("cannot open \"%s\"\n", backup);
701 len = strlen(line);
702 while (!found && fgets(buf, BUFSIZ, fdin)) {
703 if (*buf == '#' && strncmp(line, buf, len) == 0)
704 found = TRUE;
705 fputs(buf, fdout);
707 if (!found) {
708 if (verbose)
709 warning("Adding new delimiting line \"%s\" and dependencies...\n",
710 line);
711 puts(line); /* same as fputs(fdout); but with newline */
712 } else if (append) {
713 while (fgets(buf, BUFSIZ, fdin)) {
714 fputs(buf, fdout);
717 fflush(fdout);
718 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
719 chmod(makefile, st.st_mode);
720 #else
721 fchmod(fileno(fdout), st.st_mode);
722 #endif /* USGISH */
725 #if NeedVarargsPrototypes
726 int fatalerr(char *msg, ...)
727 #else
728 /*VARARGS*/
729 int fatalerr(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
730 char *msg;
731 #endif
733 #if NeedVarargsPrototypes
734 va_list args;
735 #endif
736 fprintf(stderr, "%s: error: ", ProgramName);
737 #if NeedVarargsPrototypes
738 va_start(args, msg);
739 vfprintf(stderr, msg, args);
740 va_end(args);
741 #else
742 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
743 #endif
744 exit (1);
747 #if NeedVarargsPrototypes
748 int warning(char *msg, ...)
749 #else
750 /*VARARGS0*/
751 int warning(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
752 char *msg;
753 #endif
755 #ifdef DEBUG_MKDEPEND
756 #if NeedVarargsPrototypes
757 va_list args;
758 #endif
759 fprintf(stderr, "%s: warning: ", ProgramName);
760 #if NeedVarargsPrototypes
761 va_start(args, msg);
762 vfprintf(stderr, msg, args);
763 va_end(args);
764 #else
765 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
766 #endif
767 #endif /* DEBUG_MKDEPEND */
768 return 0;
771 #if NeedVarargsPrototypes
772 void warning1(char *msg, ...)
773 #else
774 /*VARARGS0*/
775 void warning1(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
776 char *msg;
777 #endif
779 #ifdef DEBUG_MKDEPEND
780 #if NeedVarargsPrototypes
781 va_list args;
782 va_start(args, msg);
783 vfprintf(stderr, msg, args);
784 va_end(args);
785 #else
786 fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
787 #endif
788 #endif /* DEBUG_MKDEPEND */
791 void convert_slashes(path)
792 char* path;
794 #if defined (WNT) || defined(OS2)
796 * Convert backslashes to slashes
798 char *ptr;
799 if (native_win_slashes) {
800 for (ptr = (char*)path; *ptr; ++ptr)
801 if (*ptr == '/')
802 *ptr = '\\';
803 } else {
804 for (ptr = (char*)path; *ptr; ++ptr)
805 if (*ptr == '\\')
806 *ptr = '/';
808 #endif
811 char* append_slash(path)
812 char* path;
814 char *ptr, *new_string;
815 if ((path[strlen(path) - 1] == '/') || (path[strlen(path) - 1] == '\\')) {
816 new_string = path;
817 } else {
818 new_string = (char*)malloc(sizeof(char) * (strlen(path) + 2));
819 strcpy(new_string, path);
820 if (native_win_slashes)
821 strcat(new_string, "\\");
822 else
823 strcat(new_string, "/");
825 return new_string;