LCOV - code coverage report
Current view: top level - workdir/unxlngi6.pro/CustomTarget/ucpp/source - cpp.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 555 1255 44.2 %
Date: 2012-08-25 Functions: 33 47 70.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 359 1239 29.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * C and T preprocessor, and integrated lexer
       3                 :            :  * (c) Thomas Pornin 1999 - 2002
       4                 :            :  *
       5                 :            :  * Redistribution and use in source and binary forms, with or without
       6                 :            :  * modification, are permitted provided that the following conditions
       7                 :            :  * are met:
       8                 :            :  * 1. Redistributions of source code must retain the above copyright
       9                 :            :  *    notice, this list of conditions and the following disclaimer.
      10                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      11                 :            :  *    notice, this list of conditions and the following disclaimer in the
      12                 :            :  *    documentation and/or other materials provided with the distribution.
      13                 :            :  * 4. The name of the authors may not be used to endorse or promote
      14                 :            :  *    products derived from this software without specific prior written
      15                 :            :  *    permission.
      16                 :            :  *
      17                 :            :  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
      18                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      19                 :            :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20                 :            :  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
      21                 :            :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      22                 :            :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
      23                 :            :  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
      24                 :            :  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      25                 :            :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
      26                 :            :  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
      27                 :            :  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28                 :            :  *
      29                 :            :  */
      30                 :            : 
      31                 :            : #define VERS_MAJ        1
      32                 :            : #define VERS_MIN        3
      33                 :            : /* uncomment the following if you cannot set it with a compiler flag */
      34                 :            : /* #define STAND_ALONE */
      35                 :            : 
      36                 :            : #include "tune.h"
      37                 :            : #include <stdio.h>
      38                 :            : #include <string.h>
      39                 :            : #include <stdarg.h>
      40                 :            : #include <setjmp.h>
      41                 :            : #include <stddef.h>
      42                 :            : #include <limits.h>
      43                 :            : #include <time.h>
      44                 :            : #include "ucppi.h"
      45                 :            : #include "mem.h"
      46                 :            : #include "nhash.h"
      47                 :            : #ifdef UCPP_MMAP
      48                 :            : #include <unistd.h>
      49                 :            : #include <sys/types.h>
      50                 :            : #include <sys/mman.h>
      51                 :            : #include <fcntl.h>
      52                 :            : #endif
      53                 :            : 
      54                 :            : /*
      55                 :            :  * The standard path where includes are looked for.
      56                 :            :  */
      57                 :            : #ifdef STAND_ALONE
      58                 :            : static char *include_path_std[] = { STD_INCLUDE_PATH, 0 };
      59                 :            : #endif
      60                 :            : static char **include_path;
      61                 :            : static size_t include_path_nb = 0;
      62                 :            : 
      63                 :            : int no_special_macros = 0;
      64                 :            : int emit_dependencies = 0, emit_defines = 0, emit_assertions = 0;
      65                 :            : FILE *emit_output;
      66                 :            : 
      67                 :            : #ifdef STAND_ALONE
      68                 :            : static char *system_macros_def[] = { STD_MACROS, 0 };
      69                 :            : static char *system_assertions_def[] = { STD_ASSERT, 0 };
      70                 :            : #endif
      71                 :            : 
      72                 :            : char *current_filename = 0, *current_long_filename = 0;
      73                 :            : static int current_incdir = -1;
      74                 :            : 
      75                 :            : #ifndef NO_UCPP_ERROR_FUNCTIONS
      76                 :            : /*
      77                 :            :  * "ouch" is the name for an internal ucpp error. If AUDIT is not defined,
      78                 :            :  * no code calling this function will be generated; a "ouch" may still be
      79                 :            :  * emitted by getmem() (in mem.c) if MEM_CHECK is defined, but this "ouch"
      80                 :            :  * does not use this function.
      81                 :            :  */
      82                 :          0 : void ucpp_ouch(char *fmt, ...)
      83                 :            : {
      84                 :            :         va_list ap;
      85                 :            : 
      86                 :          0 :         va_start(ap, fmt);
      87                 :          0 :         fprintf(stderr, "%s: ouch, ", current_filename);
      88                 :          0 :         vfprintf(stderr, fmt, ap);
      89                 :          0 :         fprintf(stderr, "\n");
      90                 :          0 :         va_end(ap);
      91                 :          0 :         die();
      92                 :          0 : }
      93                 :            : 
      94                 :            : /*
      95                 :            :  * report an error, with current_filename, line, and printf-like syntax
      96                 :            :  */
      97                 :          0 : void ucpp_error(long line, char *fmt, ...)
      98                 :            : {
      99                 :            :         va_list ap;
     100                 :            : 
     101                 :          0 :         va_start(ap, fmt);
     102         [ #  # ]:          0 :         if (line > 0)
     103                 :          0 :                 fprintf(stderr, "%s: line %ld: ", current_filename, line);
     104         [ #  # ]:          0 :         else if (line == 0) fprintf(stderr, "%s: ", current_filename);
     105                 :          0 :         vfprintf(stderr, fmt, ap);
     106                 :          0 :         fprintf(stderr, "\n");
     107         [ #  # ]:          0 :         if (line >= 0) {
     108                 :          0 :                 struct stack_context *sc = report_context();
     109                 :            :                 size_t i;
     110                 :            : 
     111         [ #  # ]:          0 :                 for (i = 0; sc[i].line >= 0; i ++)
     112         [ #  # ]:          0 :                         fprintf(stderr, "\tincluded from %s:%ld\n",
     113                 :          0 :                                 sc[i].long_name ? sc[i].long_name : sc[i].name,
     114                 :          0 :                                 sc[i].line);
     115                 :          0 :                 freemem(sc);
     116                 :            :         }
     117                 :          0 :         va_end(ap);
     118                 :          0 : }
     119                 :            : 
     120                 :            : /*
     121                 :            :  * like error(), with the mention "warning"
     122                 :            :  */
     123                 :          0 : void ucpp_warning(long line, char *fmt, ...)
     124                 :            : {
     125                 :            :         va_list ap;
     126                 :            : 
     127                 :          0 :         va_start(ap, fmt);
     128         [ #  # ]:          0 :         if (line > 0)
     129                 :          0 :                 fprintf(stderr, "%s: warning: line %ld: ",
     130                 :            :                         current_filename, line);
     131         [ #  # ]:          0 :         else if (line == 0)
     132                 :          0 :                 fprintf(stderr, "%s: warning: ", current_filename);
     133                 :          0 :         else fprintf(stderr, "warning: ");
     134                 :          0 :         vfprintf(stderr, fmt, ap);
     135                 :          0 :         fprintf(stderr, "\n");
     136         [ #  # ]:          0 :         if (line >= 0) {
     137                 :          0 :                 struct stack_context *sc = report_context();
     138                 :            :                 size_t i;
     139                 :            : 
     140         [ #  # ]:          0 :                 for (i = 0; sc[i].line >= 0; i ++)
     141         [ #  # ]:          0 :                         fprintf(stderr, "\tincluded from %s:%ld\n",
     142                 :          0 :                                 sc[i].long_name ? sc[i].long_name : sc[i].name,
     143                 :          0 :                                 sc[i].line);
     144                 :          0 :                 freemem(sc);
     145                 :            :         }
     146                 :          0 :         va_end(ap);
     147                 :          0 : }
     148                 :            : #endif  /* NO_UCPP_ERROR_FUNCTIONS */
     149                 :            : 
     150                 :            : /*
     151                 :            :  * Some memory allocations are manually garbage-collected; essentially,
     152                 :            :  * strings duplicated in the process of macro replacement. Each such
     153                 :            :  * string is referenced in the garbage_fifo, which is cleared when all
     154                 :            :  * nested macros have been resolved.
     155                 :            :  */
     156                 :            : 
     157                 :            : struct garbage_fifo {
     158                 :            :         char **garbage;
     159                 :            :         size_t ngarb, memgarb;
     160                 :            : };
     161                 :            : 
     162                 :            : /*
     163                 :            :  * throw_away() marks a string to be collected later
     164                 :            :  */
     165                 :          2 : void throw_away(struct garbage_fifo *gf, char *n)
     166                 :            : {
     167         [ -  + ]:          2 :         wan(gf->garbage, gf->ngarb, n, gf->memgarb);
     168                 :          2 : }
     169                 :            : 
     170                 :            : /*
     171                 :            :  * free marked strings
     172                 :            :  */
     173                 :      23912 : void garbage_collect(struct garbage_fifo *gf)
     174                 :            : {
     175                 :            :         size_t i;
     176                 :            : 
     177         [ +  + ]:      23914 :         for (i = 0; i < gf->ngarb; i ++) freemem(gf->garbage[i]);
     178                 :      23912 :         gf->ngarb = 0;
     179                 :      23912 : }
     180                 :            : 
     181                 :      23912 : static void init_garbage_fifo(struct garbage_fifo *gf)
     182                 :            : {
     183                 :      23912 :         gf->garbage = getmem((gf->memgarb = GARBAGE_LIST_MEMG)
     184                 :            :                 * sizeof(char *));
     185                 :      23912 :         gf->ngarb = 0;
     186                 :      23912 : }
     187                 :            : 
     188                 :      23912 : static void free_garbage_fifo(struct garbage_fifo *gf)
     189                 :            : {
     190                 :      23912 :         garbage_collect(gf);
     191                 :      23912 :         freemem(gf->garbage);
     192                 :      23912 :         freemem(gf);
     193                 :      23912 : }
     194                 :            : 
     195                 :            : /*
     196                 :            :  * order is important: it must match the token-constants declared as an
     197                 :            :  * enum in the header file.
     198                 :            :  */
     199                 :            : char *operators_name[] = {
     200                 :            :         " ", "\n", " ",
     201                 :            :         "0000", "name", "bunch", "pragma", "context",
     202                 :            :         "\"dummy string\"", "'dummy char'",
     203                 :            :         "/", "/=", "-", "--", "-=", "->", "+", "++", "+=", "<", "<=", "<<",
     204                 :            :         "<<=", ">", ">=", ">>", ">>=", "=", "==",
     205                 :            : #ifdef CAST_OP
     206                 :            :         "=>",
     207                 :            : #endif
     208                 :            :         "~", "!=", "&", "&&", "&=", "|", "||", "|=", "%", "%=", "*", "*=",
     209                 :            :         "^", "^=", "!",
     210                 :            :         "{", "}", "[", "]", "(", ")", ",", "?", ";",
     211                 :            :         ":", ".", "...", "#", "##", " ", "ouch", "<:", ":>", "<%", "%>",
     212                 :            :         "%:", "%:%:"
     213                 :            : };
     214                 :            : 
     215                 :            : /* the ascii representation of a token */
     216                 :            : #ifdef SEMPER_FIDELIS
     217                 :            : #define tname(x)        (ttWHI((x).type) ? " " : S_TOKEN((x).type) \
     218                 :            :                         ? (x).name : operators_name[(x).type])
     219                 :            : #else
     220                 :            : #define tname(x)        (S_TOKEN((x).type) ? (x).name \
     221                 :            :                         : operators_name[(x).type])
     222                 :            : #endif
     223                 :            : 
     224                 :          0 : char *token_name(struct token *t)
     225                 :            : {
     226 [ #  # ][ #  # ]:          0 :         return tname(*t);
     227                 :            : }
     228                 :            : 
     229                 :            : /*
     230                 :            :  * To speed up deeply nested and repeated inclusions, we:
     231                 :            :  * -- use a hash table to remember where we found each file
     232                 :            :  * -- remember when the file is protected by a #ifndef/#define/#endif
     233                 :            :  *    construction; we can then avoid including several times a file
     234                 :            :  *    when this is not necessary.
     235                 :            :  * -- remember in which directory, in the include path, the file was found.
     236                 :            :  */
     237                 :            : struct found_file {
     238                 :            :         hash_item_header head;    /* first field */
     239                 :            :         char *name;
     240                 :            :         char *protect;
     241                 :            : };
     242                 :            : 
     243                 :            : /*
     244                 :            :  * For files from system include path.
     245                 :            :  */
     246                 :            : struct found_file_sys {
     247                 :            :         hash_item_header head;    /* first field */
     248                 :            :         struct found_file *rff;
     249                 :            :         int incdir;
     250                 :            : };
     251                 :            : 
     252                 :            : static HTT found_files, found_files_sys;
     253                 :            : static int found_files_init_done = 0, found_files_sys_init_done = 0;
     254                 :            : 
     255                 :      68966 : static struct found_file *new_found_file(void)
     256                 :            : {
     257                 :      68966 :         struct found_file *ff = getmem(sizeof(struct found_file));
     258                 :            : 
     259                 :      68966 :         ff->name = 0;
     260                 :      68966 :         ff->protect = 0;
     261                 :      68966 :         return ff;
     262                 :            : }
     263                 :            : 
     264                 :      68966 : static void del_found_file(void *m)
     265                 :            : {
     266                 :      68966 :         struct found_file *ff = (struct found_file *)m;
     267                 :            : 
     268         [ +  - ]:      68966 :         if (ff->name) freemem(ff->name);
     269         [ +  + ]:      68966 :         if (ff->protect) freemem(ff->protect);
     270                 :      68966 :         freemem(ff);
     271                 :      68966 : }
     272                 :            : 
     273                 :      62988 : static struct found_file_sys *new_found_file_sys(void)
     274                 :            : {
     275                 :      62988 :         struct found_file_sys *ffs = getmem(sizeof(struct found_file_sys));
     276                 :            : 
     277                 :      62988 :         ffs->rff = 0;
     278                 :      62988 :         ffs->incdir = -1;
     279                 :      62988 :         return ffs;
     280                 :            : }
     281                 :            : 
     282                 :      62988 : static void del_found_file_sys(void *m)
     283                 :            : {
     284                 :      62988 :         struct found_file_sys *ffs = (struct found_file_sys *)m;
     285                 :            : 
     286                 :      62988 :         freemem(ffs);
     287                 :      62988 : }
     288                 :            : 
     289                 :            : /*
     290                 :            :  * To keep up with the #ifndef/#define/#endif protection mechanism
     291                 :            :  * detection.
     292                 :            :  */
     293                 :            : struct protect protect_detect;
     294                 :            : static struct protect *protect_detect_stack = 0;
     295                 :            : 
     296                 :       5978 : void set_init_filename(char *x, int real_file)
     297                 :            : {
     298         [ -  + ]:       5978 :         if (current_filename) freemem(current_filename);
     299                 :       5978 :         current_filename = sdup(x);
     300                 :       5978 :         current_long_filename = 0;
     301                 :       5978 :         current_incdir = -1;
     302         [ +  - ]:       5978 :         if (real_file) {
     303                 :       5978 :                 protect_detect.macro = 0;
     304                 :       5978 :                 protect_detect.state = 1;
     305                 :       5978 :                 protect_detect.ff = new_found_file();
     306                 :       5978 :                 protect_detect.ff->name = sdup(x);
     307                 :       5978 :                 HTT_put(&found_files, protect_detect.ff, x);
     308                 :            :         } else {
     309                 :          0 :                 protect_detect.state = 0;
     310                 :            :         }
     311                 :       5978 : }
     312                 :            : 
     313                 :       5978 : static void init_found_files(void)
     314                 :            : {
     315         [ -  + ]:       5978 :         if (found_files_init_done) HTT_kill(&found_files);
     316                 :       5978 :         HTT_init(&found_files, del_found_file);
     317                 :       5978 :         found_files_init_done = 1;
     318         [ -  + ]:       5978 :         if (found_files_sys_init_done) HTT_kill(&found_files_sys);
     319                 :       5978 :         HTT_init(&found_files_sys, del_found_file_sys);
     320                 :       5978 :         found_files_sys_init_done = 1;
     321                 :       5978 : }
     322                 :            : 
     323                 :            : /*
     324                 :            :  * Set the lexer state at the beginning of a file.
     325                 :            :  */
     326                 :     136498 : static void reinit_lexer_state(struct lexer_state *ls, int wb)
     327                 :            : {
     328                 :            : #ifndef NO_UCPP_BUF
     329                 :            :         ls->input_buf = wb ? getmem(INPUT_BUF_MEMG) : 0;
     330                 :            : #ifdef UCPP_MMAP
     331                 :            :         ls->from_mmap = 0;
     332                 :            : #endif
     333                 :            : #endif
     334                 :     136498 :         ls->input = 0;
     335                 :     136498 :         ls->ebuf = ls->pbuf = 0;
     336                 :     136498 :         ls->nlka = 0;
     337                 :     136498 :         ls->macfile = 0;
     338                 :     136498 :         ls->discard = 1;
     339                 :     136498 :         ls->last = 0;                /* we suppose '\n' is not 0 */
     340                 :     136498 :         ls->line = 1;
     341                 :     136498 :         ls->ltwnl = 1;
     342                 :     136498 :         ls->oline = 1;
     343                 :     136498 :         ls->pending_token = 0;
     344                 :     136498 :         ls->cli = 0;
     345                 :     136498 :         ls->copy_line[COPY_LINE_LENGTH - 1] = 0;
     346                 :     136498 :         ls->ifnest = 0;
     347                 :     136498 :         ls->condf[0] = ls->condf[1] = 0;
     348                 :     136498 : }
     349                 :            : 
     350                 :            : /*
     351                 :            :  * Initialize the struct lexer_state, with optional input and output buffers.
     352                 :            :  */
     353                 :      23912 : void init_buf_lexer_state(struct lexer_state *ls, int wb)
     354                 :            : {
     355                 :      23912 :         reinit_lexer_state(ls, wb);
     356                 :            : #ifndef NO_UCPP_BUF
     357                 :            :         ls->output_buf = wb ? getmem(OUTPUT_BUF_MEMG) : 0;
     358                 :            : #endif
     359                 :      23912 :         ls->sbuf = 0;
     360                 :      23912 :         ls->output_fifo = 0;
     361                 :            : 
     362                 :      23912 :         ls->ctok = getmem(sizeof(struct token));
     363                 :      23912 :         ls->ctok->name = getmem(ls->tknl = TOKEN_NAME_MEMG);
     364                 :      23912 :         ls->pending_token = 0;
     365                 :            : 
     366                 :      23912 :         ls->flags = 0;
     367                 :      23912 :         ls->count_trigraphs = 0;
     368                 :      23912 :         ls->gf = getmem(sizeof(struct garbage_fifo));
     369                 :      23912 :         init_garbage_fifo(ls->gf);
     370                 :      23912 :         ls->condcomp = 1;
     371                 :      23912 :         ls->condnest = 0;
     372                 :            : #ifdef INMACRO_FLAG
     373                 :            :         ls->inmacro = 0;
     374                 :            :         ls->macro_count = 0;
     375                 :            : #endif
     376                 :      23912 : }
     377                 :            : 
     378                 :            : /*
     379                 :            :  * Initialize the (complex) struct lexer_state.
     380                 :            :  */
     381                 :      11956 : void init_lexer_state(struct lexer_state *ls)
     382                 :            : {
     383                 :      11956 :         init_buf_lexer_state(ls, 1);
     384                 :      11956 :         ls->input = 0;
     385                 :      11956 : }
     386                 :            : 
     387                 :            : /*
     388                 :            :  * Restore what is needed from a lexer_state. This is used for #include.
     389                 :            :  */
     390                 :     112586 : static void restore_lexer_state(struct lexer_state *ls,
     391                 :            :         struct lexer_state *lsbak)
     392                 :            : {
     393                 :            : #ifndef NO_UCPP_BUF
     394                 :            :         freemem(ls->input_buf);
     395                 :            :         ls->input_buf = lsbak->input_buf;
     396                 :            : #ifdef UCPP_MMAP
     397                 :            :         ls->from_mmap = lsbak->from_mmap;
     398                 :            :         ls->input_buf_sav = lsbak->input_buf_sav;
     399                 :            : #endif
     400                 :            : #endif
     401                 :     112586 :         ls->input = lsbak->input;
     402                 :     112586 :         ls->ebuf = lsbak->ebuf;
     403                 :     112586 :         ls->pbuf = lsbak->pbuf;
     404                 :     112586 :         ls->nlka = lsbak->nlka;
     405                 :     112586 :         ls->discard = lsbak->discard;
     406                 :     112586 :         ls->line = lsbak->line;
     407                 :     112586 :         ls->oline = lsbak->oline;
     408                 :     112586 :         ls->ifnest = lsbak->ifnest;
     409                 :     112586 :         ls->condf[0] = lsbak->condf[0];
     410                 :     112586 :         ls->condf[1] = lsbak->condf[1];
     411                 :     112586 : }
     412                 :            : 
     413                 :            : /*
     414                 :            :  * close input file operations on a struct lexer_state
     415                 :            :  */
     416                 :     199486 : static void close_input(struct lexer_state *ls)
     417                 :            : {
     418                 :            : #ifdef UCPP_MMAP
     419                 :            :         if (ls->from_mmap) {
     420                 :            :                 munmap((void *)ls->input_buf, ls->ebuf);
     421                 :            :                 ls->from_mmap = 0;
     422                 :            :                 ls->input_buf = ls->input_buf_sav;
     423                 :            :         }
     424                 :            : #endif
     425         [ +  + ]:     199486 :         if (ls->input) {
     426                 :      68966 :                 fclose(ls->input);
     427                 :      68966 :                 ls->input = 0;
     428                 :            :         }
     429                 :     199486 : }
     430                 :            : 
     431                 :            : /*
     432                 :            :  * file_context (and the two functions push_ and pop_) are used to save
     433                 :            :  * all that is needed when including a file.
     434                 :            :  */
     435                 :            : static struct file_context {
     436                 :            :         struct lexer_state ls;
     437                 :            :         char *name, *long_name;
     438                 :            :         int incdir;
     439                 :            : } *ls_stack;
     440                 :            : static size_t ls_depth = 0;
     441                 :            : 
     442                 :     112586 : static void push_file_context(struct lexer_state *ls)
     443                 :            : {
     444                 :            :         struct file_context fc;
     445                 :            : 
     446                 :     112586 :         fc.name = current_filename;
     447                 :     112586 :         fc.long_name = current_long_filename;
     448                 :     112586 :         fc.incdir = current_incdir;
     449                 :     112586 :         mmv(&(fc.ls), ls, sizeof(struct lexer_state));
     450 [ +  + ][ +  + ]:     112586 :         aol(ls_stack, ls_depth, fc, LS_STACK_MEMG);
     451                 :     112586 :         ls_depth --;
     452 [ +  + ][ +  + ]:     112586 :         aol(protect_detect_stack, ls_depth, protect_detect, LS_STACK_MEMG);
     453                 :     112586 :         protect_detect.macro = 0;
     454                 :     112586 : }
     455                 :            : 
     456                 :     112586 : static void pop_file_context(struct lexer_state *ls)
     457                 :            : {
     458                 :            : #ifdef AUDIT
     459                 :            :         if (ls_depth <= 0) ouch("prepare to meet thy creator");
     460                 :            : #endif
     461                 :     112586 :         close_input(ls);
     462                 :     112586 :         restore_lexer_state(ls, &(ls_stack[-- ls_depth].ls));
     463         [ -  + ]:     112586 :         if (protect_detect.macro) freemem(protect_detect.macro);
     464                 :     112586 :         protect_detect = protect_detect_stack[ls_depth];
     465         [ +  + ]:     112586 :         if (current_filename) freemem(current_filename);
     466                 :     112586 :         current_filename = ls_stack[ls_depth].name;
     467                 :     112586 :         current_long_filename = ls_stack[ls_depth].long_name;
     468                 :     112586 :         current_incdir = ls_stack[ls_depth].incdir;
     469         [ +  + ]:     112586 :         if (ls_depth == 0) {
     470                 :      10893 :                 freemem(ls_stack);
     471                 :      10893 :                 freemem(protect_detect_stack);
     472                 :            :         }
     473                 :     112586 : }
     474                 :            : 
     475                 :            : /*
     476                 :            :  * report_context() returns the list of successive includers of the
     477                 :            :  * current file, ending with a dummy entry with a negative line number.
     478                 :            :  * The caller is responsible for freeing the returned pointer.
     479                 :            :  */
     480                 :          0 : struct stack_context *report_context(void)
     481                 :            : {
     482                 :            :         struct stack_context *sc;
     483                 :            :         size_t i;
     484                 :            : 
     485                 :          0 :         sc = getmem((ls_depth + 1) * sizeof(struct stack_context));
     486         [ #  # ]:          0 :         for (i = 0; i < ls_depth; i ++) {
     487                 :          0 :                 sc[i].name = ls_stack[ls_depth - i - 1].name;
     488                 :          0 :                 sc[i].long_name = ls_stack[ls_depth - i - 1].long_name;
     489                 :          0 :                 sc[i].line = ls_stack[ls_depth - i - 1].ls.line - 1;
     490                 :            :         }
     491                 :          0 :         sc[ls_depth].line = -1;
     492                 :          0 :         return sc;
     493                 :            : }
     494                 :            : 
     495                 :            : /*
     496                 :            :  * init_lexer_mode() is used to end initialization of a struct lexer_state
     497                 :            :  * if it must be used for a lexer
     498                 :            :  */
     499                 :          0 : void init_lexer_mode(struct lexer_state *ls)
     500                 :            : {
     501                 :          0 :         ls->flags = DEFAULT_LEXER_FLAGS;
     502                 :          0 :         ls->output_fifo = getmem(sizeof(struct token_fifo));
     503                 :          0 :         ls->output_fifo->art = ls->output_fifo->nt = 0;
     504                 :          0 :         ls->toplevel_of = ls->output_fifo;
     505                 :          0 :         ls->save_ctok = ls->ctok;
     506                 :          0 : }
     507                 :            : 
     508                 :            : /*
     509                 :            :  * release memory used by a struct lexer_state; this implies closing
     510                 :            :  * any input stream held by this structure.
     511                 :            :  */
     512                 :      23912 : void free_lexer_state(struct lexer_state *ls)
     513                 :            : {
     514                 :      23912 :         close_input(ls);
     515                 :            : #ifndef NO_UCPP_BUF
     516                 :            :         if (ls->input_buf) {
     517                 :            :                 freemem(ls->input_buf);
     518                 :            :                 ls->input_buf = 0;
     519                 :            :         }
     520                 :            :         if (ls->output_buf) {
     521                 :            :                 freemem(ls->output_buf);
     522                 :            :                 ls->output_buf = 0;
     523                 :            :         }
     524                 :            : #endif
     525 [ -  + ][ #  # ]:      23912 :         if (ls->ctok && (!ls->output_fifo || ls->output_fifo->nt == 0)) {
                 [ +  - ]
     526                 :      23912 :                 freemem(ls->ctok->name);
     527                 :      23912 :                 freemem(ls->ctok);
     528                 :      23912 :                 ls->ctok = 0;
     529                 :            :         }
     530         [ +  - ]:      23912 :         if (ls->gf) {
     531                 :      23912 :                 free_garbage_fifo(ls->gf);
     532                 :      23912 :                 ls->gf = 0;
     533                 :            :         }
     534         [ -  + ]:      23912 :         if (ls->output_fifo) {
     535                 :          0 :                 freemem(ls->output_fifo);
     536                 :          0 :                 ls->output_fifo = 0;
     537                 :            :         }
     538                 :      23912 : }
     539                 :            : 
     540                 :            : /*
     541                 :            :  * Print line information.
     542                 :            :  */
     543                 :     131954 : static void print_line_info(struct lexer_state *ls, unsigned long flags)
     544                 :            : {
     545                 :     263908 :         char *fn = current_long_filename ?
     546         [ +  + ]:     131954 :                 current_long_filename : current_filename;
     547                 :            :         char *b, *d;
     548                 :            : 
     549                 :     131954 :         b = getmem(50 + strlen(fn));
     550         [ -  + ]:     131954 :         if (flags & GCC_LINE_NUM) {
     551                 :          0 :                 sprintf(b, "# %ld \"%s\"\n", ls->line, fn);
     552                 :            :         } else {
     553                 :     131954 :                 sprintf(b, "#line %ld \"%s\"\n", ls->line, fn);
     554                 :            :         }
     555         [ +  + ]:   11170064 :         for (d = b; *d; d ++) put_char(ls, (unsigned char)(*d));
     556                 :     131954 :         freemem(b);
     557                 :     131954 : }
     558                 :            : 
     559                 :            : /*
     560                 :            :  * Enter a file; this implies the possible emission of a #line directive.
     561                 :            :  * The flags used are passed as second parameter instead of being
     562                 :            :  * extracted from the struct lexer_state.
     563                 :            :  *
     564                 :            :  * As a command-line option, gcc-like directives (with only a '#',
     565                 :            :  * without 'line') may be produced.
     566                 :            :  *
     567                 :            :  * enter_file() returns 1 if a (CONTEXT) token was produced, 0 otherwise.
     568                 :            :  */
     569                 :     131954 : int enter_file(struct lexer_state *ls, unsigned long flags)
     570                 :            : {
     571                 :     263908 :         char *fn = current_long_filename ?
     572         [ +  + ]:     131954 :                 current_long_filename : current_filename;
     573                 :            : 
     574         [ -  + ]:     131954 :         if (!(flags & LINE_NUM)) return 0;
     575 [ -  + ][ #  # ]:     131954 :         if ((flags & LEXER) && !(flags & TEXT_OUTPUT)) {
     576                 :            :                 struct token t;
     577                 :            : 
     578                 :          0 :                 t.type = CONTEXT;
     579                 :          0 :                 t.line = ls->line;
     580                 :          0 :                 t.name = fn;
     581                 :          0 :                 print_token(ls, &t, 0);
     582                 :          0 :                 return 1;
     583                 :            :         }
     584                 :     131954 :         print_line_info(ls, flags);
     585                 :     131954 :         ls->oline --;        /* emitted #line troubled oline */
     586                 :     131954 :         return 0;
     587                 :            : }
     588                 :            : 
     589                 :            : #ifdef UCPP_MMAP
     590                 :            : /*
     591                 :            :  * We open() the file, then fdopen() it and fseek() to its end. If the
     592                 :            :  * fseek() worked, we try to mmap() the file, up to the point where we
     593                 :            :  * arrived.
     594                 :            :  * On an architecture where end-of-lines are multibytes and translated
     595                 :            :  * into single '\n', bad things could happen. We strongly hope that, if
     596                 :            :  * we could fseek() to the end but could not mmap(), then we can get back.
     597                 :            :  */
     598                 :            : static void *find_file_map;
     599                 :            : static size_t map_length;
     600                 :            : 
     601                 :            : FILE *fopen_mmap_file(char *name)
     602                 :            : {
     603                 :            :         FILE *f;
     604                 :            :         int fd;
     605                 :            :         long l;
     606                 :            : 
     607                 :            :         find_file_map = 0;
     608                 :            :         fd = open(name, O_RDONLY, 0);
     609                 :            :         if (fd < 0) return 0;
     610                 :            :         l = lseek(fd, 0, SEEK_END);
     611                 :            :         f = fdopen(fd, "r");
     612                 :            :         if (!f) {
     613                 :            :                 close(fd);
     614                 :            :                 return 0;
     615                 :            :         }
     616                 :            :         if (l < 0) return f; /* not seekable */
     617                 :            :         map_length = l;
     618                 :            :         if ((find_file_map = mmap(0, map_length, PROT_READ,
     619                 :            :                 MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
     620                 :            :                 /* we could not mmap() the file; get back */
     621                 :            :                 find_file_map = 0;
     622                 :            :                 if (fseek(f, 0, SEEK_SET)) {
     623                 :            :                         /* bwaah... can't get back. This file is cursed. */
     624                 :            :                         fclose(f);
     625                 :            :                         return 0;
     626                 :            :                 }
     627                 :            :         }
     628                 :            :         return f;
     629                 :            : }
     630                 :            : 
     631                 :            : void set_input_file(struct lexer_state *ls, FILE *f)
     632                 :            : {
     633                 :            :         ls->input = f;
     634                 :            :         if (find_file_map) {
     635                 :            :                 ls->from_mmap = 1;
     636                 :            :                 ls->input_buf_sav = ls->input_buf;
     637                 :            :                 ls->input_buf = find_file_map;
     638                 :            :                 ls->pbuf = 0;
     639                 :            :                 ls->ebuf = map_length;
     640                 :            :         } else {
     641                 :            :                 ls->from_mmap = 0;
     642                 :            :         }
     643                 :            : }
     644                 :            : #endif
     645                 :            : 
     646                 :            : /*
     647                 :            :  * Find a file by looking through the include path.
     648                 :            :  * return value: a FILE * on the file, opened in "r" mode, or 0.
     649                 :            :  *
     650                 :            :  * find_file_error will contain:
     651                 :            :  *   FF_ERROR      on error (file not found or impossible to read)
     652                 :            :  *   FF_PROTECT    file is protected and therefore useless to read
     653                 :            :  *   FF_KNOWN      file is already known
     654                 :            :  *   FF_UNKNOWN    file was not already known
     655                 :            :  */
     656                 :            : static int find_file_error;
     657                 :            : 
     658                 :            : enum { FF_ERROR, FF_PROTECT, FF_KNOWN, FF_UNKNOWN };
     659                 :            : 
     660                 :     112586 : static FILE *find_file(char *name, int localdir)
     661                 :            : {
     662                 :            :         FILE *f;
     663                 :     112586 :         int i, incdir = -1;
     664                 :     112586 :         size_t nl = strlen(name);
     665                 :     112586 :         char *s = 0;
     666                 :     112586 :         struct found_file *ff = 0, *nff;
     667                 :     112586 :         int lf = 0;
     668                 :     112586 :         int nffa = 0;
     669                 :            : 
     670                 :     112586 :         find_file_error = FF_ERROR;
     671                 :     112586 :         protect_detect.state = -1;
     672                 :     112586 :         protect_detect.macro = 0;
     673         [ -  + ]:     112586 :         if (localdir) {
     674                 :            :                 int i;
     675                 :          0 :                 char *rfn = current_long_filename ? current_long_filename
     676         [ #  # ]:          0 :                         : current_filename;
     677                 :            : 
     678         [ #  # ]:          0 :                 for (i = strlen(rfn) - 1; i >= 0; i --)
     679                 :            : #ifdef MSDOS
     680                 :            :                         if (rfn[i] == '\\') break;
     681                 :            : #else
     682         [ #  # ]:          0 :                         if (rfn[i] == '/') break;
     683                 :            : #endif
     684                 :            : #if defined MSDOS
     685                 :            :                 if (i >= 0 && *name != '\\' && (nl < 2 || name[1] != ':'))
     686                 :            : #elif defined AMIGA
     687                 :            :                 if (i >= 0 && *name != '/' && (nl < 2 || name[1] != ':'))
     688                 :            : #else
     689 [ #  # ][ #  # ]:          0 :                 if (i >= 0 && *name != '/')
     690                 :            : #endif
     691                 :            :                 {
     692                 :            :                         /*
     693                 :            :                          * current file is somewhere else, and the provided
     694                 :            :                          * file name is not absolute, so we must adjust the
     695                 :            :                          * base for looking for the file; besides,
     696                 :            :                          * found_files and found_files_loc are irrelevant
     697                 :            :                          * for this search.
     698                 :            :                          */
     699                 :          0 :                         s = getmem(i + 2 + nl);
     700                 :          0 :                         mmv(s, rfn, i);
     701                 :            : #ifdef MSDOS
     702                 :            :                         s[i] = '\\';
     703                 :            : #else
     704                 :          0 :                         s[i] = '/';
     705                 :            : #endif
     706                 :          0 :                         mmv(s + i + 1, name, nl);
     707                 :          0 :                         s[i + 1 + nl] = 0;
     708                 :          0 :                         ff = HTT_get(&found_files, s);
     709                 :          0 :                 } else ff = HTT_get(&found_files, name);
     710                 :            :         }
     711         [ +  - ]:     112586 :         if (!ff) {
     712                 :     112586 :                 struct found_file_sys *ffs = HTT_get(&found_files_sys, name);
     713                 :            : 
     714         [ +  + ]:     112586 :                 if (ffs) {
     715                 :      49598 :                         ff = ffs->rff;
     716                 :      49598 :                         incdir = ffs->incdir;
     717                 :            :                 }
     718                 :            :         }
     719                 :            :         /*
     720                 :            :          * At that point: if the file was found in the cache, ff points to
     721                 :            :          * the cached descriptive structure; its name is s if s is not 0,
     722                 :            :          * name otherwise.
     723                 :            :          */
     724         [ +  + ]:     112586 :         if (ff) goto found_file_cache;
     725                 :            : 
     726                 :            :         /*
     727                 :            :          * This is the first time we find the file, or it was not protected.
     728                 :            :          */
     729                 :      62988 :         protect_detect.ff = new_found_file();
     730                 :      62988 :         nffa = 1;
     731 [ #  # ][ -  + ]:      62988 :         if (localdir &&
     732                 :            : #ifdef UCPP_MMAP
     733                 :            :                 (f = fopen_mmap_file(s ? s : name))
     734                 :            : #else
     735         [ #  # ]:          0 :                 (f = fopen(s ? s : name, "r"))
     736                 :            : #endif
     737                 :            :                 ) {
     738                 :          0 :                 lf = 1;
     739                 :          0 :                 goto found_file;
     740                 :            :         }
     741                 :            :         /*
     742                 :            :          * If s contains a name, that name is now irrelevant: it was a
     743                 :            :          * filename for a search in the current directory, and the file
     744                 :            :          * was not found.
     745                 :            :          */
     746         [ -  + ]:      62988 :         if (s) {
     747                 :          0 :                 freemem(s);
     748                 :          0 :                 s = 0;
     749                 :            :         }
     750         [ +  - ]:     161375 :         for (i = 0; (size_t)i < include_path_nb; i ++) {
     751                 :     161375 :                 size_t ni = strlen(include_path[i]);
     752                 :            : 
     753                 :     161375 :                 s = getmem(ni + nl + 2);
     754                 :     161375 :                 mmv(s, include_path[i], ni);
     755                 :            : #ifdef AMIGA
     756                 :            :         /* contributed by Volker Barthelmann */
     757                 :            :                 if (ni == 1 && *s == '.') {
     758                 :            :                         *s = 0;
     759                 :            :                         ni = 0;
     760                 :            :                 }
     761                 :            :                 if (ni > 0 && s[ni - 1] != ':' && s[ni - 1] != '/') {
     762                 :            :                         s[ni] = '/';
     763                 :            :                         mmv(s + ni + 1, name, nl + 1);
     764                 :            :                 } else {
     765                 :            :                         mmv(s + ni, name, nl + 1);
     766                 :            :                 }
     767                 :            : #else
     768                 :     161375 :                 s[ni] = '/';
     769                 :     161375 :                 mmv(s + ni + 1, name, nl + 1);
     770                 :            : #endif
     771                 :            : #ifdef MSDOS
     772                 :            :                 /* on msdos systems, replace all / by \ */
     773                 :            :                 {
     774                 :            :                         char *c;
     775                 :            : 
     776                 :            :                         for (c = s; *c; c ++) if (*c == '/') *c = '\\';
     777                 :            :                 }
     778                 :            : #endif
     779                 :     161375 :                 incdir = i;
     780         [ -  + ]:     161375 :                 if ((ff = HTT_get(&found_files, s)) != 0) {
     781                 :            :                         /*
     782                 :            :                          * The file is known, but not as a system include
     783                 :            :                          * file under the name provided.
     784                 :            :                          */
     785                 :          0 :                         struct found_file_sys *ffs = new_found_file_sys();
     786                 :            : 
     787                 :          0 :                         ffs->rff = ff;
     788                 :          0 :                         ffs->incdir = incdir;
     789                 :          0 :                         HTT_put(&found_files_sys, ffs, name);
     790                 :          0 :                         freemem(s);
     791                 :          0 :                         s = 0;
     792         [ #  # ]:          0 :                         if (nffa) {
     793                 :          0 :                                 del_found_file(protect_detect.ff);
     794                 :          0 :                                 protect_detect.ff = 0;
     795                 :          0 :                                 nffa = 0;
     796                 :            :                         }
     797                 :          0 :                         goto found_file_cache;
     798                 :            :                 }
     799                 :            : #ifdef UCPP_MMAP
     800                 :            :                 f = fopen_mmap_file(s);
     801                 :            : #else
     802                 :     161375 :                 f = fopen(s, "r");
     803                 :            : #endif
     804         [ +  + ]:     161375 :                 if (f) goto found_file;
     805                 :      98387 :                 freemem(s);
     806                 :      98387 :                 s = 0;
     807                 :            :         }
     808                 :            : zero_out:
     809         [ -  + ]:      49598 :         if (s) freemem(s);
     810         [ -  + ]:      49598 :         if (nffa) {
     811                 :          0 :                 del_found_file(protect_detect.ff);
     812                 :          0 :                 protect_detect.ff = 0;
     813                 :          0 :                 nffa = 0;
     814                 :            :         }
     815                 :      49598 :         return 0;
     816                 :            : 
     817                 :            :         /*
     818                 :            :          * This part is invoked when the file was found in the
     819                 :            :          * cache.
     820                 :            :          */
     821                 :            : found_file_cache:
     822         [ +  - ]:      49598 :         if (ff->protect) {
     823         [ +  - ]:      49598 :                 if (get_macro(ff->protect)) {
     824                 :            :                         /* file is protected, do not include it */
     825                 :      49598 :                         find_file_error = FF_PROTECT;
     826                 :      49598 :                         goto zero_out;
     827                 :            :                 }
     828                 :            :                 /* file is protected but the guardian macro is
     829                 :            :                    not available; disable guardian detection. */
     830                 :          0 :                 protect_detect.state = 0;
     831                 :            :         }
     832                 :          0 :         protect_detect.ff = ff;
     833                 :            : #ifdef UCPP_MMAP
     834                 :            :         f = fopen_mmap_file(HASH_ITEM_NAME(ff));
     835                 :            : #else
     836                 :          0 :         f = fopen(HASH_ITEM_NAME(ff), "r");
     837                 :            : #endif
     838         [ #  # ]:          0 :         if (!f) goto zero_out;
     839                 :          0 :         find_file_error = FF_KNOWN;
     840                 :          0 :         goto found_file_2;
     841                 :            : 
     842                 :            :         /*
     843                 :            :          * This part is invoked when we found a new file, which was not
     844                 :            :          * yet referenced. If lf == 1, then the file was found directly,
     845                 :            :          * otherwise it was found in some system include directory.
     846                 :            :          * A new found_file structure has been allocated and is in
     847                 :            :          * protect_detect.ff
     848                 :            :          */
     849                 :            : found_file:
     850 [ +  - ][ -  + ]:      62988 :         if (f && ((emit_dependencies == 1 && lf && current_incdir == -1)
         [ #  # ][ #  # ]
     851         [ -  + ]:      62988 :                 || emit_dependencies == 2)) {
     852         [ #  # ]:          0 :                 fprintf(emit_output, " %s", s ? s : name);
     853                 :            :         }
     854                 :      62988 :         nff = protect_detect.ff;
     855                 :      62988 :         nff->name = sdup(name);
     856                 :            : #ifdef AUDIT
     857                 :            :         if (
     858                 :            : #endif
     859         [ +  - ]:      62988 :         HTT_put(&found_files, nff, s ? s : name)
     860                 :            : #ifdef AUDIT
     861                 :            :         ) ouch("filename collided with a wraith")
     862                 :            : #endif
     863                 :            :         ;
     864         [ +  - ]:      62988 :         if (!lf) {
     865                 :      62988 :                 struct found_file_sys *ffs = new_found_file_sys();
     866                 :            : 
     867                 :      62988 :                 ffs->rff = nff;
     868                 :      62988 :                 ffs->incdir = incdir;
     869                 :      62988 :                 HTT_put(&found_files_sys, ffs, name);
     870                 :            :         }
     871         [ +  - ]:      62988 :         if (s) freemem(s);
     872                 :      62988 :         s = 0;
     873                 :      62988 :         find_file_error = FF_UNKNOWN;
     874                 :      62988 :         ff = nff;
     875                 :            : 
     876                 :            : found_file_2:
     877         [ -  + ]:      62988 :         if (s) freemem(s);
     878                 :      62988 :         current_long_filename = HASH_ITEM_NAME(ff);
     879                 :            : #ifdef NO_LIBC_BUF
     880                 :            :         setbuf(f, 0);
     881                 :            : #endif
     882                 :      62988 :         current_incdir = incdir;
     883                 :     112586 :         return f;
     884                 :            : }
     885                 :            : 
     886                 :            : /*
     887                 :            :  * Find the named file by looking through the end of the include path.
     888                 :            :  * This is for #include_next directives.
     889                 :            :  * #include_next <foo> and #include_next "foo" are considered identical,
     890                 :            :  * for all practical purposes.
     891                 :            :  */
     892                 :          0 : static FILE *find_file_next(char *name)
     893                 :            : {
     894                 :            :         int i;
     895                 :          0 :         size_t nl = strlen(name);
     896                 :            :         FILE *f;
     897                 :            :         struct found_file *ff;
     898                 :            : 
     899                 :          0 :         find_file_error = FF_ERROR;
     900                 :          0 :         protect_detect.state = -1;
     901                 :          0 :         protect_detect.macro = 0;
     902         [ #  # ]:          0 :         for (i = current_incdir + 1; (size_t)i < include_path_nb; i ++) {
     903                 :            :                 char *s;
     904                 :          0 :                 size_t ni = strlen(include_path[i]);
     905                 :            : 
     906                 :          0 :                 s = getmem(ni + nl + 2);
     907                 :          0 :                 mmv(s, include_path[i], ni);
     908                 :          0 :                 s[ni] = '/';
     909                 :          0 :                 mmv(s + ni + 1, name, nl + 1);
     910                 :            : #ifdef MSDOS
     911                 :            :                 /* on msdos systems, replace all / by \ */
     912                 :            :                 {
     913                 :            :                         char *c;
     914                 :            : 
     915                 :            :                         for (c = s; *c; c ++) if (*c == '/') *c = '\\';
     916                 :            :                 }
     917                 :            : #endif
     918                 :          0 :                 ff = HTT_get(&found_files, s);
     919         [ #  # ]:          0 :                 if (ff) {
     920                 :            :                         /* file was found in the cache */
     921         [ #  # ]:          0 :                         if (ff->protect) {
     922         [ #  # ]:          0 :                                 if (get_macro(ff->protect)) {
     923                 :          0 :                                         find_file_error = FF_PROTECT;
     924                 :          0 :                                         freemem(s);
     925                 :          0 :                                         return 0;
     926                 :            :                                 }
     927                 :            :                                 /* file is protected but the guardian macro is
     928                 :            :                                    not available; disable guardian detection. */
     929                 :          0 :                                 protect_detect.state = 0;
     930                 :            :                         }
     931                 :          0 :                         protect_detect.ff = ff;
     932                 :            : #ifdef UCPP_MMAP
     933                 :            :                         f = fopen_mmap_file(HASH_ITEM_NAME(ff));
     934                 :            : #else
     935                 :          0 :                         f = fopen(HASH_ITEM_NAME(ff), "r");
     936                 :            : #endif
     937         [ #  # ]:          0 :                         if (!f) {
     938                 :            :                                 /* file is referenced but yet unavailable. */
     939                 :          0 :                                 freemem(s);
     940                 :          0 :                                 return 0;
     941                 :            :                         }
     942                 :          0 :                         find_file_error = FF_KNOWN;
     943                 :          0 :                         freemem(s);
     944                 :          0 :                         s = HASH_ITEM_NAME(ff);
     945                 :            :                 } else {
     946                 :            : #ifdef UCPP_MMAP
     947                 :            :                         f = fopen_mmap_file(s);
     948                 :            : #else
     949                 :          0 :                         f = fopen(s, "r");
     950                 :            : #endif
     951         [ #  # ]:          0 :                         if (f) {
     952         [ #  # ]:          0 :                                 if (emit_dependencies == 2) {
     953                 :          0 :                                         fprintf(emit_output, " %s", s);
     954                 :            :                                 }
     955                 :          0 :                                 ff = protect_detect.ff = new_found_file();
     956                 :          0 :                                 ff->name = sdup(s);
     957                 :            : #ifdef AUDIT
     958                 :            :                                 if (
     959                 :            : #endif
     960                 :          0 :                                 HTT_put(&found_files, ff, s)
     961                 :            : #ifdef AUDIT
     962                 :            :                                 ) ouch("filename collided with a wraith")
     963                 :            : #endif
     964                 :            :                                 ;
     965                 :          0 :                                 find_file_error = FF_UNKNOWN;
     966                 :          0 :                                 freemem(s);
     967                 :          0 :                                 s = HASH_ITEM_NAME(ff);
     968                 :            :                         }
     969                 :            :                 }
     970         [ #  # ]:          0 :                 if (f) {
     971                 :          0 :                         current_long_filename = s;
     972                 :          0 :                         current_incdir = i;
     973                 :          0 :                         return f;
     974                 :            :                 }
     975                 :          0 :                 freemem(s);
     976                 :            :         }
     977                 :          0 :         return 0;
     978                 :            : }
     979                 :            : 
     980                 :            : /*
     981                 :            :  * The #if directive. This function parse the expression, performs macro
     982                 :            :  * expansion (and handles the "defined" operator), and call eval_expr.
     983                 :            :  * return value: 1 if the expression is true, 0 if it is false, -1 on error.
     984                 :            :  */
     985                 :          2 : static int handle_if(struct lexer_state *ls)
     986                 :            : {
     987                 :            :         struct token_fifo tf, tf1, tf2, tf3, *save_tf;
     988                 :          2 :         long l = ls->line;
     989                 :            :         unsigned long z;
     990                 :          2 :         int ret = 0, ltww = 1;
     991                 :            : 
     992                 :            :         /* first, get the whole line */
     993                 :          2 :         tf.art = tf.nt = 0;
     994 [ +  - ][ +  + ]:          6 :         while (!next_token(ls) && ls->ctok->type != NEWLINE) {
     995                 :            :                 struct token t;
     996                 :            : 
     997 [ +  - ][ +  + ]:          4 :                 if (ltww && ttMWS(ls->ctok->type)) continue;
         [ +  - ][ -  + ]
     998 [ +  - ][ +  - ]:          2 :                 ltww = ttMWS(ls->ctok->type);
                 [ -  + ]
     999                 :          2 :                 t.type = ls->ctok->type;
    1000                 :          2 :                 t.line = l;
    1001 [ +  - ][ +  - ]:          2 :                 if (S_TOKEN(ls->ctok->type)) {
    1002                 :          2 :                         t.name = sdup(ls->ctok->name);
    1003                 :          2 :                         throw_away(ls->gf, t.name);
    1004                 :            :                 }
    1005 [ +  - ][ -  + ]:          2 :                 aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG);
    1006                 :            :         }
    1007 [ -  + ][ #  # ]:          2 :         if (ltww && tf.nt) if ((-- tf.nt) == 0) freemem(tf.t);
                 [ #  # ]
    1008         [ -  + ]:          2 :         if (tf.nt == 0) {
    1009                 :          0 :                 error(l, "void condition for a #if/#elif");
    1010                 :          0 :                 return -1;
    1011                 :            :         }
    1012                 :            :         /* handle the "defined" operator */
    1013                 :          2 :         tf1.art = tf1.nt = 0;
    1014         [ +  + ]:          4 :         while (tf.art < tf.nt) {
    1015                 :            :                 struct token *ct, rt;
    1016                 :            :                 struct macro *m;
    1017                 :            :                 size_t nidx, eidx;
    1018                 :            : 
    1019                 :          2 :                 ct = tf.t + (tf.art ++);
    1020 [ -  + ][ #  # ]:          2 :                 if (ct->type == NAME && !strcmp(ct->name, "defined")) {
    1021         [ #  # ]:          0 :                         if (tf.art >= tf.nt) goto store_token;
    1022                 :          0 :                         nidx = tf.art;
    1023 [ #  # ][ #  # ]:          0 :                         if (ttMWS(tf.t[nidx].type))
                 [ #  # ]
    1024         [ #  # ]:          0 :                                 if (++ nidx >= tf.nt) goto store_token;
    1025         [ #  # ]:          0 :                         if (tf.t[nidx].type == NAME) {
    1026                 :          0 :                                 eidx = nidx;
    1027                 :          0 :                                 goto check_macro;
    1028                 :            :                         }
    1029         [ #  # ]:          0 :                         if (tf.t[nidx].type != LPAR) goto store_token;
    1030         [ #  # ]:          0 :                         if (++ nidx >= tf.nt) goto store_token;
    1031 [ #  # ][ #  # ]:          0 :                         if (ttMWS(tf.t[nidx].type))
                 [ #  # ]
    1032         [ #  # ]:          0 :                                 if (++ nidx >= tf.nt) goto store_token;
    1033         [ #  # ]:          0 :                         if (tf.t[nidx].type != NAME) goto store_token;
    1034                 :          0 :                         eidx = nidx + 1;
    1035         [ #  # ]:          0 :                         if (eidx >= tf.nt) goto store_token;
    1036 [ #  # ][ #  # ]:          0 :                         if (ttMWS(tf.t[eidx].type))
                 [ #  # ]
    1037         [ #  # ]:          0 :                                 if (++ eidx >= tf.nt) goto store_token;
    1038         [ #  # ]:          0 :                         if (tf.t[eidx].type != RPAR) goto store_token;
    1039                 :          0 :                         goto check_macro;
    1040                 :            :                 }
    1041                 :            :         store_token:
    1042 [ +  - ][ -  + ]:          2 :                 aol(tf1.t, tf1.nt, *ct, TOKEN_LIST_MEMG);
    1043                 :          2 :                 continue;
    1044                 :            : 
    1045                 :            :         check_macro:
    1046                 :          0 :                 m = get_macro(tf.t[nidx].name);
    1047                 :          0 :                 rt.type = NUMBER;
    1048         [ #  # ]:          0 :                 rt.name = m ? "1L" : "0L";
    1049 [ #  # ][ #  # ]:          0 :                 aol(tf1.t, tf1.nt, rt, TOKEN_LIST_MEMG);
    1050                 :          0 :                 tf.art = eidx + 1;
    1051                 :            :         }
    1052                 :          2 :         freemem(tf.t);
    1053         [ -  + ]:          2 :         if (tf1.nt == 0) {
    1054                 :          0 :                 error(l, "void condition (after expansion) for a #if/#elif");
    1055                 :          0 :                 return -1;
    1056                 :            :         }
    1057                 :            : 
    1058                 :            :         /* perform all macro substitutions */
    1059                 :          2 :         tf2.art = tf2.nt = 0;
    1060                 :          2 :         save_tf = ls->output_fifo;
    1061                 :          2 :         ls->output_fifo = &tf2;
    1062         [ +  + ]:          4 :         while (tf1.art < tf1.nt) {
    1063                 :            :                 struct token *ct;
    1064                 :            : 
    1065                 :          2 :                 ct = tf1.t + (tf1.art ++);
    1066         [ -  + ]:          2 :                 if (ct->type == NAME) {
    1067                 :          0 :                         struct macro *m = get_macro(ct->name);
    1068                 :            : 
    1069         [ #  # ]:          0 :                         if (m) {
    1070         [ #  # ]:          0 :                                 if (substitute_macro(ls, m, &tf1, 0,
    1071                 :            : #ifdef NO_PRAGMA_IN_DIRECTIVE
    1072                 :            :                                         1,
    1073                 :            : #else
    1074                 :            :                                         0,
    1075                 :            : #endif
    1076                 :            :                                         ct->line)) {
    1077                 :          0 :                                         ls->output_fifo = save_tf;
    1078                 :          0 :                                         goto error1;
    1079                 :            :                                 }
    1080                 :          0 :                                 continue;
    1081                 :            :                         }
    1082 [ +  - ][ -  + ]:          2 :                 } else if ((ct->type == SHARP || ct->type == DIG_SHARP)
    1083         [ #  # ]:          0 :                         && (ls->flags & HANDLE_ASSERTIONS)) {
    1084                 :            :                         /* we have an assertion; parse it */
    1085                 :          0 :                         int nnp, ltww = 1;
    1086                 :          0 :                         size_t i = tf1.art;
    1087                 :            :                         struct token_fifo atl;
    1088                 :            :                         char *aname;
    1089                 :            :                         struct assert *a;
    1090                 :          0 :                         int av = 0;
    1091                 :            :                         struct token rt;
    1092                 :            : 
    1093                 :          0 :                         atl.art = atl.nt = 0;
    1094 [ #  # ][ #  # ]:          0 :                         while (i < tf1.nt && ttMWS(tf1.t[i].type)) i ++;
         [ #  # ][ #  # ]
    1095         [ #  # ]:          0 :                         if (i >= tf1.nt) goto assert_error;
    1096         [ #  # ]:          0 :                         if (tf1.t[i].type != NAME) goto assert_error;
    1097                 :          0 :                         aname = tf1.t[i ++].name;
    1098 [ #  # ][ #  # ]:          0 :                         while (i < tf1.nt && ttMWS(tf1.t[i].type)) i ++;
         [ #  # ][ #  # ]
    1099         [ #  # ]:          0 :                         if (i >= tf1.nt) goto assert_generic;
    1100         [ #  # ]:          0 :                         if (tf1.t[i].type != LPAR) goto assert_generic;
    1101                 :          0 :                         i ++;
    1102 [ #  # ][ #  # ]:          0 :                         for (nnp = 1; nnp && i < tf1.nt; i ++) {
    1103 [ #  # ][ #  # ]:          0 :                                 if (ltww && ttMWS(tf1.t[i].type)) continue;
         [ #  # ][ #  # ]
    1104         [ #  # ]:          0 :                                 if (tf1.t[i].type == LPAR) nnp ++;
    1105         [ #  # ]:          0 :                                 else if (tf1.t[i].type == RPAR
    1106         [ #  # ]:          0 :                                         && (-- nnp) == 0) {
    1107                 :          0 :                                         tf1.art = i + 1;
    1108                 :          0 :                                         break;
    1109                 :            :                                 }
    1110 [ #  # ][ #  # ]:          0 :                                 ltww = ttMWS(tf1.t[i].type);
                 [ #  # ]
    1111 [ #  # ][ #  # ]:          0 :                                 aol(atl.t, atl.nt, tf1.t[i], TOKEN_LIST_MEMG);
    1112                 :            :                         }
    1113         [ #  # ]:          0 :                         if (nnp) goto assert_error;
    1114 [ #  # ][ #  # ]:          0 :                         if (ltww && atl.nt && (-- atl.nt) == 0) freemem(atl.t);
                 [ #  # ]
    1115         [ #  # ]:          0 :                         if (atl.nt == 0) goto assert_error;
    1116                 :            : 
    1117                 :            :                         /* the assertion is in aname and atl; check it */
    1118                 :          0 :                         a = get_assertion(aname);
    1119 [ #  # ][ #  # ]:          0 :                         if (a) for (i = 0; i < a->nbval; i ++)
    1120         [ #  # ]:          0 :                                 if (!cmp_token_list(&atl, a->val + i)) {
    1121                 :          0 :                                         av = 1;
    1122                 :          0 :                                         break;
    1123                 :            :                                 }
    1124                 :          0 :                         rt.type = NUMBER;
    1125         [ #  # ]:          0 :                         rt.name = av ? "1" : "0";
    1126 [ #  # ][ #  # ]:          0 :                         aol(tf2.t, tf2.nt, rt, TOKEN_LIST_MEMG);
    1127         [ #  # ]:          0 :                         if (atl.nt) freemem(atl.t);
    1128                 :          0 :                         continue;
    1129                 :            : 
    1130                 :            :                 assert_generic:
    1131                 :          0 :                         tf1.art = i;
    1132                 :          0 :                         rt.type = NUMBER;
    1133         [ #  # ]:          0 :                         rt.name = get_assertion(aname) ? "1" : "0";
    1134 [ #  # ][ #  # ]:          0 :                         aol(tf2.t, tf2.nt, rt, TOKEN_LIST_MEMG);
    1135                 :          0 :                         continue;
    1136                 :            : 
    1137                 :            :                 assert_error:
    1138                 :          0 :                         error(l, "syntax error for assertion in #if");
    1139                 :          0 :                         ls->output_fifo = save_tf;
    1140                 :            :                         goto error1;
    1141                 :            :                 }
    1142 [ +  - ][ -  + ]:          2 :                 aol(tf2.t, tf2.nt, *ct, TOKEN_LIST_MEMG);
    1143                 :            :         }
    1144                 :          2 :         ls->output_fifo = save_tf;
    1145                 :          2 :         freemem(tf1.t);
    1146         [ -  + ]:          2 :         if (tf2.nt == 0) {
    1147                 :          0 :                 error(l, "void condition (after expansion) for a #if/#elif");
    1148                 :          0 :                 return -1;
    1149                 :            :         }
    1150                 :            : 
    1151                 :            :         /*
    1152                 :            :          * suppress whitespace and replace rogue identifiers by 0
    1153                 :            :          */
    1154                 :          2 :         tf3.art = tf3.nt = 0;
    1155         [ +  + ]:          4 :         while (tf2.art < tf2.nt) {
    1156                 :          2 :                 struct token *ct = tf2.t + (tf2.art ++);
    1157                 :            : 
    1158 [ +  - ][ +  - ]:          2 :                 if (ttMWS(ct->type)) continue;
                 [ -  + ]
    1159         [ -  + ]:          2 :                 if (ct->type == NAME) {
    1160                 :            :                         /*
    1161                 :            :                          * a rogue identifier; we replace it with "0".
    1162                 :            :                          */
    1163                 :            :                         struct token rt;
    1164                 :            : 
    1165                 :          0 :                         rt.type = NUMBER;
    1166                 :          0 :                         rt.name = "0";
    1167 [ #  # ][ #  # ]:          0 :                         aol(tf3.t, tf3.nt, rt, TOKEN_LIST_MEMG);
    1168                 :          0 :                         continue;
    1169                 :            :                 }
    1170 [ +  - ][ -  + ]:          2 :                 aol(tf3.t, tf3.nt, *ct, TOKEN_LIST_MEMG);
    1171                 :            :         }
    1172                 :          2 :         freemem(tf2.t);
    1173                 :            : 
    1174         [ -  + ]:          2 :         if (tf3.nt == 0) {
    1175                 :          0 :                 error(l, "void condition (after expansion) for a #if/#elif");
    1176                 :          0 :                 return -1;
    1177                 :            :         }
    1178                 :          2 :         eval_line = l;
    1179                 :          2 :         z = eval_expr(&tf3, &ret, (ls->flags & WARN_STANDARD) != 0);
    1180                 :          2 :         freemem(tf3.t);
    1181         [ -  + ]:          2 :         if (ret) return -1;
    1182                 :          2 :         return (z != 0);
    1183                 :            : 
    1184                 :            : error1:
    1185         [ #  # ]:          0 :         if (tf1.nt) freemem(tf1.t);
    1186         [ #  # ]:          0 :         if (tf2.nt) freemem(tf2.t);
    1187                 :          2 :         return -1;
    1188                 :            : }
    1189                 :            : 
    1190                 :            : /*
    1191                 :            :  * A #include was found; parse the end of line, replace macros if
    1192                 :            :  * necessary.
    1193                 :            :  *
    1194                 :            :  * If nex is set to non-zero, the directive is considered as a #include_next
    1195                 :            :  * (extension to C99, mimicked from GNU)
    1196                 :            :  */
    1197                 :     112586 : static int handle_include(struct lexer_state *ls, unsigned long flags, int nex)
    1198                 :            : {
    1199                 :     112586 :         int c, string_fname = 0;
    1200                 :            :         char *fname;
    1201                 :            :         unsigned char *fname2;
    1202                 :     112586 :         size_t fname_ptr = 0;
    1203                 :     112586 :         long l = ls->line;
    1204                 :            :         int x, y;
    1205                 :            :         FILE *f;
    1206                 :            :         struct token_fifo tf, tf2, *save_tf;
    1207                 :            :         size_t nl;
    1208                 :            :         int tgd;
    1209                 :            :         struct lexer_state alt_ls;
    1210                 :            : 
    1211                 :            : #define left_angle(t)   ((t) == LT || (t) == LEQ || (t) == LSH \
    1212                 :            :                         || (t) == ASLSH || (t) == DIG_LBRK || (t) == LBRA)
    1213                 :            : #define right_angle(t)  ((t) == GT || (t) == RSH || (t) == ARROW \
    1214                 :            :                         || (t) == DIG_RBRK || (t) == DIG_RBRA)
    1215                 :            : 
    1216 [ +  - ][ +  - ]:     225172 :         while ((c = grap_char(ls)) >= 0 && c != '\n') {
    1217         [ +  + ]:     225172 :                 if (space_char(c)) {
    1218                 :     112586 :                         discard_char(ls);
    1219                 :     112586 :                         continue;
    1220                 :            :                 }
    1221         [ +  - ]:     112586 :                 if (c == '<') {
    1222                 :     112586 :                         discard_char(ls);
    1223         [ +  - ]:    4165152 :                         while ((c = grap_char(ls)) >= 0) {
    1224                 :    4165152 :                                 discard_char(ls);
    1225         [ -  + ]:    4165152 :                                 if (c == '\n') goto include_last_chance;
    1226         [ +  + ]:    4165152 :                                 if (c == '>') break;
    1227 [ +  + ][ +  + ]:    4052566 :                                 aol(fname, fname_ptr, (char)c, FNAME_MEMG);
    1228                 :            :                         }
    1229 [ +  + ][ +  - ]:     112586 :                         aol(fname, fname_ptr, (char)0, FNAME_MEMG);
    1230                 :     112586 :                         string_fname = 0;
    1231                 :     112586 :                         goto do_include;
    1232         [ #  # ]:          0 :                 } else if (c == '"') {
    1233                 :          0 :                         discard_char(ls);
    1234         [ #  # ]:          0 :                         while ((c = grap_char(ls)) >= 0) {
    1235                 :          0 :                                 discard_char(ls);
    1236         [ #  # ]:          0 :                                 if (c == '\n') {
    1237                 :            :                                 /* macro replacements won't save that one */
    1238         [ #  # ]:          0 :                                         if (fname_ptr) freemem(fname);
    1239                 :          0 :                                         goto include_error;
    1240                 :            :                                 }
    1241         [ #  # ]:          0 :                                 if (c == '"') break;
    1242 [ #  # ][ #  # ]:          0 :                                 aol(fname, fname_ptr, (char)c, FNAME_MEMG);
    1243                 :            :                         }
    1244 [ #  # ][ #  # ]:          0 :                         aol(fname, fname_ptr, (char)0, FNAME_MEMG);
    1245                 :          0 :                         string_fname = 1;
    1246                 :          0 :                         goto do_include;
    1247                 :            :                 }
    1248                 :          0 :                 goto include_macro;
    1249                 :            :         }
    1250                 :            : 
    1251                 :            : include_last_chance:
    1252                 :            :         /*
    1253                 :            :          * We found a '<' but not the trailing '>'; so we tokenize the
    1254                 :            :          * line, and try to act upon it. The standard lets us free in that
    1255                 :            :          * matter, and no sane programmer would use such a construct, but
    1256                 :            :          * it is no reason not to support it.
    1257                 :            :          */
    1258         [ #  # ]:          0 :         if (fname_ptr == 0) goto include_error;
    1259                 :          0 :         fname2 = getmem(fname_ptr + 1);
    1260                 :          0 :         mmv(fname2 + 1, fname, fname_ptr);
    1261                 :          0 :         fname2[0] = '<';
    1262                 :            :         /*
    1263                 :            :          * We merely copy the lexer_state structure; this should be ok,
    1264                 :            :          * since we do want to share the memory structure (garbage_fifo),
    1265                 :            :          * and do not touch any other context-full thing.
    1266                 :            :          */
    1267                 :          0 :         alt_ls = *ls;
    1268                 :          0 :         alt_ls.input = 0;
    1269                 :          0 :         alt_ls.input_string = fname2;
    1270                 :          0 :         alt_ls.pbuf = 0;
    1271                 :          0 :         alt_ls.ebuf = fname_ptr + 1;
    1272                 :          0 :         tf.art = tf.nt = 0;
    1273         [ #  # ]:          0 :         while (!next_token(&alt_ls)) {
    1274 [ #  # ][ #  # ]:          0 :                 if (!ttMWS(alt_ls.ctok->type)) {
                 [ #  # ]
    1275                 :            :                         struct token t;
    1276                 :            : 
    1277                 :          0 :                         t.type = alt_ls.ctok->type;
    1278                 :          0 :                         t.line = l;
    1279 [ #  # ][ #  # ]:          0 :                         if (S_TOKEN(alt_ls.ctok->type)) {
    1280                 :          0 :                                 t.name = sdup(alt_ls.ctok->name);
    1281                 :          0 :                                 throw_away(alt_ls.gf, t.name);
    1282                 :            :                         }
    1283 [ #  # ][ #  # ]:          0 :                         aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG);
    1284                 :            :                 }
    1285                 :            :         }
    1286                 :          0 :         freemem(fname2);
    1287         [ #  # ]:          0 :         if (alt_ls.pbuf < alt_ls.ebuf) goto include_error;
    1288                 :            :                 /* tokenizing failed */
    1289                 :          0 :         goto include_macro2;
    1290                 :            :         
    1291                 :            : include_error:
    1292                 :          0 :         error(l, "invalid '#include'");
    1293                 :          0 :         return 1;
    1294                 :            : 
    1295                 :            : include_macro:
    1296                 :          0 :         tf.art = tf.nt = 0;
    1297 [ #  # ][ #  # ]:          0 :         while (!next_token(ls) && ls->ctok->type != NEWLINE) {
    1298 [ #  # ][ #  # ]:          0 :                 if (!ttMWS(ls->ctok->type)) {
                 [ #  # ]
    1299                 :            :                         struct token t;
    1300                 :            : 
    1301                 :          0 :                         t.type = ls->ctok->type;
    1302                 :          0 :                         t.line = l;
    1303 [ #  # ][ #  # ]:          0 :                         if (S_TOKEN(ls->ctok->type)) {
    1304                 :          0 :                                 t.name = sdup(ls->ctok->name);
    1305                 :          0 :                                 throw_away(ls->gf, t.name);
    1306                 :            :                         }
    1307 [ #  # ][ #  # ]:          0 :                         aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG);
    1308                 :            :                 }
    1309                 :            :         }
    1310                 :            : include_macro2:
    1311                 :          0 :         tf2.art = tf2.nt = 0;
    1312                 :          0 :         save_tf = ls->output_fifo;
    1313                 :          0 :         ls->output_fifo = &tf2;
    1314         [ #  # ]:          0 :         while (tf.art < tf.nt) {
    1315                 :            :                 struct token *ct;
    1316                 :            : 
    1317                 :          0 :                 ct = tf.t + (tf.art ++);
    1318         [ #  # ]:          0 :                 if (ct->type == NAME) {
    1319                 :          0 :                         struct macro *m = get_macro(ct->name);
    1320         [ #  # ]:          0 :                         if (m) {
    1321         [ #  # ]:          0 :                                 if (substitute_macro(ls, m, &tf, 0,
    1322                 :            : #ifdef NO_PRAGMA_IN_DIRECTIVE
    1323                 :            :                                         1,
    1324                 :            : #else
    1325                 :            :                                         0,
    1326                 :            : #endif
    1327                 :            :                                         ct->line)) {
    1328                 :          0 :                                         ls->output_fifo = save_tf;
    1329                 :          0 :                                         return -1;
    1330                 :            :                                 }
    1331                 :          0 :                                 continue;
    1332                 :            :                         }
    1333                 :            :                 }
    1334 [ #  # ][ #  # ]:          0 :                 aol(tf2.t, tf2.nt, *ct, TOKEN_LIST_MEMG);
    1335                 :            :         }
    1336                 :          0 :         freemem(tf.t);
    1337                 :          0 :         ls->output_fifo = save_tf;
    1338 [ #  # ][ #  # ]:          0 :         for (x = 0; (size_t)x < tf2.nt && ttWHI(tf2.t[x].type); x ++);
         [ #  # ][ #  # ]
                 [ #  # ]
    1339 [ #  # ][ #  # ]:          0 :         for (y = tf2.nt - 1; y >= 0 && ttWHI(tf2.t[y].type); y --);
         [ #  # ][ #  # ]
                 [ #  # ]
    1340         [ #  # ]:          0 :         if ((size_t)x >= tf2.nt) goto include_macro_err;
    1341         [ #  # ]:          0 :         if (tf2.t[x].type == STRING) {
    1342         [ #  # ]:          0 :                 if (y != x) goto include_macro_err;
    1343         [ #  # ]:          0 :                 if (tf2.t[x].name[0] == 'L') {
    1344         [ #  # ]:          0 :                         if (ls->flags & WARN_STANDARD)
    1345                 :          0 :                                 warning(l, "wide string for #include");
    1346                 :          0 :                         fname = sdup(tf2.t[x].name);
    1347                 :          0 :                         nl = strlen(fname);
    1348                 :          0 :                         *(fname + nl - 1) = 0;
    1349                 :          0 :                         mmvwo(fname, fname + 2, nl - 2);
    1350                 :            :                 } else {
    1351                 :          0 :                         fname = sdup(tf2.t[x].name);
    1352                 :          0 :                         nl = strlen(fname);
    1353                 :          0 :                         *(fname + nl - 1) = 0;
    1354                 :          0 :                         mmvwo(fname, fname + 1, nl - 1);
    1355                 :            :                 }
    1356                 :          0 :                 string_fname = 1;
    1357 [ #  # ][ #  # ]:          0 :         } else if (left_angle(tf2.t[x].type) && right_angle(tf2.t[y].type)) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1358                 :            :                 int i, j;
    1359                 :            : 
    1360         [ #  # ]:          0 :                 if (ls->flags & WARN_ANNOYING) warning(l, "reconstruction "
    1361                 :            :                         "of <foo> in #include");
    1362 [ #  # ][ #  # ]:          0 :                 for (j = 0, i = x; i <= y; i ++) if (!ttWHI(tf2.t[i].type))
         [ #  # ][ #  # ]
                 [ #  # ]
    1363 [ #  # ][ #  # ]:          0 :                         j += strlen(tname(tf2.t[i]));
    1364                 :          0 :                 fname = getmem(j + 1);
    1365         [ #  # ]:          0 :                 for (j = 0, i = x; i <= y; i ++) {
    1366 [ #  # ][ #  # ]:          0 :                         if (ttWHI(tf2.t[i].type)) continue;
         [ #  # ][ #  # ]
    1367 [ #  # ][ #  # ]:          0 :                         strcpy(fname + j, tname(tf2.t[i]));
    1368 [ #  # ][ #  # ]:          0 :                         j += strlen(tname(tf2.t[i]));
    1369                 :            :                 }
    1370                 :          0 :                 *(fname + j - 1) = 0;
    1371                 :          0 :                 mmvwo(fname, fname + 1, j);
    1372                 :          0 :                 string_fname = 0;
    1373                 :            :         } else goto include_macro_err;
    1374                 :          0 :         freemem(tf2.t);
    1375                 :          0 :         goto do_include_next;
    1376                 :            : 
    1377                 :            : include_macro_err:
    1378                 :          0 :         error(l, "macro expansion did not produce a valid filename "
    1379                 :            :                 "for #include");
    1380         [ #  # ]:          0 :         if (tf2.nt) freemem(tf2.t);
    1381                 :          0 :         return 1;
    1382                 :            : 
    1383                 :            : do_include:
    1384                 :     112586 :         tgd = 1;
    1385         [ +  - ]:     112586 :         while (!next_token(ls)) {
    1386 [ +  - ][ +  - ]:     112586 :                 if (tgd && !ttWHI(ls->ctok->type)
         [ +  - ][ +  - ]
                 [ -  + ]
    1387         [ #  # ]:          0 :                         && (ls->flags & WARN_STANDARD)) {
    1388                 :          0 :                         warning(l, "trailing garbage in #include");
    1389                 :          0 :                         tgd = 0;
    1390                 :            :                 }
    1391         [ +  - ]:     112586 :                 if (ls->ctok->type == NEWLINE) break;
    1392                 :            :         }
    1393                 :            : 
    1394                 :            :         /* the increment of ls->line is intended so that the line
    1395                 :            :            numbering is reported correctly in report_context() even if
    1396                 :            :            the #include is at the end of the file with no trailing newline */
    1397         [ -  + ]:     112586 :         if (ls->ctok->type != NEWLINE) ls->line ++;
    1398                 :            : do_include_next:
    1399 [ -  + ][ #  # ]:     112586 :         if (!(ls->flags & LEXER) && (ls->flags & KEEP_OUTPUT))
    1400                 :          0 :                 put_char(ls, '\n');
    1401                 :     112586 :         push_file_context(ls);
    1402                 :     112586 :         reinit_lexer_state(ls, 1);
    1403                 :            : #ifdef MSDOS
    1404                 :            :         /* on msdos systems, replace all / by \ */
    1405                 :            :         {
    1406                 :            :                 char *d;
    1407                 :            : 
    1408                 :            :                 for (d = fname; *d; d ++) if (*d == '/') *d = '\\';
    1409                 :            :         }
    1410                 :            : #endif
    1411         [ -  + ]:     112586 :         f = nex ? find_file_next(fname) : find_file(fname, string_fname);
    1412         [ +  + ]:     112586 :         if (!f) {
    1413                 :      49598 :                 current_filename = 0;
    1414                 :      49598 :                 pop_file_context(ls);
    1415         [ -  + ]:      49598 :                 if (find_file_error == FF_ERROR) {
    1416                 :          0 :                         error(l, "file '%s' not found", fname);
    1417                 :          0 :                         freemem(fname);
    1418                 :          0 :                         return 1;
    1419                 :            :                 }
    1420                 :            :                 /* file was found, but it is useless to include it again */
    1421                 :      49598 :                 freemem(fname);
    1422                 :      49598 :                 return 0;
    1423                 :            :         }
    1424                 :            : #ifdef UCPP_MMAP
    1425                 :            :         set_input_file(ls, f);
    1426                 :            : #else
    1427                 :      62988 :         ls->input = f;
    1428                 :            : #endif
    1429                 :      62988 :         current_filename = fname;
    1430                 :      62988 :         enter_file(ls, flags);
    1431                 :     112586 :         return 0;
    1432                 :            : 
    1433                 :            : #undef left_angle
    1434                 :            : #undef right_angle
    1435                 :            : }
    1436                 :            : 
    1437                 :            : /*
    1438                 :            :  * for #line directives
    1439                 :            :  */
    1440                 :          0 : static int handle_line(struct lexer_state *ls, unsigned long flags)
    1441                 :            : {
    1442                 :            :         char *fname;
    1443                 :          0 :         long l = ls->line;
    1444                 :            :         struct token_fifo tf, tf2, *save_tf;
    1445                 :            :         size_t nl, j;
    1446                 :            :         unsigned long z;
    1447                 :            : 
    1448                 :          0 :         tf.art = tf.nt = 0;
    1449 [ #  # ][ #  # ]:          0 :         while (!next_token(ls) && ls->ctok->type != NEWLINE) {
    1450 [ #  # ][ #  # ]:          0 :                 if (!ttMWS(ls->ctok->type)) {
                 [ #  # ]
    1451                 :            :                         struct token t;
    1452                 :            : 
    1453                 :          0 :                         t.type = ls->ctok->type;
    1454                 :          0 :                         t.line = l;
    1455 [ #  # ][ #  # ]:          0 :                         if (S_TOKEN(ls->ctok->type)) {
    1456                 :          0 :                                 t.name = sdup(ls->ctok->name);
    1457                 :          0 :                                 throw_away(ls->gf, t.name);
    1458                 :            :                         }
    1459 [ #  # ][ #  # ]:          0 :                         aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG);
    1460                 :            :                 }
    1461                 :            :         }
    1462                 :          0 :         tf2.art = tf2.nt = 0;
    1463                 :          0 :         save_tf = ls->output_fifo;
    1464                 :          0 :         ls->output_fifo = &tf2;
    1465         [ #  # ]:          0 :         while (tf.art < tf.nt) {
    1466                 :            :                 struct token *ct;
    1467                 :            : 
    1468                 :          0 :                 ct = tf.t + (tf.art ++);
    1469         [ #  # ]:          0 :                 if (ct->type == NAME) {
    1470                 :          0 :                         struct macro *m = get_macro(ct->name);
    1471         [ #  # ]:          0 :                         if (m) {
    1472         [ #  # ]:          0 :                                 if (substitute_macro(ls, m, &tf, 0,
    1473                 :            : #ifdef NO_PRAGMA_IN_DIRECTIVE
    1474                 :            :                                         1,
    1475                 :            : #else
    1476                 :            :                                         0,
    1477                 :            : #endif
    1478                 :            :                                         ct->line)) {
    1479                 :          0 :                                         ls->output_fifo = save_tf;
    1480                 :          0 :                                         return -1;
    1481                 :            :                                 }
    1482                 :          0 :                                 continue;
    1483                 :            :                         }
    1484                 :            :                 }
    1485 [ #  # ][ #  # ]:          0 :                 aol(tf2.t, tf2.nt, *ct, TOKEN_LIST_MEMG);
    1486                 :            :         }
    1487                 :          0 :         freemem(tf.t);
    1488 [ #  # ][ #  # ]:          0 :         for (tf2.art = 0; tf2.art < tf2.nt && ttWHI(tf2.t[tf2.art].type);
         [ #  # ][ #  # ]
                 [ #  # ]
    1489                 :          0 :                 tf2.art ++);
    1490                 :          0 :         ls->output_fifo = save_tf;
    1491 [ #  # ][ #  # ]:          0 :         if (tf2.art == tf2.nt || (tf2.t[tf2.art].type != NUMBER
    1492         [ #  # ]:          0 :                 && tf2.t[tf2.art].type != CHAR)) {
    1493                 :          0 :                 error(l, "not a valid number for #line");
    1494                 :          0 :                 goto line_macro_err;
    1495                 :            :         }
    1496         [ #  # ]:          0 :         for (j = 0; tf2.t[tf2.art].name[j]; j ++)
    1497         [ #  # ]:          0 :                 if (tf2.t[tf2.art].name[j] < '0'
    1498         [ #  # ]:          0 :                         || tf2.t[tf2.art].name[j] > '9')
    1499         [ #  # ]:          0 :                         if (ls->flags & WARN_STANDARD)
    1500                 :          0 :                                 warning(l, "non-standard line number in #line");
    1501         [ #  # ]:          0 :         if (catch(eval_exception)) goto line_macro_err;
    1502                 :          0 :         z = strtoconst(tf2.t[tf2.art].name);
    1503 [ #  # ][ #  # ]:          0 :         if (j > 10 || z > 2147483647U) {
    1504                 :          0 :                 error(l, "out-of-bound line number for #line");
    1505                 :          0 :                 goto line_macro_err;
    1506                 :            :         }
    1507                 :          0 :         ls->oline = ls->line = z;
    1508         [ #  # ]:          0 :         if ((++ tf2.art) < tf2.nt) {
    1509                 :            :                 size_t i;
    1510                 :            : 
    1511 [ #  # ][ #  # ]:          0 :                 for (i = tf2.art; i < tf2.nt && ttMWS(tf2.t[i].type); i ++);
         [ #  # ][ #  # ]
    1512         [ #  # ]:          0 :                 if (i < tf2.nt) {
    1513         [ #  # ]:          0 :                         if (tf2.t[i].type != STRING) {
    1514                 :          0 :                                 error(l, "not a valid filename for #line");
    1515                 :          0 :                                 goto line_macro_err;
    1516                 :            :                         }
    1517         [ #  # ]:          0 :                         if (tf2.t[i].name[0] == 'L') {
    1518         [ #  # ]:          0 :                                 if (ls->flags & WARN_STANDARD) {
    1519                 :          0 :                                         warning(l, "wide string for #line");
    1520                 :            :                                 }
    1521                 :          0 :                                 fname = sdup(tf2.t[i].name);
    1522                 :          0 :                                 nl = strlen(fname);
    1523                 :          0 :                                 *(fname + nl - 1) = 0;
    1524                 :          0 :                                 mmvwo(fname, fname + 2, nl - 2);
    1525                 :            :                         } else {
    1526                 :          0 :                                 fname = sdup(tf2.t[i].name);
    1527                 :          0 :                                 nl = strlen(fname);
    1528                 :          0 :                                 *(fname + nl - 1) = 0;
    1529                 :          0 :                                 mmvwo(fname, fname + 1, nl - 1);
    1530                 :            :                         }
    1531         [ #  # ]:          0 :                         if (current_filename) freemem(current_filename);
    1532                 :          0 :                         current_filename = fname;
    1533                 :            :                 }
    1534 [ #  # ][ #  # ]:          0 :                 for (i ++; i < tf2.nt && ttMWS(tf2.t[i].type); i ++);
         [ #  # ][ #  # ]
    1535 [ #  # ][ #  # ]:          0 :                 if (i < tf2.nt && (ls->flags & WARN_STANDARD)) {
    1536                 :          0 :                         warning(l, "trailing garbage in #line");
    1537                 :            :                 }
    1538                 :            :         }
    1539                 :          0 :         freemem(tf2.t);
    1540                 :          0 :         enter_file(ls, flags);
    1541                 :          0 :         return 0;
    1542                 :            : 
    1543                 :            : line_macro_err:
    1544         [ #  # ]:          0 :         if (tf2.nt) freemem(tf2.t);
    1545                 :          0 :         return 1;
    1546                 :            : }
    1547                 :            : 
    1548                 :            : /*
    1549                 :            :  * a #error directive: we emit the message without any modification
    1550                 :            :  * (except the usual backslash+newline and trigraphs)
    1551                 :            :  */
    1552                 :          0 : static void handle_error(struct lexer_state *ls)
    1553                 :            : {
    1554                 :            :         int c;
    1555                 :          0 :         size_t p = 0, lp = 128;
    1556                 :          0 :         long l = ls->line;
    1557                 :          0 :         unsigned char *buf = getmem(lp);
    1558                 :            : 
    1559 [ #  # ][ #  # ]:          0 :         while ((c = grap_char(ls)) >= 0 && c != '\n') {
    1560                 :          0 :                 discard_char(ls);
    1561         [ #  # ]:          0 :                 wan(buf, p, (unsigned char)c, lp);
    1562                 :            :         }
    1563         [ #  # ]:          0 :         wan(buf, p, 0, lp);
    1564                 :          0 :         error(l, "#error%s", buf);
    1565                 :          0 :         freemem(buf);
    1566                 :          0 : }
    1567                 :            : 
    1568                 :            : /*
    1569                 :            :  * convert digraph tokens to their standard equivalent.
    1570                 :            :  */
    1571                 :          0 : static int undig(int type)
    1572                 :            : {
    1573                 :            :         static int ud[6] = { LBRK, RBRK, LBRA, RBRA, SHARP, DSHARP };
    1574                 :            : 
    1575                 :          0 :         return ud[type - DIG_LBRK];
    1576                 :            : }
    1577                 :            : 
    1578                 :            : #ifdef PRAGMA_TOKENIZE
    1579                 :            : /*
    1580                 :            :  * Make a compressed representation of a token list; the contents of
    1581                 :            :  * the token_fifo are freed. Values equal to 0 are replaced by
    1582                 :            :  * PRAGMA_TOKEN_END (by default, (unsigned char)'\n') and the compressed
    1583                 :            :  * string is padded by a 0 (so that it may be * handled like a string).
    1584                 :            :  * Digraph tokens are replaced by their non-digraph equivalents.
    1585                 :            :  */
    1586                 :          0 : struct comp_token_fifo compress_token_list(struct token_fifo *tf)
    1587                 :            : {
    1588                 :            :         struct comp_token_fifo ct;
    1589                 :            :         size_t l;
    1590                 :            : 
    1591         [ #  # ]:          0 :         for (l = 0, tf->art = 0; tf->art < tf->nt; tf->art ++) {
    1592                 :          0 :                 l ++;
    1593 [ #  # ][ #  # ]:          0 :                 if (S_TOKEN(tf->t[tf->art].type))
    1594                 :          0 :                         l += strlen(tf->t[tf->art].name) + 1;
    1595                 :            :         }
    1596                 :          0 :         ct.t = getmem((ct.length = l) + 1);
    1597         [ #  # ]:          0 :         for (l = 0, tf->art = 0; tf->art < tf->nt; tf->art ++) {
    1598                 :          0 :                 int tt = tf->t[tf->art].type;
    1599                 :            : 
    1600         [ #  # ]:          0 :                 if (tt == 0) tt = PRAGMA_TOKEN_END;
    1601 [ #  # ][ #  # ]:          0 :                 if (tt > DIGRAPH_TOKENS && tt < DIGRAPH_TOKENS_END)
    1602                 :          0 :                         tt = undig(tt);
    1603                 :          0 :                 ct.t[l ++] = tt;
    1604 [ #  # ][ #  # ]:          0 :                 if (S_TOKEN(tt)) {
    1605                 :          0 :                         char *tn = tf->t[tf->art].name;
    1606                 :          0 :                         size_t sl = strlen(tn);
    1607                 :            : 
    1608                 :          0 :                         mmv(ct.t + l, tn, sl);
    1609                 :          0 :                         l += sl;
    1610                 :          0 :                         ct.t[l ++] = PRAGMA_TOKEN_END;
    1611                 :          0 :                         freemem(tn);
    1612                 :            :                 }
    1613                 :            :         }
    1614                 :          0 :         ct.t[l] = 0;
    1615         [ #  # ]:          0 :         if (tf->nt) freemem(tf->t);
    1616                 :          0 :         ct.rp = 0;
    1617                 :          0 :         return ct;
    1618                 :            : }
    1619                 :            : #endif
    1620                 :            : 
    1621                 :            : /*
    1622                 :            :  * A #pragma directive: we make a PRAGMA token containing the rest of
    1623                 :            :  * the line.
    1624                 :            :  *
    1625                 :            :  * We strongly hope that we are called only in LEXER mode.
    1626                 :            :  */
    1627                 :          0 : static void handle_pragma(struct lexer_state *ls)
    1628                 :            : {
    1629                 :            :         unsigned char *buf;
    1630                 :            :         struct token t;
    1631                 :          0 :         long l = ls->line;
    1632                 :            : 
    1633                 :            : #ifdef PRAGMA_TOKENIZE
    1634                 :            :         struct token_fifo tf;
    1635                 :            : 
    1636                 :          0 :         tf.art = tf.nt = 0;
    1637 [ #  # ][ #  # ]:          0 :         while (!next_token(ls) && ls->ctok->type != NEWLINE)
    1638 [ #  # ][ #  # ]:          0 :                 if (!ttMWS(ls->ctok->type)) break;
                 [ #  # ]
    1639         [ #  # ]:          0 :         if (ls->ctok->type != NEWLINE) {
    1640                 :            :                 do {
    1641                 :            :                         struct token t;
    1642                 :            : 
    1643                 :          0 :                         t.type = ls->ctok->type;
    1644 [ #  # ][ #  # ]:          0 :                         if (ttMWS(t.type)) continue;
                 [ #  # ]
    1645 [ #  # ][ #  # ]:          0 :                         if (S_TOKEN(t.type)) t.name = sdup(ls->ctok->name);
    1646 [ #  # ][ #  # ]:          0 :                         aol(tf.t, tf.nt, t, TOKEN_LIST_MEMG);
    1647 [ #  # ][ #  # ]:          0 :                 } while (!next_token(ls) && ls->ctok->type != NEWLINE);
    1648                 :            :         }
    1649         [ #  # ]:          0 :         if (tf.nt == 0) {
    1650                 :            :                 /* void pragma are silently ignored */
    1651                 :          0 :                 return;
    1652                 :            :         }
    1653                 :          0 :         buf = (compress_token_list(&tf)).t;
    1654                 :            : #else
    1655                 :            :         int c, x = 1, y = 32;
    1656                 :            : 
    1657                 :            :         while ((c = grap_char(ls)) >= 0 && c != '\n') {
    1658                 :            :                 discard_char(ls);
    1659                 :            :                 if (!space_char(c)) break;
    1660                 :            :         }
    1661                 :            :         /* void #pragma are ignored */
    1662                 :            :         if (c == '\n') return;
    1663                 :            :         buf = getmem(y);
    1664                 :            :         buf[0] = c;
    1665                 :            :         while ((c = grap_char(ls)) >= 0 && c != '\n') {
    1666                 :            :                 discard_char(ls);
    1667                 :            :                 wan(buf, x, c, y);
    1668                 :            :         }
    1669                 :            :         for (x --; x >= 0 && space_char(buf[x]); x --);
    1670                 :            :         x ++;
    1671                 :            :         wan(buf, x, 0, y);
    1672                 :            : #endif
    1673                 :          0 :         t.type = PRAGMA;
    1674                 :          0 :         t.line = l;
    1675                 :          0 :         t.name = (char *)buf;
    1676 [ #  # ][ #  # ]:          0 :         aol(ls->output_fifo->t, ls->output_fifo->nt, t, TOKEN_LIST_MEMG);
    1677                 :          0 :         throw_away(ls->gf, (char *)buf);
    1678                 :            : }
    1679                 :            : 
    1680                 :            : /*
    1681                 :            :  * We saw a # at the beginning of a line (or preceeded only by whitespace).
    1682                 :            :  * We check the directive name and act accordingly.
    1683                 :            :  */
    1684                 :     317537 : static int handle_cpp(struct lexer_state *ls, int sharp_type)
    1685                 :            : {
    1686                 :            : #define condfset(x)     do { \
    1687                 :            :                 ls->condf[(x) / 32] |= 1UL << ((x) % 32); \
    1688                 :            :         } while (0)
    1689                 :            : #define condfclr(x)     do { \
    1690                 :            :                 ls->condf[(x) / 32] &= ~(1UL << ((x) % 32)); \
    1691                 :            :         } while (0)
    1692                 :            : #define condfval(x)     ((ls->condf[(x) / 32] & (1UL << ((x) % 32))) != 0)
    1693                 :            : 
    1694                 :     317537 :         long l = ls->line;
    1695                 :     317537 :         unsigned long save_flags = ls->flags;
    1696                 :     317537 :         int ret = 0;
    1697                 :            : 
    1698                 :     317537 :         save_flags = ls->flags;
    1699                 :     317537 :         ls->flags |= LEXER;
    1700         [ +  - ]:     317537 :         while (!next_token(ls)) {
    1701                 :     317537 :                 int t = ls->ctok->type;
    1702                 :            : 
    1703   [ -  -  -  +  :     317537 :                 switch (t) {
                      - ]
    1704                 :            :                 case COMMENT:
    1705         [ #  # ]:          0 :                         if (ls->flags & WARN_ANNOYING) {
    1706                 :          0 :                                 warning(l, "comment in the middle of "
    1707                 :            :                                         "a cpp directive");
    1708                 :            :                         }
    1709                 :            :                         /* fall through */
    1710                 :            :                 case NONE:
    1711                 :          0 :                         continue;
    1712                 :            :                 case NEWLINE:
    1713                 :            :                         /* null directive */
    1714         [ #  # ]:          0 :                         if (ls->flags & WARN_ANNOYING) {
    1715                 :            :                                 /* truly an annoying warning; null directives
    1716                 :            :                                    are rare but may increase readability of
    1717                 :            :                                    some source files, and they are legal */
    1718                 :          0 :                                 warning(l, "null cpp directive");
    1719                 :            :                         }
    1720         [ #  # ]:          0 :                         if (!(ls->flags & LEXER)) put_char(ls, '\n');
    1721                 :          0 :                         goto handle_exit2;
    1722                 :            :                 case NAME:
    1723                 :     317537 :                         break;
    1724                 :            :                 default:
    1725         [ #  # ]:          0 :                         if (ls->flags & FAIL_SHARP) {
    1726                 :            :                                 /* LPS 20050602 - ignores '#!' if on the first line */
    1727 [ #  # ][ #  # ]:          0 :                                 if( ( l == 1 ) &&
    1728                 :          0 :                                     ( ls->condcomp ) )
    1729                 :            :                                 {
    1730                 :          0 :                                         ret = 1;
    1731                 :            :                                 }
    1732                 :            :                                 else
    1733                 :            :                                 /* LPS 20050602 */
    1734         [ #  # ]:          0 :                                 if (ls->condcomp) {
    1735                 :          0 :                                         error(l, "rogue '#'");
    1736                 :          0 :                                         ret = 1;
    1737                 :            :                                 } else {
    1738         [ #  # ]:          0 :                                         if (ls->flags & WARN_STANDARD) {
    1739                 :          0 :                                                 warning(l, "rogue '#' in code "
    1740                 :            :                                                         "compiled out");
    1741                 :          0 :                                                 ret = 0;
    1742                 :            :                                         }
    1743                 :            :                                 }
    1744                 :          0 :                                 ls->flags = save_flags;
    1745                 :          0 :                                 goto handle_warp_ign;
    1746                 :            :                         } else {
    1747                 :            :                                 struct token u;
    1748                 :            : 
    1749                 :          0 :                                 u.type = sharp_type;
    1750                 :          0 :                                 u.line = l;
    1751                 :          0 :                                 ls->flags = save_flags;
    1752                 :          0 :                                 print_token(ls, &u, 0);
    1753                 :          0 :                                 print_token(ls, ls->ctok, 0);
    1754         [ #  # ]:          0 :                                 if (ls->flags & WARN_ANNOYING) {
    1755                 :          0 :                                         warning(l, "rogue '#' dumped");
    1756                 :            :                                 }
    1757                 :            :                                 goto handle_exit3;
    1758                 :            :                         }
    1759                 :            :                 }
    1760         [ +  + ]:     317537 :                 if (ls->condcomp) {
    1761         [ +  + ]:     317273 :                         if (!strcmp(ls->ctok->name, "define")) {
    1762                 :      68136 :                                 ret = handle_define(ls);
    1763                 :      68136 :                                 goto handle_exit;
    1764         [ -  + ]:     249137 :                         } else if (!strcmp(ls->ctok->name, "undef")) {
    1765                 :          0 :                                 ret = handle_undef(ls);
    1766                 :          0 :                                 goto handle_exit;
    1767         [ +  + ]:     249137 :                         } else if (!strcmp(ls->ctok->name, "if")) {
    1768         [ -  + ]:          2 :                                 if ((++ ls->ifnest) > 63) goto too_many_if;
    1769                 :          2 :                                 condfclr(ls->ifnest - 1);
    1770                 :          2 :                                 ret = handle_if(ls);
    1771         [ -  + ]:          2 :                                 if (ret > 0) ret = 0;
    1772         [ +  - ]:          2 :                                 else if (ret == 0) {
    1773                 :          2 :                                         ls->condcomp = 0;
    1774                 :          2 :                                         ls->condmet = 0;
    1775                 :          2 :                                         ls->condnest = ls->ifnest - 1;
    1776                 :            :                                 }
    1777                 :          0 :                                 else ret = 1;
    1778                 :          2 :                                 goto handle_exit;
    1779         [ -  + ]:     249135 :                         } else if (!strcmp(ls->ctok->name, "ifdef")) {
    1780         [ #  # ]:          0 :                                 if ((++ ls->ifnest) > 63) goto too_many_if;
    1781                 :          0 :                                 condfclr(ls->ifnest - 1);
    1782                 :          0 :                                 ret = handle_ifdef(ls);
    1783         [ #  # ]:          0 :                                 if (ret > 0) ret = 0;
    1784         [ #  # ]:          0 :                                 else if (ret == 0) {
    1785                 :          0 :                                         ls->condcomp = 0;
    1786                 :          0 :                                         ls->condmet = 0;
    1787                 :          0 :                                         ls->condnest = ls->ifnest - 1;
    1788                 :            :                                 }
    1789                 :          0 :                                 else ret = 1;
    1790                 :          0 :                                 goto handle_exit;
    1791         [ +  + ]:     249135 :                         } else if (!strcmp(ls->ctok->name, "ifndef")) {
    1792         [ -  + ]:      68340 :                                 if ((++ ls->ifnest) > 63) goto too_many_if;
    1793                 :      68340 :                                 condfclr(ls->ifnest - 1);
    1794                 :      68340 :                                 ret = handle_ifndef(ls);
    1795         [ +  + ]:      68340 :                                 if (ret > 0) ret = 0;
    1796         [ +  - ]:        131 :                                 else if (ret == 0) {
    1797                 :        131 :                                         ls->condcomp = 0;
    1798                 :        131 :                                         ls->condmet = 0;
    1799                 :        131 :                                         ls->condnest = ls->ifnest - 1;
    1800                 :            :                                 }
    1801                 :          0 :                                 else ret = 1;
    1802                 :      68340 :                                 goto handle_exit;
    1803         [ -  + ]:     180795 :                         } else if (!strcmp(ls->ctok->name, "else")) {
    1804         [ #  # ]:          0 :                                 if (ls->ifnest == 0
    1805         [ #  # ]:          0 :                                         || condfval(ls->ifnest - 1)) {
    1806                 :          0 :                                         error(l, "rogue #else");
    1807                 :          0 :                                         ret = 1;
    1808                 :          0 :                                         goto handle_warp;
    1809                 :            :                                 }
    1810                 :          0 :                                 condfset(ls->ifnest - 1);
    1811         [ #  # ]:          0 :                                 if (ls->ifnest == 1) protect_detect.state = 0;
    1812                 :          0 :                                 ls->condcomp = 0;
    1813                 :          0 :                                 ls->condmet = 1;
    1814                 :          0 :                                 ls->condnest = ls->ifnest - 1;
    1815                 :          0 :                                 goto handle_warp;
    1816         [ -  + ]:     180795 :                         } else if (!strcmp(ls->ctok->name, "elif")) {
    1817         [ #  # ]:          0 :                                 if (ls->ifnest == 0
    1818         [ #  # ]:          0 :                                         || condfval(ls->ifnest - 1)) {
    1819                 :          0 :                                         error(l, "rogue #elif");
    1820                 :          0 :                                         ret = 1;
    1821                 :          0 :                                         goto handle_warp_ign;
    1822                 :            :                                 }
    1823         [ #  # ]:          0 :                                 if (ls->ifnest == 1) protect_detect.state = 0;
    1824                 :          0 :                                 ls->condcomp = 0;
    1825                 :          0 :                                 ls->condmet = 1;
    1826                 :          0 :                                 ls->condnest = ls->ifnest - 1;
    1827                 :          0 :                                 goto handle_warp_ign;
    1828         [ +  + ]:     180795 :                         } else if (!strcmp(ls->ctok->name, "endif")) {
    1829         [ -  + ]:      68209 :                                 if (ls->ifnest == 0) {
    1830                 :          0 :                                         error(l, "unmatched #endif");
    1831                 :          0 :                                         ret = 1;
    1832                 :          0 :                                         goto handle_warp;
    1833                 :            :                                 }
    1834         [ +  + ]:      68209 :                                 if ((-- ls->ifnest) == 0
    1835         [ +  + ]:      68138 :                                         && protect_detect.state == 2) {
    1836                 :      68137 :                                         protect_detect.state = 3;
    1837                 :            :                                 }
    1838                 :      68209 :                                 goto handle_warp;
    1839         [ +  - ]:     112586 :                         } else if (!strcmp(ls->ctok->name, "include")) {
    1840                 :     112586 :                                 ret = handle_include(ls, save_flags, 0);
    1841                 :     112586 :                                 goto handle_exit3;
    1842         [ #  # ]:          0 :                         } else if (!strcmp(ls->ctok->name, "include_next")) {
    1843                 :          0 :                                 ret = handle_include(ls, save_flags, 1);
    1844                 :          0 :                                 goto handle_exit3;
    1845         [ #  # ]:          0 :                         } else if (!strcmp(ls->ctok->name, "pragma")) {
    1846         [ #  # ]:          0 :                                 if (!(save_flags & LEXER)) {
    1847                 :            : #ifdef PRAGMA_DUMP
    1848                 :            :                                         /* dump #pragma in output */
    1849                 :            :                                         struct token u;
    1850                 :            : 
    1851                 :          0 :                                         u.type = sharp_type;
    1852                 :          0 :                                         u.line = l;
    1853                 :          0 :                                         ls->flags = save_flags;
    1854                 :          0 :                                         print_token(ls, &u, 0);
    1855                 :          0 :                                         print_token(ls, ls->ctok, 0);
    1856         [ #  # ]:          0 :                                         while (ls->flags |= LEXER,
    1857                 :          0 :                                                 !next_token(ls)) {
    1858                 :            :                                                 long save_line;
    1859                 :            : 
    1860                 :          0 :                                                 ls->flags &= ~LEXER;
    1861                 :          0 :                                                 save_line = ls->line;
    1862                 :          0 :                                                 ls->line = l;
    1863                 :          0 :                                                 print_token(ls, ls->ctok, 0);
    1864                 :          0 :                                                 ls->line = save_line;
    1865         [ #  # ]:          0 :                                                 if (ls->ctok->type == NEWLINE)
    1866                 :          0 :                                                         break;
    1867                 :            :                                         }
    1868                 :            :                                         goto handle_exit3;
    1869                 :            : #else
    1870                 :            :                                         if (ls->flags & WARN_PRAGMA)
    1871                 :            :                                                 warning(l, "#pragma ignored "
    1872                 :            :                                                         "and not dumped");
    1873                 :            :                                         goto handle_warp_ign;
    1874                 :            : #endif
    1875                 :            :                                 }
    1876         [ #  # ]:          0 :                                 if (!(ls->flags & HANDLE_PRAGMA))
    1877                 :          0 :                                         goto handle_warp_ign;
    1878                 :          0 :                                 handle_pragma(ls);
    1879                 :          0 :                                 goto handle_exit;
    1880         [ #  # ]:          0 :                         } else if (!strcmp(ls->ctok->name, "error")) {
    1881                 :          0 :                                 ret = 1;
    1882                 :          0 :                                 handle_error(ls);
    1883                 :          0 :                                 goto handle_exit;
    1884         [ #  # ]:          0 :                         } else if (!strcmp(ls->ctok->name, "line")) {
    1885                 :          0 :                                 ret = handle_line(ls, save_flags);
    1886                 :          0 :                                 goto handle_exit;
    1887         [ #  # ]:          0 :                         } else if ((ls->flags & HANDLE_ASSERTIONS)
    1888         [ #  # ]:          0 :                                 && !strcmp(ls->ctok->name, "assert")) {
    1889                 :          0 :                                 ret = handle_assert(ls);
    1890                 :          0 :                                 goto handle_exit;
    1891         [ #  # ]:          0 :                         } else if ((ls->flags & HANDLE_ASSERTIONS)
    1892         [ #  # ]:          0 :                                 && !strcmp(ls->ctok->name, "unassert")) {
    1893                 :          0 :                                 ret = handle_unassert(ls);
    1894                 :          0 :                                 goto handle_exit;
    1895                 :            :                         }
    1896                 :            :                 } else {
    1897         [ -  + ]:        264 :                         if (!strcmp(ls->ctok->name, "else")) {
    1898         [ #  # ]:          0 :                                 if (condfval(ls->ifnest - 1)
    1899         [ #  # ]:          0 :                                         && (ls->flags & WARN_STANDARD)) {
    1900                 :          0 :                                         warning(l, "rogue #else in code "
    1901                 :            :                                                 "compiled out");
    1902                 :            :                                 }
    1903         [ #  # ]:          0 :                                 if (ls->condnest == ls->ifnest - 1) {
    1904         [ #  # ]:          0 :                                         if (!ls->condmet) ls->condcomp = 1;
    1905                 :            :                                 }
    1906                 :          0 :                                 condfset(ls->ifnest - 1);
    1907         [ #  # ]:          0 :                                 if (ls->ifnest == 1) protect_detect.state = 0;
    1908                 :          0 :                                 goto handle_warp;
    1909         [ -  + ]:        264 :                         } else if (!strcmp(ls->ctok->name, "elif")) {
    1910         [ #  # ]:          0 :                                 if (condfval(ls->ifnest - 1)
    1911         [ #  # ]:          0 :                                         && (ls->flags & WARN_STANDARD)) {
    1912                 :          0 :                                         warning(l, "rogue #elif in code "
    1913                 :            :                                                 "compiled out");
    1914                 :            :                                 }
    1915         [ #  # ]:          0 :                                 if (ls->condnest != ls->ifnest - 1
    1916         [ #  # ]:          0 :                                         || ls->condmet)
    1917                 :            :                                         goto handle_warp_ign;
    1918         [ #  # ]:          0 :                                 if (ls->ifnest == 1) protect_detect.state = 0;
    1919                 :          0 :                                 ret = handle_if(ls);
    1920         [ #  # ]:          0 :                                 if (ret > 0) {
    1921                 :          0 :                                         ls->condcomp = 1;
    1922                 :          0 :                                         ls->condmet = 1;
    1923                 :          0 :                                         ret = 0;
    1924         [ #  # ]:          0 :                                 } else if (ret < 0) ret = 1;
    1925                 :          0 :                                 goto handle_exit;
    1926         [ +  + ]:        264 :                         } else if (!strcmp(ls->ctok->name, "endif")) {
    1927         [ +  - ]:        133 :                                 if ((-- ls->ifnest) == ls->condnest) {
    1928 [ +  + ][ -  + ]:        133 :                                         if (ls->ifnest == 0 &&
    1929                 :          2 :                                                 protect_detect.state == 2)
    1930                 :          0 :                                                 protect_detect.state = 3;
    1931                 :        133 :                                         ls->condcomp = 1;
    1932                 :            :                                 }
    1933                 :        133 :                                 goto handle_warp;
    1934         [ +  - ]:        131 :                         } else if (!strcmp(ls->ctok->name, "if")
    1935         [ +  - ]:        131 :                                 || !strcmp(ls->ctok->name, "ifdef")
    1936         [ -  + ]:        131 :                                 || !strcmp(ls->ctok->name, "ifndef")) {
    1937         [ #  # ]:          0 :                                 if ((++ ls->ifnest) > 63) goto too_many_if;
    1938                 :          0 :                                 condfclr(ls->ifnest - 1);
    1939                 :            :                         }
    1940                 :        131 :                         goto handle_warp_ign;
    1941                 :            :                 }
    1942                 :            :                 /*
    1943                 :            :                  * Unrecognized directive. We emit either an error or
    1944                 :            :                  * an annoying warning, depending on a command-line switch.
    1945                 :            :                  */
    1946         [ #  # ]:          0 :                 if (ls->flags & FAIL_SHARP) {
    1947                 :          0 :                         error(l, "unknown cpp directive '#%s'",
    1948                 :          0 :                                 ls->ctok->name);
    1949                 :          0 :                         goto handle_warp_ign;
    1950                 :            :                 } else {
    1951                 :            :                         struct token u;
    1952                 :            : 
    1953                 :          0 :                         u.type = sharp_type;
    1954                 :          0 :                         u.line = l;
    1955                 :          0 :                         ls->flags = save_flags;
    1956                 :          0 :                         print_token(ls, &u, 0);
    1957                 :          0 :                         print_token(ls, ls->ctok, 0);
    1958         [ #  # ]:          0 :                         if (ls->flags & WARN_ANNOYING) {
    1959                 :          0 :                                 warning(l, "rogue '#' dumped");
    1960                 :            :                         }
    1961                 :            :                 }
    1962                 :            :         }
    1963                 :          0 :         return 1;
    1964                 :            : 
    1965                 :            : handle_warp_ign:
    1966 [ +  + ][ +  - ]:       1969 :         while (!next_token(ls)) if (ls->ctok->type == NEWLINE) break;
    1967                 :        131 :         goto handle_exit;
    1968                 :            : handle_warp:
    1969         [ +  - ]:      68342 :         while (!next_token(ls)) {
    1970 [ +  - ][ +  - ]:      68342 :                 if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD)) {
         [ +  - ][ -  + ]
                 [ #  # ]
    1971                 :          0 :                         warning(l, "trailing garbage in "
    1972                 :            :                                 "preprocessing directive");
    1973                 :            :                 }
    1974         [ +  - ]:      68342 :                 if (ls->ctok->type == NEWLINE) break;
    1975                 :            :         }
    1976                 :            : handle_exit:
    1977         [ -  + ]:     204951 :         if (!(ls->flags & LEXER)) put_char(ls, '\n');
    1978                 :            : handle_exit3:
    1979         [ +  + ]:     317537 :         if (protect_detect.state == 1) {
    1980                 :          3 :                 protect_detect.state = 0;
    1981         [ +  + ]:     317534 :         } else if (protect_detect.state == -1) {
    1982                 :            :                 /* just after the #include */
    1983                 :      62988 :                 protect_detect.state = 1;
    1984                 :            :         }
    1985                 :            : handle_exit2:
    1986                 :     317537 :         ls->flags = save_flags;
    1987                 :     317537 :         return ret;
    1988                 :            : too_many_if:
    1989                 :          0 :         error(l, "too many levels of conditional inclusion (max 63)");
    1990                 :          0 :         ret = 1;
    1991                 :     317537 :         goto handle_warp;
    1992                 :            : #undef condfset
    1993                 :            : #undef condfclr
    1994                 :            : #undef condfval
    1995                 :            : }
    1996                 :            : 
    1997                 :            : /*
    1998                 :            :  * This is the main entry function. It maintains count of #, and call the
    1999                 :            :  * appropriate functions when it encounters a cpp directive or a macro
    2000                 :            :  * name.
    2001                 :            :  * return value: positive on error; CPPERR_EOF means "end of input reached"
    2002                 :            :  */
    2003                 :   11727374 : int cpp(struct lexer_state *ls)
    2004                 :            : {
    2005                 :   11727374 :         int r = 0;
    2006                 :            : 
    2007         [ +  + ]:   11790362 :         while (next_token(ls)) {
    2008         [ +  + ]:      68966 :                 if (protect_detect.state == 3) {
    2009                 :            :                         /*
    2010                 :            :                          * At that point, protect_detect.ff->protect might
    2011                 :            :                          * be non-zero, if the file has been recursively
    2012                 :            :                          * included, and a guardian detected.
    2013                 :            :                          */
    2014         [ +  - ]:      68136 :                         if (!protect_detect.ff->protect) {
    2015                 :            :                                 /* Cool ! A new guardian has been detected. */
    2016                 :      68136 :                                 protect_detect.ff->protect =
    2017                 :      68136 :                                         protect_detect.macro;
    2018         [ #  # ]:          0 :                         } else if (protect_detect.macro) {
    2019                 :            :                                 /* We found a guardian but an old one. */
    2020                 :          0 :                                 freemem(protect_detect.macro);
    2021                 :            :                         }
    2022                 :      68136 :                         protect_detect.macro = 0;
    2023                 :            :                 }
    2024         [ -  + ]:      68966 :                 if (ls->ifnest) {
    2025                 :          0 :                         error(ls->line, "unterminated #if construction "
    2026                 :            :                                 "(depth %ld)", ls->ifnest);
    2027                 :          0 :                         r = CPPERR_NEST;
    2028                 :            :                 }
    2029         [ +  + ]:      68966 :                 if (ls_depth == 0) return CPPERR_EOF;
    2030                 :      62988 :                 close_input(ls);
    2031 [ -  + ][ +  - ]:      62988 :                 if (!(ls->flags & LEXER) && !ls->ltwnl) {
    2032                 :          0 :                         put_char(ls, '\n');
    2033                 :          0 :                         ls->ltwnl = 1;
    2034                 :            :                 }
    2035                 :      62988 :                 pop_file_context(ls);
    2036                 :      62988 :                 ls->oline ++;
    2037         [ -  + ]:      62988 :                 if (enter_file(ls, ls->flags)) {
    2038                 :          0 :                         ls->ctok->type = NEWLINE;
    2039                 :          0 :                         ls->ltwnl = 1;
    2040                 :          0 :                         break;
    2041                 :            :                 }
    2042                 :            :         }
    2043 [ +  + ][ +  + ]:   11721396 :         if (!(ls->ltwnl && (ls->ctok->type == SHARP
    2044         [ +  - ]:    3784035 :                 || ls->ctok->type == DIG_SHARP))
    2045 [ +  + ][ +  + ]:   11403859 :                 && protect_detect.state == 1 && !ttWHI(ls->ctok->type)) {
         [ +  + ][ +  - ]
                 [ +  + ]
    2046                 :            :                 /* the first non-whitespace token encountered is not
    2047                 :            :                    a sharp introducing a cpp directive */
    2048                 :        826 :                 protect_detect.state = 0;
    2049                 :            :         }
    2050 [ +  + ][ +  - ]:   11721396 :         if (protect_detect.state == 3 && !ttWHI(ls->ctok->type)) {
         [ +  + ][ +  - ]
                 [ +  + ]
    2051                 :            :                 /* a non-whitespace token encountered after the #endif */
    2052                 :          1 :                 protect_detect.state = 0;
    2053                 :            :         }
    2054         [ +  + ]:   11721396 :         if (ls->condcomp) {
    2055 [ +  + ][ +  + ]:   11721091 :                 if (ls->ltwnl && (ls->ctok->type == SHARP
    2056         [ -  + ]:    3784024 :                         || ls->ctok->type == DIG_SHARP)) {
    2057                 :     317273 :                         int x = handle_cpp(ls, ls->ctok->type);
    2058                 :            : 
    2059                 :     317273 :                         ls->ltwnl = 1;
    2060         [ -  + ]:     317273 :                         return r ? r : x;
    2061                 :            :                 }
    2062         [ +  + ]:   11403818 :                 if (ls->ctok->type == NAME) {
    2063                 :            :                         struct macro *m;
    2064                 :            : 
    2065         [ -  + ]:    2415999 :                         if ((m = get_macro(ls->ctok->name)) != 0) {
    2066                 :            :                                 int x;
    2067                 :            : 
    2068                 :          0 :                                 x = substitute_macro(ls, m, 0, 1, 0,
    2069                 :          0 :                                         ls->ctok->line);
    2070         [ #  # ]:          0 :                                 if (!(ls->flags & LEXER))
    2071                 :          0 :                                         garbage_collect(ls->gf);
    2072         [ #  # ]:          0 :                                 return r ? r : x;
    2073                 :            :                         }
    2074         [ +  - ]:    2415999 :                         if (!(ls->flags & LEXER))
    2075                 :    2415999 :                                 print_token(ls, ls->ctok, 0);
    2076                 :            :                 }
    2077                 :            :         } else {
    2078 [ +  + ][ +  + ]:        305 :                 if (ls->ltwnl && (ls->ctok->type == SHARP
    2079         [ -  + ]:         11 :                         || ls->ctok->type == DIG_SHARP)) {
    2080                 :        264 :                         int x = handle_cpp(ls, ls->ctok->type);
    2081                 :            : 
    2082                 :        264 :                         ls->ltwnl = 1;
    2083         [ -  + ]:        264 :                         return r ? r : x;
    2084                 :            :                 }
    2085                 :            :         }
    2086         [ +  + ]:   11403859 :         if (ls->ctok->type == NEWLINE) ls->ltwnl = 1;
    2087 [ +  + ][ +  + ]:    9004255 :         else if (!ttWHI(ls->ctok->type)) ls->ltwnl = 0;
         [ +  - ][ +  - ]
    2088         [ -  + ]:   11727374 :         return r ? r : -1;
    2089                 :            : }
    2090                 :            : 
    2091                 :            : #ifndef STAND_ALONE
    2092                 :            : /*
    2093                 :            :  * llex() and lex() are the lexing functions, when the preprocessor is
    2094                 :            :  * linked to another code. llex() should be called only by lex().
    2095                 :            :  */
    2096                 :            : static int llex(struct lexer_state *ls)
    2097                 :            : {
    2098                 :            :         struct token_fifo *tf = ls->output_fifo;
    2099                 :            :         int r;
    2100                 :            : 
    2101                 :            :         if (tf->nt != 0) {
    2102                 :            :                 if (tf->art < tf->nt) {
    2103                 :            : #ifdef INMACRO_FLAG
    2104                 :            :                         if (!ls->inmacro) {
    2105                 :            :                                 ls->inmacro = 1;
    2106                 :            :                                 ls->macro_count ++;
    2107                 :            :                         }
    2108                 :            : #endif
    2109                 :            :                         ls->ctok = tf->t + (tf->art ++);
    2110                 :            :                         if (ls->ctok->type > DIGRAPH_TOKENS
    2111                 :            :                                 && ls->ctok->type < DIGRAPH_TOKENS_END) {
    2112                 :            :                                 ls->ctok->type = undig(ls->ctok->type);
    2113                 :            :                         }
    2114                 :            :                         return 0;
    2115                 :            :                 } else {
    2116                 :            : #ifdef INMACRO_FLAG
    2117                 :            :                         ls->inmacro = 0;
    2118                 :            : #endif
    2119                 :            :                         freemem(tf->t);
    2120                 :            :                         tf->art = tf->nt = 0;
    2121                 :            :                         garbage_collect(ls->gf);
    2122                 :            :                         ls->ctok = ls->save_ctok;
    2123                 :            :                 }
    2124                 :            :         }
    2125                 :            :         r = cpp(ls);
    2126                 :            :         if (ls->ctok->type > DIGRAPH_TOKENS
    2127                 :            :                 && ls->ctok->type < LAST_MEANINGFUL_TOKEN) {
    2128                 :            :                 ls->ctok->type = undig(ls->ctok->type);
    2129                 :            :         }
    2130                 :            :         if (r > 0) return r;
    2131                 :            :         if (r < 0) return 0;
    2132                 :            :         return llex(ls);
    2133                 :            : }
    2134                 :            : 
    2135                 :            : /*
    2136                 :            :  * lex() reads the next token from the processed stream and stores it
    2137                 :            :  * into ls->ctok.
    2138                 :            :  * return value: non zero on error (including CPPERR_EOF, which is not
    2139                 :            :  * quite an error)
    2140                 :            :  */
    2141                 :            : int lex(struct lexer_state *ls)
    2142                 :            : {
    2143                 :            :         int r;
    2144                 :            : 
    2145                 :            :         do {
    2146                 :            :                 r = llex(ls);
    2147                 :            : #ifdef SEMPER_FIDELIS
    2148                 :            :         } while (!r && !ls->condcomp);
    2149                 :            : #else
    2150                 :            :         } while (!r && (!ls->condcomp || (ttWHI(ls->ctok->type) &&
    2151                 :            :                 (!(ls->flags & LINE_NUM) || ls->ctok->type != NEWLINE))));
    2152                 :            : #endif
    2153                 :            :         return r;
    2154                 :            : }
    2155                 :            : #endif
    2156                 :            : 
    2157                 :            : /*
    2158                 :            :  * check_cpp_errors() must be called when the end of input is reached;
    2159                 :            :  * it checks pending errors due to truncated constructs (actually none,
    2160                 :            :  * this is reserved for future evolutions).
    2161                 :            :  */
    2162                 :       5978 : int check_cpp_errors(struct lexer_state *ls)
    2163                 :            : {
    2164         [ +  - ]:       5978 :         if (ls->flags & KEEP_OUTPUT) {
    2165                 :       5978 :                 put_char(ls, '\n');
    2166                 :            :         }
    2167         [ -  + ]:       5978 :         if (emit_dependencies) fputc('\n', emit_output);
    2168                 :            : #ifndef NO_UCPP_BUF
    2169                 :            :         if (!(ls->flags & LEXER)) {
    2170                 :            :                 flush_output(ls);
    2171                 :            :         }
    2172                 :            : #endif
    2173 [ -  + ][ #  # ]:       5978 :         if ((ls->flags & WARN_TRIGRAPHS) && ls->count_trigraphs)
    2174                 :          0 :                 warning(0, "%ld trigraph(s) encountered", ls->count_trigraphs);
    2175                 :       5978 :         return 0;
    2176                 :            : }
    2177                 :            : 
    2178                 :            : /*
    2179                 :            :  * init_cpp() initializes static tables inside ucpp. It needs not be
    2180                 :            :  * called more than once.
    2181                 :            :  */
    2182                 :       5978 : void init_cpp(void)
    2183                 :            : {
    2184                 :       5978 :         init_cppm();
    2185                 :       5978 : }
    2186                 :            : 
    2187                 :            : /*
    2188                 :            :  * (re)init the global tables.
    2189                 :            :  * If standard_assertions is non 0, init the assertions table.
    2190                 :            :  */
    2191                 :       5978 : void init_tables(int with_assertions)
    2192                 :            : {
    2193                 :            :         time_t t;
    2194                 :            :         struct tm *ct;
    2195                 :            : 
    2196                 :       5978 :         init_buf_lexer_state(&dsharp_lexer, 0);
    2197                 :            : #ifdef PRAGMA_TOKENIZE
    2198                 :       5978 :         init_buf_lexer_state(&tokenize_lexer, 0);
    2199                 :            : #endif
    2200                 :       5978 :         time(&t);
    2201                 :       5978 :         ct = localtime(&t);
    2202                 :            : #ifdef NOSTRFTIME
    2203                 :            :         /* we have a quite old compiler, that does not know the
    2204                 :            :            (standard since 1990) strftime() function. */
    2205                 :            :         {
    2206                 :            :                 char *c = asctime(ct);
    2207                 :            : 
    2208                 :            :                 compile_time[0] = '"';
    2209                 :            :                 mmv(compile_time + 1, c + 11, 8);
    2210                 :            :                 compile_time[9] = '"';
    2211                 :            :                 compile_time[10] = 0;
    2212                 :            :                 compile_date[0] = '"';
    2213                 :            :                 mmv(compile_date + 1, c + 4, 7);
    2214                 :            :                 mmv(compile_date + 8, c + 20, 4);
    2215                 :            :                 compile_date[12] = '"';
    2216                 :            :                 compile_date[13] = 0;
    2217                 :            :         }
    2218                 :            : #else
    2219                 :       5978 :         strftime(compile_time, 12, "\"%H:%M:%S\"", ct);
    2220                 :       5978 :         strftime(compile_date, 24, "\"%b %d %Y\"", ct);
    2221                 :            : #endif
    2222                 :       5978 :         init_macros();
    2223         [ +  - ]:       5978 :         if (with_assertions) init_assertions();
    2224                 :       5978 :         init_found_files();
    2225                 :       5978 : }
    2226                 :            : 
    2227                 :            : /*
    2228                 :            :  * Resets the include path.
    2229                 :            :  */
    2230                 :       5978 : void init_include_path(char *incpath[])
    2231                 :            : {
    2232         [ -  + ]:       5978 :         if (include_path_nb) {
    2233                 :            :                 size_t i;
    2234                 :            : 
    2235         [ #  # ]:          0 :                 for (i = 0; i < include_path_nb; i ++)
    2236                 :          0 :                         freemem(include_path[i]);
    2237                 :          0 :                 freemem(include_path);
    2238                 :          0 :                 include_path_nb = 0;
    2239                 :            :         }
    2240         [ -  + ]:       5978 :         if (incpath) {
    2241                 :            :                 int i;
    2242                 :            : 
    2243         [ #  # ]:          0 :                 for (i = 0; incpath[i]; i ++)
    2244 [ #  # ][ #  # ]:          0 :                         aol(include_path, include_path_nb,
    2245                 :            :                                 sdup(incpath[i]), INCPATH_MEMG);
    2246                 :            :         }
    2247                 :       5978 : }
    2248                 :            : 
    2249                 :            : /*
    2250                 :            :  * add_incpath() adds "path" to the standard include path.
    2251                 :            :  */
    2252                 :      17929 : void add_incpath(char *path)
    2253                 :            : {
    2254 [ +  + ][ -  + ]:      17929 :         aol(include_path, include_path_nb, sdup(path), INCPATH_MEMG);
    2255                 :      17929 : }
    2256                 :            : 
    2257                 :            : /*
    2258                 :            :  * This function cleans the memory. It should release all allocated
    2259                 :            :  * memory structures and may be called even if the current pre-processing
    2260                 :            :  * is not finished or reported an error.
    2261                 :            :  */
    2262                 :       5978 : void wipeout()
    2263                 :            : {
    2264                 :            :         struct lexer_state ls;
    2265                 :            : 
    2266         [ +  - ]:       5978 :         if (include_path_nb > 0) {
    2267                 :            :                 size_t i;
    2268                 :            : 
    2269         [ +  + ]:      23907 :                 for (i = 0; i < include_path_nb; i ++)
    2270                 :      17929 :                         freemem(include_path[i]);
    2271                 :       5978 :                 freemem(include_path);
    2272                 :       5978 :                 include_path = 0;
    2273                 :       5978 :                 include_path_nb = 0;
    2274                 :            :         }
    2275         [ +  - ]:       5978 :         if (current_filename) freemem(current_filename);
    2276                 :       5978 :         current_filename = 0;
    2277                 :       5978 :         current_long_filename = 0;
    2278                 :       5978 :         current_incdir = -1;
    2279                 :       5978 :         protect_detect.state = 0;
    2280         [ +  + ]:       5978 :         if (protect_detect.macro) freemem(protect_detect.macro);
    2281                 :       5978 :         protect_detect.macro = 0;
    2282                 :       5978 :         protect_detect.ff = 0;
    2283                 :       5978 :         init_lexer_state(&ls);
    2284         [ -  + ]:       5978 :         while (ls_depth > 0) pop_file_context(&ls);
    2285                 :       5978 :         free_lexer_state(&ls);
    2286                 :       5978 :         free_lexer_state(&dsharp_lexer);
    2287                 :            : #ifdef PRAGMA_TOKENIZE
    2288                 :       5978 :         free_lexer_state(&tokenize_lexer);
    2289                 :            : #endif
    2290         [ +  - ]:       5978 :         if (found_files_init_done) HTT_kill(&found_files);
    2291                 :       5978 :         found_files_init_done = 0;
    2292         [ +  - ]:       5978 :         if (found_files_sys_init_done) HTT_kill(&found_files_sys);
    2293                 :       5978 :         found_files_sys_init_done = 0;
    2294                 :       5978 :         wipe_macros();
    2295                 :       5978 :         wipe_assertions();
    2296                 :       5978 : }
    2297                 :            : 
    2298                 :            : #ifdef STAND_ALONE
    2299                 :            : /*
    2300                 :            :  * print some help
    2301                 :            :  */
    2302                 :          0 : static void usage(char *command_name)
    2303                 :            : {
    2304                 :          0 :         fprintf(stderr,
    2305                 :            :         "Usage: %s [options] [file]\n"
    2306                 :            :         "language options:\n"
    2307                 :            :         "  -C              keep comments in output\n"
    2308                 :            :         "  -s              keep '#' when no cpp directive is recognized\n"
    2309                 :            :         "  -l              do not emit line numbers\n"
    2310                 :            :         "  -lg             emit gcc-like line numbers\n"
    2311                 :            :         "  -CC             disable C++-like comments\n"
    2312                 :            :         "  -a, -na, -a0    handle (or not) assertions\n"
    2313                 :            :         "  -V              disable macros with extra arguments\n"
    2314                 :            :         "  -u              understand UTF-8 in source\n"
    2315                 :            :         "  -X              enable -a, -u and -Y\n"
    2316                 :            :         "  -c90            mimic C90 behaviour\n"
    2317                 :            :         "  -t              disable trigraph support\n"
    2318                 :            :         "warning options:\n"
    2319                 :            :         "  -wt             emit a final warning when trigaphs are encountered\n"
    2320                 :            :         "  -wtt            emit warnings for each trigaph encountered\n"
    2321                 :            :         "  -wa             emit warnings that are usually useless\n"
    2322                 :            :         "  -w0             disable standard warnings\n"
    2323                 :            :         "directory options:\n"
    2324                 :            :         "  -I directory    add 'directory' before the standard include path\n"
    2325                 :            :         "  -J directory    add 'directory' after the standard include path\n"
    2326                 :            :         "  -zI             do not use the standard include path\n"
    2327                 :            :         "  -M              emit Makefile-like dependencies instead of normal "
    2328                 :            :                         "output\n"
    2329                 :            :         "  -Ma             emit also dependancies for system files\n"
    2330                 :            :         "  -o file         store output in file\n"
    2331                 :            :         "macro and assertion options:\n"
    2332                 :            :         "  -Dmacro         predefine 'macro'\n"
    2333                 :            :         "  -Dmacro=def     predefine 'macro' with 'def' content\n"
    2334                 :            :         "  -Umacro         undefine 'macro'\n"
    2335                 :            :         "  -Afoo(bar)      assert foo(bar)\n"
    2336                 :            :         "  -Bfoo(bar)      unassert foo(bar)\n"
    2337                 :            :         "  -Y              predefine system-dependant macros\n"
    2338                 :            :         "  -Z              do not predefine special macros\n"
    2339                 :            :         "  -d              emit defined macros\n"
    2340                 :            :         "  -e              emit assertions\n"
    2341                 :            :         "misc options:\n"
    2342                 :            :         "  -v              print version number and settings\n"
    2343                 :            :         "  -h              show this help\n",
    2344                 :            :         command_name);
    2345                 :          0 : }
    2346                 :            : 
    2347                 :            : /*
    2348                 :            :  * print version and compile-time settings
    2349                 :            :  */
    2350                 :          0 : static void version(void)
    2351                 :            : {
    2352                 :            :         size_t i;
    2353                 :            : 
    2354                 :          0 :         fprintf(stderr, "ucpp version %d.%d\n", VERS_MAJ, VERS_MIN);
    2355                 :          0 :         fprintf(stderr, "search path:\n");
    2356         [ #  # ]:          0 :         for (i = 0; i < include_path_nb; i ++)
    2357                 :          0 :                 fprintf(stderr, "  %s\n", include_path[i]);
    2358                 :          0 : }
    2359                 :            : 
    2360                 :            : /*
    2361                 :            :  * parse_opt() initializes many things according to the command-line
    2362                 :            :  * options.
    2363                 :            :  * Return values:
    2364                 :            :  * 0  on success
    2365                 :            :  * 1  on semantic error (redefinition of a special macro, for instance)
    2366                 :            :  * 2  on syntaxic error (unknown options for instance)
    2367                 :            :  */
    2368                 :       5978 : static int parse_opt(int argc, char *argv[], struct lexer_state *ls)
    2369                 :            : {
    2370                 :       5978 :         int i, ret = 0;
    2371                 :       5978 :         char *filename = 0;
    2372                 :       5978 :         int with_std_incpath = 1;
    2373                 :       5978 :         int print_version = 0, print_defs = 0, print_asserts = 0;
    2374                 :       5978 :         int system_macros = 0, standard_assertions = 1;
    2375                 :            : 
    2376                 :       5978 :         init_lexer_state(ls);
    2377                 :       5978 :         ls->flags = DEFAULT_CPP_FLAGS;
    2378                 :       5978 :         emit_output = ls->output = stdout;
    2379 [ +  + ][ +  + ]:      53797 :         for (i = 1; i < argc; i ++) if (argv[i][0] == '-') {
    2380         [ -  + ]:      41841 :                 if (!strcmp(argv[i], "-h")) {
    2381                 :          0 :                         return 2;
    2382         [ +  + ]:      41841 :                 } else if (!strcmp(argv[i], "-C")) {
    2383                 :       5978 :                         ls->flags &= ~DISCARD_COMMENTS;
    2384         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-CC")) {
    2385                 :          0 :                         ls->flags &= ~CPLUSPLUS_COMMENTS;
    2386         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-a")) {
    2387                 :          0 :                         ls->flags |= HANDLE_ASSERTIONS;
    2388         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-na")) {
    2389                 :          0 :                         ls->flags |= HANDLE_ASSERTIONS;
    2390                 :          0 :                         standard_assertions = 0;
    2391         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-a0")) {
    2392                 :          0 :                         ls->flags &= ~HANDLE_ASSERTIONS;
    2393         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-V")) {
    2394                 :          0 :                         ls->flags &= ~MACRO_VAARG;
    2395         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-u")) {
    2396                 :          0 :                         ls->flags |= UTF8_SOURCE;
    2397         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-X")) {
    2398                 :          0 :                         ls->flags |= HANDLE_ASSERTIONS;
    2399                 :          0 :                         ls->flags |= UTF8_SOURCE;
    2400                 :          0 :                         system_macros = 1;
    2401         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-c90")) {
    2402                 :          0 :                         ls->flags &= ~MACRO_VAARG;
    2403                 :          0 :                         ls->flags &= ~CPLUSPLUS_COMMENTS;
    2404                 :          0 :                         c99_compliant = 0;
    2405                 :          0 :                         c99_hosted = -1;
    2406         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-t")) {
    2407                 :          0 :                         ls->flags &= ~HANDLE_TRIGRAPHS;
    2408         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-wt")) {
    2409                 :          0 :                         ls->flags |= WARN_TRIGRAPHS;
    2410         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-wtt")) {
    2411                 :          0 :                         ls->flags |= WARN_TRIGRAPHS_MORE;
    2412         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-wa")) {
    2413                 :          0 :                         ls->flags |= WARN_ANNOYING;
    2414         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-w0")) {
    2415                 :          0 :                         ls->flags &= ~WARN_STANDARD;
    2416                 :          0 :                         ls->flags &= ~WARN_PRAGMA;
    2417         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-s")) {
    2418                 :          0 :                         ls->flags &= ~FAIL_SHARP;
    2419         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-l")) {
    2420                 :          0 :                         ls->flags &= ~LINE_NUM;
    2421         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-lg")) {
    2422                 :          0 :                         ls->flags |= GCC_LINE_NUM;
    2423         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-M")) {
    2424                 :          0 :                         ls->flags &= ~KEEP_OUTPUT;
    2425                 :          0 :                         emit_dependencies = 1;
    2426         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-Ma")) {
    2427                 :          0 :                         ls->flags &= ~KEEP_OUTPUT;
    2428                 :          0 :                         emit_dependencies = 2;
    2429         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-Y")) {
    2430                 :          0 :                         system_macros = 1;
    2431         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-Z")) {
    2432                 :          0 :                         no_special_macros = 1;
    2433         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-d")) {
    2434                 :          0 :                         ls->flags &= ~KEEP_OUTPUT;
    2435                 :          0 :                         print_defs = 1;
    2436         [ -  + ]:      35863 :                 } else if (!strcmp(argv[i], "-e")) {
    2437                 :          0 :                         ls->flags &= ~KEEP_OUTPUT;
    2438                 :          0 :                         print_asserts = 1;
    2439         [ +  + ]:      35863 :                 } else if (!strcmp(argv[i], "-zI")) {
    2440                 :       5978 :                         with_std_incpath = 0;
    2441 [ +  - ][ -  + ]:      29885 :                 } else if (!strcmp(argv[i], "-I") || !strcmp(argv[i], "-J")) {
    2442                 :          0 :                         i ++;
    2443         [ +  + ]:      29885 :                 } else if (!strcmp(argv[i], "-o")) {
    2444         [ -  + ]:       5978 :                         if ((++ i) >= argc) {
    2445                 :          0 :                                 error(-1, "missing filename after -o");
    2446                 :          0 :                                 return 2;
    2447                 :            :                         }
    2448 [ -  + ][ #  # ]:       5978 :                         if (argv[i][0] == '-' && argv[i][1] == 0) {
    2449                 :          0 :                                 emit_output = ls->output = stdout;
    2450                 :            :                         } else {
    2451                 :       5978 :                                 ls->output = fopen(argv[i], "w");
    2452         [ -  + ]:       5978 :                                 if (!ls->output) {
    2453                 :          0 :                                         error(-1, "failed to open for "
    2454                 :          0 :                                                 "writing: %s", argv[i]);
    2455                 :          0 :                                         return 2;
    2456                 :            :                                 }
    2457                 :       5978 :                                 emit_output = ls->output;
    2458                 :            :                         }
    2459         [ -  + ]:      23907 :                 } else if (!strcmp(argv[i], "-v")) {
    2460                 :          0 :                         print_version = 1;
    2461 [ +  + ][ +  - ]:      23907 :                 } else if (argv[i][1] != 'I' && argv[i][1] != 'J'
    2462 [ -  + ][ #  # ]:       5978 :                         && argv[i][1] != 'D' && argv[i][1] != 'U'
    2463 [ #  # ][ #  # ]:          0 :                         && argv[i][1] != 'A' && argv[i][1] != 'B')
    2464                 :      41841 :                         warning(-1, "unknown option '%s'", argv[i]);
    2465                 :            :         } else {
    2466         [ -  + ]:       5978 :                 if (filename != 0) {
    2467                 :          0 :                         error(-1, "spurious duplicate filename '%s' - vs. '%s' ", argv[i], filename);
    2468                 :          0 :                         return 2;
    2469                 :            :                 }
    2470                 :       5978 :                 filename = argv[i];
    2471                 :            :         }
    2472                 :       5978 :         init_tables(ls->flags & HANDLE_ASSERTIONS);
    2473                 :       5978 :         init_include_path(0);
    2474         [ +  - ]:       5978 :         if (filename) {
    2475                 :            : #ifdef UCPP_MMAP
    2476                 :            :                 FILE *f = fopen_mmap_file(filename);
    2477                 :            : 
    2478                 :            :                 ls->input = 0;
    2479                 :            :                 if (f) set_input_file(ls, f);
    2480                 :            : #else
    2481                 :       5978 :                 ls->input = fopen(filename, "r");
    2482                 :            : #endif
    2483         [ -  + ]:       5978 :                 if (!ls->input) {
    2484                 :          0 :                         error(-1, "file '%s' not found", filename);
    2485                 :          0 :                         return 1;
    2486                 :            :                 }
    2487                 :            : #ifdef NO_LIBC_BUF
    2488                 :            :                 setbuf(ls->input, 0);
    2489                 :            : #endif
    2490                 :       5978 :                 set_init_filename(filename, 1);
    2491                 :            :         } else {
    2492                 :          0 :                 ls->input = stdin;
    2493                 :          0 :                 set_init_filename("<stdin>", 0);
    2494                 :            :         }
    2495         [ +  + ]:      59775 :         for (i = 1; i < argc; i ++)
    2496 [ +  + ][ +  + ]:      53797 :                 if (argv[i][0] == '-' && argv[i][1] == 'I')
    2497         [ +  - ]:      17929 :                         add_incpath(argv[i][2] ? argv[i] + 2 : argv[i + 1]);
    2498 [ -  + ][ #  # ]:       5978 :         if (system_macros) for (i = 0; system_macros_def[i]; i ++)
    2499 [ #  # ][ #  # ]:          0 :                 ret = ret || define_macro(ls, system_macros_def[i]);
    2500         [ +  + ]:      59775 :         for (i = 1; i < argc; i ++)
    2501 [ +  + ][ +  + ]:      53797 :                 if (argv[i][0] == '-' && argv[i][1] == 'D')
    2502 [ +  - ][ -  + ]:       5978 :                         ret = ret || define_macro(ls, argv[i] + 2);
    2503         [ +  + ]:      59775 :         for (i = 1; i < argc; i ++)
    2504 [ +  + ][ -  + ]:      53797 :                 if (argv[i][0] == '-' && argv[i][1] == 'U')
    2505 [ #  # ][ #  # ]:          0 :                         ret = ret || undef_macro(ls, argv[i] + 2);
    2506         [ +  - ]:       5978 :         if (ls->flags & HANDLE_ASSERTIONS) {
    2507         [ +  - ]:       5978 :                 if (standard_assertions)
    2508         [ -  + ]:       5978 :                         for (i = 0; system_assertions_def[i]; i ++)
    2509                 :          0 :                                 make_assertion(system_assertions_def[i]);
    2510         [ +  + ]:      59775 :                 for (i = 1; i < argc; i ++)
    2511 [ +  + ][ -  + ]:      53797 :                         if (argv[i][0] == '-' && argv[i][1] == 'A')
    2512 [ #  # ][ #  # ]:          0 :                                 ret = ret || make_assertion(argv[i] + 2);
    2513         [ +  + ]:      59775 :                 for (i = 1; i < argc; i ++)
    2514 [ +  + ][ -  + ]:      53797 :                         if (argv[i][0] == '-' && argv[i][1] == 'B')
    2515 [ #  # ][ #  # ]:          0 :                                 ret = ret || destroy_assertion(argv[i] + 2);
    2516                 :            :         } else {
    2517         [ #  # ]:          0 :                 for (i = 1; i < argc; i ++)
    2518         [ #  # ]:          0 :                         if (argv[i][0] == '-'
    2519 [ #  # ][ #  # ]:          0 :                                 && (argv[i][1] == 'A' || argv[i][1] == 'B'))
    2520                 :          0 :                                 warning(-1, "assertions disabled");
    2521                 :            :         }
    2522         [ -  + ]:       5978 :         if (with_std_incpath) {
    2523         [ #  # ]:          0 :                 for (i = 0; include_path_std[i]; i ++)
    2524                 :          0 :                         add_incpath(include_path_std[i]);
    2525                 :            :         }
    2526         [ +  + ]:      59775 :         for (i = 1; i < argc; i ++)
    2527 [ +  + ][ -  + ]:      53797 :                 if (argv[i][0] == '-' && argv[i][1] == 'J')
    2528         [ #  # ]:          0 :                         add_incpath(argv[i][2] ? argv[i] + 2 : argv[i + 1]);
    2529                 :            : 
    2530         [ -  + ]:       5978 :         if (print_version) {
    2531                 :          0 :                 version();
    2532                 :          0 :                 return 1;
    2533                 :            :         }
    2534         [ -  + ]:       5978 :         if (print_defs) {
    2535                 :          0 :                 print_defines();
    2536                 :          0 :                 emit_defines = 1;
    2537                 :            :         }
    2538 [ -  + ][ #  # ]:       5978 :         if (print_asserts && (ls->flags & HANDLE_ASSERTIONS)) {
    2539                 :          0 :                 print_assertions();
    2540                 :          0 :                 emit_assertions = 1;
    2541                 :            :         }
    2542                 :       5978 :         return ret;
    2543                 :            : }
    2544                 :            : 
    2545                 :       5978 : int main(int argc, char *argv[])
    2546                 :            : {
    2547                 :            :         struct lexer_state ls;
    2548                 :       5978 :         int r, fr = 0;
    2549                 :            : 
    2550                 :       5978 :         init_cpp();
    2551         [ -  + ]:       5978 :         if ((r = parse_opt(argc, argv, &ls)) != 0) {
    2552         [ #  # ]:          0 :                 if (r == 2) usage(argv[0]);
    2553                 :          0 :                 return EXIT_FAILURE;
    2554                 :            :         }
    2555                 :       5978 :         enter_file(&ls, ls.flags);
    2556 [ +  - ][ -  + ]:   11727374 :         while ((r = cpp(&ls)) < CPPERR_EOF) fr = fr || (r > 0);
                 [ +  + ]
    2557 [ +  - ][ -  + ]:       5978 :         fr = fr || check_cpp_errors(&ls);
    2558                 :       5978 :         free_lexer_state(&ls);
    2559                 :       5978 :         wipeout();
    2560                 :            : #ifdef MEM_DEBUG
    2561                 :            :         report_leaks();
    2562                 :            : #endif
    2563                 :       5978 :         return fr ? EXIT_FAILURE : EXIT_SUCCESS;
    2564                 :            : }
    2565                 :            : #endif

Generated by: LCOV version 1.10