LCOV - code coverage report
Current view: top level - libreoffice/soltools/cpp - _lex.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 250 0.0 %
Date: 2012-12-17 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_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           0 :     expandlex(void)
     265             : {
     266             :      /* const */ struct fsm *fp;
     267             :     int i, j, nstate;
     268             : 
     269           0 :     for (fp = fsm; fp->state >= 0; fp++)
     270             :     {
     271           0 :         for (i = 0; fp->ch[i]; i++)
     272             :         {
     273           0 :             nstate = fp->nextstate;
     274           0 :             if (nstate >= S_SELF)
     275           0 :                 nstate = ~nstate;
     276           0 :             switch (fp->ch[i])
     277             :             {
     278             : 
     279             :                 case C_XX:              /* random characters */
     280           0 :                     for (j = 0; j < 256; j++)
     281           0 :                         bigfsm[j][fp->state] = (short) nstate;
     282           0 :                     continue;
     283             :                 case C_ALPH:
     284           0 :                     for (j = 0; j < 256; j++)
     285           0 :                         if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
     286           0 :                             || j == '_')
     287           0 :                             bigfsm[j][fp->state] = (short) nstate;
     288           0 :                     continue;
     289             :                 case C_NUM:
     290           0 :                     for (j = '0'; j <= '9'; j++)
     291           0 :                         bigfsm[j][fp->state] = (short) nstate;
     292           0 :                     continue;
     293             :                 default:
     294           0 :                     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           0 :     for (i = 0; i < MAXSTATE; i++)
     304             :     {
     305           0 :         for (j = 0; j < 0xFF; j++)
     306           0 :             if (j == '?' || j == '\\' || j == '\n' || j == '\r')
     307             :             {
     308           0 :                 if (bigfsm[j][i] > 0)
     309           0 :                     bigfsm[j][i] = ~bigfsm[j][i];
     310           0 :                 bigfsm[j][i] &= ~QBSBIT;
     311             :             }
     312           0 :         bigfsm[EOB][i] = ~S_EOB;
     313           0 :         if (bigfsm[EOFC][i] >= 0)
     314           0 :             bigfsm[EOFC][i] = ~S_EOF;
     315             :     }
     316           0 : }
     317             : 
     318             : void
     319           0 :     fixlex(void)
     320             : {
     321             :     /* do C++ comments? */
     322           0 :     if ((Cplusplus == 0) || (Cflag != 0))
     323           0 :         bigfsm['/'][COM1] = bigfsm['x'][COM1];
     324           0 : }
     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           0 :     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           0 :     Source *s = cursource;
     341           0 :     int nmac = 0;
     342             : 
     343           0 :     tp = trp->lp;
     344           0 :     ip = s->inp;
     345           0 :     if (reset)
     346             :     {
     347           0 :         s->lineinc = 0;
     348           0 :         if (ip >= s->inl)
     349             :         {                               /* nothing in buffer */
     350           0 :             s->inl = s->inb;
     351           0 :             fillbuf(s);
     352           0 :             ip = s->inp = s->inb;
     353             :         }
     354             :         else
     355           0 :             if (ip >= s->inb + (3 * INS / 4))
     356             :             {
     357           0 :                 memmove(s->inb, ip, 4 + s->inl - ip);
     358           0 :                 s->inl = s->inb + (s->inl - ip);
     359           0 :                 ip = s->inp = s->inb;
     360             :             }
     361             :     }
     362           0 :     maxp = &trp->bp[trp->max];
     363           0 :     runelen = 1;
     364             :     for (;;)
     365             :     {
     366             : continue2:
     367           0 :         if (tp >= maxp)
     368             :         {
     369           0 :             trp->lp = tp;
     370           0 :             tp = growtokenrow(trp);
     371           0 :             maxp = &trp->bp[trp->max];
     372             :         }
     373           0 :         tp->type = UNCLASS;
     374           0 :         tp->t = ip;
     375           0 :         tp->wslen = 0;
     376           0 :         tp->flag = 0;
     377           0 :         state = START;
     378             :         for (;;)
     379             :         {
     380           0 :             oldstate = state;
     381             : 
     382           0 :             c = *ip;
     383             : 
     384           0 :             if ((state = bigfsm[c][state]) >= 0)
     385             :             {
     386           0 :                 ip += runelen;
     387           0 :                 runelen = 1;
     388           0 :                 continue;
     389             :             }
     390           0 :             state = ~state;
     391             :     reswitch:
     392           0 :             switch (state & 0177)
     393             :             {
     394             :                 case S_SELF:
     395           0 :                     ip += runelen;
     396           0 :                     runelen = 1;
     397             :                 case S_SELFB:
     398           0 :                     tp->type = (unsigned char) GETACT(state);
     399           0 :                     tp->len = ip - tp->t;
     400           0 :                     tp++;
     401           0 :                     goto continue2;
     402             : 
     403             :                 case S_NAME:            /* like S_SELFB but with nmac check */
     404           0 :                     tp->type = NAME;
     405           0 :                     tp->len = ip - tp->t;
     406           0 :                     nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
     407           0 :                     tp++;
     408           0 :                     goto continue2;
     409             : 
     410             :                 case S_WS:
     411           0 :                     tp->wslen = ip - tp->t;
     412           0 :                     tp->t = ip;
     413           0 :                     state = START;
     414           0 :                     continue;
     415             : 
     416             :                 default:
     417           0 :                     if ((state & QBSBIT) == 0)
     418             :                     {
     419           0 :                         ip += runelen;
     420           0 :                         runelen = 1;
     421           0 :                         continue;
     422             :                     }
     423           0 :                     state &= ~QBSBIT;
     424           0 :                     s->inp = ip;
     425             : 
     426           0 :                     if (c == '\n')
     427             :                     {
     428           0 :                         while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
     429             : 
     430           0 :                         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           0 :                         goto reswitch;
     437             :                     }
     438             : 
     439           0 :                     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           0 :                     if (c == '?')
     456             :                     {                   /* check trigraph */
     457           0 :                         if (trigraph(s))
     458             :                         {
     459           0 :                             state = oldstate;
     460           0 :                             continue;
     461             :                         }
     462           0 :                         goto reswitch;
     463             :                     }
     464           0 :                     if (c == '\\')
     465             :                     {                   /* line-folding */
     466           0 :                         if (foldline(s))
     467             :                         {
     468           0 :                             s->lineinc++;
     469           0 :                             state = oldstate;
     470           0 :                             continue;
     471             :                         }
     472           0 :                         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           0 :                     s->inp = ip;
     481           0 :                     fillbuf(cursource);
     482           0 :                     state = oldstate;
     483           0 :                     continue;
     484             : 
     485             :                 case S_EOF:
     486           0 :                     tp->type = END;
     487           0 :                     tp->len = 0;
     488           0 :                     s->inp = ip;
     489           0 :                     if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
     490           0 :                         error(WARNING, "No newline at end of file");
     491           0 :                     trp->lp = tp + 1;
     492           0 :                     return nmac;
     493             : 
     494             :                 case S_STNL:
     495           0 :                     error(ERROR, "Unterminated string or char const");
     496             :                 case S_NL:
     497           0 :                     tp->t = ip;
     498           0 :                     tp->type = NL;
     499           0 :                     tp->len = 1;
     500           0 :                     tp->wslen = 0;
     501           0 :                     s->lineinc++;
     502           0 :                     s->inp = ip + 1;
     503           0 :                     trp->lp = tp + 1;
     504           0 :                     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           0 :                     s->lineinc++;
     512           0 :                     state = COM2;
     513           0 :                     ip += runelen;
     514           0 :                     runelen = 1;
     515           0 :                     continue;
     516             : 
     517             :                 case S_EOFCOM:
     518           0 :                     error(WARNING, "EOF inside comment");
     519           0 :                     --ip;
     520             :                 case S_COMMENT:
     521           0 :                     if (!Cflag)
     522             :                     {
     523           0 :                         tp->t = ++ip;
     524           0 :                         tp->t[-1] = ' ';
     525           0 :                         tp->wslen = 1;
     526           0 :                         state = START;
     527           0 :                         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           0 :         }
     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           0 :     trigraph(Source * s)
     549             : {
     550             :     uchar c;
     551             : 
     552           0 :     while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
     553             :     ;
     554           0 :     if (s->inp[1] != '?')
     555           0 :         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           0 :     foldline(Source * s)
     598             : {
     599           0 :     int n = 1;
     600             : 
     601             :     /* skip pending wihite spaces */
     602           0 :     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           0 :     while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
     611             : 
     612             :     /* skip DOS line ends */
     613           0 :     if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
     614           0 :         ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
     615           0 :         n++;
     616             : 
     617           0 :     if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
     618             :     {
     619           0 :         memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
     620           0 :         s->inl -= n + 1;
     621           0 :         return 1;
     622             :     }
     623           0 :     return 0;
     624             : }
     625             : 
     626             : int
     627           0 :     fillbuf(Source * s)
     628             : {
     629             :     int n;
     630             : 
     631           0 :     if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
     632           0 :         n = 0;
     633           0 :     s->inl += n;
     634           0 :     s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
     635           0 :     if (n == 0)
     636             :     {
     637           0 :         s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
     638           0 :         return EOF;
     639             :     }
     640           0 :     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           0 :     setsource(char *name, int path, int fd, char *str, int wrap)
     650             : {
     651           0 :     Source *s = new(Source);
     652             :     size_t len;
     653             : 
     654           0 :     s->line = 1;
     655           0 :     s->lineinc = 0;
     656           0 :     s->fd = fd;
     657           0 :     s->filename = name;
     658           0 :     s->next = cursource;
     659           0 :     s->ifdepth = 0;
     660           0 :     s->pathdepth = path;
     661           0 :     s->wrap = wrap;
     662             : 
     663           0 :     cursource = s;
     664             : 
     665           0 :     if (s->wrap)
     666           0 :         genwrap(0);
     667             : 
     668             :     /* slop at right for EOB */
     669           0 :     if (str)
     670             :     {
     671           0 :         len = strlen(str);
     672           0 :         s->inb = domalloc(len + 4);
     673           0 :         s->inp = s->inb;
     674           0 :         strncpy((char *) s->inp, str, len);
     675             :     }
     676             :     else
     677             :     {
     678           0 :         s->inb = domalloc(INS + 4);
     679           0 :         s->inp = s->inb;
     680           0 :         len = 0;
     681             :     }
     682           0 :     s->inl = s->inp + len;
     683           0 :     s->inl[0] = s->inl[1] = EOB;
     684             : 
     685           0 :     return s;
     686             : }
     687             : 
     688             : void
     689           0 :     unsetsource(void)
     690             : {
     691           0 :     Source *s = cursource;
     692             : 
     693           0 :     if (s->wrap)
     694           0 :         genwrap(1);
     695             : 
     696           0 :     if (s->fd >= 0)
     697             :     {
     698           0 :         close(s->fd);
     699           0 :         dofree(s->inb);
     700             :     }
     701           0 :     cursource = s->next;
     702           0 :     dofree(s);
     703           0 : }
     704             : 
     705             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10