Convert all the things to Unix format.
This commit is contained in:
parent
020c84db3d
commit
9519588f59
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
---
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
|
|
|
@ -1,135 +1,135 @@
|
|||
!File: lint.h
|
||||
/*#define LINT 1 *//* if defined, 'lint' is produced */
|
||||
|
||||
|
||||
!File: pathlength.h
|
||||
#define PATHLENGTH 1024 /* max. length of path to file */
|
||||
|
||||
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define ERR_SHADOW 5 /* a syntax error overshadows error messages
|
||||
until ERR_SHADOW symbols have been
|
||||
accepted without syntax error */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 64 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: nparams.h
|
||||
#define NPARAMS 32 /* maximum number of parameters */
|
||||
#define STDC_NPARAMS 31 /* ANSI limit on number of parameters */
|
||||
|
||||
|
||||
!File: ifdepth.h
|
||||
#define IFDEPTH 256 /* maximum number of nested if-constructions */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 3 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!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
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 16 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: trgt_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_WORD 4
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_LNGLNG -1
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_DOUBLE 8
|
||||
#define SZ_LNGDBL 8 /* for now */
|
||||
#define SZ_POINTER 4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#define AL_LNGLNG SZ_WORD
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#define AL_LNGDBL SZ_WORD
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: botch_free.h
|
||||
/*#define BOTCH_FREE 1* *//* when defined, botch freed memory, as a check */
|
||||
|
||||
|
||||
!File: dataflow.h
|
||||
#define DATAFLOW 1 /* produce some compile-time xref */
|
||||
|
||||
|
||||
!File: debug.h
|
||||
/*#define DEBUG 1 *//* perform various self-tests */
|
||||
#define NDEBUG 1 /* disable assertions */
|
||||
|
||||
|
||||
!File: use_tmp.h
|
||||
#define PREPEND_SCOPES 1 /* collect exa, exp, ina and inp commands
|
||||
and if USE_TMP is defined let them
|
||||
precede the rest of the generated
|
||||
compact code */
|
||||
#define USE_TMP 1 /* use C_insertpart, C_endpart mechanism
|
||||
to generate EM-code in the order needed
|
||||
for the code-generators. If not defined,
|
||||
the old-style peephole optimizer is
|
||||
needed. */
|
||||
|
||||
|
||||
!File: parbufsize.h
|
||||
#define PARBUFSIZE 1024
|
||||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 32 /* 1st piece of memory for repl. text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
/*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */
|
||||
|
||||
|
||||
!File: static.h
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
/*#define NOCROSS 1 *//* if NOT defined, cross compiler */
|
||||
|
||||
|
||||
!File: regcount.h
|
||||
/*#define REGCOUNT 1 *//* count occurrences for register messages */
|
||||
|
||||
|
||||
!File: dbsymtab.h
|
||||
#define DBSYMTAB 1 /* ability to produce symbol table for debugger */
|
||||
|
||||
|
||||
!File: lint.h
|
||||
/*#define LINT 1 *//* if defined, 'lint' is produced */
|
||||
|
||||
|
||||
!File: pathlength.h
|
||||
#define PATHLENGTH 1024 /* max. length of path to file */
|
||||
|
||||
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define ERR_SHADOW 5 /* a syntax error overshadows error messages
|
||||
until ERR_SHADOW symbols have been
|
||||
accepted without syntax error */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 64 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: nparams.h
|
||||
#define NPARAMS 32 /* maximum number of parameters */
|
||||
#define STDC_NPARAMS 31 /* ANSI limit on number of parameters */
|
||||
|
||||
|
||||
!File: ifdepth.h
|
||||
#define IFDEPTH 256 /* maximum number of nested if-constructions */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 3 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!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
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 16 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: trgt_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_WORD 4
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_LNGLNG -1
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_DOUBLE 8
|
||||
#define SZ_LNGDBL 8 /* for now */
|
||||
#define SZ_POINTER 4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#define AL_LNGLNG SZ_WORD
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#define AL_LNGDBL SZ_WORD
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: botch_free.h
|
||||
/*#define BOTCH_FREE 1* *//* when defined, botch freed memory, as a check */
|
||||
|
||||
|
||||
!File: dataflow.h
|
||||
#define DATAFLOW 1 /* produce some compile-time xref */
|
||||
|
||||
|
||||
!File: debug.h
|
||||
/*#define DEBUG 1 *//* perform various self-tests */
|
||||
#define NDEBUG 1 /* disable assertions */
|
||||
|
||||
|
||||
!File: use_tmp.h
|
||||
#define PREPEND_SCOPES 1 /* collect exa, exp, ina and inp commands
|
||||
and if USE_TMP is defined let them
|
||||
precede the rest of the generated
|
||||
compact code */
|
||||
#define USE_TMP 1 /* use C_insertpart, C_endpart mechanism
|
||||
to generate EM-code in the order needed
|
||||
for the code-generators. If not defined,
|
||||
the old-style peephole optimizer is
|
||||
needed. */
|
||||
|
||||
|
||||
!File: parbufsize.h
|
||||
#define PARBUFSIZE 1024
|
||||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 32 /* 1st piece of memory for repl. text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
/*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */
|
||||
|
||||
|
||||
!File: static.h
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
/*#define NOCROSS 1 *//* if NOT defined, cross compiler */
|
||||
|
||||
|
||||
!File: regcount.h
|
||||
/*#define REGCOUNT 1 *//* count occurrences for register messages */
|
||||
|
||||
|
||||
!File: dbsymtab.h
|
||||
#define DBSYMTAB 1 /* ability to produce symbol table for debugger */
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,354 +1,354 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* EXPRESSION SYNTAX PARSER */
|
||||
|
||||
{
|
||||
#include <alloc.h>
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "type.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "code.h"
|
||||
#include "error.h"
|
||||
#include "ch3.h"
|
||||
#include "ch3bin.h"
|
||||
#include "ch3mon.h"
|
||||
#include "proto.h"
|
||||
#include "sizes.h"
|
||||
|
||||
extern struct expr *intexpr();
|
||||
int InSizeof = 0; /* inside a sizeof- expression */
|
||||
int ResultKnown = 0; /* result of the expression is already known */
|
||||
|
||||
/* Since the grammar in the standard is not LL(n), it is modified so that
|
||||
* it accepts basically the same grammar. This means that there is no 1-1
|
||||
* mapping from the grammar in the standard to the grammar given here.
|
||||
* Such is life.
|
||||
*/
|
||||
}
|
||||
|
||||
/* 3.3.1 */
|
||||
primary(register struct expr **expp;) :
|
||||
IDENTIFIER
|
||||
{dot2expr(expp);}
|
||||
|
|
||||
constant(expp)
|
||||
|
|
||||
string(expp)
|
||||
|
|
||||
'(' expression(expp) ')'
|
||||
{ (*expp)->ex_flags |= EX_PARENS; }
|
||||
;
|
||||
|
||||
|
||||
/* Character string literals that are adjacent tokens
|
||||
* are concatenated into a single character string
|
||||
* literal.
|
||||
*/
|
||||
string(register struct expr **expp;)
|
||||
{ register int i, len;
|
||||
register char *str;
|
||||
register int fund;
|
||||
}
|
||||
:
|
||||
STRING
|
||||
{ str = dot.tk_bts;
|
||||
len = dot.tk_len;
|
||||
fund = dot.tk_fund;
|
||||
}
|
||||
[
|
||||
STRING
|
||||
{ /* A pasted string keeps the type of the first
|
||||
* string literal.
|
||||
* The pasting of normal strings and wide
|
||||
* character strings are stated as having an
|
||||
* undefined behaviour.
|
||||
*/
|
||||
if (dot.tk_fund != fund)
|
||||
warning("illegal pasting of string literals");
|
||||
str = Realloc(str, (unsigned) (--len + dot.tk_len));
|
||||
for (i = 0; i < dot.tk_len; i++)
|
||||
str[len++] = dot.tk_bts[i];
|
||||
}
|
||||
]*
|
||||
{ string2expr(expp, str, len); }
|
||||
;
|
||||
|
||||
/* 3.3.2 */
|
||||
postfix_expression(register struct expr **expp;)
|
||||
{ int oper;
|
||||
struct expr *e1 = 0;
|
||||
struct idf *idf;
|
||||
}
|
||||
:
|
||||
primary(expp)
|
||||
[
|
||||
'[' expression(&e1) ']'
|
||||
{ ch3bin(expp, '[', e1); e1 = 0; }
|
||||
|
|
||||
'(' parameter_list(&e1)? ')'
|
||||
{ ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; }
|
||||
|
|
||||
[ '.' | ARROW ] { oper = DOT; }
|
||||
identifier(&idf) { ch3sel(expp, oper, idf); }
|
||||
|
|
||||
[
|
||||
PLUSPLUS { oper = POSTINCR; }
|
||||
|
|
||||
MINMIN { oper = POSTDECR; }
|
||||
]
|
||||
{ ch3incr(expp, oper); }
|
||||
]*
|
||||
;
|
||||
|
||||
parameter_list(struct expr **expp;)
|
||||
{struct expr *e1 = 0;}
|
||||
:
|
||||
assignment_expression(expp)
|
||||
{any2opnd(expp, PARCOMMA);}
|
||||
[ %persistent
|
||||
','
|
||||
assignment_expression(&e1)
|
||||
{any2opnd(&e1, PARCOMMA);}
|
||||
{ch3bin(expp, PARCOMMA, e1);}
|
||||
]*
|
||||
;
|
||||
|
||||
%first first_of_type_specifier, type_specifier;
|
||||
|
||||
/* 3.3.3 & 3.3.4 */
|
||||
unary(register struct expr **expp;)
|
||||
{struct type *tp; int oper;}
|
||||
:
|
||||
%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
|
||||
cast(&tp) unary(expp)
|
||||
{ ch3cast(expp, CAST, tp);
|
||||
(*expp)->ex_flags |= EX_CAST;
|
||||
if (int_size != pointer_size)
|
||||
(*expp)->ex_flags &= ~EX_PTRDIFF;
|
||||
}
|
||||
|
|
||||
postfix_expression(expp)
|
||||
|
|
||||
unop(&oper) unary(expp)
|
||||
{ch3mon(oper, expp);}
|
||||
|
|
||||
size_of(expp)
|
||||
;
|
||||
|
||||
/* When an identifier is used in a sizeof()-expression, we must stil not
|
||||
* mark it as used.
|
||||
* extern int i; .... sizeof(i) .... need not have a definition for i
|
||||
*/
|
||||
size_of(register struct expr **expp;)
|
||||
{struct type *tp;}
|
||||
:
|
||||
SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */
|
||||
[%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
|
||||
cast(&tp)
|
||||
{
|
||||
*expp = intexpr(size_of_type(tp, "type"), UNSIGNED);
|
||||
(*expp)->ex_flags |= EX_SIZEOF;
|
||||
}
|
||||
|
|
||||
unary(expp)
|
||||
{ch3mon(SIZEOF, expp);}
|
||||
]
|
||||
{ InSizeof--; }
|
||||
;
|
||||
|
||||
/* 3.3.5-3.3.17 */
|
||||
/* The set of operators in C is stratified in 15 levels, with level
|
||||
N being treated in RM 7.N (although this is not the standard
|
||||
anymore). The standard describes this in phrase-structure-grammar,
|
||||
which we are unable to parse. The description that follows comes
|
||||
from the old C-compiler.
|
||||
|
||||
In principle each operator is assigned a rank, ranging
|
||||
from 1 to 15. Such an expression can be parsed by a construct
|
||||
like:
|
||||
binary_expression(int maxrank;)
|
||||
{int oper;}
|
||||
:
|
||||
binary_expression(maxrank - 1)
|
||||
[%if (rank_of(DOT) <= maxrank)
|
||||
binop(&oper)
|
||||
binary_expression(rank_of(oper)-1)
|
||||
]?
|
||||
;
|
||||
except that some call of 'unary' is necessary, depending on the
|
||||
grammar.
|
||||
|
||||
This simple view is marred by three complications:
|
||||
1. Level 15 (comma operator) is not allowed in many
|
||||
contexts and is different.
|
||||
2. Level 13 (conditional operator) is a ternary operator,
|
||||
which does not fit this scheme at all.
|
||||
3. Level 14 (assignment operators) group right-to-left, as
|
||||
opposed to 2-12, which group left-to-right (or are
|
||||
immaterial).
|
||||
4. The operators in level 14 start with operators in levels
|
||||
2-13 (RM 7.14: The two parts of a compound assignment
|
||||
operator are separate tokens.) This causes LL1 problems.
|
||||
This forces us to have four rules:
|
||||
binary_expression for level 2-12
|
||||
conditional_expression for level 13
|
||||
assignment_expression for level 14 and
|
||||
expression for the most general expression
|
||||
*/
|
||||
|
||||
binary_expression(int maxrank; struct expr **expp;)
|
||||
{int oper, OldResultKnown; struct expr *e1;}
|
||||
:
|
||||
unary(expp)
|
||||
[%while (rank_of(DOT) <= maxrank )
|
||||
/* '?', '=', and ',' are no binops
|
||||
*/
|
||||
binop(&oper)
|
||||
{ OldResultKnown = ResultKnown;
|
||||
if (oper == OR || oper == AND) {
|
||||
if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
|
||||
if (is_zero_cst(*expp)) {
|
||||
if (oper == AND) ResultKnown++;
|
||||
} else if (oper == OR) ResultKnown++;
|
||||
}
|
||||
}
|
||||
}
|
||||
binary_expression(rank_of(oper)-1, &e1)
|
||||
{
|
||||
ch3bin(expp, oper, e1);
|
||||
ResultKnown = OldResultKnown;
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
/* 3.3.15 */
|
||||
conditional_expression(struct expr **expp;)
|
||||
{struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;}
|
||||
:
|
||||
/* allow all binary operators */
|
||||
binary_expression(rank_of('?') - 1, expp)
|
||||
[ '?'
|
||||
{ OldResultKnown = ResultKnown;
|
||||
if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
|
||||
ConstExpr++;
|
||||
if (is_zero_cst(*expp)) ResultKnown++;
|
||||
}
|
||||
}
|
||||
expression(&e1)
|
||||
':'
|
||||
{ if (ConstExpr) {
|
||||
if (OldResultKnown == ResultKnown) ResultKnown++;
|
||||
else ResultKnown = OldResultKnown;
|
||||
}
|
||||
}
|
||||
conditional_expression(&e2)
|
||||
{
|
||||
ResultKnown = OldResultKnown;
|
||||
ch3bin(&e1, ':', e2);
|
||||
opnd2test(expp, '?');
|
||||
ch3bin(expp, '?', e1);
|
||||
}
|
||||
]?
|
||||
;
|
||||
|
||||
/* 3.3.16 */
|
||||
assignment_expression(struct expr **expp;)
|
||||
{ int oper;
|
||||
struct expr *e1 = 0;
|
||||
}
|
||||
:
|
||||
conditional_expression(expp)
|
||||
[
|
||||
asgnop(&oper)
|
||||
assignment_expression(&e1)
|
||||
{ch3asgn(expp, oper, e1);}
|
||||
|
|
||||
empty /* LLgen artefact ??? */
|
||||
]
|
||||
;
|
||||
|
||||
/* 3.3.17 */
|
||||
expression(struct expr **expp;)
|
||||
{struct expr *e1;}
|
||||
:
|
||||
assignment_expression(expp)
|
||||
[ ','
|
||||
assignment_expression(&e1)
|
||||
{
|
||||
ch3bin(expp, ',', e1);
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
unop(int *oper;) :
|
||||
['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN]
|
||||
{ if (DOT == '&') DOT = ADDRESSOF;
|
||||
*oper = DOT;
|
||||
}
|
||||
;
|
||||
|
||||
multop:
|
||||
'*' | '/' | '%'
|
||||
;
|
||||
|
||||
addop:
|
||||
'+' | '-'
|
||||
;
|
||||
|
||||
shiftop:
|
||||
LEFT | RIGHT
|
||||
;
|
||||
|
||||
relop:
|
||||
'<' | '>' | LESSEQ | GREATEREQ
|
||||
;
|
||||
|
||||
eqop:
|
||||
EQUAL | NOTEQUAL
|
||||
;
|
||||
|
||||
arithop:
|
||||
multop | addop | shiftop
|
||||
|
|
||||
'&' | '^' | '|'
|
||||
;
|
||||
|
||||
binop(int *oper;) :
|
||||
[ arithop | relop | eqop | AND | OR ]
|
||||
{*oper = DOT;}
|
||||
;
|
||||
|
||||
asgnop(register int *oper;):
|
||||
[ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB
|
||||
| LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ]
|
||||
{ *oper = DOT; }
|
||||
|
||||
;
|
||||
|
||||
constant(struct expr **expp;) :
|
||||
[
|
||||
INTEGER
|
||||
|
|
||||
FLOATING
|
||||
] {dot2expr(expp);}
|
||||
;
|
||||
|
||||
/* 3.4 */
|
||||
constant_expression (struct expr **expp;) :
|
||||
conditional_expression(expp)
|
||||
{ chk_cst_expr(expp); }
|
||||
;
|
||||
|
||||
identifier(struct idf **idfp;) :
|
||||
[ IDENTIFIER
|
||||
| TYPE_IDENTIFIER
|
||||
]
|
||||
{ *idfp = dot.tk_idf; }
|
||||
;
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* EXPRESSION SYNTAX PARSER */
|
||||
|
||||
{
|
||||
#include <alloc.h>
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "type.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "code.h"
|
||||
#include "error.h"
|
||||
#include "ch3.h"
|
||||
#include "ch3bin.h"
|
||||
#include "ch3mon.h"
|
||||
#include "proto.h"
|
||||
#include "sizes.h"
|
||||
|
||||
extern struct expr *intexpr();
|
||||
int InSizeof = 0; /* inside a sizeof- expression */
|
||||
int ResultKnown = 0; /* result of the expression is already known */
|
||||
|
||||
/* Since the grammar in the standard is not LL(n), it is modified so that
|
||||
* it accepts basically the same grammar. This means that there is no 1-1
|
||||
* mapping from the grammar in the standard to the grammar given here.
|
||||
* Such is life.
|
||||
*/
|
||||
}
|
||||
|
||||
/* 3.3.1 */
|
||||
primary(register struct expr **expp;) :
|
||||
IDENTIFIER
|
||||
{dot2expr(expp);}
|
||||
|
|
||||
constant(expp)
|
||||
|
|
||||
string(expp)
|
||||
|
|
||||
'(' expression(expp) ')'
|
||||
{ (*expp)->ex_flags |= EX_PARENS; }
|
||||
;
|
||||
|
||||
|
||||
/* Character string literals that are adjacent tokens
|
||||
* are concatenated into a single character string
|
||||
* literal.
|
||||
*/
|
||||
string(register struct expr **expp;)
|
||||
{ register int i, len;
|
||||
register char *str;
|
||||
register int fund;
|
||||
}
|
||||
:
|
||||
STRING
|
||||
{ str = dot.tk_bts;
|
||||
len = dot.tk_len;
|
||||
fund = dot.tk_fund;
|
||||
}
|
||||
[
|
||||
STRING
|
||||
{ /* A pasted string keeps the type of the first
|
||||
* string literal.
|
||||
* The pasting of normal strings and wide
|
||||
* character strings are stated as having an
|
||||
* undefined behaviour.
|
||||
*/
|
||||
if (dot.tk_fund != fund)
|
||||
warning("illegal pasting of string literals");
|
||||
str = Realloc(str, (unsigned) (--len + dot.tk_len));
|
||||
for (i = 0; i < dot.tk_len; i++)
|
||||
str[len++] = dot.tk_bts[i];
|
||||
}
|
||||
]*
|
||||
{ string2expr(expp, str, len); }
|
||||
;
|
||||
|
||||
/* 3.3.2 */
|
||||
postfix_expression(register struct expr **expp;)
|
||||
{ int oper;
|
||||
struct expr *e1 = 0;
|
||||
struct idf *idf;
|
||||
}
|
||||
:
|
||||
primary(expp)
|
||||
[
|
||||
'[' expression(&e1) ']'
|
||||
{ ch3bin(expp, '[', e1); e1 = 0; }
|
||||
|
|
||||
'(' parameter_list(&e1)? ')'
|
||||
{ ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; }
|
||||
|
|
||||
[ '.' | ARROW ] { oper = DOT; }
|
||||
identifier(&idf) { ch3sel(expp, oper, idf); }
|
||||
|
|
||||
[
|
||||
PLUSPLUS { oper = POSTINCR; }
|
||||
|
|
||||
MINMIN { oper = POSTDECR; }
|
||||
]
|
||||
{ ch3incr(expp, oper); }
|
||||
]*
|
||||
;
|
||||
|
||||
parameter_list(struct expr **expp;)
|
||||
{struct expr *e1 = 0;}
|
||||
:
|
||||
assignment_expression(expp)
|
||||
{any2opnd(expp, PARCOMMA);}
|
||||
[ %persistent
|
||||
','
|
||||
assignment_expression(&e1)
|
||||
{any2opnd(&e1, PARCOMMA);}
|
||||
{ch3bin(expp, PARCOMMA, e1);}
|
||||
]*
|
||||
;
|
||||
|
||||
%first first_of_type_specifier, type_specifier;
|
||||
|
||||
/* 3.3.3 & 3.3.4 */
|
||||
unary(register struct expr **expp;)
|
||||
{struct type *tp; int oper;}
|
||||
:
|
||||
%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
|
||||
cast(&tp) unary(expp)
|
||||
{ ch3cast(expp, CAST, tp);
|
||||
(*expp)->ex_flags |= EX_CAST;
|
||||
if (int_size != pointer_size)
|
||||
(*expp)->ex_flags &= ~EX_PTRDIFF;
|
||||
}
|
||||
|
|
||||
postfix_expression(expp)
|
||||
|
|
||||
unop(&oper) unary(expp)
|
||||
{ch3mon(oper, expp);}
|
||||
|
|
||||
size_of(expp)
|
||||
;
|
||||
|
||||
/* When an identifier is used in a sizeof()-expression, we must stil not
|
||||
* mark it as used.
|
||||
* extern int i; .... sizeof(i) .... need not have a definition for i
|
||||
*/
|
||||
size_of(register struct expr **expp;)
|
||||
{struct type *tp;}
|
||||
:
|
||||
SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */
|
||||
[%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
|
||||
cast(&tp)
|
||||
{
|
||||
*expp = intexpr(size_of_type(tp, "type"), UNSIGNED);
|
||||
(*expp)->ex_flags |= EX_SIZEOF;
|
||||
}
|
||||
|
|
||||
unary(expp)
|
||||
{ch3mon(SIZEOF, expp);}
|
||||
]
|
||||
{ InSizeof--; }
|
||||
;
|
||||
|
||||
/* 3.3.5-3.3.17 */
|
||||
/* The set of operators in C is stratified in 15 levels, with level
|
||||
N being treated in RM 7.N (although this is not the standard
|
||||
anymore). The standard describes this in phrase-structure-grammar,
|
||||
which we are unable to parse. The description that follows comes
|
||||
from the old C-compiler.
|
||||
|
||||
In principle each operator is assigned a rank, ranging
|
||||
from 1 to 15. Such an expression can be parsed by a construct
|
||||
like:
|
||||
binary_expression(int maxrank;)
|
||||
{int oper;}
|
||||
:
|
||||
binary_expression(maxrank - 1)
|
||||
[%if (rank_of(DOT) <= maxrank)
|
||||
binop(&oper)
|
||||
binary_expression(rank_of(oper)-1)
|
||||
]?
|
||||
;
|
||||
except that some call of 'unary' is necessary, depending on the
|
||||
grammar.
|
||||
|
||||
This simple view is marred by three complications:
|
||||
1. Level 15 (comma operator) is not allowed in many
|
||||
contexts and is different.
|
||||
2. Level 13 (conditional operator) is a ternary operator,
|
||||
which does not fit this scheme at all.
|
||||
3. Level 14 (assignment operators) group right-to-left, as
|
||||
opposed to 2-12, which group left-to-right (or are
|
||||
immaterial).
|
||||
4. The operators in level 14 start with operators in levels
|
||||
2-13 (RM 7.14: The two parts of a compound assignment
|
||||
operator are separate tokens.) This causes LL1 problems.
|
||||
This forces us to have four rules:
|
||||
binary_expression for level 2-12
|
||||
conditional_expression for level 13
|
||||
assignment_expression for level 14 and
|
||||
expression for the most general expression
|
||||
*/
|
||||
|
||||
binary_expression(int maxrank; struct expr **expp;)
|
||||
{int oper, OldResultKnown; struct expr *e1;}
|
||||
:
|
||||
unary(expp)
|
||||
[%while (rank_of(DOT) <= maxrank )
|
||||
/* '?', '=', and ',' are no binops
|
||||
*/
|
||||
binop(&oper)
|
||||
{ OldResultKnown = ResultKnown;
|
||||
if (oper == OR || oper == AND) {
|
||||
if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
|
||||
if (is_zero_cst(*expp)) {
|
||||
if (oper == AND) ResultKnown++;
|
||||
} else if (oper == OR) ResultKnown++;
|
||||
}
|
||||
}
|
||||
}
|
||||
binary_expression(rank_of(oper)-1, &e1)
|
||||
{
|
||||
ch3bin(expp, oper, e1);
|
||||
ResultKnown = OldResultKnown;
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
/* 3.3.15 */
|
||||
conditional_expression(struct expr **expp;)
|
||||
{struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;}
|
||||
:
|
||||
/* allow all binary operators */
|
||||
binary_expression(rank_of('?') - 1, expp)
|
||||
[ '?'
|
||||
{ OldResultKnown = ResultKnown;
|
||||
if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
|
||||
ConstExpr++;
|
||||
if (is_zero_cst(*expp)) ResultKnown++;
|
||||
}
|
||||
}
|
||||
expression(&e1)
|
||||
':'
|
||||
{ if (ConstExpr) {
|
||||
if (OldResultKnown == ResultKnown) ResultKnown++;
|
||||
else ResultKnown = OldResultKnown;
|
||||
}
|
||||
}
|
||||
conditional_expression(&e2)
|
||||
{
|
||||
ResultKnown = OldResultKnown;
|
||||
ch3bin(&e1, ':', e2);
|
||||
opnd2test(expp, '?');
|
||||
ch3bin(expp, '?', e1);
|
||||
}
|
||||
]?
|
||||
;
|
||||
|
||||
/* 3.3.16 */
|
||||
assignment_expression(struct expr **expp;)
|
||||
{ int oper;
|
||||
struct expr *e1 = 0;
|
||||
}
|
||||
:
|
||||
conditional_expression(expp)
|
||||
[
|
||||
asgnop(&oper)
|
||||
assignment_expression(&e1)
|
||||
{ch3asgn(expp, oper, e1);}
|
||||
|
|
||||
empty /* LLgen artefact ??? */
|
||||
]
|
||||
;
|
||||
|
||||
/* 3.3.17 */
|
||||
expression(struct expr **expp;)
|
||||
{struct expr *e1;}
|
||||
:
|
||||
assignment_expression(expp)
|
||||
[ ','
|
||||
assignment_expression(&e1)
|
||||
{
|
||||
ch3bin(expp, ',', e1);
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
unop(int *oper;) :
|
||||
['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN]
|
||||
{ if (DOT == '&') DOT = ADDRESSOF;
|
||||
*oper = DOT;
|
||||
}
|
||||
;
|
||||
|
||||
multop:
|
||||
'*' | '/' | '%'
|
||||
;
|
||||
|
||||
addop:
|
||||
'+' | '-'
|
||||
;
|
||||
|
||||
shiftop:
|
||||
LEFT | RIGHT
|
||||
;
|
||||
|
||||
relop:
|
||||
'<' | '>' | LESSEQ | GREATEREQ
|
||||
;
|
||||
|
||||
eqop:
|
||||
EQUAL | NOTEQUAL
|
||||
;
|
||||
|
||||
arithop:
|
||||
multop | addop | shiftop
|
||||
|
|
||||
'&' | '^' | '|'
|
||||
;
|
||||
|
||||
binop(int *oper;) :
|
||||
[ arithop | relop | eqop | AND | OR ]
|
||||
{*oper = DOT;}
|
||||
;
|
||||
|
||||
asgnop(register int *oper;):
|
||||
[ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB
|
||||
| LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ]
|
||||
{ *oper = DOT; }
|
||||
|
||||
;
|
||||
|
||||
constant(struct expr **expp;) :
|
||||
[
|
||||
INTEGER
|
||||
|
|
||||
FLOATING
|
||||
] {dot2expr(expp);}
|
||||
;
|
||||
|
||||
/* 3.4 */
|
||||
constant_expression (struct expr **expp;) :
|
||||
conditional_expression(expp)
|
||||
{ chk_cst_expr(expp); }
|
||||
;
|
||||
|
||||
identifier(struct idf **idfp;) :
|
||||
[ IDENTIFIER
|
||||
| TYPE_IDENTIFIER
|
||||
]
|
||||
{ *idfp = dot.tk_idf; }
|
||||
;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,227 +1,227 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* PROGRAM PARSER */
|
||||
|
||||
/* The presence of typedef declarations renders it impossible to
|
||||
make a context-free grammar of C. Consequently we need
|
||||
context-sensitive parsing techniques, the simplest one being
|
||||
a subtle cooperation between the parser and the lexical scanner.
|
||||
The lexical scanner has to know whether to return IDENTIFIER
|
||||
or TYPE_IDENTIFIER for a given tag, and it obtains this information
|
||||
from the definition list, as constructed by the parser.
|
||||
The present grammar is essentially LL(2), and is processed by
|
||||
a parser generator which accepts LL(1) with tie breaking rules
|
||||
in C, of the form %if(cond) and %while(cond). To solve the LL(1)
|
||||
ambiguities, the lexical scanner does a one symbol look-ahead.
|
||||
This symbol, however, cannot always be correctly assessed, since
|
||||
the present symbol may cause a change in the definition list
|
||||
which causes the identification of the look-ahead symbol to be
|
||||
invalidated.
|
||||
The lexical scanner relies on the parser (or its routines) to
|
||||
detect this situation and then update the look-ahead symbol.
|
||||
An alternative approach would be to reassess the look-ahead symbol
|
||||
in the lexical scanner when it is promoted to dot symbol. This
|
||||
would be more beautiful but less correct, since then for a short
|
||||
while there would be a discrepancy between the look-ahead symbol
|
||||
and the definition list; I think it would nevertheless work in
|
||||
correct programs.
|
||||
A third solution would be to enter the identifier as soon as it
|
||||
is found; its storage class is then known, although its full type
|
||||
isn't. We would have to fill that in afterwards.
|
||||
|
||||
At block exit the situation is even worse. Upon reading the
|
||||
closing brace, the names declared inside the function are cleared
|
||||
from the name list. This action may expose a type identifier that
|
||||
is the same as the identifier in the look-ahead symbol. This
|
||||
situation certainly invalidates the third solution, and casts
|
||||
doubts upon the second.
|
||||
*/
|
||||
|
||||
%lexical LLlex;
|
||||
%start C_program, program;
|
||||
%start If_expr, control_if_expression;
|
||||
|
||||
{
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "label.h"
|
||||
#include "type.h"
|
||||
#include "declar.h"
|
||||
#include "decspecs.h"
|
||||
#include "code.h"
|
||||
#include "expr.h"
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "declarator.h"
|
||||
#include "stack.h"
|
||||
#include "proto.h"
|
||||
#include "error.h"
|
||||
#ifdef LINT
|
||||
#include "l_lint.h"
|
||||
#endif /* LINT */
|
||||
|
||||
}
|
||||
|
||||
control_if_expression
|
||||
{
|
||||
struct expr *exprX;
|
||||
}
|
||||
:
|
||||
constant_expression(&exprX)
|
||||
{
|
||||
}
|
||||
;
|
||||
|
||||
/* 3.7 */
|
||||
program:
|
||||
[%persistent external_definition]*
|
||||
{ unstack_world(); }
|
||||
;
|
||||
|
||||
/* A C identifier definition is remarkable in that it formulates
|
||||
the declaration in a way different from most other languages:
|
||||
e.g., rather than defining x as a pointer-to-integer, it defines
|
||||
*x as an integer and lets the compiler deduce that x is actually
|
||||
pointer-to-integer. This has profound consequences, both for the
|
||||
structure of an identifier definition and for the compiler.
|
||||
|
||||
A definition starts with a decl_specifiers, which contains things
|
||||
like
|
||||
typedef int
|
||||
which is implicitly repeated for every definition in the list, and
|
||||
then for each identifier a declarator is given, of the form
|
||||
*a()
|
||||
or so. The decl_specifiers is kept in a struct decspecs, to be
|
||||
used again and again, while the declarator is stored in a struct
|
||||
declarator, only to be passed to declare_idf together with the
|
||||
struct decspecs.
|
||||
|
||||
With the introduction of prototypes, extra problems for the scope
|
||||
administration were introduced as well. We can have, for example,
|
||||
int x(double x);
|
||||
and
|
||||
int x(double x) { ... use(x) ... }
|
||||
In the first case, the parameter name can be forgotten, whereas in
|
||||
the second case, the parameter should have a block scope. The
|
||||
problem lies in the fact that the parameter's type is known before
|
||||
the type of the function, which causes the def structure to be on
|
||||
the end of the list. Our solution is as follows:
|
||||
1- In case of a declaration, throw the parameter identifier away
|
||||
before the declaration of the outer x.
|
||||
2- In case of a definition, the function begin_proc() changes the
|
||||
def list for the identifier. This means that declare_idf()
|
||||
contains an extra test in case we already saw a declaration of
|
||||
such a function, because this function is called before
|
||||
begin_proc().
|
||||
*/
|
||||
|
||||
external_definition
|
||||
{ struct decspecs Ds;
|
||||
struct declarator Dc;
|
||||
}
|
||||
:
|
||||
{ Ds = null_decspecs;
|
||||
Dc = null_declarator;
|
||||
}
|
||||
[ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
|
||||
decl_specifiers(&Ds)
|
||||
|
|
||||
{do_decspecs(&Ds);}
|
||||
]
|
||||
[
|
||||
declarator(&Dc)
|
||||
{
|
||||
declare_idf(&Ds, &Dc, level);
|
||||
#ifdef LINT
|
||||
lint_ext_def(Dc.dc_idf, Ds.ds_sc);
|
||||
#endif /* LINT */
|
||||
}
|
||||
[
|
||||
function(&Ds, &Dc)
|
||||
|
|
||||
{ if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
|
||||
Ds.ds_notypegiven) {
|
||||
strict("declaration specifiers missing");
|
||||
}
|
||||
}
|
||||
non_function(&Ds, &Dc)
|
||||
]
|
||||
|
|
||||
{ if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
|
||||
Ds.ds_notypegiven) {
|
||||
strict("declaration missing");
|
||||
}
|
||||
}
|
||||
';'
|
||||
]
|
||||
{remove_declarator(&Dc); flush_strings(); }
|
||||
;
|
||||
|
||||
non_function(register struct decspecs *ds; register struct declarator *dc;)
|
||||
:
|
||||
{ reject_params(dc);
|
||||
}
|
||||
[
|
||||
initializer(dc->dc_idf, ds->ds_sc)
|
||||
|
|
||||
{ code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
|
||||
]
|
||||
{
|
||||
#ifdef LINT
|
||||
lint_non_function_decl(ds, dc);
|
||||
#endif /* LINT */
|
||||
}
|
||||
[
|
||||
','
|
||||
init_declarator(ds)
|
||||
]*
|
||||
';'
|
||||
;
|
||||
|
||||
/* 3.7.1 */
|
||||
function(struct decspecs *ds; struct declarator *dc;)
|
||||
{
|
||||
arith fbytes;
|
||||
register struct idf *idf = dc->dc_idf;
|
||||
}
|
||||
:
|
||||
{
|
||||
#ifdef LINT
|
||||
lint_start_function();
|
||||
#endif /* LINT */
|
||||
idf_initialized(idf);
|
||||
stack_level(); /* L_FORMAL1 declarations */
|
||||
declare_params(dc);
|
||||
begin_proc(ds, idf); /* sets global function info */
|
||||
stack_level(); /* L_FORMAL2 declarations */
|
||||
declare_protos(dc);
|
||||
}
|
||||
declaration*
|
||||
{
|
||||
check_formals(idf, dc); /* check style-mixtures */
|
||||
declare_formals(idf, &fbytes);
|
||||
#ifdef LINT
|
||||
lint_formals();
|
||||
#endif /* LINT */
|
||||
}
|
||||
compound_statement
|
||||
{
|
||||
end_proc(fbytes);
|
||||
#ifdef LINT
|
||||
lint_implicit_return();
|
||||
#endif /* LINT */
|
||||
unstack_level(); /* L_FORMAL2 declarations */
|
||||
#ifdef LINT
|
||||
lint_end_formals();
|
||||
#endif /* LINT */
|
||||
unstack_level(); /* L_FORMAL1 declarations */
|
||||
#ifdef LINT
|
||||
lint_end_function();
|
||||
#endif /* LINT */
|
||||
}
|
||||
;
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* PROGRAM PARSER */
|
||||
|
||||
/* The presence of typedef declarations renders it impossible to
|
||||
make a context-free grammar of C. Consequently we need
|
||||
context-sensitive parsing techniques, the simplest one being
|
||||
a subtle cooperation between the parser and the lexical scanner.
|
||||
The lexical scanner has to know whether to return IDENTIFIER
|
||||
or TYPE_IDENTIFIER for a given tag, and it obtains this information
|
||||
from the definition list, as constructed by the parser.
|
||||
The present grammar is essentially LL(2), and is processed by
|
||||
a parser generator which accepts LL(1) with tie breaking rules
|
||||
in C, of the form %if(cond) and %while(cond). To solve the LL(1)
|
||||
ambiguities, the lexical scanner does a one symbol look-ahead.
|
||||
This symbol, however, cannot always be correctly assessed, since
|
||||
the present symbol may cause a change in the definition list
|
||||
which causes the identification of the look-ahead symbol to be
|
||||
invalidated.
|
||||
The lexical scanner relies on the parser (or its routines) to
|
||||
detect this situation and then update the look-ahead symbol.
|
||||
An alternative approach would be to reassess the look-ahead symbol
|
||||
in the lexical scanner when it is promoted to dot symbol. This
|
||||
would be more beautiful but less correct, since then for a short
|
||||
while there would be a discrepancy between the look-ahead symbol
|
||||
and the definition list; I think it would nevertheless work in
|
||||
correct programs.
|
||||
A third solution would be to enter the identifier as soon as it
|
||||
is found; its storage class is then known, although its full type
|
||||
isn't. We would have to fill that in afterwards.
|
||||
|
||||
At block exit the situation is even worse. Upon reading the
|
||||
closing brace, the names declared inside the function are cleared
|
||||
from the name list. This action may expose a type identifier that
|
||||
is the same as the identifier in the look-ahead symbol. This
|
||||
situation certainly invalidates the third solution, and casts
|
||||
doubts upon the second.
|
||||
*/
|
||||
|
||||
%lexical LLlex;
|
||||
%start C_program, program;
|
||||
%start If_expr, control_if_expression;
|
||||
|
||||
{
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "label.h"
|
||||
#include "type.h"
|
||||
#include "declar.h"
|
||||
#include "decspecs.h"
|
||||
#include "code.h"
|
||||
#include "expr.h"
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "declarator.h"
|
||||
#include "stack.h"
|
||||
#include "proto.h"
|
||||
#include "error.h"
|
||||
#ifdef LINT
|
||||
#include "l_lint.h"
|
||||
#endif /* LINT */
|
||||
|
||||
}
|
||||
|
||||
control_if_expression
|
||||
{
|
||||
struct expr *exprX;
|
||||
}
|
||||
:
|
||||
constant_expression(&exprX)
|
||||
{
|
||||
}
|
||||
;
|
||||
|
||||
/* 3.7 */
|
||||
program:
|
||||
[%persistent external_definition]*
|
||||
{ unstack_world(); }
|
||||
;
|
||||
|
||||
/* A C identifier definition is remarkable in that it formulates
|
||||
the declaration in a way different from most other languages:
|
||||
e.g., rather than defining x as a pointer-to-integer, it defines
|
||||
*x as an integer and lets the compiler deduce that x is actually
|
||||
pointer-to-integer. This has profound consequences, both for the
|
||||
structure of an identifier definition and for the compiler.
|
||||
|
||||
A definition starts with a decl_specifiers, which contains things
|
||||
like
|
||||
typedef int
|
||||
which is implicitly repeated for every definition in the list, and
|
||||
then for each identifier a declarator is given, of the form
|
||||
*a()
|
||||
or so. The decl_specifiers is kept in a struct decspecs, to be
|
||||
used again and again, while the declarator is stored in a struct
|
||||
declarator, only to be passed to declare_idf together with the
|
||||
struct decspecs.
|
||||
|
||||
With the introduction of prototypes, extra problems for the scope
|
||||
administration were introduced as well. We can have, for example,
|
||||
int x(double x);
|
||||
and
|
||||
int x(double x) { ... use(x) ... }
|
||||
In the first case, the parameter name can be forgotten, whereas in
|
||||
the second case, the parameter should have a block scope. The
|
||||
problem lies in the fact that the parameter's type is known before
|
||||
the type of the function, which causes the def structure to be on
|
||||
the end of the list. Our solution is as follows:
|
||||
1- In case of a declaration, throw the parameter identifier away
|
||||
before the declaration of the outer x.
|
||||
2- In case of a definition, the function begin_proc() changes the
|
||||
def list for the identifier. This means that declare_idf()
|
||||
contains an extra test in case we already saw a declaration of
|
||||
such a function, because this function is called before
|
||||
begin_proc().
|
||||
*/
|
||||
|
||||
external_definition
|
||||
{ struct decspecs Ds;
|
||||
struct declarator Dc;
|
||||
}
|
||||
:
|
||||
{ Ds = null_decspecs;
|
||||
Dc = null_declarator;
|
||||
}
|
||||
[ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
|
||||
decl_specifiers(&Ds)
|
||||
|
|
||||
{do_decspecs(&Ds);}
|
||||
]
|
||||
[
|
||||
declarator(&Dc)
|
||||
{
|
||||
declare_idf(&Ds, &Dc, level);
|
||||
#ifdef LINT
|
||||
lint_ext_def(Dc.dc_idf, Ds.ds_sc);
|
||||
#endif /* LINT */
|
||||
}
|
||||
[
|
||||
function(&Ds, &Dc)
|
||||
|
|
||||
{ if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
|
||||
Ds.ds_notypegiven) {
|
||||
strict("declaration specifiers missing");
|
||||
}
|
||||
}
|
||||
non_function(&Ds, &Dc)
|
||||
]
|
||||
|
|
||||
{ if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
|
||||
Ds.ds_notypegiven) {
|
||||
strict("declaration missing");
|
||||
}
|
||||
}
|
||||
';'
|
||||
]
|
||||
{remove_declarator(&Dc); flush_strings(); }
|
||||
;
|
||||
|
||||
non_function(register struct decspecs *ds; register struct declarator *dc;)
|
||||
:
|
||||
{ reject_params(dc);
|
||||
}
|
||||
[
|
||||
initializer(dc->dc_idf, ds->ds_sc)
|
||||
|
|
||||
{ code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
|
||||
]
|
||||
{
|
||||
#ifdef LINT
|
||||
lint_non_function_decl(ds, dc);
|
||||
#endif /* LINT */
|
||||
}
|
||||
[
|
||||
','
|
||||
init_declarator(ds)
|
||||
]*
|
||||
';'
|
||||
;
|
||||
|
||||
/* 3.7.1 */
|
||||
function(struct decspecs *ds; struct declarator *dc;)
|
||||
{
|
||||
arith fbytes;
|
||||
register struct idf *idf = dc->dc_idf;
|
||||
}
|
||||
:
|
||||
{
|
||||
#ifdef LINT
|
||||
lint_start_function();
|
||||
#endif /* LINT */
|
||||
idf_initialized(idf);
|
||||
stack_level(); /* L_FORMAL1 declarations */
|
||||
declare_params(dc);
|
||||
begin_proc(ds, idf); /* sets global function info */
|
||||
stack_level(); /* L_FORMAL2 declarations */
|
||||
declare_protos(dc);
|
||||
}
|
||||
declaration*
|
||||
{
|
||||
check_formals(idf, dc); /* check style-mixtures */
|
||||
declare_formals(idf, &fbytes);
|
||||
#ifdef LINT
|
||||
lint_formals();
|
||||
#endif /* LINT */
|
||||
}
|
||||
compound_statement
|
||||
{
|
||||
end_proc(fbytes);
|
||||
#ifdef LINT
|
||||
lint_implicit_return();
|
||||
#endif /* LINT */
|
||||
unstack_level(); /* L_FORMAL2 declarations */
|
||||
#ifdef LINT
|
||||
lint_end_formals();
|
||||
#endif /* LINT */
|
||||
unstack_level(); /* L_FORMAL1 declarations */
|
||||
#ifdef LINT
|
||||
lint_end_function();
|
||||
#endif /* LINT */
|
||||
}
|
||||
;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,16 +1,16 @@
|
|||
default:
|
||||
if (tok <= 0) return "end of file";
|
||||
if (tok < 040 || tok >= 0177) {
|
||||
return "bad token";
|
||||
}
|
||||
/* fall through */
|
||||
case '\n':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\r':
|
||||
case '\t':
|
||||
index = (index+2) & (SIZBUF-1);
|
||||
buf[index] = tok;
|
||||
return &buf[index];
|
||||
}
|
||||
default:
|
||||
if (tok <= 0) return "end of file";
|
||||
if (tok < 040 || tok >= 0177) {
|
||||
return "bad token";
|
||||
}
|
||||
/* fall through */
|
||||
case '\n':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\r':
|
||||
case '\t':
|
||||
index = (index+2) & (SIZBUF-1);
|
||||
buf[index] = tok;
|
||||
return &buf[index];
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
/* Generated by make.tokcase */
|
||||
/* $Id$ */
|
||||
#include "Lpars.h"
|
||||
|
||||
char *symbol2str(int tok)
|
||||
{
|
||||
#define SIZBUF 8
|
||||
/* allow for a few invocations in f.i. an argument list */
|
||||
static char buf[SIZBUF];
|
||||
static int index;
|
||||
|
||||
switch (tok) {
|
||||
/* Generated by make.tokcase */
|
||||
/* $Id$ */
|
||||
#include "Lpars.h"
|
||||
|
||||
char *symbol2str(int tok)
|
||||
{
|
||||
#define SIZBUF 8
|
||||
/* allow for a few invocations in f.i. an argument list */
|
||||
static char buf[SIZBUF];
|
||||
static int index;
|
||||
|
||||
switch (tok) {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
L_ACK_MODULES_ALLOC = {
|
||||
$PWD/Malloc.c,
|
||||
$PWD/Salloc.c,
|
||||
$PWD/Srealloc.c,
|
||||
$PWD/Realloc.c,
|
||||
$PWD/botch.c,
|
||||
$PWD/clear.c,
|
||||
$PWD/st_alloc.c,
|
||||
$PWD/std_alloc.c,
|
||||
$PWD/No_Mem.c,
|
||||
$PWD/alloc.h
|
||||
};
|
||||
|
||||
L_ACK_MODULES_ALLOC = {
|
||||
$PWD/Malloc.c,
|
||||
$PWD/Salloc.c,
|
||||
$PWD/Srealloc.c,
|
||||
$PWD/Realloc.c,
|
||||
$PWD/botch.c,
|
||||
$PWD/clear.c,
|
||||
$PWD/st_alloc.c,
|
||||
$PWD/std_alloc.c,
|
||||
$PWD/No_Mem.c,
|
||||
$PWD/alloc.h
|
||||
};
|
||||
|
||||
|
|
|
@ -1,80 +1,80 @@
|
|||
.TH ALLOC 3 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
Malloc, Salloc, Realloc, Srealloc, st_alloc, st_free\ \-\ low level memory allocation routines
|
||||
.SH SYNOPSIS
|
||||
.B #include <alloc.h>
|
||||
.PP
|
||||
.B char *Malloc(unsigned int size)
|
||||
.PP
|
||||
.B char *Salloc(char *str, unsigned int size)
|
||||
.PP
|
||||
.B char *Realloc(char *buf, unsigned int size)
|
||||
.PP
|
||||
.B char *Srealloc(char *str, unsigned int size)
|
||||
.PP
|
||||
.B char *st_alloc(char **phead, unsigned int size, int count)
|
||||
.PP
|
||||
.B st_free(char *ptr, char **phead, unsigned int size)
|
||||
.PP
|
||||
.B void clear(char *ptr, unsigned int size)
|
||||
.PP
|
||||
.void No_Mem()
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
This set of routines provides a checking memory allocation mechanism.
|
||||
.PP
|
||||
\fIMalloc\fR returns a pointer to a block of at least \fIsize\fR
|
||||
bytes, beginning on a boundary suitable for any data type.
|
||||
.PP
|
||||
\fISalloc\fR returns a pointer to a block of at least \fIsize\fR
|
||||
bytes, initialized with the null-terminated string \fIstr\fR.
|
||||
.PP
|
||||
\fIRealloc\fR changes the size of
|
||||
the block at \fIbuf\fR to \fIsize\fR bytes, and returns a pointer to the
|
||||
(possibly moved) block. If \fIbuf\fP is a null pointer, \fIRealloc\fP
|
||||
behaves as \fIMalloc\fP.
|
||||
.PP
|
||||
\fISrealloc\fR reallocates
|
||||
the string at \fIstr\fR to \fIsize\fR bytes.
|
||||
It actually does the same as \fIRealloc\fP, and exists only for
|
||||
backwards compatibility.
|
||||
.PP
|
||||
All these routines use \fImalloc\fR and \fIrealloc\fR.
|
||||
The routine \fIfree\fR can be used on pointers returned by these routines.
|
||||
.PP
|
||||
\fISt_alloc\fR and \fIst_free\fR provide a mechanism for maintaining free lists
|
||||
of structures.
|
||||
\fISt_alloc\fR takes three parameters: \fIphead\fR is a pointer to a field
|
||||
containing the head of the free list, \fIsize\fR contains the size of the
|
||||
structures, and \fIcount\fR indicates how many new structures must be allocated
|
||||
in case the free list is exhausted.
|
||||
It returns a pointer to a zero-initialized structure.
|
||||
\fISt_free\fR also takes three parameters: \fIptr\fR is a pointer to
|
||||
the structure to be freed, \fIphead\fR is again a pointer to a field
|
||||
containing the head of the free list, and \fIsize\fR again contains the size
|
||||
of the structures.
|
||||
These last two routines are best used in a macro.
|
||||
.PP
|
||||
\fIclear\fR clears \fIsize\fR bytes, starting at \fIptr\fR.
|
||||
.SH FILES
|
||||
.nf
|
||||
~em/modules/h/alloc.h
|
||||
~em/modules/lib/liballoc.a
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
malloc(3)
|
||||
.SH DIAGNOSTICS
|
||||
\fIMalloc\fR, \fISalloc\fR, \fIRealloc\fP, \fISrealloc\fR, and \fIst_alloc\fR
|
||||
call a routine \fINo_Mem\fR if there is no memory available. This routine
|
||||
is not supposed to return. A default one, that
|
||||
gives an error message and stops execution, is provided.
|
||||
.SH BUGS
|
||||
The
|
||||
.I st_alloc
|
||||
mechanism only works for structures that are large enough to contain one
|
||||
pointer.
|
||||
Also,
|
||||
.I st_free
|
||||
actually is a macro, and references its arguments more than once, so they
|
||||
better not have side-effects.
|
||||
.TH ALLOC 3 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
Malloc, Salloc, Realloc, Srealloc, st_alloc, st_free\ \-\ low level memory allocation routines
|
||||
.SH SYNOPSIS
|
||||
.B #include <alloc.h>
|
||||
.PP
|
||||
.B char *Malloc(unsigned int size)
|
||||
.PP
|
||||
.B char *Salloc(char *str, unsigned int size)
|
||||
.PP
|
||||
.B char *Realloc(char *buf, unsigned int size)
|
||||
.PP
|
||||
.B char *Srealloc(char *str, unsigned int size)
|
||||
.PP
|
||||
.B char *st_alloc(char **phead, unsigned int size, int count)
|
||||
.PP
|
||||
.B st_free(char *ptr, char **phead, unsigned int size)
|
||||
.PP
|
||||
.B void clear(char *ptr, unsigned int size)
|
||||
.PP
|
||||
.void No_Mem()
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
This set of routines provides a checking memory allocation mechanism.
|
||||
.PP
|
||||
\fIMalloc\fR returns a pointer to a block of at least \fIsize\fR
|
||||
bytes, beginning on a boundary suitable for any data type.
|
||||
.PP
|
||||
\fISalloc\fR returns a pointer to a block of at least \fIsize\fR
|
||||
bytes, initialized with the null-terminated string \fIstr\fR.
|
||||
.PP
|
||||
\fIRealloc\fR changes the size of
|
||||
the block at \fIbuf\fR to \fIsize\fR bytes, and returns a pointer to the
|
||||
(possibly moved) block. If \fIbuf\fP is a null pointer, \fIRealloc\fP
|
||||
behaves as \fIMalloc\fP.
|
||||
.PP
|
||||
\fISrealloc\fR reallocates
|
||||
the string at \fIstr\fR to \fIsize\fR bytes.
|
||||
It actually does the same as \fIRealloc\fP, and exists only for
|
||||
backwards compatibility.
|
||||
.PP
|
||||
All these routines use \fImalloc\fR and \fIrealloc\fR.
|
||||
The routine \fIfree\fR can be used on pointers returned by these routines.
|
||||
.PP
|
||||
\fISt_alloc\fR and \fIst_free\fR provide a mechanism for maintaining free lists
|
||||
of structures.
|
||||
\fISt_alloc\fR takes three parameters: \fIphead\fR is a pointer to a field
|
||||
containing the head of the free list, \fIsize\fR contains the size of the
|
||||
structures, and \fIcount\fR indicates how many new structures must be allocated
|
||||
in case the free list is exhausted.
|
||||
It returns a pointer to a zero-initialized structure.
|
||||
\fISt_free\fR also takes three parameters: \fIptr\fR is a pointer to
|
||||
the structure to be freed, \fIphead\fR is again a pointer to a field
|
||||
containing the head of the free list, and \fIsize\fR again contains the size
|
||||
of the structures.
|
||||
These last two routines are best used in a macro.
|
||||
.PP
|
||||
\fIclear\fR clears \fIsize\fR bytes, starting at \fIptr\fR.
|
||||
.SH FILES
|
||||
.nf
|
||||
~em/modules/h/alloc.h
|
||||
~em/modules/lib/liballoc.a
|
||||
.fi
|
||||
.SH "SEE ALSO"
|
||||
malloc(3)
|
||||
.SH DIAGNOSTICS
|
||||
\fIMalloc\fR, \fISalloc\fR, \fIRealloc\fP, \fISrealloc\fR, and \fIst_alloc\fR
|
||||
call a routine \fINo_Mem\fR if there is no memory available. This routine
|
||||
is not supposed to return. A default one, that
|
||||
gives an error message and stops execution, is provided.
|
||||
.SH BUGS
|
||||
The
|
||||
.I st_alloc
|
||||
mechanism only works for structures that are large enough to contain one
|
||||
pointer.
|
||||
Also,
|
||||
.I st_free
|
||||
actually is a macro, and references its arguments more than once, so they
|
||||
better not have side-effects.
|
||||
|
|
|
@ -1,116 +1,116 @@
|
|||
#
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
bdos: ! BDOS entry point
|
||||
out 0xff
|
||||
ora a
|
||||
ret
|
||||
|
||||
COLDSTART: ! system startup entry point --- this needs to be four bytes after FBASE.
|
||||
jmp boot ! 0: Cold start routine
|
||||
bios:
|
||||
jmp wboot ! 1: Warm boot - reload command processor
|
||||
jmp const ! 2: Console status
|
||||
jmp conin ! 3: Console input
|
||||
jmp conout ! 4: Console output
|
||||
jmp list ! 5: Printer output
|
||||
jmp punch ! 6: Paper tape punch output
|
||||
jmp reader ! 7: Paper tape reader input
|
||||
jmp home ! 8: Move disc head to track 0
|
||||
jmp seldsk ! 9: Select disc drive
|
||||
jmp settrk !10: Set track number
|
||||
jmp setsec !11: Set sector number
|
||||
jmp setdma !12: Set DMA address
|
||||
jmp read !13: Read a sector
|
||||
jmp write !14: Write a sector
|
||||
|
||||
boot:
|
||||
xra a
|
||||
sta 3 ! iobyte
|
||||
sta 4 ! drive
|
||||
! falls through
|
||||
wboot:
|
||||
mvi a, 0xc3 ! jmp
|
||||
sta 0
|
||||
sta 5
|
||||
|
||||
lxi h, bios
|
||||
shld 1
|
||||
|
||||
lxi h, bdos
|
||||
shld 6
|
||||
|
||||
lda 4 ! get the current drive/user
|
||||
mov c, a
|
||||
out 1
|
||||
|
||||
const:
|
||||
out 2
|
||||
ora a
|
||||
ret
|
||||
|
||||
conin:
|
||||
out 3
|
||||
ora a
|
||||
ret
|
||||
|
||||
conout:
|
||||
out 4
|
||||
ora a
|
||||
ret
|
||||
|
||||
list:
|
||||
out 5
|
||||
ora a
|
||||
ret
|
||||
|
||||
punch:
|
||||
out 6
|
||||
ora a
|
||||
ret
|
||||
|
||||
reader:
|
||||
out 7
|
||||
ora a
|
||||
ret
|
||||
|
||||
home:
|
||||
out 8
|
||||
ora a
|
||||
ret
|
||||
|
||||
seldsk:
|
||||
out 9
|
||||
ora a
|
||||
ret
|
||||
|
||||
settrk:
|
||||
out 10
|
||||
ora a
|
||||
ret
|
||||
|
||||
setsec:
|
||||
out 11
|
||||
ora a
|
||||
ret
|
||||
|
||||
setdma:
|
||||
out 12
|
||||
ora a
|
||||
ret
|
||||
|
||||
read:
|
||||
out 13
|
||||
ora a
|
||||
ret
|
||||
|
||||
write:
|
||||
out 14
|
||||
ora a
|
||||
ret
|
||||
|
||||
#
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
bdos: ! BDOS entry point
|
||||
out 0xff
|
||||
ora a
|
||||
ret
|
||||
|
||||
COLDSTART: ! system startup entry point --- this needs to be four bytes after FBASE.
|
||||
jmp boot ! 0: Cold start routine
|
||||
bios:
|
||||
jmp wboot ! 1: Warm boot - reload command processor
|
||||
jmp const ! 2: Console status
|
||||
jmp conin ! 3: Console input
|
||||
jmp conout ! 4: Console output
|
||||
jmp list ! 5: Printer output
|
||||
jmp punch ! 6: Paper tape punch output
|
||||
jmp reader ! 7: Paper tape reader input
|
||||
jmp home ! 8: Move disc head to track 0
|
||||
jmp seldsk ! 9: Select disc drive
|
||||
jmp settrk !10: Set track number
|
||||
jmp setsec !11: Set sector number
|
||||
jmp setdma !12: Set DMA address
|
||||
jmp read !13: Read a sector
|
||||
jmp write !14: Write a sector
|
||||
|
||||
boot:
|
||||
xra a
|
||||
sta 3 ! iobyte
|
||||
sta 4 ! drive
|
||||
! falls through
|
||||
wboot:
|
||||
mvi a, 0xc3 ! jmp
|
||||
sta 0
|
||||
sta 5
|
||||
|
||||
lxi h, bios
|
||||
shld 1
|
||||
|
||||
lxi h, bdos
|
||||
shld 6
|
||||
|
||||
lda 4 ! get the current drive/user
|
||||
mov c, a
|
||||
out 1
|
||||
|
||||
const:
|
||||
out 2
|
||||
ora a
|
||||
ret
|
||||
|
||||
conin:
|
||||
out 3
|
||||
ora a
|
||||
ret
|
||||
|
||||
conout:
|
||||
out 4
|
||||
ora a
|
||||
ret
|
||||
|
||||
list:
|
||||
out 5
|
||||
ora a
|
||||
ret
|
||||
|
||||
punch:
|
||||
out 6
|
||||
ora a
|
||||
ret
|
||||
|
||||
reader:
|
||||
out 7
|
||||
ora a
|
||||
ret
|
||||
|
||||
home:
|
||||
out 8
|
||||
ora a
|
||||
ret
|
||||
|
||||
seldsk:
|
||||
out 9
|
||||
ora a
|
||||
ret
|
||||
|
||||
settrk:
|
||||
out 10
|
||||
ora a
|
||||
ret
|
||||
|
||||
setsec:
|
||||
out 11
|
||||
ora a
|
||||
ret
|
||||
|
||||
setdma:
|
||||
out 12
|
||||
ora a
|
||||
ret
|
||||
|
||||
read:
|
||||
out 13
|
||||
ora a
|
||||
ret
|
||||
|
||||
write:
|
||||
out 14
|
||||
ora a
|
||||
ret
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,15 +1,15 @@
|
|||
#ifndef SIM__HEADER
|
||||
#define SIM__HEADER
|
||||
|
||||
unsigned int cpu_read_byte(unsigned int address);
|
||||
unsigned int cpu_read_word(unsigned int address);
|
||||
unsigned int cpu_read_long(unsigned int address);
|
||||
void cpu_write_byte(unsigned int address, unsigned int value);
|
||||
void cpu_write_word(unsigned int address, unsigned int value);
|
||||
void cpu_write_long(unsigned int address, unsigned int value);
|
||||
void cpu_pulse_reset(void);
|
||||
void cpu_set_fc(unsigned int fc);
|
||||
int cpu_irq_ack(int level);
|
||||
void cpu_instr_callback(int pc);
|
||||
|
||||
#endif /* SIM__HEADER */
|
||||
#ifndef SIM__HEADER
|
||||
#define SIM__HEADER
|
||||
|
||||
unsigned int cpu_read_byte(unsigned int address);
|
||||
unsigned int cpu_read_word(unsigned int address);
|
||||
unsigned int cpu_read_long(unsigned int address);
|
||||
void cpu_write_byte(unsigned int address, unsigned int value);
|
||||
void cpu_write_word(unsigned int address, unsigned int value);
|
||||
void cpu_write_long(unsigned int address, unsigned int value);
|
||||
void cpu_pulse_reset(void);
|
||||
void cpu_set_fc(unsigned int fc);
|
||||
int cpu_irq_ack(int level);
|
||||
void cpu_instr_callback(int pc);
|
||||
|
||||
#endif /* SIM__HEADER */
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
Following is a repost of the public domain 'make' that I posted
|
||||
to net.sources a couple of months ago. I have fixed a few bugs, and
|
||||
added some more features, and the resulting changes amounted to
|
||||
about as much text as the whole program (hence the repost).
|
||||
|
||||
For those that missed the net.sources posting, this is a public domain
|
||||
re-implementation of the UNIX make program. There is no manual included;
|
||||
for documentation, refer to a UNIX manual, or the source.
|
||||
|
||||
Here is a list of the changes made:
|
||||
|
||||
i) If '-' (ignore) or '@' (silent) where used at the start
|
||||
of a command, their effect was not turned off for the following
|
||||
commands.
|
||||
ii) A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o),
|
||||
if first in the file would be taken as the default target.
|
||||
This resulted in error messages like "Don't know how to
|
||||
make .c", because things like .SUFFIXES were being made.
|
||||
This was further complicated by ---
|
||||
iii) Special target lines with no dependents (ie. .SUFFIXES:\n)
|
||||
were not clearing out the existing dependents like
|
||||
they should.
|
||||
iv) Default rules could not be redefined because of the error
|
||||
checking for commands being defined twice. Now you are
|
||||
allowed to define a target beinging with '.', having
|
||||
no dependents with commands.
|
||||
v) The -q option didn't do the time comparison correctly,
|
||||
or clear the variable used to keep track of this. Thus
|
||||
it didn't work very well.
|
||||
vi) The syntax ${..} for macro's supported by UNIX make was
|
||||
not supported.
|
||||
vii) There wuz a couple of spelling errors.
|
||||
viii) When make checked for implicit rules on targets without
|
||||
a suffix, there were problems. (Note: The ~ feature of
|
||||
UNIX make wasn't and still isn't supported)
|
||||
ix) The -n option did not print @ lines like it was supposed to.
|
||||
x) :: added. (See UNIX manual)
|
||||
xi) $? added. (see UNIX manual)
|
||||
|
||||
Hacked further by Ceriel Jacobs to make it work better. Use this "make" to
|
||||
install ACK under Microsoft Xenix V3.2. Some of the makefiles are just too
|
||||
big for the Xenix "make". Strange, they work on a PDP-11 ...
|
||||
|
||||
Made it almost ISO C90 and POSIX portable by Carl Eric Codere, and
|
||||
also made it safer by using correct datatypes on some library calls.
|
||||
Following is a repost of the public domain 'make' that I posted
|
||||
to net.sources a couple of months ago. I have fixed a few bugs, and
|
||||
added some more features, and the resulting changes amounted to
|
||||
about as much text as the whole program (hence the repost).
|
||||
|
||||
For those that missed the net.sources posting, this is a public domain
|
||||
re-implementation of the UNIX make program. There is no manual included;
|
||||
for documentation, refer to a UNIX manual, or the source.
|
||||
|
||||
Here is a list of the changes made:
|
||||
|
||||
i) If '-' (ignore) or '@' (silent) where used at the start
|
||||
of a command, their effect was not turned off for the following
|
||||
commands.
|
||||
ii) A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o),
|
||||
if first in the file would be taken as the default target.
|
||||
This resulted in error messages like "Don't know how to
|
||||
make .c", because things like .SUFFIXES were being made.
|
||||
This was further complicated by ---
|
||||
iii) Special target lines with no dependents (ie. .SUFFIXES:\n)
|
||||
were not clearing out the existing dependents like
|
||||
they should.
|
||||
iv) Default rules could not be redefined because of the error
|
||||
checking for commands being defined twice. Now you are
|
||||
allowed to define a target beinging with '.', having
|
||||
no dependents with commands.
|
||||
v) The -q option didn't do the time comparison correctly,
|
||||
or clear the variable used to keep track of this. Thus
|
||||
it didn't work very well.
|
||||
vi) The syntax ${..} for macro's supported by UNIX make was
|
||||
not supported.
|
||||
vii) There wuz a couple of spelling errors.
|
||||
viii) When make checked for implicit rules on targets without
|
||||
a suffix, there were problems. (Note: The ~ feature of
|
||||
UNIX make wasn't and still isn't supported)
|
||||
ix) The -n option did not print @ lines like it was supposed to.
|
||||
x) :: added. (See UNIX manual)
|
||||
xi) $? added. (see UNIX manual)
|
||||
|
||||
Hacked further by Ceriel Jacobs to make it work better. Use this "make" to
|
||||
install ACK under Microsoft Xenix V3.2. Some of the makefiles are just too
|
||||
big for the Xenix "make". Strange, they work on a PDP-11 ...
|
||||
|
||||
Made it almost ISO C90 and POSIX portable by Carl Eric Codere, and
|
||||
also made it safer by using correct datatypes on some library calls.
|
||||
|
|
|
@ -1,349 +1,349 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* t o p g e n . g
|
||||
*
|
||||
* Grammar of optimizer description, and some code generation
|
||||
*/
|
||||
|
||||
%token LETTER, DIGIT, OTHER, SPACE;
|
||||
%token LINE_TERMINATOR, OPERAND_SEPARATOR, INSTRUCTION_SEPARATOR,
|
||||
PATTERN_SEPARATOR, OPEN_BRACKET, CLOSE_BRACKET;
|
||||
%lexical LLlex;
|
||||
%start LLparse, optim_description;
|
||||
|
||||
{
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "token.h"
|
||||
#include "symtab.h"
|
||||
#include "misc.h"
|
||||
#include "hash.h"
|
||||
#include "pattern.h"
|
||||
|
||||
char idbuf[BUFSIZ], buf[BUFSIZ];
|
||||
int countid; /* # of variables */
|
||||
int countpat; /* # of patterns */
|
||||
static int patlen; /* Maximum number of instructions in pattern */
|
||||
static int maxoperand; /* Maximum number of operands of instruction */
|
||||
extern FILE *input; /* file descriptor of inputfile */
|
||||
|
||||
|
||||
|
||||
extern int onlyspace(char* s);
|
||||
extern void error(char *s, char* s1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
optim_description
|
||||
{ struct symtab *p; } :
|
||||
SPACE* parameters
|
||||
{ p = findident("MAXOP",LOOKING,&deftable);
|
||||
if (p == 0) maxoperand = 2; /* default */
|
||||
else maxoperand = p->s_num;
|
||||
}
|
||||
separator SPACE* mode_definitions
|
||||
separator SPACE* patterns
|
||||
separator
|
||||
{ register int c;
|
||||
fprintf(genc, linedir, lineno, inpfile);
|
||||
while ((c = getc(input)) != EOF) {
|
||||
putc(c,genc);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
parameters :
|
||||
[ parameter_line | declaration_block ]*
|
||||
;
|
||||
|
||||
parameter_line
|
||||
{ struct symtab *p;
|
||||
int lin;
|
||||
} :
|
||||
identifier
|
||||
{ p = findident(idbuf,ENTERING,&deftable);}
|
||||
SPACE
|
||||
{ lin = lineno;}
|
||||
value
|
||||
{ p->s_num = atoi(buf);}
|
||||
/* This action in fact only needed for MAXOP */
|
||||
LINE_TERMINATOR
|
||||
SPACE*
|
||||
{ fprintf(genh, linedir, lin, inpfile);
|
||||
fprintf(genh,"#define %s %s\n",p->s_name,buf);}
|
||||
;
|
||||
|
||||
value
|
||||
{ char *p1 = buf;} :
|
||||
[
|
||||
[ OPEN_BRACKET
|
||||
| CLOSE_BRACKET
|
||||
| OPERAND_SEPARATOR
|
||||
| PATTERN_SEPARATOR
|
||||
| INSTRUCTION_SEPARATOR
|
||||
| SPACE
|
||||
| LETTER
|
||||
| DIGIT
|
||||
| OTHER
|
||||
| '%'
|
||||
]
|
||||
{ *p1++ = dot.t_attrib;}
|
||||
]*
|
||||
{ *p1 = '\0';}
|
||||
;
|
||||
|
||||
declaration_block :
|
||||
OPEN_BRACKET
|
||||
{ fprintf(genh, linedir, lineno, inpfile);}
|
||||
[
|
||||
[ LINE_TERMINATOR
|
||||
| OPERAND_SEPARATOR
|
||||
| PATTERN_SEPARATOR
|
||||
| INSTRUCTION_SEPARATOR
|
||||
| SPACE
|
||||
| LETTER
|
||||
| DIGIT
|
||||
| OTHER
|
||||
| '%'
|
||||
]
|
||||
{ putc(dot.t_attrib, genh);}
|
||||
]*
|
||||
CLOSE_BRACKET
|
||||
SPACE*
|
||||
{ putc('\n', genh);}
|
||||
;
|
||||
|
||||
mode_definitions
|
||||
{ int lin; } :
|
||||
{ fputs("int tok_chk(int varno) {\n\tint r;\n", genc);
|
||||
fputs("\tchar *VAL;\n\n",genc);
|
||||
fputs("\tVAL = var[varno].value;\n",genc);
|
||||
fputs("\tswitch(varno) {\n",genc);
|
||||
}
|
||||
[
|
||||
token_list
|
||||
constraint(&lin)
|
||||
{ fprintf(genc,linedir,lin,inpfile);
|
||||
fprintf(genc,"\t\tr = (%s); break;\n",buf);
|
||||
}
|
||||
LINE_TERMINATOR
|
||||
SPACE*
|
||||
]*
|
||||
{ fputs("\tdefault :\n\t\tassert(0);\n",genc);
|
||||
fputs("\t}\n\treturn r;\n}\n\n",genc);
|
||||
}
|
||||
;
|
||||
|
||||
token_list :
|
||||
new_identifier
|
||||
SPACE*
|
||||
[
|
||||
OPERAND_SEPARATOR
|
||||
SPACE*
|
||||
new_identifier
|
||||
SPACE*
|
||||
]*
|
||||
;
|
||||
|
||||
new_identifier
|
||||
{ struct symtab *p;} :
|
||||
identifier
|
||||
{ p = findident(idbuf,ENTERING,&idtable);
|
||||
p->s_num = ++countid;
|
||||
fprintf(genc,"\tcase %d:\n", countid);
|
||||
}
|
||||
;
|
||||
|
||||
constraint (int *lin;)
|
||||
{ char *p = buf; } :
|
||||
OPEN_BRACKET
|
||||
{ *lin = lineno;}
|
||||
[
|
||||
[ LINE_TERMINATOR
|
||||
| OPERAND_SEPARATOR
|
||||
| PATTERN_SEPARATOR
|
||||
| INSTRUCTION_SEPARATOR
|
||||
| LETTER
|
||||
| DIGIT
|
||||
| SPACE
|
||||
| OTHER
|
||||
| '%'
|
||||
]
|
||||
{ *p++ = dot.t_attrib;}
|
||||
]*
|
||||
{ *p = '\0';
|
||||
if (onlyspace(buf)) strcpy(buf,"TRUE");
|
||||
}
|
||||
CLOSE_BRACKET
|
||||
SPACE*
|
||||
;
|
||||
|
||||
patterns
|
||||
{ int lin;
|
||||
char *constr;
|
||||
int np, nr;
|
||||
} :
|
||||
[
|
||||
{ countpat++;
|
||||
constr = (char *) 0;
|
||||
fprintf(genc,"struct instr_descr pat%d[] = {\n",
|
||||
countpat);
|
||||
}
|
||||
instruction_list(&np)
|
||||
{ if (np > patlen) patlen = np;
|
||||
fputs("\n};\n\n",genc);
|
||||
}
|
||||
[
|
||||
constraint(&lin)
|
||||
{ /* Save the constraint, we need it later on */
|
||||
constr = malloc((unsigned)(strlen(buf)+1));
|
||||
strcpy(constr,buf);
|
||||
}
|
||||
]?
|
||||
PATTERN_SEPARATOR
|
||||
{ fprintf(genc,"struct instr_descr rep%d[] = {\n",
|
||||
countpat);
|
||||
}
|
||||
replacement(&nr)
|
||||
{ fputs("\n};\n\n",genc);}
|
||||
LINE_TERMINATOR
|
||||
SPACE*
|
||||
{ addpattern(constr,lin,np,nr);}
|
||||
]*
|
||||
{ printhashtable();
|
||||
printpatterns();
|
||||
fprintf(genh,"#define NRVARS %d\n",countid);
|
||||
fprintf(genh,"#define NRPATTERNS %d\n",countpat);
|
||||
fprintf(genh,"#define MIN_WINDOW_SIZE %d\n",
|
||||
patlen+3);
|
||||
fclose(genh);
|
||||
}
|
||||
;
|
||||
|
||||
instruction_list(int *n;) :
|
||||
instruction(1)
|
||||
{ *n = 1;}
|
||||
[
|
||||
INSTRUCTION_SEPARATOR
|
||||
{ fputs(",\n",genc);}
|
||||
SPACE*
|
||||
instruction(0)
|
||||
{ *n += 1;}
|
||||
]*
|
||||
;
|
||||
|
||||
instruction(int opt;)
|
||||
{ int count = 0;} :
|
||||
opcode(opt)
|
||||
{ if (strcmp(buf,"ANY") != 0) {
|
||||
fprintf(genc,"\t{\"%s\", {",buf);
|
||||
}
|
||||
else fputs("\t{(char *) 0, {",genc);
|
||||
count = 0;
|
||||
}
|
||||
[
|
||||
operand(' ')
|
||||
{ count = 1;}
|
||||
[
|
||||
OPERAND_SEPARATOR
|
||||
{ count++;}
|
||||
SPACE*
|
||||
operand(',')
|
||||
]*
|
||||
{ if (count > maxoperand) {
|
||||
error("Too many operands","");
|
||||
}
|
||||
}
|
||||
]?
|
||||
{ while (count++ < maxoperand) {
|
||||
fprintf(genc,"%c{\"\",-1,\"\"}",count == 1 ? ' ' : ',');
|
||||
}
|
||||
putc('}',genc);
|
||||
putc('}',genc);
|
||||
}
|
||||
;
|
||||
|
||||
opcode(int opt;)
|
||||
{ char *p = buf;} :
|
||||
[
|
||||
[ LETTER
|
||||
| DIGIT
|
||||
| OTHER
|
||||
]
|
||||
{ *p++ = dot.t_attrib;}
|
||||
]+
|
||||
SPACE+
|
||||
{ *p = '\0';
|
||||
if (opt) addtohashtable(buf,countpat);
|
||||
}
|
||||
;
|
||||
|
||||
operand(int c;)
|
||||
{ register struct symtab *p = 0;} :
|
||||
{ fprintf(genc, "%c{\"", c);}
|
||||
[
|
||||
identifier
|
||||
{ if (!p) {
|
||||
p = findident(idbuf,LOOKING,&idtable);
|
||||
if (p) fprintf(genc,"\",%d,\"",p->s_num);
|
||||
else fputs(idbuf,genc);
|
||||
}
|
||||
else fputs(idbuf,genc);
|
||||
}
|
||||
| DIGIT
|
||||
{ putc(dot.t_attrib,genc);}
|
||||
| OTHER
|
||||
{ putc(dot.t_attrib,genc);}
|
||||
]+
|
||||
{ if (p) fputs("\"}",genc);
|
||||
else fputs("\",0,\"\"}",genc);
|
||||
}
|
||||
SPACE*
|
||||
;
|
||||
|
||||
replacement (int *n;)
|
||||
{register int i;} :
|
||||
SPACE*
|
||||
{ *n = 0;}
|
||||
[
|
||||
instruction(0)
|
||||
{ *n = 1;}
|
||||
[
|
||||
INSTRUCTION_SEPARATOR
|
||||
{ fputs(",\n", genc);}
|
||||
SPACE*
|
||||
instruction(0)
|
||||
{ *n += 1;}
|
||||
]*
|
||||
| /* empty replacement, but there must be a
|
||||
* structure initializer anyway
|
||||
*/
|
||||
{ fputs("\t{\"\", {",genc);
|
||||
for (i = 0; i < maxoperand; i++) {
|
||||
fprintf(genc, "%c{\"\",-1,\"\"}",i?',':' ');
|
||||
}
|
||||
fputs("}}",genc);
|
||||
}
|
||||
]
|
||||
;
|
||||
|
||||
|
||||
identifier
|
||||
{ char *p = idbuf; } :
|
||||
LETTER
|
||||
{ *p++ = dot.t_attrib;}
|
||||
[ %while (1)
|
||||
LETTER { *p++ = dot.t_attrib;}
|
||||
| DIGIT { *p++ = dot.t_attrib;}
|
||||
]*
|
||||
{ *p = '\0';}
|
||||
;
|
||||
|
||||
separator :
|
||||
'%' '%' SPACE* LINE_TERMINATOR
|
||||
;
|
||||
/* $Id$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* t o p g e n . g
|
||||
*
|
||||
* Grammar of optimizer description, and some code generation
|
||||
*/
|
||||
|
||||
%token LETTER, DIGIT, OTHER, SPACE;
|
||||
%token LINE_TERMINATOR, OPERAND_SEPARATOR, INSTRUCTION_SEPARATOR,
|
||||
PATTERN_SEPARATOR, OPEN_BRACKET, CLOSE_BRACKET;
|
||||
%lexical LLlex;
|
||||
%start LLparse, optim_description;
|
||||
|
||||
{
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "token.h"
|
||||
#include "symtab.h"
|
||||
#include "misc.h"
|
||||
#include "hash.h"
|
||||
#include "pattern.h"
|
||||
|
||||
char idbuf[BUFSIZ], buf[BUFSIZ];
|
||||
int countid; /* # of variables */
|
||||
int countpat; /* # of patterns */
|
||||
static int patlen; /* Maximum number of instructions in pattern */
|
||||
static int maxoperand; /* Maximum number of operands of instruction */
|
||||
extern FILE *input; /* file descriptor of inputfile */
|
||||
|
||||
|
||||
|
||||
extern int onlyspace(char* s);
|
||||
extern void error(char *s, char* s1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
optim_description
|
||||
{ struct symtab *p; } :
|
||||
SPACE* parameters
|
||||
{ p = findident("MAXOP",LOOKING,&deftable);
|
||||
if (p == 0) maxoperand = 2; /* default */
|
||||
else maxoperand = p->s_num;
|
||||
}
|
||||
separator SPACE* mode_definitions
|
||||
separator SPACE* patterns
|
||||
separator
|
||||
{ register int c;
|
||||
fprintf(genc, linedir, lineno, inpfile);
|
||||
while ((c = getc(input)) != EOF) {
|
||||
putc(c,genc);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
parameters :
|
||||
[ parameter_line | declaration_block ]*
|
||||
;
|
||||
|
||||
parameter_line
|
||||
{ struct symtab *p;
|
||||
int lin;
|
||||
} :
|
||||
identifier
|
||||
{ p = findident(idbuf,ENTERING,&deftable);}
|
||||
SPACE
|
||||
{ lin = lineno;}
|
||||
value
|
||||
{ p->s_num = atoi(buf);}
|
||||
/* This action in fact only needed for MAXOP */
|
||||
LINE_TERMINATOR
|
||||
SPACE*
|
||||
{ fprintf(genh, linedir, lin, inpfile);
|
||||
fprintf(genh,"#define %s %s\n",p->s_name,buf);}
|
||||
;
|
||||
|
||||
value
|
||||
{ char *p1 = buf;} :
|
||||
[
|
||||
[ OPEN_BRACKET
|
||||
| CLOSE_BRACKET
|
||||
| OPERAND_SEPARATOR
|
||||
| PATTERN_SEPARATOR
|
||||
| INSTRUCTION_SEPARATOR
|
||||
| SPACE
|
||||
| LETTER
|
||||
| DIGIT
|
||||
| OTHER
|
||||
| '%'
|
||||
]
|
||||
{ *p1++ = dot.t_attrib;}
|
||||
]*
|
||||
{ *p1 = '\0';}
|
||||
;
|
||||
|
||||
declaration_block :
|
||||
OPEN_BRACKET
|
||||
{ fprintf(genh, linedir, lineno, inpfile);}
|
||||
[
|
||||
[ LINE_TERMINATOR
|
||||
| OPERAND_SEPARATOR
|
||||
| PATTERN_SEPARATOR
|
||||
| INSTRUCTION_SEPARATOR
|
||||
| SPACE
|
||||
| LETTER
|
||||
| DIGIT
|
||||
| OTHER
|
||||
| '%'
|
||||
]
|
||||
{ putc(dot.t_attrib, genh);}
|
||||
]*
|
||||
CLOSE_BRACKET
|
||||
SPACE*
|
||||
{ putc('\n', genh);}
|
||||
;
|
||||
|
||||
mode_definitions
|
||||
{ int lin; } :
|
||||
{ fputs("int tok_chk(int varno) {\n\tint r;\n", genc);
|
||||
fputs("\tchar *VAL;\n\n",genc);
|
||||
fputs("\tVAL = var[varno].value;\n",genc);
|
||||
fputs("\tswitch(varno) {\n",genc);
|
||||
}
|
||||
[
|
||||
token_list
|
||||
constraint(&lin)
|
||||
{ fprintf(genc,linedir,lin,inpfile);
|
||||
fprintf(genc,"\t\tr = (%s); break;\n",buf);
|
||||
}
|
||||
LINE_TERMINATOR
|
||||
SPACE*
|
||||
]*
|
||||
{ fputs("\tdefault :\n\t\tassert(0);\n",genc);
|
||||
fputs("\t}\n\treturn r;\n}\n\n",genc);
|
||||
}
|
||||
;
|
||||
|
||||
token_list :
|
||||
new_identifier
|
||||
SPACE*
|
||||
[
|
||||
OPERAND_SEPARATOR
|
||||
SPACE*
|
||||
new_identifier
|
||||
SPACE*
|
||||
]*
|
||||
;
|
||||
|
||||
new_identifier
|
||||
{ struct symtab *p;} :
|
||||
identifier
|
||||
{ p = findident(idbuf,ENTERING,&idtable);
|
||||
p->s_num = ++countid;
|
||||
fprintf(genc,"\tcase %d:\n", countid);
|
||||
}
|
||||
;
|
||||
|
||||
constraint (int *lin;)
|
||||
{ char *p = buf; } :
|
||||
OPEN_BRACKET
|
||||
{ *lin = lineno;}
|
||||
[
|
||||
[ LINE_TERMINATOR
|
||||
| OPERAND_SEPARATOR
|
||||
| PATTERN_SEPARATOR
|
||||
| INSTRUCTION_SEPARATOR
|
||||
| LETTER
|
||||
| DIGIT
|
||||
| SPACE
|
||||
| OTHER
|
||||
| '%'
|
||||
]
|
||||
{ *p++ = dot.t_attrib;}
|
||||
]*
|
||||
{ *p = '\0';
|
||||
if (onlyspace(buf)) strcpy(buf,"TRUE");
|
||||
}
|
||||
CLOSE_BRACKET
|
||||
SPACE*
|
||||
;
|
||||
|
||||
patterns
|
||||
{ int lin;
|
||||
char *constr;
|
||||
int np, nr;
|
||||
} :
|
||||
[
|
||||
{ countpat++;
|
||||
constr = (char *) 0;
|
||||
fprintf(genc,"struct instr_descr pat%d[] = {\n",
|
||||
countpat);
|
||||
}
|
||||
instruction_list(&np)
|
||||
{ if (np > patlen) patlen = np;
|
||||
fputs("\n};\n\n",genc);
|
||||
}
|
||||
[
|
||||
constraint(&lin)
|
||||
{ /* Save the constraint, we need it later on */
|
||||
constr = malloc((unsigned)(strlen(buf)+1));
|
||||
strcpy(constr,buf);
|
||||
}
|
||||
]?
|
||||
PATTERN_SEPARATOR
|
||||
{ fprintf(genc,"struct instr_descr rep%d[] = {\n",
|
||||
countpat);
|
||||
}
|
||||
replacement(&nr)
|
||||
{ fputs("\n};\n\n",genc);}
|
||||
LINE_TERMINATOR
|
||||
SPACE*
|
||||
{ addpattern(constr,lin,np,nr);}
|
||||
]*
|
||||
{ printhashtable();
|
||||
printpatterns();
|
||||
fprintf(genh,"#define NRVARS %d\n",countid);
|
||||
fprintf(genh,"#define NRPATTERNS %d\n",countpat);
|
||||
fprintf(genh,"#define MIN_WINDOW_SIZE %d\n",
|
||||
patlen+3);
|
||||
fclose(genh);
|
||||
}
|
||||
;
|
||||
|
||||
instruction_list(int *n;) :
|
||||
instruction(1)
|
||||
{ *n = 1;}
|
||||
[
|
||||
INSTRUCTION_SEPARATOR
|
||||
{ fputs(",\n",genc);}
|
||||
SPACE*
|
||||
instruction(0)
|
||||
{ *n += 1;}
|
||||
]*
|
||||
;
|
||||
|
||||
instruction(int opt;)
|
||||
{ int count = 0;} :
|
||||
opcode(opt)
|
||||
{ if (strcmp(buf,"ANY") != 0) {
|
||||
fprintf(genc,"\t{\"%s\", {",buf);
|
||||
}
|
||||
else fputs("\t{(char *) 0, {",genc);
|
||||
count = 0;
|
||||
}
|
||||
[
|
||||
operand(' ')
|
||||
{ count = 1;}
|
||||
[
|
||||
OPERAND_SEPARATOR
|
||||
{ count++;}
|
||||
SPACE*
|
||||
operand(',')
|
||||
]*
|
||||
{ if (count > maxoperand) {
|
||||
error("Too many operands","");
|
||||
}
|
||||
}
|
||||
]?
|
||||
{ while (count++ < maxoperand) {
|
||||
fprintf(genc,"%c{\"\",-1,\"\"}",count == 1 ? ' ' : ',');
|
||||
}
|
||||
putc('}',genc);
|
||||
putc('}',genc);
|
||||
}
|
||||
;
|
||||
|
||||
opcode(int opt;)
|
||||
{ char *p = buf;} :
|
||||
[
|
||||
[ LETTER
|
||||
| DIGIT
|
||||
| OTHER
|
||||
]
|
||||
{ *p++ = dot.t_attrib;}
|
||||
]+
|
||||
SPACE+
|
||||
{ *p = '\0';
|
||||
if (opt) addtohashtable(buf,countpat);
|
||||
}
|
||||
;
|
||||
|
||||
operand(int c;)
|
||||
{ register struct symtab *p = 0;} :
|
||||
{ fprintf(genc, "%c{\"", c);}
|
||||
[
|
||||
identifier
|
||||
{ if (!p) {
|
||||
p = findident(idbuf,LOOKING,&idtable);
|
||||
if (p) fprintf(genc,"\",%d,\"",p->s_num);
|
||||
else fputs(idbuf,genc);
|
||||
}
|
||||
else fputs(idbuf,genc);
|
||||
}
|
||||
| DIGIT
|
||||
{ putc(dot.t_attrib,genc);}
|
||||
| OTHER
|
||||
{ putc(dot.t_attrib,genc);}
|
||||
]+
|
||||
{ if (p) fputs("\"}",genc);
|
||||
else fputs("\",0,\"\"}",genc);
|
||||
}
|
||||
SPACE*
|
||||
;
|
||||
|
||||
replacement (int *n;)
|
||||
{register int i;} :
|
||||
SPACE*
|
||||
{ *n = 0;}
|
||||
[
|
||||
instruction(0)
|
||||
{ *n = 1;}
|
||||
[
|
||||
INSTRUCTION_SEPARATOR
|
||||
{ fputs(",\n", genc);}
|
||||
SPACE*
|
||||
instruction(0)
|
||||
{ *n += 1;}
|
||||
]*
|
||||
| /* empty replacement, but there must be a
|
||||
* structure initializer anyway
|
||||
*/
|
||||
{ fputs("\t{\"\", {",genc);
|
||||
for (i = 0; i < maxoperand; i++) {
|
||||
fprintf(genc, "%c{\"\",-1,\"\"}",i?',':' ');
|
||||
}
|
||||
fputs("}}",genc);
|
||||
}
|
||||
]
|
||||
;
|
||||
|
||||
|
||||
identifier
|
||||
{ char *p = idbuf; } :
|
||||
LETTER
|
||||
{ *p++ = dot.t_attrib;}
|
||||
[ %while (1)
|
||||
LETTER { *p++ = dot.t_attrib;}
|
||||
| DIGIT { *p++ = dot.t_attrib;}
|
||||
]*
|
||||
{ *p = '\0';}
|
||||
;
|
||||
|
||||
separator :
|
||||
'%' '%' SPACE* LINE_TERMINATOR
|
||||
;
|
||||
|
|
Loading…
Reference in a new issue