"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/smake/readfile.c" (5 Sep 2021, 11319 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "readfile.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-09-01_vs_2021-09-18 or 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    1 /* @(#)readfile.c   1.68 21/09/05 Copyright 1985-2021 J. Schilling */
    2 #include <schily/mconfig.h>
    3 #ifndef lint
    4 static  UConst char sccsid[] =
    5     "@(#)readfile.c 1.68 21/09/05 Copyright 1985-2021 J. Schilling";
    6 #endif
    7 /*
    8  *  Make program
    9  *  File/string reading routines
   10  *
   11  *  Copyright (c) 1985-2021 by J. Schilling
   12  */
   13 /*
   14  * The contents of this file are subject to the terms of the
   15  * Common Development and Distribution License, Version 1.0 only
   16  * (the "License").  You may not use this file except in compliance
   17  * with the License.
   18  *
   19  * See the file CDDL.Schily.txt in this distribution for details.
   20  * A copy of the CDDL is also available via the Internet at
   21  * http://www.opensource.org/licenses/cddl1.txt
   22  *
   23  * When distributing Covered Code, include this CDDL HEADER in each
   24  * file and include the License file CDDL.Schily.txt from this distribution.
   25  */
   26 
   27 #include <schily/stdio.h>
   28 #include <schily/types.h>
   29 #include <schily/standard.h>
   30 #include <schily/stdlib.h>
   31 #include <schily/string.h>
   32 #include <schily/schily.h>
   33 #include <schily/ctype.h>
   34 #include "make.h"
   35 
   36 LOCAL   int fillrdbuf   __PR((void));
   37 EXPORT  char    *peekrdbuf  __PR((void));
   38 EXPORT  char    *getrdbuf   __PR((void));
   39 EXPORT  int getrdbufsize    __PR((void));
   40 EXPORT  void    setincmd    __PR((BOOL isincmd));
   41 EXPORT  void    getch       __PR((void));
   42 EXPORT  int peekch      __PR((void));
   43 EXPORT  void    skipline    __PR((void));
   44 EXPORT  void    readstring  __PR((char *str, char *strname));
   45 EXPORT  void    readfile    __PR((char *name, BOOL must_exist));
   46 EXPORT  void    doinclude   __PR((char *name, BOOL must_exist));
   47 EXPORT  void    makeincs    __PR((void));
   48 
   49 #if defined(unix) || defined(IS_UNIX)
   50 #   define  RDBUF_SIZE  1024
   51 #else
   52 #   define  RDBUF_SIZE  512
   53 #endif
   54 
   55 /*
   56  * Several variables needed for reading with look ahead
   57  * to allow easy parsing of make files.
   58  */
   59 EXPORT  int lastc       = 0;        /* last input character     */
   60 EXPORT  int firstc      = 0;        /* first character in line  */
   61 LOCAL   FILE    *mfp        = (FILE *)NULL; /* currently open make file */
   62 EXPORT  char    *mfname     = NULL;     /* name of current make file */
   63 LOCAL   int olineno     = 1;        /* old line number (include) */
   64 EXPORT  int lineno      = 1;        /* current line number      */
   65 EXPORT  int col     = 0;        /* current column       */
   66 LOCAL   BOOL    incmd       = FALSE;    /* cmd list line starts \n\t */
   67 LOCAL   char    *readbfp;           /* current read buf pointer  */
   68 LOCAL   char    *readbfstart;           /* start of current read buf */
   69 LOCAL   char    *readbfend;         /* end of current read buf  */
   70 LOCAL   char    rdbuf[RDBUF_SIZE];      /* the real read buffer     */
   71 LOCAL   char    *rd_buffer  = rdbuf;    /* a pointer to start of buf */
   72 
   73 #define UC  (unsigned char)
   74 /*
   75  * Get or peek a character from current Makefile.
   76  */
   77 #define mygetc()    ((readbfp >= readbfend) ? fillrdbuf() : UC *readbfp++)
   78 #define mypeekc()   ((readbfp >= readbfend) ? (fillrdbuf() == EOF ? \
   79                         EOF : UC *--readbfp) : UC *readbfp)
   80 #define myungetc(c) (*(--readbfp) = c)
   81 
   82 /*
   83  * Fill or refill the read buffer that is used by the mygetc() CPP macro.
   84  */
   85 LOCAL int
   86 fillrdbuf()
   87 {
   88     ssize_t ret;
   89 
   90     if (mfp == (FILE *) NULL)   /* EOF while reading from a string. */
   91         return (EOF);
   92     readbfp = rd_buffer;
   93     readbfstart = rd_buffer;    /* used for better error reporting */
   94     ret = fileread(mfp, rd_buffer, RDBUF_SIZE);
   95     if (ret < 0)
   96         comerr("Read error on '%s'.\n", mfname);
   97     readbfend = rd_buffer + ret;
   98     if (readbfp >= readbfend)
   99         return (EOF);
  100     return ((int) UC *readbfp++);
  101 }
  102 
  103 EXPORT BOOL
  104 istext(c)
  105     int c;
  106 {
  107     return (isalnum(c) || c == SLASH);
  108 }
  109 
  110 /*
  111  * Copy easy characters to speed up parsing by avoiding to call getch()
  112  */
  113 EXPORT char *
  114 gtext(s)
  115     char    *s;
  116 {
  117     register int    c = 0;      /* keep stupid gcc happy */
  118     register char   *p = readbfp;
  119 
  120     while (p < readbfend) {
  121         c = (int) UC *p++;
  122         /*
  123          * We support easy to detect chars that are very probable
  124          * with the usual names.
  125          */
  126         if (!isalnum(c) && c != SLASH && c != '-' && c != '.') {
  127             --p;
  128             break;
  129         }
  130         if (s >= gbufend)
  131             s = growgbuf(s);
  132         *s++ = c;
  133     }
  134     if (p != readbfp) {
  135         lastc = c;
  136         readbfp = p;
  137     }
  138     return (s);
  139 }
  140 
  141 EXPORT char *
  142 peekrdbuf()
  143 {
  144     return (readbfp);
  145 }
  146 
  147 EXPORT char *
  148 getrdbuf()
  149 {
  150     return (readbfstart);
  151 }
  152 
  153 EXPORT int
  154 getrdbufsize()
  155 {
  156     return (readbfend - readbfstart);
  157 }
  158 
  159 /*
  160  * Switch the behaviour of the reader for parsing commandlines/others.
  161  */
  162 EXPORT void
  163 setincmd(isincmd)
  164     BOOL    isincmd;
  165 {
  166     incmd = isincmd ? TRUE:FALSE;
  167 }
  168 
  169 /*
  170  * Get a character.
  171  * Handle backslash-newline combinations and special conditions
  172  * for comment and command lines.
  173  * Count lines for error messages.
  174  */
  175 EXPORT void
  176 getch()
  177 {
  178     col++;
  179     lastc = mygetc();
  180     if (lastc == EOF)
  181         return;
  182     if (lastc == '\n') {
  183         firstc = mypeekc();
  184         lineno++;
  185         col = 0;
  186         return;
  187     } else if (lastc == '\\' && !incmd && mypeekc() == '\n') {
  188         lastc = mygetc();
  189         firstc = mypeekc();
  190         lineno++;
  191         col = 0;
  192         for (;;) {      /* Skip white space at start of line */
  193             register int    c;
  194 
  195             c = mypeekc();
  196             if (c != ' ' && c != '\t') {
  197                 lastc = ' ';
  198                 return;
  199             }
  200             mygetc();
  201             col++;
  202         }
  203     }
  204 
  205     if (lastc == '#' && !incmd) {
  206         if (mfp == (FILE *) NULL)   /* Do not skip past # when */
  207             return;         /* reading from string.    */
  208         skipline();
  209     }
  210 }
  211 
  212 EXPORT int
  213 peekch()
  214 {
  215     return (mypeekc());
  216 }
  217 
  218 /*
  219  * Unget a character.
  220  */
  221 EXPORT void
  222 ungetch(c)
  223     int c;
  224 {
  225     myungetc(c);
  226 }
  227 
  228 /*
  229  * Fast method to skip to the end of a commented out line.
  230  * Always use the POSIX method (skip to next un-escaped new line).
  231  */
  232 EXPORT void
  233 skipline()
  234 {
  235     register int    c = lastc;
  236 
  237     if (c == '\n')
  238         return;
  239 
  240     while (c != EOF) {
  241         c = mygetc();
  242         if (c == '\n') {
  243             lineno++;
  244             col = 0;
  245             lastc = c;
  246             firstc = mypeekc();
  247             return;
  248         } else if (c == '\\' && mypeekc() == '\n') {
  249             lineno++;
  250             col = 0;
  251             c = mygetc();
  252         }
  253     }
  254     firstc = lastc = c;
  255 }
  256 
  257 /*
  258  * Parse input from a string.
  259  */
  260 EXPORT void
  261 readstring(str, strname)
  262     char    *str;
  263     char    *strname;
  264 {
  265     mfname = strname;
  266     readbfp = str;
  267     readbfstart = str;  /* used for better error reporting */
  268     readbfend = str + strlen(str);
  269     firstc = *str;
  270     incmd = FALSE;
  271     parsefile();
  272     mfname = NULL;
  273 }
  274 
  275 /*
  276  * Parse input from the current Makefile.
  277  */
  278 EXPORT void
  279 readfile(name, must_exist)
  280     char    *name;
  281     BOOL    must_exist;
  282 {
  283     /*
  284      * Diese Meldung ist noch falsch (Rekursion/Makefiles)
  285      */
  286     if (Do_Warn)
  287         error("Reading file '%s' in line %d of '%s'\n", name,
  288             olineno, mfname);
  289 
  290     if (streql(name, "-")) {
  291         mfp = stdin;
  292         name = "Standard in";
  293     } else {
  294         if ((mfp = fileopen(name, "ru")) == (FILE *)NULL && must_exist)
  295             comerr("Can not open '%s'.\n", name);
  296     }
  297     file_raise(mfp, FALSE);
  298     mfname = name;
  299     readbfp = readbfend;        /* Force immediate call of fillrdbuf.*/
  300     firstc = mypeekc();
  301     incmd = FALSE;
  302     if (mfp) {
  303         parsefile();
  304         fclose(mfp);
  305     }
  306     mfp = (FILE *) NULL;
  307     mfname = NULL;
  308     col = 0;
  309 }
  310 
  311 list_t  *Incs;
  312 list_t  **inctail = &Incs;
  313 
  314 /*
  315  * Handle the "include" directive in makefiles.
  316  * If an include file does not exists, first try to find a rule to make it.
  317  * If this does not help, try to call include failure exception handling.
  318  * This exception handling enables some automake features of smake in allowing
  319  * the to call a shell script that will create the missing (may be architecture
  320  * dependant) include file on the fly with something that will at least allow
  321  * smake to continue on this platform.
  322  */
  323 EXPORT void
  324 doinclude(name, must_exist)
  325     char    *name;
  326     BOOL    must_exist;
  327 {
  328     int slc = lastc;
  329     int sfc = firstc;
  330     FILE    *smf = mfp;
  331     char    *smfn = mfname;
  332     int slineno = lineno;
  333     int scol = col;
  334     char    *srbp = readbfp;
  335     char    *srbs = readbfstart;
  336     char    *srbe = readbfend;
  337     char    *srbf = rd_buffer;
  338     char    include_buf[RDBUF_SIZE];
  339     obj_t   *st = default_tgt;
  340     obj_t   *o;
  341     list_t  *lp;
  342 
  343     olineno = lineno-1;
  344     lastc   = 0;
  345     firstc  = 0;
  346     lineno  = 1;
  347     col = 0;
  348     rd_buffer = include_buf;
  349 
  350     setup_dotvars();
  351     name = substitute(name, NullObj, 0, 0);
  352     name = strsave(name);
  353 
  354     /*
  355      * Try to make "name". Do not fail if this does not succeed.
  356      * We just decide on how to continue based on o->o_date is != 0.
  357      * If o->o_date == and must_exist == TRUE, we trigger the
  358      * .INCLUDE_FAILED: action.
  359      */
  360     xmake(name, FALSE);
  361     default_tgt = st;
  362 
  363     o = objlook(name, TRUE);
  364 
  365     /*
  366      * In order to work around a gmake bug, we need to write Makefiles that
  367      * make an included file to depend on a previously included file in
  368      * order to make gmake believe that a rule exists to make the included
  369      * file. This is otherwise nonsense but it is in conflict with our
  370      * strategy to reset o->o_date after the file has been included in
  371      * order to force to re-evaluate the complete set of rules after
  372      * everything has been read. In this special case, it looks as if the
  373      * file could not be made as it depends on a "nonexistent" target.
  374      * A solution is to fetch the time again before we decide how to go on.
  375      */
  376     if (o->o_date == 0) {
  377         o->o_date = gftime(name);   /* Check if file is present */
  378     }
  379 
  380     if (Debug > 1)
  381         error("doinclude(%s, %d)= date: %s level: %d\n",
  382             name, must_exist, prtime(o->o_date), o->o_level);
  383 
  384     /*
  385      * "name" does not exist and could not be made.
  386      * If must_exist == TRUE, trigger the .INCLUDE_FAILED: action.
  387      */
  388     if (must_exist && o->o_date == 0 && IncludeFailed) {
  389         list_t  l;
  390 
  391         o->o_date = newtime;        /* Force to be out of date  */
  392         l.l_next = (list_t *)0;     /* Only one element:        */
  393         l.l_obj = o;            /* The file to be included  */
  394         IncludeFailed->o_list = &l; /* Make it $^           */
  395         IncludeFailed->o_date = (date_t)0;
  396         omake(IncludeFailed, FALSE);    /* Try to apply rules       */
  397         o->o_date = gftime(name);   /* Check if file is present */
  398     }
  399 
  400     /*
  401      * If "name" exists or could be made by a specific rule or the
  402      * fall back rule .INCLUDE_FAILED:, parse the content of the file
  403      * to be included.
  404      */
  405     if (must_exist || o->o_date != 0) {
  406         char    includename[TYPICAL_NAMEMAX];
  407         char    *iname;
  408 
  409         if (Prdep)
  410             error("Reading file '%s' from '%s'\n", name, mfname);
  411 
  412         /*
  413          * Now add this object to the list of objects that must be
  414          * remade to force integrity of our lists before we start
  415          * to make the real targets.
  416          */
  417         lp = (list_t *) fastalloc(sizeof (*lp));
  418         lp->l_obj = o;
  419         *inctail = lp;
  420         inctail = &lp->l_next;
  421         lp->l_next = 0;
  422 
  423         /*
  424          * The code in update.c needs to make sure that o->o_level has
  425          * the right value tp create the right name for include.
  426          */
  427         iname = build_path(o->o_level, o->o_name, o->o_namelen,
  428                     includename, sizeof (includename));
  429 /*error("include '%s' -> '%s' %s\n", o->o_name, iname, prtime(o->o_date));*/
  430         if (iname != NULL) {
  431             readfile(iname, must_exist);
  432             if (iname != o->o_name && iname != includename)
  433                 free(iname);
  434         } else {
  435             comerrno(EX_BAD,
  436                 "Cannot build path for 'include %s'.\n",
  437                 o->o_name);
  438         }
  439         /*
  440          * Zurücksetzen des Datums bewirkt Neuauswertung
  441          * der Abhängigkeitsliste.
  442          * XXX Das kann Probleme bei make depend geben.
  443          */
  444         o->o_date = 0;
  445     }
  446 
  447     lastc = slc;
  448     firstc = sfc;
  449     mfp = smf;
  450     mfname = smfn;
  451     lineno = slineno;
  452     col = scol;
  453     readbfp = srbp;
  454     readbfstart = srbs;
  455     readbfend = srbe;
  456     rd_buffer = srbf;
  457 }
  458 
  459 /*
  460  * Re-make the included files.
  461  * This must be done because after they have been made the first time,
  462  * the dependency list may have changed. If we don't remake the included
  463  * files, the xxx.d dependency files will not be remade after we touch a file
  464  * that is not in the primary source list.
  465  */
  466 EXPORT void
  467 makeincs()
  468 {
  469     list_t  *l;
  470 
  471     for (l = Incs; l != 0; l = l->l_next) {
  472 /*      printf("inc(%s)\n", l->l_obj->o_name);*/
  473         omake(l->l_obj, TRUE);
  474     }
  475 }