LCOV - code coverage report
Current view: top level - bash-4.4.23 - mksyntax.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 116 136 85.3 %
Date: 2020-10-29 14:49:28 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /*
       2             :  * mksyntax.c - construct shell syntax table for fast char attribute lookup.
       3             :  */
       4             : 
       5             : /* Copyright (C) 2000-2009 Free Software Foundation, Inc.
       6             : 
       7             :    This file is part of GNU Bash, the Bourne Again SHell.
       8             : 
       9             :    Bash is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    Bash is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "config.h"
      24             : 
      25             : #include <stdio.h>
      26             : #include "bashansi.h"
      27             : #include "chartypes.h"
      28             : #include <errno.h>
      29             : 
      30             : #ifdef HAVE_UNISTD_H
      31             : #  include <unistd.h>
      32             : #endif
      33             : 
      34             : #include "syntax.h"
      35             : 
      36             : extern int optind;
      37             : extern char *optarg;
      38             : 
      39             : #ifndef errno
      40             : extern int errno;
      41             : #endif
      42             : 
      43             : #ifndef HAVE_STRERROR
      44             : extern char *strerror();
      45             : #endif
      46             : 
      47             : struct wordflag {
      48             :         int     flag;
      49             :         char    *fstr;
      50             : } wordflags[] = {
      51             :         { CWORD,        "CWORD" },
      52             :         { CSHMETA,      "CSHMETA" },
      53             :         { CSHBRK,       "CSHBRK" },
      54             :         { CBACKQ,       "CBACKQ" },
      55             :         { CQUOTE,       "CQUOTE" },
      56             :         { CSPECL,       "CSPECL" },
      57             :         { CEXP,         "CEXP" },
      58             :         { CBSDQUOTE,    "CBSDQUOTE" },
      59             :         { CBSHDOC,      "CBSHDOC" },
      60             :         { CGLOB,        "CGLOB" },
      61             :         { CXGLOB,       "CXGLOB" },
      62             :         { CXQUOTE,      "CXQUOTE" },
      63             :         { CSPECVAR,     "CSPECVAR" },
      64             :         { CSUBSTOP,     "CSUBSTOP" },
      65             :         { CBLANK,       "CBLANK" },
      66             : };
      67             :         
      68             : #define N_WFLAGS        (sizeof (wordflags) / sizeof (wordflags[0]))
      69             : #define SYNSIZE         256
      70             : 
      71             : int     lsyntax[SYNSIZE];
      72             : int     debug;
      73             : char    *progname;
      74             : 
      75             : char    preamble[] = "\
      76             : /*\n\
      77             :  * This file was generated by mksyntax.  DO NOT EDIT.\n\
      78             :  */\n\
      79             : \n";
      80             : 
      81             : char    includes[] = "\
      82             : #include \"config.h\"\n\
      83             : #include \"stdc.h\"\n\
      84             : #include \"syntax.h\"\n\n";
      85             : 
      86             : static void
      87           0 : usage()
      88             : {
      89           0 :   fprintf (stderr, "%s: usage: %s [-d] [-o filename]\n", progname, progname);
      90           0 :   exit (2);
      91             : }
      92             : 
      93             : #ifdef INCLUDE_UNUSED
      94             : static int
      95             : getcflag (s)
      96             :      char *s;
      97             : {
      98             :   int i;
      99             : 
     100             :   for (i = 0; i < N_WFLAGS; i++)
     101             :     if (strcmp (s, wordflags[i].fstr) == 0)
     102             :       return wordflags[i].flag;
     103             :   return -1;
     104             : }
     105             : #endif
     106             : 
     107             : static char *
     108         256 : cdesc (i)
     109             :      int i;
     110             : {
     111         256 :   static char xbuf[16];
     112             : 
     113         256 :   if (i == ' ')
     114             :     return "SPC";
     115         255 :   else if (ISPRINT (i))
     116             :     {
     117          94 :       xbuf[0] = i;
     118          94 :       xbuf[1] = '\0';
     119          94 :       return (xbuf);
     120             :     }
     121         161 :   else if (i == CTLESC)
     122             :     return "CTLESC";
     123         160 :   else if (i == CTLNUL)
     124             :     return "CTLNUL";
     125         159 :   else if (i == '\033')         /* ASCII */
     126             :     return "ESC";
     127             : 
     128         158 :   xbuf[0] = '\\';
     129         158 :   xbuf[2] = '\0';
     130             :     
     131         158 :   switch (i)
     132             :     {
     133             : #ifdef __STDC__
     134           1 :     case '\a': xbuf[1] = 'a'; break;
     135           1 :     case '\v': xbuf[1] = 'v'; break;
     136             : #else
     137             :     case '\007': xbuf[1] = 'a'; break;
     138             :     case 0x0B: xbuf[1] = 'v'; break;
     139             : #endif
     140           1 :     case '\b': xbuf[1] = 'b'; break;
     141           1 :     case '\f': xbuf[1] = 'f'; break;
     142           1 :     case '\n': xbuf[1] = 'n'; break;
     143           1 :     case '\r': xbuf[1] = 'r'; break;
     144           1 :     case '\t': xbuf[1] = 't'; break;
     145         151 :     default: sprintf (xbuf, "%d", i); break;
     146             :     }
     147             : 
     148             :   return xbuf;  
     149             : }
     150             : 
     151             : static char *
     152             : getcstr (f)
     153             :      int f;
     154             : {
     155             :   int i;
     156             : 
     157           0 :   for (i = 0; i < N_WFLAGS; i++)
     158           0 :     if (f == wordflags[i].flag)
     159           0 :       return (wordflags[i].fstr);
     160             :   return ((char *)NULL);
     161             : }
     162             : 
     163             : static void
     164          11 : addcstr (str, flag)
     165             :      char *str;
     166             :      int flag;
     167             : {
     168          11 :   char *s, *fstr;
     169          11 :   unsigned char uc;
     170             : 
     171          66 :   for (s = str; s && *s; s++)
     172             :     {
     173          55 :       uc = *s;
     174             : 
     175          55 :       if (debug)
     176             :         {
     177           0 :           fstr = getcstr (flag);
     178           0 :           fprintf(stderr, "added %s for character %s\n", fstr, cdesc(uc));
     179             :         }
     180             :         
     181          55 :       lsyntax[uc] |= flag;
     182             :     }
     183          11 : }
     184             : 
     185             : static void
     186           4 : addcchar (c, flag)
     187             :      unsigned char c;
     188             :      int flag;
     189             : {
     190           4 :   char *fstr;
     191             : 
     192           4 :   if (debug)
     193             :     {
     194           0 :       fstr = getcstr (flag);
     195           0 :       fprintf (stderr, "added %s for character %s\n", fstr, cdesc(c));
     196             :     }
     197           4 :   lsyntax[c] |= flag;
     198           4 : }
     199             : 
     200             : static void
     201           1 : addblanks ()
     202             : {
     203           1 :   register int i;
     204           1 :   unsigned char uc;
     205             : 
     206         257 :   for (i = 0; i < SYNSIZE; i++)
     207             :     {
     208         256 :       uc = i;
     209             :       /* Since we don't call setlocale(), this defaults to the "C" locale, and
     210             :          the default blank characters will be space and tab. */
     211         256 :       if (isblank (uc))
     212           2 :         lsyntax[uc] |= CBLANK;
     213             :     }
     214           1 : }
     215             : 
     216             : /* load up the correct flag values in lsyntax */
     217             : static void
     218           1 : load_lsyntax ()
     219             : {
     220             :   /* shell metacharacters */
     221           1 :   addcstr (shell_meta_chars, CSHMETA);
     222             : 
     223             :   /* shell word break characters */
     224           1 :   addcstr (shell_break_chars, CSHBRK);
     225             : 
     226           1 :   addcchar ('`', CBACKQ);
     227             : 
     228           1 :   addcstr (shell_quote_chars, CQUOTE);
     229             : 
     230           1 :   addcchar (CTLESC, CSPECL);
     231           1 :   addcchar (CTLNUL, CSPECL);
     232             : 
     233           1 :   addcstr (shell_exp_chars, CEXP);
     234             : 
     235           1 :   addcstr (slashify_in_quotes, CBSDQUOTE);
     236           1 :   addcstr (slashify_in_here_document, CBSHDOC);
     237             : 
     238           1 :   addcstr (shell_glob_chars, CGLOB);
     239             : 
     240             : #if defined (EXTENDED_GLOB)
     241           1 :   addcstr (ext_glob_chars, CXGLOB);
     242             : #endif
     243             : 
     244           1 :   addcstr (shell_quote_chars, CXQUOTE);
     245           1 :   addcchar ('\\', CXQUOTE);
     246             : 
     247           1 :   addcstr ("@*#?-$!", CSPECVAR);      /* omits $0...$9 and $_ */
     248             : 
     249           1 :   addcstr ("-=?+", CSUBSTOP);         /* OP in ${paramOPword} */
     250             : 
     251           1 :   addblanks ();
     252           1 : }
     253             : 
     254             : static void
     255         256 : dump_lflags (fp, ind)
     256             :      FILE *fp;
     257             :      int ind;
     258             : {
     259         256 :   int xflags, first, i;
     260             : 
     261         256 :   xflags = lsyntax[ind];
     262         256 :   first = 1;
     263             : 
     264         256 :   if (xflags == 0)
     265         228 :     fputs (wordflags[0].fstr, fp);
     266             :   else
     267             :     {
     268         420 :       for (i = 1; i < N_WFLAGS; i++)
     269         392 :         if (xflags & wordflags[i].flag)
     270             :           {
     271          61 :             if (first)
     272             :               first = 0;
     273             :             else
     274          33 :               putc ('|', fp);
     275          61 :             fputs (wordflags[i].fstr, fp);
     276             :           }
     277             :     }
     278         256 : }
     279             : 
     280             : static void
     281         256 : wcomment (fp, i)
     282             :      FILE *fp;
     283             :      int i;
     284             : {
     285         256 :   fputs ("\t\t/* ", fp);
     286             : 
     287         256 :   fprintf (fp, "%s", cdesc(i));
     288             :       
     289         256 :   fputs (" */", fp);
     290         256 : }
     291             : 
     292             : static void
     293           1 : dump_lsyntax (fp)
     294             :      FILE *fp;
     295             : {
     296           1 :   int i;
     297             : 
     298           1 :   fprintf (fp, "int sh_syntabsiz = %d;\n", SYNSIZE);
     299           1 :   fprintf (fp, "int sh_syntaxtab[%d] = {\n", SYNSIZE);
     300             : 
     301         257 :   for (i = 0; i < SYNSIZE; i++)
     302             :     {
     303         256 :       putc ('\t', fp);
     304         256 :       dump_lflags (fp, i);
     305         256 :       putc (',', fp);
     306         256 :       wcomment (fp, i);
     307         256 :       putc ('\n', fp);
     308             :     }
     309             : 
     310           1 :   fprintf (fp, "};\n");
     311           1 : }
     312             : 
     313             : int
     314           1 : main(argc, argv)
     315             :      int argc;
     316             :      char **argv;
     317             : {
     318           1 :   int opt, i;
     319           1 :   char *filename;
     320           1 :   FILE *fp;
     321             : 
     322           1 :   if ((progname = strrchr (argv[0], '/')) == 0)
     323           0 :     progname = argv[0];
     324             :   else
     325           1 :     progname++;
     326             : 
     327           1 :   filename = (char *)NULL;
     328           1 :   debug = 0;
     329             : 
     330           2 :   while ((opt = getopt (argc, argv, "do:")) != EOF)
     331             :     {
     332           1 :       switch (opt)
     333             :         {
     334           0 :         case 'd':
     335           0 :           debug = 1;
     336           0 :           break;
     337           1 :         case 'o':
     338           1 :           filename = optarg;
     339           1 :           break;
     340           0 :         default:
     341           0 :           usage();
     342             :         }
     343             :     }
     344             : 
     345           1 :   argc -= optind;
     346           1 :   argv += optind;
     347             : 
     348           1 :   if (filename)
     349             :     {
     350           1 :       fp = fopen (filename, "w");
     351           1 :       if (fp == 0)
     352             :         {
     353           0 :           fprintf (stderr, "%s: %s: cannot open: %s\n", progname, filename, strerror(errno));
     354           0 :           exit (1);
     355             :         }
     356             :     }
     357             :   else
     358             :     {
     359           0 :       filename = "stdout";
     360           0 :       fp = stdout;
     361             :     }
     362             : 
     363             : 
     364         257 :   for (i = 0; i < SYNSIZE; i++)
     365         256 :     lsyntax[i] = CWORD;
     366             : 
     367           1 :   load_lsyntax ();
     368             : 
     369           1 :   fprintf (fp, "%s\n", preamble);
     370           1 :   fprintf (fp, "%s\n", includes);
     371             : 
     372           1 :   dump_lsyntax (fp);
     373             : 
     374           1 :   if (fp != stdout)
     375           1 :     fclose (fp);
     376           1 :   exit (0);
     377             : }
     378             : 
     379             : 
     380             : #if !defined (HAVE_STRERROR)
     381             : 
     382             : #include <bashtypes.h>
     383             : #if defined (HAVE_SYS_PARAM_H)
     384             : #  include <sys/param.h>
     385             : #endif
     386             : 
     387             : #if defined (HAVE_UNISTD_H)
     388             : #  include <unistd.h>
     389             : #endif
     390             : 
     391             : /* Return a string corresponding to the error number E.  From
     392             :    the ANSI C spec. */
     393             : #if defined (strerror)
     394             : #  undef strerror
     395             : #endif
     396             : 
     397             : char *
     398             : strerror (e)
     399             :      int e;
     400             : {
     401             :   static char emsg[40];
     402             : #if defined (HAVE_SYS_ERRLIST)
     403             :   extern int sys_nerr;
     404             :   extern char *sys_errlist[];
     405             : 
     406             :   if (e > 0 && e < sys_nerr)
     407             :     return (sys_errlist[e]);
     408             :   else
     409             : #endif /* HAVE_SYS_ERRLIST */
     410             :     {
     411             :       sprintf (emsg, "Unknown system error %d", e);
     412             :       return (&emsg[0]);
     413             :     }
     414             : }
     415             : #endif /* HAVE_STRERROR */

Generated by: LCOV version 1.14.0.6.4058