Back to index

lightning-sunbird  0.9+nobinonly
main.c
Go to the documentation of this file.
00001 /* $Xorg: main.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */
00002 /*
00003 
00004 Copyright (c) 1993, 1994, 1998 The Open Group
00005 
00006 Permission to use, copy, modify, distribute, and sell this software and its
00007 documentation for any purpose is hereby granted without fee, provided that
00008 the above copyright notice appear in all copies and that both that
00009 copyright notice and this permission notice appear in supporting
00010 documentation.
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00018 THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021 
00022 Except as contained in this notice, the name of The Open Group shall not be
00023 used in advertising or otherwise to promote the sale, use or other dealings
00024 in this Software without prior written authorization from The Open Group.
00025 
00026 */
00027 /* $XFree86: xc/config/makedepend/main.c,v 3.32 2003/03/26 20:43:48 tsi Exp $ */
00028 
00029 #include "def.h"
00030 #ifdef hpux
00031 #define sigvec sigvector
00032 #endif /* hpux */
00033 
00034 #ifdef X_POSIX_C_SOURCE
00035 #define _POSIX_C_SOURCE X_POSIX_C_SOURCE
00036 #include <signal.h>
00037 #undef _POSIX_C_SOURCE
00038 #else
00039 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
00040 #include <signal.h>
00041 #else
00042 #define _POSIX_SOURCE
00043 #include <signal.h>
00044 #undef _POSIX_SOURCE
00045 #endif
00046 #endif
00047 
00048 #include <stdarg.h>
00049 
00050 #ifdef MINIX
00051 #define USE_CHMOD    1
00052 #endif
00053 
00054 #ifdef DEBUG
00055 int    _debugmask;
00056 #endif
00057 
00058 /* #define DEBUG_DUMP */
00059 #ifdef DEBUG_DUMP
00060 #define DBG_PRINT(file, fmt, args)   fprintf(file, fmt, args)
00061 #else
00062 #define DBG_PRINT(file, fmt, args)   /* empty */
00063 #endif
00064 
00065 #define DASH_INC_PRE    "#include \""
00066 #define DASH_INC_POST   "\""
00067 
00068 char *ProgramName;
00069 
00070 char   *directives[] = {
00071        "if",
00072        "ifdef",
00073        "ifndef",
00074        "else",
00075        "endif",
00076        "define",
00077        "undef",
00078        "include",
00079        "line",
00080        "pragma",
00081        "error",
00082        "ident",
00083        "sccs",
00084        "elif",
00085        "eject",
00086        "warning",
00087        "include_next",
00088        NULL
00089 };
00090 
00091 #define MAKEDEPEND
00092 #include "imakemdep.h"      /* from config sources */
00093 #undef MAKEDEPEND
00094 
00095 struct inclist inclist[ MAXFILES ],
00096               *inclistp = inclist,
00097               *inclistnext = inclist,
00098               maininclist;
00099 
00100 static char   *filelist[ MAXFILES ];
00101 char          *includedirs[ MAXDIRS + 1 ],
00102               **includedirsnext = includedirs;
00103 char          *notdotdot[ MAXDIRS ];
00104 static int    cmdinc_count = 0;
00105 static char   *cmdinc_list[ 2 * MAXINCFILES ];
00106 char          *objprefix = "";
00107 char          *objsuffix = OBJSUFFIX;
00108 static char   *startat = "# DO NOT DELETE";
00109 int           width = 78;
00110 static boolean       append = FALSE;
00111 boolean              printed = FALSE;
00112 boolean              verbose = FALSE;
00113 boolean              show_where_not = FALSE;
00114 /* Warn on multiple includes of same file */
00115 boolean       warn_multiple = FALSE;
00116 
00117 static void setfile_cmdinc(struct filepointer *filep, long count, char **list);
00118 static void redirect(char *line, char *makefile);
00119 
00120 static
00121 #ifdef SIGNALRETURNSINT
00122 int
00123 #else
00124 void
00125 #endif
00126 catch (int sig)
00127 {
00128        fflush (stdout);
00129        fatalerr ("got signal %d\n", sig);
00130 }
00131 
00132 #if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__UNIXOS2__) || defined(Lynx_22) || defined(__CYGWIN__)
00133 #define USGISH
00134 #endif
00135 
00136 #ifndef USGISH
00137 #ifdef X_NOT_POSIX
00138 #define sigaction sigvec
00139 #define sa_handler sv_handler
00140 #define sa_mask sv_mask
00141 #define sa_flags sv_flags
00142 #endif
00143 struct sigaction sig_act;
00144 #endif /* USGISH */
00145 
00146 int
00147 main(int argc, char *argv[])
00148 {
00149        char   **fp = filelist;
00150        char   **incp = includedirs;
00151        char   *p;
00152        struct inclist       *ip;
00153        char   *makefile = NULL;
00154        struct filepointer   *filecontent;
00155        struct symtab *psymp = predefs;
00156        char *endmarker = NULL;
00157        char *defincdir = NULL;
00158        char **undeflist = NULL;
00159        int numundefs = 0, i;
00160        register char offset;
00161 
00162        ProgramName = argv[0];
00163 
00164        while (psymp->s_name)
00165        {
00166            define2(psymp->s_name, psymp->s_value, &maininclist);
00167            psymp++;
00168        }
00169        if (argc == 2 && argv[1][0] == '@') {
00170            struct stat ast;
00171            int afd;
00172            char *args;
00173            char **nargv;
00174            int nargc;
00175            char quotechar = '\0';
00176 
00177            nargc = 1;
00178            if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
00179               fatalerr("cannot open \"%s\"\n", argv[1]+1);
00180            fstat(afd, &ast);
00181            args = (char *)malloc(ast.st_size + 1);
00182            if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
00183               fatalerr("failed to read %s\n", argv[1]+1);
00184            args[ast.st_size] = '\0';
00185            close(afd);
00186            for (p = args; *p; p++) {
00187               if (quotechar) {
00188                   if (quotechar == '\\' ||
00189                      (*p == quotechar && p[-1] != '\\'))
00190                      quotechar = '\0';
00191                   continue;
00192               }
00193               switch (*p) {
00194               case '\\':
00195               case '"':
00196               case '\'':
00197                   quotechar = *p;
00198                   break;
00199               case ' ':
00200               case '\n':
00201                   *p = '\0';
00202                   if (p > args && p[-1])
00203                      nargc++;
00204                   break;
00205               }
00206            }
00207            if (p[-1])
00208               nargc++;
00209            nargv = (char **)malloc(nargc * sizeof(char *));
00210            nargv[0] = argv[0];
00211            argc = 1;
00212            for (p = args; argc < nargc; p += strlen(p) + 1)
00213               if (*p) nargv[argc++] = p;
00214            argv = nargv;
00215        }
00216        for(argc--, argv++; argc; argc--, argv++) {
00217               /* if looking for endmarker then check before parsing */
00218               if (endmarker && strcmp (endmarker, *argv) == 0) {
00219                   endmarker = NULL;
00220                   continue;
00221               }
00222               if (**argv != '-') {
00223                      /* treat +thing as an option for C++ */
00224                      if (endmarker && **argv == '+')
00225                             continue;
00226                      *fp++ = argv[0];
00227                      continue;
00228               }
00229               switch(argv[0][1]) {
00230               case '-':
00231                      endmarker = &argv[0][2];
00232                      if (endmarker[0] == '\0') endmarker = "--";
00233                      break;
00234               case 'D':
00235                      offset = 2;
00236                      if (argv[0][2] == '\0') {
00237                             argv++;
00238                             argc--;
00239                             offset = 0;
00240                      }
00241                      /* offset +1 here since first def letter
00242                       * cannot be `=`
00243                       */
00244                      for (p = argv[0] + offset + 1; *p; p++)
00245                             if (*p == '=') {
00246                                    *p = ' ';
00247                                    break;
00248                             }
00249                      define(argv[0] + offset, &maininclist);
00250                      break;
00251               case 'I':
00252                      if (incp >= includedirs + MAXDIRS)
00253                          fatalerr("Too many -I flags.\n");
00254                      *incp++ = argv[0]+2;
00255                      if (**(incp-1) == '\0') {
00256                             *(incp-1) = *(++argv);
00257                             argc--;
00258                      }
00259                      break;
00260               case 'U':
00261                      /* Undef's override all -D's so save them up */
00262                      numundefs++;
00263                      if (numundefs == 1)
00264                          undeflist = malloc(sizeof(char *));
00265                      else
00266                          undeflist = realloc(undeflist,
00267                                           numundefs * sizeof(char *));
00268                      offset = 2;
00269                      if (argv[0][2] == '\0') {
00270                             argv++;
00271                             argc--;
00272                             offset = 0;
00273                      }
00274                      undeflist[numundefs - 1] = argv[0] + offset;
00275                      break;
00276               case 'Y':
00277                      defincdir = argv[0]+2;
00278                      break;
00279               /* do not use if endmarker processing */
00280               case 'a':
00281                      if (endmarker) break;
00282                      append = TRUE;
00283                      break;
00284               case 'w':
00285                      if (endmarker) break;
00286                      if (argv[0][2] == '\0') {
00287                             argv++;
00288                             argc--;
00289                             width = atoi(argv[0]);
00290                      } else
00291                             width = atoi(argv[0]+2);
00292                      break;
00293               case 'o':
00294                      if (endmarker) break;
00295                      if (argv[0][2] == '\0') {
00296                             argv++;
00297                             argc--;
00298                             objsuffix = argv[0];
00299                      } else
00300                             objsuffix = argv[0]+2;
00301                      break;
00302               case 'p':
00303                      if (endmarker) break;
00304                      if (argv[0][2] == '\0') {
00305                             argv++;
00306                             argc--;
00307                             objprefix = argv[0];
00308                      } else
00309                             objprefix = argv[0]+2;
00310                      break;
00311               case 'v':
00312                      if (endmarker) break;
00313                      verbose = TRUE;
00314 #ifdef DEBUG
00315                      if (argv[0][2])
00316                             _debugmask = atoi(argv[0]+2);
00317 #endif
00318                      break;
00319               case 's':
00320                      if (endmarker) break;
00321                      startat = argv[0]+2;
00322                      if (*startat == '\0') {
00323                             startat = *(++argv);
00324                             argc--;
00325                      }
00326                      if (*startat != '#')
00327                             fatalerr("-s flag's value should start %s\n",
00328                                    "with '#'.");
00329                      break;
00330               case 'f':
00331                      if (endmarker) break;
00332                      makefile = argv[0]+2;
00333                      if (*makefile == '\0') {
00334                             makefile = *(++argv);
00335                             argc--;
00336                      }
00337                      break;
00338 
00339               case 'm':
00340                      warn_multiple = TRUE;
00341                      break;
00342                      
00343               /* Ignore -O, -g so we can just pass ${CFLAGS} to
00344                  makedepend
00345                */
00346               case 'O':
00347               case 'g':
00348                      break;
00349               case 'i':
00350                      if (strcmp(&argv[0][1],"include") == 0) {
00351                             char *buf;
00352                             if (argc<2)
00353                                    fatalerr("option -include is a "
00354                                            "missing its parameter\n");
00355                             if (cmdinc_count >= MAXINCFILES)
00356                                    fatalerr("Too many -include flags.\n");
00357                             argc--;
00358                             argv++;
00359                             buf = malloc(strlen(DASH_INC_PRE) +
00360                                         strlen(argv[0]) +
00361                                         strlen(DASH_INC_POST) + 1);
00362                             if(!buf)
00363                                    fatalerr("out of memory at "
00364                                            "-include string\n");
00365                             cmdinc_list[2 * cmdinc_count + 0] = argv[0];
00366                             cmdinc_list[2 * cmdinc_count + 1] = buf;
00367                             cmdinc_count++;
00368                             break;
00369                      }
00370                      /* intentional fall through */
00371               default:
00372                      if (endmarker) break;
00373        /*            fatalerr("unknown opt = %s\n", argv[0]); */
00374                      warning("ignoring option %s\n", argv[0]);
00375               }
00376        }
00377        /* Now do the undefs from the command line */
00378        for (i = 0; i < numundefs; i++)
00379            undefine(undeflist[i], &maininclist);
00380        if (numundefs > 0)
00381            free(undeflist);
00382 
00383        if (!defincdir) {
00384 #ifdef PREINCDIR
00385            if (incp >= includedirs + MAXDIRS)
00386               fatalerr("Too many -I flags.\n");
00387            *incp++ = PREINCDIR;
00388 #endif
00389 #ifdef __UNIXOS2__
00390            {
00391               char *emxinc = getenv("C_INCLUDE_PATH");
00392               /* can have more than one component */
00393               if (emxinc) {
00394                   char *beg, *end;
00395                   beg= (char*)strdup(emxinc);
00396                   for (;;) {
00397                      end = (char*)strchr(beg,';');
00398                      if (end) *end = 0;
00399                      if (incp >= includedirs + MAXDIRS)
00400                             fatalerr("Too many include dirs\n");
00401                      *incp++ = beg;
00402                      if (!end) break;
00403                      beg = end+1;
00404                   }
00405               }
00406            }
00407 #else /* !__UNIXOS2__, does not use INCLUDEDIR at all */
00408            if (incp >= includedirs + MAXDIRS)
00409               fatalerr("Too many -I flags.\n");
00410            *incp++ = INCLUDEDIR;
00411 #endif
00412 
00413 #ifdef EXTRAINCDIR
00414            if (incp >= includedirs + MAXDIRS)
00415               fatalerr("Too many -I flags.\n");
00416            *incp++ = EXTRAINCDIR;
00417 #endif
00418 
00419 #ifdef POSTINCDIR
00420            if (incp >= includedirs + MAXDIRS)
00421               fatalerr("Too many -I flags.\n");
00422            *incp++ = POSTINCDIR;
00423 #endif
00424        } else if (*defincdir) {
00425            if (incp >= includedirs + MAXDIRS)
00426               fatalerr("Too many -I flags.\n");
00427            *incp++ = defincdir;
00428        }
00429 
00430        redirect(startat, makefile);
00431 
00432        /*
00433         * catch signals.
00434         */
00435 #ifdef USGISH
00436 /*  should really reset SIGINT to SIG_IGN if it was.  */
00437 #ifdef SIGHUP
00438        signal (SIGHUP, catch);
00439 #endif
00440        signal (SIGINT, catch);
00441 #ifdef SIGQUIT
00442        signal (SIGQUIT, catch);
00443 #endif
00444        signal (SIGILL, catch);
00445 #ifdef SIGBUS
00446        signal (SIGBUS, catch);
00447 #endif
00448        signal (SIGSEGV, catch);
00449 #ifdef SIGSYS
00450        signal (SIGSYS, catch);
00451 #endif
00452 #else
00453        sig_act.sa_handler = catch;
00454 #if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
00455        sigemptyset(&sig_act.sa_mask);
00456        sigaddset(&sig_act.sa_mask, SIGINT);
00457        sigaddset(&sig_act.sa_mask, SIGQUIT);
00458 #ifdef SIGBUS
00459        sigaddset(&sig_act.sa_mask, SIGBUS);
00460 #endif
00461        sigaddset(&sig_act.sa_mask, SIGILL);
00462        sigaddset(&sig_act.sa_mask, SIGSEGV);
00463        sigaddset(&sig_act.sa_mask, SIGHUP);
00464        sigaddset(&sig_act.sa_mask, SIGPIPE);
00465 #ifdef SIGSYS
00466        sigaddset(&sig_act.sa_mask, SIGSYS);
00467 #endif
00468 #else
00469        sig_act.sa_mask = ((1<<(SIGINT -1))
00470                         |(1<<(SIGQUIT-1))
00471 #ifdef SIGBUS
00472                         |(1<<(SIGBUS-1))
00473 #endif
00474                         |(1<<(SIGILL-1))
00475                         |(1<<(SIGSEGV-1))
00476                         |(1<<(SIGHUP-1))
00477                         |(1<<(SIGPIPE-1))
00478 #ifdef SIGSYS
00479                         |(1<<(SIGSYS-1))
00480 #endif
00481                         );
00482 #endif /* _POSIX_SOURCE */
00483        sig_act.sa_flags = 0;
00484        sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
00485        sigaction(SIGINT, &sig_act, (struct sigaction *)0);
00486        sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
00487        sigaction(SIGILL, &sig_act, (struct sigaction *)0);
00488 #ifdef SIGBUS
00489        sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
00490 #endif
00491        sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
00492 #ifdef SIGSYS
00493        sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
00494 #endif
00495 #endif /* USGISH */
00496 
00497        /*
00498         * now peruse through the list of files.
00499         */
00500        for(fp=filelist; *fp; fp++) {
00501               DBG_PRINT(stderr,"file: %s\n",*fp);
00502               filecontent = getfile(*fp);
00503               setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
00504               ip = newinclude(*fp, (char *)NULL);
00505 
00506               find_includes(filecontent, ip, ip, 0, FALSE);
00507               freefile(filecontent);
00508               recursive_pr_include(ip, ip->i_file, base_name(*fp));
00509               inc_clean();
00510        }
00511        if (printed)
00512               printf("\n");
00513        return 0;
00514 }
00515 
00516 #ifdef __UNIXOS2__
00517 /*
00518  * eliminate \r chars from file
00519  */
00520 static int 
00521 elim_cr(char *buf, int sz)
00522 {
00523        int i,wp;
00524        for (i= wp = 0; i<sz; i++) {
00525               if (buf[i] != '\r')
00526                      buf[wp++] = buf[i];
00527        }
00528        return wp;
00529 }
00530 #endif
00531 
00532 struct filepointer *
00533 getfile(char *file)
00534 {
00535        int    fd;
00536        struct filepointer   *content;
00537        struct stat   st;
00538 
00539        content = (struct filepointer *)malloc(sizeof(struct filepointer));
00540        content->f_name = file;
00541        if ((fd = open(file, O_RDONLY)) < 0) {
00542               warning("cannot open \"%s\"\n", file);
00543               content->f_p = content->f_base = content->f_end = (char *)malloc(1);
00544               *content->f_p = '\0';
00545               return(content);
00546        }
00547        fstat(fd, &st);
00548        content->f_base = (char *)malloc(st.st_size+1);
00549        if (content->f_base == NULL)
00550               fatalerr("cannot allocate mem\n");
00551        if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
00552               fatalerr("failed to read %s\n", file);
00553 #ifdef __UNIXOS2__
00554        st.st_size = elim_cr(content->f_base,st.st_size);
00555 #endif
00556        close(fd);
00557        content->f_len = st.st_size+1;
00558        content->f_p = content->f_base;
00559        content->f_end = content->f_base + st.st_size;
00560        *content->f_end = '\0';
00561        content->f_line = 0;
00562        content->cmdinc_count = 0;
00563        content->cmdinc_list = NULL;
00564        content->cmdinc_line = 0;
00565        return(content);
00566 }
00567 
00568 void
00569 setfile_cmdinc(struct filepointer* filep, long count, char** list)
00570 {
00571        filep->cmdinc_count = count;
00572        filep->cmdinc_list = list;
00573        filep->cmdinc_line = 0;
00574 }
00575 
00576 void
00577 freefile(struct filepointer *fp)
00578 {
00579        free(fp->f_base);
00580        free(fp);
00581 }
00582 
00583 char *copy(char *str)
00584 {
00585        char   *p = (char *)malloc(strlen(str) + 1);
00586 
00587        strcpy(p, str);
00588        return(p);
00589 }
00590 
00591 int
00592 match(char *str, char **list)
00593 {
00594        int    i;
00595 
00596        for (i=0; *list; i++, list++)
00597               if (strcmp(str, *list) == 0)
00598                      return(i);
00599        return(-1);
00600 }
00601 
00602 /*
00603  * Get the next line.  We only return lines beginning with '#' since that
00604  * is all this program is ever interested in.
00605  */
00606 char *getnextline(struct filepointer *filep)
00607 {
00608        char   *p,    /* walking pointer */
00609               *eof,  /* end of file pointer */
00610               *bol;  /* beginning of line pointer */
00611        int    lineno;       /* line number */
00612        boolean whitespace = FALSE;
00613 
00614        /*
00615         * Fake the "-include" line files in form of #include to the
00616         * start of each file.
00617         */
00618        if (filep->cmdinc_line < filep->cmdinc_count) {
00619               char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
00620               char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
00621               filep->cmdinc_line++;
00622               sprintf(buf,"%s%s%s",DASH_INC_PRE,inc,DASH_INC_POST);
00623               DBG_PRINT(stderr,"%s\n",buf);
00624               return(buf);
00625        }
00626 
00627        p = filep->f_p;
00628        eof = filep->f_end;
00629        if (p >= eof)
00630               return((char *)NULL);
00631        lineno = filep->f_line;
00632 
00633        for (bol = p--; ++p < eof; ) {
00634               if ((bol == p) && ((*p == ' ') || (*p == '\t')))
00635               {
00636                      /* Consume leading white-spaces for this line */
00637                      while (((p+1) < eof) && ((*p == ' ') || (*p == '\t')))
00638                      {
00639                             p++;
00640                             bol++;
00641                      }
00642                      whitespace = TRUE;
00643               }
00644         
00645               if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
00646                      /* Consume C comments */
00647                      *(p++) = ' ';
00648                      *(p++) = ' ';
00649                      while (p < eof && *p) {
00650                             if (*p == '*' && (p+1) < eof && *(p+1) == '/') {
00651                                    *(p++) = ' ';
00652                                    *(p++) = ' ';
00653                                    break;
00654                             }
00655                             if (*p == '\n')
00656                                    lineno++;
00657                             *(p++) = ' ';
00658                      }
00659                      --p;
00660               }
00661               else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
00662                      /* Consume C++ comments */
00663                      *(p++) = ' ';
00664                      *(p++) = ' ';
00665                      while (p < eof && *p) {
00666                             if (*p == '\\' && (p+1) < eof &&
00667                                 *(p+1) == '\n') {
00668                                    *(p++) = ' ';
00669                                    lineno++;
00670                             }
00671                             else if (*p == '?' && (p+3) < eof &&
00672                                     *(p+1) == '?' && 
00673                                     *(p+2) == '/' &&
00674                                     *(p+3) == '\n') {
00675                                    *(p++) = ' ';
00676                                    *(p++) = ' ';
00677                                    *(p++) = ' ';
00678                                    lineno++;
00679                             }
00680                             else if (*p == '\n')
00681                                    break; /* to process end of line */
00682                             *(p++) = ' ';
00683                      }
00684                      --p;
00685               }
00686               else if (*p == '\\' && (p+1) < eof && *(p+1) == '\n') {
00687                      /* Consume backslash line terminations */
00688                      *(p++) = ' ';
00689                      *p = ' ';
00690                      lineno++;
00691               }
00692               else if (*p == '?' && (p+3) < eof &&
00693                       *(p+1) == '?' && *(p+2) == '/' && *(p+3) == '\n') {
00694                      /* Consume trigraph'ed backslash line terminations */
00695                      *(p++) = ' ';
00696                      *(p++) = ' ';
00697                      *(p++) = ' ';
00698                      *p = ' ';
00699                      lineno++;
00700               }
00701               else if (*p == '\n') {
00702                      lineno++;
00703                      if (*bol == '#') {
00704                             char *cp;
00705 
00706                             *(p++) = '\0';
00707                             /* punt lines with just # (yacc generated) */
00708                             for (cp = bol+1; 
00709                                  *cp && (*cp == ' ' || *cp == '\t'); cp++);
00710                             if (*cp) goto done;
00711                             --p;
00712                      }
00713                      bol = p+1;
00714                      whitespace = FALSE;
00715               }
00716        }
00717        if (*bol != '#')
00718               bol = NULL;
00719 done:
00720        if (bol && whitespace) {
00721               warning("%s:  non-portable whitespace encountered at line %d\n",
00722                      filep->f_name, lineno);
00723        }
00724        filep->f_p = p;
00725        filep->f_line = lineno;
00726 #ifdef DEBUG_DUMP
00727        if (bol)
00728               DBG_PRINT(stderr,"%s\n",bol);
00729 #endif
00730        return(bol);
00731 }
00732 
00733 /*
00734  * Strip the file name down to what we want to see in the Makefile.
00735  * It will have objprefix and objsuffix around it.
00736  */
00737 char *base_name(char *file)
00738 {
00739        char   *p;
00740 
00741        file = copy(file);
00742        for(p=file+strlen(file); p>file && *p != '.'; p--) ;
00743 
00744        if (*p == '.')
00745               *p = '\0';
00746        return(file);
00747 }
00748 
00749 #if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__UNIXOS2__) && !defined(clipper) && !defined(__clipper__)
00750 int rename (char *from, char *to)
00751 {
00752     (void) unlink (to);
00753     if (link (from, to) == 0) {
00754        unlink (from);
00755        return 0;
00756     } else {
00757        return -1;
00758     }
00759 }
00760 #endif /* USGISH */
00761 
00762 void
00763 redirect(char *line, char *makefile)
00764 {
00765        struct stat   st;
00766        FILE   *fdin, *fdout;
00767        char   backup[ BUFSIZ ],
00768               buf[ BUFSIZ ];
00769        boolean       found = FALSE;
00770        int    len;
00771 
00772        /*
00773         * if makefile is "-" then let it pour onto stdout.
00774         */
00775        if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
00776               puts(line);
00777               return;
00778        }
00779 
00780        /*
00781         * use a default makefile is not specified.
00782         */
00783        if (!makefile) {
00784               if (stat("Makefile", &st) == 0)
00785                      makefile = "Makefile";
00786               else if (stat("makefile", &st) == 0)
00787                      makefile = "makefile";
00788               else
00789                      fatalerr("[mM]akefile is not present\n");
00790        }
00791        else
00792            stat(makefile, &st);
00793        if ((fdin = fopen(makefile, "r")) == NULL)
00794               fatalerr("cannot open \"%s\"\n", makefile);
00795        sprintf(backup, "%s.bak", makefile);
00796        unlink(backup);
00797 #if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
00798        fclose(fdin);
00799 #endif
00800        if (rename(makefile, backup) < 0)
00801               fatalerr("cannot rename %s to %s\n", makefile, backup);
00802 #if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
00803        if ((fdin = fopen(backup, "r")) == NULL)
00804               fatalerr("cannot open \"%s\"\n", backup);
00805 #endif
00806        if ((fdout = freopen(makefile, "w", stdout)) == NULL)
00807               fatalerr("cannot open \"%s\"\n", backup);
00808        len = strlen(line);
00809        while (!found && fgets(buf, BUFSIZ, fdin)) {
00810               if (*buf == '#' && strncmp(line, buf, len) == 0)
00811                      found = TRUE;
00812               fputs(buf, fdout);
00813        }
00814        if (!found) {
00815               if (verbose)
00816               warning("Adding new delimiting line \"%s\" and dependencies...\n",
00817                      line);
00818               puts(line); /* same as fputs(fdout); but with newline */
00819        } else if (append) {
00820            while (fgets(buf, BUFSIZ, fdin)) {
00821               fputs(buf, fdout);
00822            }
00823        }
00824        fflush(fdout);
00825 #if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
00826        chmod(makefile, st.st_mode);
00827 #else
00828         fchmod(fileno(fdout), st.st_mode);
00829 #endif /* USGISH */
00830 }
00831 
00832 void
00833 fatalerr(char *msg, ...)
00834 {
00835        va_list args;
00836        fprintf(stderr, "%s: error:  ", ProgramName);
00837        va_start(args, msg);
00838        vfprintf(stderr, msg, args);
00839        va_end(args);
00840        exit (1);
00841 }
00842 
00843 void
00844 warning(char *msg, ...)
00845 {
00846        va_list args;
00847        fprintf(stderr, "%s: warning:  ", ProgramName);
00848        va_start(args, msg);
00849        vfprintf(stderr, msg, args);
00850        va_end(args);
00851 }
00852 
00853 void
00854 warning1(char *msg, ...)
00855 {
00856        va_list args;
00857        va_start(args, msg);
00858        vfprintf(stderr, msg, args);
00859        va_end(args);
00860 }