695 lines
18 KiB
C
695 lines
18 KiB
C
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#if (defined(_WIN32) || defined(_MSDOS) || defined(__IBMC__)) && !(defined S390)
|
|||
|
#include <io.h>
|
|||
|
#else
|
|||
|
#include <unistd.h>
|
|||
|
#endif
|
|||
|
#include "cpp.h"
|
|||
|
|
|||
|
/*
|
|||
|
* lexical FSM encoding
|
|||
|
* when in state state, and one of the characters
|
|||
|
* in ch arrives, enter nextstate.
|
|||
|
* States >= S_SELF are either final, or at least require special action.
|
|||
|
* In 'fsm' there is a line for each state X charset X nextstate.
|
|||
|
* List chars that overwrite previous entries later (e.g. C_ALPH
|
|||
|
* can be overridden by '_' by a later entry; and C_XX is the
|
|||
|
* the universal set, and should always be first.
|
|||
|
* States above S_SELF are represented in the big table as negative values.
|
|||
|
* S_SELF and S_SELFB encode the resulting token type in the upper bits.
|
|||
|
* These actions differ in that S_SELF doesn't have a lookahead char,
|
|||
|
* S_SELFB does.
|
|||
|
*
|
|||
|
* The encoding is blown out into a big table for time-efficiency.
|
|||
|
* Entries have
|
|||
|
* nextstate: 6 bits; ?\ marker: 1 bit; tokentype: 9 bits.
|
|||
|
*/
|
|||
|
|
|||
|
#define MAXSTATE 32
|
|||
|
#define ACT(tok,act) ((tok<<7)+act)
|
|||
|
#define QBSBIT 0100
|
|||
|
#define GETACT(st) (st>>7)&0x1ff
|
|||
|
|
|||
|
/* character classes */
|
|||
|
#define C_WS 1
|
|||
|
#define C_ALPH 2
|
|||
|
#define C_NUM 3
|
|||
|
#define C_EOF 4
|
|||
|
#ifdef S390
|
|||
|
#define C_XX 6
|
|||
|
#else
|
|||
|
#define C_XX 5
|
|||
|
#endif
|
|||
|
|
|||
|
enum state
|
|||
|
{
|
|||
|
START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
|
|||
|
CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
|
|||
|
CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
|
|||
|
S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
|
|||
|
S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
|
|||
|
};
|
|||
|
|
|||
|
int tottok;
|
|||
|
int tokkind[256];
|
|||
|
struct fsm
|
|||
|
{
|
|||
|
int state; /* if in this state */
|
|||
|
uchar ch[4]; /* and see one of these characters */
|
|||
|
int nextstate; /* enter this state if +ve */
|
|||
|
};
|
|||
|
|
|||
|
/*const*/ struct fsm fsm[] = {
|
|||
|
/* start state */
|
|||
|
START, {C_XX}, ACT(UNCLASS, S_SELF),
|
|||
|
START, {' ', '\t', '\v'}, WS1,
|
|||
|
START, {C_NUM}, NUM1,
|
|||
|
START, {'.'}, NUM3,
|
|||
|
START, {C_ALPH}, ID1,
|
|||
|
START, {'L'}, ST1,
|
|||
|
START, {'"'}, ST2,
|
|||
|
START, {'\''}, CC1,
|
|||
|
START, {'/'}, COM1,
|
|||
|
START, {EOFC}, S_EOF,
|
|||
|
START, {'\n'}, S_NL,
|
|||
|
START, {'-'}, MINUS1,
|
|||
|
START, {'+'}, PLUS1,
|
|||
|
START, {'<'}, LT1,
|
|||
|
START, {'>'}, GT1,
|
|||
|
START, {'='}, ASG1,
|
|||
|
START, {'!'}, NOT1,
|
|||
|
START, {'&'}, AND1,
|
|||
|
START, {'|'}, OR1,
|
|||
|
START, {'#'}, SHARP1,
|
|||
|
START, {'%'}, PCT1,
|
|||
|
START, {'['}, ACT(SBRA, S_SELF),
|
|||
|
START, {']'}, ACT(SKET, S_SELF),
|
|||
|
START, {'('}, ACT(LP, S_SELF),
|
|||
|
START, {')'}, ACT(RP, S_SELF),
|
|||
|
START, {'*'}, STAR1,
|
|||
|
START, {','}, ACT(COMMA, S_SELF),
|
|||
|
START, {'?'}, ACT(QUEST, S_SELF),
|
|||
|
START, {':'}, ACT(COLON, S_SELF),
|
|||
|
START, {';'}, ACT(SEMIC, S_SELF),
|
|||
|
START, {'{'}, ACT(CBRA, S_SELF),
|
|||
|
START, {'}'}, ACT(CKET, S_SELF),
|
|||
|
START, {'~'}, ACT(TILDE, S_SELF),
|
|||
|
START, {'^'}, CIRC1,
|
|||
|
|
|||
|
/* saw a digit */
|
|||
|
NUM1, {C_XX}, ACT(NUMBER, S_SELFB),
|
|||
|
NUM1, {C_NUM, C_ALPH, '.'}, NUM1,
|
|||
|
NUM1, {'E', 'e'}, NUM2,
|
|||
|
NUM1, {'_'}, ACT(NUMBER, S_SELFB),
|
|||
|
|
|||
|
/* saw possible start of exponent, digits-e */
|
|||
|
NUM2, {C_XX}, ACT(NUMBER, S_SELFB),
|
|||
|
NUM2, {'+', '-'}, NUM1,
|
|||
|
NUM2, {C_NUM, C_ALPH}, NUM1,
|
|||
|
NUM2, {'_'}, ACT(NUMBER, S_SELFB),
|
|||
|
|
|||
|
/* saw a '.', which could be a number or an operator */
|
|||
|
NUM3, {C_XX}, ACT(DOT, S_SELFB),
|
|||
|
NUM3, {'.'}, DOTS1,
|
|||
|
NUM3, {C_NUM}, NUM1,
|
|||
|
|
|||
|
DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB),
|
|||
|
DOTS1, {C_NUM}, NUM1,
|
|||
|
DOTS1, {'.'}, ACT(ELLIPS, S_SELF),
|
|||
|
|
|||
|
/* saw a letter or _ */
|
|||
|
ID1, {C_XX}, ACT(NAME, S_NAME),
|
|||
|
ID1, {C_ALPH, C_NUM}, ID1,
|
|||
|
|
|||
|
/* saw L (start of wide string?) */
|
|||
|
ST1, {C_XX}, ACT(NAME, S_NAME),
|
|||
|
ST1, {C_ALPH, C_NUM}, ID1,
|
|||
|
ST1, {'"'}, ST2,
|
|||
|
ST1, {'\''}, CC1,
|
|||
|
|
|||
|
/* saw " beginning string */
|
|||
|
ST2, {C_XX}, ST2,
|
|||
|
ST2, {'"'}, ACT(STRING, S_SELF),
|
|||
|
ST2, {'\\'}, ST3,
|
|||
|
ST2, {'\n'}, S_STNL,
|
|||
|
ST2, {EOFC}, S_EOFSTR,
|
|||
|
|
|||
|
/* saw \ in string */
|
|||
|
ST3, {C_XX}, ST2,
|
|||
|
ST3, {'\n'}, S_STNL,
|
|||
|
ST3, {EOFC}, S_EOFSTR,
|
|||
|
|
|||
|
/* saw ' beginning character const */
|
|||
|
CC1, {C_XX}, CC1,
|
|||
|
CC1, {'\''}, ACT(CCON, S_SELF),
|
|||
|
CC1, {'\\'}, CC2,
|
|||
|
CC1, {'\n'}, S_STNL,
|
|||
|
CC1, {EOFC}, S_EOFSTR,
|
|||
|
|
|||
|
/* saw \ in ccon */
|
|||
|
CC2, {C_XX}, CC1,
|
|||
|
CC2, {'\n'}, S_STNL,
|
|||
|
CC2, {EOFC}, S_EOFSTR,
|
|||
|
|
|||
|
/* saw /, perhaps start of comment */
|
|||
|
COM1, {C_XX}, ACT(SLASH, S_SELFB),
|
|||
|
COM1, {'='}, ACT(ASSLASH, S_SELF),
|
|||
|
COM1, {'*'}, COM2,
|
|||
|
COM1, {'/'}, COM4,
|
|||
|
|
|||
|
/* saw "/*", start of comment */
|
|||
|
COM2, {C_XX}, COM2,
|
|||
|
COM2, {'\n'}, S_COMNL,
|
|||
|
COM2, {'*'}, COM3,
|
|||
|
COM2, {EOFC}, S_EOFCOM,
|
|||
|
|
|||
|
/* saw the * possibly ending a comment */
|
|||
|
COM3, {C_XX}, COM2,
|
|||
|
COM3, {'\n'}, S_COMNL,
|
|||
|
COM3, {'*'}, COM3,
|
|||
|
COM3, {'/'}, S_COMMENT,
|
|||
|
|
|||
|
/* // comment */
|
|||
|
COM4, {C_XX}, COM4,
|
|||
|
COM4, {'\n'}, S_NL,
|
|||
|
COM4, {EOFC}, S_EOFCOM,
|
|||
|
|
|||
|
/* saw white space, eat it up */
|
|||
|
WS1, {C_XX}, S_WS,
|
|||
|
WS1, {'\t', '\v', ' '}, WS1,
|
|||
|
|
|||
|
/* saw -, check --, -=, -> */
|
|||
|
MINUS1, {C_XX}, ACT(MINUS, S_SELFB),
|
|||
|
MINUS1, {'-'}, ACT(MMINUS, S_SELF),
|
|||
|
MINUS1, {'='}, ACT(ASMINUS, S_SELF),
|
|||
|
MINUS1, {'>'}, ACT(ARROW, S_SELF),
|
|||
|
|
|||
|
/* saw +, check ++, += */
|
|||
|
PLUS1, {C_XX}, ACT(PLUS, S_SELFB),
|
|||
|
PLUS1, {'+'}, ACT(PPLUS, S_SELF),
|
|||
|
PLUS1, {'='}, ACT(ASPLUS, S_SELF),
|
|||
|
|
|||
|
/* saw <, check <<, <<=, <= */
|
|||
|
LT1, {C_XX}, ACT(LT, S_SELFB),
|
|||
|
LT1, {'<'}, LT2,
|
|||
|
LT1, {'='}, ACT(LEQ, S_SELF),
|
|||
|
LT2, {C_XX}, ACT(LSH, S_SELFB),
|
|||
|
LT2, {'='}, ACT(ASLSH, S_SELF),
|
|||
|
|
|||
|
/* saw >, check >>, >>=, >= */
|
|||
|
GT1, {C_XX}, ACT(GT, S_SELFB),
|
|||
|
GT1, {'>'}, GT2,
|
|||
|
GT1, {'='}, ACT(GEQ, S_SELF),
|
|||
|
GT2, {C_XX}, ACT(RSH, S_SELFB),
|
|||
|
GT2, {'='}, ACT(ASRSH, S_SELF),
|
|||
|
|
|||
|
/* = */
|
|||
|
ASG1, {C_XX}, ACT(ASGN, S_SELFB),
|
|||
|
ASG1, {'='}, ACT(EQ, S_SELF),
|
|||
|
|
|||
|
/* ! */
|
|||
|
NOT1, {C_XX}, ACT(NOT, S_SELFB),
|
|||
|
NOT1, {'='}, ACT(NEQ, S_SELF),
|
|||
|
|
|||
|
/* & */
|
|||
|
AND1, {C_XX}, ACT(AND, S_SELFB),
|
|||
|
AND1, {'&'}, ACT(LAND, S_SELF),
|
|||
|
AND1, {'='}, ACT(ASAND, S_SELF),
|
|||
|
|
|||
|
/* | */
|
|||
|
OR1, {C_XX}, ACT(OR, S_SELFB),
|
|||
|
OR1, {'|'}, ACT(LOR, S_SELF),
|
|||
|
OR1, {'='}, ACT(ASOR, S_SELF),
|
|||
|
|
|||
|
/* # */
|
|||
|
SHARP1, {C_XX}, ACT(SHARP, S_SELFB),
|
|||
|
SHARP1, {'#'}, ACT(DSHARP, S_SELF),
|
|||
|
|
|||
|
/* % */
|
|||
|
PCT1, {C_XX}, ACT(PCT, S_SELFB),
|
|||
|
PCT1, {'='}, ACT(ASPCT, S_SELF),
|
|||
|
|
|||
|
/* * */
|
|||
|
STAR1, {C_XX}, ACT(STAR, S_SELFB),
|
|||
|
STAR1, {'='}, ACT(ASSTAR, S_SELF),
|
|||
|
|
|||
|
/* ^ */
|
|||
|
CIRC1, {C_XX}, ACT(CIRC, S_SELFB),
|
|||
|
CIRC1, {'='}, ACT(ASCIRC, S_SELF),
|
|||
|
|
|||
|
-1
|
|||
|
};
|
|||
|
|
|||
|
/* first index is char, second is state */
|
|||
|
/* increase #states to power of 2 to encourage use of shift */
|
|||
|
short bigfsm[256][MAXSTATE];
|
|||
|
|
|||
|
void
|
|||
|
expandlex(void)
|
|||
|
{
|
|||
|
/* const */ struct fsm *fp;
|
|||
|
int i, j, nstate;
|
|||
|
|
|||
|
for (fp = fsm; fp->state >= 0; fp++)
|
|||
|
{
|
|||
|
for (i = 0; fp->ch[i]; i++)
|
|||
|
{
|
|||
|
nstate = fp->nextstate;
|
|||
|
if (nstate >= S_SELF)
|
|||
|
nstate = ~nstate;
|
|||
|
switch (fp->ch[i])
|
|||
|
{
|
|||
|
|
|||
|
case C_XX: /* random characters */
|
|||
|
for (j = 0; j < 256; j++)
|
|||
|
bigfsm[j][fp->state] = nstate;
|
|||
|
continue;
|
|||
|
case C_ALPH:
|
|||
|
for (j = 0; j <= 256; j++)
|
|||
|
#ifdef S390
|
|||
|
if( isalpha( j ) || (j == '_') )
|
|||
|
#else
|
|||
|
if ('a' <= j && j <= 'z' || 'A' <= j && j <= 'Z'
|
|||
|
|| j == '_')
|
|||
|
#endif
|
|||
|
bigfsm[j][fp->state] = nstate;
|
|||
|
continue;
|
|||
|
case C_NUM:
|
|||
|
for (j = '0'; j <= '9'; j++)
|
|||
|
bigfsm[j][fp->state] = nstate;
|
|||
|
continue;
|
|||
|
default:
|
|||
|
bigfsm[fp->ch[i]][fp->state] = nstate;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* install special cases for ? (trigraphs), \ (splicing), runes, and
|
|||
|
* EOB
|
|||
|
*/
|
|||
|
for (i = 0; i < MAXSTATE; i++)
|
|||
|
{
|
|||
|
for (j = 0; j < 0xFF; j++)
|
|||
|
if (j == '?' || j == '\\' || j == '\n' || j == '\r')
|
|||
|
{
|
|||
|
if (bigfsm[j][i] > 0)
|
|||
|
bigfsm[j][i] = ~bigfsm[j][i];
|
|||
|
bigfsm[j][i] &= ~QBSBIT;
|
|||
|
}
|
|||
|
bigfsm[EOB][i] = ~S_EOB;
|
|||
|
if (bigfsm[EOFC][i] >= 0)
|
|||
|
bigfsm[EOFC][i] = ~S_EOF;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
fixlex(void)
|
|||
|
{
|
|||
|
/* do C++ comments? */
|
|||
|
if ((Cplusplus == 0) || (Cflag != 0))
|
|||
|
bigfsm['/'][COM1] = bigfsm['x'][COM1];
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* fill in a row of tokens from input, terminated by NL or END
|
|||
|
* First token is put at trp->lp.
|
|||
|
* Reset is non-zero when the input buffer can be "rewound."
|
|||
|
* The value is a flag indicating that possible macros have
|
|||
|
* been seen in the row.
|
|||
|
*/
|
|||
|
int
|
|||
|
gettokens(Tokenrow * trp, int reset)
|
|||
|
{
|
|||
|
register int c, state, oldstate;
|
|||
|
register uchar *ip;
|
|||
|
register Token *tp, *maxp;
|
|||
|
int runelen;
|
|||
|
Source *s = cursource;
|
|||
|
int nmac = 0;
|
|||
|
extern char outbuf[];
|
|||
|
|
|||
|
tp = trp->lp;
|
|||
|
ip = s->inp;
|
|||
|
if (reset)
|
|||
|
{
|
|||
|
s->lineinc = 0;
|
|||
|
if (ip >= s->inl)
|
|||
|
{ /* nothing in buffer */
|
|||
|
s->inl = s->inb;
|
|||
|
fillbuf(s);
|
|||
|
ip = s->inp = s->inb;
|
|||
|
}
|
|||
|
else
|
|||
|
if (ip >= s->inb + (3 * INS / 4))
|
|||
|
{
|
|||
|
memmove(s->inb, ip, 4 + s->inl - ip);
|
|||
|
s->inl = s->inb + (s->inl - ip);
|
|||
|
ip = s->inp = s->inb;
|
|||
|
}
|
|||
|
}
|
|||
|
maxp = &trp->bp[trp->max];
|
|||
|
runelen = 1; /* S390: XDBX st<73>rzt ab! */
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
continue2:
|
|||
|
if (tp >= maxp)
|
|||
|
{
|
|||
|
trp->lp = tp;
|
|||
|
tp = growtokenrow(trp);
|
|||
|
maxp = &trp->bp[trp->max];
|
|||
|
}
|
|||
|
tp->type = UNCLASS;
|
|||
|
tp->t = ip;
|
|||
|
tp->wslen = 0;
|
|||
|
tp->flag = 0;
|
|||
|
state = START;
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
oldstate = state;
|
|||
|
|
|||
|
c = *ip; /* S390: XDBX st<73>rzt (gelegentlich) ab! */
|
|||
|
|
|||
|
if ((state = bigfsm[c][state]) >= 0)
|
|||
|
{
|
|||
|
ip += runelen;
|
|||
|
runelen = 1;
|
|||
|
continue;
|
|||
|
}
|
|||
|
state = ~state;
|
|||
|
reswitch:
|
|||
|
switch (state & 0177)
|
|||
|
{
|
|||
|
case S_SELF:
|
|||
|
ip += runelen;
|
|||
|
runelen = 1;
|
|||
|
case S_SELFB:
|
|||
|
tp->type = GETACT(state);
|
|||
|
tp->len = ip - tp->t;
|
|||
|
tp++;
|
|||
|
goto continue2;
|
|||
|
|
|||
|
case S_NAME: /* like S_SELFB but with nmac check */
|
|||
|
tp->type = NAME;
|
|||
|
tp->len = ip - tp->t;
|
|||
|
nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
|
|||
|
tp++;
|
|||
|
goto continue2;
|
|||
|
|
|||
|
case S_WS:
|
|||
|
tp->wslen = ip - tp->t;
|
|||
|
tp->t = ip;
|
|||
|
state = START;
|
|||
|
continue;
|
|||
|
|
|||
|
default:
|
|||
|
if ((state & QBSBIT) == 0)
|
|||
|
{
|
|||
|
ip += runelen;
|
|||
|
runelen = 1;
|
|||
|
continue;
|
|||
|
}
|
|||
|
state &= ~QBSBIT;
|
|||
|
s->inp = ip;
|
|||
|
|
|||
|
if (c == '\n')
|
|||
|
{
|
|||
|
while (s->inp + 1 >= s->inl && fillbuf(s) != EOF); /* S390: XDBX st<73>rzt (manchmal) ab! */
|
|||
|
|
|||
|
if (s->inp[1] == '\r')
|
|||
|
{
|
|||
|
memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
|
|||
|
s->inl -= 1;
|
|||
|
}
|
|||
|
|
|||
|
goto reswitch;
|
|||
|
}
|
|||
|
|
|||
|
if (c == '\r')
|
|||
|
{
|
|||
|
while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
|
|||
|
|
|||
|
if (s->inp[1] == '\n')
|
|||
|
{
|
|||
|
memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
|
|||
|
s->inl -= 1;
|
|||
|
}
|
|||
|
else
|
|||
|
*s->inp = '\n';
|
|||
|
|
|||
|
state = oldstate;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (c == '?')
|
|||
|
{ /* check trigraph */
|
|||
|
if (trigraph(s))
|
|||
|
{
|
|||
|
state = oldstate;
|
|||
|
continue;
|
|||
|
}
|
|||
|
goto reswitch;
|
|||
|
}
|
|||
|
if (c == '\\')
|
|||
|
{ /* line-folding */
|
|||
|
if (foldline(s))
|
|||
|
{
|
|||
|
s->lineinc++;
|
|||
|
state = oldstate;
|
|||
|
continue;
|
|||
|
}
|
|||
|
goto reswitch;
|
|||
|
}
|
|||
|
error(WARNING, "Lexical botch in cpp");
|
|||
|
ip += runelen;
|
|||
|
runelen = 1;
|
|||
|
continue;
|
|||
|
|
|||
|
case S_EOB:
|
|||
|
s->inp = ip;
|
|||
|
fillbuf(cursource);
|
|||
|
state = oldstate;
|
|||
|
continue;
|
|||
|
|
|||
|
case S_EOF:
|
|||
|
tp->type = END;
|
|||
|
tp->len = 0;
|
|||
|
s->inp = ip;
|
|||
|
if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
|
|||
|
error(WARNING, "No newline at end of file");
|
|||
|
trp->lp = tp + 1;
|
|||
|
return nmac;
|
|||
|
|
|||
|
case S_STNL:
|
|||
|
error(ERROR, "Unterminated string or char const");
|
|||
|
case S_NL:
|
|||
|
tp->t = ip;
|
|||
|
tp->type = NL;
|
|||
|
tp->len = 1;
|
|||
|
tp->wslen = 0;
|
|||
|
s->lineinc++;
|
|||
|
s->inp = ip + 1;
|
|||
|
trp->lp = tp + 1;
|
|||
|
return nmac;
|
|||
|
|
|||
|
case S_EOFSTR:
|
|||
|
error(FATAL, "EOF in string or char constant");
|
|||
|
break;
|
|||
|
|
|||
|
case S_COMNL:
|
|||
|
s->lineinc++;
|
|||
|
state = COM2;
|
|||
|
ip += runelen;
|
|||
|
runelen = 1;
|
|||
|
continue;
|
|||
|
|
|||
|
case S_EOFCOM:
|
|||
|
error(WARNING, "EOF inside comment");
|
|||
|
--ip;
|
|||
|
case S_COMMENT:
|
|||
|
if (!Cflag)
|
|||
|
{
|
|||
|
tp->t = ++ip;
|
|||
|
tp->t[-1] = ' ';
|
|||
|
tp->wslen = 1;
|
|||
|
state = START;
|
|||
|
continue;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
runelen = 1;
|
|||
|
s->lineinc = 0;;
|
|||
|
tp->type = COMMENT;
|
|||
|
tp->flag |= XTWS;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
ip += runelen;
|
|||
|
runelen = 1;
|
|||
|
tp->len = ip - tp->t;
|
|||
|
tp++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* have seen ?; handle the trigraph it starts (if any) else 0 */
|
|||
|
int
|
|||
|
trigraph(Source * s)
|
|||
|
{
|
|||
|
int c;
|
|||
|
|
|||
|
while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
|
|||
|
;
|
|||
|
if (s->inp[1] != '?')
|
|||
|
return 0;
|
|||
|
c = 0;
|
|||
|
switch (s->inp[2])
|
|||
|
{
|
|||
|
case '=':
|
|||
|
c = '#';
|
|||
|
break;
|
|||
|
case '(':
|
|||
|
c = '[';
|
|||
|
break;
|
|||
|
case '/':
|
|||
|
c = '\\';
|
|||
|
break;
|
|||
|
case ')':
|
|||
|
c = ']';
|
|||
|
break;
|
|||
|
case '\'':
|
|||
|
c = '^';
|
|||
|
break;
|
|||
|
case '<':
|
|||
|
c = '{';
|
|||
|
break;
|
|||
|
case '!':
|
|||
|
c = '|';
|
|||
|
break;
|
|||
|
case '>':
|
|||
|
c = '}';
|
|||
|
break;
|
|||
|
case '-':
|
|||
|
c = '~';
|
|||
|
break;
|
|||
|
}
|
|||
|
if (c)
|
|||
|
{
|
|||
|
*s->inp = c;
|
|||
|
memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
|
|||
|
s->inl -= 2;
|
|||
|
}
|
|||
|
return c;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
foldline(Source * s)
|
|||
|
{
|
|||
|
int n = 1;
|
|||
|
|
|||
|
/* skip pending wihite spaces */
|
|||
|
while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
|
|||
|
{
|
|||
|
n++;
|
|||
|
if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
/* refill buffer */
|
|||
|
while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
|
|||
|
|
|||
|
/* skip DOS line ends */
|
|||
|
if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
|
|||
|
((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
|
|||
|
n++;
|
|||
|
|
|||
|
if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
|
|||
|
{
|
|||
|
memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
|
|||
|
s->inl -= n + 1;
|
|||
|
return 1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
fillbuf(Source * s)
|
|||
|
{
|
|||
|
int n;
|
|||
|
|
|||
|
if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
|
|||
|
n = 0;
|
|||
|
s->inl += n;
|
|||
|
s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
|
|||
|
if (n == 0)
|
|||
|
{
|
|||
|
s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
|
|||
|
return EOF;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Push down to new source of characters.
|
|||
|
* If fd>0 and str==NULL, then from a file `name';
|
|||
|
* if fd==-1 and str, then from the string.
|
|||
|
*/
|
|||
|
Source *
|
|||
|
setsource(char *name, int path, int fd, char *str, int wrap)
|
|||
|
{
|
|||
|
Source *s = new(Source);
|
|||
|
int len;
|
|||
|
|
|||
|
s->line = 1;
|
|||
|
s->lineinc = 0;
|
|||
|
s->fd = fd;
|
|||
|
s->filename = name;
|
|||
|
s->next = cursource;
|
|||
|
s->ifdepth = 0;
|
|||
|
s->pathdepth = path;
|
|||
|
s->wrap = wrap;
|
|||
|
|
|||
|
cursource = s;
|
|||
|
|
|||
|
if (s->wrap)
|
|||
|
genwrap(0);
|
|||
|
|
|||
|
/* slop at right for EOB */
|
|||
|
if (str)
|
|||
|
{
|
|||
|
len = strlen(str);
|
|||
|
s->inb = domalloc(len + 4);
|
|||
|
s->inp = s->inb;
|
|||
|
strncpy((char *) s->inp, str, len);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
s->inb = domalloc(INS + 4);
|
|||
|
s->inp = s->inb;
|
|||
|
len = 0;
|
|||
|
}
|
|||
|
s->inl = s->inp + len;
|
|||
|
s->inl[0] = s->inl[1] = EOB;
|
|||
|
|
|||
|
return s;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
unsetsource(void)
|
|||
|
{
|
|||
|
Source *s = cursource;
|
|||
|
|
|||
|
if (s->wrap)
|
|||
|
genwrap(1);
|
|||
|
|
|||
|
if (s->fd >= 0)
|
|||
|
{
|
|||
|
close(s->fd);
|
|||
|
dofree(s->inb);
|
|||
|
}
|
|||
|
cursource = s->next;
|
|||
|
dofree(s);
|
|||
|
}
|