fixed bugs, added dynamic buffer allocation to preprocessor
This commit is contained in:
parent
3107e638f8
commit
96da16ce33
24 changed files with 386 additions and 283 deletions
|
@ -34,12 +34,9 @@
|
|||
#define DENSITY 2 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!File: lapbuf.h
|
||||
#define LAPBUF 4096 /* size of macro replacement buffer */
|
||||
|
||||
|
||||
!File: argbuf.h
|
||||
#define ARGBUF 2048 /* size of macro actual parameter buffer */
|
||||
!File: macbuf.h
|
||||
#define LAPBUF 128 /* initial size of macro replacement buffer */
|
||||
#define ARGBUF 128 /* initial size of macro parameter buffer(s) */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
|
@ -107,7 +104,6 @@
|
|||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 32 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 16 /* stepsize for enlarging repl.text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
|
|
|
@ -29,7 +29,7 @@ int token_nmb = 0; /* number of the ahead token */
|
|||
int tk_nmb_at_last_syn_err = -5/*ERR_SHADOW*/;
|
||||
/* token number at last syntax error */
|
||||
|
||||
#ifndef NOPP
|
||||
#ifndef NOPP
|
||||
int ReplaceMacros = 1; /* replacing macros */
|
||||
int AccDefined = 0; /* accept "defined(...)" */
|
||||
int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
|
||||
|
@ -40,7 +40,7 @@ int AccFileSpecifier = 0; /* return filespecifier <...> */
|
|||
int EoiForNewline = 0; /* return EOI upon encountering newline */
|
||||
int File_Inserted = 0; /* a file has just been inserted */
|
||||
int LexSave = 0; /* last character read by GetChar */
|
||||
#define MAX_LL_DEPTH 2
|
||||
#define MAX_LL_DEPTH 2
|
||||
|
||||
#define FLG_ESEEN 0x01 /* possibly a floating point number */
|
||||
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */
|
||||
|
@ -115,6 +115,7 @@ GetToken(ptok)
|
|||
*/
|
||||
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
|
||||
register int ch, nch;
|
||||
int nlflag = 0;
|
||||
|
||||
token_nmb++;
|
||||
|
||||
|
@ -145,7 +146,9 @@ firstline:
|
|||
end-of-information of the line.
|
||||
*/
|
||||
return ptok->tk_symb = EOI;
|
||||
while ((ch = GetChar()), (ch == '#' || class(ch) == STSKIP)) {
|
||||
|
||||
while ((ch = GetChar()),
|
||||
(ch == '#' || ch == '/' || class(ch) == STSKIP)) {
|
||||
/* blanks are allowed before hashes */
|
||||
if (ch == '#') {
|
||||
/* a control line follows */
|
||||
|
@ -155,6 +158,13 @@ firstline:
|
|||
File_Inserted = 0;
|
||||
goto firstline;
|
||||
}
|
||||
} else if (ch == '/') {
|
||||
if ((GetChar() == '*') && !InputLevel) {
|
||||
skipcomment();
|
||||
} else {
|
||||
UnGetChar();
|
||||
break;
|
||||
}
|
||||
#endif /* NOPP */
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +176,7 @@ firstline:
|
|||
case STSKIP: /* just skip the skip characters */
|
||||
goto again;
|
||||
case STGARB: /* garbage character */
|
||||
#ifndef NOPP
|
||||
#ifndef NOPP
|
||||
garbage:
|
||||
#endif
|
||||
if (040 < ch && ch < 0177)
|
||||
|
@ -252,14 +262,12 @@ garbage:
|
|||
return ptok->tk_symb = XORAB;
|
||||
break;
|
||||
case '/':
|
||||
if (nch == '*'
|
||||
#ifndef NOPP
|
||||
&& !InputLevel
|
||||
#endif
|
||||
) {
|
||||
#ifndef NOPP
|
||||
if (nch == '*' && !InputLevel) {
|
||||
skipcomment();
|
||||
goto again;
|
||||
}
|
||||
#endif
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = DIVAB;
|
||||
break;
|
||||
|
@ -323,7 +331,7 @@ garbage:
|
|||
idef = ptok->tk_idf = idf_hashed(buf, tg - buf, hash);
|
||||
idef->id_file = ptok->tk_file;
|
||||
idef->id_line = ptok->tk_line;
|
||||
#ifndef NOPP
|
||||
#ifndef NOPP
|
||||
if (idef->id_macro && ReplaceMacros && !NoExpandNext) {
|
||||
if (replace(idef))
|
||||
goto again;
|
||||
|
@ -429,6 +437,7 @@ garbage:
|
|||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
skipcomment()
|
||||
{
|
||||
/* The last character read has been the '*' of '/_*'. The
|
||||
|
@ -475,6 +484,7 @@ skipcomment()
|
|||
#endif LINT
|
||||
NoUnstack--;
|
||||
}
|
||||
#endif /* NOPP */
|
||||
|
||||
arith
|
||||
char_constant(nm)
|
||||
|
@ -628,7 +638,7 @@ again:
|
|||
if (ch == '?')
|
||||
ch = trigraph();
|
||||
|
||||
/* \\\n are removed from the input stream */
|
||||
/* \<newline> is removed from the input stream */
|
||||
if (ch == '\\') {
|
||||
LoadChar(ch);
|
||||
if (ch == '\n') {
|
||||
|
|
|
@ -99,8 +99,7 @@
|
|||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 8 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 8 /* stepsize for enlarging repl.text */
|
||||
#define ITEXTSIZE 16 /* 1st piece of memory for repl. text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Machine and environ dependent definitions
|
||||
EMHOME = ../../..
|
||||
CC = $(EMHOME)/bin/fcc
|
||||
CC = cc
|
||||
#CC = cc
|
||||
CFLOW = cflow
|
||||
MKDEP = $(EMHOME)/bin/mkdep
|
||||
PRID = $(EMHOME)/bin/prid
|
||||
|
@ -117,7 +117,7 @@ GSRC = $(GCSRC) $(GHSTRSRC)
|
|||
|
||||
# .h files generated by `make hfiles LLfiles'; PLEASE KEEP THIS UP-TO-DATE!
|
||||
GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
|
||||
idfsize.h ifdepth.h inputtype.h lapbuf.h argbuf.h lint.h \
|
||||
idfsize.h ifdepth.h inputtype.h macbuf.h lint.h \
|
||||
nobitfield.h nopp.h nocross.h \
|
||||
nparams.h numsize.h parbufsize.h pathlength.h Lpars.h \
|
||||
strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h \
|
||||
|
@ -614,7 +614,6 @@ domacro.o: parbufsize.h
|
|||
domacro.o: spec_arith.h
|
||||
domacro.o: textsize.h
|
||||
replace.o: LLlex.h
|
||||
replace.o: argbuf.h
|
||||
replace.o: arith.h
|
||||
replace.o: assert.h
|
||||
replace.o: class.h
|
||||
|
@ -623,7 +622,7 @@ replace.o: file_info.h
|
|||
replace.o: idf.h
|
||||
replace.o: idfsize.h
|
||||
replace.o: input.h
|
||||
replace.o: lapbuf.h
|
||||
replace.o: macbuf.h
|
||||
replace.o: macro.h
|
||||
replace.o: nopp.h
|
||||
replace.o: nparams.h
|
||||
|
|
|
@ -34,12 +34,9 @@
|
|||
#define DENSITY 2 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!File: lapbuf.h
|
||||
#define LAPBUF 4096 /* size of macro replacement buffer */
|
||||
|
||||
|
||||
!File: argbuf.h
|
||||
#define ARGBUF 2048 /* sizeof of macro actual parameter buffer */
|
||||
!File: macbuf.h
|
||||
#define LAPBUF 128 /* initial size of macro replacement buffer */
|
||||
#define ARGBUF 128 /* initial size of macro parameter buffer(s) */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
|
@ -106,8 +103,7 @@
|
|||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 8 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 8 /* stepsize for enlarging repl.text */
|
||||
#define ITEXTSIZE 16 /* 1st piece of memory for repl. text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
|
|
|
@ -200,7 +200,6 @@ any2arith(expp, oper)
|
|||
switch (fund = (*expp)->ex_type->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case GENERIC:
|
||||
ASSERT((*expp)->ex_type->tp_size <= int_type->tp_size);
|
||||
|
||||
if ((*expp)->ex_type->tp_unsigned
|
||||
|
@ -322,6 +321,7 @@ int2float(expp, tp)
|
|||
converted to the floating type tp.
|
||||
*/
|
||||
register struct expr *exp = *expp;
|
||||
int uns = (*expp)->ex_type->tp_unsigned;
|
||||
|
||||
fp_used = 1;
|
||||
if (is_cp_cst(exp)) {
|
||||
|
@ -335,7 +335,7 @@ int2float(expp, tp)
|
|||
exp->ex_type = tp;
|
||||
exp->ex_class = Float;
|
||||
exp->FL_VALUE = 0;
|
||||
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH));
|
||||
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns);
|
||||
exp->FL_DATLAB = 0;
|
||||
}
|
||||
else *expp = arith2arith(tp, INT2FLOAT, *expp);
|
||||
|
@ -348,9 +348,23 @@ float2int(expp, tp)
|
|||
/* The expression *expp, which is of some floating type, is
|
||||
converted to the integral type tp.
|
||||
*/
|
||||
register struct expr *ex = *expp;
|
||||
|
||||
fp_used = 1;
|
||||
*expp = arith2arith(tp, FLOAT2INT, *expp);
|
||||
if (is_fp_cst(ex)) {
|
||||
arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned);
|
||||
|
||||
if (flt_status == FLT_OVFL)
|
||||
expr_warning(ex,"overflow in float to int conversion");
|
||||
else if (flt_status == FLT_UNFL)
|
||||
expr_warning(ex,"underflow in float to unsigned conversion");
|
||||
ex->ex_type = tp;
|
||||
/* The following lines are copied from fill_int_expr */
|
||||
ex->ex_class = Value;
|
||||
ex->VL_CLASS = Const;
|
||||
ex->VL_VALUE = ar;
|
||||
cut_size(ex);
|
||||
} else *expp = arith2arith(tp, FLOAT2INT, ex);
|
||||
}
|
||||
|
||||
float2float(expp, tp)
|
||||
|
@ -426,17 +440,7 @@ opnd2logical(expp, oper)
|
|||
{
|
||||
int fund = (*expp)->ex_type->tp_fund;
|
||||
|
||||
if (fund == FUNCTION || fund == ARRAY) {
|
||||
expr_warning(*expp, "%s operand to %s",
|
||||
symbol2str(fund),
|
||||
symbol2str(oper));
|
||||
if (fund == FUNCTION) {
|
||||
function2pointer(*expp);
|
||||
}
|
||||
else array2pointer(*expp);
|
||||
}
|
||||
#ifndef NOBITFIELD
|
||||
else
|
||||
if (fund == FIELD)
|
||||
field2arith(expp);
|
||||
#endif NOBITFIELD
|
||||
|
@ -490,6 +494,9 @@ any2opnd(expp, oper)
|
|||
{
|
||||
if (!*expp)
|
||||
return;
|
||||
|
||||
if (oper == SIZEOF || oper == '&') return;
|
||||
|
||||
switch ((*expp)->ex_type->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
|
@ -504,6 +511,9 @@ any2opnd(expp, oper)
|
|||
if ((*expp)->ex_class == String)
|
||||
string2pointer(*expp);
|
||||
break;
|
||||
case FUNCTION:
|
||||
function2pointer(*expp);
|
||||
break;
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
field2arith(expp);
|
||||
|
|
|
@ -267,12 +267,32 @@ ch3cast(expp, oper, tp)
|
|||
}
|
||||
else
|
||||
if (oldtp->tp_fund == POINTER && tp->tp_fund == POINTER) {
|
||||
if (oper == CASTAB)
|
||||
expr_warning(*expp, "incompatible pointers");
|
||||
else
|
||||
if (oper != CAST)
|
||||
expr_warning(*expp, "incompatible pointers in %s",
|
||||
switch (oper) {
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
case '=':
|
||||
case CASTAB:
|
||||
case RETURN:
|
||||
if (tp->tp_up && oldtp->tp_up) {
|
||||
if (tp->tp_up->tp_fund == VOID
|
||||
&& oldtp->tp_up->tp_fund != FUNCTION) {
|
||||
break; /* switch */
|
||||
}
|
||||
if (oldtp->tp_up->tp_fund == VOID
|
||||
&& tp->tp_up->tp_fund != FUNCTION) {
|
||||
break; /* switch */
|
||||
}
|
||||
}
|
||||
/* falltrough */
|
||||
default:
|
||||
if (oper == CASTAB)
|
||||
expr_warning(*expp, "incompatible pointers");
|
||||
else
|
||||
expr_warning(*expp, "incompatible pointers in %s",
|
||||
symbol2str(oper));
|
||||
break;
|
||||
case CAST: break;
|
||||
}
|
||||
#ifdef LINT
|
||||
if (oper != CAST)
|
||||
lint_ptr_conv(oldtp->tp_up->tp_fund, tp->tp_up->tp_fund);
|
||||
|
@ -552,6 +572,7 @@ ch3asgn(expp, oper, expr)
|
|||
char *oper_string = symbol2str(oper);
|
||||
|
||||
/* We expect an lvalue */
|
||||
if (fund == ARRAY || fund == FUNCTION) exp->ex_lvalue = 0;
|
||||
if (!exp->ex_lvalue) {
|
||||
expr_error(exp, "no lvalue in operand of %s", oper_string);
|
||||
} else if (exp->ex_flags & EX_ILVALUE) {
|
||||
|
@ -616,7 +637,6 @@ is_integral_type(tp)
|
|||
register struct type *tp;
|
||||
{
|
||||
switch (tp->tp_fund) {
|
||||
case GENERIC:
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
|
@ -637,7 +657,6 @@ is_arith_type(tp)
|
|||
register struct type *tp;
|
||||
{
|
||||
switch (tp->tp_fund) {
|
||||
case GENERIC:
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
|
|
|
@ -39,20 +39,21 @@ ch3bin(expp, oper, expr)
|
|||
|
||||
any2opnd(expp, oper);
|
||||
expp_tp = (*expp)->ex_type;
|
||||
/* expp_tp can never be ARRAY, since any2opnd() converts the type
|
||||
* to pointer (except for SIZEOF and unary &).
|
||||
*/
|
||||
any2opnd(&expr, oper);
|
||||
switch (oper) {
|
||||
case '[': /* 3.3.2.1 */
|
||||
/* indexing follows the commutative laws */
|
||||
switch (expp_tp->tp_fund) {
|
||||
case POINTER:
|
||||
case ARRAY:
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
return;
|
||||
default: /* unindexable */
|
||||
switch (expr->ex_type->tp_fund) {
|
||||
case POINTER:
|
||||
case ARRAY:
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
return;
|
||||
|
@ -124,6 +125,7 @@ ch3bin(expp, oper, expr)
|
|||
case '+':
|
||||
if (expr->ex_type->tp_fund == POINTER) { /* swap operands */
|
||||
struct expr *etmp = expr;
|
||||
expp_tp = expr->ex_type; /* both in registers */
|
||||
expr = *expp;
|
||||
*expp = etmp;
|
||||
}
|
||||
|
@ -295,9 +297,10 @@ pntminuspnt(expp, oper, expr)
|
|||
*/
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
ch3cast(expp, CAST, pa_type); /* ptr-ptr: result has pa_type */
|
||||
ch3bin(expp, '/',
|
||||
intexpr(size_of_type(up_type, "object"), pa_type->tp_fund));
|
||||
ch3cast(expp, CAST, pa_type); /* result will be an integgral expr */
|
||||
ch3bin(expp, '/'
|
||||
, intexpr(size_of_type(up_type, symbol2str(up_type->tp_fund))
|
||||
, pa_type->tp_fund));
|
||||
ch3cast(expp, CAST, pa_type); /* result will be an integral expr */
|
||||
/* cast necessary ??? */
|
||||
}
|
||||
|
||||
|
|
|
@ -28,20 +28,15 @@ ch3mon(oper, expp)
|
|||
*/
|
||||
register struct expr *expr;
|
||||
|
||||
any2opnd(expp, oper);
|
||||
|
||||
switch (oper) {
|
||||
case '*': /* 3.3.3.2 */
|
||||
/* no FIELD type allowed */
|
||||
if ((*expp)->ex_type->tp_fund == ARRAY)
|
||||
array2pointer(*expp);
|
||||
if ((*expp)->ex_type->tp_fund != POINTER) {
|
||||
if ((*expp)->ex_type->tp_fund != FUNCTION) {
|
||||
expr_error(*expp,
|
||||
"* applied to non-pointer (%s)",
|
||||
symbol2str((*expp)->ex_type->tp_fund));
|
||||
} else {
|
||||
warning("superfluous use of * on function");
|
||||
/* ignore indirection (yegh) */
|
||||
}
|
||||
} else {
|
||||
expr = *expp;
|
||||
if (expr->ex_lvalue == 0 && expr->ex_class != String)
|
||||
|
@ -63,13 +58,11 @@ ch3mon(oper, expp)
|
|||
break;
|
||||
case '&':
|
||||
if ((*expp)->ex_type->tp_fund == ARRAY) {
|
||||
expr_warning(*expp, "& before array ignored");
|
||||
array2pointer(*expp);
|
||||
(*expp)->ex_type = pointer_to((*expp)->ex_type, 0);
|
||||
}
|
||||
else
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION) {
|
||||
expr_warning(*expp, "& before function ignored");
|
||||
function2pointer(*expp);
|
||||
(*expp)->ex_type = pointer_to((*expp)->ex_type, 0);
|
||||
}
|
||||
else
|
||||
#ifndef NOBITFIELD
|
||||
|
@ -135,10 +128,6 @@ ch3mon(oper, expp)
|
|||
NILEXPR, oper, *expp);
|
||||
break;
|
||||
case '!':
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*expp);
|
||||
if ((*expp)->ex_type->tp_fund != POINTER)
|
||||
any2arith(expp, oper);
|
||||
opnd2test(expp, '!');
|
||||
if (is_cp_cst(*expp)) {
|
||||
(*expp)->VL_VALUE = !((*expp)->VL_VALUE);
|
||||
|
@ -158,8 +147,9 @@ ch3mon(oper, expp)
|
|||
(*expp)->VL_IDF->id_text);
|
||||
expr = intexpr((*expp)->ex_class == String ?
|
||||
(arith)((*expp)->SG_LEN) :
|
||||
size_of_type((*expp)->ex_type, "object"),
|
||||
INT);
|
||||
size_of_type((*expp)->ex_type,
|
||||
symbol2str((*expp)->ex_type->tp_fund))
|
||||
, INT);
|
||||
expr->ex_flags |= EX_SIZEOF;
|
||||
free_expression(*expp);
|
||||
*expp = expr;
|
||||
|
|
|
@ -462,17 +462,15 @@ loc_init(expr, id)
|
|||
unknownsize = 1;
|
||||
case STRUCT:
|
||||
case UNION:
|
||||
if (!tmpoffset) { /* first time for this variable */
|
||||
if (expr != (struct expr *) 0) {
|
||||
break; /* switch */
|
||||
} else if (!tmpoffset) {/* first time for this variable */
|
||||
tmpoffset = id->id_def->df_address;
|
||||
id->id_def->df_address = data_label();
|
||||
C_df_dlb((label)id->id_def->df_address);
|
||||
} else {
|
||||
/* generate a 'loi, sti' sequence. The peephole
|
||||
* optimizer will optimize this into a 'blm'
|
||||
* whenever possible.
|
||||
*/
|
||||
C_lae_dlb((label)id->id_def->df_address, (arith)0);
|
||||
C_loi(tp->tp_size);
|
||||
load_block(tp->tp_size, 1);
|
||||
if (unknownsize) {
|
||||
/* tmpoffset += tp->tp_size; */
|
||||
unknownsize = 0;
|
||||
|
@ -483,7 +481,7 @@ loc_init(expr, id)
|
|||
, id->id_def->df_sc);
|
||||
}
|
||||
C_lal(tmpoffset);
|
||||
C_sti(tp->tp_size);
|
||||
store_block(tp->tp_size, 1);
|
||||
id->id_def->df_address = tmpoffset;
|
||||
tmpoffset = 0;
|
||||
}
|
||||
|
|
|
@ -123,7 +123,6 @@ convtype(tp)
|
|||
register struct type *tp;
|
||||
{
|
||||
switch (tp->tp_fund) {
|
||||
case GENERIC:
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
|
|
|
@ -226,6 +226,7 @@ initializer(struct idf *idf; int sc;)
|
|||
}
|
||||
'='
|
||||
{
|
||||
if (AHEAD != '{') autoagg = 0;
|
||||
#ifdef LINT
|
||||
lint_statement();
|
||||
#endif LINT
|
||||
|
|
|
@ -14,16 +14,18 @@
|
|||
#include "nopp.h"
|
||||
|
||||
#ifndef NOPP
|
||||
#include "ifdepth.h"
|
||||
#include "botch_free.h"
|
||||
#include "nparams.h"
|
||||
#include "parbufsize.h"
|
||||
#include "textsize.h"
|
||||
#include "ifdepth.h"
|
||||
#include "botch_free.h"
|
||||
#include "nparams.h"
|
||||
#include "parbufsize.h"
|
||||
#include "textsize.h"
|
||||
#include "idfsize.h"
|
||||
#include "assert.h"
|
||||
#include <alloc.h>
|
||||
#include "class.h"
|
||||
#include "macro.h"
|
||||
#include "macbuf.h"
|
||||
#include "replace.h"
|
||||
|
||||
extern char options[];
|
||||
extern char **inctable; /* list of include directories */
|
||||
|
@ -167,7 +169,15 @@ int to_endif;
|
|||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
UnGetChar();
|
||||
/* A possible '/' is not pushed back */
|
||||
if (ch == '/') {
|
||||
ch = GetChar();
|
||||
if (ch != '*') UnGetChar();
|
||||
else {
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
} else UnGetChar();
|
||||
SkipToNewLine();
|
||||
continue;
|
||||
}
|
||||
|
@ -211,9 +221,10 @@ int to_endif;
|
|||
lexerror("#else after #else");
|
||||
++(ifstack[nestlevel]);
|
||||
if (!to_endif && nestlevel == skiplevel) {
|
||||
if (SkipToNewLine())
|
||||
if (SkipToNewLine()) {
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #else");
|
||||
}
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
|
@ -222,9 +233,10 @@ int to_endif;
|
|||
case K_ENDIF:
|
||||
ASSERT(nestlevel > nestlow);
|
||||
if (nestlevel == skiplevel) {
|
||||
if (SkipToNewLine())
|
||||
if (SkipToNewLine()) {
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #endif");
|
||||
}
|
||||
nestlevel--;
|
||||
NoUnstack--;
|
||||
return;
|
||||
|
@ -311,7 +323,7 @@ do_define()
|
|||
return;
|
||||
}
|
||||
/* there is a formal parameter list if the identifier is
|
||||
followed immediately by a '('.
|
||||
followed immediately by a '('.
|
||||
*/
|
||||
ch = GetChar();
|
||||
if (ch == '(') {
|
||||
|
@ -324,17 +336,8 @@ do_define()
|
|||
/* read the replacement text if there is any */
|
||||
ch = skipspaces(ch,0); /* find first character of the text */
|
||||
ASSERT(ch != EOI);
|
||||
if (class(ch) == STNL) {
|
||||
/* Treat `#define something' as `#define something ""'
|
||||
*/
|
||||
repl_text = Malloc(1);
|
||||
*repl_text = '\0';
|
||||
length = 0;
|
||||
}
|
||||
else {
|
||||
UnGetChar();
|
||||
repl_text = get_text((nformals > 0) ? formals : 0, &length);
|
||||
}
|
||||
UnGetChar();
|
||||
repl_text = get_text((nformals > 0) ? formals : 0, &length);
|
||||
macro_def(id, repl_text, nformals, length, NOFLAG);
|
||||
LineNumber++;
|
||||
}
|
||||
|
@ -382,9 +385,10 @@ do_else()
|
|||
|
||||
do_endif()
|
||||
{
|
||||
if (SkipToNewLine())
|
||||
if (SkipToNewLine()) {
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #endif");
|
||||
}
|
||||
if (nestlevel <= nestlow) {
|
||||
lexerror("#endif without corresponding #if");
|
||||
}
|
||||
|
@ -551,7 +555,7 @@ find_name(nm, index)
|
|||
char *nm, *index[];
|
||||
{
|
||||
/* find_name() returns the index of "nm" in the namelist
|
||||
"index" if it can be found there. 0 is returned if it is
|
||||
"index" if it can be found there. 0 is returned if it is
|
||||
not there.
|
||||
*/
|
||||
register char **ip = &index[0];
|
||||
|
@ -563,6 +567,8 @@ find_name(nm, index)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
|
||||
|
||||
char *
|
||||
get_text(formals, length)
|
||||
char *formals[];
|
||||
|
@ -573,101 +579,109 @@ get_text(formals, length)
|
|||
substituting each formal parameter by a special character
|
||||
(non-ascii: 0200 & (order-number in the formal parameter
|
||||
list)) in order to substitute this character later by the
|
||||
actual parameter. The replacement text is copied into
|
||||
actual parameter. The replacement text is copied into
|
||||
itself because the copied text will contain fewer or the
|
||||
same amount of characters. The length of the replacement
|
||||
same amount of characters. The length of the replacement
|
||||
text is returned.
|
||||
|
||||
Implementation:
|
||||
finite automaton : we are only interested in
|
||||
identifiers, because they might be replaced by some actual
|
||||
parameter. Other tokens will not be seen as such.
|
||||
finite automaton : we are interested in
|
||||
1- white space, sequences must be mapped onto 1 single
|
||||
blank.
|
||||
2- identifiers, since they might be replaced by some
|
||||
actual parameter.
|
||||
3- strings and character constants, since replacing
|
||||
variables within them is illegal, and white-space is
|
||||
significant.
|
||||
4- comment, same as for 1
|
||||
Other tokens will not be seen as such.
|
||||
*/
|
||||
register int c;
|
||||
register int text_size;
|
||||
char *text = Malloc(text_size = ITEXTSIZE);
|
||||
register int pos = 0;
|
||||
struct repl repls;
|
||||
register struct repl *repl = &repls;
|
||||
int blank = 0;
|
||||
|
||||
c = GetChar();
|
||||
|
||||
repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
|
||||
while ((c != EOI) && (class(c) != STNL)) {
|
||||
if (BLANK(c)) {
|
||||
if (!blank++) add2repl(repl, ' ');
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\'' || c == '"') {
|
||||
register int delim = c;
|
||||
|
||||
do {
|
||||
/* being careful, as ever */
|
||||
if (pos+3 >= text_size)
|
||||
text = Realloc(text,
|
||||
(unsigned) (text_size += RTEXTSIZE));
|
||||
text[pos++] = c;
|
||||
if (c == '\\')
|
||||
text[pos++] = GetChar();
|
||||
add2repl(repl, c);
|
||||
if (c == '\\') add2repl(repl, GetChar());
|
||||
c = GetChar();
|
||||
} while (c != delim && c != EOI && class(c) != STNL);
|
||||
text[pos++] = c;
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
}
|
||||
else
|
||||
if (c == '/') {
|
||||
} else if (c == '/') {
|
||||
c = GetChar();
|
||||
if (pos+1 >= text_size)
|
||||
text = Realloc(text,
|
||||
(unsigned) (text_size += RTEXTSIZE));
|
||||
if (c == '*') {
|
||||
skipcomment();
|
||||
text[pos++] = ' ';
|
||||
if(blank++) add2repl(repl, ' ');
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
text[pos++] = '/';
|
||||
}
|
||||
else
|
||||
if (formals && (class(c) == STIDF || class(c) == STELL)) {
|
||||
else add2repl(repl, '/');
|
||||
} else if (formals
|
||||
&& (class(c) == STIDF || class(c) == STELL)) {
|
||||
char id_buf[IDFSIZE + 1];
|
||||
register id_size = 0;
|
||||
register n;
|
||||
register char *idp = id_buf;
|
||||
int n;
|
||||
|
||||
/* read identifier: it may be a formal parameter */
|
||||
id_buf[id_size++] = c;
|
||||
*idp++ = c;
|
||||
do {
|
||||
c = GetChar();
|
||||
if (id_size <= IDFSIZE)
|
||||
id_buf[id_size++] = c;
|
||||
if (idp <= &id_buf[IDFSIZE])
|
||||
*idp++ = c;
|
||||
} while (in_idf(c));
|
||||
id_buf[--id_size] = '\0';
|
||||
if (n = find_name(id_buf, formals)) {
|
||||
/* construct the formal parameter mark */
|
||||
if (pos+1 >= text_size)
|
||||
text = Realloc(text,
|
||||
(unsigned) (text_size += RTEXTSIZE));
|
||||
text[pos++] = FORMALP | (char) n;
|
||||
}
|
||||
*--idp = '\0';
|
||||
/* construct the formal parameter mark or identifier */
|
||||
if (n = find_name(id_buf, formals))
|
||||
add2repl(repl, FORMALP | (char) n);
|
||||
else {
|
||||
register char *ptr = &id_buf[0];
|
||||
|
||||
while (pos + id_size >= text_size)
|
||||
text = Realloc(text,
|
||||
(unsigned) (text_size += RTEXTSIZE));
|
||||
while (text[pos++] = *ptr++)
|
||||
/* EMPTY */ ;
|
||||
pos--;
|
||||
idp = id_buf;
|
||||
while (*idp) add2repl(repl, *idp++);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pos+1 >= text_size)
|
||||
text = Realloc(text,
|
||||
(unsigned) (text_size += RTEXTSIZE));
|
||||
text[pos++] = c;
|
||||
} else if (class(c) == STNUM) {
|
||||
add2repl(repl, c);
|
||||
if (c == '.') {
|
||||
c = GetChar();
|
||||
if (class(c) != STNUM) {
|
||||
blank = 0; continue;
|
||||
}
|
||||
add2repl(repl, c);
|
||||
}
|
||||
c = GetChar();
|
||||
while(in_idf(c) || c == '.') {
|
||||
add2repl(repl, c);
|
||||
if((c = GetChar()) == 'e' || c == 'E') {
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
if (c == '+' || c == '-') {
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
}
|
||||
blank = 0;
|
||||
}
|
||||
text[pos++] = '\0';
|
||||
*length = pos - 1;
|
||||
return text;
|
||||
*length = repl->r_ptr - repl->r_text;
|
||||
return Realloc(repl->r_text, repl->r_ptr - repl->r_text + 1);
|
||||
}
|
||||
|
||||
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
|
||||
|
||||
/* macroeq() decides whether two macro replacement texts are
|
||||
identical. This version compares the texts, which occur
|
||||
as strings, without taking care of the leading and trailing
|
||||
|
@ -676,7 +690,7 @@ get_text(formals, length)
|
|||
macroeq(s, t)
|
||||
register char *s, *t;
|
||||
{
|
||||
|
||||
|
||||
/* skip leading spaces */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
|
@ -746,9 +760,10 @@ do_line(l)
|
|||
unsigned int l;
|
||||
{
|
||||
struct token tk;
|
||||
int t = GetToken(&tk);
|
||||
|
||||
LineNumber = l - 1; /* the number of the next input line */
|
||||
if (GetToken(&tk) == STRING) /* is there a filespecifier? */
|
||||
FileName = tk.tk_bts;
|
||||
SkipToNewLine();
|
||||
LineNumber = l; /* the number of the next input line */
|
||||
if (t == STRING) /* is there a filespecifier? */
|
||||
FileName = tk.tk_bts;
|
||||
}
|
||||
|
|
|
@ -502,7 +502,7 @@ is_zero_cst(expr)
|
|||
case Value:
|
||||
return expr->VL_VALUE == 0;
|
||||
case Float:
|
||||
flt_arith2flt((arith) 0, &var);
|
||||
flt_arith2flt((arith) 0, &var, 0);
|
||||
return flt_cmp(&var, &(expr->FL_ARITH)) == 0;
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
|
|
|
@ -205,8 +205,10 @@ declare_idf(ds, dc, lvl)
|
|||
but it has to be:
|
||||
*/
|
||||
extern char *symbol2str();
|
||||
error("unknown %s-type",
|
||||
symbol2str(type->tp_fund));
|
||||
if (type->tp_fund != VOID)
|
||||
error("unknown %s-type",
|
||||
symbol2str(type->tp_fund));
|
||||
else error("void is not a complete type");
|
||||
}
|
||||
else if (type->tp_fund != LABEL) {
|
||||
/* CJ */
|
||||
|
|
|
@ -61,9 +61,15 @@ initial_value(register struct type **tpp; register struct expr **expp;) :
|
|||
if ((*expp)->ex_type->tp_fund == ARRAY)
|
||||
array2pointer(*expp);
|
||||
if (tpp) {
|
||||
gen_simple_exp(tpp, expp);
|
||||
free_expression(*expp);
|
||||
*expp = 0;
|
||||
if (is_ld_cst(*expp) || is_fp_cst(*expp) || level >= L_LOCAL) {
|
||||
gen_simple_exp(tpp, expp);
|
||||
free_expression(*expp);
|
||||
*expp = 0;
|
||||
} else {
|
||||
expr_error(*expp,"illegal initialisation");
|
||||
free_expression(*expp);
|
||||
*expp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
||||
|
@ -152,6 +158,7 @@ gen_simple_exp(tpp, expp)
|
|||
check_and_pad(expp, tpp);
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
case VOID:
|
||||
gen_error = pack_level;
|
||||
break;
|
||||
default:
|
||||
|
@ -544,6 +551,7 @@ and also to prevent runtime coercions for compile-time constants.
|
|||
#endif NOBITFIELD
|
||||
|
||||
case ERRONEOUS:
|
||||
case VOID:
|
||||
break;
|
||||
default:
|
||||
crash("check_ival");
|
||||
|
|
|
@ -239,12 +239,6 @@ init()
|
|||
reserve(tkidf); /* mark the C reserved words as such */
|
||||
init_specials(special_ids); /* mark special ids as such */
|
||||
|
||||
/* Treat the type generic as int, having the same size and
|
||||
alignment requirements.
|
||||
This type is used as top type for void pointers, and is
|
||||
transparent to the user.
|
||||
*/
|
||||
gen_type = standard_type(GENERIC, 0, 1, (arith)1);
|
||||
schar_type = standard_type(CHAR, 0, 1, (arith)1);
|
||||
uchar_type = standard_type(CHAR, UNSIGNED, 1, (arith)1);
|
||||
|
||||
|
@ -267,7 +261,7 @@ init()
|
|||
float_type = standard_type(FLOAT, 0, float_align, float_size);
|
||||
double_type = standard_type(DOUBLE, 0, double_align, double_size);
|
||||
lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size);
|
||||
void_type = standard_type(VOID, 0, 1, (arith)0);
|
||||
void_type = standard_type(VOID, 0, 1, (arith)-1);
|
||||
label_type = standard_type(LABEL, 0, 0, (arith)0);
|
||||
error_type = standard_type(ERRONEOUS, 0, 1, (arith)1);
|
||||
|
||||
|
|
|
@ -74,11 +74,13 @@ add_proto(pl, ds, dc, lvl)
|
|||
type = declare_type(ds->ds_type, dc);
|
||||
if (type->tp_size < (arith)0 && actual_declaration(sc, type)) {
|
||||
extern char *symbol2str();
|
||||
error("unknown %s-type", symbol2str(type->tp_fund));
|
||||
} else if (type->tp_size == 0) {
|
||||
if (idf != (struct idf *)0)
|
||||
error("illegal use of void in argument list");
|
||||
else pl->pl_flag = PL_VOID;
|
||||
if (type->tp_fund != VOID)
|
||||
error("unknown %s-type", symbol2str(type->tp_fund));
|
||||
else {
|
||||
if (idf != (struct idf *)0)
|
||||
error("illegal use of void in argument list");
|
||||
else pl->pl_flag = PL_VOID;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform some special conversions for parameters.
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
#include "class.h"
|
||||
#include "assert.h"
|
||||
#include "static.h"
|
||||
#include "lapbuf.h"
|
||||
#include "argbuf.h"
|
||||
#include "macbuf.h"
|
||||
#include "replace.h"
|
||||
|
||||
extern struct idf *GetIdentifier();
|
||||
|
@ -46,7 +45,7 @@ replace(idf)
|
|||
if (idf->id_macro->mc_flag & NOREPLACE)
|
||||
return 0;
|
||||
repl = new_repl();
|
||||
repl->r_ptr = repl->r_text;
|
||||
repl->r_ptr = repl->r_text = Malloc(repl->r_size = LAPBUF);
|
||||
repl->r_args = new_args();
|
||||
repl->r_idf = idf;
|
||||
if (!expand_macro(repl, idf))
|
||||
|
@ -65,6 +64,25 @@ unstackrepl()
|
|||
Unstacked++;
|
||||
}
|
||||
|
||||
freeargs(args)
|
||||
struct args *args;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* We must don't know how many parameters were specified, so be
|
||||
* prepared to free all NPARAMS parameters.
|
||||
* When an expvec is !0, the rawvec will also be !0.
|
||||
* When an expvec is 0, all remaining vectors will also be 0.
|
||||
*/
|
||||
for (i = 0; i < NPARAMS; i++) {
|
||||
if (args->a_expvec[i]) {
|
||||
free(args->a_expvec[i]);
|
||||
free(args->a_rawvec[i]);
|
||||
} else break;
|
||||
}
|
||||
free_args(args);
|
||||
}
|
||||
|
||||
EnableMacros()
|
||||
{
|
||||
register struct repl *r = ReplaceList, *prev = 0;
|
||||
|
@ -77,7 +95,8 @@ EnableMacros()
|
|||
r->r_idf->id_macro->mc_flag &= ~NOREPLACE;
|
||||
if (!prev) ReplaceList = nxt;
|
||||
else prev->next = nxt;
|
||||
free_args(r->r_args);
|
||||
free(r->r_text);
|
||||
freeargs(r->r_args);
|
||||
free_repl(r);
|
||||
}
|
||||
else prev = r;
|
||||
|
@ -105,7 +124,7 @@ expand_macro(repl, idf)
|
|||
|
||||
A special case is "defined". This acts as a unary operator
|
||||
on a single, unexpanded identifier, which may be surrounded
|
||||
by parenthesis. The function expand_defined handles this.
|
||||
by parenthesis. The function expand_defined() handles this.
|
||||
*/
|
||||
register struct macro *mac = idf->id_macro;
|
||||
struct args *args = repl->r_args;
|
||||
|
@ -149,15 +168,10 @@ expand_macro(repl, idf)
|
|||
a+b; --> + + b ;
|
||||
|
||||
'a' must be substituded, but the result should be
|
||||
three tokens: + + ID. Because this preprocessor is
|
||||
character based, we have a problem.
|
||||
For now: just insert a space after all tokens,
|
||||
until ANSI fixes this flaw.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^ tsk tsk tsk
|
||||
three tokens: + + ID. Therefore a token separator is
|
||||
inserted after the replacement.
|
||||
*/
|
||||
if (*repl->r_ptr != TOKSEP) *repl->r_ptr++ = TOKSEP;
|
||||
*repl->r_ptr = '\0';
|
||||
|
||||
if (*(repl->r_ptr - 1) != TOKSEP) add2repl(repl, TOKSEP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -179,8 +193,7 @@ expand_defined(repl)
|
|||
error("identifier missing");
|
||||
if (parens && ch != ')') error(") missing");
|
||||
if (!parens || ch != ')') UnGetChar();
|
||||
*repl->r_ptr++ = '0';
|
||||
*repl->r_ptr = '\0';
|
||||
add2repl(repl, '0');
|
||||
return;
|
||||
}
|
||||
UnGetChar();
|
||||
|
@ -190,8 +203,14 @@ expand_defined(repl)
|
|||
ch = skipspaces(ch, 0);
|
||||
if (parens && ch != ')') error(") missing");
|
||||
if (!parens || ch != ')') UnGetChar();
|
||||
*repl->r_ptr++ = (id && id->id_macro) ? '1' : '0';
|
||||
*repl->r_ptr = '\0';
|
||||
add2repl(repl, (id && id->id_macro) ? '1' : '0');
|
||||
}
|
||||
|
||||
newarg(args)
|
||||
struct args *args;
|
||||
{
|
||||
args->a_expptr = args->a_expbuf = Malloc(args->a_expsize = ARGBUF);
|
||||
args->a_rawptr = args->a_rawbuf = Malloc(args->a_rawsize = ARGBUF);
|
||||
}
|
||||
|
||||
getactuals(repl, idf)
|
||||
|
@ -208,8 +227,7 @@ getactuals(repl, idf)
|
|||
register int ch;
|
||||
|
||||
argcnt = 0;
|
||||
args->a_expvec[0] = args->a_expptr = &args->a_expbuf[0];
|
||||
args->a_rawvec[0] = args->a_rawptr = &args->a_rawbuf[0];
|
||||
newarg(args);
|
||||
if ((ch = GetChar()) != ')') {
|
||||
UnGetChar();
|
||||
while ((ch = actual(repl)) != ')' ) {
|
||||
|
@ -218,15 +236,18 @@ getactuals(repl, idf)
|
|||
return;
|
||||
}
|
||||
stash(repl, '\0', 1);
|
||||
args->a_expvec[argcnt] = args->a_expbuf;
|
||||
args->a_rawvec[argcnt] = args->a_rawbuf;
|
||||
++argcnt;
|
||||
args->a_expvec[argcnt] = args->a_expptr;
|
||||
args->a_rawvec[argcnt] = args->a_rawptr;
|
||||
if (argcnt == STDC_NPARAMS)
|
||||
lexstrict("number of parameters exceeds ANSI standard");
|
||||
if (argcnt >= NPARAMS)
|
||||
fatal("argument vector overflow");
|
||||
newarg(args);
|
||||
}
|
||||
stash(repl, '\0', 1);
|
||||
args->a_expvec[argcnt] = args->a_expbuf;
|
||||
args->a_rawvec[argcnt] = args->a_rawbuf;
|
||||
++argcnt;
|
||||
}
|
||||
if (argcnt < nps)
|
||||
|
@ -245,7 +266,7 @@ struct repl *repl;
|
|||
|
||||
/* stash identifier name */
|
||||
for (p = nrepl->r_idf->id_text; *p != '\0'; p++)
|
||||
*args->a_rawptr++ = *p;
|
||||
stash(repl, *p, -1);
|
||||
|
||||
/* The following code deals with expanded function
|
||||
like macro calls. It makes the following code
|
||||
|
@ -267,8 +288,8 @@ struct repl *repl;
|
|||
*args->a_rawptr++ = '(';
|
||||
for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
|
||||
for (p = ap->a_rawvec[i]; *p != '\0'; p++)
|
||||
*args->a_rawptr++ = *p;
|
||||
*args->a_rawptr++ = ',';
|
||||
stash(repl, *p, -1);
|
||||
stash(repl, ',', -1);
|
||||
}
|
||||
*(args->a_rawptr-1) = ')'; /* delete last ',' */
|
||||
}
|
||||
|
@ -386,27 +407,43 @@ actual(repl)
|
|||
} else if (ch == '\n') {
|
||||
/* newlines are accepted as white spaces */
|
||||
LineNumber++;
|
||||
while ((ch = GetChar()), class(ch) == STSKIP)
|
||||
/* EMPTY */;
|
||||
|
||||
/* This piece of code needs some explanation:
|
||||
consider the call of a macro defined as:
|
||||
#define sum(a,b) (a+b)
|
||||
in the following form:
|
||||
sum(
|
||||
#include phone_number
|
||||
/_* comment *_/ #include phone_number
|
||||
,2);
|
||||
in which case the include must be handled
|
||||
interpreted as such.
|
||||
*/
|
||||
|
||||
ch = GetChar();
|
||||
while (class(ch) == STSKIP || ch == '/') {
|
||||
if (ch == '/') {
|
||||
if ((ch = GetChar()) == '*' && !InputLevel) {
|
||||
skipcomment();
|
||||
stash(repl, ' ', !nostashraw);
|
||||
ch = GetChar();
|
||||
continue;
|
||||
} else {
|
||||
UnGetChar();
|
||||
ch = '/';
|
||||
}
|
||||
stash(repl, '/', !nostashraw);
|
||||
break;
|
||||
} else ch = GetChar();
|
||||
}
|
||||
if (ch == '#')
|
||||
domacro();
|
||||
else if (ch == EOI) {
|
||||
lexerror("unterminated macro call");
|
||||
return ')';
|
||||
}
|
||||
UnGetChar();
|
||||
stash(repl, ' ', !nostashraw);
|
||||
if (ch != '/') {
|
||||
UnGetChar();
|
||||
stash(repl, ' ', !nostashraw);
|
||||
}
|
||||
} else if (ch == '/') {
|
||||
/* comments are treated as one white space token */
|
||||
if ((ch = GetChar()) == '*' && !InputLevel) {
|
||||
|
@ -509,52 +546,50 @@ macro2buffer(repl, idf, args)
|
|||
smarter should be done (but even a DFA is O(|s|)).
|
||||
*/
|
||||
register char *ptr = idf->id_macro->mc_text;
|
||||
register char *tmpptr;
|
||||
int err = 0;
|
||||
char *stringify();
|
||||
|
||||
while (*ptr) {
|
||||
ASSERT(repl->r_ptr < &(repl->r_text[LAPBUF]));
|
||||
if (*ptr == '\'' || *ptr == '"') {
|
||||
register int delim = *ptr;
|
||||
|
||||
do {
|
||||
*repl->r_ptr++ = *ptr;
|
||||
add2repl(repl, *ptr);
|
||||
if (*ptr == '\\')
|
||||
*repl->r_ptr++ = *++ptr;
|
||||
add2repl(repl, *++ptr);
|
||||
if (*ptr == '\0') {
|
||||
lexerror("unterminated string");
|
||||
*repl->r_ptr = '\0';
|
||||
return;
|
||||
}
|
||||
ptr++;
|
||||
} while (*ptr != delim || *ptr == '\0');
|
||||
*repl->r_ptr++ = *ptr++;
|
||||
add2repl(repl, *ptr++);
|
||||
} else if (*ptr == '#') {
|
||||
if (*++ptr == '#') {
|
||||
register int tmpindex;
|
||||
/* ## - paste operator */
|
||||
ptr++;
|
||||
|
||||
/* trim the actual replacement list */
|
||||
--repl->r_ptr;
|
||||
while (is_wsp(*repl->r_ptr)
|
||||
&& repl->r_ptr >= repl->r_text)
|
||||
while (repl->r_ptr >= repl->r_text
|
||||
&& is_wsp(*repl->r_ptr))
|
||||
--repl->r_ptr;
|
||||
|
||||
/* ## occurred at the beginning of the replacement list.
|
||||
*/
|
||||
if (repl->r_ptr == repl->r_text
|
||||
&& is_wsp(*repl->r_ptr)) {
|
||||
if (repl->r_ptr < repl->r_text) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
while(*repl->r_ptr == TOKSEP
|
||||
&& repl->r_ptr >= repl->r_text)
|
||||
if (repl->r_ptr >= repl->r_text
|
||||
&& *repl->r_ptr == TOKSEP)
|
||||
--repl->r_ptr;
|
||||
|
||||
tmpptr = repl->r_ptr;
|
||||
++repl->r_ptr;
|
||||
tmpindex = repl->r_ptr - repl->r_text;
|
||||
/* tmpindex can be 0 */
|
||||
|
||||
/* skip space in macro replacement list */
|
||||
while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
|
||||
|
@ -569,27 +604,29 @@ macro2buffer(repl, idf, args)
|
|||
ASSERT(n > 0);
|
||||
p = args->a_rawvec[n-1];
|
||||
if (p) { /* else macro argument missing */
|
||||
while (is_wsp(*p))
|
||||
p++;
|
||||
while (is_wsp(*p)) p++;
|
||||
if (*p == NOEXPM) p++;
|
||||
while (*p)
|
||||
*repl->r_ptr++ = *p++;
|
||||
}
|
||||
if (in_idf(*tmpptr + 1)) {
|
||||
while (in_idf(*tmpptr)
|
||||
&& tmpptr >= repl->r_text)
|
||||
tmpptr--;
|
||||
if (*tmpptr == NOEXPM) *tmpptr = TOKSEP;
|
||||
add2repl(repl, *p++);
|
||||
}
|
||||
while (tmpindex > 0
|
||||
&& in_idf(repl->r_text[tmpindex]))
|
||||
tmpindex--;
|
||||
if (tmpindex >= 0
|
||||
&& repl->r_text[tmpindex] == NOEXPM)
|
||||
repl->r_text[tmpindex] = TOKSEP;
|
||||
} else if (*ptr == '\0') {
|
||||
err = 1;
|
||||
break;
|
||||
} else {
|
||||
if (in_idf(*ptr)) {
|
||||
while (in_idf(*tmpptr)
|
||||
&& tmpptr >= repl->r_text)
|
||||
tmpptr--;
|
||||
if (*tmpptr == NOEXPM) *tmpptr = TOKSEP;
|
||||
tmpindex--;
|
||||
while (tmpindex > 0
|
||||
&& in_idf(repl->r_text[tmpindex]))
|
||||
tmpindex--;
|
||||
if (tmpindex >= 0
|
||||
&& repl->r_text[tmpindex] == NOEXPM)
|
||||
repl->r_text[tmpindex] = TOKSEP;
|
||||
}
|
||||
}
|
||||
} else /* # operator */
|
||||
|
@ -602,7 +639,7 @@ macro2buffer(repl, idf, args)
|
|||
ASSERT(n > 0);
|
||||
|
||||
/* This is VERY dirty, we look ahead for the
|
||||
## operater. If it's found we use the raw
|
||||
## operator. If it's found we use the raw
|
||||
argument buffer instead of the expanded
|
||||
one.
|
||||
*/
|
||||
|
@ -613,17 +650,15 @@ macro2buffer(repl, idf, args)
|
|||
else
|
||||
q = args->a_expvec[n-1];
|
||||
|
||||
p = repl->r_ptr;
|
||||
if (q) /* else macro argument missing */
|
||||
while (*q)
|
||||
*repl->r_ptr++ = *q++;
|
||||
add2repl(repl, *q++);
|
||||
|
||||
if (*repl->r_ptr != TOKSEP)
|
||||
*repl->r_ptr++ = TOKSEP;
|
||||
if (*(repl->r_ptr - 1) != TOKSEP)
|
||||
add2repl(repl, TOKSEP);
|
||||
} else
|
||||
*repl->r_ptr++ = *ptr++;
|
||||
add2repl(repl, *ptr++);
|
||||
}
|
||||
*repl->r_ptr = '\0';
|
||||
if (err)
|
||||
lexerror("illegal use of the ## operator");
|
||||
}
|
||||
|
@ -660,12 +695,12 @@ stringify(repl, ptr, args)
|
|||
|
||||
ASSERT(n != 0);
|
||||
p = args->a_rawvec[n-1];
|
||||
*repl->r_ptr++ = '"';
|
||||
add2repl(repl, '"');
|
||||
while (*p) {
|
||||
if (is_wsp(*p)) {
|
||||
if (!space) {
|
||||
space = 1;
|
||||
*repl->r_ptr++ = ' ';
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
p++;
|
||||
continue;
|
||||
|
@ -678,22 +713,41 @@ stringify(repl, ptr, args)
|
|||
delim = 0;
|
||||
backslash = *p == '\\';
|
||||
if (*p == '"' || (delim && *p == '\\'))
|
||||
*repl->r_ptr++ = '\\';
|
||||
add2repl(repl, '\\');
|
||||
if (*p == TOKSEP || *p == NOEXPM) p++;
|
||||
else *repl->r_ptr++ = *p++;
|
||||
else add2repl(repl, *p++);
|
||||
}
|
||||
|
||||
/* trim spaces in the replacement list */
|
||||
for (--repl->r_ptr; is_wsp(*repl->r_ptr); repl->r_ptr--)
|
||||
/* EMPTY */;
|
||||
*++repl->r_ptr = '"';
|
||||
++repl->r_ptr; /* oops, one to far */
|
||||
++repl->r_ptr; /* oops, one to far */
|
||||
add2repl(repl, '"');
|
||||
} else
|
||||
error("illegal use of # operator");
|
||||
*repl->r_ptr = '\0';
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* The following routine is also called from domacro.c.
|
||||
*/
|
||||
add2repl(repl, ch)
|
||||
register struct repl *repl;
|
||||
int ch;
|
||||
{
|
||||
register int index = repl->r_ptr - repl->r_text;
|
||||
|
||||
if (index + 1 >= repl->r_size) {
|
||||
repl->r_text = Realloc(repl->r_text, repl->r_size <<= 1);
|
||||
repl->r_ptr = repl->r_text + index;
|
||||
}
|
||||
*repl->r_ptr++ = ch;
|
||||
*repl->r_ptr = '\0';
|
||||
}
|
||||
|
||||
/* If the variable stashraw is negative, we must only stash into the raw
|
||||
* buffer. If the variable is zero, we must only stash into the expanded
|
||||
* buffer. Otherwise, we must use both buffers.
|
||||
*/
|
||||
stash(repl, ch, stashraw)
|
||||
struct repl *repl;
|
||||
register int ch;
|
||||
|
@ -702,14 +756,24 @@ stash(repl, ch, stashraw)
|
|||
/* Stash characters into the macro expansion buffer.
|
||||
*/
|
||||
register struct args *args = repl->r_args;
|
||||
register int index = args->a_expptr - args->a_expbuf;
|
||||
|
||||
if (args->a_expptr >= &(args->a_expbuf[ARGBUF]))
|
||||
fatal("macro argument buffer overflow");
|
||||
*args->a_expptr++ = ch;
|
||||
if (stashraw >= 0) {
|
||||
if (index + 1 >= args->a_expsize) {
|
||||
args->a_expbuf = Realloc(args->a_expbuf,
|
||||
args->a_expsize <<= 1);
|
||||
args->a_expptr = args->a_expbuf + index;
|
||||
}
|
||||
*args->a_expptr++ = ch;
|
||||
}
|
||||
|
||||
if (stashraw) {
|
||||
if (args->a_rawptr >= &(args->a_rawbuf[ARGBUF]))
|
||||
fatal("raw macro argument buffer overflow");
|
||||
index = args->a_rawptr - args->a_rawbuf;
|
||||
if (index + 1 >= args->a_rawsize) {
|
||||
args->a_rawbuf = Realloc(args->a_rawbuf,
|
||||
args->a_rawsize <<= 1);
|
||||
args->a_rawptr = args->a_rawbuf + index;
|
||||
}
|
||||
*args->a_rawptr++ = ch;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@ struct repl {
|
|||
struct idf *r_idf; /* name of the macro */
|
||||
struct args *r_args; /* replacement parameters */
|
||||
int r_level; /* level of insertion */
|
||||
char *r_ptr; /* replacement text pointer */
|
||||
char r_text[LAPBUF]; /* replacement text */
|
||||
int r_size; /* current size of replacement buffer */
|
||||
char *r_ptr; /* replacement text index pointer */
|
||||
char *r_text; /* replacement text */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "repl" 4 */
|
||||
|
@ -27,12 +28,14 @@ struct repl {
|
|||
operator, and an expanded one as argument for h().
|
||||
*/
|
||||
struct args {
|
||||
char *a_expptr; /* expanded argument pointer */
|
||||
char *a_expptr; /* expanded argument index pointer */
|
||||
char *a_expbuf; /* expanded argument buffer pointer */
|
||||
int a_expsize; /* current size of expanded buffer */
|
||||
char *a_expvec[NPARAMS]; /* expanded argument vector */
|
||||
char a_expbuf[ARGBUF]; /* expanded argument buffer space */
|
||||
char *a_rawptr; /* raw argument pointer */
|
||||
char *a_rawptr; /* raw argument index pointer */
|
||||
char *a_rawbuf; /* raw argument buffer pointer */
|
||||
int a_rawsize; /* current size of raw buffer */
|
||||
char *a_rawvec[NPARAMS]; /* raw argument vector */
|
||||
char a_rawbuf[ARGBUF]; /* raw argument buffer space */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "args" 2 */
|
||||
|
|
|
@ -65,16 +65,16 @@ SkipToNewLine()
|
|||
register int garbage = 0;
|
||||
|
||||
while ((ch = GetChar()) != '\n') {
|
||||
#ifndef NOPP
|
||||
if (ch == '/') {
|
||||
if ((ch = GetChar()) == '*'
|
||||
#ifndef NOPP
|
||||
&& !InputLevel
|
||||
#endif
|
||||
) {
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!is_wsp(ch))
|
||||
garbage = 1;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,6 @@ struct tokenname tkfunny[] = { /* internal keywords */
|
|||
{LNGDBL, "long double"},
|
||||
{ULONG, "unsigned long"},
|
||||
{VOID, "void"},
|
||||
{GENERIC, "generic"},
|
||||
|
||||
{ARRAY, "array"},
|
||||
{FUNCTION, "function"},
|
||||
|
|
|
@ -33,7 +33,7 @@ struct type
|
|||
*int_type, *uint_type,
|
||||
*long_type, *ulong_type,
|
||||
*float_type, *double_type, *lngdbl_type,
|
||||
*void_type, *gen_type, *label_type,
|
||||
*void_type, *label_type,
|
||||
*string_type, *funint_type, *error_type;
|
||||
|
||||
struct type *pa_type; /* Pointer-Arithmetic type */
|
||||
|
@ -98,22 +98,17 @@ construct_type(fund, tp, qual, count, pl)
|
|||
dtp = function_of(tp, pl, qual);
|
||||
break;
|
||||
case POINTER:
|
||||
if (tp->tp_fund == VOID) {
|
||||
/* A void pointer has the same characteristics as a
|
||||
character pointer. I can't make them equal, because
|
||||
i would like to have the type information around */
|
||||
tp = qualifier_type(gen_type, tp->tp_typequal);
|
||||
}
|
||||
dtp = pointer_to(tp, qual);
|
||||
break;
|
||||
case ARRAY:
|
||||
if (count >= 0 && tp->tp_size < 0) {
|
||||
if (tp->tp_fund == VOID) {
|
||||
error("cannot construct array of void");
|
||||
count = (arith) -1;
|
||||
} else if (count >= 0 && tp->tp_size < 0) {
|
||||
error("cannot construct array of unknown type");
|
||||
count = (arith)-1;
|
||||
}
|
||||
else if (tp->tp_size == 0) /* CJ */
|
||||
strict("array elements have size 0");
|
||||
if (count >= (arith)0)
|
||||
if (count > (arith)0)
|
||||
count *= tp->tp_size;
|
||||
dtp = array_of(tp, count, qual);
|
||||
break;
|
||||
|
@ -150,7 +145,8 @@ function_of(tp, pl, qual)
|
|||
if (!dtp) {
|
||||
dtp = create_type(FUNCTION);
|
||||
dtp->tp_up = tp;
|
||||
dtp->tp_size = pointer_size;
|
||||
/* dtp->tp_size = pointer_size; ??? */
|
||||
dtp->tp_size = -1; /* function size is not known */
|
||||
dtp->tp_align = pointer_align;
|
||||
dtp->tp_typequal = qual;
|
||||
dtp->tp_proto = pl;
|
||||
|
|
|
@ -48,7 +48,7 @@ extern struct type
|
|||
*int_type, *uint_type,
|
||||
*long_type, *ulong_type,
|
||||
*float_type, *double_type, *lngdbl_type,
|
||||
*void_type, *gen_type, *label_type,
|
||||
*void_type, *label_type,
|
||||
*string_type, *funint_type, *error_type;
|
||||
|
||||
extern struct type *pa_type; /* type.c */
|
||||
|
|
Loading…
Reference in a new issue