LCOV - code coverage report
Current view: top level - soltools/cpp - _lex.c (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 250 0.0 %
Date: 2014-04-14 Functions: 0 8 0.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           0 :     expandlex(void)
     263             : {
     264             :      /* const */ struct fsm *fp;
     265             :     int i, j, nstate;
     266             : 
     267           0 :     for (fp = fsm; fp->state >= 0; fp++)
     268             :     {
     269           0 :         for (i = 0; fp->ch[i]; i++)
     270             :         {
     271           0 :             nstate = fp->nextstate;
     272           0 :             if (nstate >= S_SELF)
     273           0 :                 nstate = ~nstate;
     274           0 :             switch (fp->ch[i])
     275             :             {
     276             : 
     277             :                 case C_XX:              /* random characters */
     278           0 :                     for (j = 0; j < 256; j++)
     279           0 :                         bigfsm[j][fp->state] = (short) nstate;
     280           0 :                     continue;
     281             :                 case C_ALPH:
     282           0 :                     for (j = 0; j < 256; j++)
     283           0 :                         if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
     284           0 :                             || j == '_')
     285           0 :                             bigfsm[j][fp->state] = (short) nstate;
     286           0 :                     continue;
     287             :                 case C_NUM:
     288           0 :                     for (j = '0'; j <= '9'; j++)
     289           0 :                         bigfsm[j][fp->state] = (short) nstate;
     290           0 :                     continue;
     291             :                 default:
     292           0 :                     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           0 :     for (i = 0; i < MAXSTATE; i++)
     302             :     {
     303           0 :         for (j = 0; j < 0xFF; j++)
     304           0 :             if (j == '?' || j == '\\' || j == '\n' || j == '\r')
     305             :             {
     306           0 :                 if (bigfsm[j][i] > 0)
     307           0 :                     bigfsm[j][i] = ~bigfsm[j][i];
     308           0 :                 bigfsm[j][i] &= ~QBSBIT;
     309             :             }
     310           0 :         bigfsm[EOB][i] = ~S_EOB;
     311           0 :         if (bigfsm[EOFC][i] >= 0)
     312           0 :             bigfsm[EOFC][i] = ~S_EOF;
     313             :     }
     314           0 : }
     315             : 
     316             : void
     317           0 :     fixlex(void)
     318             : {
     319             :     /* do C++ comments? */
     320           0 :     if ((Cplusplus == 0) || (Cflag != 0))
     321           0 :         bigfsm['/'][COM1] = bigfsm['x'][COM1];
     322           0 : }
     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           0 :     gettokens(Tokenrow * trp, int reset)
     333             : {
     334             :     register int c, state, oldstate;
     335             :     register uchar *ip;
     336             :     register Token *tp, *maxp;
     337             :     int runelen;
     338           0 :     Source *s = cursource;
     339           0 :     int nmac = 0;
     340             : 
     341           0 :     tp = trp->lp;
     342           0 :     ip = s->inp;
     343           0 :     if (reset)
     344             :     {
     345           0 :         s->lineinc = 0;
     346           0 :         if (ip >= s->inl)
     347             :         {                               /* nothing in buffer */
     348           0 :             s->inl = s->inb;
     349           0 :             fillbuf(s);
     350           0 :             ip = s->inp = s->inb;
     351             :         }
     352             :         else
     353           0 :             if (ip >= s->inb + (3 * INS / 4))
     354             :             {
     355           0 :                 memmove(s->inb, ip, 4 + s->inl - ip);
     356           0 :                 s->inl = s->inb + (s->inl - ip);
     357           0 :                 ip = s->inp = s->inb;
     358             :             }
     359             :     }
     360           0 :     maxp = &trp->bp[trp->max];
     361           0 :     runelen = 1;
     362             :     for (;;)
     363             :     {
     364             : continue2:
     365           0 :         if (tp >= maxp)
     366             :         {
     367           0 :             trp->lp = tp;
     368           0 :             tp = growtokenrow(trp);
     369           0 :             maxp = &trp->bp[trp->max];
     370             :         }
     371           0 :         tp->type = UNCLASS;
     372           0 :         tp->t = ip;
     373           0 :         tp->wslen = 0;
     374           0 :         tp->flag = 0;
     375           0 :         state = START;
     376             :         for (;;)
     377             :         {
     378           0 :             oldstate = state;
     379             : 
     380           0 :             c = *ip;
     381             : 
     382           0 :             if ((state = bigfsm[c][state]) >= 0)
     383             :             {
     384           0 :                 ip += runelen;
     385           0 :                 runelen = 1;
     386           0 :                 continue;
     387             :             }
     388           0 :             state = ~state;
     389             :     reswitch:
     390           0 :             switch (state & 0177)
     391             :             {
     392             :                 case S_SELF:
     393           0 :                     ip += runelen;
     394           0 :                     runelen = 1;
     395             :                 case S_SELFB:
     396           0 :                     tp->type = (unsigned char) GETACT(state);
     397           0 :                     tp->len = ip - tp->t;
     398           0 :                     tp++;
     399           0 :                     goto continue2;
     400             : 
     401             :                 case S_NAME:            /* like S_SELFB but with nmac check */
     402           0 :                     tp->type = NAME;
     403           0 :                     tp->len = ip - tp->t;
     404           0 :                     nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
     405           0 :                     tp++;
     406           0 :                     goto continue2;
     407             : 
     408             :                 case S_WS:
     409           0 :                     tp->wslen = ip - tp->t;
     410           0 :                     tp->t = ip;
     411           0 :                     state = START;
     412           0 :                     continue;
     413             : 
     414             :                 default:
     415           0 :                     if ((state & QBSBIT) == 0)
     416             :                     {
     417           0 :                         ip += runelen;
     418           0 :                         runelen = 1;
     419           0 :                         continue;
     420             :                     }
     421           0 :                     state &= ~QBSBIT;
     422           0 :                     s->inp = ip;
     423             : 
     424           0 :                     if (c == '\n')
     425             :                     {
     426           0 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     427             : 
     428           0 :                         if (s->inp[1] == '\r')
     429             :                         {
     430           0 :                             memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
     431           0 :                             s->inl -= 1;
     432             :                         }
     433             : 
     434           0 :                         goto reswitch;
     435             :                     }
     436             : 
     437           0 :                     if (c == '\r')
     438             :                     {
     439           0 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     440             : 
     441           0 :                         if (s->inp[1] == '\n')
     442             :                         {
     443           0 :                             memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
     444           0 :                             s->inl -= 1;
     445             :                         }
     446             :                         else
     447           0 :                             *s->inp = '\n';
     448             : 
     449           0 :                         state = oldstate;
     450           0 :                         continue;
     451             :                     }
     452             : 
     453           0 :                     if (c == '?')
     454             :                     {                   /* check trigraph */
     455           0 :                         if (trigraph(s))
     456             :                         {
     457           0 :                             state = oldstate;
     458           0 :                             continue;
     459             :                         }
     460           0 :                         goto reswitch;
     461             :                     }
     462           0 :                     if (c == '\\')
     463             :                     {                   /* line-folding */
     464           0 :                         if (foldline(s))
     465             :                         {
     466           0 :                             s->lineinc++;
     467           0 :                             state = oldstate;
     468           0 :                             continue;
     469             :                         }
     470           0 :                         goto reswitch;
     471             :                     }
     472           0 :                     error(WARNING, "Lexical botch in cpp");
     473           0 :                     ip += runelen;
     474           0 :                     runelen = 1;
     475           0 :                     continue;
     476             : 
     477             :                 case S_EOB:
     478           0 :                     s->inp = ip;
     479           0 :                     fillbuf(cursource);
     480           0 :                     state = oldstate;
     481           0 :                     continue;
     482             : 
     483             :                 case S_EOF:
     484           0 :                     tp->type = END;
     485           0 :                     tp->len = 0;
     486           0 :                     s->inp = ip;
     487           0 :                     if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
     488           0 :                         error(WARNING, "No newline at end of file");
     489           0 :                     trp->lp = tp + 1;
     490           0 :                     return nmac;
     491             : 
     492             :                 case S_STNL:
     493           0 :                     error(ERROR, "Unterminated string or char const");
     494             :                 case S_NL:
     495           0 :                     tp->t = ip;
     496           0 :                     tp->type = NL;
     497           0 :                     tp->len = 1;
     498           0 :                     tp->wslen = 0;
     499           0 :                     s->lineinc++;
     500           0 :                     s->inp = ip + 1;
     501           0 :                     trp->lp = tp + 1;
     502           0 :                     return nmac;
     503             : 
     504             :                 case S_EOFSTR:
     505           0 :                     error(FATAL, "EOF in string or char constant");
     506           0 :                     break;
     507             : 
     508             :                 case S_COMNL:
     509           0 :                     s->lineinc++;
     510           0 :                     state = COM2;
     511           0 :                     ip += runelen;
     512           0 :                     runelen = 1;
     513           0 :                     continue;
     514             : 
     515             :                 case S_EOFCOM:
     516           0 :                     error(WARNING, "EOF inside comment");
     517           0 :                     --ip;
     518             :                 case S_COMMENT:
     519           0 :                     if (!Cflag)
     520             :                     {
     521           0 :                         tp->t = ++ip;
     522           0 :                         tp->t[-1] = ' ';
     523           0 :                         tp->wslen = 1;
     524           0 :                         state = START;
     525           0 :                         continue;
     526             :                     }
     527             :                     else
     528             :                     {
     529           0 :                         runelen = 1;
     530           0 :                         s->lineinc = 0;;
     531           0 :                         tp->type = COMMENT;
     532           0 :                         tp->flag |= XTWS;
     533             :                     }
     534             :             }
     535           0 :             break;
     536           0 :         }
     537           0 :         ip += runelen;
     538           0 :         runelen = 1;
     539           0 :         tp->len = ip - tp->t;
     540           0 :         tp++;
     541           0 :     }
     542             : }
     543             : 
     544             : /* have seen ?; handle the trigraph it starts (if any) else 0 */
     545             : int
     546           0 :     trigraph(Source * s)
     547             : {
     548             :     uchar c;
     549             : 
     550           0 :     while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
     551             :     ;
     552           0 :     if (s->inp[1] != '?')
     553           0 :         return 0;
     554           0 :     c = 0;
     555           0 :     switch (s->inp[2])
     556             :     {
     557             :         case '=':
     558           0 :             c = '#';
     559           0 :             break;
     560             :         case '(':
     561           0 :             c = '[';
     562           0 :             break;
     563             :         case '/':
     564           0 :             c = '\\';
     565           0 :             break;
     566             :         case ')':
     567           0 :             c = ']';
     568           0 :             break;
     569             :         case '\'':
     570           0 :             c = '^';
     571           0 :             break;
     572             :         case '<':
     573           0 :             c = '{';
     574           0 :             break;
     575             :         case '!':
     576           0 :             c = '|';
     577           0 :             break;
     578             :         case '>':
     579           0 :             c = '}';
     580           0 :             break;
     581             :         case '-':
     582           0 :             c = '~';
     583           0 :             break;
     584             :     }
     585           0 :     if (c)
     586             :     {
     587           0 :         *s->inp = c;
     588           0 :         memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
     589           0 :         s->inl -= 2;
     590             :     }
     591           0 :     return c;
     592             : }
     593             : 
     594             : int
     595           0 :     foldline(Source * s)
     596             : {
     597           0 :     int n = 1;
     598             : 
     599             :     /* skip pending wihite spaces */
     600           0 :     while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
     601             :     {
     602           0 :         n++;
     603           0 :         if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
     604           0 :             break;
     605             :     }
     606             : 
     607             :     /* refill buffer */
     608           0 :     while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
     609             : 
     610             :     /* skip DOS line ends */
     611           0 :     if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
     612           0 :         ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
     613           0 :         n++;
     614             : 
     615           0 :     if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
     616             :     {
     617           0 :         memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
     618           0 :         s->inl -= n + 1;
     619           0 :         return 1;
     620             :     }
     621           0 :     return 0;
     622             : }
     623             : 
     624             : int
     625           0 :     fillbuf(Source * s)
     626             : {
     627             :     int n;
     628             : 
     629           0 :     if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
     630           0 :         n = 0;
     631           0 :     s->inl += n;
     632           0 :     s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
     633           0 :     if (n == 0)
     634             :     {
     635           0 :         s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
     636           0 :         return EOF;
     637             :     }
     638           0 :     return 0;
     639             : }
     640             : 
     641             : /*
     642             :  * Push down to new source of characters.
     643             :  * If fd>0 and str==NULL, then from a file `name';
     644             :  * if fd==-1 and str, then from the string.
     645             :  */
     646             : Source *
     647           0 :     setsource(char *name, int path, int fd, char *str, int wrap)
     648             : {
     649           0 :     Source *s = new(Source);
     650             :     size_t len;
     651             : 
     652           0 :     s->line = 1;
     653           0 :     s->lineinc = 0;
     654           0 :     s->fd = fd;
     655           0 :     s->filename = name;
     656           0 :     s->next = cursource;
     657           0 :     s->ifdepth = 0;
     658           0 :     s->pathdepth = path;
     659           0 :     s->wrap = wrap;
     660             : 
     661           0 :     cursource = s;
     662             : 
     663           0 :     if (s->wrap)
     664           0 :         genwrap(0);
     665             : 
     666             :     /* slop at right for EOB */
     667           0 :     if (str)
     668             :     {
     669           0 :         len = strlen(str);
     670           0 :         s->inb = domalloc(len + 4);
     671           0 :         s->inp = s->inb;
     672           0 :         strncpy((char *) s->inp, str, len);
     673             :     }
     674             :     else
     675             :     {
     676           0 :         s->inb = domalloc(INS + 4);
     677           0 :         s->inp = s->inb;
     678           0 :         len = 0;
     679             :     }
     680           0 :     s->inl = s->inp + len;
     681           0 :     s->inl[0] = s->inl[1] = EOB;
     682             : 
     683           0 :     return s;
     684             : }
     685             : 
     686             : void
     687           0 :     unsetsource(void)
     688             : {
     689           0 :     Source *s = cursource;
     690             : 
     691           0 :     if (s->wrap)
     692           0 :         genwrap(1);
     693             : 
     694           0 :     if (s->fd >= 0)
     695             :     {
     696           0 :         close(s->fd);
     697           0 :         dofree(s->inb);
     698             :     }
     699           0 :     cursource = s->next;
     700           0 :     dofree(s);
     701           0 : }
     702             : 
     703             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10