LCOV - code coverage report
Current view: top level - libreoffice/soltools/cpp - _lex.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 187 250 74.8 %
Date: 2012-12-27 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_WS    1
      55             : #define C_ALPH  2
      56             : #define C_NUM   3
      57             : #define C_EOF   4
      58             : #define C_XX    5
      59             : 
      60             : enum state
      61             : {
      62             :     START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
      63             :     CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
      64             :     CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
      65             :     S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
      66             :     S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
      67             : };
      68             : 
      69             : int tottok;
      70             : int tokkind[256];
      71             : struct fsm
      72             : {
      73             :     int state;                          /* if in this state */
      74             :     uchar ch[4];                        /* and see one of these characters */
      75             :     int nextstate;                      /* enter this state if +ve */
      76             : };
      77             : 
      78             :  /*const*/ struct fsm fsm[] = {
      79             :     /* start state */
      80             :          {START, {C_XX}, ACT(UNCLASS, S_SELF)},
      81             :          {START, {' ', '\t', '\v'}, WS1},
      82             :          {START, {C_NUM}, NUM1},
      83             :          {START, {'.'}, NUM3},
      84             :          {START, {C_ALPH}, ID1},
      85             :          {START, {'L'}, ST1},
      86             :          {START, {'"'}, ST2},
      87             :          {START, {'\''}, CC1},
      88             :          {START, {'/'}, COM1},
      89             :          {START, {EOFC}, S_EOF},
      90             :          {START, {'\n'}, S_NL},
      91             :          {START, {'-'}, MINUS1},
      92             :          {START, {'+'}, PLUS1},
      93             :          {START, {'<'}, LT1},
      94             :          {START, {'>'}, GT1},
      95             :          {START, {'='}, ASG1},
      96             :          {START, {'!'}, NOT1},
      97             :          {START, {'&'}, AND1},
      98             :          {START, {'|'}, OR1},
      99             :          {START, {'#'}, SHARP1},
     100             :          {START, {'%'}, PCT1},
     101             :          {START, {'['}, ACT(SBRA, S_SELF)},
     102             :          {START, {']'}, ACT(SKET, S_SELF)},
     103             :          {START, {'('}, ACT(LP, S_SELF)},
     104             :          {START, {')'}, ACT(RP, S_SELF)},
     105             :          {START, {'*'}, STAR1},
     106             :          {START, {','}, ACT(COMMA, S_SELF)},
     107             :          {START, {'?'}, ACT(QUEST, S_SELF)},
     108             :          {START, {':'}, ACT(COLON, S_SELF)},
     109             :          {START, {';'}, ACT(SEMIC, S_SELF)},
     110             :          {START, {'{'}, ACT(CBRA, S_SELF)},
     111             :          {START, {'}'}, ACT(CKET, S_SELF)},
     112             :          {START, {'~'}, ACT(TILDE, S_SELF)},
     113             :          {START, {'^'}, CIRC1},
     114             : 
     115             :     /* saw a digit */
     116             :          {NUM1, {C_XX}, ACT(NUMBER, S_SELFB)},
     117             :          {NUM1, {C_NUM, C_ALPH, '.'}, NUM1},
     118             :          {NUM1, {'E', 'e'}, NUM2},
     119             :          {NUM1, {'_'}, ACT(NUMBER, S_SELFB)},
     120             : 
     121             :     /* saw possible start of exponent, digits-e */
     122             :          {NUM2, {C_XX}, ACT(NUMBER, S_SELFB)},
     123             :          {NUM2, {'+', '-'}, NUM1},
     124             :          {NUM2, {C_NUM, C_ALPH}, NUM1},
     125             :          {NUM2, {'_'}, ACT(NUMBER, S_SELFB)},
     126             : 
     127             :     /* saw a '.', which could be a number or an operator */
     128             :          {NUM3, {C_XX}, ACT(DOT, S_SELFB)},
     129             :          {NUM3, {'.'}, DOTS1},
     130             :          {NUM3, {C_NUM}, NUM1},
     131             : 
     132             :          {DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB)},
     133             :          {DOTS1, {C_NUM}, NUM1},
     134             :          {DOTS1, {'.'}, ACT(ELLIPS, S_SELF)},
     135             : 
     136             :     /* saw a letter or _ */
     137             :          {ID1, {C_XX}, ACT(NAME, S_NAME)},
     138             :          {ID1, {C_ALPH, C_NUM}, ID1},
     139             : 
     140             :     /* saw L (start of wide string?) */
     141             :          {ST1, {C_XX}, ACT(NAME, S_NAME)},
     142             :          {ST1, {C_ALPH, C_NUM}, ID1},
     143             :          {ST1, {'"'}, ST2},
     144             :          {ST1, {'\''}, CC1},
     145             : 
     146             :     /* saw " beginning string */
     147             :          {ST2, {C_XX}, ST2},
     148             :          {ST2, {'"'}, ACT(STRING, S_SELF)},
     149             :          {ST2, {'\\'}, ST3},
     150             :          {ST2, {'\n'}, S_STNL},
     151             :          {ST2, {EOFC}, S_EOFSTR},
     152             : 
     153             :     /* saw \ in string */
     154             :          {ST3, {C_XX}, ST2},
     155             :          {ST3, {'\n'}, S_STNL},
     156             :          {ST3, {EOFC}, S_EOFSTR},
     157             : 
     158             :     /* saw ' beginning character const */
     159             :          {CC1, {C_XX}, CC1},
     160             :          {CC1, {'\''}, ACT(CCON, S_SELF)},
     161             :          {CC1, {'\\'}, CC2},
     162             :          {CC1, {'\n'}, S_STNL},
     163             :          {CC1, {EOFC}, S_EOFSTR},
     164             : 
     165             :     /* saw \ in ccon */
     166             :          {CC2, {C_XX}, CC1},
     167             :          {CC2, {'\n'}, S_STNL},
     168             :          {CC2, {EOFC}, S_EOFSTR},
     169             : 
     170             :     /* saw /, perhaps start of comment */
     171             :          {COM1, {C_XX}, ACT(SLASH, S_SELFB)},
     172             :          {COM1, {'='}, ACT(ASSLASH, S_SELF)},
     173             :          {COM1, {'*'}, COM2},
     174             :          {COM1, {'/'}, COM4},
     175             : 
     176             :     /* saw / followed by *, start of comment */
     177             :          {COM2, {C_XX}, COM2},
     178             :          {COM2, {'\n'}, S_COMNL},
     179             :          {COM2, {'*'}, COM3},
     180             :          {COM2, {EOFC}, S_EOFCOM},
     181             : 
     182             :     /* saw the * possibly ending a comment */
     183             :          {COM3, {C_XX}, COM2},
     184             :          {COM3, {'\n'}, S_COMNL},
     185             :          {COM3, {'*'}, COM3},
     186             :          {COM3, {'/'}, S_COMMENT},
     187             : 
     188             :     /* // comment */
     189             :          {COM4, {C_XX}, COM4},
     190             :          {COM4, {'\n'}, S_NL},
     191             :          {COM4, {EOFC}, S_EOFCOM},
     192             : 
     193             :     /* saw white space, eat it up */
     194             :          {WS1, {C_XX}, S_WS},
     195             :          {WS1, {'\t', '\v', ' '}, WS1},
     196             : 
     197             :     /* saw -, check --, -=, -> */
     198             :          {MINUS1, {C_XX}, ACT(MINUS, S_SELFB)},
     199             :          {MINUS1, {'-'}, ACT(MMINUS, S_SELF)},
     200             :          {MINUS1, {'='}, ACT(ASMINUS, S_SELF)},
     201             :          {MINUS1, {'>'}, ACT(ARROW, S_SELF)},
     202             : 
     203             :     /* saw +, check ++, += */
     204             :          {PLUS1, {C_XX}, ACT(PLUS, S_SELFB)},
     205             :          {PLUS1, {'+'}, ACT(PPLUS, S_SELF)},
     206             :          {PLUS1, {'='}, ACT(ASPLUS, S_SELF)},
     207             : 
     208             :     /* saw <, check <<, <<=, <= */
     209             :          {LT1, {C_XX}, ACT(LT, S_SELFB)},
     210             :          {LT1, {'<'}, LT2},
     211             :          {LT1, {'='}, ACT(LEQ, S_SELF)},
     212             :          {LT2, {C_XX}, ACT(LSH, S_SELFB)},
     213             :          {LT2, {'='}, ACT(ASLSH, S_SELF)},
     214             : 
     215             :     /* saw >, check >>, >>=, >= */
     216             :          {GT1, {C_XX}, ACT(GT, S_SELFB)},
     217             :          {GT1, {'>'}, GT2},
     218             :          {GT1, {'='}, ACT(GEQ, S_SELF)},
     219             :          {GT2, {C_XX}, ACT(RSH, S_SELFB)},
     220             :          {GT2, {'='}, ACT(ASRSH, S_SELF)},
     221             : 
     222             :     /* = */
     223             :          {ASG1, {C_XX}, ACT(ASGN, S_SELFB)},
     224             :          {ASG1, {'='}, ACT(EQ, S_SELF)},
     225             : 
     226             :     /* ! */
     227             :          {NOT1, {C_XX}, ACT(NOT, S_SELFB)},
     228             :          {NOT1, {'='}, ACT(NEQ, S_SELF)},
     229             : 
     230             :     /* & */
     231             :          {AND1, {C_XX}, ACT(AND, S_SELFB)},
     232             :          {AND1, {'&'}, ACT(LAND, S_SELF)},
     233             :          {AND1, {'='}, ACT(ASAND, S_SELF)},
     234             : 
     235             :     /* | */
     236             :          {OR1, {C_XX}, ACT(OR, S_SELFB)},
     237             :          {OR1, {'|'}, ACT(LOR, S_SELF)},
     238             :          {OR1, {'='}, ACT(ASOR, S_SELF)},
     239             : 
     240             :     /* # */
     241             :          {SHARP1, {C_XX}, ACT(SHARP, S_SELFB)},
     242             :          {SHARP1, {'#'}, ACT(DSHARP, S_SELF)},
     243             : 
     244             :     /* % */
     245             :          {PCT1, {C_XX}, ACT(PCT, S_SELFB)},
     246             :          {PCT1, {'='}, ACT(ASPCT, S_SELF)},
     247             : 
     248             :     /* * */
     249             :          {STAR1, {C_XX}, ACT(STAR, S_SELFB)},
     250             :          {STAR1, {'='}, ACT(ASSTAR, S_SELF)},
     251             : 
     252             :     /* ^ */
     253             :          {CIRC1, {C_XX}, ACT(CIRC, S_SELFB)},
     254             :          {CIRC1, {'='}, ACT(ASCIRC, S_SELF)},
     255             : 
     256             :          {-1, "", 0}
     257             : };
     258             : 
     259             : /* first index is char, second is state */
     260             : /* increase #states to power of 2 to encourage use of shift */
     261             : short bigfsm[256][MAXSTATE];
     262             : 
     263             : void
     264          75 :     expandlex(void)
     265             : {
     266             :      /* const */ struct fsm *fp;
     267             :     int i, j, nstate;
     268             : 
     269        9225 :     for (fp = fsm; fp->state >= 0; fp++)
     270             :     {
     271       19125 :         for (i = 0; fp->ch[i]; i++)
     272             :         {
     273        9975 :             nstate = fp->nextstate;
     274        9975 :             if (nstate >= S_SELF)
     275        5625 :                 nstate = ~nstate;
     276        9975 :             switch (fp->ch[i])
     277             :             {
     278             : 
     279             :                 case C_XX:              /* random characters */
     280      578250 :                     for (j = 0; j < 256; j++)
     281      576000 :                         bigfsm[j][fp->state] = (short) nstate;
     282        2250 :                     continue;
     283             :                 case C_ALPH:
     284       96375 :                     for (j = 0; j < 256; j++)
     285       96000 :                         if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
     286       76500 :                             || j == '_')
     287       19875 :                             bigfsm[j][fp->state] = (short) nstate;
     288         375 :                     continue;
     289             :                 case C_NUM:
     290        5775 :                     for (j = '0'; j <= '9'; j++)
     291        5250 :                         bigfsm[j][fp->state] = (short) nstate;
     292         525 :                     continue;
     293             :                 default:
     294        6825 :                     bigfsm[fp->ch[i]][fp->state] = (short) nstate;
     295             :             }
     296             :         }
     297             :     }
     298             : 
     299             :     /*
     300             :      * install special cases for ? (trigraphs),  \ (splicing), runes, and
     301             :      * EOB
     302             :      */
     303        2475 :     for (i = 0; i < MAXSTATE; i++)
     304             :     {
     305      614400 :         for (j = 0; j < 0xFF; j++)
     306      612000 :             if (j == '?' || j == '\\' || j == '\n' || j == '\r')
     307             :             {
     308        9600 :                 if (bigfsm[j][i] > 0)
     309        1575 :                     bigfsm[j][i] = ~bigfsm[j][i];
     310        9600 :                 bigfsm[j][i] &= ~QBSBIT;
     311             :             }
     312        2400 :         bigfsm[EOB][i] = ~S_EOB;
     313        2400 :         if (bigfsm[EOFC][i] >= 0)
     314         225 :             bigfsm[EOFC][i] = ~S_EOF;
     315             :     }
     316          75 : }
     317             : 
     318             : void
     319          75 :     fixlex(void)
     320             : {
     321             :     /* do C++ comments? */
     322          75 :     if ((Cplusplus == 0) || (Cflag != 0))
     323           0 :         bigfsm['/'][COM1] = bigfsm['x'][COM1];
     324          75 : }
     325             : 
     326             : /*
     327             :  * fill in a row of tokens from input, terminated by NL or END
     328             :  * First token is put at trp->lp.
     329             :  * Reset is non-zero when the input buffer can be "rewound."
     330             :  * The value is a flag indicating that possible macros have
     331             :  * been seen in the row.
     332             :  */
     333             : int
     334       70386 :     gettokens(Tokenrow * trp, int reset)
     335             : {
     336             :     register int c, state, oldstate;
     337             :     register uchar *ip;
     338             :     register Token *tp, *maxp;
     339             :     int runelen;
     340       70386 :     Source *s = cursource;
     341       70386 :     int nmac = 0;
     342             : 
     343       70386 :     tp = trp->lp;
     344       70386 :     ip = s->inp;
     345       70386 :     if (reset)
     346             :     {
     347       70382 :         s->lineinc = 0;
     348       70382 :         if (ip >= s->inl)
     349             :         {                               /* nothing in buffer */
     350         462 :             s->inl = s->inb;
     351         462 :             fillbuf(s);
     352         462 :             ip = s->inp = s->inb;
     353             :         }
     354             :         else
     355       69920 :             if (ip >= s->inb + (3 * INS / 4))
     356             :             {
     357         166 :                 memmove(s->inb, ip, 4 + s->inl - ip);
     358         166 :                 s->inl = s->inb + (s->inl - ip);
     359         166 :                 ip = s->inp = s->inb;
     360             :             }
     361             :     }
     362       70386 :     maxp = &trp->bp[trp->max];
     363       70386 :     runelen = 1;
     364             :     for (;;)
     365             :     {
     366             : continue2:
     367     1737150 :         if (tp >= maxp)
     368             :         {
     369       20823 :             trp->lp = tp;
     370       20823 :             tp = growtokenrow(trp);
     371       20823 :             maxp = &trp->bp[trp->max];
     372             :         }
     373     1737150 :         tp->type = UNCLASS;
     374     1737150 :         tp->t = ip;
     375     1737150 :         tp->wslen = 0;
     376     1737150 :         tp->flag = 0;
     377     1737150 :         state = START;
     378             :         for (;;)
     379             :         {
     380     8080889 :             oldstate = state;
     381             : 
     382     8080889 :             c = *ip;
     383             : 
     384     8080889 :             if ((state = bigfsm[c][state]) >= 0)
     385             :             {
     386     5605130 :                 ip += runelen;
     387     5605130 :                 runelen = 1;
     388     5605130 :                 continue;
     389             :             }
     390     2475759 :             state = ~state;
     391             :     reswitch:
     392     2550229 :             switch (state & 0177)
     393             :             {
     394             :                 case S_SELF:
     395      761167 :                     ip += runelen;
     396      761167 :                     runelen = 1;
     397             :                 case S_SELFB:
     398      955363 :                     tp->type = (unsigned char) GETACT(state);
     399      955363 :                     tp->len = ip - tp->t;
     400      955363 :                     tp++;
     401      955363 :                     goto continue2;
     402             : 
     403             :                 case S_NAME:            /* like S_SELFB but with nmac check */
     404      711401 :                     tp->type = NAME;
     405      711401 :                     tp->len = ip - tp->t;
     406      711401 :                     nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
     407      711401 :                     tp++;
     408      711401 :                     goto continue2;
     409             : 
     410             :                 case S_WS:
     411      579974 :                     tp->wslen = ip - tp->t;
     412      579974 :                     tp->t = ip;
     413      579974 :                     state = START;
     414      579974 :                     continue;
     415             : 
     416             :                 default:
     417      208077 :                     if ((state & QBSBIT) == 0)
     418             :                     {
     419        2353 :                         ip += runelen;
     420        2353 :                         runelen = 1;
     421        2353 :                         continue;
     422             :                     }
     423      205724 :                     state &= ~QBSBIT;
     424      205724 :                     s->inp = ip;
     425             : 
     426      205724 :                     if (c == '\n')
     427             :                     {
     428       66204 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     429             : 
     430       66204 :                         if (s->inp[1] == '\r')
     431             :                         {
     432           0 :                             memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
     433           0 :                             s->inl -= 1;
     434             :                         }
     435             : 
     436       66204 :                         goto reswitch;
     437             :                     }
     438             : 
     439      139520 :                     if (c == '\r')
     440             :                     {
     441           0 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     442             : 
     443           0 :                         if (s->inp[1] == '\n')
     444             :                         {
     445           0 :                             memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
     446           0 :                             s->inl -= 1;
     447             :                         }
     448             :                         else
     449           0 :                             *s->inp = '\n';
     450             : 
     451           0 :                         state = oldstate;
     452           0 :                         continue;
     453             :                     }
     454             : 
     455      139520 :                     if (c == '?')
     456             :                     {                   /* check trigraph */
     457           1 :                         if (trigraph(s))
     458             :                         {
     459           0 :                             state = oldstate;
     460           0 :                             continue;
     461             :                         }
     462           1 :                         goto reswitch;
     463             :                     }
     464      139519 :                     if (c == '\\')
     465             :                     {                   /* line-folding */
     466      139519 :                         if (foldline(s))
     467             :                         {
     468      131254 :                             s->lineinc++;
     469      131254 :                             state = oldstate;
     470      131254 :                             continue;
     471             :                         }
     472        8265 :                         goto reswitch;
     473             :                     }
     474           0 :                     error(WARNING, "Lexical botch in cpp");
     475           0 :                     ip += runelen;
     476           0 :                     runelen = 1;
     477           0 :                     continue;
     478             : 
     479             :                 case S_EOB:
     480       22569 :                     s->inp = ip;
     481       22569 :                     fillbuf(cursource);
     482       22569 :                     state = oldstate;
     483       22569 :                     continue;
     484             : 
     485             :                 case S_EOF:
     486       21301 :                     tp->type = END;
     487       21301 :                     tp->len = 0;
     488       21301 :                     s->inp = ip;
     489       21301 :                     if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
     490           0 :                         error(WARNING, "No newline at end of file");
     491       21301 :                     trp->lp = tp + 1;
     492       21301 :                     return nmac;
     493             : 
     494             :                 case S_STNL:
     495           0 :                     error(ERROR, "Unterminated string or char const");
     496             :                 case S_NL:
     497       49085 :                     tp->t = ip;
     498       49085 :                     tp->type = NL;
     499       49085 :                     tp->len = 1;
     500       49085 :                     tp->wslen = 0;
     501       49085 :                     s->lineinc++;
     502       49085 :                     s->inp = ip + 1;
     503       49085 :                     trp->lp = tp + 1;
     504       49085 :                     return nmac;
     505             : 
     506             :                 case S_EOFSTR:
     507           0 :                     error(FATAL, "EOF in string or char constant");
     508           0 :                     break;
     509             : 
     510             :                 case S_COMNL:
     511        2037 :                     s->lineinc++;
     512        2037 :                     state = COM2;
     513        2037 :                     ip += runelen;
     514        2037 :                     runelen = 1;
     515        2037 :                     continue;
     516             : 
     517             :                 case S_EOFCOM:
     518           0 :                     error(WARNING, "EOF inside comment");
     519           0 :                     --ip;
     520             :                 case S_COMMENT:
     521         422 :                     if (!Cflag)
     522             :                     {
     523         422 :                         tp->t = ++ip;
     524         422 :                         tp->t[-1] = ' ';
     525         422 :                         tp->wslen = 1;
     526         422 :                         state = START;
     527         422 :                         continue;
     528             :                     }
     529             :                     else
     530             :                     {
     531           0 :                         runelen = 1;
     532           0 :                         s->lineinc = 0;;
     533           0 :                         tp->type = COMMENT;
     534           0 :                         tp->flag |= XTWS;
     535             :                     }
     536             :             }
     537           0 :             break;
     538     6343739 :         }
     539           0 :         ip += runelen;
     540           0 :         runelen = 1;
     541           0 :         tp->len = ip - tp->t;
     542           0 :         tp++;
     543           0 :     }
     544             : }
     545             : 
     546             : /* have seen ?; handle the trigraph it starts (if any) else 0 */
     547             : int
     548           1 :     trigraph(Source * s)
     549             : {
     550             :     uchar c;
     551             : 
     552           1 :     while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
     553             :     ;
     554           1 :     if (s->inp[1] != '?')
     555           1 :         return 0;
     556           0 :     c = 0;
     557           0 :     switch (s->inp[2])
     558             :     {
     559             :         case '=':
     560           0 :             c = '#';
     561           0 :             break;
     562             :         case '(':
     563           0 :             c = '[';
     564           0 :             break;
     565             :         case '/':
     566           0 :             c = '\\';
     567           0 :             break;
     568             :         case ')':
     569           0 :             c = ']';
     570           0 :             break;
     571             :         case '\'':
     572           0 :             c = '^';
     573           0 :             break;
     574             :         case '<':
     575           0 :             c = '{';
     576           0 :             break;
     577             :         case '!':
     578           0 :             c = '|';
     579           0 :             break;
     580             :         case '>':
     581           0 :             c = '}';
     582           0 :             break;
     583             :         case '-':
     584           0 :             c = '~';
     585           0 :             break;
     586             :     }
     587           0 :     if (c)
     588             :     {
     589           0 :         *s->inp = c;
     590           0 :         memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
     591           0 :         s->inl -= 2;
     592             :     }
     593           0 :     return c;
     594             : }
     595             : 
     596             : int
     597      139519 :     foldline(Source * s)
     598             : {
     599      139519 :     int n = 1;
     600             : 
     601             :     /* skip pending wihite spaces */
     602      279038 :     while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
     603             :     {
     604           0 :         n++;
     605           0 :         if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
     606           0 :             break;
     607             :     }
     608             : 
     609             :     /* refill buffer */
     610      139519 :     while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
     611             : 
     612             :     /* skip DOS line ends */
     613      279038 :     if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
     614      270773 :         ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
     615           0 :         n++;
     616             : 
     617      139519 :     if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
     618             :     {
     619      131254 :         memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
     620      131254 :         s->inl -= n + 1;
     621      131254 :         return 1;
     622             :     }
     623        8265 :     return 0;
     624             : }
     625             : 
     626             : int
     627       23313 :     fillbuf(Source * s)
     628             : {
     629             :     int n;
     630             : 
     631       23313 :     if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
     632       21578 :         n = 0;
     633       23313 :     s->inl += n;
     634       23313 :     s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
     635       23313 :     if (n == 0)
     636             :     {
     637       21578 :         s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
     638       21578 :         return EOF;
     639             :     }
     640        1735 :     return 0;
     641             : }
     642             : 
     643             : /*
     644             :  * Push down to new source of characters.
     645             :  * If fd>0 and str==NULL, then from a file `name';
     646             :  * if fd==-1 and str, then from the string.
     647             :  */
     648             : Source *
     649      224074 :     setsource(char *name, int path, int fd, char *str, int wrap)
     650             : {
     651      224074 :     Source *s = new(Source);
     652             :     size_t len;
     653             : 
     654      224074 :     s->line = 1;
     655      224074 :     s->lineinc = 0;
     656      224074 :     s->fd = fd;
     657      224074 :     s->filename = name;
     658      224074 :     s->next = cursource;
     659      224074 :     s->ifdepth = 0;
     660      224074 :     s->pathdepth = path;
     661      224074 :     s->wrap = wrap;
     662             : 
     663      224074 :     cursource = s;
     664             : 
     665      224074 :     if (s->wrap)
     666           0 :         genwrap(0);
     667             : 
     668             :     /* slop at right for EOB */
     669      224074 :     if (str)
     670             :     {
     671      223843 :         len = strlen(str);
     672      223843 :         s->inb = domalloc(len + 4);
     673      223843 :         s->inp = s->inb;
     674      223843 :         strncpy((char *) s->inp, str, len);
     675             :     }
     676             :     else
     677             :     {
     678         231 :         s->inb = domalloc(INS + 4);
     679         231 :         s->inp = s->inb;
     680         231 :         len = 0;
     681             :     }
     682      224074 :     s->inl = s->inp + len;
     683      224074 :     s->inl[0] = s->inl[1] = EOB;
     684             : 
     685      224074 :     return s;
     686             : }
     687             : 
     688             : void
     689      223999 :     unsetsource(void)
     690             : {
     691      223999 :     Source *s = cursource;
     692             : 
     693      223999 :     if (s->wrap)
     694           0 :         genwrap(1);
     695             : 
     696      223999 :     if (s->fd >= 0)
     697             :     {
     698         156 :         close(s->fd);
     699         156 :         dofree(s->inb);
     700             :     }
     701      223999 :     cursource = s->next;
     702      223999 :     dofree(s);
     703      223999 : }
     704             : 
     705             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10