#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
!File: textsize.h
#define ITEXTSIZE 32 /* 1st piece of memory for repl. text */
-#define RTEXTSIZE 16 /* stepsize for enlarging repl.text */
!File: inputtype.h
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 */
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 */
*/
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
register int ch, nch;
+ int nlflag = 0;
token_nmb++;
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 */
File_Inserted = 0;
goto firstline;
}
+ } else if (ch == '/') {
+ if ((GetChar() == '*') && !InputLevel) {
+ skipcomment();
+ } else {
+ UnGetChar();
+ break;
+ }
#endif /* NOPP */
}
}
case STSKIP: /* just skip the skip characters */
goto again;
case STGARB: /* garbage character */
-#ifndef NOPP
+#ifndef NOPP
garbage:
#endif
if (040 < ch && ch < 0177)
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;
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;
/*NOTREACHED*/
}
+#ifndef NOPP
skipcomment()
{
/* The last character read has been the '*' of '/_*'. The
#endif LINT
NoUnstack--;
}
+#endif /* NOPP */
arith
char_constant(nm)
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') {
!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
# Machine and environ dependent definitions
EMHOME = ../../..
CC = $(EMHOME)/bin/fcc
-CC = cc
+#CC = cc
CFLOW = cflow
MKDEP = $(EMHOME)/bin/mkdep
PRID = $(EMHOME)/bin/prid
# .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 \
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
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
#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
!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
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
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)) {
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);
/* 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)
{
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
{
if (!*expp)
return;
+
+ if (oper == SIZEOF || oper == '&') return;
+
switch ((*expp)->ex_type->tp_fund) {
case CHAR:
case SHORT:
if ((*expp)->ex_class == String)
string2pointer(*expp);
break;
+ case FUNCTION:
+ function2pointer(*expp);
+ break;
#ifndef NOBITFIELD
case FIELD:
field2arith(expp);
}
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);
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) {
register struct type *tp;
{
switch (tp->tp_fund) {
- case GENERIC:
case CHAR:
case SHORT:
case INT:
register struct type *tp;
{
switch (tp->tp_fund) {
- case GENERIC:
case CHAR:
case SHORT:
case INT:
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;
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;
}
*/
*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 ??? */
}
*/
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)
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
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);
(*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;
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;
, 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;
}
register struct type *tp;
{
switch (tp->tp_fund) {
- case GENERIC:
case CHAR:
case SHORT:
case INT:
}
'='
{
+ if (AHEAD != '{') autoagg = 0;
#ifdef LINT
lint_statement();
#endif LINT
#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 */
NoUnstack--;
return;
}
- UnGetChar();
+ /* A possible '/' is not pushed back */
+ if (ch == '/') {
+ ch = GetChar();
+ if (ch != '*') UnGetChar();
+ else {
+ skipcomment();
+ continue;
+ }
+ } else UnGetChar();
SkipToNewLine();
continue;
}
lexerror("#else after #else");
++(ifstack[nestlevel]);
if (!to_endif && nestlevel == skiplevel) {
- if (SkipToNewLine())
+ if (SkipToNewLine()) {
if (!options['o'])
lexstrict("garbage following #else");
+ }
NoUnstack--;
return;
}
case K_ENDIF:
ASSERT(nestlevel > nestlow);
if (nestlevel == skiplevel) {
- if (SkipToNewLine())
+ if (SkipToNewLine()) {
if (!options['o'])
lexstrict("garbage following #endif");
+ }
nestlevel--;
NoUnstack--;
return;
return;
}
/* there is a formal parameter list if the identifier is
- followed immediately by a '('.
+ followed immediately by a '('.
*/
ch = GetChar();
if (ch == '(') {
/* 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++;
}
do_endif()
{
- if (SkipToNewLine())
+ if (SkipToNewLine()) {
if (!options['o'])
lexstrict("garbage following #endif");
+ }
if (nestlevel <= nestlow) {
lexerror("#endif without corresponding #if");
}
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];
return 0;
}
+#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
+
char *
get_text(formals, length)
char *formals[];
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 (class(c) == STNUM) {
+ add2repl(repl, c);
+ if (c == '.') {
+ c = GetChar();
+ if (class(c) != STNUM) {
+ blank = 0; continue;
+ }
+ add2repl(repl, c);
}
- }
- else {
- if (pos+1 >= text_size)
- text = Realloc(text,
- (unsigned) (text_size += RTEXTSIZE));
- text[pos++] = 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
macroeq(s, t)
register char *s, *t;
{
-
+
/* skip leading spaces */
while (BLANK(*s)) s++;
while (BLANK(*t)) t++;
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;
}
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*/
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 */
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;
+ }
}
}
|
check_and_pad(expp, tpp);
break;
case ERRONEOUS:
+ case VOID:
gen_error = pack_level;
break;
default:
#endif NOBITFIELD
case ERRONEOUS:
+ case VOID:
break;
default:
crash("check_ival");
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);
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);
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.
#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();
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))
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;
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;
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;
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;
}
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();
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)
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)) != ')' ) {
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)
/* 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
*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 ',' */
}
} 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) {
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))
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 */
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.
*/
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");
}
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;
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;
/* 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;
}
}
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 */
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 */
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;
}
{LNGDBL, "long double"},
{ULONG, "unsigned long"},
{VOID, "void"},
- {GENERIC, "generic"},
{ARRAY, "array"},
{FUNCTION, "function"},
*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 */
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;
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;
*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 */