LCOV - code coverage report
Current view: top level - src - dumpsexp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 315 0.0 %
Date: 2016-09-12 12:56:58 Functions: 0 16 0.0 %

          Line data    Source code
       1             : /* dumpsexp.c - Dump S-expressions.
       2             :  * Copyright (C) 2007, 2010 Free Software Foundation, Inc.
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published
       6             :  * by the Free Software Foundation; either version 3 of the License,
       7             :  * or (at your option) any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful, but
      10             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include <config.h>
      19             : #include <stdio.h>
      20             : #include <string.h>
      21             : #include <stdlib.h>
      22             : #include <assert.h>
      23             : #include <stdarg.h>
      24             : #include <errno.h>
      25             : /* For a native WindowsCE binary we need to include gpg-error.h to
      26             :    provide a replacement for strerror.  */
      27             : #ifdef __MINGW32CE__
      28             : # include <gpg-error.h>
      29             : #endif
      30             : 
      31             : #define PGM "dumpsexp"
      32             : #define MYVERSION_LINE PGM " (Libgcrypt) " VERSION
      33             : #define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n"
      34             : 
      35             : 
      36             : static int verbose;  /* Verbose mode.  */
      37             : static int decimal;  /* Print addresses in decimal.  */
      38             : static int assume_hex;  /* Assume input is hexencoded.  */
      39             : static int advanced; /* Advanced format output.  */
      40             : 
      41             : static void
      42           0 : print_version (int with_help)
      43             : {
      44           0 :   fputs (MYVERSION_LINE "\n"
      45             :          "Copyright (C) 2010 Free Software Foundation, Inc.\n"
      46             :          "License GPLv3+: GNU GPL version 3 or later "
      47             :          "<http://gnu.org/licenses/gpl.html>\n"
      48             :          "This is free software: you are free to change and redistribute it.\n"
      49             :          "There is NO WARRANTY, to the extent permitted by law.\n",
      50             :          stdout);
      51             : 
      52           0 :   if (with_help)
      53           0 :     fputs ("\n"
      54             :            "Usage: " PGM " [OPTIONS] [file]\n"
      55             :            "Debug tool for S-expressions\n"
      56             :            "\n"
      57             :            "  --decimal     Print offsets using decimal notation\n"
      58             :            "  --assume-hex  Assume input is a hex dump\n"
      59             :            "  --advanced    Print file in advanced format\n"
      60             :            "  --verbose     Show what we are doing\n"
      61             :            "  --version     Print version of the program and exit\n"
      62             :            "  --help        Display this help and exit\n"
      63             :            BUGREPORT_LINE, stdout );
      64             : 
      65           0 :   exit (0);
      66             : }
      67             : 
      68             : static int
      69           0 : print_usage (void)
      70             : {
      71           0 :   fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr);
      72           0 :   fputs ("       (use --help to display options)\n", stderr);
      73           0 :   exit (1);
      74             : }
      75             : 
      76             : 
      77             : #define space_p(a)    ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
      78             : #define digit_p(a)    ((a) >= '0' && (a) <= '9')
      79             : #define octdigit_p(a) ((a) >= '0' && (a) <= '7')
      80             : #define alpha_p(a)    (   ((a) >= 'A' && (a) <= 'Z')  \
      81             :                        || ((a) >= 'a' && (a) <= 'z'))
      82             : #define hexdigit_p(a) (digit_p (a)                     \
      83             :                        || ((a) >= 'A' && (a) <= 'F')  \
      84             :                        || ((a) >= 'a' && (a) <= 'f'))
      85             : #define xtoi_1(a)     ((a) <= '9'? ((a)- '0'): \
      86             :                        (a) <= 'F'? ((a)-'A'+10):((a)-'a'+10))
      87             : 
      88             : 
      89             : /* Return true if P points to a byte containing a whitespace according
      90             :    to the S-expressions definition. */
      91             : static inline int
      92           0 : whitespace_p (int c)
      93             : {
      94           0 :   switch (c)
      95             :     {
      96           0 :     case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
      97           0 :     default: return 0;
      98             :     }
      99             : }
     100             : 
     101             : static void
     102           0 : logit (const char *format, ...)
     103             : {
     104             :   va_list arg_ptr;
     105             : 
     106           0 :   va_start (arg_ptr, format) ;
     107           0 :   fputs (PGM ": ", stderr);
     108           0 :   vfprintf (stderr, format, arg_ptr);
     109           0 :   putc ('\n', stderr);
     110           0 :   va_end (arg_ptr);
     111           0 : }
     112             : 
     113             : /* The raw data buffer and its current length */
     114             : static unsigned char databuffer[16];
     115             : static int databufferlen;
     116             : /* The number of bytes in databuffer which should be skipped at a flush.  */
     117             : static int skipdatabufferlen;
     118             : /* The number of raw bytes printed on the last line.  */
     119             : static int nbytesprinted;
     120             : /* The file offset of the current data buffer .  */
     121             : static unsigned long databufferoffset;
     122             : 
     123             : 
     124             : 
     125             : static int
     126           0 : my_getc (FILE *fp)
     127             : {
     128             :   int c1, c2;
     129             : 
     130           0 :   if (!assume_hex)
     131           0 :     return getc (fp);
     132             : 
     133           0 :   while ( (c1=getc (fp)) != EOF && space_p (c1) )
     134             :     ;
     135           0 :   if (c1 == EOF)
     136           0 :     return EOF;
     137             : 
     138           0 :   if (!hexdigit_p (c1))
     139             :     {
     140           0 :       logit ("non hex-digit encountered\n");
     141           0 :       return EOF;
     142             :     }
     143             : 
     144           0 :   while ( (c2=getc (fp)) != EOF && space_p (c2) )
     145             :     ;
     146           0 :   if (c2 == EOF)
     147             :     {
     148           0 :       logit ("error reading second hex nibble\n");
     149           0 :       return EOF;
     150             :     }
     151           0 :   if (!hexdigit_p (c2))
     152             :     {
     153           0 :       logit ("second hex nibble is not a hex-digit\n");
     154           0 :       return EOF;
     155             :     }
     156           0 :   return xtoi_1 (c1) * 16 + xtoi_1 (c2);
     157             : }
     158             : 
     159             : 
     160             : 
     161             : 
     162             : 
     163             : /* Flush the raw data buffer.  */
     164             : static void
     165           0 : flushdatabuffer (void)
     166             : {
     167             :   int i;
     168             : 
     169           0 :   if (!databufferlen)
     170           0 :     return;
     171           0 :   nbytesprinted = 0;
     172           0 :   if (decimal)
     173           0 :     printf ("%08lu ", databufferoffset);
     174             :   else
     175           0 :     printf ("%08lx ", databufferoffset);
     176           0 :   for (i=0; i < databufferlen; i++)
     177             :     {
     178           0 :       if (i == 8)
     179           0 :         putchar (' ');
     180           0 :       if (i < skipdatabufferlen)
     181           0 :         fputs ("   ", stdout);
     182             :       else
     183             :         {
     184           0 :           printf (" %02x", databuffer[i]);
     185           0 :           databufferoffset++;
     186             :         }
     187           0 :       nbytesprinted++;
     188             :     }
     189           0 :   for (; i < sizeof (databuffer); i++)
     190             :     {
     191           0 :       if (i == 8)
     192           0 :         putchar (' ');
     193           0 :       fputs ("   ", stdout);
     194             :     }
     195           0 :   fputs ("  |", stdout);
     196           0 :   for (i=0; i < databufferlen; i++)
     197             :     {
     198           0 :       if (i < skipdatabufferlen)
     199           0 :         putchar (' ');
     200           0 :       else if (databuffer[i] >= ' ' && databuffer[i] <= '~'
     201           0 :                && databuffer[i] != '|')
     202           0 :         putchar (databuffer[i]);
     203             :       else
     204           0 :         putchar ('.');
     205             :     }
     206           0 :   putchar ('|');
     207           0 :   putchar ('\n');
     208           0 :   databufferlen = 0;
     209           0 :   skipdatabufferlen = 0;
     210             : }
     211             : 
     212             : 
     213             : /* Add C to the raw data buffer and flush as needed.  */
     214             : static void
     215           0 : addrawdata (int c)
     216             : {
     217           0 :   if ( databufferlen >= sizeof databuffer )
     218           0 :     flushdatabuffer ();
     219           0 :   databuffer[databufferlen++] = c;
     220           0 : }
     221             : 
     222             : 
     223             : static void
     224           0 : printcursor (int both)
     225             : {
     226             :   int i;
     227             : 
     228           0 :   flushdatabuffer ();
     229           0 :   printf ("%8s ", "");
     230           0 :   for (i=0; i < sizeof (databuffer); i++)
     231             :     {
     232           0 :       if (i == 8)
     233           0 :         putchar (' ');
     234           0 :       if (i+1 == nbytesprinted)
     235             :         {
     236           0 :           fputs (" ^ ", stdout);
     237           0 :           if (!both)
     238           0 :             break;
     239             :         }
     240             :       else
     241           0 :         fputs ("   ", stdout);
     242             :     }
     243           0 :   if (both)
     244             :     {
     245           0 :       fputs ("   ", stdout);
     246           0 :       for (i=0; i < nbytesprinted-1; i++)
     247           0 :         putchar (' ');
     248           0 :       putchar ('^');
     249             :     }
     250           0 :   databufferlen = skipdatabufferlen = nbytesprinted;
     251           0 : }
     252             : 
     253             : static void
     254           0 : printerr (const char *text)
     255             : {
     256           0 :   printcursor (1);
     257           0 :   printf ("\n          Error: %s\n", text);
     258           0 : }
     259             : 
     260             : static void
     261           0 : printctl (const char *text)
     262             : {
     263           0 :   if (verbose && !advanced)
     264             :     {
     265           0 :       printcursor (0);
     266           0 :       printf ("%s\n", text);
     267             :     }
     268           0 : }
     269             : 
     270             : static void
     271           0 : printchr (int c)
     272             : {
     273           0 :   putchar (c);
     274           0 : }
     275             : 
     276             : /* static void */
     277             : /* printhex (int c) */
     278             : /* { */
     279             : /*   printf ("\\x%02x", c); */
     280             : /* } */
     281             : 
     282             : 
     283             : #if 0
     284             : /****************
     285             :  * Print SEXP to buffer using the MODE.  Returns the length of the
     286             :  * SEXP in buffer or 0 if the buffer is too short (We have at least an
     287             :  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
     288             :  * the required length is returned.
     289             :  */
     290             : size_t
     291             : gcry_sexp_sprint (const gcry_sexp_t list,
     292             :                   void *buffer, size_t maxlength )
     293             : {
     294             :   static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
     295             :   const unsigned char *s;
     296             :   char *d;
     297             :   DATALEN n;
     298             :   char numbuf[20];
     299             :   int i, indent = 0;
     300             : 
     301             :   s = list? list->d : empty;
     302             :   d = buffer;
     303             :   while ( *s != ST_STOP )
     304             :     {
     305             :       switch ( *s )
     306             :         {
     307             :         case ST_OPEN:
     308             :           s++;
     309             :           if (indent)
     310             :             putchar ('\n');
     311             :           for (i=0; i < indent; i++)
     312             :             putchar (' ');
     313             :           putchar ('(');
     314             :           indent++;
     315             :           break;
     316             :         case ST_CLOSE:
     317             :           s++;
     318             :           putchar (')');
     319             :           indent--;
     320             :           if (*s != ST_OPEN && *s != ST_STOP)
     321             :             {
     322             :               putchar ('\n');
     323             :               for (i=0; i < indent; i++)
     324             :                 putchar (' ');
     325             :             }
     326             :           break;
     327             :         case ST_DATA:
     328             :           s++;
     329             :           memcpy (&n, s, sizeof n);
     330             :           s += sizeof n;
     331             :           {
     332             :             int type;
     333             :             size_t nn;
     334             : 
     335             :             switch ( (type=suitable_encoding (s, n)))
     336             :               {
     337             :               case 1: nn = convert_to_string (s, n, NULL); break;
     338             :               case 2: nn = convert_to_token (s, n, NULL); break;
     339             :               default: nn = convert_to_hex (s, n, NULL); break;
     340             :               }
     341             :             switch (type)
     342             :               {
     343             :               case 1: convert_to_string (s, n, d); break;
     344             :               case 2: convert_to_token (s, n, d); break;
     345             :               default: convert_to_hex (s, n, d); break;
     346             :               }
     347             :             d += nn;
     348             :             if (s[n] != ST_CLOSE)
     349             :               putchar (' ');
     350             :           }
     351             :           else
     352             :             {
     353             :               snprintf (numbuf, sizeof numbuf,  "%u:", (unsigned int)n );
     354             :               d = stpcpy (d, numbuf);
     355             :               memcpy (d, s, n);
     356             :               d += n;
     357             :             }
     358             :           s += n;
     359             :           break;
     360             :         default:
     361             :           BUG ();
     362             :         }
     363             :     }
     364             :   putchar ('\n');
     365             :   return len;
     366             : }
     367             : #endif
     368             : 
     369             : 
     370             : /* Prepare for saving a chunk of data.  */
     371             : static void
     372           0 : init_data (void)
     373             : {
     374             : 
     375           0 : }
     376             : 
     377             : /* Push C on the current data chunk.  */
     378             : static void
     379           0 : push_data (int c)
     380             : {
     381             :   (void)c;
     382           0 : }
     383             : 
     384             : /* Flush and thus print the current data chunk.  */
     385             : static void
     386           0 : flush_data (void)
     387             : {
     388             : 
     389           0 : }
     390             : 
     391             : 
     392             : /* Returns 0 on success.  */
     393             : static int
     394           0 : parse_and_print (FILE *fp)
     395             : {
     396             :   static const char tokenchars[] =
     397             :     "abcdefghijklmnopqrstuvwxyz"
     398             :     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     399             :     "0123456789-./_:*+=";
     400             :   int c;
     401           0 :   int level = 0;
     402           0 :   int tokenc = 0;
     403           0 :   int hexcount = 0;
     404           0 :   int disphint = 0;
     405           0 :   unsigned long datalen = 0;
     406             :   char quote_buf[10];
     407           0 :   int quote_idx = 0;
     408             :   enum
     409             :     {
     410             :       INIT_STATE = 0, IN_NUMBER, PRE_DATA, IN_DATA, IN_STRING,
     411             :       IN_ESCAPE, IN_OCT_ESC, IN_HEX_ESC,
     412             :       CR_ESC, LF_ESC, IN_HEXFMT, IN_BASE64
     413             :     }
     414           0 :   state = INIT_STATE;
     415             : 
     416             : 
     417           0 :   while ((c = my_getc (fp)) != EOF )
     418             :     {
     419           0 :       addrawdata (c);
     420           0 :       switch (state)
     421             :         {
     422             :         case INIT_STATE:
     423           0 :           if (tokenc)
     424             :             {
     425           0 :               if (strchr (tokenchars, c))
     426             :                 {
     427           0 :                   printchr (c);
     428           0 :                   continue;
     429             :                 }
     430           0 :               tokenc = 0;
     431             :             }
     432             :         parse_init_state:
     433           0 :           if (c == '(')
     434             :             {
     435           0 :               if (disphint)
     436             :                 {
     437           0 :                   printerr ("unmatched display hint");
     438           0 :                   disphint = 0;
     439             :                 }
     440           0 :               printctl ("open");
     441           0 :               level++;
     442             :             }
     443           0 :           else if (c == ')')
     444             :             {
     445           0 :               if (disphint)
     446             :                 {
     447           0 :                   printerr ("unmatched display hint");
     448           0 :                   disphint = 0;
     449             :                 }
     450           0 :               printctl ("close");
     451           0 :               level--;
     452             :             }
     453           0 :           else if (c == '\"')
     454             :             {
     455           0 :               state = IN_STRING;
     456           0 :               printctl ("beginstring");
     457           0 :               init_data ();
     458             :             }
     459           0 :           else if (c == '#')
     460             :             {
     461           0 :               state = IN_HEXFMT;
     462           0 :               hexcount = 0;
     463           0 :               printctl ("beginhex");
     464           0 :               init_data ();
     465             :             }
     466           0 :           else if (c == '|')
     467             :             {
     468           0 :               state = IN_BASE64;
     469           0 :               printctl ("beginbase64");
     470           0 :               init_data ();
     471             :             }
     472           0 :           else if (c == '[')
     473             :             {
     474           0 :               if (disphint)
     475           0 :                 printerr ("nested display hint");
     476           0 :               disphint = c;
     477             :             }
     478           0 :           else if (c == ']')
     479             :             {
     480           0 :               if (!disphint)
     481           0 :                 printerr ("no open display hint");
     482           0 :               disphint = 0;
     483             :             }
     484           0 :           else if (c >= '0' && c <= '9')
     485             :             {
     486           0 :               if (c == '0')
     487           0 :                 printerr ("zero prefixed length");
     488           0 :               state = IN_NUMBER;
     489           0 :               datalen = (c - '0');
     490             :             }
     491           0 :           else if (strchr (tokenchars, c))
     492             :             {
     493           0 :               printchr (c);
     494           0 :               tokenc = c;
     495             :             }
     496           0 :           else if (whitespace_p (c))
     497             :             ;
     498           0 :           else if (c == '{')
     499             :             {
     500           0 :               printerr ("rescanning is not supported");
     501             :             }
     502           0 :           else if (c == '&' || c == '\\')
     503             :             {
     504           0 :               printerr ("reserved punctuation detected");
     505             :             }
     506             :           else
     507             :             {
     508           0 :               printerr ("bad character detected");
     509             :             }
     510           0 :           break;
     511             : 
     512             :         case IN_NUMBER:
     513           0 :           if (digit_p (c))
     514           0 :             {
     515           0 :               unsigned long tmp = datalen * 10 + (c - '0');
     516           0 :               if (tmp < datalen)
     517             :                 {
     518           0 :                   printerr ("overflow in data length");
     519           0 :                   state = INIT_STATE;
     520           0 :                   datalen = 0;
     521             :                 }
     522             :               else
     523           0 :                 datalen = tmp;
     524             :             }
     525           0 :           else if (c == ':')
     526             :             {
     527           0 :               if (!datalen)
     528             :                 {
     529           0 :                   printerr ("no data length");
     530           0 :                   state = INIT_STATE;
     531             :                 }
     532             :               else
     533           0 :                 state = PRE_DATA;
     534             :             }
     535           0 :           else if (c == '\"' || c == '#' || c == '|' )
     536             :             {
     537             :               /* We ignore the optional length and divert to the init
     538             :                  state parser code. */
     539             :               goto parse_init_state;
     540             :             }
     541             :           else
     542           0 :             printerr ("invalid length specification");
     543           0 :           break;
     544             : 
     545             :         case PRE_DATA:
     546           0 :           state = IN_DATA;
     547           0 :           printctl ("begindata");
     548           0 :           init_data ();
     549             :         case IN_DATA:
     550           0 :           if (datalen)
     551             :             {
     552           0 :               push_data (c);
     553           0 :               datalen--;
     554             :             }
     555           0 :           if (!datalen)
     556             :             {
     557           0 :               state = INIT_STATE;
     558           0 :               printctl ("enddata");
     559           0 :               flush_data ();
     560             :             }
     561           0 :           break;
     562             : 
     563             :         case IN_STRING:
     564           0 :           if (c == '\"')
     565             :             {
     566           0 :               printctl ("endstring");
     567           0 :               flush_data ();
     568           0 :               state = INIT_STATE;
     569             :             }
     570           0 :           else if (c == '\\')
     571           0 :             state = IN_ESCAPE;
     572             :           else
     573           0 :             push_data (c);
     574           0 :           break;
     575             : 
     576             :         case IN_ESCAPE:
     577           0 :           switch (c)
     578             :             {
     579           0 :             case 'b':  push_data ('\b'); state = IN_STRING; break;
     580           0 :             case 't':  push_data ('\t'); state = IN_STRING; break;
     581           0 :             case 'v':  push_data ('\v'); state = IN_STRING; break;
     582           0 :             case 'n':  push_data ('\n'); state = IN_STRING; break;
     583           0 :             case 'f':  push_data ('\f'); state = IN_STRING; break;
     584           0 :             case 'r':  push_data ('\r'); state = IN_STRING; break;
     585           0 :             case '"':  push_data ('"');  state = IN_STRING; break;
     586           0 :             case '\'': push_data ('\''); state = IN_STRING; break;
     587           0 :             case '\\': push_data ('\\'); state = IN_STRING; break;
     588             : 
     589             :             case '0': case '1': case '2': case '3': case '4':
     590             :             case '5': case '6': case '7':
     591           0 :               state = IN_OCT_ESC;
     592           0 :               quote_idx = 0;
     593           0 :               quote_buf[quote_idx++] = c;
     594           0 :               break;
     595             : 
     596             :             case 'x':
     597           0 :               state = IN_HEX_ESC;
     598           0 :               quote_idx = 0;
     599           0 :               break;
     600             : 
     601             :             case '\r':
     602           0 :               state = CR_ESC;
     603           0 :               break;
     604             : 
     605             :             case '\n':
     606           0 :               state = LF_ESC;
     607           0 :               break;
     608             : 
     609             :             default:
     610           0 :               printerr ("invalid escape sequence");
     611           0 :               state = IN_STRING;
     612           0 :               break;
     613             :             }
     614           0 :           break;
     615             : 
     616             :         case IN_OCT_ESC:
     617           0 :           if (quote_idx < 3 && strchr ("01234567", c))
     618             :             {
     619           0 :               quote_buf[quote_idx++] = c;
     620           0 :               if (quote_idx == 3)
     621             :                 {
     622           0 :                   push_data ((unsigned int)quote_buf[0] * 8 * 8
     623           0 :                              + (unsigned int)quote_buf[1] * 8
     624           0 :                              + (unsigned int)quote_buf[2]);
     625           0 :                   state = IN_STRING;
     626             :                 }
     627             :             }
     628             :           else
     629           0 :             state = IN_STRING;
     630           0 :           break;
     631             :         case IN_HEX_ESC:
     632           0 :           if (quote_idx < 2 && strchr ("0123456789abcdefABCDEF", c))
     633             :             {
     634           0 :               quote_buf[quote_idx++] = c;
     635           0 :               if (quote_idx == 2)
     636             :                 {
     637           0 :                   push_data (xtoi_1 (quote_buf[0]) * 16
     638           0 :                              + xtoi_1 (quote_buf[1]));
     639           0 :                   state = IN_STRING;
     640             :                 }
     641             :             }
     642             :           else
     643           0 :             state = IN_STRING;
     644           0 :           break;
     645             :         case CR_ESC:
     646           0 :           state = IN_STRING;
     647           0 :           break;
     648             :         case LF_ESC:
     649           0 :           state = IN_STRING;
     650           0 :           break;
     651             : 
     652             :         case IN_HEXFMT:
     653           0 :           if (hexdigit_p (c))
     654             :             {
     655           0 :               push_data (c);
     656           0 :               hexcount++;
     657             :             }
     658           0 :           else if (c == '#')
     659             :             {
     660           0 :               if ((hexcount & 1))
     661           0 :                 printerr ("odd number of hex digits");
     662           0 :               printctl ("endhex");
     663           0 :               flush_data ();
     664           0 :               state = INIT_STATE;
     665             :             }
     666           0 :           else if (!whitespace_p (c))
     667           0 :             printerr ("bad hex character");
     668           0 :           break;
     669             : 
     670             :         case IN_BASE64:
     671           0 :           if (c == '|')
     672             :             {
     673           0 :               printctl ("endbase64");
     674           0 :               flush_data ();
     675           0 :               state = INIT_STATE;
     676             :             }
     677             :           else
     678           0 :             push_data (c);
     679           0 :           break;
     680             : 
     681             :         default:
     682           0 :           logit ("invalid state %d detected", state);
     683           0 :           exit (1);
     684             :         }
     685             :     }
     686           0 :   flushdatabuffer ();
     687           0 :   if (ferror (fp))
     688             :     {
     689           0 :       logit ("error reading input: %s\n", strerror (errno));
     690           0 :       return -1;
     691             :     }
     692           0 :   return 0;
     693             : }
     694             : 
     695             : 
     696             : 
     697             : int
     698           0 : main (int argc, char **argv)
     699             : {
     700             :   int rc;
     701             : 
     702           0 :   if (argc)
     703             :     {
     704           0 :       argc--; argv++;
     705             :     }
     706           0 :   while (argc && **argv == '-' && (*argv)[1] == '-')
     707             :     {
     708           0 :       if (!(*argv)[2])
     709             :         {
     710           0 :           argc--; argv++;
     711           0 :           break;
     712             :         }
     713           0 :       else if (!strcmp (*argv, "--version"))
     714           0 :         print_version (0);
     715           0 :       else if (!strcmp (*argv, "--help"))
     716           0 :         print_version (1);
     717           0 :       else if (!strcmp (*argv, "--verbose"))
     718             :         {
     719           0 :           argc--; argv++;
     720           0 :           verbose = 1;
     721             :         }
     722           0 :       else if (!strcmp (*argv, "--decimal"))
     723             :         {
     724           0 :           argc--; argv++;
     725           0 :           decimal = 1;
     726             :         }
     727           0 :       else if (!strcmp (*argv, "--assume-hex"))
     728             :         {
     729           0 :           argc--; argv++;
     730           0 :           assume_hex = 1;
     731             :         }
     732           0 :       else if (!strcmp (*argv, "--advanced"))
     733             :         {
     734           0 :           argc--; argv++;
     735           0 :           advanced = 1;
     736             :         }
     737             :       else
     738           0 :         print_usage ();
     739             :     }
     740             : 
     741           0 :   if (!argc)
     742             :     {
     743           0 :       rc = parse_and_print (stdin);
     744             :     }
     745             :   else
     746             :     {
     747           0 :       rc = 0;
     748           0 :       for (; argc; argv++, argc--)
     749             :         {
     750           0 :           FILE *fp = fopen (*argv, "rb");
     751           0 :           if (!fp)
     752             :             {
     753           0 :               logit ("can't open `%s': %s\n", *argv, strerror (errno));
     754           0 :               rc = 1;
     755             :             }
     756             :           else
     757             :             {
     758           0 :               if (parse_and_print (fp))
     759           0 :                 rc = 1;
     760           0 :               fclose (fp);
     761             :             }
     762             :         }
     763             :     }
     764             : 
     765           0 :   return !!rc;
     766             : }

Generated by: LCOV version 1.11