ack/lang/cem/cpp.ansi/preprocess.c

603 lines
12 KiB
C
Raw Permalink Normal View History

1989-10-23 10:35:56 +00:00
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
1994-06-24 14:02:31 +00:00
/* $Id$ */
1989-10-23 10:35:56 +00:00
/* PREPROCESSOR DRIVER */
#include <stdlib.h>
#include <stdio.h>
#include <system.h>
#include <alloc.h>
#include "preprocess.h"
#include "input.h"
#include "parameters.h"
#include "arith.h"
#include "LLlex.h"
#include "class.h"
#include "macro.h"
#include "domacro.h"
#include "replace.h"
#include "idf.h"
#include "error.h"
#include "bits.h"
#include "skip.h"
1989-10-23 10:35:56 +00:00
char _obuf[OBUFSIZE];
1989-10-23 10:35:56 +00:00
#ifdef DOBITS
char bits[128];
1989-10-23 10:35:56 +00:00
#endif
extern int InputLevel;
extern char* sprint();
void Xflush(void)
1989-10-23 10:35:56 +00:00
{
sys_write(STDOUT, _obuf, OBUFSIZE);
}
static char* SkipComment();
extern char options[];
/* #pragma directives are saved here and passed to the compiler later on.
*/
struct prag_info
{
int pr_linnr;
char* pr_fil;
char* pr_text;
};
static struct prag_info* pragma_tab;
static int pragma_nr;
void do_pragma(void)
{
register int size = ITEXTSIZE;
char* cur_line = Malloc((unsigned)size);
register char* c_ptr = cur_line;
register int c = GetChar();
register int delim = 0;
while (c != '\n')
{
if (c_ptr + 1 - cur_line == size)
{
cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
c_ptr = cur_line + size - 1;
size += ITEXTSIZE;
}
if (delim)
{
if (c == delim)
{
delim = 0;
}
else if (c == '\\')
{
*c_ptr++ = c;
c = GetChar();
if (c == '\n')
break;
}
}
else if (c == '\'' || c == '"')
{
delim = c;
}
else if (c == '/')
{
if (!InputLevel)
{
c = GetChar();
if (c == '*')
{
skipcomment();
continue;
}
else if (c == '/')
{
skiplinecomment();
continue;
}
*c_ptr++ = '/';
}
}
*c_ptr++ = c;
c = GetChar();
}
*c_ptr = '\0';
if (!pragma_nr)
{
pragma_tab = (struct prag_info*)Malloc(sizeof(struct prag_info));
}
else
{
pragma_tab = (struct prag_info*)Realloc(
(char*)pragma_tab, (unsigned)(sizeof(struct prag_info) * (pragma_nr + 1)));
}
if (delim)
{
error("unclosed opening %c", delim);
}
pragma_tab[pragma_nr].pr_linnr = LineNumber;
pragma_tab[pragma_nr].pr_fil = FileName;
pragma_tab[pragma_nr].pr_text = cur_line;
pragma_nr++;
LineNumber++;
}
char Xbuf[256];
void preprocess(char *fn)
1989-10-23 10:35:56 +00:00
{
register int c;
register char* op = _obuf;
register char* ob = &_obuf[OBUFSIZE];
1989-10-23 10:35:56 +00:00
int lineno = 0;
int startline;
1989-10-23 10:35:56 +00:00
#define flush(X) (sys_write(STDOUT, _obuf, X))
#define echo(ch) \
if (op == ob) \
{ \
Xflush(); \
op = _obuf; \
} \
*op++ = (ch);
#define newline() \
op--; \
while (op >= _obuf && (*op == ' ' || *op == '\t')) \
op--; \
op++; \
echo('\n')
1989-10-23 10:35:56 +00:00
if (!options['P'])
{
1989-10-23 10:35:56 +00:00
/* Generate a line directive communicating the
source filename
*/
register char* p = Xbuf;
1989-10-23 10:35:56 +00:00
sprint(p, "%s 1 \"%s\"\n", LINE_PREFIX, FileName);
while (*p)
{
1989-10-23 10:35:56 +00:00
echo(*p++);
}
}
#define do_line_dir(lineno, fn) \
if (lineno != LineNumber || fn != FileName) \
{ \
fn = FileName; \
lineno = LineNumber; \
if (!options['P']) \
{ \
register char* p = Xbuf; \
sprint(Xbuf, "%s %d \"%s\"\n", LINE_PREFIX, (int)LineNumber, FileName); \
op--; \
while (op >= _obuf && (class(*op) == STSKIP || *op == '\n')) \
op--; \
op++; \
newline(); \
while (*p) \
{ \
echo(*p++); \
} \
} \
}
1989-10-23 10:35:56 +00:00
for (;;)
{
1989-10-23 10:35:56 +00:00
LineNumber++;
lineno++;
startline = 1;
1989-10-23 10:35:56 +00:00
c = GetChar();
while (startline)
{
/* first flush the saved pragma's */
if (pragma_nr)
{
register int i = 0;
int LiNo = LineNumber;
char* FiNam = FileName;
while (i < pragma_nr)
{
register char* c_ptr = "#pragma";
LineNumber = pragma_tab[i].pr_linnr;
FileName = pragma_tab[i].pr_fil;
do_line_dir(lineno, fn);
while (*c_ptr)
{
echo(*c_ptr++);
}
c_ptr = pragma_tab[i].pr_text;
while (*c_ptr)
{
echo(*c_ptr++);
}
newline();
lineno++;
free(pragma_tab[i].pr_text);
i++;
}
free((char*)pragma_tab);
pragma_tab = (struct prag_info*)0;
pragma_nr = 0;
LineNumber = LiNo;
FileName = FiNam;
do_line_dir(lineno, fn);
}
while (class(c) == STSKIP || c == '/')
{
if (c == '/')
{
if (!InputLevel)
{
c = GetChar();
if (c == '*')
{
op = SkipComment(op, &lineno);
if (!op)
return;
if (!options['C'])
{
echo(' ');
}
c = GetChar();
continue;
}
else if (c == '/')
{
skiplinecomment();
c = GetChar();
continue;
}
UnGetChar();
c = '/';
}
break;
}
echo(c);
c = GetChar();
}
1989-10-23 10:35:56 +00:00
if (c == '#')
{
domacro();
lineno++;
newline();
do_line_dir(lineno, fn);
c = GetChar();
}
else
startline = 0;
1989-10-23 10:35:56 +00:00
}
do_line_dir(lineno, fn);
for (;;)
{
1989-10-23 10:35:56 +00:00
/* illegal character */
if (c & 0200)
{
if (c == EOI)
{
1989-10-23 10:35:56 +00:00
newline();
flush((int)(op - _obuf));
1989-10-23 10:35:56 +00:00
return;
}
fatal("non-ascii character read");
}
/* comments */
if (c == '/' && !InputLevel)
{
1989-10-23 10:35:56 +00:00
c = GetChar();
if (c == '*')
{
op = SkipComment(op, &lineno);
if (!op)
return;
if (!options['C'])
{
echo(' ');
}
1989-10-23 10:35:56 +00:00
c = GetChar();
continue;
}
else if (c == '/')
{
skiplinecomment();
c = GetChar();
continue;
}
1989-10-23 10:35:56 +00:00
echo('/');
continue;
}
/* switch on character */
switch (class(c))
{
case STNL:
newline();
break;
case STSTR:
case STCHAR:
1989-10-23 10:35:56 +00:00
{
register int stopc = c;
int escaped;
1989-10-23 10:35:56 +00:00
do
{
escaped = 0;
1989-10-23 10:35:56 +00:00
echo(c);
c = GetChar();
if (c == '\n')
{
/* the compiler will complain */
break;
}
else if (c == EOI)
{
newline();
flush((int)(op - _obuf));
return;
}
if (c == '\\')
{
echo(c);
1989-10-31 10:02:48 +00:00
c = GetChar();
if (c == '\n')
{
++LineNumber;
lineno++;
}
else
escaped = 1;
1989-10-23 10:35:56 +00:00
}
} while (escaped || c != stopc);
echo(c);
if (c == '\n')
break; /* Don't eat # */
c = GetChar();
continue;
1989-10-23 10:35:56 +00:00
}
case STNUM:
/* The following code is quit ugly. This because
* ..3 == . .3 , whereas ...3 == ... 3
*/
1989-10-23 10:35:56 +00:00
echo(c);
if (c == '.')
{
1989-10-23 10:35:56 +00:00
c = GetChar();
if (c == '.')
{
if ((c = GetChar()) == '.')
{
echo('.');
echo('.');
c = GetChar();
continue;
}
UnGetChar();
c = '.';
continue;
}
else if (!is_dig(c))
{
continue;
}
else
{
1989-10-23 10:35:56 +00:00
echo(c);
}
}
c = GetChar();
while (in_idf(c) || c == '.')
{
echo(c);
if (c == 'e' || c == 'E')
{
1989-10-23 10:35:56 +00:00
c = GetChar();
if (c == '+' || c == '-')
{
echo(c);
c = GetChar();
}
1989-10-23 10:35:56 +00:00
}
else
c = GetChar();
}
1989-10-23 10:35:56 +00:00
continue;
case STELL:
c = GetChar();
UnGetChar();
if (c == '"' || c == '\'')
{
echo('L');
continue;
}
c = 'L';
case STIDF:
{
extern int idfsize; /* ??? */
char buf[IDFSIZE + 1];
register char* tg = &buf[0];
register char* maxpos = &buf[idfsize];
register struct idf* idef;
int NoExpandNext = 0;
1989-10-23 10:35:56 +00:00
#define tstmac(bx) \
if (!(bits[c] & bx)) \
goto nomac
#define cpy *tg++ = c
#define load \
c = GetChar(); \
if (!in_idf(c)) \
goto endidf
1989-10-23 10:35:56 +00:00
/* unstack macro's when allowed. */
if (Unstacked)
EnableMacros();
if (c == NOEXPM)
{
NoExpandNext = 1;
c = GetChar();
}
1989-10-23 10:35:56 +00:00
#ifdef DOBITS
cpy;
tstmac(bit0);
load;
cpy;
tstmac(bit1);
load;
cpy;
tstmac(bit2);
load;
cpy;
tstmac(bit3);
load;
cpy;
tstmac(bit4);
load;
cpy;
tstmac(bit5);
load;
cpy;
tstmac(bit6);
load;
cpy;
tstmac(bit7);
load;
1989-10-23 10:35:56 +00:00
#endif
for (;;)
{
if (tg < maxpos)
{
cpy;
}
load;
1989-10-23 10:35:56 +00:00
}
endidf:
if (c != EOF)
UnGetChar();
*tg = '\0'; /* mark the end of the identifier */
if ((idef = findidf(buf)) && idef->id_macro && ReplaceMacros && !NoExpandNext)
{
if (replace(idef))
{
echo(' ');
c = GetChar();
continue;
}
tg = buf;
while (*tg)
{
echo(*tg++);
}
1989-10-23 10:35:56 +00:00
c = GetChar();
if (in_idf(c))
{
echo(' ');
}
1989-10-23 10:35:56 +00:00
continue;
}
nomac:
*tg = '\0';
1989-10-23 10:35:56 +00:00
tg = buf;
while (*tg)
{
1989-10-23 10:35:56 +00:00
echo(*tg++);
}
c = GetChar();
while (in_idf(c))
{
echo(c);
c = GetChar();
}
1989-10-23 10:35:56 +00:00
continue;
}
case STMSPEC:
if (InputLevel)
{
echo(' '); /* seperate tokens */
c = GetChar();
continue;
}
/* else fallthrough */
default:
1989-10-23 10:35:56 +00:00
echo(c);
c = GetChar();
continue;
}
break;
}
}
/*NOTREACHED*/
}
static char* SkipComment(char *op, int *lineno)
{
char* ob = &_obuf[OBUFSIZE];
1990-04-10 10:52:52 +00:00
register int c, oldc = '\0';
NoUnstack++;
if (options['C'])
{
echo('/');
echo('*');
}
c = GetChar();
for (;;)
{
if (c == EOI)
{
newline();
1990-04-25 15:10:13 +00:00
flush((int)(op - _obuf));
op = 0;
break;
}
if (options['C'])
{
echo(c);
}
if (c == '\n')
{
++LineNumber;
++*lineno;
if (!options['C'])
{
echo(c);
}
}
if (c == '*')
{
c = GetChar();
if (c == '/')
{
if (options['C'])
{
echo(c);
}
break; /* for(;;) */
}
else if (oldc == '/')
{
1990-04-10 10:52:52 +00:00
warning("comment inside comment ?");
}
1990-04-10 10:52:52 +00:00
oldc = '*';
}
else
{
1990-04-10 10:52:52 +00:00
oldc = c;
c = GetChar();
}
}
NoUnstack--;
return op;
}