LCOV - code coverage report
Current view: top level - src - c.l (source / functions) Hit Total Coverage
Test: coverage.info Lines: 174 252 69.0 %
Date: 2015-04-20 Functions: 7 14 50.0 %

          Line data    Source code
       1             : /* This file is part of GNU cflow
       2             :    Copyright (C) 1997, 2005, 2007, 2010 Sergey Poznyakoff
       3             : 
       4             :    GNU cflow is free software; you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation; either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    GNU cflow is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public
      15             :    License along with GNU cflow; if not, write to the Free Software
      16             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      17             :    MA 02110-1301 USA */
      18             : 
      19             : %top {
      20             : #include <cflow.h>
      21             : #include <ctype.h>
      22             : #include <parser.h>
      23             : }
      24             : 
      25             : %x comment
      26             : %x string
      27             : %x stringwait
      28             : %x longline
      29             : %{
      30             :      
      31             : struct obstack string_stk;
      32             : 
      33             : int line_num;
      34             : char *filename;
      35             : char *canonical_filename; 
      36             : YYSTYPE yylval;
      37             : unsigned input_file_count; /* Number of input files, processed by source() */
      38             :  
      39             : int ident();
      40             : void update_loc();
      41             : #define lex_error(msg) error_at_line(0, 0, filename, line_num, "%s", msg)
      42             : 
      43             : /* Keep the token returned at the previous call to yylex. This is used
      44             :    as a lexical tie-in to ensure that the next token after STRUCT is
      45             :    IDENTIFIER. See get_token and ident below. */
      46             : static int prev_token;
      47             : 
      48             : %}
      49             : FILENAME [^\n*?]*
      50             : ONUMBER (0[0-7]*)
      51             : HNUMBER (0[xX][0-9a-fA-F]*)
      52             : DNUMBER ([1-9][0-9]*)
      53             : DIGITS  [0-9][0-9]*
      54             : IDENT [a-zA-Z_][a-zA-Z0-9_]*
      55             : WS    [ \t\f\r]* 
      56             : %%
      57             :      /* comments */
      58           0 : "//".*\n                ++line_num;
      59        8217 : "/*"                  BEGIN(comment);
      60        8217 : <comment>[^*\n]*  ;
      61       23565 : <comment>[^*\n]*\n        ++line_num;
      62       15348 : <comment>"*"+[^*/\n]*   ;
      63        3848 : <comment>"*"+[^*/\n]*\n ++line_num;
      64       15988 : <comment>"*"+"/"      BEGIN(INITIAL); 
      65        8217 :      /* Line directives */
      66       11777 : ^{WS}#{WS}line{WS}{DIGITS}.*\n |
      67        1440 : ^{WS}#{WS}{DIGITS}.*\n   { update_loc(); }
      68        1440 :      /* skip any preproc */
      69        1601 : ^{WS}#.*\\\n             { BEGIN(longline); ++line_num; }
      70        4233 : {WS}#.*\n                ++line_num;
      71        5320 : <longline>.*\\\n         ++line_num; 
      72        1570 : <longline>.*\n           { BEGIN(INITIAL); ++line_num; }
      73        4233 :      /* keywords */
      74        1248 : auto                 /* ignored */;
      75         305 : extern               return EXTERN; 
      76        1827 : static               return STATIC;
      77         448 : typedef              return TYPEDEF;
      78        3155 : struct               {yylval.str = "struct"; return STRUCT;}
      79         304 : union                {yylval.str = "union"; return STRUCT;}
      80        1392 : enum                 {yylval.str = "enum"; return STRUCT;}
      81       11212 : \*                   { yylval.str = "*";
      82       11276 :                        return MODIFIER;
      83       11212 :                    }
      84             :      /* Operators
      85             :       *
      86             :       */
      87        7552 : "->"                 {yylval.str = "->"; return MEMBER_OF;}
      88        3008 : "."                  {yylval.str = "."; return MEMBER_OF;}
      89        7600 : "*="                 {yylval.str = "*="; return OP;}
      90        3008 : "/="                 {yylval.str = "/="; return OP;}
      91         144 : "/"                  {yylval.str = "/"; return OP;}
      92           0 : "%="                 {yylval.str = "%="; return OP;}
      93         112 : "%"                  {yylval.str = "%"; return OP;}
      94         378 : "+="                 {yylval.str = "+="; return OP;}
      95        1261 : "+"                  {yylval.str = "+"; return OP;}
      96         411 : "-="                 {yylval.str = "-="; return OP;}
      97        1777 : "-"                  {yylval.str = "-"; return OP;}
      98          49 : "<<="                {yylval.str = "<<="; return OP;}
      99         532 : ">>="                {yylval.str = ">>="; return OP;}
     100          16 : "&="                 {yylval.str = "&="; return OP;}
     101         112 : "|="                 {yylval.str = "|="; return OP;}
     102           0 : "^="                 {yylval.str = "^="; return OP;}
     103         112 : "^"                  {yylval.str = "^"; return OP;}
     104         551 : "||"                 {yylval.str = "||"; return OP;}
     105         112 : "|"                  {yylval.str = "|"; return OP;}
     106        1539 : "&&"                 {yylval.str = "&&"; return OP;}
     107        2250 : "&"                  {yylval.str = "&"; return OP;}
     108        4118 : "=="                 {yylval.str = "=="; return OP;}
     109       16308 : "="                  {yylval.str = "="; return '=';}
     110        3829 : "!="                 {yylval.str = "!="; return OP;}
     111       15356 : "!"                  {yylval.str = "!"; return OP;}
     112         958 : ">="                 {yylval.str = ">="; return OP;}
     113        1493 : ">"                  {yylval.str = ">"; return OP;}
     114         373 : "<="                 {yylval.str = "<="; return OP;}
     115        1039 : "<"                  {yylval.str = "<"; return OP;}    
     116         114 : "<<"                 {yylval.str = "<<"; return OP;}
     117         748 : ">>"                 {yylval.str = ">>"; return OP;}
     118        2421 : "++"                 {yylval.str = "++"; return OP;}
     119         340 : "--"                 {yylval.str = "--"; return OP;}
     120        2421 : '.'  |
     121         324 : '\\.' |
     122             : '\\[0-7]{2,3}' |
     123        3296 : '\\[xX][0-9a-fA-F]{1,2}'  return STRING;
     124        3296 :      /* Identifiers and constants
     125             :       *
     126             :       */
     127             : "..." |
     128      140919 : {IDENT}                 return ident();
     129      147616 : {ONUMBER}               { obstack_grow(&string_stk, yytext, yyleng+1);
     130        6697 :                           yylval.str = obstack_finish(&string_stk);
     131       13394 :                           return WORD;
     132             :                       }
     133       38790 : [+\-]?{DNUMBER}[^eE.]   { yyless(yyleng-1);
     134       38790 :                           obstack_grow(&string_stk, yytext, yyleng+1);
     135       38790 :                           yylval.str = obstack_finish(&string_stk);
     136       77580 :                           return WORD;}
     137             : {HNUMBER} |               
     138             : [+\-]?{DIGITS}?\.{DIGITS}([eE][+\-]?{DIGITS})? |
     139             : [+\-]?{DIGITS}\.([eE][+\-]?{DIGITS})? {
     140          64 :     obstack_grow(&string_stk, yytext, yyleng+1);
     141          64 :     yylval.str = obstack_finish(&string_stk);
     142          64 :     return WORD;
     143             : }
     144             : 
     145             :       /* strings 
     146             :       * State map:
     147             :       *
     148             :       * "<string>blahblahblah"<stringwait>
     149             :       * <stringwait>"<string>blahblahblah"<stringwait>
     150             :       * <stringwait>.<INITIAL>
     151             :       */
     152        5460 : \"    BEGIN(string);
     153       10920 : <string>[^\\"\n]*       ;
     154        5225 : <string>\n              { ++line_num; lex_error(_("unterminated string?")); } 
     155        5225 : <string>\\.             ;
     156         568 : <string>\\\n            ++line_num;
     157        6028 : <string>\"              BEGIN(stringwait);
     158        5460 : <stringwait>{WS}        ;
     159        5780 : <stringwait>\n          ++line_num; 
     160         320 : <stringwait>\"          BEGIN(string);
     161           0 : <stringwait>.           {
     162        5508 :      BEGIN(INITIAL);
     163       10920 :      yyless(0); /* put the symbol back */
     164        5460 :      return STRING;
     165             : }
     166       93756 : \n                      ++line_num;
     167       93756 : {WS}                    ;
     168      209788 :        /*\f                      ;*/
     169      306802 : ^\{                     return LBRACE0;
     170        3276 : ^\}                     return RBRACE0;
     171      176990 : .                       return yytext[0];
     172        3276 : %%
     173      173732 : 
     174           0 : static char *keywords[] = {
     175             :     "break",
     176             :     "case",
     177             :     "continue",
     178             :     "default",
     179             :     "do",
     180             :     "else",
     181             :     "for",
     182             :     "goto",
     183             :     "if",
     184             :     "return",
     185             :     "sizeof",
     186             :     "switch",
     187             :     "while"
     188             : };
     189             : 
     190             : static char *types[] = {
     191             :     "char",
     192             :     "double",
     193             :     "float",
     194             :     "int",
     195             :     "void",
     196             : };
     197             : 
     198             : static char *qualifiers[] = {
     199             :     "long",
     200             :     "const",
     201             :     "register",
     202             :     "restrict",
     203             :     "short",
     204             :     "signed",
     205             :     "unsigned",
     206             :     "volatile",
     207             :     "inline"
     208             : };
     209             : 
     210             : void
     211             : init_tokens()
     212          21 : {
     213             :      int i;
     214             :      Symbol *sp;
     215             :     
     216             :      for (i = 0; i < NUMITEMS(keywords); i++) {
     217         294 :           sp = install(keywords[i], INSTALL_OVERWRITE);
     218         273 :           sp->type = SymToken;
     219         273 :           sp->token_type = WORD;
     220         273 :      }
     221             :      
     222             :      for (i = 0; i < NUMITEMS(types); i++) {
     223         126 :           sp = install(types[i], INSTALL_OVERWRITE);
     224         105 :           sp->type = SymToken;
     225         105 :           sp->token_type = TYPE;
     226         105 :           sp->source = NULL;
     227         105 :           sp->def_line = -1;
     228         105 :           sp->ref_line = NULL;
     229         105 :      }  
     230             : 
     231             :      for (i = 0; i < NUMITEMS(qualifiers); i++) {
     232         210 :           sp = install(qualifiers[i], INSTALL_OVERWRITE);
     233         189 :           sp->type = SymToken;
     234         189 :           sp->token_type = QUALIFIER;
     235         189 :           sp->source = NULL;
     236         189 :           sp->def_line = -1;
     237         189 :           sp->ref_line = NULL;
     238         189 :      }  
     239             :      sp = install("...", INSTALL_OVERWRITE);
     240          21 :      sp->type = SymToken;
     241          21 :      sp->token_type = IDENTIFIER;
     242          21 :      sp->source = NULL;
     243          21 :      sp->def_line = -1;
     244          21 :      sp->ref_line = NULL;
     245          21 : }       
     246          21 : 
     247             : void
     248             : init_lex(int debug_level)
     249          21 : {
     250             :      yy_flex_debug = debug_level;
     251          21 :      obstack_init(&string_stk);
     252          21 :      init_tokens();
     253          21 : }
     254          21 : 
     255             : int
     256             : ident()
     257      140919 : {
     258             :      /* Do not attempt any symbol table lookup if the previous token was
     259             :         STRUCT.  This helps properly parse constructs like:
     260             : 
     261             :           typedef struct foo foo;
     262             :           struct foo {
     263             :             int dummy;
     264             :           };
     265             :      */
     266             :      if (prev_token != STRUCT) {
     267      140919 :           Symbol *sp = lookup(yytext);
     268      139559 :           if (sp && sp->type == SymToken) {
     269      139559 :                yylval.str = sp->name;
     270       36938 :                return sp->token_type;
     271       36938 :           }
     272             :      }
     273             :      obstack_grow(&string_stk, yytext, yyleng);
     274      103981 :      obstack_1grow(&string_stk, 0);
     275      103981 :      yylval.str = obstack_finish(&string_stk);
     276      103981 :      return IDENTIFIER;
     277      103981 : }
     278             : 
     279             : 
     280             : 
     281             : char *pp_bin;
     282             : char *pp_opts;
     283             : static struct obstack *opt_stack;
     284             : 
     285             : void
     286             : set_preprocessor(const char *arg)
     287           0 : {
     288             :      pp_bin = arg ? xstrdup(arg) : NULL;
     289           0 : }
     290           0 : 
     291             : void
     292             : pp_option(const char *arg)
     293           0 : {
     294             :      if (!opt_stack) {
     295           0 :           if (!pp_bin)
     296           0 :                pp_bin = CFLOW_PREPROC;
     297           0 :           opt_stack = xmalloc(sizeof *opt_stack);
     298           0 :           obstack_init(opt_stack);
     299           0 :      }
     300             :      obstack_1grow(opt_stack, ' ');
     301           0 :      obstack_grow(opt_stack, arg, strlen (arg));
     302           0 : }
     303           0 : 
     304             : void
     305             : pp_finalize()
     306           0 : {
     307             :      char *s = obstack_finish(opt_stack);
     308           0 :      if (!pp_opts)
     309           0 :           pp_opts = xstrdup(s);
     310           0 :      else {
     311             :           pp_opts = xrealloc(pp_opts, strlen(pp_opts) + strlen(s) + 1);
     312           0 :           strcat(pp_opts, s);
     313           0 :      }
     314             :      obstack_free(opt_stack, s);
     315           0 :      free(opt_stack);
     316           0 :      opt_stack = NULL;
     317           0 : }
     318           0 : 
     319             : FILE *
     320             : pp_open(const char *name)
     321           0 : {
     322             :      FILE *fp;
     323             :      char *s;
     324             :      size_t size;
     325             :      
     326             :      if (opt_stack)
     327           0 :           pp_finalize();
     328           0 :      size = strlen(pp_bin) + 1 + strlen(name) + 1;
     329           0 :      if (pp_opts)
     330           0 :           size += strlen(pp_opts);
     331           0 :      s = xmalloc(size);
     332           0 :      strcpy(s, pp_bin);
     333           0 :      if (pp_opts)
     334           0 :           strcat(s, pp_opts);
     335           0 :      strcat(s, " ");
     336           0 :      strcat(s, name);
     337           0 :      if (debug)
     338           0 :           printf(_("Command line: %s\n"), s);
     339           0 :      fp = popen(s, "r");
     340           0 :      if (!fp)
     341           0 :           error(0, errno, _("cannot execute `%s'"), s);
     342           0 :      free(s);
     343           0 :      return fp;
     344           0 : }
     345             : 
     346             : void
     347             : pp_close(FILE *fp)
     348           0 : {
     349             :      pclose(fp);
     350           0 : }
     351           0 : 
     352             : 
     353             : 
     354             : int
     355             : yywrap()
     356         229 : {
     357             :      if (!yyin)
     358         229 :           return 1;
     359           0 :      if (preprocess_option)
     360         229 :           pp_close(yyin);
     361           0 :      else
     362             :           fclose(yyin);
     363         229 :      yyin = NULL;
     364         229 : #ifdef FLEX_SCANNER
     365             :      yy_delete_buffer(YY_CURRENT_BUFFER);
     366         229 : #endif
     367             :      delete_statics();
     368         229 :      return 1;
     369         229 : }
     370             : 
     371             : static int hit_eof;
     372             : 
     373             : int
     374             : get_token()
     375      430793 : {
     376             :      int tok;
     377             : 
     378             :      if (hit_eof)
     379      430793 :           tok = 0;
     380          10 :      else {
     381             :           tok = yylex();
     382      430783 :           prev_token = tok;
     383      430783 :           if (!tok)
     384      430783 :                hit_eof = 1;
     385         229 :      }
     386             :      return tok;
     387      430793 : }
     388             : 
     389             : int
     390             : source(char *name)
     391         229 : {
     392             :      FILE *fp;
     393             : 
     394             :      fp = fopen(name, "r");
     395         229 :      if (!fp) {
     396         229 :           error(0, errno, _("cannot open `%s'"), name);
     397           0 :           return 1;
     398           0 :      }
     399             :      if (preprocess_option) {
     400         229 :           fclose(fp);
     401           0 :           fp = pp_open(name);
     402           0 :           if (!fp)
     403           0 :                return 1;
     404           0 :      }
     405             :      obstack_grow(&string_stk, name, strlen(name)+1);
     406         229 :      filename = obstack_finish(&string_stk);
     407         229 :      canonical_filename = filename;
     408         229 :      line_num = 1;
     409         229 :      input_file_count++;
     410         229 :      hit_eof = 0;
     411         229 : 
     412             :      yyrestart(fp);
     413         229 :      return 0;
     414         229 : }
     415             : 
     416             : static int
     417             : getnum(unsigned  base, int  count)
     418           0 : {
     419             :      int  c, n;
     420             :      unsigned i;
     421             : 
     422             :      for (n = 0; count; count--) {
     423           0 :           if (isdigit(c = input()))
     424           0 :                i = c - '0';
     425           0 :           else
     426             :                i = toupper(c) - 'A' + 10;
     427           0 :           if (i > base) {
     428           0 :                unput(c);
     429           0 :                break;
     430           0 :           }
     431             :           n = n * base + i;
     432           0 :      }
     433             :      return n;
     434           0 : }
     435             : 
     436             : int
     437             : backslash()
     438           0 : {                                  
     439             :      int c;
     440             :      
     441             :      switch (c = input()) {                        
     442           0 :      case 'a':   return '\a';                  
     443           0 :      case 'b':   return '\b';                  
     444           0 :      case 'f':   return '\f';                  
     445           0 :      case 'n':   return '\n';                  
     446           0 :      case 'r':   return '\r';                  
     447           0 :      case 't':   return '\t';                  
     448           0 :      case 'x':   return getnum(16,2);          
     449           0 :      case '0':   return getnum(8,3);           
     450           0 :      }                                             
     451             :      return c;                                         
     452           0 : }                                                     
     453             : 
     454             : void
     455             : update_loc()
     456        1440 : {
     457             :      char *p;
     458             :      
     459             :      for (p = strchr(yytext, '#')+1; *p && isspace(*p); p++)
     460        1440 :           ;
     461             :      if (p[0] == 'l') /* line */
     462        1440 :           p += 4;
     463        1440 : 
     464             :      line_num = strtoul(p, &p, 10);
     465        1440 :      for ( ; *p && isspace(*p); p++)
     466        1440 :           ;
     467             :      if (p[0] == '"') {
     468        1440 :           int n;
     469             :           
     470             :           for (p++, n = 0; p[n] && p[n] != '"'; n++)
     471        1440 :                ;
     472             :           obstack_grow(&string_stk, p, n);
     473        1440 :           obstack_1grow(&string_stk, 0);
     474        1440 :           filename = obstack_finish(&string_stk);
     475        1440 :      }
     476             :      if (debug > 1)
     477        1440 :           printf(_("New location: %s:%d\n"), filename, line_num);
     478        1350 : }
     479        1440 :           

Generated by: LCOV version 1.10