dtudcfonted: Resolve CID 86280
[oweals/cde.git] / cde / config / makedepend / main.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: main.c /main/86 1998/03/25 08:17:50 kaleb $ */
24 /*
25
26 Copyright (c) 1993, 1994, 1998 The Open Group
27
28 All Rights Reserved.
29
30 The above copyright notice and this permission notice shall be included in
31 all copies or substantial portions of the Software.
32
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
36 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
37 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
38 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39
40 Except as contained in this notice, the name of The Open Group shall not be
41 used in advertising or otherwise to promote the sale, use or other dealings
42 in this Software without prior written authorization from The Open Group.
43
44 */
45
46 #include "def.h"
47 #ifdef hpux
48 #define sigvec sigvector
49 #endif /* hpux */
50
51 #ifdef X_POSIX_C_SOURCE
52 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
53 #include <signal.h>
54 #undef _POSIX_C_SOURCE
55 #else
56 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
57 #include <signal.h>
58 #else
59 #define _POSIX_SOURCE
60 #include <signal.h>
61 #undef _POSIX_SOURCE
62 #endif
63 #endif
64
65 #if NeedVarargsPrototypes
66 #include <stdarg.h>
67 #endif
68
69 #ifdef DEBUG
70 int     _debugmask;
71 #endif
72
73 char *ProgramName;
74
75 char    *directives[] = {
76         "if",
77         "ifdef",
78         "ifndef",
79         "else",
80         "endif",
81         "define",
82         "undef",
83         "include",
84         "line",
85         "pragma",
86         "error",
87         "ident",
88         "sccs",
89         "elif",
90         "eject",
91         "warning",
92         NULL
93 };
94
95 #define MAKEDEPEND
96 #include "imakemdep.h"  /* from config sources */
97 #undef MAKEDEPEND
98
99 struct  inclist inclist[ MAXFILES ],
100                 *inclistp = inclist,
101                 maininclist;
102
103 char    *filelist[ MAXFILES ];
104 char    *includedirs[ MAXDIRS + 1 ];
105 char    *notdotdot[ MAXDIRS ];
106 char    *objprefix = "";
107 char    *objsuffix = OBJSUFFIX;
108 char    *startat = "# DO NOT DELETE";
109 int     width = 78;
110 boolean append = FALSE;
111 boolean printed = FALSE;
112 boolean verbose = FALSE;
113 boolean show_where_not = FALSE;
114 boolean warn_multiple = FALSE;  /* Warn on multiple includes of same file */
115
116 void freefile();
117 void redirect();
118 #if !NeedVarargsPrototypes
119 void fatalerr();
120 void warning();
121 void warning1();
122 #endif
123
124 static
125 #ifdef SIGNALRETURNSINT
126 int
127 #else
128 void
129 #endif
130 catch (sig)
131     int sig;
132 {
133         fflush (stdout);
134         fatalerr ("got signal %d\n", sig);
135 }
136
137 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32)
138 #define USGISH
139 #endif
140
141 #ifndef USGISH
142 #ifndef _POSIX_SOURCE
143 #define sigaction sigvec
144 #define sa_handler sv_handler
145 #define sa_mask sv_mask
146 #define sa_flags sv_flags
147 #endif
148 struct sigaction sig_act;
149 #endif /* USGISH */
150
151 int main(argc, argv)
152         int     argc;
153         char    **argv;
154 {
155         register char   **fp = filelist;
156         register char   **incp = includedirs;
157         register char   *p;
158         register struct inclist *ip;
159         char    *makefile = NULL;
160         struct filepointer      *filecontent;
161         struct symtab *psymp = predefs;
162         char *endmarker = NULL;
163         char *defincdir = NULL;
164
165         ProgramName = argv[0];
166
167         while (psymp->s_name)
168         {
169             define2(psymp->s_name, psymp->s_value, &maininclist);
170             psymp++;
171         }
172         if (argc == 2 && argv[1][0] == '@') {
173             struct stat ast;
174             int afd;
175             char *args;
176             char **nargv;
177             int nargc;
178             char quotechar = '\0';
179
180             nargc = 1;
181             if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
182                 fatalerr("cannot open \"%s\"\n", argv[1]+1);
183             fstat(afd, &ast);
184             args = (char *)malloc(ast.st_size + 1);
185             if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
186                 fatalerr("failed to read %s\n", argv[1]+1);
187             args[ast.st_size] = '\0';
188             close(afd);
189             for (p = args; *p; p++) {
190                 if (quotechar) {
191                     if (quotechar == '\\' ||
192                         (*p == quotechar && p[-1] != '\\'))
193                         quotechar = '\0';
194                     continue;
195                 }
196                 switch (*p) {
197                 case '\\':
198                 case '"':
199                 case '\'':
200                     quotechar = *p;
201                     break;
202                 case ' ':
203                 case '\n':
204                     *p = '\0';
205                     if (p > args && p[-1])
206                         nargc++;
207                     break;
208                 }
209             }
210             if (p[-1])
211                 nargc++;
212             nargv = (char **)malloc(nargc * sizeof(char *));
213             nargv[0] = argv[0];
214             argc = 1;
215             for (p = args; argc < nargc; p += strlen(p) + 1)
216                 if (*p) nargv[argc++] = p;
217             argv = nargv;
218         }
219         for(argc--, argv++; argc; argc--, argv++) {
220                 /* if looking for endmarker then check before parsing */
221                 if (endmarker && strcmp (endmarker, *argv) == 0) {
222                     endmarker = NULL;
223                     continue;
224                 }
225                 if (**argv != '-') {
226                         /* treat +thing as an option for C++ */
227                         if (endmarker && **argv == '+')
228                                 continue;
229                         *fp++ = argv[0];
230                         continue;
231                 }
232                 switch(argv[0][1]) {
233                 case '-':
234                         endmarker = &argv[0][2];
235                         if (endmarker[0] == '\0') endmarker = "--";
236                         break;
237                 case 'D':
238                         if (argv[0][2] == '\0') {
239                                 argv++;
240                                 argc--;
241                         }
242                         for (p=argv[0] + 2; *p ; p++)
243                                 if (*p == '=') {
244                                         *p = ' ';
245                                         break;
246                                 }
247                         define(argv[0] + 2, &maininclist);
248                         break;
249                 case 'I':
250                         if (incp >= includedirs + MAXDIRS)
251                             fatalerr("Too many -I flags.\n");
252                         *incp++ = argv[0]+2;
253                         if (**(incp-1) == '\0') {
254                                 *(incp-1) = *(++argv);
255                                 argc--;
256                         }
257                         break;
258                 case 'i':
259                         if (strncmp(argv[0]+2, "system", 6) == 0) {
260                                 if (incp >= includedirs + MAXDIRS)
261                                     fatalerr("Too many -I flags.\n");
262                                 *incp++ = argv[0]+8;
263                                 if (**(incp-1) == '\0') {
264                                         *(incp-1) = *(++argv);
265                                         argc--;
266                                 }
267                         }
268                         break;
269                 case 'Y':
270                         defincdir = argv[0]+2;
271                         break;
272                 /* do not use if endmarker processing */
273                 case 'a':
274                         if (endmarker) break;
275                         append = TRUE;
276                         break;
277                 case 'w':
278                         if (endmarker) break;
279                         if (argv[0][2] == '\0') {
280                                 argv++;
281                                 argc--;
282                                 width = atoi(argv[0]);
283                         } else
284                                 width = atoi(argv[0]+2);
285                         break;
286                 case 'o':
287                         if (endmarker) break;
288                         if (argv[0][2] == '\0') {
289                                 argv++;
290                                 argc--;
291                                 objsuffix = argv[0];
292                         } else
293                                 objsuffix = argv[0]+2;
294                         break;
295                 case 'p':
296                         if (endmarker) break;
297                         if (argv[0][2] == '\0') {
298                                 argv++;
299                                 argc--;
300                                 objprefix = argv[0];
301                         } else
302                                 objprefix = argv[0]+2;
303                         break;
304                 case 'v':
305                         if (endmarker) break;
306                         verbose = TRUE;
307 #ifdef DEBUG
308                         if (argv[0][2])
309                                 _debugmask = atoi(argv[0]+2);
310 #endif
311                         break;
312                 case 's':
313                         if (endmarker) break;
314                         startat = argv[0]+2;
315                         if (*startat == '\0') {
316                                 startat = *(++argv);
317                                 argc--;
318                         }
319                         if (*startat != '#')
320                                 fatalerr("-s flag's value should start %s\n",
321                                         "with '#'.");
322                         break;
323                 case 'f':
324                         if (endmarker) break;
325                         makefile = argv[0]+2;
326                         if (*makefile == '\0') {
327                                 makefile = *(++argv);
328                                 argc--;
329                         }
330                         break;
331
332                 case 'm':
333                         warn_multiple = TRUE;
334                         break;
335                         
336                 /* Ignore -O, -g so we can just pass ${CFLAGS} to
337                    makedepend
338                  */
339                 case 'O':
340                 case 'g':
341                         break;
342                 default:
343                         if (endmarker) break;
344         /*              fatalerr("unknown opt = %s\n", argv[0]); */
345                         warning("ignoring option %s\n", argv[0]);
346                 }
347         }
348         if (!defincdir) {
349 #ifdef PREINCDIR
350             if (incp >= includedirs + MAXDIRS)
351                 fatalerr("Too many -I flags.\n");
352             *incp++ = PREINCDIR;
353 #endif
354             if (incp >= includedirs + MAXDIRS)
355                 fatalerr("Too many -I flags.\n");
356             *incp++ = INCLUDEDIR;
357 #ifdef POSTINCDIR
358             if (incp >= includedirs + MAXDIRS)
359                 fatalerr("Too many -I flags.\n");
360             *incp++ = POSTINCDIR;
361 #endif
362         } else if (*defincdir) {
363             if (incp >= includedirs + MAXDIRS)
364                 fatalerr("Too many -I flags.\n");
365             *incp++ = defincdir;
366         }
367
368         redirect(startat, makefile);
369
370         /*
371          * catch signals.
372          */
373 #ifdef USGISH
374 /*  should really reset SIGINT to SIG_IGN if it was.  */
375 #ifdef SIGHUP
376         signal (SIGHUP, catch);
377 #endif
378         signal (SIGINT, catch);
379 #ifdef SIGQUIT
380         signal (SIGQUIT, catch);
381 #endif
382         signal (SIGILL, catch);
383 #ifdef SIGBUS
384         signal (SIGBUS, catch);
385 #endif
386         signal (SIGSEGV, catch);
387 #ifdef SIGSYS
388         signal (SIGSYS, catch);
389 #endif
390 #else
391         sig_act.sa_handler = catch;
392 #ifdef _POSIX_SOURCE
393         sigemptyset(&sig_act.sa_mask);
394         sigaddset(&sig_act.sa_mask, SIGINT);
395         sigaddset(&sig_act.sa_mask, SIGQUIT);
396 #ifdef SIGBUS
397         sigaddset(&sig_act.sa_mask, SIGBUS);
398 #endif
399         sigaddset(&sig_act.sa_mask, SIGILL);
400         sigaddset(&sig_act.sa_mask, SIGSEGV);
401         sigaddset(&sig_act.sa_mask, SIGHUP);
402         sigaddset(&sig_act.sa_mask, SIGPIPE);
403 #ifdef SIGSYS
404         sigaddset(&sig_act.sa_mask, SIGSYS);
405 #endif
406 #else
407         sig_act.sa_mask = ((1<<(SIGINT -1))
408                            |(1<<(SIGQUIT-1))
409 #ifdef SIGBUS
410                            |(1<<(SIGBUS-1))
411 #endif
412                            |(1<<(SIGILL-1))
413                            |(1<<(SIGSEGV-1))
414                            |(1<<(SIGHUP-1))
415                            |(1<<(SIGPIPE-1))
416 #ifdef SIGSYS
417                            |(1<<(SIGSYS-1))
418 #endif
419                            );
420 #endif /* _POSIX_SOURCE */
421         sig_act.sa_flags = 0;
422         sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
423         sigaction(SIGINT, &sig_act, (struct sigaction *)0);
424         sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
425         sigaction(SIGILL, &sig_act, (struct sigaction *)0);
426 #ifdef SIGBUS
427         sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
428 #endif
429         sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
430 #ifdef SIGSYS
431         sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
432 #endif
433 #endif /* USGISH */
434
435         /*
436          * now peruse through the list of files.
437          */
438         for(fp=filelist; *fp; fp++) {
439                 filecontent = getfile(*fp);
440                 ip = newinclude(*fp, (char *)NULL);
441
442                 find_includes(filecontent, ip, ip, 0, FALSE);
443                 freefile(filecontent);
444                 recursive_pr_include(ip, ip->i_file, base_name(*fp));
445                 inc_clean();
446         }
447         if (printed)
448                 printf("\n");
449         exit(0);
450 }
451
452 struct filepointer *getfile(file)
453         char    *file;
454 {
455         register int    fd;
456         struct filepointer      *content;
457         struct stat     st;
458
459         content = (struct filepointer *)malloc(sizeof(struct filepointer));
460         if ((fd = open(file, O_RDONLY)) < 0) {
461                 warning("cannot open \"%s\"\n", file);
462                 content->f_p = content->f_base = content->f_end = (char *)malloc(1);
463                 *content->f_p = '\0';
464                 return(content);
465         }
466         fstat(fd, &st);
467         content->f_base = (char *)malloc(st.st_size+1);
468         if (content->f_base == NULL)
469                 fatalerr("cannot allocate mem\n");
470         if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
471                 fatalerr("failed to read %s\n", file);
472         close(fd);
473         content->f_len = st.st_size+1;
474         content->f_p = content->f_base;
475         content->f_end = content->f_base + st.st_size;
476         *content->f_end = '\0';
477         content->f_line = 0;
478         return(content);
479 }
480
481 void
482 freefile(fp)
483         struct filepointer      *fp;
484 {
485         free(fp->f_base);
486         free(fp);
487 }
488
489 char *copy(str)
490         register char   *str;
491 {
492         register char   *p = (char *)malloc(strlen(str) + 1);
493
494         strncpy(p, str, strlen(str) + 1);
495         return(p);
496 }
497
498 int match(str, list)
499         register char   *str, **list;
500 {
501         register int    i;
502
503         for (i=0; *list; i++, list++)
504                 if (strcmp(str, *list) == 0)
505                         return(i);
506         return(-1);
507 }
508
509 /*
510  * Get the next line.  We only return lines beginning with '#' since that
511  * is all this program is ever interested in.
512  */
513 char *our_getline(filep)
514         register struct filepointer     *filep;
515 {
516         register char   *p,     /* walking pointer */
517                         *eof,   /* end of file pointer */
518                         *bol;   /* beginning of line pointer */
519         register int    lineno; /* line number */
520
521         p = filep->f_p;
522         eof = filep->f_end;
523         if (p >= eof)
524                 return((char *)NULL);
525         lineno = filep->f_line;
526
527         for(bol = p--; ++p < eof; ) {
528                 if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
529                         /* consume C comments */
530                         *p++ = ' ', *p++ = ' ';
531                         while (*p) {
532                                 if (*p == '*' && *(p+1) == '/') {
533                                         *p++ = ' ', *p = ' ';
534                                         break;
535                                 }
536                                 else if (*p == '\n')
537                                         lineno++;
538                                 *p++ = ' ';
539                         }
540                         continue;
541                 }
542                 else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
543                         /* consume C++ comments */
544                         *p++ = ' ';
545                         *p++ = ' ';
546                         while (p < eof && *p) {
547                                 if (*p == '\\' && (p+1) < eof &&
548                                     *(p+1) == '\n') {
549                                         *(p++) = ' ';
550                                         lineno++;
551                                 }
552                                 else if (*p == '?' && (p+3) < eof &&
553                                          *(p+1) == '?' &&
554                                          *(p+2) == '/' &&
555                                          *(p+3) == '\n') {
556                                         *(p++) = ' ';
557                                         *(p++) = ' ';
558                                         *(p++) = ' ';
559                                         lineno++;
560                                 }
561                                 else if (*p == '\n')
562                                         break;  /* to process end of line */
563                                 *(p++) = ' ';
564                         }
565                         --p;
566                 }
567                 else if (*p == '\\') {
568                         if (*(p+1) == '\n') {
569                                 *p = ' ';
570                                 *(p+1) = ' ';
571                                 lineno++;
572                         }
573                 }
574                 else if (*p == '\n') {
575                         lineno++;
576                         if (*bol == '#') {
577                                 register char *cp;
578
579                                 *p++ = '\0';
580                                 /* punt lines with just # (yacc generated) */
581                                 for (cp = bol+1; 
582                                      *cp && (*cp == ' ' || *cp == '\t'); cp++);
583                                 if (*cp) goto done;
584                         }
585                         bol = p+1;
586                 }
587         }
588         if (*bol != '#')
589                 bol = NULL;
590 done:
591         filep->f_p = p;
592         filep->f_line = lineno;
593         return(bol);
594 }
595
596 /*
597  * Strip the file name down to what we want to see in the Makefile.
598  * It will have objprefix and objsuffix around it.
599  */
600 char *base_name(file)
601         register char   *file;
602 {
603         register char   *p;
604
605         file = copy(file);
606         for(p=file+strlen(file); p>file && *p != '.'; p--) ;
607
608         if (*p == '.')
609                 *p = '\0';
610         return(file);
611 }
612
613 #if defined(USG) && !defined(CRAY) && !defined(SVR4)
614 int rename (from, to)
615     char *from, *to;
616 {
617     (void) unlink (to);
618     if (link (from, to) == 0) {
619         unlink (from);
620         return 0;
621     } else {
622         return -1;
623     }
624 }
625 #endif /* USGISH */
626
627 void
628 redirect(line, makefile)
629         char    *line,
630                 *makefile;
631 {
632         struct stat     st;
633         FILE    *fdin, *fdout;
634         char    backup[ BUFSIZ ],
635                 buf[ BUFSIZ ];
636         boolean found = FALSE;
637         int     len;
638
639         /*
640          * if makefile is "-" then let it pour onto stdout.
641          */
642         if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
643                 puts(line);
644                 return;
645         }
646
647         /*
648          * use a default makefile is not specified.
649          */
650         if (!makefile) {
651                 if (stat("Makefile", &st) == 0)
652                         makefile = "Makefile";
653                 else if (stat("makefile", &st) == 0)
654                         makefile = "makefile";
655                 else
656                         fatalerr("[mM]akefile is not present\n");
657         }
658         else
659             stat(makefile, &st);
660         if ((fdin = fopen(makefile, "r")) == NULL)
661                 fatalerr("cannot open \"%s\"\n", makefile);
662         snprintf(backup, BUFSIZ, "%s.bak", makefile);
663         unlink(backup);
664 #ifdef WIN32
665         fclose(fdin);
666 #endif
667         if (rename(makefile, backup) < 0)
668                 fatalerr("cannot rename %s to %s\n", makefile, backup);
669 #ifdef WIN32
670         if ((fdin = fopen(backup, "r")) == NULL)
671                 fatalerr("cannot open \"%s\"\n", backup);
672 #endif
673         if ((fdout = freopen(makefile, "w", stdout)) == NULL)
674                 fatalerr("cannot open \"%s\"\n", backup);
675         len = strlen(line);
676         while (!found && fgets(buf, BUFSIZ, fdin)) {
677                 if (*buf == '#' && strncmp(line, buf, len) == 0)
678                         found = TRUE;
679                 fputs(buf, fdout);
680         }
681         if (!found) {
682                 if (verbose)
683                 warning("Adding new delimiting line \"%s\" and dependencies...\n",
684                         line);
685                 puts(line); /* same as fputs(fdout); but with newline */
686         } else if (append) {
687             while (fgets(buf, BUFSIZ, fdin)) {
688                 fputs(buf, fdout);
689             }
690         }
691         fflush(fdout);
692 #if defined(USGISH) || defined(_SEQUENT_)
693         chmod(makefile, st.st_mode);
694 #else
695         fchmod(fileno(fdout), st.st_mode);
696 #endif /* USGISH */
697 }
698
699 void
700 #if NeedVarargsPrototypes
701 fatalerr(char *msg, ...)
702 #else
703 /*VARARGS*/
704 fatalerr(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
705     char *msg;
706 #endif
707 {
708 #if NeedVarargsPrototypes
709         va_list args;
710 #endif
711         fprintf(stderr, "%s: error:  ", ProgramName);
712 #if NeedVarargsPrototypes
713         va_start(args, msg);
714         vfprintf(stderr, msg, args);
715         va_end(args);
716 #else
717         fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
718 #endif
719         exit (1);
720 }
721
722 void
723 #if NeedVarargsPrototypes
724 warning(char *msg, ...)
725 #else
726 /*VARARGS0*/
727 warning(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
728     char *msg;
729 #endif
730 {
731 #if NeedVarargsPrototypes
732         va_list args;
733 #endif
734         fprintf(stderr, "%s: warning:  ", ProgramName);
735 #if NeedVarargsPrototypes
736         va_start(args, msg);
737         vfprintf(stderr, msg, args);
738         va_end(args);
739 #else
740         fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
741 #endif
742 }
743
744 void
745 #if NeedVarargsPrototypes
746 warning1(char *msg, ...)
747 #else
748 /*VARARGS0*/
749 warning1(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9)
750     char *msg;
751 #endif
752 {
753 #if NeedVarargsPrototypes
754         va_list args;
755         va_start(args, msg);
756         vfprintf(stderr, msg, args);
757         va_end(args);
758 #else
759         fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9);
760 #endif
761 }