LCOV - code coverage report
Current view: top level - soltools/cpp - _lex.c (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 187 250 74.8 %
Date: 2015-06-13 12:38:46 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <stdio.h>
      21             : #include <stdlib.h>
      22             : #include <string.h>
      23             : #if (defined(_WIN32) || defined(__IBMC__))
      24             : #include <io.h>
      25             : #else
      26             : #include <unistd.h>
      27             : #endif
      28             : #include "cpp.h"
      29             : /*
      30             :  * lexical FSM encoding
      31             :  *   when in state state, and one of the characters
      32             :  *   in ch arrives, enter nextstate.
      33             :  *   States >= S_SELF are either final, or at least require special action.
      34             :  *   In 'fsm' there is a line for each state X charset X nextstate.
      35             :  *   List chars that overwrite previous entries later (e.g. C_ALPH
      36             :  *   can be overridden by '_' by a later entry; and C_XX is the
      37             :  *   the universal set, and should always be first.
      38             :  *   States above S_SELF are represented in the big table as negative values.
      39             :  *   S_SELF and S_SELFB encode the resulting token type in the upper bits.
      40             :  *   These actions differ in that S_SELF doesn't have a lookahead char,
      41             :  *   S_SELFB does.
      42             :  *
      43             :  *   The encoding is blown out into a big table for time-efficiency.
      44             :  *   Entries have
      45             :  *      nextstate: 6 bits; ?\ marker: 1 bit; tokentype: 9 bits.
      46             :  */
      47             : 
      48             : #define MAXSTATE        32
      49             : #define ACT(tok,act)    ((tok<<7)+act)
      50             : #define QBSBIT          0100
      51             : #define GETACT(st)      ((st>>7)&0x1ff)
      52             : 
      53             : /* character classes */
      54             : #define C_ALPH  1
      55             : #define C_NUM   2
      56             : #define C_XX    3
      57             : 
      58             : enum state
      59             : {
      60             :     START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
      61             :     CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
      62             :     CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
      63             :     S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
      64             :     S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
      65             : };
      66             : 
      67             : int tottok;
      68             : int tokkind[256];
      69             : struct fsm
      70             : {
      71             :     int state;                          /* if in this state */
      72             :     uchar ch[4];                        /* and see one of these characters */
      73             :     int nextstate;                      /* enter this state if +ve */
      74             : };
      75             : 
      76             :  /*const*/ struct fsm fsm[] = {
      77             :     /* start state */
      78             :          {START, {C_XX}, ACT(UNCLASS, S_SELF)},
      79             :          {START, {' ', '\t', '\v'}, WS1},
      80             :          {START, {C_NUM}, NUM1},
      81             :          {START, {'.'}, NUM3},
      82             :          {START, {C_ALPH}, ID1},
      83             :          {START, {'L'}, ST1},
      84             :          {START, {'"'}, ST2},
      85             :          {START, {'\''}, CC1},
      86             :          {START, {'/'}, COM1},
      87             :          {START, {EOFC}, S_EOF},
      88             :          {START, {'\n'}, S_NL},
      89             :          {START, {'-'}, MINUS1},
      90             :          {START, {'+'}, PLUS1},
      91             :          {START, {'<'}, LT1},
      92             :          {START, {'>'}, GT1},
      93             :          {START, {'='}, ASG1},
      94             :          {START, {'!'}, NOT1},
      95             :          {START, {'&'}, AND1},
      96             :          {START, {'|'}, OR1},
      97             :          {START, {'#'}, SHARP1},
      98             :          {START, {'%'}, PCT1},
      99             :          {START, {'['}, ACT(SBRA, S_SELF)},
     100             :          {START, {']'}, ACT(SKET, S_SELF)},
     101             :          {START, {'('}, ACT(LP, S_SELF)},
     102             :          {START, {')'}, ACT(RP, S_SELF)},
     103             :          {START, {'*'}, STAR1},
     104             :          {START, {','}, ACT(COMMA, S_SELF)},
     105             :          {START, {'?'}, ACT(QUEST, S_SELF)},
     106             :          {START, {':'}, ACT(COLON, S_SELF)},
     107             :          {START, {';'}, ACT(SEMIC, S_SELF)},
     108             :          {START, {'{'}, ACT(CBRA, S_SELF)},
     109             :          {START, {'}'}, ACT(CKET, S_SELF)},
     110             :          {START, {'~'}, ACT(TILDE, S_SELF)},
     111             :          {START, {'^'}, CIRC1},
     112             : 
     113             :     /* saw a digit */
     114             :          {NUM1, {C_XX}, ACT(NUMBER, S_SELFB)},
     115             :          {NUM1, {C_NUM, C_ALPH, '.'}, NUM1},
     116             :          {NUM1, {'E', 'e'}, NUM2},
     117             :          {NUM1, {'_'}, ACT(NUMBER, S_SELFB)},
     118             : 
     119             :     /* saw possible start of exponent, digits-e */
     120             :          {NUM2, {C_XX}, ACT(NUMBER, S_SELFB)},
     121             :          {NUM2, {'+', '-'}, NUM1},
     122             :          {NUM2, {C_NUM, C_ALPH}, NUM1},
     123             :          {NUM2, {'_'}, ACT(NUMBER, S_SELFB)},
     124             : 
     125             :     /* saw a '.', which could be a number or an operator */
     126             :          {NUM3, {C_XX}, ACT(DOT, S_SELFB)},
     127             :          {NUM3, {'.'}, DOTS1},
     128             :          {NUM3, {C_NUM}, NUM1},
     129             : 
     130             :          {DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB)},
     131             :          {DOTS1, {C_NUM}, NUM1},
     132             :          {DOTS1, {'.'}, ACT(ELLIPS, S_SELF)},
     133             : 
     134             :     /* saw a letter or _ */
     135             :          {ID1, {C_XX}, ACT(NAME, S_NAME)},
     136             :          {ID1, {C_ALPH, C_NUM}, ID1},
     137             : 
     138             :     /* saw L (start of wide string?) */
     139             :          {ST1, {C_XX}, ACT(NAME, S_NAME)},
     140             :          {ST1, {C_ALPH, C_NUM}, ID1},
     141             :          {ST1, {'"'}, ST2},
     142             :          {ST1, {'\''}, CC1},
     143             : 
     144             :     /* saw " beginning string */
     145             :          {ST2, {C_XX}, ST2},
     146             :          {ST2, {'"'}, ACT(STRING, S_SELF)},
     147             :          {ST2, {'\\'}, ST3},
     148             :          {ST2, {'\n'}, S_STNL},
     149             :          {ST2, {EOFC}, S_EOFSTR},
     150             : 
     151             :     /* saw \ in string */
     152             :          {ST3, {C_XX}, ST2},
     153             :          {ST3, {'\n'}, S_STNL},
     154             :          {ST3, {EOFC}, S_EOFSTR},
     155             : 
     156             :     /* saw ' beginning character const */
     157             :          {CC1, {C_XX}, CC1},
     158             :          {CC1, {'\''}, ACT(CCON, S_SELF)},
     159             :          {CC1, {'\\'}, CC2},
     160             :          {CC1, {'\n'}, S_STNL},
     161             :          {CC1, {EOFC}, S_EOFSTR},
     162             : 
     163             :     /* saw \ in ccon */
     164             :          {CC2, {C_XX}, CC1},
     165             :          {CC2, {'\n'}, S_STNL},
     166             :          {CC2, {EOFC}, S_EOFSTR},
     167             : 
     168             :     /* saw /, perhaps start of comment */
     169             :          {COM1, {C_XX}, ACT(SLASH, S_SELFB)},
     170             :          {COM1, {'='}, ACT(ASSLASH, S_SELF)},
     171             :          {COM1, {'*'}, COM2},
     172             :          {COM1, {'/'}, COM4},
     173             : 
     174             :     /* saw / followed by *, start of comment */
     175             :          {COM2, {C_XX}, COM2},
     176             :          {COM2, {'\n'}, S_COMNL},
     177             :          {COM2, {'*'}, COM3},
     178             :          {COM2, {EOFC}, S_EOFCOM},
     179             : 
     180             :     /* saw the * possibly ending a comment */
     181             :          {COM3, {C_XX}, COM2},
     182             :          {COM3, {'\n'}, S_COMNL},
     183             :          {COM3, {'*'}, COM3},
     184             :          {COM3, {'/'}, S_COMMENT},
     185             : 
     186             :     /* // comment */
     187             :          {COM4, {C_XX}, COM4},
     188             :          {COM4, {'\n'}, S_NL},
     189             :          {COM4, {EOFC}, S_EOFCOM},
     190             : 
     191             :     /* saw white space, eat it up */
     192             :          {WS1, {C_XX}, S_WS},
     193             :          {WS1, {'\t', '\v', ' '}, WS1},
     194             : 
     195             :     /* saw -, check --, -=, -> */
     196             :          {MINUS1, {C_XX}, ACT(MINUS, S_SELFB)},
     197             :          {MINUS1, {'-'}, ACT(MMINUS, S_SELF)},
     198             :          {MINUS1, {'='}, ACT(ASMINUS, S_SELF)},
     199             :          {MINUS1, {'>'}, ACT(ARROW, S_SELF)},
     200             : 
     201             :     /* saw +, check ++, += */
     202             :          {PLUS1, {C_XX}, ACT(PLUS, S_SELFB)},
     203             :          {PLUS1, {'+'}, ACT(PPLUS, S_SELF)},
     204             :          {PLUS1, {'='}, ACT(ASPLUS, S_SELF)},
     205             : 
     206             :     /* saw <, check <<, <<=, <= */
     207             :          {LT1, {C_XX}, ACT(LT, S_SELFB)},
     208             :          {LT1, {'<'}, LT2},
     209             :          {LT1, {'='}, ACT(LEQ, S_SELF)},
     210             :          {LT2, {C_XX}, ACT(LSH, S_SELFB)},
     211             :          {LT2, {'='}, ACT(ASLSH, S_SELF)},
     212             : 
     213             :     /* saw >, check >>, >>=, >= */
     214             :          {GT1, {C_XX}, ACT(GT, S_SELFB)},
     215             :          {GT1, {'>'}, GT2},
     216             :          {GT1, {'='}, ACT(GEQ, S_SELF)},
     217             :          {GT2, {C_XX}, ACT(RSH, S_SELFB)},
     218             :          {GT2, {'='}, ACT(ASRSH, S_SELF)},
     219             : 
     220             :     /* = */
     221             :          {ASG1, {C_XX}, ACT(ASGN, S_SELFB)},
     222             :          {ASG1, {'='}, ACT(EQ, S_SELF)},
     223             : 
     224             :     /* ! */
     225             :          {NOT1, {C_XX}, ACT(NOT, S_SELFB)},
     226             :          {NOT1, {'='}, ACT(NEQ, S_SELF)},
     227             : 
     228             :     /* & */
     229             :          {AND1, {C_XX}, ACT(AND, S_SELFB)},
     230             :          {AND1, {'&'}, ACT(LAND, S_SELF)},
     231             :          {AND1, {'='}, ACT(ASAND, S_SELF)},
     232             : 
     233             :     /* | */
     234             :          {OR1, {C_XX}, ACT(OR, S_SELFB)},
     235             :          {OR1, {'|'}, ACT(LOR, S_SELF)},
     236             :          {OR1, {'='}, ACT(ASOR, S_SELF)},
     237             : 
     238             :     /* # */
     239             :          {SHARP1, {C_XX}, ACT(SHARP, S_SELFB)},
     240             :          {SHARP1, {'#'}, ACT(DSHARP, S_SELF)},
     241             : 
     242             :     /* % */
     243             :          {PCT1, {C_XX}, ACT(PCT, S_SELFB)},
     244             :          {PCT1, {'='}, ACT(ASPCT, S_SELF)},
     245             : 
     246             :     /* * */
     247             :          {STAR1, {C_XX}, ACT(STAR, S_SELFB)},
     248             :          {STAR1, {'='}, ACT(ASSTAR, S_SELF)},
     249             : 
     250             :     /* ^ */
     251             :          {CIRC1, {C_XX}, ACT(CIRC, S_SELFB)},
     252             :          {CIRC1, {'='}, ACT(ASCIRC, S_SELF)},
     253             : 
     254             :          {-1, "", 0}
     255             : };
     256             : 
     257             : /* first index is char, second is state */
     258             : /* increase #states to power of 2 to encourage use of shift */
     259             : short bigfsm[256][MAXSTATE];
     260             : 
     261             : void
     262          53 :     expandlex(void)
     263             : {
     264             :      /* const */ struct fsm *fp;
     265             :     int i, j, nstate;
     266             : 
     267        6519 :     for (fp = fsm; fp->state >= 0; fp++)
     268             :     {
     269       13515 :         for (i = 0; fp->ch[i]; i++)
     270             :         {
     271        7049 :             nstate = fp->nextstate;
     272        7049 :             if (nstate >= S_SELF)
     273        3975 :                 nstate = ~nstate;
     274        7049 :             switch (fp->ch[i])
     275             :             {
     276             : 
     277             :                 case C_XX:              /* random characters */
     278      408630 :                     for (j = 0; j < 256; j++)
     279      407040 :                         bigfsm[j][fp->state] = (short) nstate;
     280        1590 :                     continue;
     281             :                 case C_ALPH:
     282       68105 :                     for (j = 0; j < 256; j++)
     283       67840 :                         if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
     284       54060 :                             || j == '_')
     285       14045 :                             bigfsm[j][fp->state] = (short) nstate;
     286         265 :                     continue;
     287             :                 case C_NUM:
     288        4081 :                     for (j = '0'; j <= '9'; j++)
     289        3710 :                         bigfsm[j][fp->state] = (short) nstate;
     290         371 :                     continue;
     291             :                 default:
     292        4823 :                     bigfsm[fp->ch[i]][fp->state] = (short) nstate;
     293             :             }
     294             :         }
     295             :     }
     296             : 
     297             :     /*
     298             :      * install special cases for ? (trigraphs),  \ (splicing), runes, and
     299             :      * EOB
     300             :      */
     301        1749 :     for (i = 0; i < MAXSTATE; i++)
     302             :     {
     303      434176 :         for (j = 0; j < 0xFF; j++)
     304      432480 :             if (j == '?' || j == '\\' || j == '\n' || j == '\r')
     305             :             {
     306        6784 :                 if (bigfsm[j][i] > 0)
     307        1113 :                     bigfsm[j][i] = ~bigfsm[j][i];
     308        6784 :                 bigfsm[j][i] &= ~QBSBIT;
     309             :             }
     310        1696 :         bigfsm[EOB][i] = ~S_EOB;
     311        1696 :         if (bigfsm[EOFC][i] >= 0)
     312         159 :             bigfsm[EOFC][i] = ~S_EOF;
     313             :     }
     314          53 : }
     315             : 
     316             : void
     317          53 :     fixlex(void)
     318             : {
     319             :     /* do C++ comments? */
     320          53 :     if ((Cplusplus == 0) || (Cflag != 0))
     321           0 :         bigfsm['/'][COM1] = bigfsm['x'][COM1];
     322          53 : }
     323             : 
     324             : /*
     325             :  * fill in a row of tokens from input, terminated by NL or END
     326             :  * First token is put at trp->lp.
     327             :  * Reset is non-zero when the input buffer can be "rewound."
     328             :  * The value is a flag indicating that possible macros have
     329             :  * been seen in the row.
     330             :  */
     331             : int
     332       56800 :     gettokens(Tokenrow * trp, int reset)
     333             : {
     334             :     int c, state, oldstate;
     335             :     uchar *ip;
     336             :     Token *tp, *maxp;
     337             :     int runelen;
     338       56800 :     Source *s = cursource;
     339       56800 :     int nmac = 0;
     340             : 
     341       56800 :     tp = trp->lp;
     342       56800 :     ip = s->inp;
     343       56800 :     if (reset)
     344             :     {
     345       56800 :         s->lineinc = 0;
     346       56800 :         if (ip >= s->inl)
     347             :         {                               /* nothing in buffer */
     348         386 :             s->inl = s->inb;
     349         386 :             fillbuf(s);
     350         386 :             ip = s->inp = s->inb;
     351             :         }
     352             :         else
     353       56414 :             if (ip >= s->inb + (3 * INS / 4))
     354             :             {
     355          67 :                 memmove(s->inb, ip, 4 + s->inl - ip);
     356          67 :                 s->inl = s->inb + (s->inl - ip);
     357          67 :                 ip = s->inp = s->inb;
     358             :             }
     359             :     }
     360       56800 :     maxp = &trp->bp[trp->max];
     361       56800 :     runelen = 1;
     362             :     for (;;)
     363             :     {
     364             : continue2:
     365     1115563 :         if (tp >= maxp)
     366             :         {
     367       24848 :             trp->lp = tp;
     368       24848 :             tp = growtokenrow(trp);
     369       24848 :             maxp = &trp->bp[trp->max];
     370             :         }
     371     1115563 :         tp->type = UNCLASS;
     372     1115563 :         tp->t = ip;
     373     1115563 :         tp->wslen = 0;
     374     1115563 :         tp->flag = 0;
     375     1115563 :         state = START;
     376             :         for (;;)
     377             :         {
     378     5372711 :             oldstate = state;
     379             : 
     380     5372711 :             c = *ip;
     381             : 
     382     5372711 :             if ((state = bigfsm[c][state]) >= 0)
     383             :             {
     384     3826691 :                 ip += runelen;
     385     3826691 :                 runelen = 1;
     386     3826691 :                 continue;
     387             :             }
     388     1546020 :             state = ~state;
     389             :     reswitch:
     390     1603507 :             switch (state & 0177)
     391             :             {
     392             :                 case S_SELF:
     393      445321 :                     ip += runelen;
     394      445321 :                     runelen = 1;
     395             :                     /*fall-through*/
     396             :                 case S_SELFB:
     397      598459 :                     tp->type = (unsigned char) GETACT(state);
     398      598459 :                     tp->len = ip - tp->t;
     399      598459 :                     tp++;
     400      598459 :                     goto continue2;
     401             : 
     402             :                 case S_NAME:            /* like S_SELFB but with nmac check */
     403      460304 :                     tp->type = NAME;
     404      460304 :                     tp->len = ip - tp->t;
     405      460304 :                     nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
     406      460304 :                     tp++;
     407      460304 :                     goto continue2;
     408             : 
     409             :                 case S_WS:
     410      332952 :                     tp->wslen = ip - tp->t;
     411      332952 :                     tp->t = ip;
     412      332952 :                     state = START;
     413      332952 :                     continue;
     414             : 
     415             :                 default:
     416      133287 :                     if ((state & QBSBIT) == 0)
     417             :                     {
     418        1638 :                         ip += runelen;
     419        1638 :                         runelen = 1;
     420        1638 :                         continue;
     421             :                     }
     422      131649 :                     state &= ~QBSBIT;
     423      131649 :                     s->inp = ip;
     424             : 
     425      131649 :                     if (c == '\n')
     426             :                     {
     427       51106 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     428             : 
     429       51106 :                         if (s->inp[1] == '\r')
     430             :                         {
     431           0 :                             memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
     432           0 :                             s->inl -= 1;
     433             :                         }
     434             : 
     435       51106 :                         goto reswitch;
     436             :                     }
     437             : 
     438       80543 :                     if (c == '\r')
     439             :                     {
     440           0 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     441             : 
     442           0 :                         if (s->inp[1] == '\n')
     443             :                         {
     444           0 :                             memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
     445           0 :                             s->inl -= 1;
     446             :                         }
     447             :                         else
     448           0 :                             *s->inp = '\n';
     449             : 
     450           0 :                         state = oldstate;
     451           0 :                         continue;
     452             :                     }
     453             : 
     454       80543 :                     if (c == '?')
     455             :                     {                   /* check trigraph */
     456           1 :                         if (trigraph(s))
     457             :                         {
     458           0 :                             state = oldstate;
     459           0 :                             continue;
     460             :                         }
     461           1 :                         goto reswitch;
     462             :                     }
     463       80542 :                     if (c == '\\')
     464             :                     {                   /* line-folding */
     465       80542 :                         if (foldline(s))
     466             :                         {
     467       74162 :                             s->lineinc++;
     468       74162 :                             state = oldstate;
     469       74162 :                             continue;
     470             :                         }
     471        6380 :                         goto reswitch;
     472             :                     }
     473           0 :                     error(WARNING, "Lexical botch in cpp");
     474           0 :                     ip += runelen;
     475           0 :                     runelen = 1;
     476           0 :                     continue;
     477             : 
     478             :                 case S_EOB:
     479       19686 :                     s->inp = ip;
     480       19686 :                     fillbuf(cursource);
     481       19686 :                     state = oldstate;
     482       19686 :                     continue;
     483             : 
     484             :                 case S_EOF:
     485       18966 :                     tp->type = END;
     486       18966 :                     tp->len = 0;
     487       18966 :                     s->inp = ip;
     488       18966 :                     if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
     489           0 :                         error(WARNING, "No newline at end of file");
     490       18966 :                     trp->lp = tp + 1;
     491       18966 :                     return nmac;
     492             : 
     493             :                 case S_STNL:
     494           0 :                     error(ERROR, "Unterminated string or char const");
     495             :                 case S_NL:
     496       37834 :                     tp->t = ip;
     497       37834 :                     tp->type = NL;
     498       37834 :                     tp->len = 1;
     499       37834 :                     tp->wslen = 0;
     500       37834 :                     s->lineinc++;
     501       37834 :                     s->inp = ip + 1;
     502       37834 :                     trp->lp = tp + 1;
     503       37834 :                     return nmac;
     504             : 
     505             :                 case S_EOFSTR:
     506           0 :                     error(FATAL, "EOF in string or char constant");
     507           0 :                     break;
     508             : 
     509             :                 case S_COMNL:
     510        1752 :                     s->lineinc++;
     511        1752 :                     state = COM2;
     512        1752 :                     ip += runelen;
     513        1752 :                     runelen = 1;
     514        1752 :                     continue;
     515             : 
     516             :                 case S_EOFCOM:
     517           0 :                     error(WARNING, "EOF inside comment");
     518           0 :                     --ip;
     519             :                 case S_COMMENT:
     520         267 :                     if (!Cflag)
     521             :                     {
     522         267 :                         tp->t = ++ip;
     523         267 :                         tp->t[-1] = ' ';
     524         267 :                         tp->wslen = 1;
     525         267 :                         state = START;
     526         267 :                         continue;
     527             :                     }
     528             :                     else
     529             :                     {
     530           0 :                         runelen = 1;
     531           0 :                         s->lineinc = 0;;
     532           0 :                         tp->type = COMMENT;
     533           0 :                         tp->flag |= XTWS;
     534             :                     }
     535             :             }
     536           0 :             break;
     537     4257148 :         }
     538           0 :         ip += runelen;
     539           0 :         runelen = 1;
     540           0 :         tp->len = ip - tp->t;
     541           0 :         tp++;
     542           0 :     }
     543             : }
     544             : 
     545             : /* have seen ?; handle the trigraph it starts (if any) else 0 */
     546             : int
     547           1 :     trigraph(Source * s)
     548             : {
     549             :     uchar c;
     550             : 
     551           1 :     while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
     552             :     ;
     553           1 :     if (s->inp[1] != '?')
     554           1 :         return 0;
     555           0 :     c = 0;
     556           0 :     switch (s->inp[2])
     557             :     {
     558             :         case '=':
     559           0 :             c = '#';
     560           0 :             break;
     561             :         case '(':
     562           0 :             c = '[';
     563           0 :             break;
     564             :         case '/':
     565           0 :             c = '\\';
     566           0 :             break;
     567             :         case ')':
     568           0 :             c = ']';
     569           0 :             break;
     570             :         case '\'':
     571           0 :             c = '^';
     572           0 :             break;
     573             :         case '<':
     574           0 :             c = '{';
     575           0 :             break;
     576             :         case '!':
     577           0 :             c = '|';
     578           0 :             break;
     579             :         case '>':
     580           0 :             c = '}';
     581           0 :             break;
     582             :         case '-':
     583           0 :             c = '~';
     584           0 :             break;
     585             :     }
     586           0 :     if (c)
     587             :     {
     588           0 :         *s->inp = c;
     589           0 :         memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
     590           0 :         s->inl -= 2;
     591             :     }
     592           0 :     return c;
     593             : }
     594             : 
     595             : int
     596       80542 :     foldline(Source * s)
     597             : {
     598       80542 :     int n = 1;
     599             : 
     600             :     /* skip pending wihite spaces */
     601      161084 :     while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
     602             :     {
     603           0 :         n++;
     604           0 :         if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
     605           0 :             break;
     606             :     }
     607             : 
     608             :     /* refill buffer */
     609       80542 :     while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
     610             : 
     611             :     /* skip DOS line ends */
     612      161084 :     if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
     613      154704 :         ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
     614           0 :         n++;
     615             : 
     616       80542 :     if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
     617             :     {
     618       74162 :         memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
     619       74162 :         s->inl -= n + 1;
     620       74162 :         return 1;
     621             :     }
     622        6380 :     return 0;
     623             : }
     624             : 
     625             : int
     626       20306 :     fillbuf(Source * s)
     627             : {
     628             :     int n;
     629             : 
     630       20306 :     if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
     631       19193 :         n = 0;
     632       20306 :     s->inl += n;
     633       20306 :     s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
     634       20306 :     if (n == 0)
     635             :     {
     636       19193 :         s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
     637       19193 :         return EOF;
     638             :     }
     639        1113 :     return 0;
     640             : }
     641             : 
     642             : /*
     643             :  * Push down to new source of characters.
     644             :  * If fd>0 and str==NULL, then from a file `name';
     645             :  * if fd==-1 and str, then from the string.
     646             :  */
     647             : Source *
     648      216954 :     setsource(char *name, int path, int fd, char *str, int wrap)
     649             : {
     650      216954 :     Source *s = new(Source);
     651             :     size_t len;
     652             : 
     653      216954 :     s->line = 1;
     654      216954 :     s->lineinc = 0;
     655      216954 :     s->fd = fd;
     656      216954 :     s->filename = name;
     657      216954 :     s->next = cursource;
     658      216954 :     s->ifdepth = 0;
     659      216954 :     s->pathdepth = path;
     660      216954 :     s->wrap = wrap;
     661             : 
     662      216954 :     cursource = s;
     663             : 
     664      216954 :     if (s->wrap)
     665           0 :         genwrap(0);
     666             : 
     667             :     /* slop at right for EOB */
     668      216954 :     if (str)
     669             :     {
     670      216761 :         len = strlen(str);
     671      216761 :         s->inb = domalloc(len + 4);
     672      216761 :         s->inp = s->inb;
     673      216761 :         strncpy((char *) s->inp, str, len);
     674             :     }
     675             :     else
     676             :     {
     677         193 :         s->inb = domalloc(INS + 4);
     678         193 :         s->inp = s->inb;
     679         193 :         len = 0;
     680             :     }
     681      216954 :     s->inl = s->inp + len;
     682      216954 :     s->inl[0] = s->inl[1] = EOB;
     683             : 
     684      216954 :     return s;
     685             : }
     686             : 
     687             : void
     688      216901 :     unsetsource(void)
     689             : {
     690      216901 :     Source *s = cursource;
     691             : 
     692      216901 :     if (s->wrap)
     693           0 :         genwrap(1);
     694             : 
     695      216901 :     if (s->fd >= 0)
     696             :     {
     697         140 :         close(s->fd);
     698         140 :         dofree(s->inb);
     699             :     }
     700      216901 :     cursource = s->next;
     701      216901 :     dofree(s);
     702      216901 : }
     703             : 
     704             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11