Merge from default.
This commit is contained in:
commit
7cdd0cd5c0
17
.appveyor.yml
Normal file
17
.appveyor.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
environment:
|
||||
matrix:
|
||||
- CYGWIN: C:\cygwin64
|
||||
|
||||
clone_depth: 1
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
install:
|
||||
- '%CYGWIN%\bin\bash -lc "cygcheck -dc cygwin"'
|
||||
- '%CYGWIN%\setup-x86_64 -q -P bison,flex,ninja'
|
||||
|
||||
build_script:
|
||||
- 'echo building...'
|
||||
- '%CYGWIN%\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make +ack"'
|
||||
|
|
@ -1,12 +1,17 @@
|
|||
---
|
||||
BasedOnStyle: WebKit
|
||||
AllowShortLoopsOnASingleLine: 'false'
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: false
|
||||
BasedOnStyle: WebKit
|
||||
BinPackArguments: true
|
||||
BinPackParameters: false
|
||||
BreakBeforeBraces: Allman
|
||||
ColumnLimit: 100
|
||||
IndentCaseLabels: 'true'
|
||||
PointerAlignment: Left
|
||||
SortIncludes: false
|
||||
TabWidth: '4'
|
||||
UseTab: ForIndentation
|
||||
SortIncludes: false
|
||||
|
||||
...
|
||||
|
|
15
.drone.yml
Normal file
15
.drone.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
clone:
|
||||
depth: 10
|
||||
build:
|
||||
image: teaci/msys32
|
||||
pull: true
|
||||
shell: $$arch
|
||||
commands:
|
||||
- if [ $$arch = sh ]; then apt update; apt install build-essential bison flex; fi
|
||||
- make PREFIX=/tmp/acki +ack
|
||||
|
||||
matrix:
|
||||
arch:
|
||||
- sh
|
||||
#- msys32
|
||||
|
4
Makefile
4
Makefile
|
@ -15,8 +15,8 @@ ACK_TEMP_DIR = /tmp
|
|||
# install it and just want to run the ACK from the build directory
|
||||
# (/tmp/ack-build/staging, by default), leave this as $(INSDIR).
|
||||
|
||||
#PREFIX = /usr/local
|
||||
PREFIX = $(INSDIR)
|
||||
PREFIX = /usr/local
|
||||
#PREFIX = $(INSDIR)
|
||||
|
||||
# Where do you want to put the object files used when building?
|
||||
|
||||
|
|
3
README
3
README
|
@ -33,6 +33,7 @@ pc86 produces bootable floppy disk images for 8086 PCs
|
|||
linux386 produces ELF executables for PC Linux systems
|
||||
linux68k produces ELF executables for m68020 Linux systems
|
||||
linuxppc produces ELF executables for PowerPC Linux systems
|
||||
linuxmips produces ELF executables for little-endian MIPS32r2 Linux systems
|
||||
cpm produces i80 CP/M .COM files
|
||||
rpi produces Raspberry Pi GPU binaries
|
||||
pdpv7 produces PDP/11 V7 Unix binaries
|
||||
|
@ -194,4 +195,4 @@ Please enjoy.
|
|||
|
||||
David Given (davidgiven on Github)
|
||||
dg@cowlark.com
|
||||
2016-11-26
|
||||
2018-09-18
|
||||
|
|
|
@ -10,19 +10,20 @@ vars.plats = {
|
|||
"linux386",
|
||||
"linux68k",
|
||||
"linuxppc",
|
||||
"linuxmips",
|
||||
"osx386",
|
||||
"osxppc",
|
||||
-- --"qemuppc",
|
||||
"pc86",
|
||||
"rpi",
|
||||
"pdpv7",
|
||||
"em22",
|
||||
}
|
||||
vars.plats_with_tests = {
|
||||
"cpm",
|
||||
"linux68k",
|
||||
"linux386",
|
||||
"linuxppc",
|
||||
-- --"qemuppc",
|
||||
"linuxmips",
|
||||
"pc86",
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Strings are allocated in a fixed string descriptor table
|
||||
** This mechanism is used to avoid string copying as much as possible
|
||||
*/
|
||||
|
||||
typedef struct{
|
||||
char *strval;
|
||||
int strcount;
|
||||
int strlength;
|
||||
} String;
|
||||
|
||||
extern String *_newstr(char* str);
|
||||
|
||||
#define MAXSTRING 1024
|
179
h/con_float
179
h/con_float
|
@ -37,47 +37,57 @@
|
|||
#define FL_MSB_AT_LOW_ADDRESS 0
|
||||
#endif
|
||||
|
||||
#define I0 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
#define I0 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
|
||||
#define I1 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
#define I1 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0))
|
||||
#define I2 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
#define I2 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
|
||||
#define I3 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
#define I3 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0))
|
||||
#define I4 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
#define I4 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
|
||||
#define I5 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
#define I5 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0))
|
||||
#define I6 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
#define I6 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1))
|
||||
#define I7 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
#define I7 \
|
||||
((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \
|
||||
+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0))
|
||||
|
||||
#ifndef USE_FLT
|
||||
static int
|
||||
float_cst(str, sz, buf)
|
||||
char *str, *buf;
|
||||
int sz;
|
||||
static int float_cst(str, sz, buf) char *str, *buf;
|
||||
int sz;
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
char* p;
|
||||
float fl;
|
||||
double f;
|
||||
double atof();
|
||||
|
||||
if (sz!= 4 && sz!= 8) {
|
||||
if (sz != 4 && sz != 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
f = atof(str);
|
||||
if (sz == 4) {
|
||||
if (sz == 4)
|
||||
{
|
||||
fl = f;
|
||||
p = (char *) &fl;
|
||||
p = (char*)&fl;
|
||||
}
|
||||
else {
|
||||
p = (char *) &f;
|
||||
else
|
||||
{
|
||||
p = (char*)&f;
|
||||
}
|
||||
for (i = sz; i; i--) {
|
||||
for (i = sz; i; i--)
|
||||
{
|
||||
*buf++ = *p++;
|
||||
}
|
||||
return 0;
|
||||
|
@ -87,89 +97,105 @@ float_cst(str, sz, buf)
|
|||
#include <ctype.h>
|
||||
#include <flt_arith.h>
|
||||
|
||||
int
|
||||
float_cst(str, sz, buf)
|
||||
char *str, *buf;
|
||||
int sz;
|
||||
int float_cst(str, sz, buf) char *str, *buf;
|
||||
int sz;
|
||||
{
|
||||
int overflow = 0;
|
||||
flt_arith e;
|
||||
|
||||
if (sz!= 4 && sz!= 8) {
|
||||
if (sz != 4 && sz != 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
flt_str2flt(str, &e);
|
||||
#ifdef IEEEFLOAT
|
||||
if (sz == 4) {
|
||||
if (sz == 4)
|
||||
{
|
||||
#endif
|
||||
#ifdef PDPFLOAT
|
||||
e.flt_exp += 129;
|
||||
#else
|
||||
e.flt_exp += 127;
|
||||
#endif
|
||||
if (e.flt_mantissa.flt_h_32 == 0) e.flt_exp = 0;
|
||||
if (e.flt_mantissa.flt_h_32 == 0)
|
||||
e.flt_exp = 0;
|
||||
#ifdef IEEEFLOAT
|
||||
if (e.flt_mantissa.flt_h_32 & 0x80) {
|
||||
if (e.flt_mantissa.flt_h_32 & 0x80)
|
||||
{
|
||||
/* rounding */
|
||||
if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) {
|
||||
if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00)
|
||||
{
|
||||
e.flt_exp++;
|
||||
e.flt_mantissa.flt_h_32 = 0x80000000;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
e.flt_mantissa.flt_h_32 += 0x80;
|
||||
}
|
||||
}
|
||||
if (e.flt_exp >= 255) {
|
||||
if (e.flt_exp >= 255)
|
||||
{
|
||||
overflow = 1;
|
||||
e.flt_exp = 255;
|
||||
e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0;
|
||||
}
|
||||
if (e.flt_exp <= 0) {
|
||||
if (e.flt_exp <= 0)
|
||||
{
|
||||
flt_b64_sft(&(e.flt_mantissa), 1);
|
||||
if (e.flt_exp < 0) {
|
||||
if (e.flt_exp < 0)
|
||||
{
|
||||
flt_b64_sft(&(e.flt_mantissa), -e.flt_exp);
|
||||
e.flt_exp = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef IEEEFLOAT
|
||||
if (sz == 4 && (e.flt_mantissa.flt_h_32 & 0x80)) {
|
||||
if (sz == 4 && (e.flt_mantissa.flt_h_32 & 0x80))
|
||||
{
|
||||
/* rounding */
|
||||
if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) {
|
||||
if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00)
|
||||
{
|
||||
e.flt_exp++;
|
||||
e.flt_mantissa.flt_h_32 = 0x80000000;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
e.flt_mantissa.flt_h_32 += 0x80;
|
||||
}
|
||||
}
|
||||
if (sz == 8 && (e.flt_mantissa.flt_l_32 & 0x80)) {
|
||||
if (sz == 8 && (e.flt_mantissa.flt_l_32 & 0x80))
|
||||
{
|
||||
/* rounding */
|
||||
if ((e.flt_mantissa.flt_l_32 & 0xffffff00) == 0xffffff00) {
|
||||
if ((e.flt_mantissa.flt_l_32 & 0xffffff00) == 0xffffff00)
|
||||
{
|
||||
e.flt_mantissa.flt_l_32 = 0;
|
||||
if (e.flt_mantissa.flt_h_32 == 0xffffffff) {
|
||||
if (e.flt_mantissa.flt_h_32 == 0xffffffff)
|
||||
{
|
||||
e.flt_exp++;
|
||||
e.flt_mantissa.flt_h_32 = 0x80000000;
|
||||
}
|
||||
else e.flt_mantissa.flt_h_32++;
|
||||
else
|
||||
e.flt_mantissa.flt_h_32++;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
e.flt_mantissa.flt_l_32 += 0x80;
|
||||
}
|
||||
}
|
||||
if (e.flt_exp > 255) {
|
||||
if (e.flt_exp > 255)
|
||||
{
|
||||
overflow = 1;
|
||||
e.flt_exp = 255;
|
||||
e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
buf[I0] = (e.flt_sign << 7) | (e.flt_exp >> 1);
|
||||
buf[I1] = ((e.flt_exp&1) << 7) |
|
||||
((e.flt_mantissa.flt_h_32 & 0x7fffffff) >> 24);
|
||||
buf[I1] = ((e.flt_exp & 1) << 7) | ((e.flt_mantissa.flt_h_32 & 0x7fffffff) >> 24);
|
||||
buf[I2] = e.flt_mantissa.flt_h_32 >> 16;
|
||||
buf[I3] = e.flt_mantissa.flt_h_32 >> 8;
|
||||
#ifndef IEEEFLOAT
|
||||
if (sz == 8) {
|
||||
if (sz == 8)
|
||||
{
|
||||
buf[I4] = e.flt_mantissa.flt_h_32;
|
||||
buf[I5] = e.flt_mantissa.flt_l_32 >> 24;
|
||||
buf[I6] = e.flt_mantissa.flt_l_32 >> 16;
|
||||
|
@ -181,37 +207,47 @@ float_cst(str, sz, buf)
|
|||
flt_b64_sft(&(e.flt_mantissa), -24);
|
||||
#ifdef IEEEFLOAT
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
e.flt_exp += 1023;
|
||||
if (e.flt_mantissa.flt_h_32 == 0) e.flt_exp = 0;
|
||||
if (e.flt_mantissa.flt_l_32 & 0x400) {
|
||||
if (e.flt_mantissa.flt_h_32 == 0)
|
||||
e.flt_exp = 0;
|
||||
if (e.flt_mantissa.flt_l_32 & 0x400)
|
||||
{
|
||||
/* rounding */
|
||||
if ((e.flt_mantissa.flt_l_32 & 0xfffff800) == 0xfffff800) {
|
||||
if ((e.flt_mantissa.flt_l_32 & 0xfffff800) == 0xfffff800)
|
||||
{
|
||||
e.flt_mantissa.flt_l_32 = 0;
|
||||
if (e.flt_mantissa.flt_h_32 == 0xffffffff) {
|
||||
if (e.flt_mantissa.flt_h_32 == 0xffffffff)
|
||||
{
|
||||
e.flt_exp++;
|
||||
e.flt_mantissa.flt_h_32 = 0x80000000;
|
||||
}
|
||||
else e.flt_mantissa.flt_h_32++;
|
||||
else
|
||||
e.flt_mantissa.flt_h_32++;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
e.flt_mantissa.flt_l_32 += 0x400;
|
||||
}
|
||||
}
|
||||
if (e.flt_exp >= 2047) {
|
||||
if (e.flt_exp >= 2047)
|
||||
{
|
||||
overflow = 1;
|
||||
e.flt_exp = 2047;
|
||||
e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0;
|
||||
}
|
||||
if (e.flt_exp <= 0) {
|
||||
if (e.flt_exp <= 0)
|
||||
{
|
||||
flt_b64_sft(&(e.flt_mantissa), 1);
|
||||
if (e.flt_exp < 0) {
|
||||
if (e.flt_exp < 0)
|
||||
{
|
||||
flt_b64_sft(&(e.flt_mantissa), -e.flt_exp);
|
||||
e.flt_exp = 0;
|
||||
}
|
||||
}
|
||||
buf[I0] = (e.flt_sign << 7) | (e.flt_exp >> 4);
|
||||
buf[I1] = ((e.flt_exp & 017)<< 4) | ((e.flt_mantissa.flt_h_32 >> 27) & 017);
|
||||
buf[I1] = ((e.flt_exp & 017) << 4) | ((e.flt_mantissa.flt_h_32 >> 27) & 017);
|
||||
buf[I2] = e.flt_mantissa.flt_h_32 >> 19;
|
||||
buf[I3] = e.flt_mantissa.flt_h_32 >> 11;
|
||||
buf[I4] = e.flt_mantissa.flt_h_32 >> 3;
|
||||
|
@ -221,15 +257,17 @@ float_cst(str, sz, buf)
|
|||
flt_b64_sft(&(e.flt_mantissa), -53);
|
||||
}
|
||||
#endif
|
||||
#if ! FL_MSL_AT_LOW_ADDRESS
|
||||
if (sz == 4) {
|
||||
#if !FL_MSL_AT_LOW_ADDRESS
|
||||
if (sz == 4)
|
||||
{
|
||||
buf[I4] = buf[I0];
|
||||
buf[I5] = buf[I1];
|
||||
buf[I6] = buf[I2];
|
||||
buf[I7] = buf[I3];
|
||||
}
|
||||
#endif
|
||||
if (overflow) {
|
||||
if (overflow)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
|
@ -237,22 +275,25 @@ float_cst(str, sz, buf)
|
|||
#endif /* USE_FLT */
|
||||
|
||||
#ifdef CODE_GENERATOR
|
||||
con_float()
|
||||
void con_float(void)
|
||||
{
|
||||
char buf[8];
|
||||
int rval = float_cst(str, (int)argval, buf);
|
||||
int i;
|
||||
|
||||
if (rval == 1) {
|
||||
fprintf(stderr,"float constant size = %d\n",(int)argval);
|
||||
if (rval == 1)
|
||||
{
|
||||
fprintf(stderr, "float constant size = %d\n", (int)argval);
|
||||
fatal("bad fcon size");
|
||||
}
|
||||
fprintf(codefile,"!float %s sz %d\n", str, (int)argval);
|
||||
if (rval == 2) {
|
||||
fprintf(codefile, "!float %s sz %d\n", str, (int)argval);
|
||||
if (rval == 2)
|
||||
{
|
||||
fprintf(stderr, "Warning: overflow in floating point constant %s\n", str);
|
||||
}
|
||||
fprintf(codefile, ".data1 0%o", buf[0] & 0377);
|
||||
for (i = 1; i < (int)argval; i++) {
|
||||
for (i = 1; i < (int)argval; i++)
|
||||
{
|
||||
fprintf(codefile, ",0%o", buf[i] & 0377);
|
||||
}
|
||||
putc('\n', codefile);
|
||||
|
@ -260,19 +301,19 @@ con_float()
|
|||
#endif /* CODE_GENERATOR */
|
||||
|
||||
#ifdef CODE_EXPANDER
|
||||
con_float(str, argval)
|
||||
char *str;
|
||||
arith argval;
|
||||
void con_float(const char* str, arith argval)
|
||||
{
|
||||
char buf[8];
|
||||
int rval = float_cst(str, (int)argval, buf);
|
||||
int i;
|
||||
|
||||
if (rval == 1) {
|
||||
if (rval == 1)
|
||||
{
|
||||
argval = 8;
|
||||
rval = float_cst(str, 8, buf);
|
||||
}
|
||||
for (i = 0; i < (int)argval; i++) {
|
||||
for (i = 0; i < (int)argval; i++)
|
||||
{
|
||||
gen1(buf[i]);
|
||||
}
|
||||
}
|
||||
|
|
16
h/m2_traps.h
16
h/m2_traps.h
|
@ -1,16 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
|
||||
/* Modula-2 runtime errors */
|
||||
|
||||
#define M2_TOOLARGE 64 /* stack of process too large */
|
||||
#define M2_TOOMANY 65 /* too many nested traps & handlers */
|
||||
#define M2_NORESULT 66 /* no RETURN from procedure function */
|
||||
#define M2_UOVFL 67 /* cardinal overflow */
|
||||
#define M2_FORCH 68 /* FOR-loop control variable changed */
|
||||
#define M2_UUVFL 69 /* cardinal underflow */
|
||||
#define M2_INTERNAL 70 /* internal error, should not happen */
|
||||
#define M2_UNIXSIG 71 /* unix signal */
|
3
h/out.h
3
h/out.h
|
@ -68,6 +68,9 @@ struct outname {
|
|||
#define RELOPPC 4 /* PowerPC 26-bit address */
|
||||
#define RELOPPC_LIS 5 /* PowerPC lis */
|
||||
#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */
|
||||
#define RELOMIPS 7 /* MIPS */
|
||||
#define RELO2HI 8 /* high 2 bytes of word */
|
||||
#define RELO2HISAD 9 /* high 2 bytes of word, sign adjusted */
|
||||
|
||||
#define RELPC 0x2000 /* pc relative */
|
||||
#define RELBR 0x4000 /* High order byte lowest address. */
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "lib.h"
|
||||
|
||||
long _abl(long i)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "bc_string.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
int _asc(String* str)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lib.h"
|
||||
|
||||
void asrt(int b)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
/*
|
||||
* (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <math.h>
|
||||
#include "lib.h"
|
||||
|
||||
double _atn(double x) { return atan(x); }
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* BASIC file io definitions */
|
||||
|
||||
extern FILE *_chanrd;
|
|
@ -12,6 +12,7 @@ for _, plat in ipairs(vars.plats) do
|
|||
"h+emheaders",
|
||||
"lang/cem/libcc.ansi/headers+pkg",
|
||||
"plat/"..plat.."/include+pkg",
|
||||
"./*.h",
|
||||
},
|
||||
vars = { plat = plat }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "bc_string.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
String* _chr(int i)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
int _cint(double f)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib.h"
|
||||
|
||||
int _errsym;
|
||||
int _erlsym;
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
/*
|
||||
* (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define __NO_DEFS
|
||||
#include <math.h>
|
||||
#include "lib.h"
|
||||
|
||||
double _exp(double x)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
|
||||
; $Id$
|
||||
|
||||
#define FARG 0
|
||||
#define ERES EM_DSIZE
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
|
||||
; $Id$
|
||||
|
||||
#define ARG1 0
|
||||
#define ARG2 EM_DSIZE
|
||||
#define IRES 2*EM_DSIZE
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "bc_string.h"
|
||||
#include <stdio.h>
|
||||
#include "bc_io.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
Filedesc _fdtable[16];
|
||||
/* BASIC file descriptor table */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
#include "lib.h"
|
||||
|
||||
void _hlt(int nr)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "bc_io.h"
|
||||
#include "lib.h"
|
||||
|
||||
/* dtrg --- this originally used sgtty.h to do clever tty manipulation.
|
||||
* Strictly this should be converted to use termios, but for simplicity
|
||||
|
|
|
@ -1,9 +1,107 @@
|
|||
#ifndef LIB_H
|
||||
#define LIB_H
|
||||
|
||||
typedef struct{
|
||||
char *strval;
|
||||
int strcount;
|
||||
int strlength;
|
||||
} String;
|
||||
|
||||
#define MAXSTRING 1024
|
||||
|
||||
extern String *_chr(int i);
|
||||
extern String *_concat(String *s1, String *s2);
|
||||
extern String *_hex(int i);
|
||||
extern String *_left(int size, String *s);
|
||||
extern String *_mid(int i1, int i2, String *s);
|
||||
extern String *_mkd(double d);
|
||||
extern String *_mki(long i);
|
||||
extern String *_newstr(char *str);
|
||||
extern String *_nstr(double f);
|
||||
extern String *_oct(int i);
|
||||
extern String *_right(int length, String *str);
|
||||
extern String *_space(int d);
|
||||
extern String *_strascii(void);
|
||||
extern String *_string(double f, double d);
|
||||
extern char *salloc(unsigned length);
|
||||
extern double _abr(double f);
|
||||
extern double _atn(double x);
|
||||
extern double _cos(double x);
|
||||
extern double _cvd(String *s);
|
||||
extern double _exp(double x);
|
||||
extern double _fcint(double f);
|
||||
extern double _log(double x);
|
||||
extern double _power(double x, double y);
|
||||
extern double _rnd(double d);
|
||||
extern double _sin(double x);
|
||||
extern double _sqt(double x);
|
||||
extern double _tan(double x);
|
||||
extern double _trunc(double f);
|
||||
extern int _asc(String *str);
|
||||
extern int _cint(double f);
|
||||
extern int _fix(double f);
|
||||
extern int _forsgn(double v);
|
||||
extern int _ioeof(int channel);
|
||||
extern int _length(String *str);
|
||||
extern int _retstmt(void);
|
||||
extern int _sgn(double v);
|
||||
extern int _stop(void);
|
||||
extern int _strcomp(String *s1, String *s2);
|
||||
extern int peek(int addr);
|
||||
extern long _abl(long i);
|
||||
extern long _cvi(String *s);
|
||||
extern void _asschn(void);
|
||||
extern void _clochn(int nr);
|
||||
extern void _closeall(void);
|
||||
extern void _decstr(String *str);
|
||||
extern void _delstr(String *src);
|
||||
extern void _fltswap(double *i1, double *i2);
|
||||
extern void _gosub(int x);
|
||||
extern void _goto_err(void);
|
||||
extern void _hlt(int nr);
|
||||
extern void _in(char *buf);
|
||||
extern void _incstr(String *src);
|
||||
extern void _ini_trp(void);
|
||||
extern void _intswap(int *i1, int *i2);
|
||||
extern void _midstmt(String *s2, int i1, int i2, String *s);
|
||||
extern void _nl(void);
|
||||
extern void _opnchn(int reclen, String *fname, String *mode);
|
||||
extern void _out(char *str);
|
||||
extern void _outnl(void);
|
||||
extern void _poke(int i, int j);
|
||||
extern void _prfnum(double f);
|
||||
extern void _prinum(int i);
|
||||
extern void _prstr(String *str);
|
||||
extern void _qstmark(void);
|
||||
extern void _randomi(void);
|
||||
extern void _rdline(String **s);
|
||||
extern void _readflt(double *addr);
|
||||
extern void _readint(int *addr);
|
||||
extern void _readln(void);
|
||||
extern void _readstr(String **s);
|
||||
extern void _restore(int line);
|
||||
extern void _setchan(int index);
|
||||
extern void _setline(void);
|
||||
extern void _setrand(int i);
|
||||
extern void _settrap(int nr);
|
||||
extern void _spc(int x);
|
||||
extern void _str(double f, char *buffer);
|
||||
extern void _strcpy(String *dst, String *src);
|
||||
extern void _strswap(String **s1, String **s2);
|
||||
extern void _tab(int x);
|
||||
extern void _trace(int i);
|
||||
extern void _trap(void);
|
||||
extern void _trpfatal(int i);
|
||||
extern void _trpset(int nr);
|
||||
extern void _wrcomma(void);
|
||||
extern void _wrflt(double f);
|
||||
extern void _wrint(int i);
|
||||
extern void _wrnl(void);
|
||||
extern void _wrstr(String *s);
|
||||
extern void _zone(void);
|
||||
extern void asrt(int b);
|
||||
extern void error(int index);
|
||||
extern char* salloc(unsigned length);
|
||||
extern void sfree(char* c);
|
||||
extern void readskip(void);
|
||||
extern void sfree(char *c);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
/*
|
||||
* (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define __NO_DEFS
|
||||
#include <math.h>
|
||||
#include "lib.h"
|
||||
|
||||
double _log(double x)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "bc_string.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
String* _mki(long i)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "bc_string.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
String* _oct(int i)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
int peek(int addr)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <math.h>
|
||||
#include "lib.h"
|
||||
|
||||
double _power(double x, double y) { return pow(x, y); }
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "bc_string.h"
|
||||
#include <string.h>
|
||||
#include "bc_io.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
/* Here all routine to generate terminal oriented output is located */
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib.h"
|
||||
|
||||
#if !defined(EM_WSIZE)
|
||||
#define EM_WSIZE _EM_WSIZE
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include "bc_string.h"
|
||||
#include "bc_io.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
void _readln(void)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
#define MAXNESTING 1000
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
#include "lib.h"
|
||||
|
||||
char* salloc(unsigned length)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
; $Id$
|
||||
; Save the line where the error occurred
|
||||
exp $_setline
|
||||
pro $_setline,0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
int _sgn(double v)
|
||||
{
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
/*
|
||||
* (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define __NO_DEFS
|
||||
#include <math.h>
|
||||
#include "lib.h"
|
||||
|
||||
double _sin(double x) { return sin(x); }
|
||||
double _cos(double x) { return cos(x); }
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
/*
|
||||
* (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define __NO_DEFS
|
||||
#include <math.h>
|
||||
#include "lib.h"
|
||||
|
||||
double _sqt(double x) { return sqrt(x); }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lib.h"
|
||||
|
||||
_stop()
|
||||
{
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bc_string.h"
|
||||
#include "lib.h"
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define ok(X) \
|
||||
if (X == 0) \
|
||||
return;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "bc_string.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
void _intswap(int* i1, int* i2)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* $Id$ */
|
||||
#include <stdio.h>
|
||||
#include "lib.h"
|
||||
|
||||
void _trace(int i)
|
||||
{
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include "lib.h"
|
||||
|
||||
#ifndef NSIG
|
||||
#define NSIG _NSIG
|
||||
#endif
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Trap handling */
|
||||
int _trpline; /* BASIC return label */
|
||||
jmp_buf trpbuf;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "bc_string.h"
|
||||
#include "bc_io.h"
|
||||
|
||||
/* $Id$ */
|
||||
#include "lib.h"
|
||||
|
||||
/* assume that the channel has been set */
|
||||
|
||||
|
|
|
@ -199,19 +199,26 @@ int lab;
|
|||
|
||||
genreturns()
|
||||
{
|
||||
int count;
|
||||
int nr;
|
||||
|
||||
nr= genlabel();
|
||||
C_df_dnam("returns");
|
||||
C_rom_ilb((label) nr);
|
||||
C_rom_cst((arith)1);
|
||||
C_rom_cst((arith) (gosubcnt-1));
|
||||
C_rom_cst((arith) (gosubcnt-2));
|
||||
|
||||
count = 0;
|
||||
while ( gosubhead)
|
||||
{
|
||||
C_rom_ilb((label) gosubhead->emlabel);
|
||||
gosubhead= gosubhead->nextlist;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count != (gosubcnt-1))
|
||||
error("gosub count table mismatch");
|
||||
|
||||
C_df_ilb((label) nr);
|
||||
C_loc((arith) 1);
|
||||
C_cal("error");
|
||||
|
|
|
@ -111,10 +111,6 @@
|
|||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nopp.h
|
||||
/*#define NOPP 1 /* if NOT defined, use built-int preprocessor */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
||||
|
||||
|
|
|
@ -22,18 +22,11 @@
|
|||
/* Data about the token yielded */
|
||||
struct token dot, ahead, aside;
|
||||
int token_nmb = 0; /* number of the ahead token */
|
||||
int tk_nmb_at_last_syn_err = -5/*ERR_SHADOW*/;
|
||||
/* token number at last syntax error */
|
||||
int tk_nmb_at_last_syn_err = -5 /*ERR_SHADOW*/;
|
||||
/* token number at last syntax error */
|
||||
int idfsize = IDFSIZE;
|
||||
char sp_occurred[SP_TOTAL+1];
|
||||
char sp_occurred[SP_TOTAL + 1];
|
||||
|
||||
#ifndef NOPP
|
||||
int ReplaceMacros = 1; /* replacing macros */
|
||||
int AccDefined = 0; /* accept "defined(...)" */
|
||||
int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
|
||||
int Unstacked = 0; /* an unstack is done */
|
||||
extern int InputLevel;
|
||||
#endif
|
||||
int AccFileSpecifier = 0; /* return filespecifier <...> */
|
||||
int EoiForNewline = 0; /* return EOI upon encountering newline */
|
||||
int File_Inserted = 0; /* a file has just been inserted */
|
||||
|
@ -48,44 +41,19 @@ extern arith full_mask[];
|
|||
extern int lint_skip_comment;
|
||||
#endif
|
||||
|
||||
#ifndef NOPP
|
||||
static struct token LexStack[MAX_LL_DEPTH];
|
||||
static LexSP = 0;
|
||||
|
||||
void skipcomment();
|
||||
|
||||
/* In PushLex() the actions are taken in order to initialise or
|
||||
re-initialise the lexical scanner.
|
||||
E.g. at the invocation of a sub-parser that uses LLlex(), the
|
||||
state of the current parser should be saved.
|
||||
*/
|
||||
PushLex()
|
||||
{
|
||||
assert(LexSP < MAX_LL_DEPTH);
|
||||
assert(ASIDE == 0); /* ASIDE = 0; */
|
||||
GetToken(&ahead);
|
||||
LexStack[LexSP++] = dot;
|
||||
}
|
||||
|
||||
PopLex()
|
||||
{
|
||||
assert(LexSP > 0);
|
||||
dot = LexStack[--LexSP];
|
||||
}
|
||||
#endif /* NOPP */
|
||||
|
||||
int
|
||||
LLlex()
|
||||
int LLlex()
|
||||
{
|
||||
/* LLlex() plays the role of Lexical Analyzer for the C parser.
|
||||
The look-ahead and putting aside of tokens are taken into
|
||||
account.
|
||||
*/
|
||||
if (ASIDE) { /* a token is put aside */
|
||||
if (ASIDE)
|
||||
{ /* a token is put aside */
|
||||
dot = aside;
|
||||
ASIDE = 0;
|
||||
}
|
||||
else { /* read ahead and return the old one */
|
||||
else
|
||||
{ /* read ahead and return the old one */
|
||||
#ifdef LINT
|
||||
lint_comment_ahead();
|
||||
#endif /* LINT */
|
||||
|
@ -104,13 +72,10 @@ LLlex()
|
|||
return DOT;
|
||||
}
|
||||
|
||||
|
||||
char *string_token();
|
||||
char* string_token();
|
||||
arith char_constant();
|
||||
|
||||
int
|
||||
GetToken(ptok)
|
||||
register struct token *ptok;
|
||||
int GetToken(ptok) register struct token* ptok;
|
||||
{
|
||||
/* GetToken() is the actual token recognizer. It calls the
|
||||
control line interpreter if it encounters a "\n{w}*#"
|
||||
|
@ -122,7 +87,8 @@ GetToken(ptok)
|
|||
|
||||
token_nmb++;
|
||||
|
||||
if (File_Inserted) {
|
||||
if (File_Inserted)
|
||||
{
|
||||
File_Inserted = 0;
|
||||
goto firstline;
|
||||
}
|
||||
|
@ -138,9 +104,10 @@ go_on: /* rescan, the following character has been read */
|
|||
ptok->tk_file = FileName;
|
||||
ptok->tk_line = LineNumber;
|
||||
|
||||
switch (class(ch)) { /* detect character class */
|
||||
switch (class(ch))
|
||||
{ /* detect character class */
|
||||
case STNL: /* newline, vertical space or formfeed */
|
||||
firstline:
|
||||
firstline:
|
||||
LineNumber++; /* also at vs and ff */
|
||||
ptok->tk_file = FileName;
|
||||
ptok->tk_line = LineNumber;
|
||||
|
@ -150,29 +117,14 @@ firstline:
|
|||
*/
|
||||
return ptok->tk_symb = EOI;
|
||||
|
||||
while ((ch = GetChar()),
|
||||
(ch == '#'
|
||||
#ifndef NOPP
|
||||
|| ch == '/'
|
||||
#endif
|
||||
|| class(ch) == STSKIP)) {
|
||||
while ((ch = GetChar()), (ch == '#'
|
||||
|| class(ch) == STSKIP))
|
||||
{
|
||||
/* blanks are allowed before hashes */
|
||||
if (ch == '#') {
|
||||
if (ch == '#')
|
||||
{
|
||||
/* a control line follows */
|
||||
domacro();
|
||||
#ifndef NOPP
|
||||
if (File_Inserted) {
|
||||
File_Inserted = 0;
|
||||
goto firstline;
|
||||
}
|
||||
} else if (ch == '/') {
|
||||
if ((GetChar() == '*') && !InputLevel) {
|
||||
skipcomment();
|
||||
} else {
|
||||
UnGetChar();
|
||||
break;
|
||||
}
|
||||
#endif /* NOPP */
|
||||
}
|
||||
}
|
||||
/* We have to loop here, because in
|
||||
|
@ -183,12 +135,12 @@ firstline:
|
|||
case STSKIP: /* just skip the skip characters */
|
||||
goto again;
|
||||
case STGARB: /* garbage character */
|
||||
#ifndef NOPP
|
||||
garbage:
|
||||
#endif
|
||||
if (040 < ch && ch < 0177) {
|
||||
if (040 < ch && ch < 0177)
|
||||
{
|
||||
return ptok->tk_symb = ch;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
lexerror("garbage char \\%03o", ch);
|
||||
}
|
||||
goto again;
|
||||
|
@ -196,7 +148,8 @@ garbage:
|
|||
return ptok->tk_symb = ch;
|
||||
case STCOMP: /* maybe the start of a compound token */
|
||||
nch = GetChar(); /* character lookahead */
|
||||
switch (ch) {
|
||||
switch (ch)
|
||||
{
|
||||
case '!':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = NOTEQUAL;
|
||||
|
@ -222,13 +175,14 @@ garbage:
|
|||
return ptok->tk_symb = MINAB;
|
||||
break;
|
||||
case '<':
|
||||
if (AccFileSpecifier) {
|
||||
if (AccFileSpecifier)
|
||||
{
|
||||
UnGetChar(); /* pushback nch */
|
||||
ptok->tk_bts = string_token("file specifier",
|
||||
'>', &(ptok->tk_len));
|
||||
ptok->tk_bts = string_token("file specifier", '>', &(ptok->tk_len));
|
||||
return ptok->tk_symb = FILESPECIFIER;
|
||||
}
|
||||
if (nch == '<') {
|
||||
if (nch == '<')
|
||||
{
|
||||
if ((nch = GetChar()) == '=')
|
||||
return ptok->tk_symb = LEFTAB;
|
||||
UnGetChar();
|
||||
|
@ -244,7 +198,8 @@ garbage:
|
|||
case '>':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = GREATEREQ;
|
||||
if (nch == '>') {
|
||||
if (nch == '>')
|
||||
{
|
||||
if ((nch = GetChar()) == '=')
|
||||
return ptok->tk_symb = RIGHTAB;
|
||||
UnGetChar();
|
||||
|
@ -270,12 +225,6 @@ garbage:
|
|||
return ptok->tk_symb = XORAB;
|
||||
break;
|
||||
case '/':
|
||||
#ifndef NOPP
|
||||
if (nch == '*' && !InputLevel) {
|
||||
skipcomment();
|
||||
goto again;
|
||||
}
|
||||
#endif
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = DIVAB;
|
||||
break;
|
||||
|
@ -295,12 +244,14 @@ garbage:
|
|||
return ptok->tk_symb = STRING;
|
||||
case STELL: /* wide character constant/string prefix */
|
||||
nch = GetChar();
|
||||
if (nch == '"') {
|
||||
ptok->tk_bts = string_token("wide character string",
|
||||
'"', &(ptok->tk_len));
|
||||
if (nch == '"')
|
||||
{
|
||||
ptok->tk_bts = string_token("wide character string", '"', &(ptok->tk_len));
|
||||
ptok->tk_fund = WCHAR; /* string of wide characters */
|
||||
return ptok->tk_symb = STRING;
|
||||
} else if (nch == '\'') {
|
||||
}
|
||||
else if (nch == '\'')
|
||||
{
|
||||
ptok->tk_ival = char_constant("wide character");
|
||||
ptok->tk_fund = INT;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
|
@ -309,21 +260,14 @@ garbage:
|
|||
/* fallthrough */
|
||||
case STIDF:
|
||||
{
|
||||
register char *tg = &buf[0];
|
||||
register char* tg = &buf[0];
|
||||
register int pos = -1;
|
||||
register struct idf *idef;
|
||||
register struct idf* idef;
|
||||
extern int idfsize; /* ??? */
|
||||
#ifndef NOPP
|
||||
int NoExpandNext = 0;
|
||||
|
||||
if (Unstacked) EnableMacros(); /* unstack macro's when allowed. */
|
||||
if (ch == NOEXPM) {
|
||||
NoExpandNext = 1;
|
||||
ch = GetChar();
|
||||
}
|
||||
#endif
|
||||
do { /* read the identifier */
|
||||
if (++pos < idfsize) {
|
||||
do
|
||||
{ /* read the identifier */
|
||||
if (++pos < idfsize)
|
||||
{
|
||||
*tg++ = ch;
|
||||
}
|
||||
ch = GetChar();
|
||||
|
@ -336,48 +280,40 @@ garbage:
|
|||
sp_occurred[idef->id_special] = 1;
|
||||
idef->id_file = ptok->tk_file;
|
||||
idef->id_line = ptok->tk_line;
|
||||
#ifndef NOPP
|
||||
if (idef->id_macro && ReplaceMacros && !NoExpandNext) {
|
||||
if (replace(idef))
|
||||
goto again;
|
||||
}
|
||||
if (UnknownIdIsZero && idef->id_reserved != SIZEOF) {
|
||||
ptok->tk_ival = (arith)0;
|
||||
ptok->tk_fund = INT;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
#endif /* NOPP */
|
||||
ptok->tk_symb = (
|
||||
idef->id_reserved
|
||||
ptok->tk_symb
|
||||
= (idef->id_reserved
|
||||
? idef->id_reserved
|
||||
: idef->id_def && idef->id_def->df_sc == TYPEDEF
|
||||
? TYPE_IDENTIFIER
|
||||
: IDENTIFIER
|
||||
);
|
||||
: idef->id_def && idef->id_def->df_sc == TYPEDEF ? TYPE_IDENTIFIER
|
||||
: IDENTIFIER);
|
||||
return IDENTIFIER;
|
||||
}
|
||||
case STNUM: /* a numeric constant */
|
||||
{
|
||||
register int siz_left = NUMSIZE - 1;
|
||||
register char *np = &buf[0];
|
||||
register char* np = &buf[0];
|
||||
int flags = 0;
|
||||
|
||||
#define store(ch) if (--siz_left >= 0) \
|
||||
#define store(ch) \
|
||||
if (--siz_left >= 0) \
|
||||
*np++ = ch;
|
||||
|
||||
if (ch == '.') {
|
||||
if (ch == '.')
|
||||
{
|
||||
/* An embarrasing ambiguity. We have either a
|
||||
pp-number, a field operator, an ELLIPSIS or
|
||||
an error (..).
|
||||
*/
|
||||
ch = GetChar();
|
||||
if (!is_dig(ch)) { /* . or ... */
|
||||
if (ch == '.') {
|
||||
if (!is_dig(ch))
|
||||
{ /* . or ... */
|
||||
if (ch == '.')
|
||||
{
|
||||
if ((ch = GetChar()) == '.')
|
||||
return ptok->tk_symb = ELLIPSIS;
|
||||
UnGetChar(); /* not '.' */
|
||||
ChPushBack('.'); /* sigh ... */
|
||||
} else
|
||||
}
|
||||
else
|
||||
UnGetChar(); /* not '.' */
|
||||
return ptok->tk_symb = '.';
|
||||
}
|
||||
|
@ -387,31 +323,37 @@ garbage:
|
|||
}
|
||||
store(ch);
|
||||
ch = GetChar();
|
||||
while(in_idf(ch) || ch == '.') {
|
||||
while (in_idf(ch) || ch == '.')
|
||||
{
|
||||
store(ch);
|
||||
if (ch == '.') flags |= FLG_DOTSEEN;
|
||||
if (ch == 'e' || ch == 'E') {
|
||||
if (ch == '.')
|
||||
flags |= FLG_DOTSEEN;
|
||||
if (ch == 'e' || ch == 'E')
|
||||
{
|
||||
flags |= FLG_ESEEN;
|
||||
ch = GetChar();
|
||||
if (ch == '+' || ch == '-') {
|
||||
if (ch == '+' || ch == '-')
|
||||
{
|
||||
flags |= FLG_DOTSEEN; /* trick */
|
||||
store(ch);
|
||||
ch = GetChar();
|
||||
}
|
||||
} else ch = GetChar();
|
||||
}
|
||||
else
|
||||
ch = GetChar();
|
||||
}
|
||||
store('\0');
|
||||
UnGetChar();
|
||||
|
||||
np = &buf[0];
|
||||
ch = *np++;
|
||||
if (siz_left < 0) {
|
||||
if (siz_left < 0)
|
||||
{
|
||||
lexerror("number too long");
|
||||
if ((flags & FLG_DOTSEEN)
|
||||
|| (flags & FLG_ESEEN
|
||||
&& !(ch == '0'
|
||||
&& (*np == 'x' || *np == 'X')))) {
|
||||
ptok->tk_fval = Salloc("0.0", (unsigned) 4);
|
||||
|| (flags & FLG_ESEEN && !(ch == '0' && (*np == 'x' || *np == 'X'))))
|
||||
{
|
||||
ptok->tk_fval = Salloc("0.0", (unsigned)4);
|
||||
ptok->tk_fund = DOUBLE;
|
||||
return ptok->tk_symb = FLOATING;
|
||||
}
|
||||
|
@ -421,8 +363,8 @@ garbage:
|
|||
}
|
||||
/* Now, the pp-number must be converted into a token */
|
||||
if ((flags & FLG_DOTSEEN)
|
||||
|| (flags & FLG_ESEEN
|
||||
&& !(ch == '0' && (*np == 'x' || *np == 'X')))) {
|
||||
|| (flags & FLG_ESEEN && !(ch == '0' && (*np == 'x' || *np == 'X'))))
|
||||
{
|
||||
strflt2tok(&buf[0], ptok);
|
||||
return ptok->tk_symb = FLOATING;
|
||||
}
|
||||
|
@ -431,77 +373,13 @@ garbage:
|
|||
}
|
||||
case STEOI: /* end of text on source file */
|
||||
return ptok->tk_symb = EOI;
|
||||
#ifndef NOPP
|
||||
case STMSPEC:
|
||||
if (!InputLevel) goto garbage;
|
||||
if (ch == TOKSEP) goto again;
|
||||
/* fallthrough shouldn't happen */
|
||||
#endif
|
||||
default: /* this cannot happen */
|
||||
crash("bad class for char 0%o", ch);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
void
|
||||
skipcomment()
|
||||
{
|
||||
/* The last character read has been the '*' of '/_*'. The
|
||||
characters, except NL and EOI, between '/_*' and the first
|
||||
occurring '*_/' are not interpreted.
|
||||
NL only affects the LineNumber. EOI is not legal.
|
||||
|
||||
Important note: it is not possible to stop skipping comment
|
||||
beyond the end-of-file of an included file.
|
||||
EOI is returned by LoadChar only on encountering EOF of the
|
||||
top-level file...
|
||||
*/
|
||||
register int c, oldc = '\0';
|
||||
|
||||
NoUnstack++;
|
||||
c = GetChar();
|
||||
#ifdef LINT
|
||||
if (! lint_skip_comment) {
|
||||
lint_start_comment();
|
||||
lint_comment_char(c);
|
||||
}
|
||||
#endif /* LINT */
|
||||
do {
|
||||
while (c != '*') {
|
||||
if (class(c) == STNL) {
|
||||
++LineNumber;
|
||||
} else if (c == EOI) {
|
||||
NoUnstack--;
|
||||
#ifdef LINT
|
||||
if (! lint_skip_comment) lint_end_comment();
|
||||
#endif /* LINT */
|
||||
return;
|
||||
}
|
||||
oldc = c;
|
||||
c = GetChar();
|
||||
#ifdef LINT
|
||||
if (! lint_skip_comment) lint_comment_char(c);
|
||||
#endif /* LINT */
|
||||
} /* last Character seen was '*' */
|
||||
c = GetChar();
|
||||
if ( c != '/' && oldc == '/')
|
||||
lexwarning("comment inside comment ?");
|
||||
oldc = '*';
|
||||
#ifdef LINT
|
||||
if (! lint_skip_comment) lint_comment_char(c);
|
||||
#endif /* LINT */
|
||||
} while (c != '/');
|
||||
#ifdef LINT
|
||||
if (! lint_skip_comment) lint_end_comment();
|
||||
#endif /* LINT */
|
||||
NoUnstack--;
|
||||
}
|
||||
#endif /* NOPP */
|
||||
|
||||
arith
|
||||
char_constant(nm)
|
||||
char *nm;
|
||||
arith char_constant(nm) char* nm;
|
||||
{
|
||||
register arith val = 0;
|
||||
register int ch;
|
||||
|
@ -511,15 +389,18 @@ char_constant(nm)
|
|||
if (ch == '\'')
|
||||
lexerror("%s constant too short", nm);
|
||||
else
|
||||
while (ch != '\'') {
|
||||
if (ch == '\n') {
|
||||
while (ch != '\'')
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
lexerror("newline in %s constant", nm);
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == '\\')
|
||||
ch = quoted(GetChar());
|
||||
if (ch >= 128) ch -= 256;
|
||||
if (ch >= 128)
|
||||
ch -= 256;
|
||||
if (size < (int)int_size)
|
||||
val |= ch << 8 * size;
|
||||
size++;
|
||||
|
@ -532,24 +413,25 @@ char_constant(nm)
|
|||
return val;
|
||||
}
|
||||
|
||||
char *
|
||||
string_token(nm, stop_char, plen)
|
||||
char *nm;
|
||||
int *plen;
|
||||
char* string_token(nm, stop_char, plen) char* nm;
|
||||
int* plen;
|
||||
{
|
||||
register int ch;
|
||||
register int str_size;
|
||||
register char *str = Malloc((unsigned) (str_size = ISTRSIZE));
|
||||
register char* str = Malloc((unsigned)(str_size = ISTRSIZE));
|
||||
register int pos = 0;
|
||||
|
||||
ch = GetChar();
|
||||
while (ch != stop_char) {
|
||||
if (ch == '\n') {
|
||||
while (ch != stop_char)
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
lexerror("newline in %s", nm);
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
if (ch == EOI)
|
||||
{
|
||||
lexerror("end-of-file inside %s", nm);
|
||||
break;
|
||||
}
|
||||
|
@ -557,7 +439,7 @@ string_token(nm, stop_char, plen)
|
|||
ch = quoted(GetChar());
|
||||
str[pos++] = ch;
|
||||
if (pos == str_size)
|
||||
str = Realloc(str, (unsigned) (str_size += RSTRSIZE));
|
||||
str = Realloc(str, (unsigned)(str_size += RSTRSIZE));
|
||||
ch = GetChar();
|
||||
}
|
||||
str[pos++] = '\0'; /* for filenames etc. */
|
||||
|
@ -565,16 +447,16 @@ string_token(nm, stop_char, plen)
|
|||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
quoted(ch)
|
||||
register int ch;
|
||||
int quoted(ch) register int ch;
|
||||
{
|
||||
/* quoted() replaces an escaped character sequence by the
|
||||
character meant.
|
||||
*/
|
||||
/* first char after backslash already in ch */
|
||||
if (!is_oct(ch)) { /* a quoted char */
|
||||
switch (ch) {
|
||||
if (!is_oct(ch))
|
||||
{ /* a quoted char */
|
||||
switch (ch)
|
||||
{
|
||||
case 'n':
|
||||
ch = '\n';
|
||||
break;
|
||||
|
@ -601,7 +483,8 @@ quoted(ch)
|
|||
register int hex = 0;
|
||||
register int vch;
|
||||
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
ch = GetChar();
|
||||
if ((vch = hex_val(ch)) == -1)
|
||||
break;
|
||||
|
@ -612,166 +495,115 @@ quoted(ch)
|
|||
}
|
||||
}
|
||||
}
|
||||
else { /* a quoted octal */
|
||||
else
|
||||
{ /* a quoted octal */
|
||||
register int oct = 0, cnt = 0;
|
||||
|
||||
do {
|
||||
oct = oct*8 + (ch-'0');
|
||||
do
|
||||
{
|
||||
oct = oct * 8 + (ch - '0');
|
||||
ch = GetChar();
|
||||
} while (is_oct(ch) && ++cnt < 3);
|
||||
UnGetChar();
|
||||
ch = oct;
|
||||
}
|
||||
return ch&0377;
|
||||
return ch & 0377;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hex_val(ch)
|
||||
register int ch;
|
||||
int hex_val(ch) register int ch;
|
||||
{
|
||||
return is_dig(ch) ? ch - '0'
|
||||
: is_hex(ch) ? (ch - 'a' + 10) & 017
|
||||
: -1;
|
||||
return is_dig(ch) ? ch - '0' : is_hex(ch) ? (ch - 'a' + 10) & 017 : -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GetChar()
|
||||
int GetChar()
|
||||
{
|
||||
/* The routines GetChar and trigraph parses the trigraph
|
||||
sequences and removes occurences of \\\n.
|
||||
*/
|
||||
register int ch;
|
||||
|
||||
#ifndef NOPP
|
||||
again:
|
||||
#endif
|
||||
LoadChar(ch);
|
||||
|
||||
#ifndef NOPP
|
||||
/* possible trigraph sequence */
|
||||
if (ch == '?')
|
||||
ch = trigraph();
|
||||
|
||||
/* \<newline> is removed from the input stream */
|
||||
if (ch == '\\') {
|
||||
LoadChar(ch);
|
||||
if (ch == '\n') {
|
||||
++LineNumber;
|
||||
goto again;
|
||||
}
|
||||
PushBack();
|
||||
ch = '\\';
|
||||
}
|
||||
#endif
|
||||
return(LexSave = ch);
|
||||
return (LexSave = ch);
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
int
|
||||
trigraph()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
LoadChar(ch);
|
||||
if (ch == '?') {
|
||||
LoadChar(ch);
|
||||
switch (ch) { /* its a trigraph */
|
||||
case '=':
|
||||
ch = '#';
|
||||
return(ch);
|
||||
case '(':
|
||||
ch = '[';
|
||||
return(ch);
|
||||
case '/':
|
||||
ch = '\\';
|
||||
return(ch);
|
||||
case ')':
|
||||
ch = ']';
|
||||
return(ch);
|
||||
case '\'':
|
||||
ch = '^';
|
||||
return(ch);
|
||||
case '<':
|
||||
ch = '{';
|
||||
return(ch);
|
||||
case '!':
|
||||
ch = '|';
|
||||
return(ch);
|
||||
case '>':
|
||||
ch = '}';
|
||||
return(ch);
|
||||
case '-':
|
||||
ch = '~';
|
||||
return(ch);
|
||||
}
|
||||
PushBack();
|
||||
}
|
||||
PushBack();
|
||||
return('?');
|
||||
}
|
||||
#endif
|
||||
|
||||
/* strflt2tok only checks the syntax of the floating-point number and
|
||||
* selects the right type for the number.
|
||||
*/
|
||||
strflt2tok(fltbuf, ptok)
|
||||
char fltbuf[];
|
||||
struct token *ptok;
|
||||
strflt2tok(fltbuf, ptok) char fltbuf[];
|
||||
struct token* ptok;
|
||||
{
|
||||
register char *cp = fltbuf;
|
||||
register char* cp = fltbuf;
|
||||
int malformed = 0;
|
||||
|
||||
while (is_dig(*cp)) cp++;
|
||||
if (*cp == '.') {
|
||||
while (is_dig(*cp))
|
||||
cp++;
|
||||
if (*cp == '.')
|
||||
{
|
||||
cp++;
|
||||
while (is_dig(*cp))
|
||||
cp++;
|
||||
while (is_dig(*cp)) cp++;
|
||||
}
|
||||
if (*cp == 'e' || *cp == 'E') {
|
||||
if (*cp == 'e' || *cp == 'E')
|
||||
{
|
||||
cp++;
|
||||
if (*cp == '+' || *cp == '-')
|
||||
cp++;
|
||||
if (!is_dig(*cp)) malformed++;
|
||||
while (is_dig(*cp)) cp++;
|
||||
if (!is_dig(*cp))
|
||||
malformed++;
|
||||
while (is_dig(*cp))
|
||||
cp++;
|
||||
}
|
||||
if (*cp == 'f' || *cp == 'F') {
|
||||
if (*(cp + 1)) malformed++;
|
||||
if (*cp == 'f' || *cp == 'F')
|
||||
{
|
||||
if (*(cp + 1))
|
||||
malformed++;
|
||||
*cp = '\0';
|
||||
ptok->tk_fund = FLOAT;
|
||||
} else if (*cp == 'l' || *cp == 'L') {
|
||||
if (*(cp + 1)) malformed++;
|
||||
}
|
||||
else if (*cp == 'l' || *cp == 'L')
|
||||
{
|
||||
if (*(cp + 1))
|
||||
malformed++;
|
||||
*cp = '\0';
|
||||
ptok->tk_fund = LNGDBL;
|
||||
} else {
|
||||
if (*cp) malformed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*cp)
|
||||
malformed++;
|
||||
ptok->tk_fund = DOUBLE;
|
||||
}
|
||||
if (malformed) {
|
||||
if (malformed)
|
||||
{
|
||||
lexerror("malformed floating constant");
|
||||
ptok->tk_fval = Salloc("0.0", (unsigned) 4);
|
||||
} else {
|
||||
ptok->tk_fval = Salloc(fltbuf, (unsigned) (cp - fltbuf + 1));
|
||||
ptok->tk_fval = Salloc("0.0", (unsigned)4);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptok->tk_fval = Salloc(fltbuf, (unsigned)(cp - fltbuf + 1));
|
||||
}
|
||||
}
|
||||
|
||||
strint2tok(intbuf, ptok)
|
||||
char intbuf[];
|
||||
struct token *ptok;
|
||||
strint2tok(intbuf, ptok) char intbuf[];
|
||||
struct token* ptok;
|
||||
{
|
||||
register char *cp = intbuf;
|
||||
register char* cp = intbuf;
|
||||
int base = 10;
|
||||
arith val = 0, dig, ubound;
|
||||
int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
|
||||
int fund;
|
||||
|
||||
assert(*cp != '-');
|
||||
if (*cp == '0') {
|
||||
if (*cp == '0')
|
||||
{
|
||||
cp++;
|
||||
if (*cp == 'x' || *cp == 'X') {
|
||||
if (*cp == 'x' || *cp == 'X')
|
||||
{
|
||||
cp++;
|
||||
base = 16;
|
||||
} else base = 8;
|
||||
}
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
/* The upperbound will be the same as when computed with
|
||||
* max_unsigned_arith / base (since base is even). The problem here
|
||||
|
@ -779,68 +611,99 @@ struct token *ptok;
|
|||
*/
|
||||
ubound = max_arith / (base / 2);
|
||||
|
||||
while (is_hex(*cp)) {
|
||||
while (is_hex(*cp))
|
||||
{
|
||||
dig = hex_val(*cp);
|
||||
if (dig >= base) {
|
||||
if (dig >= base)
|
||||
{
|
||||
malformed++; /* ignore */
|
||||
}
|
||||
else {
|
||||
if (val < 0 || val > ubound) ovfl++;
|
||||
else
|
||||
{
|
||||
if (val < 0 || val > ubound)
|
||||
ovfl++;
|
||||
val *= base;
|
||||
if (val < 0 && val + dig >= 0) ovfl++;
|
||||
if (val < 0 && val + dig >= 0)
|
||||
ovfl++;
|
||||
val += dig;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
|
||||
while (*cp) {
|
||||
if (*cp == 'l' || *cp == 'L') lng_flg++;
|
||||
else if (*cp == 'u' || *cp == 'U') uns_flg++;
|
||||
else break;
|
||||
while (*cp)
|
||||
{
|
||||
if (*cp == 'l' || *cp == 'L')
|
||||
lng_flg++;
|
||||
else if (*cp == 'u' || *cp == 'U')
|
||||
uns_flg++;
|
||||
else
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
if (*cp) {
|
||||
if (*cp)
|
||||
{
|
||||
malformed++;
|
||||
}
|
||||
if (malformed) {
|
||||
lexerror("malformed %s integer constant",
|
||||
(base == 10 ? "decimal"
|
||||
: (base == 8 ? "octal"
|
||||
: "hexadecimal")));
|
||||
} else {
|
||||
if (malformed)
|
||||
{
|
||||
lexerror(
|
||||
"malformed %s integer constant",
|
||||
(base == 10 ? "decimal" : (base == 8 ? "octal" : "hexadecimal")));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lng_flg > 1)
|
||||
lexerror("only one long suffix allowed");
|
||||
if (uns_flg > 1)
|
||||
lexerror("only one unsigned suffix allowed");
|
||||
}
|
||||
if (ovfl) {
|
||||
if (ovfl)
|
||||
{
|
||||
lexwarning("overflow in constant");
|
||||
fund = ULONG;
|
||||
} else if (!lng_flg && (val & full_mask[(int)int_size]) == val) {
|
||||
if (val >= 0 && val <= max_int) {
|
||||
}
|
||||
else if (!lng_flg && (val & full_mask[(int)int_size]) == val)
|
||||
{
|
||||
if (val >= 0 && val <= max_int)
|
||||
{
|
||||
fund = INT;
|
||||
} else if (int_size == long_size) {
|
||||
}
|
||||
else if (int_size == long_size)
|
||||
{
|
||||
fund = UNSIGNED;
|
||||
} else if (base == 10 && !uns_flg)
|
||||
}
|
||||
else if (base == 10 && !uns_flg)
|
||||
fund = LONG;
|
||||
else fund = UNSIGNED;
|
||||
} else if((val & full_mask[(int)long_size]) == val) {
|
||||
if (val >= 0) fund = LONG;
|
||||
else fund = ULONG;
|
||||
} else { /* sizeof(arith) is greater than long_size */
|
||||
else
|
||||
fund = UNSIGNED;
|
||||
}
|
||||
else if ((val & full_mask[(int)long_size]) == val)
|
||||
{
|
||||
if (val >= 0)
|
||||
fund = LONG;
|
||||
else
|
||||
fund = ULONG;
|
||||
}
|
||||
else
|
||||
{ /* sizeof(arith) is greater than long_size */
|
||||
assert(arith_size > long_size);
|
||||
lexwarning("constant too large for target machine");
|
||||
/* cut the size to prevent further complaints */
|
||||
val &= full_mask[(int)long_size];
|
||||
fund = ULONG;
|
||||
}
|
||||
if (lng_flg) {
|
||||
if (lng_flg)
|
||||
{
|
||||
/* fund can't be INT */
|
||||
if (fund == UNSIGNED) fund = ULONG;
|
||||
if (fund == UNSIGNED)
|
||||
fund = ULONG;
|
||||
}
|
||||
if (uns_flg) {
|
||||
if (fund == INT) fund = UNSIGNED;
|
||||
else if (fund == LONG) fund = ULONG;
|
||||
if (uns_flg)
|
||||
{
|
||||
if (fund == INT)
|
||||
fund = UNSIGNED;
|
||||
else if (fund == LONG)
|
||||
fund = ULONG;
|
||||
}
|
||||
ptok->tk_fund = fund;
|
||||
ptok->tk_ival = val;
|
||||
|
|
|
@ -43,12 +43,6 @@ extern struct token dot, ahead, aside;
|
|||
extern int token_nmb; /* number of the ahead token */
|
||||
extern int tk_nmb_at_last_syn_err; /* token number at last syntax error */
|
||||
|
||||
#ifndef NOPP
|
||||
extern int ReplaceMacros; /* "LLlex.c" */
|
||||
extern int AccDefined; /* "LLlex.c" */
|
||||
extern int Unstacked; /* "LLlex.c" */
|
||||
extern int UnknownIdIsZero; /* "LLlex.c" */
|
||||
#endif /* NOPP */
|
||||
extern int EoiForNewline; /* "LLlex.c" */
|
||||
extern int AccFileSpecifier; /* "LLlex.c" */
|
||||
extern int File_Inserted; /* "LLlex.c" */
|
||||
|
|
|
@ -111,10 +111,6 @@
|
|||
/*#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nopp.h
|
||||
#define NOPP 1 /* if NOT defined, use built-int preprocessor */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
||||
|
||||
|
|
|
@ -111,7 +111,6 @@ cprogram {
|
|||
"./field.c",
|
||||
"./fltcstoper.c",
|
||||
"./idf.c",
|
||||
"./init.c",
|
||||
"./input.c",
|
||||
"./l_comment.c",
|
||||
"./l_ev_ord.c",
|
||||
|
@ -124,7 +123,6 @@ cprogram {
|
|||
"./options.c",
|
||||
"./pragma.c",
|
||||
"./proto.c",
|
||||
"./replace.c",
|
||||
"./skip.c",
|
||||
"./stab.c",
|
||||
"./stack.c",
|
||||
|
|
|
@ -14,12 +14,7 @@
|
|||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "input.h"
|
||||
#include "replace.h"
|
||||
|
||||
#ifndef NOPP
|
||||
#include <alloc.h>
|
||||
#include "class.h"
|
||||
#include "macro.h"
|
||||
#ifdef DBSYMTAB
|
||||
#include <stb.h>
|
||||
#include <em.h>
|
||||
|
@ -27,775 +22,8 @@ int IncludeLevel = 0;
|
|||
#endif
|
||||
|
||||
extern char options[];
|
||||
extern char **inctable; /* list of include directories */
|
||||
extern char *getwdir();
|
||||
char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
|
||||
/* 1 if a corresponding ELSE has been */
|
||||
/* encountered. */
|
||||
|
||||
int nestlevel = -1;
|
||||
|
||||
void macro_def();
|
||||
void do_define();
|
||||
|
||||
struct idf *
|
||||
GetIdentifier(skiponerr)
|
||||
int skiponerr; /* skip the rest of the line on error */
|
||||
{
|
||||
/* returns a pointer to the descriptor of the identifier that is
|
||||
read from the input stream. When the input doe not contain
|
||||
an identifier, the rest of the line is skipped when
|
||||
skiponerr is on, and a null-pointer is returned.
|
||||
The substitution of macros is disabled.
|
||||
*/
|
||||
int tmp = UnknownIdIsZero;
|
||||
int tok;
|
||||
struct token tk;
|
||||
|
||||
UnknownIdIsZero = ReplaceMacros = 0;
|
||||
tok = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
UnknownIdIsZero = tmp;
|
||||
if (tok != IDENTIFIER) {
|
||||
if (skiponerr && tok != EOI) SkipToNewLine();
|
||||
return (struct idf *)0;
|
||||
}
|
||||
return tk.tk_idf;
|
||||
}
|
||||
|
||||
/* domacro() is the control line interpreter. The '#' has already
|
||||
been read by the lexical analyzer by which domacro() is called.
|
||||
The token appearing directly after the '#' is obtained by calling
|
||||
the basic lexical analyzing function GetToken() and is interpreted
|
||||
to perform the action belonging to that token.
|
||||
An error message is produced when the token is not recognized,
|
||||
i.e. it is not one of "define" .. "undef" , integer or newline.
|
||||
*/
|
||||
domacro()
|
||||
{
|
||||
struct token tk; /* the token itself */
|
||||
int toknum;
|
||||
|
||||
EoiForNewline = 1;
|
||||
ReplaceMacros = 0;
|
||||
toknum = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
switch(toknum) { /* select control line action */
|
||||
case IDENTIFIER: /* is it a macro keyword? */
|
||||
switch (tk.tk_idf->id_resmac) {
|
||||
case K_DEFINE: /* "define" */
|
||||
do_define();
|
||||
break;
|
||||
case K_ELIF: /* "elif" */
|
||||
do_elif();
|
||||
break;
|
||||
case K_ELSE: /* "else" */
|
||||
do_else();
|
||||
break;
|
||||
case K_ENDIF: /* "endif" */
|
||||
do_endif();
|
||||
break;
|
||||
case K_IF: /* "if" */
|
||||
do_if();
|
||||
break;
|
||||
case K_IFDEF: /* "ifdef" */
|
||||
do_ifdef(1);
|
||||
break;
|
||||
case K_IFNDEF: /* "ifndef" */
|
||||
do_ifdef(0);
|
||||
break;
|
||||
case K_INCLUDE: /* "include" */
|
||||
do_include();
|
||||
break;
|
||||
case K_LINE: /* "line" */
|
||||
/* set LineNumber and FileName according to
|
||||
the arguments.
|
||||
*/
|
||||
if (GetToken(&tk) != INTEGER) {
|
||||
lexerror("bad #line syntax");
|
||||
SkipToNewLine();
|
||||
}
|
||||
else
|
||||
do_line((unsigned int)tk.tk_ival);
|
||||
break;
|
||||
case K_ERROR: /* "error" */
|
||||
do_error();
|
||||
break;
|
||||
case K_PRAGMA: /* "pragma" */
|
||||
do_pragma();
|
||||
break;
|
||||
case K_UNDEF: /* "undef" */
|
||||
do_undef((struct idf *) 0);
|
||||
break;
|
||||
default:
|
||||
/* invalid word seen after the '#' */
|
||||
lexerror("%s: unknown control", tk.tk_idf->id_text);
|
||||
SkipToNewLine();
|
||||
}
|
||||
break;
|
||||
case INTEGER: /* # <integer> [<filespecifier>]? */
|
||||
do_line((unsigned int)tk.tk_ival);
|
||||
break;
|
||||
case EOI: /* only `#' on this line: do nothing, ignore */
|
||||
break;
|
||||
default: /* invalid token following '#' */
|
||||
lexerror("illegal # line");
|
||||
SkipToNewLine();
|
||||
}
|
||||
EoiForNewline = 0;
|
||||
}
|
||||
|
||||
#ifdef LINT
|
||||
int lint_skip_comment;
|
||||
#endif
|
||||
|
||||
void
|
||||
skip_block(to_endif)
|
||||
int to_endif;
|
||||
{
|
||||
/* skip_block() skips the input from
|
||||
1) a false #if, #ifdef, #ifndef or #elif until the
|
||||
corresponding #elif (resulting in true), #else or
|
||||
#endif is read.
|
||||
2) a #else corresponding to a true #if, #ifdef,
|
||||
#ifndef or #elif until the corresponding #endif is
|
||||
seen.
|
||||
*/
|
||||
register int ch;
|
||||
register int skiplevel = nestlevel; /* current nesting level */
|
||||
struct token tk;
|
||||
int toknum;
|
||||
|
||||
#ifdef LINT
|
||||
lint_skip_comment++;
|
||||
#endif
|
||||
NoUnstack++;
|
||||
for (;;) {
|
||||
ch = GetChar(); /* read first character after newline */
|
||||
while (class(ch) == STSKIP)
|
||||
ch = GetChar();
|
||||
if (ch != '#') {
|
||||
if (ch == EOI) {
|
||||
NoUnstack--;
|
||||
#ifdef LINT
|
||||
lint_skip_comment--;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
/* A possible '/' is not pushed back */
|
||||
if (ch == '/') {
|
||||
ch = GetChar();
|
||||
if (ch != '*') UnGetChar();
|
||||
else {
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
} else UnGetChar();
|
||||
SkipToNewLine();
|
||||
continue;
|
||||
}
|
||||
ReplaceMacros = 0;
|
||||
toknum = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
if (toknum != IDENTIFIER) {
|
||||
if (toknum != INTEGER) {
|
||||
lexerror("illegal # line");
|
||||
}
|
||||
SkipToNewLine();
|
||||
continue;
|
||||
}
|
||||
/* an IDENTIFIER: look for #if, #ifdef and #ifndef
|
||||
without interpreting them.
|
||||
Interpret #else, #elif and #endif if they occur
|
||||
on the same level.
|
||||
*/
|
||||
switch(tk.tk_idf->id_resmac) {
|
||||
default:
|
||||
case K_UNKNOWN:
|
||||
/* invalid word seen after the '#' */
|
||||
lexwarning("%s: unknown control", tk.tk_idf->id_text);
|
||||
/* fallthrough */
|
||||
case K_DEFINE:
|
||||
case K_ERROR:
|
||||
case K_INCLUDE:
|
||||
case K_LINE:
|
||||
case K_PRAGMA:
|
||||
case K_UNDEF:
|
||||
case K_FILE:
|
||||
SkipToNewLine();
|
||||
break;
|
||||
case K_IF:
|
||||
case K_IFDEF:
|
||||
case K_IFNDEF:
|
||||
push_if();
|
||||
SkipToNewLine();
|
||||
break;
|
||||
case K_ELIF:
|
||||
if (ifstack[nestlevel])
|
||||
lexerror("#elif after #else");
|
||||
if (!to_endif && nestlevel == skiplevel) {
|
||||
nestlevel--;
|
||||
push_if();
|
||||
if (ifexpr()) {
|
||||
NoUnstack--;
|
||||
#ifdef LINT
|
||||
lint_skip_comment--;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
else SkipToNewLine(); /* otherwise done in ifexpr() */
|
||||
break;
|
||||
case K_ELSE:
|
||||
if (ifstack[nestlevel])
|
||||
lexerror("#else after #else");
|
||||
++(ifstack[nestlevel]);
|
||||
if (!to_endif && nestlevel == skiplevel) {
|
||||
if (SkipToNewLine()) {
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #else");
|
||||
}
|
||||
NoUnstack--;
|
||||
#ifdef LINT
|
||||
lint_skip_comment--;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else SkipToNewLine();
|
||||
break;
|
||||
case K_ENDIF:
|
||||
assert(nestlevel > nestlow);
|
||||
if (nestlevel == skiplevel) {
|
||||
if (SkipToNewLine()) {
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #endif");
|
||||
}
|
||||
nestlevel--;
|
||||
NoUnstack--;
|
||||
#ifdef LINT
|
||||
lint_skip_comment--;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else SkipToNewLine();
|
||||
nestlevel--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ifexpr()
|
||||
{
|
||||
/* ifexpr() returns whether the restricted constant
|
||||
expression following #if or #elif evaluates to true. This
|
||||
is done by calling the LLgen generated subparser for
|
||||
constant expressions. The result of this expression will
|
||||
be given in the extern long variable "ifval".
|
||||
*/
|
||||
extern arith ifval;
|
||||
int errors = err_occurred;
|
||||
|
||||
ifval = (arith)0;
|
||||
AccDefined = 1;
|
||||
UnknownIdIsZero = 1;
|
||||
PushLex(); /* NEW parser */
|
||||
If_expr(); /* invoke constant expression parser */
|
||||
PopLex(); /* OLD parser */
|
||||
AccDefined = 0;
|
||||
UnknownIdIsZero = 0;
|
||||
return (errors == err_occurred) && (ifval != (arith)0);
|
||||
}
|
||||
|
||||
do_include()
|
||||
{
|
||||
/* do_include() performs the inclusion of a file.
|
||||
*/
|
||||
char *filenm;
|
||||
char *result;
|
||||
int tok;
|
||||
struct token tk;
|
||||
|
||||
AccFileSpecifier = 1;
|
||||
if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
|
||||
filenm = tk.tk_bts;
|
||||
else {
|
||||
lexerror("bad include syntax");
|
||||
filenm = (char *)0;
|
||||
}
|
||||
AccFileSpecifier = 0;
|
||||
if (SkipToNewLine()) {
|
||||
lexerror("bad include syntax");
|
||||
}
|
||||
inctable[0] = WorkingDir;
|
||||
if (filenm) {
|
||||
if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
|
||||
lexerror("cannot open include file \"%s\"", filenm);
|
||||
add_dependency(filenm);
|
||||
free(filenm);
|
||||
}
|
||||
else {
|
||||
add_dependency(result);
|
||||
WorkingDir = getwdir(result);
|
||||
File_Inserted = 1;
|
||||
FileName = result;
|
||||
LineNumber = 0;
|
||||
nestlow = nestlevel;
|
||||
#ifdef DBSYMTAB
|
||||
IncludeLevel++;
|
||||
if (options['g']) {
|
||||
C_ms_stb_cst(FileName, N_BINCL, 0, (arith) 0);
|
||||
}
|
||||
#endif /* DBSYMTAB */
|
||||
if (result != filenm) free(filenm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_define()
|
||||
{
|
||||
/* do_define() interprets a #define control line.
|
||||
*/
|
||||
struct idf *id; /* the #defined identifier's descriptor */
|
||||
int nformals = -1; /* keep track of the number of formals */
|
||||
char *formals[NPARAMS]; /* pointers to the names of the formals */
|
||||
char parbuf[PARBUFSIZE]; /* names of formals */
|
||||
char *repl_text; /* start of the replacement text */
|
||||
int length; /* length of the replacement text */
|
||||
register ch;
|
||||
char *get_text();
|
||||
|
||||
/* read the #defined macro's name */
|
||||
if (!(id = GetIdentifier(1))) {
|
||||
lexerror("illegal #define line");
|
||||
return;
|
||||
}
|
||||
/* there is a formal parameter list if the identifier is
|
||||
followed immediately by a '('.
|
||||
*/
|
||||
ch = GetChar();
|
||||
if (ch == '(') {
|
||||
if ((nformals = getparams(formals, parbuf)) == -1) {
|
||||
SkipToNewLine();
|
||||
return; /* an error occurred */
|
||||
}
|
||||
ch = GetChar();
|
||||
}
|
||||
/* read the replacement text if there is any */
|
||||
ch = skipspaces(ch,0); /* find first character of the text */
|
||||
assert(ch != EOI);
|
||||
/* UnGetChar() is not right when replacement starts with a '/' */
|
||||
ChPushBack(ch);
|
||||
repl_text = get_text((nformals > 0) ? formals : 0, &length);
|
||||
macro_def(id, repl_text, nformals, length, NOFLAG);
|
||||
LineNumber++;
|
||||
}
|
||||
|
||||
push_if()
|
||||
{
|
||||
if (nestlevel >= IFDEPTH)
|
||||
fatal("too many nested #if/#ifdef/#ifndef");
|
||||
else
|
||||
ifstack[++nestlevel] = 0;
|
||||
}
|
||||
|
||||
do_elif()
|
||||
{
|
||||
if (nestlevel <= nestlow) {
|
||||
lexerror("#elif without corresponding #if");
|
||||
SkipToNewLine();
|
||||
}
|
||||
else { /* restart at this level as if a #if is detected. */
|
||||
if (ifstack[nestlevel]) {
|
||||
lexerror("#elif after #else");
|
||||
SkipToNewLine();
|
||||
}
|
||||
nestlevel--;
|
||||
push_if();
|
||||
skip_block(1);
|
||||
}
|
||||
}
|
||||
|
||||
do_else()
|
||||
{
|
||||
if (SkipToNewLine())
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #else");
|
||||
if (nestlevel <= nestlow)
|
||||
lexerror("#else without corresponding #if");
|
||||
else { /* mark this level as else-d */
|
||||
if (ifstack[nestlevel]) {
|
||||
lexerror("#else after #else");
|
||||
}
|
||||
++(ifstack[nestlevel]);
|
||||
skip_block(1);
|
||||
}
|
||||
}
|
||||
|
||||
do_endif()
|
||||
{
|
||||
if (SkipToNewLine()) {
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #endif");
|
||||
}
|
||||
if (nestlevel <= nestlow) {
|
||||
lexerror("#endif without corresponding #if");
|
||||
}
|
||||
else nestlevel--;
|
||||
}
|
||||
|
||||
do_if()
|
||||
{
|
||||
push_if();
|
||||
if (!ifexpr()) /* a false #if/#elif expression */
|
||||
skip_block(0);
|
||||
}
|
||||
|
||||
do_ifdef(how)
|
||||
{
|
||||
register struct idf *id;
|
||||
|
||||
/* how == 1 : ifdef; how == 0 : ifndef
|
||||
*/
|
||||
push_if();
|
||||
if (!(id = GetIdentifier(1)))
|
||||
lexerror("illegal #ifdef construction");
|
||||
else if (SkipToNewLine())
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #%s <identifier>",
|
||||
how ? "ifdef" : "ifndef");
|
||||
|
||||
/* The next test is a shorthand for:
|
||||
(how && !id->id_macro) || (!how && id->id_macro)
|
||||
*/
|
||||
if (how ^ (id && id->id_macro != 0))
|
||||
skip_block(0);
|
||||
}
|
||||
|
||||
/* argidf != NULL when the undef came from a -U option */
|
||||
do_undef(argidf)
|
||||
struct idf *argidf;
|
||||
{
|
||||
register struct idf *id = argidf;
|
||||
|
||||
/* Forget a macro definition. */
|
||||
if (id || (id = GetIdentifier(1))) {
|
||||
if (id->id_macro) { /* forget the macro */
|
||||
if (id->id_macro->mc_flag & NOUNDEF) {
|
||||
lexerror("it is not allowed to undef %s", id->id_text);
|
||||
} else {
|
||||
free(id->id_macro->mc_text);
|
||||
free_macro(id->id_macro);
|
||||
id->id_macro = (struct macro *) 0;
|
||||
}
|
||||
} /* else: don't complain */
|
||||
if (!argidf) {
|
||||
if (SkipToNewLine())
|
||||
if (!options['o'])
|
||||
lexstrict("garbage following #undef");
|
||||
}
|
||||
}
|
||||
else
|
||||
lexerror("illegal #undef construction");
|
||||
}
|
||||
|
||||
do_error()
|
||||
{
|
||||
int len;
|
||||
char *get_text();
|
||||
char *bp = get_text((char **) 0, &len);
|
||||
|
||||
lexerror("user error: %s", bp);
|
||||
free(bp);
|
||||
LineNumber++;
|
||||
}
|
||||
|
||||
int
|
||||
getparams(buf, parbuf)
|
||||
char *buf[];
|
||||
char parbuf[];
|
||||
{
|
||||
/* getparams() reads the formal parameter list of a macro
|
||||
definition.
|
||||
The number of parameters is returned.
|
||||
As a formal parameter list is expected when calling this
|
||||
routine, -1 is returned if an error is detected, for
|
||||
example:
|
||||
#define one(1), where 1 is not an identifier.
|
||||
Note that the '(' has already been eaten.
|
||||
The names of the formal parameters are stored into parbuf.
|
||||
*/
|
||||
register char **pbuf = &buf[0];
|
||||
register int c;
|
||||
register char *ptr = &parbuf[0];
|
||||
register char **pbuf2;
|
||||
|
||||
c = GetChar();
|
||||
c = skipspaces(c,0);
|
||||
if (c == ')') { /* no parameters: #define name() */
|
||||
*pbuf = (char *) 0;
|
||||
return 0;
|
||||
}
|
||||
for (;;) { /* eat the formal parameter list */
|
||||
if (class(c) != STIDF && class(c) != STELL) {
|
||||
lexerror("#define: bad formal parameter");
|
||||
return -1;
|
||||
}
|
||||
*pbuf = ptr; /* name of the formal */
|
||||
*ptr++ = c;
|
||||
if (ptr >= &parbuf[PARBUFSIZE])
|
||||
fatal("formal parameter buffer overflow");
|
||||
do { /* eat the identifier name */
|
||||
c = GetChar();
|
||||
*ptr++ = c;
|
||||
if (ptr >= &parbuf[PARBUFSIZE])
|
||||
fatal("formal parameter buffer overflow");
|
||||
} while (in_idf(c));
|
||||
*(ptr - 1) = '\0'; /* mark end of the name */
|
||||
|
||||
/* Check if this formal parameter is already used.
|
||||
Usually, macros do not have many parameters, so ...
|
||||
*/
|
||||
for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
|
||||
if (!strcmp(*pbuf2, *pbuf)) {
|
||||
lexerror("formal parameter \"%s\" already used",
|
||||
*pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
pbuf++;
|
||||
c = skipspaces(c,0);
|
||||
if (c == ')') { /* end of the formal parameter list */
|
||||
*pbuf = (char *) 0;
|
||||
return pbuf - buf;
|
||||
}
|
||||
if (c != ',') {
|
||||
lexerror("#define: bad formal parameter list");
|
||||
return -1;
|
||||
}
|
||||
c = GetChar();
|
||||
c = skipspaces(c,0);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
void
|
||||
macro_def(id, text, nformals, length, flags)
|
||||
register struct idf *id;
|
||||
char *text;
|
||||
{
|
||||
register struct macro *newdef = id->id_macro;
|
||||
|
||||
/* macro_def() puts the contents and information of a macro
|
||||
definition into a structure and stores it into the symbol
|
||||
table entry belonging to the name of the macro.
|
||||
An error is given if there was already a definition
|
||||
*/
|
||||
if (newdef) { /* is there a redefinition? */
|
||||
if (newdef->mc_flag & NOUNDEF) {
|
||||
lexerror("it is not allowed to redefine %s", id->id_text);
|
||||
} else if (!macroeq(newdef->mc_text, text))
|
||||
lexerror("illegal redefine of \"%s\"", id->id_text);
|
||||
free(text);
|
||||
return;
|
||||
}
|
||||
id->id_macro = newdef = new_macro();
|
||||
newdef->mc_text = text; /* replacement text */
|
||||
newdef->mc_nps = nformals; /* nr of formals */
|
||||
newdef->mc_length = length; /* length of repl. text */
|
||||
newdef->mc_flag = flags; /* special flags */
|
||||
}
|
||||
|
||||
int
|
||||
find_name(nm, index)
|
||||
char *nm, *index[];
|
||||
{
|
||||
/* find_name() returns the index of "nm" in the namelist
|
||||
"index" if it can be found there. 0 is returned if it is
|
||||
not there.
|
||||
*/
|
||||
register char **ip = &index[0];
|
||||
|
||||
while (*ip)
|
||||
if (strcmp(nm, *ip++) == 0)
|
||||
return ip - &index[0];
|
||||
/* arrived here, nm is not in the name list. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
|
||||
|
||||
char *
|
||||
get_text(formals, length)
|
||||
char *formals[];
|
||||
int *length;
|
||||
{
|
||||
/* get_text() copies the replacement text of a macro
|
||||
definition with zero, one or more parameters, thereby
|
||||
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
|
||||
itself because the copied text will contain fewer or the
|
||||
same amount of characters. The length of the replacement
|
||||
text is returned.
|
||||
|
||||
Implementation:
|
||||
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;
|
||||
struct repl repls;
|
||||
register struct repl *repl = &repls;
|
||||
int blank = 0;
|
||||
|
||||
c = GetChar();
|
||||
|
||||
repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
|
||||
*repl->r_ptr = '\0';
|
||||
while ((c != EOI) && (class(c) != STNL)) {
|
||||
if (BLANK(c)) {
|
||||
blank++;
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\'' || c == '"') {
|
||||
register int delim = c;
|
||||
|
||||
if (blank) {
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
do {
|
||||
add2repl(repl, c);
|
||||
if (c == '\\') add2repl(repl, GetChar());
|
||||
c = GetChar();
|
||||
} while (c != delim && c != EOI && class(c) != STNL);
|
||||
if (c == EOI || class(c) == STNL) {
|
||||
lexstrict("unclosed opening %c", delim);
|
||||
break;
|
||||
}
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
} else if (c == '/') {
|
||||
c = GetChar();
|
||||
if (c == '*') {
|
||||
skipcomment();
|
||||
blank++;
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
if (blank) {
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
add2repl(repl, '/');
|
||||
} else if (formals
|
||||
&& (class(c) == STIDF || class(c) == STELL)) {
|
||||
char id_buf[IDFSIZE + 1];
|
||||
register char *idp = id_buf;
|
||||
int n;
|
||||
|
||||
/* read identifier: it may be a formal parameter */
|
||||
*idp++ = c;
|
||||
do {
|
||||
c = GetChar();
|
||||
if (idp <= &id_buf[IDFSIZE])
|
||||
*idp++ = c;
|
||||
} while (in_idf(c));
|
||||
*--idp = '\0';
|
||||
|
||||
if (blank) {
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
/* construct the formal parameter mark or identifier */
|
||||
if (n = find_name(id_buf, formals))
|
||||
add2repl(repl, FORMALP | (char) n);
|
||||
else {
|
||||
idp = id_buf;
|
||||
while (*idp) add2repl(repl, *idp++);
|
||||
}
|
||||
} else if (class(c) == STNUM) {
|
||||
if (blank) {
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
add2repl(repl, c);
|
||||
if (c == '.') {
|
||||
c = GetChar();
|
||||
if (class(c) != STNUM) {
|
||||
continue;
|
||||
}
|
||||
add2repl(repl, c);
|
||||
}
|
||||
c = GetChar();
|
||||
while(in_idf(c) || c == '.') {
|
||||
add2repl(repl, c);
|
||||
if((c = GetChar()) == 'e' || c == 'E') {
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
if (c == '+' || c == '-') {
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (blank) {
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
}
|
||||
}
|
||||
*length = repl->r_ptr - repl->r_text;
|
||||
return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text +1));
|
||||
}
|
||||
|
||||
/* 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
|
||||
blanks (spaces and tabs).
|
||||
*/
|
||||
macroeq(s, t)
|
||||
register char *s, *t;
|
||||
{
|
||||
|
||||
/* skip leading spaces */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
/* first non-blank encountered in both strings */
|
||||
/* The actual comparison loop: */
|
||||
while (*s && *s == *t)
|
||||
s++, t++;
|
||||
/* two cases are possible when arrived here: */
|
||||
if (*s == '\0') { /* *s == '\0' */
|
||||
while (BLANK(*t)) t++;
|
||||
return *t == '\0';
|
||||
}
|
||||
else { /* *s != *t */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
return (*s == '\0') && (*t == '\0');
|
||||
}
|
||||
}
|
||||
#else /* NOPP */
|
||||
|
||||
struct idf *
|
||||
GetIdentifier(skiponerr)
|
||||
int skiponerr; /* skip the rest of the line on error */
|
||||
struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */
|
||||
{
|
||||
/* returns a pointer to the descriptor of the identifier that is
|
||||
read from the input stream. When the input does not contain
|
||||
|
@ -807,9 +35,11 @@ GetIdentifier(skiponerr)
|
|||
struct token tk;
|
||||
|
||||
tok = GetToken(&tk);
|
||||
if (tok != IDENTIFIER) {
|
||||
if (skiponerr && tok != EOI) SkipToNewLine();
|
||||
return (struct idf *)0;
|
||||
if (tok != IDENTIFIER)
|
||||
{
|
||||
if (skiponerr && tok != EOI)
|
||||
SkipToNewLine();
|
||||
return (struct idf*)0;
|
||||
}
|
||||
return tk.tk_idf;
|
||||
}
|
||||
|
@ -820,14 +50,18 @@ domacro()
|
|||
struct token tk;
|
||||
|
||||
EoiForNewline = 1;
|
||||
if ((tok = GetToken(&tk)) == IDENTIFIER) {
|
||||
if (! strcmp(tk.tk_idf->id_text, "pragma")) {
|
||||
if ((tok = GetToken(&tk)) == IDENTIFIER)
|
||||
{
|
||||
if (!strcmp(tk.tk_idf->id_text, "pragma"))
|
||||
{
|
||||
do_pragma();
|
||||
EoiForNewline = 0;
|
||||
return;
|
||||
}
|
||||
} else if (tok == INTEGER) {
|
||||
do_line((unsigned int) tk.tk_ival);
|
||||
}
|
||||
else if (tok == INTEGER)
|
||||
{
|
||||
do_line((unsigned int)tk.tk_ival);
|
||||
EoiForNewline = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -835,24 +69,24 @@ domacro()
|
|||
EoiForNewline = 0;
|
||||
SkipToNewLine();
|
||||
}
|
||||
#endif /* NOPP */
|
||||
|
||||
|
||||
do_line(l)
|
||||
unsigned int l;
|
||||
do_line(l) unsigned int l;
|
||||
{
|
||||
struct token tk;
|
||||
int t = GetToken(&tk);
|
||||
|
||||
if (t != EOI) SkipToNewLine();
|
||||
if (t != EOI)
|
||||
SkipToNewLine();
|
||||
LineNumber = l; /* the number of the next input line */
|
||||
if (t == STRING) { /* is there a filespecifier? */
|
||||
/*
|
||||
if (t == STRING)
|
||||
{ /* is there a filespecifier? */
|
||||
/*
|
||||
* Do not attempt to free the old string, since it might
|
||||
* be used in a def structure.
|
||||
*/
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g'] && strcmp(FileName, tk.tk_bts) != 0) {
|
||||
if (options['g'] && strcmp(FileName, tk.tk_bts) != 0)
|
||||
{
|
||||
C_ms_std(tk.tk_bts, N_SOL, 0);
|
||||
}
|
||||
#endif /* DBSYMTAB */
|
||||
|
|
|
@ -106,15 +106,6 @@ dumpidf(idf, opt)
|
|||
|
||||
if (!idf)
|
||||
return;
|
||||
#ifndef NOPP
|
||||
if ((opt&1) && idf->id_macro) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
print(" macro");
|
||||
}
|
||||
#endif /* NOPP */
|
||||
if ((opt&2) && idf->id_reserved) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
#include "parameters.h"
|
||||
|
||||
struct id_u {
|
||||
#ifndef NOPP
|
||||
struct macro *idd_macro;
|
||||
int idd_resmac; /* if nonzero: keyword of macroproc. */
|
||||
#endif /* NOPP */
|
||||
int idd_reserved; /* non-zero for reserved words */
|
||||
char *idd_file; /* file containing the occurrence */
|
||||
unsigned int idd_line; /* line number of the occurrence */
|
||||
|
@ -36,14 +32,5 @@ struct id_u {
|
|||
|
||||
#include <idf_pkg.spec>
|
||||
|
||||
#ifndef NOPP
|
||||
struct dependency {
|
||||
struct dependency *next;
|
||||
struct idf *dep_idf;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "dependency" 10 */
|
||||
#endif /* NOPP */
|
||||
|
||||
extern int level;
|
||||
extern struct idf *gen_idf();
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* PREPROCESSOR: INITIALIZATION ROUTINES */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "parameters.h"
|
||||
|
||||
#ifndef NOPP
|
||||
#include <system.h>
|
||||
#include <alloc.h>
|
||||
#include <time.h>
|
||||
#include "idf.h"
|
||||
#include "class.h"
|
||||
#include "macro.h"
|
||||
|
||||
extern char *sprint();
|
||||
|
||||
struct mkey {
|
||||
char *mk_reserved;
|
||||
int mk_key;
|
||||
} mkey[] = {
|
||||
{"define", K_DEFINE},
|
||||
{"elif", K_ELIF},
|
||||
{"else", K_ELSE},
|
||||
{"endif", K_ENDIF},
|
||||
{"error", K_ERROR},
|
||||
{"if", K_IF},
|
||||
{"ifdef", K_IFDEF},
|
||||
{"ifndef", K_IFNDEF},
|
||||
{"include", K_INCLUDE},
|
||||
{"line", K_LINE},
|
||||
{"pragma", K_PRAGMA},
|
||||
{"undef", K_UNDEF},
|
||||
{0, K_UNKNOWN}
|
||||
};
|
||||
|
||||
init_pp()
|
||||
{
|
||||
static char *months[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
time_t clock;
|
||||
static char dbuf[30];
|
||||
static char tbuf[30];
|
||||
struct tm *tp;
|
||||
|
||||
/* Initialise the control line keywords (if, include, define, etc)
|
||||
Although the lexical analyzer treats them as identifiers, the
|
||||
control line handler can recognize them as keywords by the
|
||||
id_resmac field of the identifier.
|
||||
*/
|
||||
{
|
||||
register struct mkey *mk = &mkey[0];
|
||||
|
||||
while (mk->mk_reserved) {
|
||||
register struct idf *idf = str2idf(mk->mk_reserved, 0);
|
||||
|
||||
if (idf->id_resmac)
|
||||
fatal("maximum identifier length insufficient");
|
||||
idf->id_resmac = mk->mk_key;
|
||||
mk++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize __LINE__, __FILE__, __DATE__, __TIME__,
|
||||
and __STDC__ macro definitions.
|
||||
*/
|
||||
clock = time(NULL);
|
||||
tp = localtime(&clock);
|
||||
|
||||
/* __DATE__ */
|
||||
sprint(dbuf, "\"%s %02d %d\"", months[tp->tm_mon],
|
||||
tp->tm_mday, tp->tm_year+1900);
|
||||
if (tp->tm_mday < 10) dbuf[5] = ' '; /* hack */
|
||||
macro_def(str2idf("__DATE__", 0), dbuf, -1, strlen(dbuf), NOUNDEF);
|
||||
|
||||
/* __TIME__ */
|
||||
sprint(tbuf, "\"%02d:%02d:%02d\"", tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||
macro_def(str2idf("__TIME__", 0), tbuf, -1, strlen(tbuf), NOUNDEF);
|
||||
|
||||
/* __LINE__ */
|
||||
macro_def(str2idf("__LINE__", 0), "0", -1, 1, NOUNDEF | FUNC);
|
||||
|
||||
/* __FILE__ */
|
||||
macro_def(str2idf("__FILE__", 0), "", -1, 1, NOUNDEF | FUNC);
|
||||
|
||||
/* __STDC__ */
|
||||
macro_def(str2idf("__STDC__", 0), "1", -1, 1, NOUNDEF);
|
||||
|
||||
/* defined(??) */
|
||||
macro_def(str2idf("defined", 0), "", 1, 1, NOUNDEF | FUNC);
|
||||
}
|
||||
#endif /* NOPP */
|
|
@ -18,50 +18,10 @@ struct file_info finfo;
|
|||
#include <inp_pkg.body>
|
||||
#include <alloc.h>
|
||||
|
||||
#ifndef NOPP
|
||||
#ifdef DBSYMTAB
|
||||
#include <stb.h>
|
||||
#include <em.h>
|
||||
extern int IncludeLevel;
|
||||
extern char options[];
|
||||
#endif
|
||||
|
||||
char *
|
||||
getwdir(fn)
|
||||
register char *fn;
|
||||
{
|
||||
register char *p;
|
||||
char *strrchr();
|
||||
|
||||
p = strrchr(fn, '/');
|
||||
while (p && *(p + 1) == '\0') { /* remove trailing /'s */
|
||||
*p = '\0';
|
||||
p = strrchr(fn, '/');
|
||||
}
|
||||
|
||||
if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
|
||||
return "";
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
fn = Salloc(fn,(unsigned) (p - &fn[0] + 1));
|
||||
*p = '/';
|
||||
return fn;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int InputLevel;
|
||||
extern int nestlevel;
|
||||
#endif /* NOPP */
|
||||
|
||||
int NoUnstack;
|
||||
|
||||
AtEoIT()
|
||||
{
|
||||
#ifndef NOPP
|
||||
InputLevel--;
|
||||
unstackrepl();
|
||||
#endif /* NOPP */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -69,22 +29,6 @@ extern char *source;
|
|||
|
||||
AtEoIF()
|
||||
{
|
||||
#ifndef NOPP
|
||||
if (nestlevel != nestlow) lexwarning("missing #endif");
|
||||
else
|
||||
#endif /* NOPP */
|
||||
if (NoUnstack) lexerror("unexpected EOF");
|
||||
#ifndef NOPP
|
||||
nestlevel = nestlow;
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g'] && IncludeLevel > 0) {
|
||||
C_ms_stb_cst(FileName, N_EINCL, 0, (arith) 0);
|
||||
}
|
||||
IncludeLevel--;
|
||||
#endif
|
||||
/* We don't free WorkingDir and FileName here because the rest of the
|
||||
* compiler may be holding pointers to them for displaying error messages.
|
||||
*/
|
||||
#endif /* NOPP */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -6,47 +6,3 @@
|
|||
/* PREPROCESSOR: DEFINITION OF MACRO DESCRIPTOR */
|
||||
|
||||
#include "parameters.h"
|
||||
|
||||
#ifndef NOPP
|
||||
/* The flags of the mc_flag field of the macro structure. Note that
|
||||
these flags can be set simultaneously.
|
||||
*/
|
||||
#define NOFLAG 0 /* no special flags */
|
||||
#define FUNC 0x1 /* function attached */
|
||||
#define NOUNDEF 0x2 /* reserved macro */
|
||||
#define NOREPLACE 0x4 /* prevent recursion */
|
||||
|
||||
#define FORMALP 0200 /* mask for creating macro formal parameter */
|
||||
|
||||
/* The macro descriptor is very simple, except the fact that the
|
||||
mc_text, which points to the replacement text, contains the
|
||||
non-ascii characters \201, \202, etc, indicating the position of a
|
||||
formal parameter in this text.
|
||||
*/
|
||||
struct macro {
|
||||
struct macro *next;
|
||||
char * mc_text; /* the replacement text */
|
||||
int mc_nps; /* number of formal parameters */
|
||||
int mc_length; /* length of replacement text */
|
||||
char mc_flag; /* marking this macro */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "macro" 20 */
|
||||
|
||||
/* `token' numbers of keywords of command-line processor
|
||||
*/
|
||||
#define K_UNKNOWN 0
|
||||
#define K_DEFINE 1
|
||||
#define K_ELIF 2
|
||||
#define K_ELSE 3
|
||||
#define K_ENDIF 4
|
||||
#define K_ERROR 5
|
||||
#define K_IF 6
|
||||
#define K_IFDEF 7
|
||||
#define K_IFNDEF 8
|
||||
#define K_INCLUDE 9
|
||||
#define K_LINE 10
|
||||
#define K_PRAGMA 11
|
||||
#define K_UNDEF 12
|
||||
#define K_FILE 100 /* for dependency generator */
|
||||
#endif /* NOPP */
|
||||
|
|
|
@ -29,19 +29,6 @@ extern struct tokenname tkidf[];
|
|||
extern char *symbol2str();
|
||||
extern char options[128];
|
||||
|
||||
#ifndef NOPP
|
||||
int inc_pos = 1; /* place where next -I goes */
|
||||
int inc_total = 0;
|
||||
int inc_max;
|
||||
char **inctable;
|
||||
|
||||
extern int do_dependencies;
|
||||
extern char *dep_file;
|
||||
static File *dep_fd = STDOUT;
|
||||
|
||||
extern char *getwdir();
|
||||
#endif /* NOPP */
|
||||
|
||||
struct sp_id special_ids[] = {
|
||||
{"__setjmp", SP_SETJMP}, /* non-local goto's are registered */
|
||||
{0, 0}
|
||||
|
@ -74,10 +61,6 @@ int
|
|||
union_align = AL_UNION;
|
||||
#endif /* NOCROSS */
|
||||
|
||||
#ifndef NOPP
|
||||
arith ifval; /* ifval will contain the result of the #if expression */
|
||||
#endif /* NOPP */
|
||||
|
||||
char *prog_name;
|
||||
|
||||
main(argc, argv)
|
||||
|
@ -86,17 +69,6 @@ main(argc, argv)
|
|||
/* parse and interpret the command line options */
|
||||
prog_name = argv[0];
|
||||
|
||||
#ifndef NOPP
|
||||
inctable = (char **) Malloc(10 * sizeof(char *));
|
||||
inctable[0] = "";
|
||||
inctable[1] = 0;
|
||||
inctable[2] = 0;
|
||||
inc_total = 3;
|
||||
inc_max = 10;
|
||||
|
||||
init_pp(); /* initialise the preprocessor macros */
|
||||
#endif /* NOPP */
|
||||
|
||||
/* Note: source file "-" indicates that the source is supplied
|
||||
as standard input. This is only allowed if INP_READ_IN_ONE is
|
||||
not defined!
|
||||
|
@ -122,83 +94,10 @@ main(argc, argv)
|
|||
if (options['m']) Info();
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef NOPP
|
||||
if (do_dependencies) {
|
||||
extern char *source;
|
||||
|
||||
list_dependencies(source);
|
||||
}
|
||||
#endif
|
||||
sys_stop(err_occurred ? S_EXIT : S_END);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
|
||||
struct dependency *file_head;
|
||||
extern char *strrchr();
|
||||
|
||||
list_dependencies(source)
|
||||
char *source;
|
||||
{
|
||||
register struct dependency *p = file_head;
|
||||
|
||||
if (source) {
|
||||
register char *s = strrchr(source, '.');
|
||||
|
||||
if (s && *(s+1)) {
|
||||
s++;
|
||||
*s++ = 'o';
|
||||
*s = '\0';
|
||||
/* the source may be in another directory than the
|
||||
* object generated, so don't include the pathname
|
||||
* leading to it.
|
||||
*/
|
||||
if (s = strrchr(source, '/')) {
|
||||
source = s + 1;
|
||||
}
|
||||
}
|
||||
else source = 0;
|
||||
}
|
||||
if (dep_file && !sys_open(dep_file, OP_WRITE, &dep_fd)) {
|
||||
fatal("could not open %s", dep_file);
|
||||
}
|
||||
while (p) {
|
||||
dependency(p->dep_idf->id_text, source);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
add_dependency(s)
|
||||
char *s;
|
||||
{
|
||||
register struct idf *p = str2idf(s, 1);
|
||||
|
||||
if (! p->id_resmac) {
|
||||
register struct dependency *q = new_dependency();
|
||||
|
||||
p->id_resmac = K_FILE;
|
||||
q->dep_idf = p;
|
||||
q->next = file_head;
|
||||
file_head = q;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dependency(s, source)
|
||||
char *s, *source;
|
||||
{
|
||||
if (options['i'] && !strncmp(s, "/usr/include/", 13)) {
|
||||
return;
|
||||
}
|
||||
if (options['m'] && source) {
|
||||
fprint(dep_fd, "%s: %s\n", source, s);
|
||||
}
|
||||
else fprint(dep_fd, "%s\n", s);
|
||||
}
|
||||
|
||||
#endif /* NOPP */
|
||||
|
||||
char *source = 0;
|
||||
|
||||
#ifdef GEN_NM_LIST
|
||||
|
@ -213,19 +112,10 @@ compile(argc, argv)
|
|||
register char *destination = 0;
|
||||
#endif /* LINT */
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef NOPP
|
||||
int pp_only = options['E'] || options['P'] || options['C'];
|
||||
#endif /* NOPP */
|
||||
#endif
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
#ifndef LINT
|
||||
#ifdef DEBUG
|
||||
#ifndef NOPP
|
||||
if (!pp_only)
|
||||
#endif /* NOPP */
|
||||
#endif
|
||||
fatal("%s: destination file not specified", prog_name);
|
||||
#endif /* LINT */
|
||||
|
@ -277,20 +167,7 @@ compile(argc, argv)
|
|||
: 0);
|
||||
#endif /* LINT */
|
||||
|
||||
#ifndef NOPP
|
||||
WorkingDir = getwdir(source);
|
||||
PushLex(); /* initialize lex machine */
|
||||
#else /* NOPP */
|
||||
GetToken(&ahead);
|
||||
#endif /* NOPP */
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef NOPP
|
||||
if (pp_only) /* run the preprocessor as if it is stand-alone */
|
||||
preprocess();
|
||||
else
|
||||
#endif /* NOPP */
|
||||
#endif /* DEBUG */
|
||||
{
|
||||
/* compile the source text */
|
||||
C_program();
|
||||
|
@ -311,9 +188,6 @@ compile(argc, argv)
|
|||
dumpidftab("end of main", options['f'] ? 7 : 0);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
#ifndef NOPP
|
||||
PopLex();
|
||||
#endif /* NOPP */
|
||||
}
|
||||
|
||||
init()
|
||||
|
@ -395,76 +269,6 @@ init_specials(si)
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef NOPP
|
||||
preprocess()
|
||||
{
|
||||
/* preprocess() is the "stand-alone" preprocessor which
|
||||
consecutively calls the lexical analyzer LLlex() to get
|
||||
the tokens and prints them in a suitable way.
|
||||
*/
|
||||
static unsigned int lastlineno = 0;
|
||||
static char *lastfilenm = "";
|
||||
|
||||
while (LLlex() != EOI) {
|
||||
if (lastlineno != dot.tk_line) {
|
||||
if (strcmp(lastfilenm, dot.tk_file) == 0) {
|
||||
if (dot.tk_line - lastlineno <= 1) {
|
||||
lastlineno++;
|
||||
print("\n");
|
||||
}
|
||||
else {
|
||||
lastlineno = dot.tk_line;
|
||||
if (!options['P'])
|
||||
print("\n#line %ld \"%s\"\n",
|
||||
lastlineno,
|
||||
lastfilenm
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastfilenm = dot.tk_file;
|
||||
lastlineno = dot.tk_line;
|
||||
if (!options['P'])
|
||||
print("\n#line %ld \"%s\"\n",
|
||||
lastlineno, lastfilenm);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strcmp(lastfilenm, dot.tk_file) != 0) {
|
||||
lastfilenm = dot.tk_file;
|
||||
if (!options['P'])
|
||||
print("\n#line %ld \"%s\"\n",
|
||||
lastlineno, lastfilenm);
|
||||
}
|
||||
switch (DOT) {
|
||||
case IDENTIFIER:
|
||||
case TYPE_IDENTIFIER:
|
||||
print("%s ", dot.tk_idf->id_text);
|
||||
break;
|
||||
case STRING:
|
||||
{
|
||||
char sbuf[1024]; /* a transient buffer */
|
||||
|
||||
print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len -
|
||||
1, sbuf));
|
||||
break;
|
||||
}
|
||||
case INTEGER:
|
||||
print("%ld ", dot.tk_ival);
|
||||
break;
|
||||
case FLOATING:
|
||||
print("%s ", dot.tk_fval);
|
||||
break;
|
||||
case EOI:
|
||||
case EOF:
|
||||
return;
|
||||
default: /* very expensive... */
|
||||
print("%s ", symbol2str(DOT));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* NOPP */
|
||||
|
||||
Info()
|
||||
{
|
||||
extern int cnt_string_cst, cnt_formal,
|
||||
|
|
|
@ -16,16 +16,6 @@
|
|||
#include "sizes.h"
|
||||
#include "align.h"
|
||||
|
||||
#ifndef NOPP
|
||||
extern char **inctable;
|
||||
extern int inc_pos;
|
||||
extern int inc_max;
|
||||
extern int inc_total;
|
||||
int do_dependencies = 0;
|
||||
char *dep_file = 0;
|
||||
|
||||
#endif /* NOPP */
|
||||
|
||||
char options[128]; /* one for every char */
|
||||
#ifdef LINT
|
||||
char loptions[128]; /* one for every char */
|
||||
|
@ -60,18 +50,6 @@ next_option: /* to allow combined one-char options */
|
|||
goto next_option;
|
||||
|
||||
#ifndef LINT
|
||||
#ifndef NOPP
|
||||
case 'A' : /* Amake dependency generation */
|
||||
do_dependencies = 1;
|
||||
if (*text) {
|
||||
dep_file = text;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
case 'm':
|
||||
options[opt] = 1;
|
||||
break;
|
||||
#endif /* NOPP */
|
||||
#endif /* LINT */
|
||||
#ifdef DBSYMTAB
|
||||
case 'g': /* symbol table for debugger */
|
||||
|
@ -110,64 +88,6 @@ next_option: /* to allow combined one-char options */
|
|||
goto next_option;
|
||||
#endif /* LINT */
|
||||
|
||||
#ifndef NOPP
|
||||
case 'D' : { /* -Dname : predefine name */
|
||||
register char *cp = text, *name, *mactext;
|
||||
unsigned maclen;
|
||||
|
||||
if (class(*cp) != STIDF && class(*cp) != STELL) {
|
||||
error("identifier missing in -D%s", text);
|
||||
break;
|
||||
}
|
||||
|
||||
name = cp;
|
||||
|
||||
while (*cp && in_idf(*cp)) {
|
||||
++cp;
|
||||
}
|
||||
|
||||
if (!*cp) { /* -Dname */
|
||||
maclen = 1;
|
||||
mactext = Salloc("1", 2);
|
||||
}
|
||||
else
|
||||
if (*cp == '=') { /* -Dname=text */
|
||||
*cp++ = '\0'; /* end of name */
|
||||
maclen = (unsigned) strlen(cp);
|
||||
mactext = Salloc(cp, maclen + 1);
|
||||
}
|
||||
else { /* -Dname?? */
|
||||
error("malformed option -D%s", text);
|
||||
break;
|
||||
}
|
||||
|
||||
macro_def(str2idf(name, 0), mactext, -1, (int)maclen, NOFLAG);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'I' : /* -Ipath : insert "path" into include list */
|
||||
if (*text) {
|
||||
int i;
|
||||
register char *new = text;
|
||||
|
||||
if (inc_total >= inc_max) {
|
||||
inctable = (char **)
|
||||
Realloc((char *)inctable,
|
||||
(unsigned)((inc_max+=10)*sizeof(char *)));
|
||||
}
|
||||
|
||||
for (i = inc_pos++; i < inc_total ; i++) {
|
||||
char *tmp = inctable[i];
|
||||
|
||||
inctable[i] = new;
|
||||
new = tmp;
|
||||
}
|
||||
inc_total++;
|
||||
}
|
||||
else inctable[inc_pos] = 0;
|
||||
break;
|
||||
#endif /* NOPP */
|
||||
|
||||
case 'M': /* maximum identifier length */
|
||||
idfsize = txt2int(&text);
|
||||
if (*text || idfsize <= 0)
|
||||
|
@ -197,12 +117,6 @@ next_option: /* to allow combined one-char options */
|
|||
break;
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
case 'U' : /* -Uname : undefine predefined */
|
||||
if (*text) do_undef(str2idf(text, 0));
|
||||
break;
|
||||
#endif /* NOPP */
|
||||
|
||||
#ifndef LINT
|
||||
#ifndef NOCROSS
|
||||
case 'V' : /* set object sizes and alignment requirements */
|
||||
|
|
|
@ -61,10 +61,6 @@
|
|||
#include "l_lint.h"
|
||||
#endif /* LINT */
|
||||
|
||||
#ifndef NOPP
|
||||
extern arith ifval;
|
||||
#endif /* NOPP */
|
||||
|
||||
extern error();
|
||||
}
|
||||
|
||||
|
@ -75,14 +71,6 @@ control_if_expression
|
|||
:
|
||||
constant_expression(&exprX)
|
||||
{
|
||||
#ifndef NOPP
|
||||
register struct expr *expr = exprX;
|
||||
if (expr->ex_flags & EX_SIZEOF)
|
||||
expr_error(expr,
|
||||
"sizeof not allowed in preprocessor");
|
||||
ifval = expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
#endif /* NOPP */
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -1,808 +0,0 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* M A C R O R E P L A C E M E N T */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "parameters.h"
|
||||
|
||||
#ifndef NOPP
|
||||
|
||||
#include <ack_string.h>
|
||||
#include <alloc.h>
|
||||
#include "idf.h"
|
||||
#include "input.h"
|
||||
#include "macro.h"
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "class.h"
|
||||
#include "replace.h"
|
||||
|
||||
extern struct idf *GetIdentifier();
|
||||
extern int InputLevel;
|
||||
struct repl *ReplaceList; /* list of currently active macros */
|
||||
|
||||
void macro2buffer();
|
||||
void getactuals();
|
||||
void expand_defined();
|
||||
|
||||
int
|
||||
replace(idf)
|
||||
register struct idf *idf;
|
||||
{
|
||||
/* replace is called by the lexical analyzer to perform
|
||||
macro replacement. The routine actualy functions as a
|
||||
higher interface to the real thing: expand_macro().
|
||||
*/
|
||||
struct repl *repl;
|
||||
|
||||
if (!(idf->id_macro)) return 0;
|
||||
if (idf->id_macro->mc_flag & NOREPLACE)
|
||||
return 0;
|
||||
repl = new_repl();
|
||||
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))
|
||||
return 0;
|
||||
InputLevel++;
|
||||
InsertText(repl->r_text, (int)(repl->r_ptr - repl->r_text));
|
||||
idf->id_macro->mc_flag |= NOREPLACE;
|
||||
repl->r_level = InputLevel;
|
||||
repl->next = ReplaceList;
|
||||
ReplaceList = repl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unstackrepl()
|
||||
{
|
||||
Unstacked++;
|
||||
}
|
||||
|
||||
freeargs(args)
|
||||
struct args *args;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* We must don't know how many parameters were specified, so be
|
||||
* prepared to free all NPARAMS parameters.
|
||||
* When an expvec is !0, the rawvec will also be !0.
|
||||
* When an expvec is 0, all remaining vectors will also be 0.
|
||||
*/
|
||||
for (i = 0; i < NPARAMS; i++) {
|
||||
if (args->a_expvec[i]) {
|
||||
free(args->a_expvec[i]);
|
||||
free(args->a_rawvec[i]);
|
||||
} else break;
|
||||
}
|
||||
free_args(args);
|
||||
}
|
||||
|
||||
EnableMacros()
|
||||
{
|
||||
register struct repl *r = ReplaceList, *prev = 0;
|
||||
|
||||
assert(Unstacked > 0);
|
||||
while(r) {
|
||||
struct repl *nxt = r->next;
|
||||
|
||||
if (r->r_level > InputLevel) {
|
||||
r->r_idf->id_macro->mc_flag &= ~NOREPLACE;
|
||||
if (!prev) ReplaceList = nxt;
|
||||
else prev->next = nxt;
|
||||
free(r->r_text);
|
||||
freeargs(r->r_args);
|
||||
free_repl(r);
|
||||
}
|
||||
else prev = r;
|
||||
r = nxt;
|
||||
}
|
||||
Unstacked = 0;
|
||||
}
|
||||
|
||||
expand_macro(repl, idf)
|
||||
register struct repl *repl;
|
||||
register struct idf *idf;
|
||||
{
|
||||
/* expand_macro() does the actual macro replacement.
|
||||
"idf" is a description of the identifier which
|
||||
caused the replacement.
|
||||
If the identifier represents a function-like macro
|
||||
call, the number of actual parameters is checked
|
||||
against the number of formal parameters. Note that
|
||||
in ANSI C the parameters are expanded first;
|
||||
this is done by calling getactuals().
|
||||
When the possible parameters are expanded, the replace-
|
||||
ment list associated with "idf" is expanded.
|
||||
expand_macro() returns 1 if the replacement succeeded
|
||||
and 0 if some error occurred.
|
||||
|
||||
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.
|
||||
*/
|
||||
register struct macro *mac = idf->id_macro;
|
||||
struct args *args = repl->r_args;
|
||||
register int ch;
|
||||
|
||||
if (mac->mc_nps != -1) { /* with parameter list */
|
||||
if (mac->mc_flag & FUNC) {
|
||||
/* the following assertion won't compile:
|
||||
assert(!strcmp("defined", idf->id_text));
|
||||
expand the assert macro by hand (??? dirty, temporary)
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
if (strcmp("defined", idf->id_text))
|
||||
crash("in %s, %u: assertion %s failed",
|
||||
__FILE__, __LINE__ - 2,
|
||||
"strcmp(\"defined\", idf->id_text)");
|
||||
#endif
|
||||
if (!AccDefined) return 0;
|
||||
expand_defined(repl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ch = GetChar();
|
||||
ch = skipspaces(ch,1);
|
||||
if (ch != '(') { /* no replacement if no () */
|
||||
ChPushBack(ch);
|
||||
return 0;
|
||||
} else
|
||||
getactuals(repl, idf);
|
||||
|
||||
}
|
||||
|
||||
if (mac->mc_flag & FUNC) /* this macro leads to special action */
|
||||
macro_func(idf);
|
||||
|
||||
macro2buffer(repl, idf, args);
|
||||
|
||||
/* According to the ANSI definition:
|
||||
|
||||
#define a +
|
||||
a+b; --> + + b ;
|
||||
|
||||
'a' must be substituded, but the result should be
|
||||
three tokens: + + ID. Therefore a token separator is
|
||||
inserted after the replacement.
|
||||
*/
|
||||
if (repl->r_text == repl->r_ptr || *(repl->r_ptr - 1) != TOKSEP) {
|
||||
add2repl(repl, TOKSEP);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
expand_defined(repl)
|
||||
register struct repl *repl;
|
||||
{
|
||||
register int ch = GetChar();
|
||||
struct idf *id;
|
||||
int parens = 0;
|
||||
|
||||
ch = skipspaces(ch, 0);
|
||||
|
||||
if (ch == '(') {
|
||||
parens++;
|
||||
ch = GetChar();
|
||||
ch = skipspaces(ch, 0);
|
||||
}
|
||||
if ((class(ch) != STIDF) && (class(ch) != STELL)) {
|
||||
error("identifier missing");
|
||||
if (parens && ch != ')') error(") missing");
|
||||
if (!parens || ch != ')') ChPushBack(ch);
|
||||
add2repl(repl, '0');
|
||||
return;
|
||||
}
|
||||
ChPushBack(ch);
|
||||
id = GetIdentifier(0);
|
||||
assert(id || class(ch) == STELL);
|
||||
ch = GetChar();
|
||||
ch = skipspaces(ch, 0);
|
||||
if (parens && ch != ')') error(") missing");
|
||||
if (!parens || ch != ')') ChPushBack(ch);
|
||||
add2repl(repl, (id && id->id_macro) ? '1' : '0');
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
getactuals(repl, idf)
|
||||
struct repl *repl;
|
||||
register struct idf *idf;
|
||||
{
|
||||
/* Get the actual parameters from the input stream.
|
||||
The hard part is done by actual(), only comma's and
|
||||
other syntactic trivialities are checked here.
|
||||
*/
|
||||
register struct args *args = repl->r_args;
|
||||
register int nps = idf->id_macro->mc_nps;
|
||||
register int argcnt;
|
||||
register int ch;
|
||||
|
||||
argcnt = 0;
|
||||
newarg(args);
|
||||
if ((ch = GetChar()) != ')') {
|
||||
UnGetChar();
|
||||
while ((ch = actual(repl)) != ')' ) {
|
||||
if (ch != ',') {
|
||||
lexerror("illegal macro call");
|
||||
return;
|
||||
}
|
||||
stash(repl, '\0', 1);
|
||||
args->a_expvec[argcnt] = args->a_expbuf;
|
||||
args->a_rawvec[argcnt] = args->a_rawbuf;
|
||||
++argcnt;
|
||||
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)
|
||||
lexerror("too few macro arguments");
|
||||
else if (argcnt > nps)
|
||||
lexerror("too many macro arguments");
|
||||
}
|
||||
|
||||
saveraw(repl)
|
||||
struct repl *repl;
|
||||
{
|
||||
register struct repl *nrepl = ReplaceList;
|
||||
register struct args *ap = nrepl->r_args;
|
||||
register char *p;
|
||||
|
||||
/* stash identifier name */
|
||||
for (p = nrepl->r_idf->id_text; *p != '\0'; p++)
|
||||
stash(repl, *p, -1);
|
||||
|
||||
/* The following code deals with expanded function
|
||||
like macro calls. It makes the following code
|
||||
work:
|
||||
|
||||
#define def(a,b) x(a,b)
|
||||
#define glue(a,b) a ## b
|
||||
|
||||
glue(abc,def(a,b))
|
||||
|
||||
Results in:
|
||||
|
||||
abcdef(a,b);
|
||||
*/
|
||||
if (ap->a_rawvec[0]) {
|
||||
/* stash arguments */
|
||||
register int i;
|
||||
|
||||
for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
|
||||
if (i == 0) stash(repl, '(', -1);
|
||||
else stash(repl, ',', -1);
|
||||
for (p = ap->a_rawvec[i]; *p != '\0'; p++)
|
||||
stash(repl, *p, -1);
|
||||
}
|
||||
stash(repl, ')', -1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
actual(repl)
|
||||
struct repl *repl;
|
||||
{
|
||||
/* This routine deals with the scanning of an actual parameter.
|
||||
It keeps in account the opening and closing brackets,
|
||||
preprocessor numbers, strings and character constants.
|
||||
*/
|
||||
register int ch = 0;
|
||||
register int level = 0, nostashraw = 0;
|
||||
int lastch;
|
||||
static int Unstacked_missed;
|
||||
|
||||
while (1) {
|
||||
lastch = ch;
|
||||
ch = GetChar();
|
||||
|
||||
if (nostashraw
|
||||
&& nostashraw >= Unstacked_missed) {
|
||||
nostashraw -= Unstacked_missed;
|
||||
Unstacked_missed = 0;
|
||||
}
|
||||
if (Unstacked) {
|
||||
nostashraw -= Unstacked;
|
||||
if (nostashraw < 0) {
|
||||
Unstacked_missed = -nostashraw;
|
||||
nostashraw = 0;
|
||||
}
|
||||
EnableMacros();
|
||||
}
|
||||
if (class(ch) == STIDF || class(ch) == STELL) {
|
||||
/* Scan a preprocessor identifier token. If the
|
||||
token is a macro, it is expanded first.
|
||||
*/
|
||||
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
|
||||
register char *p = buf;
|
||||
register struct idf *idef;
|
||||
register int pos = -1;
|
||||
extern int idfsize;
|
||||
int NoExpandMacro;
|
||||
|
||||
if (ch == NOEXPM) {
|
||||
NoExpandMacro= 1;
|
||||
ch = GetChar();
|
||||
} else NoExpandMacro = 0;
|
||||
|
||||
do {
|
||||
if (++pos < idfsize) {
|
||||
*p++ = ch;
|
||||
}
|
||||
ch = GetChar();
|
||||
} while (in_idf(ch));
|
||||
*p++ = '\0';
|
||||
ch = '\0'; /* It could be an unstashed TOKSEP */
|
||||
UnGetChar();
|
||||
|
||||
/* When the identifier has an associated macro
|
||||
replacement list, it's expanded.
|
||||
*/
|
||||
idef = findidf(buf);
|
||||
if (!idef || NoExpandMacro || !replace(idef)) {
|
||||
if (NoExpandMacro
|
||||
|| (idef && idef->id_macro
|
||||
&& (idef->id_macro->mc_flag & NOREPLACE)))
|
||||
stash(repl, NOEXPM, !nostashraw);
|
||||
for (p = buf; *p != '\0'; p++)
|
||||
stash(repl, *p, !nostashraw);
|
||||
} else {
|
||||
if (!nostashraw) saveraw(repl);
|
||||
nostashraw++;
|
||||
}
|
||||
} else if (class(ch) == STNUM) {
|
||||
/* a preprocessing number has the following
|
||||
regular expression:
|
||||
[0-9|"."[0-9]]{[0-9"."a-zA-Z_]|{[Ee][+-]}}*
|
||||
*/
|
||||
stash(repl, ch, !nostashraw);
|
||||
if (ch == '.') {
|
||||
ch = GetChar();
|
||||
if (class(ch) != STNUM) {
|
||||
ch = '\0'; /* It could be an unstashed TOKSEP */
|
||||
UnGetChar();
|
||||
continue;
|
||||
}
|
||||
else stash(repl, ch, !nostashraw);
|
||||
}
|
||||
ch = GetChar();
|
||||
while (in_idf(ch) || ch == '.') {
|
||||
stash(repl, ch, !nostashraw);
|
||||
if ((ch = GetChar()) == 'e' || ch == 'E') {
|
||||
stash(repl, ch, !nostashraw);
|
||||
ch = GetChar();
|
||||
if (ch == '+' || ch == '-') {
|
||||
stash(repl, ch, !nostashraw);
|
||||
ch = GetChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
ch = '\0'; /* It could be an unstashed TOKSEP */
|
||||
UnGetChar();
|
||||
} else if (ch == '(') {
|
||||
/* a comma may occur between parentheses */
|
||||
level++;
|
||||
stash(repl, ch, !nostashraw);
|
||||
} else if (ch == ')') {
|
||||
level--;
|
||||
/* closing parenthesis of macro call */
|
||||
if (level < 0) return ')';
|
||||
stash(repl, ch, !nostashraw);
|
||||
} else if (ch == ',') {
|
||||
if (level <= 0) { /* comma separator for next argument */
|
||||
if (level)
|
||||
lexerror("unbalanced parenthesis");
|
||||
if (!nostashraw)
|
||||
return ','; /* ??? */
|
||||
}
|
||||
stash(repl, ch, !nostashraw);
|
||||
} else if (ch == '\n') {
|
||||
/* newlines are accepted as white spaces */
|
||||
LineNumber++;
|
||||
/* 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(
|
||||
/_* comment *_/ #include phone_number
|
||||
,2);
|
||||
in which case the include must be handled
|
||||
interpreted as such.
|
||||
*/
|
||||
|
||||
a_new_line: 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();
|
||||
/* Clear File_Inserted since domacro could
|
||||
* be called again, which calls GetToken().
|
||||
*/
|
||||
File_Inserted = 0;
|
||||
goto a_new_line;
|
||||
} else if (ch == EOI) {
|
||||
lexerror("unterminated macro call");
|
||||
return ')';
|
||||
}
|
||||
if (ch != '/') {
|
||||
UnGetChar();
|
||||
ch = ' ';
|
||||
stash(repl, ' ', !nostashraw);
|
||||
}
|
||||
} else if (ch == '/') {
|
||||
/* comments are treated as one white space token */
|
||||
if ((ch = GetChar()) == '*' && !InputLevel) {
|
||||
skipcomment();
|
||||
stash(repl, ' ', !nostashraw);
|
||||
} else {
|
||||
UnGetChar();
|
||||
ch = '/';
|
||||
stash(repl, '/', !nostashraw);
|
||||
}
|
||||
} else if (ch == '\'' || ch == '"') {
|
||||
/* Strings are considered as ONE token, thus no
|
||||
replacement within strings.
|
||||
*/
|
||||
register int match = ch;
|
||||
|
||||
stash(repl, ch, !nostashraw);
|
||||
while ((ch = GetChar()) != EOI) {
|
||||
if (ch == match)
|
||||
break;
|
||||
if (ch == '\\') {
|
||||
stash(repl, ch, !nostashraw);
|
||||
ch = GetChar();
|
||||
} else if (ch == '\n') {
|
||||
lexerror("newline in string");
|
||||
LineNumber++;
|
||||
stash(repl, match, !nostashraw);
|
||||
break;
|
||||
}
|
||||
stash(repl, ch, !nostashraw);
|
||||
}
|
||||
if (ch != match) {
|
||||
lexerror("unterminated macro call");
|
||||
return ')';
|
||||
}
|
||||
stash(repl, ch, !nostashraw);
|
||||
} else {
|
||||
if (lastch == TOKSEP && ch == TOKSEP) continue;
|
||||
stash(repl, ch, !nostashraw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_func(idef)
|
||||
register struct idf *idef;
|
||||
{
|
||||
/* macro_func() performs the special actions needed with some
|
||||
macros. These macros are __FILE__ and __LINE__ which
|
||||
replacement texts must be evaluated at the time they are
|
||||
used.
|
||||
*/
|
||||
register struct macro *mac = idef->id_macro;
|
||||
static char FilNamBuf[PATHLENGTH];
|
||||
|
||||
switch (idef->id_text[2]) {
|
||||
case 'F': /* __FILE__ */
|
||||
FilNamBuf[0] = '"';
|
||||
strcpy(&FilNamBuf[1], FileName);
|
||||
strcat(FilNamBuf, "\"");
|
||||
mac->mc_text = FilNamBuf;
|
||||
mac->mc_length = strlen(FilNamBuf);
|
||||
break;
|
||||
case 'L': /* __LINE__ */
|
||||
mac->mc_text = long2str((long)LineNumber, 10);
|
||||
mac->mc_length = strlen(mac->mc_text);
|
||||
break;
|
||||
default:
|
||||
crash("(macro_func)");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
macro2buffer(repl, idf, args)
|
||||
register struct repl *repl;
|
||||
register struct idf *idf;
|
||||
register struct args *args;
|
||||
{
|
||||
/* macro2buffer expands the replacement list and places the
|
||||
result onto the replacement buffer. It deals with the #
|
||||
and ## operators, and inserts the actual parameters.
|
||||
The argument buffer contains the raw argument (needed
|
||||
for the ## operator), and the expanded argument (for
|
||||
all other parameter substitutions).
|
||||
|
||||
The grammar of the replacement list is:
|
||||
|
||||
repl_list: TOKEN repl_list
|
||||
| PARAMETER repl_list
|
||||
| '#' PARAMETER
|
||||
| TOKEN '##' TOKEN
|
||||
| PARAMETER '##' TOKEN
|
||||
| TOKEN '##' PARAMETER
|
||||
| PARAMETER '##' PARAMETER
|
||||
;
|
||||
|
||||
As the grammar indicates, we could make a DFA and
|
||||
use this finite state machine for the replacement
|
||||
list parsing (inserting the arguments, etc.).
|
||||
|
||||
Currently we go through the replacement list in a
|
||||
linear fashion. This is VERY expensive, something
|
||||
smarter should be done (but even a DFA is O(|s|)).
|
||||
*/
|
||||
register char *ptr = idf->id_macro->mc_text;
|
||||
int err = 0;
|
||||
int func = idf->id_macro->mc_nps != -1;
|
||||
char *stringify();
|
||||
|
||||
assert(ptr[idf->id_macro->mc_length] == '\0');
|
||||
while (*ptr) {
|
||||
if (*ptr == '\'' || *ptr == '"') {
|
||||
register int delim = *ptr;
|
||||
|
||||
do {
|
||||
add2repl(repl, *ptr);
|
||||
if (*ptr == '\\')
|
||||
add2repl(repl, *++ptr);
|
||||
if (*ptr == '\0') {
|
||||
lexerror("unterminated string");
|
||||
return;
|
||||
}
|
||||
ptr++;
|
||||
} while (*ptr != delim || *ptr == '\0');
|
||||
add2repl(repl, *ptr++);
|
||||
} else if (*ptr == '#' && (func || *(ptr+1) == '#')) {
|
||||
if (*++ptr == '#') {
|
||||
register int tmpindex;
|
||||
/* ## - paste operator */
|
||||
ptr++;
|
||||
|
||||
/* trim the actual replacement list */
|
||||
--repl->r_ptr;
|
||||
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) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (repl->r_ptr >= repl->r_text
|
||||
&& *repl->r_ptr == TOKSEP)
|
||||
--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))
|
||||
ptr++;
|
||||
|
||||
/* ## occurred at the end of the replacement list.
|
||||
*/
|
||||
if (*ptr & FORMALP) {
|
||||
register int n = *ptr++ & 0177;
|
||||
register char *p;
|
||||
|
||||
assert(n > 0);
|
||||
p = args->a_rawvec[n-1];
|
||||
if (p) { /* else macro argument missing */
|
||||
while (is_wsp(*p)) p++;
|
||||
if (*p == NOEXPM) p++;
|
||||
while (*p)
|
||||
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)) {
|
||||
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 */
|
||||
ptr = stringify(repl, ptr, args);
|
||||
}
|
||||
} else if (*ptr & FORMALP) {
|
||||
/* insert actual parameter */
|
||||
register int n = *ptr++ & 0177;
|
||||
register char *p, *q;
|
||||
|
||||
assert(n > 0);
|
||||
|
||||
/* This is VERY dirty, we look ahead for the
|
||||
## operator. If it's found we use the raw
|
||||
argument buffer instead of the expanded
|
||||
one.
|
||||
*/
|
||||
for (p = ptr; (*p & FORMALP) == 0 && is_wsp(*p); p++)
|
||||
/* EMPTY */;
|
||||
if (*p == '#' && p[1] == '#')
|
||||
q = args->a_rawvec[n-1];
|
||||
else
|
||||
q = args->a_expvec[n-1];
|
||||
|
||||
if (q) /* else macro argument missing */
|
||||
while (*q)
|
||||
add2repl(repl, *q++);
|
||||
|
||||
if (repl->r_text == repl->r_ptr || *(repl->r_ptr - 1) != TOKSEP)
|
||||
add2repl(repl, TOKSEP);
|
||||
} else {
|
||||
add2repl(repl, *ptr++);
|
||||
}
|
||||
}
|
||||
if (err)
|
||||
lexerror("illegal use of the ## operator");
|
||||
}
|
||||
|
||||
char *
|
||||
stringify(repl, ptr, args)
|
||||
register struct repl *repl;
|
||||
register char *ptr;
|
||||
register struct args *args;
|
||||
{
|
||||
/* If a parameter is immediately preceded by a # token
|
||||
both are replaced by a single string literal that
|
||||
contains the spelling of the token sequence for the
|
||||
corresponding argument.
|
||||
Each occurrence of white space between the argument's
|
||||
tokens become a single space character in the string
|
||||
literal. White spaces before the first token and after
|
||||
the last token comprising the argument are deleted.
|
||||
To retain the original spelling we insert backslashes
|
||||
as appropriate. We only escape backslashes if they
|
||||
occure within string tokens.
|
||||
*/
|
||||
register int space = 1; /* skip leading spaces */
|
||||
register int delim = 0; /* string or character constant delim */
|
||||
register int backslash = 0; /* last character was a \ */
|
||||
|
||||
/* skip spaces macro replacement list */
|
||||
while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
|
||||
ptr++;
|
||||
|
||||
if (*ptr & FORMALP) {
|
||||
register int n = *ptr++ & 0177;
|
||||
register char *p;
|
||||
|
||||
assert(n != 0);
|
||||
p = args->a_rawvec[n-1];
|
||||
add2repl(repl, '"');
|
||||
while (*p) {
|
||||
if (is_wsp(*p)) {
|
||||
if (!space) {
|
||||
space = 1;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
space = 0;
|
||||
|
||||
if (!delim && (*p == '"' || *p == '\''))
|
||||
delim = *p;
|
||||
else if (*p == delim && !backslash)
|
||||
delim = 0;
|
||||
backslash = *p == '\\';
|
||||
if (*p == '"' || (delim && *p == '\\'))
|
||||
add2repl(repl, '\\');
|
||||
if (*p == TOKSEP || *p == NOEXPM) 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; /* oops, one to far */
|
||||
add2repl(repl, '"');
|
||||
} else
|
||||
error("illegal use of # operator");
|
||||
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;
|
||||
|
||||
assert(index < repl->r_size);
|
||||
if (index + 2 >= repl->r_size) {
|
||||
repl->r_text = Realloc(repl->r_text, (unsigned) (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;
|
||||
int stashraw;
|
||||
{
|
||||
/* Stash characters into the macro expansion buffer.
|
||||
*/
|
||||
register struct args *args = repl->r_args;
|
||||
register int index = args->a_expptr - args->a_expbuf;
|
||||
|
||||
if (stashraw >= 0) {
|
||||
assert(index < args->a_expsize);
|
||||
if (index + 1 >= args->a_expsize) {
|
||||
args->a_expbuf = Realloc(args->a_expbuf,
|
||||
(unsigned) (args->a_expsize <<= 1));
|
||||
args->a_expptr = args->a_expbuf + index;
|
||||
}
|
||||
*args->a_expptr++ = ch;
|
||||
}
|
||||
|
||||
if (stashraw) {
|
||||
index = args->a_rawptr - args->a_rawbuf;
|
||||
assert(index < args->a_rawsize);
|
||||
if (index + 1 >= args->a_rawsize) {
|
||||
args->a_rawbuf = Realloc(args->a_rawbuf,
|
||||
(unsigned)(args->a_rawsize <<= 1));
|
||||
args->a_rawptr = args->a_rawbuf + index;
|
||||
}
|
||||
*args->a_rawptr++ = ch;
|
||||
}
|
||||
}
|
||||
#endif /* NOPP */
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/* DEFINITIONS FOR THE MACRO REPLACEMENT ROUTINES */
|
||||
|
||||
struct repl {
|
||||
struct repl *next;
|
||||
struct idf *r_idf; /* name of the macro */
|
||||
struct args *r_args; /* replacement parameters */
|
||||
int r_level; /* level of insertion */
|
||||
int r_size; /* current size of replacement buffer */
|
||||
char *r_ptr; /* replacement text index pointer */
|
||||
char *r_text; /* replacement text */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "repl" 4 */
|
||||
|
||||
#define NO_REPL (struct repl *)0
|
||||
|
||||
/* The implementation of the ## operator is currently very clumsy.
|
||||
When the the ## operator is used the arguments are taken from
|
||||
the raw buffer; this buffer contains a precise copy of the
|
||||
original argument. The fully expanded copy is in the arg buffer.
|
||||
The two copies are here explicitely because:
|
||||
|
||||
#define ABC f()
|
||||
#define ABCD 2
|
||||
#define g(x, y) x ## y + h(x)
|
||||
|
||||
g(ABC, D); // gives: 2 + h(f())
|
||||
|
||||
In this case we need two copies: one raw copy for the pasting
|
||||
operator, and an expanded one as argument for h().
|
||||
*/
|
||||
struct args {
|
||||
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_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 */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "args" 2 */
|
||||
|
||||
#define NO_ARGS (struct args *)0
|
||||
|
|
@ -11,94 +11,17 @@
|
|||
#include "class.h"
|
||||
#include "input.h"
|
||||
|
||||
#ifndef NOPP
|
||||
extern int InputLevel;
|
||||
|
||||
int
|
||||
skipspaces(ch, skipnl)
|
||||
register int ch;
|
||||
{
|
||||
/* skipspaces() skips any white space and returns the first
|
||||
non-space character.
|
||||
*/
|
||||
register int nlseen = 0;
|
||||
|
||||
for (;;) {
|
||||
while (class(ch) == STSKIP)
|
||||
ch = GetChar();
|
||||
if (skipnl && class(ch) == STNL) {
|
||||
ch = GetChar();
|
||||
LineNumber++;
|
||||
nlseen++;
|
||||
continue;
|
||||
}
|
||||
if (ch == TOKSEP && InputLevel) {
|
||||
ch = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* \\\n are handled by trigraph */
|
||||
|
||||
if (ch == '/') {
|
||||
ch = GetChar();
|
||||
if (ch == '*' && !InputLevel) {
|
||||
skipcomment();
|
||||
ch = GetChar();
|
||||
}
|
||||
else {
|
||||
UnGetChar();
|
||||
return '/';
|
||||
}
|
||||
}
|
||||
else if (nlseen && ch == '#') {
|
||||
domacro();
|
||||
ch = GetChar();
|
||||
} else
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
#endif /* NOPP */
|
||||
|
||||
SkipToNewLine()
|
||||
{
|
||||
register int ch;
|
||||
register int garbage = 0;
|
||||
#ifndef NOPP
|
||||
register int delim = 0;
|
||||
#endif
|
||||
|
||||
while ((ch = GetChar()) != '\n') {
|
||||
#ifndef NOPP
|
||||
if (delim) {
|
||||
if (ch == '\\') {
|
||||
if (GetChar() == '\n') break;
|
||||
} else if (ch == delim) {
|
||||
delim = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (ch == '\'' || ch == '\"') {
|
||||
delim = ch;
|
||||
garbage = 1;
|
||||
} else if (ch == '/') {
|
||||
if (GetChar() == '*'
|
||||
&& !InputLevel
|
||||
) {
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
else UnGetChar();
|
||||
}
|
||||
else if (ch == TOKSEP && InputLevel) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
while ((ch = GetChar()) != '\n')
|
||||
{
|
||||
if (!is_wsp(ch))
|
||||
garbage = 1;
|
||||
}
|
||||
#ifndef NOPP
|
||||
if (delim) strict("unclosed opening %c", delim);
|
||||
#endif
|
||||
++LineNumber;
|
||||
return garbage;
|
||||
}
|
||||
|
|
|
@ -30,23 +30,20 @@ int AccFileSpecifier = 0; /* return filespecifier <...> */
|
|||
int LexSave = 0; /* last character read by GetChar */
|
||||
extern int InputLevel; /* # of current macro expansions */
|
||||
|
||||
extern char *string_token();
|
||||
extern char* string_token();
|
||||
extern arith char_constant();
|
||||
#define FLG_ESEEN 0x01 /* possibly a floating point number */
|
||||
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */
|
||||
|
||||
void skipcomment();
|
||||
void skiplinecomment(void);
|
||||
|
||||
int
|
||||
LLlex()
|
||||
int LLlex()
|
||||
{
|
||||
return (DOT != EOF) ? GetToken(&dot) : EOF;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GetToken(ptok)
|
||||
register struct token *ptok;
|
||||
int GetToken(ptok) register struct token* ptok;
|
||||
{
|
||||
/* GetToken() is the actual token recognizer. It calls the
|
||||
control line interpreter if it encounters a "\n{w}*#"
|
||||
|
@ -63,14 +60,15 @@ again: /* rescan the input after an error or replacement */
|
|||
fatal("non-ascii '\\%03o' read", ch & 0377);
|
||||
/* keep track of the place of the token in the file */
|
||||
|
||||
switch (class(ch)) { /* detect character class */
|
||||
switch (class(ch))
|
||||
{ /* detect character class */
|
||||
case STNL: /* newline, vertical space or formfeed */
|
||||
LineNumber++;
|
||||
return ptok->tk_symb = EOF;
|
||||
case STSKIP: /* just skip the skip characters */
|
||||
goto again;
|
||||
case STGARB: /* garbage character */
|
||||
garbage:
|
||||
garbage:
|
||||
if (040 < ch && ch < 0177)
|
||||
error("garbage char %c", ch);
|
||||
else
|
||||
|
@ -80,7 +78,8 @@ garbage:
|
|||
return ptok->tk_symb = ch;
|
||||
case STCOMP: /* maybe the start of a compound token */
|
||||
nch = GetChar(); /* character lookahead */
|
||||
switch (ch) {
|
||||
switch (ch)
|
||||
{
|
||||
case '!':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = NOTEQUAL;
|
||||
|
@ -110,17 +109,20 @@ garbage:
|
|||
UnGetChar();
|
||||
return ptok->tk_symb = ch;
|
||||
case '<':
|
||||
if (AccFileSpecifier) {
|
||||
if (AccFileSpecifier)
|
||||
{
|
||||
UnGetChar(); /* pushback nch */
|
||||
ptok->tk_str =
|
||||
string_token("file specifier", '>');
|
||||
ptok->tk_str = string_token("file specifier", '>');
|
||||
return ptok->tk_symb = FILESPECIFIER;
|
||||
} else if (nch == '<') {
|
||||
}
|
||||
else if (nch == '<')
|
||||
{
|
||||
if ((nch = GetChar()) == '=')
|
||||
return ptok->tk_symb = LEFTAB;
|
||||
UnGetChar();
|
||||
return ptok->tk_symb = LEFT;
|
||||
} else if (nch == '=')
|
||||
}
|
||||
else if (nch == '=')
|
||||
return ptok->tk_symb = LESSEQ;
|
||||
UnGetChar();
|
||||
return ptok->tk_symb = ch;
|
||||
|
@ -132,7 +134,8 @@ garbage:
|
|||
case '>':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = GREATEREQ;
|
||||
else if (nch == '>') {
|
||||
else if (nch == '>')
|
||||
{
|
||||
if ((nch = GetChar()) == '=')
|
||||
return ptok->tk_symb = RIGHTAB;
|
||||
UnGetChar();
|
||||
|
@ -163,10 +166,19 @@ garbage:
|
|||
UnGetChar();
|
||||
return ptok->tk_symb = ch;
|
||||
case '/':
|
||||
if (nch == '*' && !InputLevel) {
|
||||
if (!InputLevel)
|
||||
{
|
||||
if (nch == '*')
|
||||
{
|
||||
skipcomment();
|
||||
goto again;
|
||||
}
|
||||
else if (nch == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
else if (nch == '=')
|
||||
return ptok->tk_symb = DIVAB;
|
||||
UnGetChar();
|
||||
|
@ -183,11 +195,13 @@ garbage:
|
|||
return ptok->tk_symb = STRING;
|
||||
case STELL: /* wide character constant/string prefix */
|
||||
nch = GetChar();
|
||||
if (nch == '"') {
|
||||
ptok->tk_str =
|
||||
string_token("wide character string", '"');
|
||||
if (nch == '"')
|
||||
{
|
||||
ptok->tk_str = string_token("wide character string", '"');
|
||||
return ptok->tk_symb = STRING;
|
||||
} else if (nch == '\'') {
|
||||
}
|
||||
else if (nch == '\'')
|
||||
{
|
||||
ptok->tk_val = char_constant("wide character");
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
|
@ -196,33 +210,57 @@ garbage:
|
|||
case STIDF:
|
||||
{
|
||||
extern int idfsize; /* ??? */
|
||||
register char *tg = &buf[0];
|
||||
register char *maxpos = &buf[idfsize];
|
||||
register char* tg = &buf[0];
|
||||
register char* maxpos = &buf[idfsize];
|
||||
int NoExpandNext = 0;
|
||||
|
||||
#define tstmac(bx) if (!(bits[ch] & bx)) goto nomac
|
||||
#define tstmac(bx) \
|
||||
if (!(bits[ch] & bx)) \
|
||||
goto nomac
|
||||
#define cpy *tg++ = ch
|
||||
#define load (ch = GetChar()); if (!in_idf(ch)) goto endidf
|
||||
#define load \
|
||||
(ch = GetChar()); \
|
||||
if (!in_idf(ch)) \
|
||||
goto endidf
|
||||
|
||||
if (Unstacked) EnableMacros(); /* unstack macro's when allowed. */
|
||||
if (ch == NOEXPM) {
|
||||
if (Unstacked)
|
||||
EnableMacros(); /* unstack macro's when allowed. */
|
||||
if (ch == NOEXPM)
|
||||
{
|
||||
NoExpandNext = 1;
|
||||
ch = GetChar();
|
||||
}
|
||||
#ifdef DOBITS
|
||||
cpy; tstmac(bit0); load;
|
||||
cpy; tstmac(bit1); load;
|
||||
cpy; tstmac(bit2); load;
|
||||
cpy; tstmac(bit3); load;
|
||||
cpy; tstmac(bit4); load;
|
||||
cpy; tstmac(bit5); load;
|
||||
cpy; tstmac(bit6); load;
|
||||
cpy; tstmac(bit7); load;
|
||||
#endif
|
||||
for(;;) {
|
||||
if (tg < maxpos) {
|
||||
cpy;
|
||||
|
||||
tstmac(bit0);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit1);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit2);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit3);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit4);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit5);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit6);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit7);
|
||||
load;
|
||||
#endif
|
||||
for (;;)
|
||||
{
|
||||
if (tg < maxpos)
|
||||
{
|
||||
cpy;
|
||||
}
|
||||
load;
|
||||
}
|
||||
|
@ -230,10 +268,12 @@ garbage:
|
|||
/*if (ch != EOI) UnGetChar();*/
|
||||
UnGetChar();
|
||||
*tg++ = '\0'; /* mark the end of the identifier */
|
||||
if (ReplaceMacros) {
|
||||
register struct idf *idef = findidf(buf);
|
||||
if (ReplaceMacros)
|
||||
{
|
||||
register struct idf* idef = findidf(buf);
|
||||
|
||||
if (idef && idef->id_macro && !NoExpandNext) {
|
||||
if (idef && idef->id_macro && !NoExpandNext)
|
||||
{
|
||||
if (replace(idef))
|
||||
goto again;
|
||||
}
|
||||
|
@ -241,15 +281,18 @@ garbage:
|
|||
|
||||
nomac: /* buf can already be null-terminated. soit */
|
||||
ch = GetChar();
|
||||
while (in_idf(ch)) {
|
||||
if (tg < maxpos) *tg++ = ch;
|
||||
while (in_idf(ch))
|
||||
{
|
||||
if (tg < maxpos)
|
||||
*tg++ = ch;
|
||||
ch = GetChar();
|
||||
}
|
||||
UnGetChar();
|
||||
*tg++ = '\0'; /* mark the end of the identifier */
|
||||
|
||||
NoExpandNext = 0;
|
||||
if (UnknownIdIsZero) {
|
||||
if (UnknownIdIsZero)
|
||||
{
|
||||
ptok->tk_val = (arith)0;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
|
@ -262,52 +305,65 @@ garbage:
|
|||
register int base = 10, vch;
|
||||
register arith val = 0;
|
||||
int ovfl = 0;
|
||||
arith ubound = max_arith/(base/2);
|
||||
arith ubound = max_arith / (base / 2);
|
||||
|
||||
/* Since the preprocessor only knows integers and has
|
||||
* nothing to do with ellipsis we just return when the
|
||||
* pp-number starts with a '.'
|
||||
*/
|
||||
if (ch == '.') {
|
||||
if (ch == '.')
|
||||
{
|
||||
return ptok->tk_symb = ch;
|
||||
}
|
||||
if (ch == '0') {
|
||||
if (ch == '0')
|
||||
{
|
||||
ch = GetChar();
|
||||
if (ch == 'x' || ch == 'X') {
|
||||
if (ch == 'x' || ch == 'X')
|
||||
{
|
||||
base = 16;
|
||||
ch = GetChar();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
base = 8;
|
||||
}
|
||||
|
||||
}
|
||||
while ((vch = val_in_base(ch, base)) >= 0) {
|
||||
if (val < 0 || val > ubound) ovfl++;
|
||||
while ((vch = val_in_base(ch, base)) >= 0)
|
||||
{
|
||||
if (val < 0 || val > ubound)
|
||||
ovfl++;
|
||||
val *= base;
|
||||
if (val < 0 && val + vch >= 0) ovfl++;
|
||||
if (val < 0 && val + vch >= 0)
|
||||
ovfl++;
|
||||
val += vch;
|
||||
ch = GetChar();
|
||||
}
|
||||
ptok->tk_unsigned = 0;
|
||||
if (ch == 'u' || ch == 'U') {
|
||||
if (ch == 'u' || ch == 'U')
|
||||
{
|
||||
ptok->tk_unsigned = 1;
|
||||
ch = GetChar();
|
||||
if (ch == 'l' || ch == 'L') {
|
||||
if (ch == 'l' || ch == 'L')
|
||||
{
|
||||
ch = GetChar();
|
||||
}
|
||||
}
|
||||
else if (ch == 'l' || ch == 'L') {
|
||||
else if (ch == 'l' || ch == 'L')
|
||||
{
|
||||
ch = GetChar();
|
||||
if (ch == 'u' || ch == 'U') {
|
||||
if (ch == 'u' || ch == 'U')
|
||||
{
|
||||
ptok->tk_unsigned = 1;
|
||||
ch = GetChar();
|
||||
}
|
||||
}
|
||||
if (ovfl) {
|
||||
if (ovfl)
|
||||
{
|
||||
warning("overflow in constant");
|
||||
ptok->tk_unsigned = 1;
|
||||
}
|
||||
else if (val < 0) {
|
||||
else if (val < 0)
|
||||
{
|
||||
/* give warning??? */
|
||||
ptok->tk_unsigned = 1;
|
||||
}
|
||||
|
@ -318,8 +374,10 @@ garbage:
|
|||
case STEOI: /* end of text on source file */
|
||||
return ptok->tk_symb = EOF;
|
||||
case STMSPEC:
|
||||
if (!InputLevel) goto garbage;
|
||||
if (ch == TOKSEP) goto again;
|
||||
if (!InputLevel)
|
||||
goto garbage;
|
||||
if (ch == TOKSEP)
|
||||
goto again;
|
||||
/* fallthrough shouldn't happen */
|
||||
default: /* this cannot happen */
|
||||
crash("bad class for char 0%o", ch);
|
||||
|
@ -327,8 +385,7 @@ garbage:
|
|||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
void
|
||||
skipcomment()
|
||||
void skipcomment()
|
||||
{
|
||||
/* The last character read has been the '*' of '/_*'. The
|
||||
characters, except NL and EOI, between '/_*' and the first
|
||||
|
@ -344,11 +401,16 @@ skipcomment()
|
|||
|
||||
NoUnstack++;
|
||||
c = GetChar();
|
||||
do {
|
||||
while (c != '*') {
|
||||
if (class(c) == STNL) {
|
||||
do
|
||||
{
|
||||
while (c != '*')
|
||||
{
|
||||
if (class(c) == STNL)
|
||||
{
|
||||
++LineNumber;
|
||||
} else if (c == EOI) {
|
||||
}
|
||||
else if (c == EOI)
|
||||
{
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
|
@ -359,9 +421,23 @@ skipcomment()
|
|||
NoUnstack--;
|
||||
}
|
||||
|
||||
arith
|
||||
char_constant(nm)
|
||||
char *nm;
|
||||
void skiplinecomment(void)
|
||||
{
|
||||
/* The last character read has been the '/' of '//'. We read
|
||||
and discard all characters up to but not including the next
|
||||
NL. */
|
||||
|
||||
for (;;) {
|
||||
int c = GetChar();
|
||||
if ((class(c) == STNL) || (c == EOI))
|
||||
{
|
||||
UnGetChar();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arith char_constant(nm) char* nm;
|
||||
{
|
||||
register arith val = 0;
|
||||
register int ch;
|
||||
|
@ -371,15 +447,18 @@ char_constant(nm)
|
|||
if (ch == '\'')
|
||||
error("%s constant too short", nm);
|
||||
else
|
||||
while (ch != '\'') {
|
||||
if (ch == '\n') {
|
||||
while (ch != '\'')
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
error("newline in %s constant", nm);
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == '\\')
|
||||
ch = quoted(GetChar());
|
||||
if (ch >= 128) ch -= 256;
|
||||
if (ch >= 128)
|
||||
ch -= 256;
|
||||
if (size < sizeof(arith))
|
||||
val |= ch << (8 * size);
|
||||
size++;
|
||||
|
@ -392,23 +471,24 @@ char_constant(nm)
|
|||
return val;
|
||||
}
|
||||
|
||||
char *
|
||||
string_token(nm, stop_char)
|
||||
char *nm;
|
||||
char* string_token(nm, stop_char) char* nm;
|
||||
{
|
||||
register int ch;
|
||||
register int str_size;
|
||||
register char *str = Malloc((unsigned) (str_size = ISTRSIZE));
|
||||
register char* str = Malloc((unsigned)(str_size = ISTRSIZE));
|
||||
register int pos = 0;
|
||||
|
||||
ch = GetChar();
|
||||
while (ch != stop_char) {
|
||||
if (ch == '\n') {
|
||||
while (ch != stop_char)
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
error("newline in %s", nm);
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
if (ch == EOI)
|
||||
{
|
||||
error("end-of-file inside %s", nm);
|
||||
break;
|
||||
}
|
||||
|
@ -424,16 +504,16 @@ string_token(nm, stop_char)
|
|||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
quoted(ch)
|
||||
register int ch;
|
||||
int quoted(ch) register int ch;
|
||||
{
|
||||
/* quoted() replaces an escaped character sequence by the
|
||||
character meant.
|
||||
*/
|
||||
/* first char after backslash already in ch */
|
||||
if (!is_oct(ch)) { /* a quoted char */
|
||||
switch (ch) {
|
||||
if (!is_oct(ch))
|
||||
{ /* a quoted char */
|
||||
switch (ch)
|
||||
{
|
||||
case 'n':
|
||||
ch = '\n';
|
||||
break;
|
||||
|
@ -460,7 +540,8 @@ quoted(ch)
|
|||
register int hex = 0;
|
||||
register int vch;
|
||||
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
ch = GetChar();
|
||||
if (vch = val_in_base(ch, 16), vch == -1)
|
||||
break;
|
||||
|
@ -470,42 +551,39 @@ quoted(ch)
|
|||
ch = hex;
|
||||
}
|
||||
}
|
||||
} else { /* a quoted octal */
|
||||
}
|
||||
else
|
||||
{ /* a quoted octal */
|
||||
register int oct = 0, cnt = 0;
|
||||
|
||||
do {
|
||||
oct = oct*8 + (ch-'0');
|
||||
do
|
||||
{
|
||||
oct = oct * 8 + (ch - '0');
|
||||
ch = GetChar();
|
||||
} while (is_oct(ch) && ++cnt < 3);
|
||||
UnGetChar();
|
||||
ch = oct;
|
||||
}
|
||||
return ch&0377;
|
||||
return ch & 0377;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
val_in_base(ch, base)
|
||||
register int ch;
|
||||
int val_in_base(ch, base) register int ch;
|
||||
{
|
||||
switch (base) {
|
||||
switch (base)
|
||||
{
|
||||
case 8:
|
||||
return (is_dig(ch) && ch < '9') ? ch - '0' : -1;
|
||||
case 10:
|
||||
return is_dig(ch) ? ch - '0' : -1;
|
||||
case 16:
|
||||
return is_dig(ch) ? ch - '0'
|
||||
: is_hex(ch) ? (ch - 'a' + 10) & 017
|
||||
: -1;
|
||||
return is_dig(ch) ? ch - '0' : is_hex(ch) ? (ch - 'a' + 10) & 017 : -1;
|
||||
default:
|
||||
fatal("(val_in_base) illegal base value %d", base);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GetChar()
|
||||
int GetChar()
|
||||
{
|
||||
/* The routines GetChar and trigraph parses the trigraph
|
||||
sequences and removes occurences of \\\n.
|
||||
|
@ -520,58 +598,60 @@ again:
|
|||
ch = trigraph();
|
||||
|
||||
/* \\\n are removed from the input stream */
|
||||
if (ch == '\\') {
|
||||
if (ch == '\\')
|
||||
{
|
||||
LoadChar(ch);
|
||||
if (ch == '\n') {
|
||||
if (ch == '\n')
|
||||
{
|
||||
++LineNumber;
|
||||
goto again;
|
||||
}
|
||||
PushBack();
|
||||
ch = '\\';
|
||||
}
|
||||
return(LexSave = ch);
|
||||
return (LexSave = ch);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
trigraph()
|
||||
int trigraph()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
LoadChar(ch);
|
||||
if (ch == '?') {
|
||||
if (ch == '?')
|
||||
{
|
||||
LoadChar(ch);
|
||||
switch (ch) { /* its a trigraph */
|
||||
switch (ch)
|
||||
{ /* its a trigraph */
|
||||
case '=':
|
||||
ch = '#';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '(':
|
||||
ch = '[';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '/':
|
||||
ch = '\\';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case ')':
|
||||
ch = ']';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '\'':
|
||||
ch = '^';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '<':
|
||||
ch = '{';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '!':
|
||||
ch = '|';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '>':
|
||||
ch = '}';
|
||||
return(ch);
|
||||
return (ch);
|
||||
case '-':
|
||||
ch = '~';
|
||||
return(ch);
|
||||
return (ch);
|
||||
}
|
||||
PushBack();
|
||||
}
|
||||
PushBack();
|
||||
return('?');
|
||||
return ('?');
|
||||
}
|
||||
|
|
|
@ -108,7 +108,8 @@ cprogram {
|
|||
installable {
|
||||
name = "pkg",
|
||||
map = {
|
||||
["$(PLATDEP)/cpp.ansi"] = "+cpp"
|
||||
["$(PLATDEP)/cpp.ansi"] = "+cpp",
|
||||
["$(INSDIR)/share/man/man6/cpp.ansi.6"] = "./ncpp.6",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,23 +22,21 @@
|
|||
#include "replace.h"
|
||||
|
||||
extern char options[];
|
||||
extern char **inctable; /* list of include directories */
|
||||
extern char *getwdir();
|
||||
extern char** inctable; /* list of include directories */
|
||||
extern char* getwdir();
|
||||
char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
|
||||
/* 1 if a corresponding ELSE has been */
|
||||
/* encountered. */
|
||||
/* 1 if a corresponding ELSE has been */
|
||||
/* encountered. */
|
||||
|
||||
int nestlevel = -1;
|
||||
int svnestlevel[30] = {-1};
|
||||
int svnestlevel[30] = { -1 };
|
||||
int nestcount;
|
||||
extern int do_preprocess;
|
||||
|
||||
void macro_def();
|
||||
void do_define();
|
||||
|
||||
char *
|
||||
GetIdentifier(skiponerr)
|
||||
int skiponerr; /* skip the rest of the line on error */
|
||||
char* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */
|
||||
{
|
||||
/* Returns a pointer to the identifier that is read from the
|
||||
input stream. When the input does not contain an
|
||||
|
@ -55,9 +53,11 @@ GetIdentifier(skiponerr)
|
|||
tok = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
UnknownIdIsZero = tmp;
|
||||
if (tok != IDENTIFIER) {
|
||||
if (skiponerr && tok != EOF) SkipToNewLine();
|
||||
return (char *)0;
|
||||
if (tok != IDENTIFIER)
|
||||
{
|
||||
if (skiponerr && tok != EOF)
|
||||
SkipToNewLine();
|
||||
return (char*)0;
|
||||
}
|
||||
return tk.tk_str;
|
||||
}
|
||||
|
@ -74,23 +74,26 @@ GetIdentifier(skiponerr)
|
|||
domacro()
|
||||
{
|
||||
struct token tk; /* the token itself */
|
||||
register struct idf *id;
|
||||
register struct idf* id;
|
||||
int toknum;
|
||||
|
||||
ReplaceMacros = 0;
|
||||
toknum = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
switch(toknum) { /* select control line action */
|
||||
switch (toknum)
|
||||
{ /* select control line action */
|
||||
case IDENTIFIER: /* is it a macro keyword? */
|
||||
id = findidf(tk.tk_str);
|
||||
if (!id) {
|
||||
if (!id)
|
||||
{
|
||||
error("%s: unknown control", tk.tk_str);
|
||||
SkipToNewLine();
|
||||
free(tk.tk_str);
|
||||
break;
|
||||
}
|
||||
free(tk.tk_str);
|
||||
switch (id->id_resmac) {
|
||||
switch (id->id_resmac)
|
||||
{
|
||||
case K_DEFINE: /* "define" */
|
||||
do_define();
|
||||
break;
|
||||
|
@ -119,7 +122,8 @@ domacro()
|
|||
/* set LineNumber and FileName according to
|
||||
the arguments.
|
||||
*/
|
||||
if (GetToken(&tk) != INTEGER) {
|
||||
if (GetToken(&tk) != INTEGER)
|
||||
{
|
||||
error("bad #line syntax");
|
||||
SkipToNewLine();
|
||||
}
|
||||
|
@ -133,7 +137,7 @@ domacro()
|
|||
do_pragma();
|
||||
break;
|
||||
case K_UNDEF: /* "undef" */
|
||||
do_undef((char *)0);
|
||||
do_undef((char*)0);
|
||||
break;
|
||||
default:
|
||||
/* invalid word seen after the '#' */
|
||||
|
@ -152,9 +156,7 @@ domacro()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
skip_block(to_endif)
|
||||
int to_endif;
|
||||
void skip_block(to_endif) int to_endif;
|
||||
{
|
||||
/* skip_block() skips the input from
|
||||
1) a false #if, #ifdef, #ifndef or #elif until the
|
||||
|
@ -168,33 +170,49 @@ int to_endif;
|
|||
register int skiplevel = nestlevel; /* current nesting level */
|
||||
struct token tk;
|
||||
int toknum;
|
||||
struct idf *id;
|
||||
struct idf* id;
|
||||
|
||||
NoUnstack++;
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
ch = GetChar(); /* read first character after newline */
|
||||
while (class(ch) == STSKIP)
|
||||
ch = GetChar();
|
||||
if (ch != '#') {
|
||||
if (ch == EOI) {
|
||||
if (ch != '#')
|
||||
{
|
||||
if (ch == EOI)
|
||||
{
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
if (ch == '/') {
|
||||
if (ch != '*') UnGetChar();
|
||||
else {
|
||||
if (ch == '/')
|
||||
{
|
||||
ch = GetChar();
|
||||
if (ch == '*')
|
||||
{
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
} else UnGetChar();
|
||||
else if (ch == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
UnGetChar();
|
||||
}
|
||||
else
|
||||
UnGetChar();
|
||||
SkipToNewLine();
|
||||
continue;
|
||||
}
|
||||
ReplaceMacros = 0;
|
||||
toknum = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
if (toknum != IDENTIFIER) {
|
||||
if (toknum != INTEGER) {
|
||||
if (toknum != IDENTIFIER)
|
||||
{
|
||||
if (toknum != INTEGER)
|
||||
{
|
||||
error("illegal # line");
|
||||
}
|
||||
SkipToNewLine();
|
||||
|
@ -206,13 +224,16 @@ int to_endif;
|
|||
on the same level.
|
||||
*/
|
||||
id = findidf(tk.tk_str);
|
||||
if (id == (struct idf *)0) {
|
||||
if (id == (struct idf*)0)
|
||||
{
|
||||
/* invalid word seen after the '#' */
|
||||
warning("%s: unknown control", tk.tk_str);
|
||||
}
|
||||
free(tk.tk_str);
|
||||
if (id == (struct idf *)0) continue;
|
||||
switch(id->id_resmac) {
|
||||
if (id == (struct idf*)0)
|
||||
continue;
|
||||
switch (id->id_resmac)
|
||||
{
|
||||
case K_DEFINE:
|
||||
case K_ERROR:
|
||||
case K_INCLUDE:
|
||||
|
@ -231,34 +252,42 @@ int to_endif;
|
|||
case K_ELIF:
|
||||
if (ifstack[nestlevel])
|
||||
error("#elif after #else");
|
||||
if (!to_endif && nestlevel == skiplevel) {
|
||||
if (!to_endif && nestlevel == skiplevel)
|
||||
{
|
||||
nestlevel--;
|
||||
push_if();
|
||||
if (ifexpr()) {
|
||||
if (ifexpr())
|
||||
{
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else SkipToNewLine(); /* otherwise done in ifexpr() */
|
||||
else
|
||||
SkipToNewLine(); /* otherwise done in ifexpr() */
|
||||
break;
|
||||
case K_ELSE:
|
||||
if (ifstack[nestlevel])
|
||||
error("#else after #else");
|
||||
++(ifstack[nestlevel]);
|
||||
if (!to_endif && nestlevel == skiplevel) {
|
||||
if (SkipToNewLine()) {
|
||||
if (!to_endif && nestlevel == skiplevel)
|
||||
{
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
if (!options['o'])
|
||||
strict("garbage following #else");
|
||||
}
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
else SkipToNewLine();
|
||||
else
|
||||
SkipToNewLine();
|
||||
break;
|
||||
case K_ENDIF:
|
||||
assert(nestlevel > svnestlevel[nestcount]);
|
||||
if (nestlevel == skiplevel) {
|
||||
if (SkipToNewLine()) {
|
||||
if (nestlevel == skiplevel)
|
||||
{
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
if (!options['o'])
|
||||
strict("garbage following #endif");
|
||||
}
|
||||
|
@ -266,14 +295,14 @@ int to_endif;
|
|||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
else SkipToNewLine();
|
||||
else
|
||||
SkipToNewLine();
|
||||
nestlevel--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ifexpr()
|
||||
{
|
||||
/* ifexpr() returns whether the restricted constant
|
||||
|
@ -299,30 +328,37 @@ do_include()
|
|||
{
|
||||
/* do_include() performs the inclusion of a file.
|
||||
*/
|
||||
char *filenm;
|
||||
char *result;
|
||||
char* filenm;
|
||||
char* result;
|
||||
int tok;
|
||||
struct token tk;
|
||||
|
||||
AccFileSpecifier = 1;
|
||||
if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
|
||||
filenm = tk.tk_str;
|
||||
else {
|
||||
else
|
||||
{
|
||||
error("bad include syntax");
|
||||
filenm = (char *)0;
|
||||
filenm = (char*)0;
|
||||
}
|
||||
AccFileSpecifier = 0;
|
||||
if (SkipToNewLine()) {
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
error("bad include syntax");
|
||||
}
|
||||
inctable[0] = WorkingDir;
|
||||
if (filenm) {
|
||||
if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
|
||||
if (do_preprocess) error("cannot open include file \"%s\"", filenm);
|
||||
else warning("cannot open include file \"%s\"", filenm);
|
||||
if (filenm)
|
||||
{
|
||||
if (!InsertFile(filenm, &inctable[tok == FILESPECIFIER], &result))
|
||||
{
|
||||
if (do_preprocess)
|
||||
error("cannot open include file \"%s\"", filenm);
|
||||
else
|
||||
warning("cannot open include file \"%s\"", filenm);
|
||||
add_dependency(filenm);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
add_dependency(result);
|
||||
WorkingDir = getwdir(result);
|
||||
svnestlevel[++nestcount] = nestlevel;
|
||||
|
@ -332,22 +368,22 @@ do_include()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_define()
|
||||
void do_define()
|
||||
{
|
||||
/* do_define() interprets a #define control line.
|
||||
*/
|
||||
register char *str; /* the #defined identifier's descriptor */
|
||||
register char* str; /* the #defined identifier's descriptor */
|
||||
int nformals = -1; /* keep track of the number of formals */
|
||||
char *formals[NPARAMS]; /* pointers to the names of the formals */
|
||||
char* formals[NPARAMS]; /* pointers to the names of the formals */
|
||||
char parbuf[PARBUFSIZE]; /* names of formals */
|
||||
char *repl_text; /* start of the replacement text */
|
||||
char* repl_text; /* start of the replacement text */
|
||||
int length; /* length of the replacement text */
|
||||
register ch;
|
||||
char *get_text();
|
||||
char* get_text();
|
||||
|
||||
/* read the #defined macro's name */
|
||||
if (!(str = GetIdentifier(1))) {
|
||||
if (!(str = GetIdentifier(1)))
|
||||
{
|
||||
error("#define: illegal macro name");
|
||||
return;
|
||||
}
|
||||
|
@ -355,8 +391,10 @@ do_define()
|
|||
followed immediately by a '('.
|
||||
*/
|
||||
ch = GetChar();
|
||||
if (ch == '(') {
|
||||
if ((nformals = getparams(formals, parbuf)) == -1) {
|
||||
if (ch == '(')
|
||||
{
|
||||
if ((nformals = getparams(formals, parbuf)) == -1)
|
||||
{
|
||||
SkipToNewLine();
|
||||
free(str);
|
||||
return; /* an error occurred */
|
||||
|
@ -364,7 +402,7 @@ do_define()
|
|||
ch = GetChar();
|
||||
}
|
||||
/* read the replacement text if there is any */
|
||||
ch = skipspaces(ch,0); /* find first character of the text */
|
||||
ch = skipspaces(ch, 0); /* find first character of the text */
|
||||
assert(ch != EOI);
|
||||
/* UnGetChar() is not right when replacement starts with a '/' */
|
||||
ChPushBack(ch);
|
||||
|
@ -383,12 +421,15 @@ push_if()
|
|||
|
||||
do_elif()
|
||||
{
|
||||
if (nestlevel <= svnestlevel[nestcount]) {
|
||||
if (nestlevel <= svnestlevel[nestcount])
|
||||
{
|
||||
error("#elif without corresponding #if");
|
||||
SkipToNewLine();
|
||||
}
|
||||
else { /* restart at this level as if a #if is detected. */
|
||||
if (ifstack[nestlevel]) {
|
||||
else
|
||||
{ /* restart at this level as if a #if is detected. */
|
||||
if (ifstack[nestlevel])
|
||||
{
|
||||
error("#elif after #else");
|
||||
SkipToNewLine();
|
||||
}
|
||||
|
@ -400,14 +441,17 @@ do_elif()
|
|||
|
||||
do_else()
|
||||
{
|
||||
if (SkipToNewLine()) {
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
if (!options['o'])
|
||||
strict("garbage following #else");
|
||||
}
|
||||
if (nestlevel <= svnestlevel[nestcount])
|
||||
error("#else without corresponding #if");
|
||||
else { /* mark this level as else-d */
|
||||
if (ifstack[nestlevel]) {
|
||||
else
|
||||
{ /* mark this level as else-d */
|
||||
if (ifstack[nestlevel])
|
||||
{
|
||||
error("#else after #else");
|
||||
}
|
||||
++(ifstack[nestlevel]);
|
||||
|
@ -417,14 +461,17 @@ do_else()
|
|||
|
||||
do_endif()
|
||||
{
|
||||
if (SkipToNewLine()) {
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
if (!options['o'])
|
||||
strict("garbage following #endif");
|
||||
}
|
||||
if (nestlevel <= svnestlevel[nestcount]) {
|
||||
if (nestlevel <= svnestlevel[nestcount])
|
||||
{
|
||||
error("#endif without corresponding #if");
|
||||
}
|
||||
else nestlevel--;
|
||||
else
|
||||
nestlevel--;
|
||||
}
|
||||
|
||||
do_if()
|
||||
|
@ -436,23 +483,26 @@ do_if()
|
|||
|
||||
do_ifdef(how)
|
||||
{
|
||||
register struct idf *id;
|
||||
register char *str;
|
||||
register struct idf* id;
|
||||
register char* str;
|
||||
|
||||
/* how == 1 : ifdef; how == 0 : ifndef
|
||||
*/
|
||||
push_if();
|
||||
if (!(str = GetIdentifier(1))) {
|
||||
if (!(str = GetIdentifier(1)))
|
||||
{
|
||||
error("illegal #ifdef construction");
|
||||
id = (struct idf *)0;
|
||||
} else {
|
||||
id = (struct idf*)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = findidf(str);
|
||||
free(str);
|
||||
}
|
||||
if (SkipToNewLine()) {
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
if (str && !options['o'])
|
||||
strict("garbage following #%s <identifier>",
|
||||
how ? "ifdef" : "ifndef");
|
||||
strict("garbage following #%s <identifier>", how ? "ifdef" : "ifndef");
|
||||
}
|
||||
|
||||
/* The next test is a shorthand for:
|
||||
|
@ -463,26 +513,32 @@ do_ifdef(how)
|
|||
}
|
||||
|
||||
/* argstr != NULL when the undef came from a -U option */
|
||||
do_undef(argstr)
|
||||
char *argstr;
|
||||
do_undef(argstr) char* argstr;
|
||||
{
|
||||
register struct idf *id;
|
||||
register char *str = argstr;
|
||||
register struct idf* id;
|
||||
register char* str = argstr;
|
||||
|
||||
/* Forget a macro definition. */
|
||||
if (str || (str = GetIdentifier(1))) {
|
||||
if ((id = findidf(str)) && id->id_macro) {
|
||||
if (id->id_macro->mc_flag & NOUNDEF) {
|
||||
if (str || (str = GetIdentifier(1)))
|
||||
{
|
||||
if ((id = findidf(str)) && id->id_macro)
|
||||
{
|
||||
if (id->id_macro->mc_flag & NOUNDEF)
|
||||
{
|
||||
error("it is not allowed to #undef %s", str);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
free(id->id_macro->mc_text);
|
||||
free_macro(id->id_macro);
|
||||
id->id_macro = (struct macro *) 0;
|
||||
id->id_macro = (struct macro*)0;
|
||||
}
|
||||
} /* else: don't complain */
|
||||
if (!argstr){
|
||||
if (!argstr)
|
||||
{
|
||||
free(str);
|
||||
if (SkipToNewLine()) {
|
||||
if (SkipToNewLine())
|
||||
{
|
||||
if (!options['o'])
|
||||
strict("garbage following #undef");
|
||||
}
|
||||
|
@ -495,18 +551,16 @@ do_undef(argstr)
|
|||
do_error()
|
||||
{
|
||||
int len;
|
||||
char *get_text();
|
||||
char *bp = get_text((char **) 0, &len);
|
||||
char* get_text();
|
||||
char* bp = get_text((char**)0, &len);
|
||||
|
||||
error("user error: %s", bp);
|
||||
free(bp);
|
||||
LineNumber++;
|
||||
}
|
||||
|
||||
int
|
||||
getparams(buf, parbuf)
|
||||
char *buf[];
|
||||
char parbuf[];
|
||||
int getparams(buf, parbuf) char* buf[];
|
||||
char parbuf[];
|
||||
{
|
||||
/* getparams() reads the formal parameter list of a macro
|
||||
definition.
|
||||
|
@ -518,19 +572,22 @@ getparams(buf, parbuf)
|
|||
Note that the '(' has already been eaten.
|
||||
The names of the formal parameters are stored into parbuf.
|
||||
*/
|
||||
register char **pbuf = &buf[0];
|
||||
register char** pbuf = &buf[0];
|
||||
register int c;
|
||||
register char *ptr = &parbuf[0];
|
||||
register char **pbuf2;
|
||||
register char* ptr = &parbuf[0];
|
||||
register char** pbuf2;
|
||||
|
||||
c = GetChar();
|
||||
c = skipspaces(c,0);
|
||||
if (c == ')') { /* no parameters: #define name() */
|
||||
*pbuf = (char *) 0;
|
||||
c = skipspaces(c, 0);
|
||||
if (c == ')')
|
||||
{ /* no parameters: #define name() */
|
||||
*pbuf = (char*)0;
|
||||
return 0;
|
||||
}
|
||||
for (;;) { /* eat the formal parameter list */
|
||||
if (class(c) != STIDF && class(c) != STELL) {
|
||||
for (;;)
|
||||
{ /* eat the formal parameter list */
|
||||
if (class(c) != STIDF && class(c) != STELL)
|
||||
{
|
||||
error("#define: bad formal parameter");
|
||||
return -1;
|
||||
}
|
||||
|
@ -538,7 +595,8 @@ getparams(buf, parbuf)
|
|||
*ptr++ = c;
|
||||
if (ptr >= &parbuf[PARBUFSIZE])
|
||||
fatal("formal parameter buffer overflow");
|
||||
do { /* eat the identifier name */
|
||||
do
|
||||
{ /* eat the identifier name */
|
||||
c = GetChar();
|
||||
*ptr++ = c;
|
||||
if (ptr >= &parbuf[PARBUFSIZE])
|
||||
|
@ -549,52 +607,61 @@ getparams(buf, parbuf)
|
|||
/* Check if this formal parameter is already used.
|
||||
Usually, macros do not have many parameters, so ...
|
||||
*/
|
||||
for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
|
||||
if (!strcmp(*pbuf2, *pbuf)) {
|
||||
warning("formal parameter \"%s\" already used",
|
||||
*pbuf);
|
||||
for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--)
|
||||
{
|
||||
if (!strcmp(*pbuf2, *pbuf))
|
||||
{
|
||||
warning("formal parameter \"%s\" already used", *pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
pbuf++;
|
||||
c = skipspaces(c,0);
|
||||
if (c == ')') { /* end of the formal parameter list */
|
||||
*pbuf = (char *) 0;
|
||||
c = skipspaces(c, 0);
|
||||
if (c == ')')
|
||||
{ /* end of the formal parameter list */
|
||||
*pbuf = (char*)0;
|
||||
return pbuf - buf;
|
||||
}
|
||||
if (c != ',') {
|
||||
if (c != ',')
|
||||
{
|
||||
error("#define: bad formal parameter list");
|
||||
return -1;
|
||||
}
|
||||
c = GetChar();
|
||||
c = skipspaces(c,0);
|
||||
c = skipspaces(c, 0);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
void
|
||||
macro_def(id, text, nformals, length, flags)
|
||||
register struct idf *id;
|
||||
char *text;
|
||||
void macro_def(id, text, nformals, length, flags) register struct idf* id;
|
||||
char* text;
|
||||
{
|
||||
register struct macro *newdef = id->id_macro;
|
||||
register struct macro* newdef = id->id_macro;
|
||||
|
||||
/* macro_def() puts the contents and information of a macro
|
||||
definition into a structure and stores it into the symbol
|
||||
table entry belonging to the name of the macro.
|
||||
An error is given if there was already a definition
|
||||
*/
|
||||
if (newdef) { /* is there a redefinition? */
|
||||
if (newdef->mc_flag & NOUNDEF) {
|
||||
if (newdef)
|
||||
{ /* is there a redefinition? */
|
||||
if (newdef->mc_flag & NOUNDEF)
|
||||
{
|
||||
error("it is not allowed to redefine %s", id->id_text);
|
||||
} else if (!macroeq(newdef->mc_text, text))
|
||||
}
|
||||
else if (!macroeq(newdef->mc_text, text))
|
||||
error("illegal redefine of \"%s\"", id->id_text);
|
||||
free(text);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DOBITS
|
||||
register char *p = id->id_text;
|
||||
#define setbit(bx) if (!*p) goto go_on; bits[*p++] |= (bx)
|
||||
register char* p = id->id_text;
|
||||
#define setbit(bx) \
|
||||
if (!*p) \
|
||||
goto go_on; \
|
||||
bits[*p++] |= (bx)
|
||||
setbit(bit0);
|
||||
setbit(bit1);
|
||||
setbit(bit2);
|
||||
|
@ -614,15 +681,13 @@ macro_def(id, text, nformals, length, flags)
|
|||
newdef->mc_flag = flags; /* special flags */
|
||||
}
|
||||
|
||||
int
|
||||
find_name(nm, index)
|
||||
char *nm, *index[];
|
||||
int find_name(nm, index) char *nm, *index[];
|
||||
{
|
||||
/* find_name() returns the index of "nm" in the namelist
|
||||
"index" if it can be found there. 0 is returned if it is
|
||||
not there.
|
||||
*/
|
||||
register char **ip = &index[0];
|
||||
register char** ip = &index[0];
|
||||
|
||||
while (*ip)
|
||||
if (strcmp(nm, *ip++) == 0)
|
||||
|
@ -633,10 +698,8 @@ find_name(nm, index)
|
|||
|
||||
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
|
||||
|
||||
char *
|
||||
get_text(formals, length)
|
||||
char *formals[];
|
||||
int *length;
|
||||
char* get_text(formals, length) char* formals[];
|
||||
int* length;
|
||||
{
|
||||
/* get_text() copies the replacement text of a macro
|
||||
definition with zero, one or more parameters, thereby
|
||||
|
@ -662,104 +725,138 @@ get_text(formals, length)
|
|||
*/
|
||||
register int c;
|
||||
struct repl repls;
|
||||
register struct repl *repl = &repls;
|
||||
register struct repl* repl = &repls;
|
||||
int blank = 0;
|
||||
|
||||
c = GetChar();
|
||||
|
||||
repl->r_ptr = repl->r_text = Malloc((unsigned)(repl->r_size = ITEXTSIZE));
|
||||
*repl->r_ptr = '\0';
|
||||
while ((c != EOI) && (class(c) != STNL)) {
|
||||
if (BLANK(c)) {
|
||||
while ((c != EOI) && (class(c) != STNL))
|
||||
{
|
||||
if (BLANK(c))
|
||||
{
|
||||
blank++;
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\'' || c == '"') {
|
||||
if (c == '\'' || c == '"')
|
||||
{
|
||||
register int delim = c;
|
||||
|
||||
if (blank) {
|
||||
if (blank)
|
||||
{
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
do {
|
||||
do
|
||||
{
|
||||
add2repl(repl, c);
|
||||
if (c == '\\') add2repl(repl, GetChar());
|
||||
if (c == '\\')
|
||||
add2repl(repl, GetChar());
|
||||
c = GetChar();
|
||||
} while (c != delim && c != EOI && class(c) != STNL);
|
||||
if (c != delim) {
|
||||
if (c != delim)
|
||||
{
|
||||
strict("unclosed opening %c", delim);
|
||||
break;
|
||||
}
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
} else if (c == '/') {
|
||||
}
|
||||
else if (c == '/')
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '*') {
|
||||
if (c == '*')
|
||||
{
|
||||
skipcomment();
|
||||
blank++;
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
if (blank) {
|
||||
else if (c == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
blank++;
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
if (blank)
|
||||
{
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
add2repl(repl, '/');
|
||||
} else if (formals
|
||||
&& (class(c) == STIDF || class(c) == STELL)) {
|
||||
}
|
||||
else if (formals && (class(c) == STIDF || class(c) == STELL))
|
||||
{
|
||||
char id_buf[IDFSIZE + 1];
|
||||
register char *idp = id_buf;
|
||||
register char* idp = id_buf;
|
||||
int n;
|
||||
|
||||
/* read identifier: it may be a formal parameter */
|
||||
*idp++ = c;
|
||||
do {
|
||||
do
|
||||
{
|
||||
c = GetChar();
|
||||
if (idp <= &id_buf[IDFSIZE])
|
||||
*idp++ = c;
|
||||
} while (in_idf(c));
|
||||
*--idp = '\0';
|
||||
|
||||
if (blank) {
|
||||
if (blank)
|
||||
{
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
/* construct the formal parameter mark or identifier */
|
||||
if (n = find_name(id_buf, formals))
|
||||
add2repl(repl, FORMALP | (char) n);
|
||||
else {
|
||||
add2repl(repl, FORMALP | (char)n);
|
||||
else
|
||||
{
|
||||
idp = id_buf;
|
||||
while (*idp) add2repl(repl, *idp++);
|
||||
while (*idp)
|
||||
add2repl(repl, *idp++);
|
||||
}
|
||||
} else if (class(c) == STNUM) {
|
||||
if (blank) {
|
||||
}
|
||||
else if (class(c) == STNUM)
|
||||
{
|
||||
if (blank)
|
||||
{
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
add2repl(repl, c);
|
||||
if (c == '.') {
|
||||
if (c == '.')
|
||||
{
|
||||
c = GetChar();
|
||||
if (class(c) != STNUM) {
|
||||
if (class(c) != STNUM)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
add2repl(repl, c);
|
||||
}
|
||||
c = GetChar();
|
||||
while(in_idf(c) || c == '.') {
|
||||
while (in_idf(c) || c == '.')
|
||||
{
|
||||
add2repl(repl, c);
|
||||
if((c = GetChar()) == 'e' || c == 'E') {
|
||||
if ((c = GetChar()) == 'e' || c == 'E')
|
||||
{
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
if (c == '+' || c == '-') {
|
||||
if (c == '+' || c == '-')
|
||||
{
|
||||
add2repl(repl, c);
|
||||
c = GetChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (blank) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (blank)
|
||||
{
|
||||
blank = 0;
|
||||
add2repl(repl, ' ');
|
||||
}
|
||||
|
@ -768,7 +865,7 @@ get_text(formals, length)
|
|||
}
|
||||
}
|
||||
*length = repl->r_ptr - repl->r_text;
|
||||
return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text +1));
|
||||
return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text + 1));
|
||||
}
|
||||
|
||||
/* macroeq() decides whether two macro replacement texts are
|
||||
|
@ -776,36 +873,42 @@ get_text(formals, length)
|
|||
as strings, without taking care of the leading and trailing
|
||||
blanks (spaces and tabs).
|
||||
*/
|
||||
macroeq(s, t)
|
||||
register char *s, *t;
|
||||
macroeq(s, t) register char* s, *t;
|
||||
{
|
||||
|
||||
/* skip leading spaces */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
while (BLANK(*s))
|
||||
s++;
|
||||
while (BLANK(*t))
|
||||
t++;
|
||||
/* first non-blank encountered in both strings */
|
||||
/* The actual comparison loop: */
|
||||
while (*s && *s == *t)
|
||||
s++, t++;
|
||||
/* two cases are possible when arrived here: */
|
||||
if (*s == '\0') { /* *s == '\0' */
|
||||
while (BLANK(*t)) t++;
|
||||
if (*s == '\0')
|
||||
{ /* *s == '\0' */
|
||||
while (BLANK(*t))
|
||||
t++;
|
||||
return *t == '\0';
|
||||
}
|
||||
else { /* *s != *t */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
else
|
||||
{ /* *s != *t */
|
||||
while (BLANK(*s))
|
||||
s++;
|
||||
while (BLANK(*t))
|
||||
t++;
|
||||
return (*s == '\0') && (*t == '\0');
|
||||
}
|
||||
}
|
||||
|
||||
do_line(l)
|
||||
unsigned int l;
|
||||
do_line(l) unsigned int l;
|
||||
{
|
||||
struct token tk;
|
||||
int t = GetToken(&tk);
|
||||
|
||||
if (t != EOF) SkipToNewLine();
|
||||
if (t != EOF)
|
||||
SkipToNewLine();
|
||||
LineNumber = l; /* the number of the next input line */
|
||||
if (t == STRING) /* is there a filespecifier? */
|
||||
FileName = tk.tk_str;
|
||||
|
|
|
@ -24,73 +24,94 @@ char bits[128];
|
|||
#endif
|
||||
extern int InputLevel;
|
||||
|
||||
extern char *sprint();
|
||||
extern char* sprint();
|
||||
|
||||
Xflush()
|
||||
{
|
||||
sys_write(STDOUT, _obuf, OBUFSIZE);
|
||||
}
|
||||
|
||||
static char *SkipComment();
|
||||
static char* SkipComment();
|
||||
extern char options[];
|
||||
|
||||
/* #pragma directives are saved here and passed to the compiler later on.
|
||||
*/
|
||||
struct prag_info {
|
||||
struct prag_info
|
||||
{
|
||||
int pr_linnr;
|
||||
char *pr_fil;
|
||||
char *pr_text;
|
||||
char* pr_fil;
|
||||
char* pr_text;
|
||||
};
|
||||
static struct prag_info *pragma_tab;
|
||||
static struct prag_info* pragma_tab;
|
||||
static int pragma_nr;
|
||||
|
||||
do_pragma()
|
||||
{
|
||||
register int size = ITEXTSIZE;
|
||||
char *cur_line = Malloc((unsigned)size);
|
||||
register char *c_ptr = cur_line;
|
||||
char* cur_line = Malloc((unsigned)size);
|
||||
register char* c_ptr = cur_line;
|
||||
register int c = GetChar();
|
||||
register int delim = 0;
|
||||
|
||||
while(c != '\n') {
|
||||
if (c_ptr + 1 - cur_line == size) {
|
||||
while (c != '\n')
|
||||
{
|
||||
if (c_ptr + 1 - cur_line == size)
|
||||
{
|
||||
cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
|
||||
c_ptr = cur_line + size - 1;
|
||||
size += ITEXTSIZE;
|
||||
}
|
||||
if (delim) {
|
||||
if (c == delim) {
|
||||
if (delim)
|
||||
{
|
||||
if (c == delim)
|
||||
{
|
||||
delim = 0;
|
||||
}
|
||||
else if (c == '\\') {
|
||||
else if (c == '\\')
|
||||
{
|
||||
*c_ptr++ = c;
|
||||
c = GetChar();
|
||||
if (c == '\n') break;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (c == '\'' || c == '"') {
|
||||
else if (c == '\'' || c == '"')
|
||||
{
|
||||
delim = c;
|
||||
}
|
||||
else if (c == '/') {
|
||||
if ((c = GetChar()) != '*' || InputLevel) {
|
||||
*c_ptr++ = '/';
|
||||
}
|
||||
else {
|
||||
else if (c == '/')
|
||||
{
|
||||
if (!InputLevel)
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '*')
|
||||
{
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
else if (c == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
continue;
|
||||
}
|
||||
*c_ptr++ = '/';
|
||||
}
|
||||
}
|
||||
*c_ptr++ = c;
|
||||
c = GetChar();
|
||||
}
|
||||
*c_ptr = '\0';
|
||||
if (!pragma_nr) {
|
||||
pragma_tab = (struct prag_info *)Malloc(sizeof(struct prag_info));
|
||||
} else {
|
||||
pragma_tab = (struct prag_info *)Realloc((char *)pragma_tab
|
||||
, (unsigned)(sizeof(struct prag_info) * (pragma_nr+1)));
|
||||
if (!pragma_nr)
|
||||
{
|
||||
pragma_tab = (struct prag_info*)Malloc(sizeof(struct prag_info));
|
||||
}
|
||||
if (delim) {
|
||||
else
|
||||
{
|
||||
pragma_tab = (struct prag_info*)Realloc(
|
||||
(char*)pragma_tab, (unsigned)(sizeof(struct prag_info) * (pragma_nr + 1)));
|
||||
}
|
||||
if (delim)
|
||||
{
|
||||
error("unclosed opening %c", delim);
|
||||
}
|
||||
pragma_tab[pragma_nr].pr_linnr = LineNumber;
|
||||
|
@ -102,98 +123,130 @@ do_pragma()
|
|||
|
||||
char Xbuf[256];
|
||||
|
||||
void
|
||||
preprocess(fn)
|
||||
char *fn;
|
||||
void preprocess(fn) char* fn;
|
||||
{
|
||||
register int c;
|
||||
register char *op = _obuf;
|
||||
register char *ob = &_obuf[OBUFSIZE];
|
||||
register char* op = _obuf;
|
||||
register char* ob = &_obuf[OBUFSIZE];
|
||||
int lineno = 0;
|
||||
int startline;
|
||||
|
||||
#define flush(X) (sys_write(STDOUT,_obuf,X))
|
||||
#define echo(ch) if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
|
||||
#define newline() op--; while (op >= _obuf && (*op == ' ' || *op == '\t')) op--; op++; echo('\n')
|
||||
#define flush(X) (sys_write(STDOUT, _obuf, X))
|
||||
#define echo(ch) \
|
||||
if (op == ob) \
|
||||
{ \
|
||||
Xflush(); \
|
||||
op = _obuf; \
|
||||
} \
|
||||
*op++ = (ch);
|
||||
#define newline() \
|
||||
op--; \
|
||||
while (op >= _obuf && (*op == ' ' || *op == '\t')) \
|
||||
op--; \
|
||||
op++; \
|
||||
echo('\n')
|
||||
|
||||
if (!options['P']) {
|
||||
if (!options['P'])
|
||||
{
|
||||
/* Generate a line directive communicating the
|
||||
source filename
|
||||
*/
|
||||
register char *p = Xbuf;
|
||||
register char* p = Xbuf;
|
||||
|
||||
sprint(p, "%s 1 \"%s\"\n",
|
||||
LINE_PREFIX,
|
||||
FileName);
|
||||
while (*p) {
|
||||
sprint(p, "%s 1 \"%s\"\n", LINE_PREFIX, FileName);
|
||||
while (*p)
|
||||
{
|
||||
echo(*p++);
|
||||
}
|
||||
}
|
||||
|
||||
#define do_line_dir(lineno, fn) \
|
||||
if (lineno != LineNumber || fn != FileName) { \
|
||||
if (lineno != LineNumber || fn != FileName) \
|
||||
{ \
|
||||
fn = FileName; \
|
||||
lineno = LineNumber; \
|
||||
if (! options['P']) { \
|
||||
register char *p = Xbuf; \
|
||||
sprint(Xbuf, "%s %d \"%s\"\n", \
|
||||
LINE_PREFIX, \
|
||||
(int)LineNumber, \
|
||||
FileName); \
|
||||
if (!options['P']) \
|
||||
{ \
|
||||
register char* p = Xbuf; \
|
||||
sprint(Xbuf, "%s %d \"%s\"\n", LINE_PREFIX, (int)LineNumber, FileName); \
|
||||
op--; \
|
||||
while (op >= _obuf && (class(*op) == STSKIP || *op == '\n')) \
|
||||
op--; \
|
||||
while (op >= _obuf \
|
||||
&& (class(*op) == STSKIP \
|
||||
|| *op == '\n')) op--; \
|
||||
op++; \
|
||||
newline(); \
|
||||
while (*p) { \
|
||||
while (*p) \
|
||||
{ \
|
||||
echo(*p++); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
LineNumber++;
|
||||
lineno++;
|
||||
startline = 1;
|
||||
c = GetChar();
|
||||
while (startline) {
|
||||
while (startline)
|
||||
{
|
||||
/* first flush the saved pragma's */
|
||||
if (pragma_nr) {
|
||||
if (pragma_nr)
|
||||
{
|
||||
register int i = 0;
|
||||
int LiNo = LineNumber;
|
||||
char *FiNam = FileName;
|
||||
char* FiNam = FileName;
|
||||
|
||||
while (i < pragma_nr) {
|
||||
register char *c_ptr = "#pragma";
|
||||
while (i < pragma_nr)
|
||||
{
|
||||
register char* c_ptr = "#pragma";
|
||||
|
||||
LineNumber = pragma_tab[i].pr_linnr;
|
||||
FileName = pragma_tab[i].pr_fil;
|
||||
do_line_dir(lineno, fn);
|
||||
while (*c_ptr) { echo(*c_ptr++); }
|
||||
while (*c_ptr)
|
||||
{
|
||||
echo(*c_ptr++);
|
||||
}
|
||||
c_ptr = pragma_tab[i].pr_text;
|
||||
while (*c_ptr) { echo(*c_ptr++); }
|
||||
newline(); lineno++;
|
||||
while (*c_ptr)
|
||||
{
|
||||
echo(*c_ptr++);
|
||||
}
|
||||
newline();
|
||||
lineno++;
|
||||
free(pragma_tab[i].pr_text);
|
||||
i++;
|
||||
}
|
||||
free((char *) pragma_tab);
|
||||
pragma_tab = (struct prag_info *)0;
|
||||
free((char*)pragma_tab);
|
||||
pragma_tab = (struct prag_info*)0;
|
||||
pragma_nr = 0;
|
||||
LineNumber = LiNo;
|
||||
FileName = FiNam;
|
||||
do_line_dir(lineno, fn);
|
||||
}
|
||||
|
||||
|
||||
while (class(c) == STSKIP || c == '/') {
|
||||
if (c == '/') {
|
||||
if (!InputLevel) {
|
||||
while (class(c) == STSKIP || c == '/')
|
||||
{
|
||||
if (c == '/')
|
||||
{
|
||||
if (!InputLevel)
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '*') {
|
||||
if (c == '*')
|
||||
{
|
||||
op = SkipComment(op, &lineno);
|
||||
if (!op) return;
|
||||
if (!options['C']) { echo(' '); }
|
||||
if (!op)
|
||||
return;
|
||||
if (!options['C'])
|
||||
{
|
||||
echo(' ');
|
||||
}
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
else if (c == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
@ -206,34 +259,52 @@ preprocess(fn)
|
|||
c = GetChar();
|
||||
}
|
||||
|
||||
if (c == '#') {
|
||||
if (c == '#')
|
||||
{
|
||||
domacro();
|
||||
lineno++;
|
||||
newline();
|
||||
do_line_dir(lineno, fn);
|
||||
c = GetChar();
|
||||
} else startline = 0;
|
||||
}
|
||||
else
|
||||
startline = 0;
|
||||
}
|
||||
do_line_dir(lineno, fn);
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
|
||||
/* illegal character */
|
||||
if (c & 0200) {
|
||||
if (c == EOI) {
|
||||
if (c & 0200)
|
||||
{
|
||||
if (c == EOI)
|
||||
{
|
||||
newline();
|
||||
flush((int)(op-_obuf));
|
||||
flush((int)(op - _obuf));
|
||||
return;
|
||||
}
|
||||
fatal("non-ascii character read");
|
||||
}
|
||||
|
||||
/* comments */
|
||||
if (c == '/' && !InputLevel) {
|
||||
if (c == '/' && !InputLevel)
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '*') {
|
||||
if (c == '*')
|
||||
{
|
||||
op = SkipComment(op, &lineno);
|
||||
if (!op) return;
|
||||
if (!options['C']) { echo(' '); }
|
||||
if (!op)
|
||||
return;
|
||||
if (!options['C'])
|
||||
{
|
||||
echo(' ');
|
||||
}
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
else if (c == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
@ -242,7 +313,8 @@ preprocess(fn)
|
|||
}
|
||||
|
||||
/* switch on character */
|
||||
switch(class(c)) {
|
||||
switch (class(c))
|
||||
{
|
||||
case STNL:
|
||||
newline();
|
||||
break;
|
||||
|
@ -252,26 +324,33 @@ preprocess(fn)
|
|||
register int stopc = c;
|
||||
int escaped;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
escaped = 0;
|
||||
echo(c);
|
||||
c = GetChar();
|
||||
if (c == '\n') {
|
||||
if (c == '\n')
|
||||
{
|
||||
/* the compiler will complain */
|
||||
break;
|
||||
}
|
||||
else if (c == EOI) {
|
||||
else if (c == EOI)
|
||||
{
|
||||
newline();
|
||||
flush((int)(op-_obuf));
|
||||
flush((int)(op - _obuf));
|
||||
return;
|
||||
}
|
||||
if (c == '\\') {
|
||||
if (c == '\\')
|
||||
{
|
||||
echo(c);
|
||||
c = GetChar();
|
||||
if (c == '\n') {
|
||||
if (c == '\n')
|
||||
{
|
||||
++LineNumber;
|
||||
lineno++;
|
||||
} else escaped = 1;
|
||||
}
|
||||
else
|
||||
escaped = 1;
|
||||
}
|
||||
} while (escaped || c != stopc);
|
||||
echo(c);
|
||||
|
@ -285,112 +364,161 @@ preprocess(fn)
|
|||
* ..3 == . .3 , whereas ...3 == ... 3
|
||||
*/
|
||||
echo(c);
|
||||
if (c == '.') {
|
||||
if (c == '.')
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '.') {
|
||||
if ((c = GetChar()) == '.') {
|
||||
echo('.'); echo('.');
|
||||
if (c == '.')
|
||||
{
|
||||
if ((c = GetChar()) == '.')
|
||||
{
|
||||
echo('.');
|
||||
echo('.');
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
UnGetChar();
|
||||
c = '.';
|
||||
continue;
|
||||
} else if (!is_dig(c)) {
|
||||
}
|
||||
else if (!is_dig(c))
|
||||
{
|
||||
continue;
|
||||
} else { echo(c); }
|
||||
}
|
||||
else
|
||||
{
|
||||
echo(c);
|
||||
}
|
||||
}
|
||||
c = GetChar();
|
||||
while (in_idf(c) || c == '.') {
|
||||
while (in_idf(c) || c == '.')
|
||||
{
|
||||
echo(c);
|
||||
if (c == 'e' || c == 'E') {
|
||||
if (c == 'e' || c == 'E')
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '+' || c == '-') {
|
||||
if (c == '+' || c == '-')
|
||||
{
|
||||
echo(c);
|
||||
c = GetChar();
|
||||
}
|
||||
} else c = GetChar();
|
||||
}
|
||||
else
|
||||
c = GetChar();
|
||||
}
|
||||
continue;
|
||||
case STELL:
|
||||
c = GetChar();
|
||||
UnGetChar();
|
||||
if (c == '"' || c == '\'') {
|
||||
if (c == '"' || c == '\'')
|
||||
{
|
||||
echo('L');
|
||||
continue;
|
||||
}
|
||||
c = 'L';
|
||||
case STIDF: {
|
||||
case STIDF:
|
||||
{
|
||||
extern int idfsize; /* ??? */
|
||||
char buf[IDFSIZE + 1];
|
||||
register char *tg = &buf[0];
|
||||
register char *maxpos = &buf[idfsize];
|
||||
register struct idf *idef;
|
||||
register char* tg = &buf[0];
|
||||
register char* maxpos = &buf[idfsize];
|
||||
register struct idf* idef;
|
||||
int NoExpandNext = 0;
|
||||
|
||||
#define tstmac(bx) if (!(bits[c] & bx)) goto nomac
|
||||
#define tstmac(bx) \
|
||||
if (!(bits[c] & bx)) \
|
||||
goto nomac
|
||||
#define cpy *tg++ = c
|
||||
#define load c = GetChar(); if (!in_idf(c)) goto endidf
|
||||
#define load \
|
||||
c = GetChar(); \
|
||||
if (!in_idf(c)) \
|
||||
goto endidf
|
||||
|
||||
/* unstack macro's when allowed. */
|
||||
if (Unstacked)
|
||||
EnableMacros();
|
||||
if (c == NOEXPM) {
|
||||
if (c == NOEXPM)
|
||||
{
|
||||
NoExpandNext = 1;
|
||||
c = GetChar();
|
||||
}
|
||||
|
||||
#ifdef DOBITS
|
||||
cpy; tstmac(bit0); load;
|
||||
cpy; tstmac(bit1); load;
|
||||
cpy; tstmac(bit2); load;
|
||||
cpy; tstmac(bit3); load;
|
||||
cpy; tstmac(bit4); load;
|
||||
cpy; tstmac(bit5); load;
|
||||
cpy; tstmac(bit6); load;
|
||||
cpy; tstmac(bit7); load;
|
||||
cpy;
|
||||
tstmac(bit0);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit1);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit2);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit3);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit4);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit5);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit6);
|
||||
load;
|
||||
cpy;
|
||||
tstmac(bit7);
|
||||
load;
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
if (tg < maxpos) {
|
||||
for (;;)
|
||||
{
|
||||
if (tg < maxpos)
|
||||
{
|
||||
cpy;
|
||||
}
|
||||
load;
|
||||
}
|
||||
endidf:
|
||||
if (c != EOF) UnGetChar();
|
||||
if (c != EOF)
|
||||
UnGetChar();
|
||||
*tg = '\0'; /* mark the end of the identifier */
|
||||
if ((idef = findidf(buf))
|
||||
&& idef->id_macro
|
||||
&& ReplaceMacros && !NoExpandNext) {
|
||||
if (replace(idef)) {
|
||||
if ((idef = findidf(buf)) && idef->id_macro && ReplaceMacros && !NoExpandNext)
|
||||
{
|
||||
if (replace(idef))
|
||||
{
|
||||
echo(' ');
|
||||
c = GetChar();
|
||||
continue;
|
||||
}
|
||||
tg = buf;
|
||||
while (*tg) {
|
||||
while (*tg)
|
||||
{
|
||||
echo(*tg++);
|
||||
}
|
||||
c = GetChar();
|
||||
if (in_idf(c)) { echo(' '); }
|
||||
if (in_idf(c))
|
||||
{
|
||||
echo(' ');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
nomac:
|
||||
*tg = '\0';
|
||||
tg = buf;
|
||||
while (*tg) {
|
||||
while (*tg)
|
||||
{
|
||||
echo(*tg++);
|
||||
}
|
||||
c = GetChar();
|
||||
while (in_idf(c)) {
|
||||
while (in_idf(c))
|
||||
{
|
||||
echo(c);
|
||||
c = GetChar();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case STMSPEC:
|
||||
if (InputLevel) {
|
||||
if (InputLevel)
|
||||
{
|
||||
echo(' '); /* seperate tokens */
|
||||
c = GetChar();
|
||||
continue;
|
||||
|
@ -407,49 +535,60 @@ preprocess(fn)
|
|||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
static char *
|
||||
SkipComment(op, lineno)
|
||||
char *op;
|
||||
int *lineno;
|
||||
static char* SkipComment(op, lineno) char* op;
|
||||
int* lineno;
|
||||
{
|
||||
char *ob = &_obuf[OBUFSIZE];
|
||||
char* ob = &_obuf[OBUFSIZE];
|
||||
register int c, oldc = '\0';
|
||||
|
||||
NoUnstack++;
|
||||
if (options['C']) {
|
||||
if (options['C'])
|
||||
{
|
||||
echo('/');
|
||||
echo('*');
|
||||
}
|
||||
c = GetChar();
|
||||
for(;;) {
|
||||
if (c == EOI) {
|
||||
for (;;)
|
||||
{
|
||||
if (c == EOI)
|
||||
{
|
||||
newline();
|
||||
flush((int)(op - _obuf));
|
||||
op = 0;
|
||||
break;
|
||||
}
|
||||
if (options['C']) {
|
||||
if (options['C'])
|
||||
{
|
||||
echo(c);
|
||||
}
|
||||
if (c == '\n') {
|
||||
if (c == '\n')
|
||||
{
|
||||
++LineNumber;
|
||||
++*lineno;
|
||||
if (!options['C']) {
|
||||
if (!options['C'])
|
||||
{
|
||||
echo(c);
|
||||
}
|
||||
}
|
||||
if (c == '*') {
|
||||
if (c == '*')
|
||||
{
|
||||
c = GetChar();
|
||||
if (c == '/') {
|
||||
if (options['C']) {
|
||||
if (c == '/')
|
||||
{
|
||||
if (options['C'])
|
||||
{
|
||||
echo(c);
|
||||
}
|
||||
break; /* for(;;) */
|
||||
} else if (oldc == '/') {
|
||||
}
|
||||
else if (oldc == '/')
|
||||
{
|
||||
warning("comment inside comment ?");
|
||||
}
|
||||
oldc = '*';
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
oldc = c;
|
||||
c = GetChar();
|
||||
}
|
||||
|
|
|
@ -12,46 +12,57 @@
|
|||
|
||||
extern int InputLevel;
|
||||
|
||||
int
|
||||
skipspaces(ch, skipnl)
|
||||
register int ch;
|
||||
int skipspaces(ch, skipnl) register int ch;
|
||||
{
|
||||
/* skipspaces() skips any white space and returns the first
|
||||
non-space character.
|
||||
*/
|
||||
register int nlseen = 0;
|
||||
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
while (class(ch) == STSKIP)
|
||||
ch = GetChar();
|
||||
if (skipnl && class(ch) == STNL) {
|
||||
if (skipnl && class(ch) == STNL)
|
||||
{
|
||||
ch = GetChar();
|
||||
LineNumber++;
|
||||
nlseen++;
|
||||
continue;
|
||||
}
|
||||
if (ch == TOKSEP && InputLevel) {
|
||||
if (ch == TOKSEP && InputLevel)
|
||||
{
|
||||
ch = GetChar();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* \\\n are handled by trigraph */
|
||||
|
||||
if (ch == '/') {
|
||||
if (ch == '/')
|
||||
{
|
||||
ch = GetChar();
|
||||
if (ch == '*' && !InputLevel) {
|
||||
if (ch == '*' && !InputLevel)
|
||||
{
|
||||
skipcomment();
|
||||
ch = GetChar();
|
||||
}
|
||||
else {
|
||||
else if (ch == '/' && !InputLevel)
|
||||
{
|
||||
skiplinecomment();
|
||||
ch = GetChar();
|
||||
}
|
||||
else
|
||||
{
|
||||
UnGetChar();
|
||||
return '/';
|
||||
}
|
||||
}
|
||||
else if (nlseen && ch == '#') {
|
||||
else if (nlseen && ch == '#')
|
||||
{
|
||||
domacro();
|
||||
ch = GetChar();
|
||||
} else
|
||||
}
|
||||
else
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
@ -62,31 +73,54 @@ SkipToNewLine()
|
|||
register int garbage = 0;
|
||||
register int delim = 0;
|
||||
|
||||
while ((ch = GetChar()) != '\n') {
|
||||
if (delim) {
|
||||
if (ch == '\\') {
|
||||
if (GetChar() == '\n') break;
|
||||
} else if (ch == delim) {
|
||||
while ((ch = GetChar()) != '\n')
|
||||
{
|
||||
if (delim)
|
||||
{
|
||||
if (ch == '\\')
|
||||
{
|
||||
if (GetChar() == '\n')
|
||||
break;
|
||||
}
|
||||
else if (ch == delim)
|
||||
{
|
||||
delim = 0;
|
||||
}
|
||||
continue;
|
||||
} else if (ch == '\'' || ch == '\"') {
|
||||
}
|
||||
else if (ch == '\'' || ch == '\"')
|
||||
{
|
||||
delim = ch;
|
||||
garbage = 1;
|
||||
} else if (ch == '/') {
|
||||
if (GetChar() == '*' && !InputLevel) {
|
||||
}
|
||||
else if (ch == '/')
|
||||
{
|
||||
if (!InputLevel)
|
||||
{
|
||||
int nch = GetChar();
|
||||
if (nch == '*')
|
||||
{
|
||||
skipcomment();
|
||||
continue;
|
||||
}
|
||||
else UnGetChar();
|
||||
else if (nch == '/')
|
||||
{
|
||||
skiplinecomment();
|
||||
continue;
|
||||
}
|
||||
else if (ch == TOKSEP && InputLevel) {
|
||||
else
|
||||
UnGetChar();
|
||||
}
|
||||
}
|
||||
else if (ch == TOKSEP && InputLevel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!is_wsp(ch))
|
||||
garbage = 1;
|
||||
}
|
||||
if (delim) strict("unclosed opening %c", delim);
|
||||
if (delim)
|
||||
strict("unclosed opening %c", delim);
|
||||
++LineNumber;
|
||||
return garbage;
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ int __funccnt = 0;
|
|||
void exit(int status)
|
||||
{
|
||||
/* "Called in reversed order of their registration" */
|
||||
while (__funccnt >= 0)
|
||||
(*__functab[__funccnt])();
|
||||
while (__funccnt)
|
||||
(*__functab[--__funccnt])();
|
||||
|
||||
_exit(status);
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ cprogram {
|
|||
"+real_h",
|
||||
"+type_h",
|
||||
"h+emheaders",
|
||||
"lang/m2/include+headers",
|
||||
"modules+headers",
|
||||
"modules/src/alloc+lib",
|
||||
"modules/src/data+lib",
|
||||
|
|
4
lang/m2/include/build.lua
Normal file
4
lang/m2/include/build.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
clibrary {
|
||||
name = "headers",
|
||||
hdrs = {"./*.h"}
|
||||
}
|
103
lang/m2/include/libm2.h
Normal file
103
lang/m2/include/libm2.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
#ifndef LIBM2_H
|
||||
#define LIBM2_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct array_descr
|
||||
{
|
||||
int lbound;
|
||||
int n_elts_min_one;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
struct int_range_descr
|
||||
{
|
||||
int low, high;
|
||||
};
|
||||
|
||||
struct uint_range_descr
|
||||
{
|
||||
unsigned int low, high;
|
||||
};
|
||||
|
||||
struct long_range_descr
|
||||
{
|
||||
long low, high;
|
||||
};
|
||||
|
||||
struct ulong_range_descr
|
||||
{
|
||||
unsigned long low, high;
|
||||
};
|
||||
|
||||
struct stack_descr
|
||||
{
|
||||
char* addr;
|
||||
int low;
|
||||
unsigned int highminlow;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct proc
|
||||
{
|
||||
unsigned size; /* size of saved stackframe(s) */
|
||||
int (*proc)(void); /* address of coroutine procedure */
|
||||
char* brk; /* stack break of this coroutine */
|
||||
};
|
||||
|
||||
extern void (*handler)(int);
|
||||
extern char** argv;
|
||||
extern int argc;
|
||||
extern char* MainLB;
|
||||
|
||||
extern double absd(double i);
|
||||
extern int CallAtEnd(void (*p)(void));
|
||||
extern int absi(int i);
|
||||
extern int dvi(int j, int i);
|
||||
extern int rmi(int j, int i);
|
||||
extern int sigtrp(int trapno, int signo);
|
||||
extern int stackprio(unsigned n);
|
||||
extern int topsave(void* brkpos, struct proc* proc);
|
||||
extern long absl(long i);
|
||||
extern long dvil(long j, long i);
|
||||
extern long rmil(long j, long i);
|
||||
extern size_t new_stackptr(struct stack_descr* pdscr, int a);
|
||||
extern unsigned int topsize(void* brkpos);
|
||||
extern void SIG(void (*)(int));
|
||||
extern void StringAssign(int dstsiz, int srcsiz, register char* dstaddr, register char* srcaddr);
|
||||
extern void TRP(int trapno);
|
||||
extern void _Arguments_(void);
|
||||
extern void _SYSTEM__NEWPROCESS(int (*p)(void), struct proc* a, unsigned n, struct proc** p1);
|
||||
extern void _SYSTEM__TRANSFER(struct proc** a, struct proc** b);
|
||||
extern void _cleanup(void);
|
||||
extern void adduchk(unsigned a, unsigned b);
|
||||
extern void blockmove(size_t siz, char* dst, char* src);
|
||||
extern void cap(unsigned u);
|
||||
extern void catch (int trapno);
|
||||
extern void copy_array(char* pp, int a);
|
||||
extern void halt(void);
|
||||
extern void init(void);
|
||||
extern void killbss(void);
|
||||
extern void load(size_t siz, register char* addr, int p);
|
||||
extern void muluchk(unsigned a, unsigned b);
|
||||
extern void rcka(struct array_descr* descr, int indx);
|
||||
extern void rcki(struct int_range_descr* descr, int val);
|
||||
extern void rckil(struct long_range_descr* descr, long val);
|
||||
extern void rcku(struct uint_range_descr* descr, unsigned val);
|
||||
extern void rckul(struct ulong_range_descr* descr, unsigned long val);
|
||||
extern void store(size_t siz, register char* addr, int p);
|
||||
extern void subuchk(unsigned a, unsigned b);
|
||||
extern void topload(struct proc* proc);
|
||||
extern void unstackprio(unsigned n);
|
||||
|
||||
/* PROCEDURE Argv(argnum: CARDINAL; VAR argument: ARRAY OF CHAR): CARDINAL; */
|
||||
extern unsigned _Arguments__Argv(int n, char* argument, int l, unsigned int u, int s);
|
||||
|
||||
/* PROCEDURE GetEnv(name: ARRAY OF CHAR; VAR value: ARRAY OF CHAR): CARDINAL; */
|
||||
extern unsigned _Arguments__GetEnv(
|
||||
char* name, int nn, unsigned int nu, int ns, char* value, int l, unsigned int u, int s);
|
||||
|
||||
/* PROCEDURE Message(str: ARRAY OF CHAR); */
|
||||
extern void _Traps__Message(char* str, int nn, unsigned int nu, int ns);
|
||||
|
||||
#endif
|
16
lang/m2/include/m2_traps.h
Normal file
16
lang/m2/include/m2_traps.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
|
||||
/* Modula-2 runtime errors */
|
||||
|
||||
#define M2_TOOLARGE 64 /* stack of process too large */
|
||||
#define M2_TOOMANY 65 /* too many nested traps & handlers */
|
||||
#define M2_NORESULT 66 /* no RETURN from procedure function */
|
||||
#define M2_UOVFL 67 /* cardinal overflow */
|
||||
#define M2_FORCH 68 /* FOR-loop control variable changed */
|
||||
#define M2_UUVFL 69 /* cardinal underflow */
|
||||
#define M2_INTERNAL 70 /* internal error, should not happen */
|
||||
#define M2_UNIXSIG 71 /* unix signal */
|
|
@ -8,66 +8,65 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include "libm2.h"
|
||||
|
||||
extern char **argv, **environ;
|
||||
extern int argc;
|
||||
unsigned int _Arguments__Argc;
|
||||
|
||||
static char *
|
||||
findname(s1, s2)
|
||||
register char *s1, *s2;
|
||||
static char* findname(char* s1, char* s2)
|
||||
{
|
||||
|
||||
while (*s1 == *s2++) s1++;
|
||||
if (*s1 == '\0' && *(s2-1) == '=') return s2;
|
||||
while (*s1 == *s2++)
|
||||
s1++;
|
||||
if (*s1 == '\0' && *(s2 - 1) == '=')
|
||||
return s2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
scopy(src, dst, max)
|
||||
register char *src, *dst;
|
||||
unsigned int max;
|
||||
static unsigned int scopy(char* src, char* dst, unsigned int max)
|
||||
{
|
||||
register unsigned int i = 0;
|
||||
|
||||
while (*src && i <= max) {
|
||||
while (*src && i <= max)
|
||||
{
|
||||
i++;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
if (i <= max) {
|
||||
if (i <= max)
|
||||
{
|
||||
*dst = '\0';
|
||||
return i+1;
|
||||
return i + 1;
|
||||
}
|
||||
while (*src++) i++;
|
||||
while (*src++)
|
||||
i++;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
_Arguments_()
|
||||
void _Arguments_(void)
|
||||
{
|
||||
_Arguments__Argc = argc;
|
||||
}
|
||||
|
||||
unsigned
|
||||
_Arguments__Argv(n, argument, l, u, s)
|
||||
unsigned int u;
|
||||
char *argument;
|
||||
unsigned int _Arguments__Argv(int n, char* argument, int l, unsigned int u, int s)
|
||||
{
|
||||
|
||||
if (n >= argc) return 0;
|
||||
if (n >= argc)
|
||||
return 0;
|
||||
return scopy(argv[n], argument, u);
|
||||
}
|
||||
|
||||
unsigned
|
||||
_Arguments__GetEnv(name, nn, nu, ns, value, l, u, s)
|
||||
char *name, *value;
|
||||
unsigned int nu, u;
|
||||
unsigned int _Arguments__GetEnv(
|
||||
char* name, int nn, unsigned int nu, int ns, char* value, int l, unsigned int u, int s)
|
||||
{
|
||||
register char **p = environ;
|
||||
register char *v = 0;
|
||||
register char** p = environ;
|
||||
register char* v = 0;
|
||||
|
||||
while (*p && !(v = findname(name, *p++))) {
|
||||
while (*p && !(v = findname(name, *p++)))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
if (!v) return 0;
|
||||
if (!v)
|
||||
return 0;
|
||||
return scopy(v, value, u);
|
||||
}
|
||||
|
|
|
@ -17,30 +17,25 @@
|
|||
the user specifies this space.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "libm2.h"
|
||||
#include <m2_traps.h>
|
||||
|
||||
#define MAXMAIN 2048
|
||||
|
||||
struct proc {
|
||||
unsigned size; /* size of saved stackframe(s) */
|
||||
int (*proc)(); /* address of coroutine procedure */
|
||||
char *brk; /* stack break of this coroutine */
|
||||
};
|
||||
static struct proc mainproc[MAXMAIN / sizeof(struct proc) + 1];
|
||||
|
||||
extern unsigned topsize();
|
||||
static struct proc* curproc = 0; /* current coroutine */
|
||||
extern char* MainLB; /* stack break of main routine */
|
||||
|
||||
static struct proc mainproc[MAXMAIN/sizeof(struct proc) + 1];
|
||||
|
||||
static struct proc *curproc = 0;/* current coroutine */
|
||||
extern char *MainLB; /* stack break of main routine */
|
||||
|
||||
_SYSTEM__NEWPROCESS(p, a, n, p1)
|
||||
int (*p)(); /* coroutine procedure */
|
||||
struct proc *a; /* pointer to area for saved stack-frame */
|
||||
unsigned n; /* size of this area */
|
||||
struct proc **p1; /* where to leave coroutine descriptor,
|
||||
void _SYSTEM__NEWPROCESS(
|
||||
int (*p)(void) /* coroutine procedure */,
|
||||
struct proc* a /* pointer to area for saved stack-frame */,
|
||||
unsigned int n /* size of this area */,
|
||||
struct proc** p1 /* where to leave coroutine descriptor,
|
||||
in this implementation the address of
|
||||
the area for saved stack-frame(s) */
|
||||
)
|
||||
{
|
||||
/* This procedure creates a new coroutine, but does not
|
||||
transfer control to it. The routine "topsize" will compute the
|
||||
|
@ -49,10 +44,11 @@ _SYSTEM__NEWPROCESS(p, a, n, p1)
|
|||
above this point for this coroutine. In Modula-2, coroutines
|
||||
must be level 0 procedures without parameters.
|
||||
*/
|
||||
char *brk = 0;
|
||||
char* brk = 0;
|
||||
unsigned sz = topsize(&brk);
|
||||
|
||||
if (sz + sizeof(struct proc) > n) {
|
||||
if (sz + sizeof(struct proc) > n)
|
||||
{
|
||||
/* not enough space */
|
||||
TRP(M2_TOOLARGE);
|
||||
}
|
||||
|
@ -60,10 +56,11 @@ _SYSTEM__NEWPROCESS(p, a, n, p1)
|
|||
a->proc = p;
|
||||
a->brk = brk;
|
||||
*p1 = a;
|
||||
if (topsave(brk, a+1))
|
||||
if (topsave(brk, a + 1))
|
||||
/* stack frame saved; now just return */
|
||||
;
|
||||
else {
|
||||
else
|
||||
{
|
||||
/* We get here through the first transfer to the coroutine
|
||||
created above.
|
||||
This also means that curproc is now set to this coroutine.
|
||||
|
@ -76,8 +73,7 @@ _SYSTEM__NEWPROCESS(p, a, n, p1)
|
|||
}
|
||||
}
|
||||
|
||||
_SYSTEM__TRANSFER(a, b)
|
||||
struct proc **a, **b;
|
||||
void _SYSTEM__TRANSFER(struct proc** a, struct proc** b)
|
||||
{
|
||||
/* transfer from one coroutine to another, saving the current
|
||||
descriptor in the space indicated by "a", and transfering to
|
||||
|
@ -85,7 +81,8 @@ _SYSTEM__TRANSFER(a, b)
|
|||
*/
|
||||
unsigned size;
|
||||
|
||||
if (! curproc) {
|
||||
if (!curproc)
|
||||
{
|
||||
/* the current coroutine is the main process;
|
||||
initialize a coroutine descriptor for it ...
|
||||
*/
|
||||
|
@ -94,20 +91,23 @@ _SYSTEM__TRANSFER(a, b)
|
|||
curproc = &mainproc[0];
|
||||
}
|
||||
*a = curproc; /* save current descriptor in "a" */
|
||||
if (*b == curproc) {
|
||||
if (*b == curproc)
|
||||
{
|
||||
/* transfer to itself is a no-op */
|
||||
return;
|
||||
}
|
||||
size = topsize(&(curproc->brk));
|
||||
if (size + sizeof(struct proc) > curproc->size) {
|
||||
if (size + sizeof(struct proc) > curproc->size)
|
||||
{
|
||||
TRP(M2_TOOLARGE);
|
||||
}
|
||||
if (topsave(curproc->brk, curproc+1)) {
|
||||
if (topsave(curproc->brk, curproc + 1))
|
||||
{
|
||||
/* stack top saved. Now restore context of target
|
||||
coroutine
|
||||
*/
|
||||
curproc = *b;
|
||||
topload(curproc+1);
|
||||
topload(curproc + 1);
|
||||
/* we never get here ... */
|
||||
}
|
||||
/* but we do get here, when a transfer is done to the coroutine in "a".
|
||||
|
|
|
@ -9,15 +9,18 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
StringAssign(dstsiz, srcsiz, dstaddr, srcaddr)
|
||||
register char *dstaddr, *srcaddr;
|
||||
#include "libm2.h"
|
||||
|
||||
void StringAssign(int dstsiz, int srcsiz, char* dstaddr, char* srcaddr)
|
||||
{
|
||||
while (srcsiz > 0) {
|
||||
while (srcsiz > 0)
|
||||
{
|
||||
*dstaddr++ = *srcaddr++;
|
||||
srcsiz--;
|
||||
dstsiz--;
|
||||
}
|
||||
if (dstsiz > 0) {
|
||||
if (dstsiz > 0)
|
||||
{
|
||||
*dstaddr = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@ IMPLEMENTATION MODULE Terminal;
|
|||
*)
|
||||
FROM SYSTEM IMPORT ADR;
|
||||
#ifdef __USG
|
||||
FROM Unix IMPORT read, write, open, fcntl;
|
||||
FROM Unix IMPORT read, write, fcntl;
|
||||
#else
|
||||
FROM Unix IMPORT read, write, open, ioctl;
|
||||
FROM Unix IMPORT read, write, ioctl;
|
||||
#endif
|
||||
VAR fildes, fdout: INTEGER;
|
||||
unreadch: CHAR;
|
||||
unread: BOOLEAN;
|
||||
tty: ARRAY[0..8] OF CHAR;
|
||||
(* tty: ARRAY[0..8] OF CHAR; *)
|
||||
|
||||
PROCEDURE Read(VAR ch: CHAR);
|
||||
BEGIN
|
||||
|
@ -115,7 +115,7 @@ BEGIN
|
|||
*)
|
||||
(* dtrg: changed so that instead of opening /dev/tty, fd 0 is always used. *)
|
||||
(* kernigh: sent output to fd 1 *)
|
||||
tty := "stdio";
|
||||
(* tty := "stdio"; *)
|
||||
fildes := 0;
|
||||
fdout := 1;
|
||||
unread := FALSE;
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include "libm2.h"
|
||||
|
||||
#ifndef NOFLOAT
|
||||
double
|
||||
absd(i)
|
||||
double i;
|
||||
double absd(double i)
|
||||
{
|
||||
return i >= 0 ? i : -i;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include "libm2.h"
|
||||
|
||||
absi(i)
|
||||
int absi(int i)
|
||||
{
|
||||
return i >= 0 ? i : -i;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
long
|
||||
absl(i)
|
||||
long i;
|
||||
#include "libm2.h"
|
||||
|
||||
long absl(long i)
|
||||
{
|
||||
return i >= 0 ? i : -i;
|
||||
}
|
||||
|
|
|
@ -8,16 +8,11 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "libm2.h"
|
||||
|
||||
#if _EM_WSIZE==_EM_PSIZE
|
||||
typedef unsigned pcnt;
|
||||
#else
|
||||
typedef unsigned long pcnt;
|
||||
#endif
|
||||
|
||||
blockmove(siz, dst, src)
|
||||
pcnt siz;
|
||||
register char *dst, *src;
|
||||
void blockmove(size_t siz, char* dst, char* src)
|
||||
{
|
||||
while (siz--) *dst++ = *src++;
|
||||
while (siz--)
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ for _, plat in ipairs(vars.plats) do
|
|||
"lang/cem/libcc.ansi/headers+pkg",
|
||||
"plat/"..plat.."/include+pkg",
|
||||
"h+emheaders",
|
||||
"lang/m2/include+headers",
|
||||
},
|
||||
vars = { plat = plat }
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include "libm2.h"
|
||||
|
||||
cap(u)
|
||||
unsigned u;
|
||||
void cap(unsigned int u)
|
||||
{
|
||||
register unsigned *p = &u;
|
||||
register unsigned* p = &u;
|
||||
|
||||
if (*p >= 'a' && *p <= 'z') *p += 'A'-'a';
|
||||
if (*p >= 'a' && *p <= 'z')
|
||||
*p += 'A' - 'a';
|
||||
}
|
||||
|
|
|
@ -11,89 +11,96 @@
|
|||
#include <em_abs.h>
|
||||
#include <m2_traps.h>
|
||||
#include <signal.h>
|
||||
#include "libm2.h"
|
||||
|
||||
static struct errm {
|
||||
int errno;
|
||||
char *errmes;
|
||||
} errors[] = {
|
||||
{ EARRAY, "array bound error"},
|
||||
{ ERANGE, "range bound error"},
|
||||
{ ESET, "set bound error"},
|
||||
{ EIOVFL, "integer overflow"},
|
||||
{ EFOVFL, "real overflow"},
|
||||
{ EFUNFL, "real underflow"},
|
||||
{ EIDIVZ, "divide by 0"},
|
||||
{ EFDIVZ, "divide by 0.0"},
|
||||
{ EIUND, "undefined integer"},
|
||||
{ EFUND, "undefined real"},
|
||||
{ ECONV, "conversion error"},
|
||||
|
||||
{ ESTACK, "stack overflow"},
|
||||
{ EHEAP, "heap overflow"},
|
||||
{ EILLINS, "illegal instruction"},
|
||||
{ EODDZ, "illegal size argument"},
|
||||
{ ECASE, "case error"},
|
||||
{ EMEMFLT, "addressing non existent memory"},
|
||||
{ EBADPTR, "bad pointer used"},
|
||||
{ EBADPC, "program counter out of range"},
|
||||
{ EBADLAE, "bad argument of lae"},
|
||||
{ EBADMON, "bad monitor call"},
|
||||
{ EBADLIN, "argument if LIN too high"},
|
||||
{ EBADGTO, "GTO descriptor error"},
|
||||
|
||||
{ M2_TOOLARGE, "stack size of process too large"},
|
||||
{ M2_TOOMANY, "too many nested traps + handlers"},
|
||||
{ M2_NORESULT, "no RETURN from function procedure"},
|
||||
{ M2_UOVFL, "cardinal overflow"},
|
||||
{ M2_FORCH, "(warning) FOR-loop control variable was changed in the body"},
|
||||
{ M2_UUVFL, "cardinal underflow"},
|
||||
{ M2_INTERNAL, "internal error; ask an expert for help"},
|
||||
{ M2_UNIXSIG, "got a unix signal"},
|
||||
{ -1, 0}
|
||||
};
|
||||
|
||||
catch(trapno)
|
||||
int trapno;
|
||||
static struct errm
|
||||
{
|
||||
register struct errm *ep = &errors[0];
|
||||
char *errmessage;
|
||||
int errno;
|
||||
char* errmes;
|
||||
} errors[] = { { EARRAY, "array bound error" },
|
||||
{ ERANGE, "range bound error" },
|
||||
{ ESET, "set bound error" },
|
||||
{ EIOVFL, "integer overflow" },
|
||||
{ EFOVFL, "real overflow" },
|
||||
{ EFUNFL, "real underflow" },
|
||||
{ EIDIVZ, "divide by 0" },
|
||||
{ EFDIVZ, "divide by 0.0" },
|
||||
{ EIUND, "undefined integer" },
|
||||
{ EFUND, "undefined real" },
|
||||
{ ECONV, "conversion error" },
|
||||
|
||||
{ ESTACK, "stack overflow" },
|
||||
{ EHEAP, "heap overflow" },
|
||||
{ EILLINS, "illegal instruction" },
|
||||
{ EODDZ, "illegal size argument" },
|
||||
{ ECASE, "case error" },
|
||||
{ EMEMFLT, "addressing non existent memory" },
|
||||
{ EBADPTR, "bad pointer used" },
|
||||
{ EBADPC, "program counter out of range" },
|
||||
{ EBADLAE, "bad argument of lae" },
|
||||
{ EBADMON, "bad monitor call" },
|
||||
{ EBADLIN, "argument if LIN too high" },
|
||||
{ EBADGTO, "GTO descriptor error" },
|
||||
|
||||
{ M2_TOOLARGE, "stack size of process too large" },
|
||||
{ M2_TOOMANY, "too many nested traps + handlers" },
|
||||
{ M2_NORESULT, "no RETURN from function procedure" },
|
||||
{ M2_UOVFL, "cardinal overflow" },
|
||||
{ M2_FORCH, "(warning) FOR-loop control variable was changed in the body" },
|
||||
{ M2_UUVFL, "cardinal underflow" },
|
||||
{ M2_INTERNAL, "internal error; ask an expert for help" },
|
||||
{ M2_UNIXSIG, "got a unix signal" },
|
||||
{ -1, 0 } };
|
||||
|
||||
void catch (int trapno)
|
||||
{
|
||||
register struct errm* ep = &errors[0];
|
||||
char* errmessage;
|
||||
char buf[20];
|
||||
register char *p, *s;
|
||||
|
||||
while (ep->errno != trapno && ep->errmes != 0) ep++;
|
||||
if (p = ep->errmes) {
|
||||
while (*p) p++;
|
||||
_Traps__Message(ep->errmes, 0, (int) (p - ep->errmes), 1);
|
||||
while (ep->errno != trapno && ep->errmes != 0)
|
||||
ep++;
|
||||
if (p = ep->errmes)
|
||||
{
|
||||
while (*p)
|
||||
p++;
|
||||
_Traps__Message(ep->errmes, 0, (int)(p - ep->errmes), 1);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
int i = trapno;
|
||||
static char q[] = "error number xxxxxxxxxxxxx";
|
||||
|
||||
p = &q[13];
|
||||
s = buf;
|
||||
if (i < 0) {
|
||||
if (i < 0)
|
||||
{
|
||||
i = -i;
|
||||
*p++ = '-';
|
||||
}
|
||||
do
|
||||
*s++ = i % 10 + '0';
|
||||
while (i /= 10);
|
||||
while (s > buf) *p++ = *--s;
|
||||
while (s > buf)
|
||||
*p++ = *--s;
|
||||
*p = 0;
|
||||
_Traps__Message(q, 0, (int) (p - q), 1);
|
||||
_Traps__Message(q, 0, (int)(p - q), 1);
|
||||
}
|
||||
#if !defined(__em24) && !defined(__em44) && !defined(__em22)
|
||||
if (trapno == M2_UNIXSIG) {
|
||||
if (trapno == M2_UNIXSIG)
|
||||
{
|
||||
extern int __signo;
|
||||
signal(__signo, SIG_DFL);
|
||||
_cleanup();
|
||||
kill(getpid(), __signo);
|
||||
_exit(trapno+1);
|
||||
_exit(trapno + 1);
|
||||
}
|
||||
#endif
|
||||
if (trapno != M2_FORCH) {
|
||||
if (trapno != M2_FORCH)
|
||||
{
|
||||
_cleanup();
|
||||
_exit(trapno+1);
|
||||
_exit(trapno + 1);
|
||||
}
|
||||
SIG(catch);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include "libm2.h"
|
||||
#include <m2_traps.h>
|
||||
|
||||
#ifndef EM_WSIZE
|
||||
|
@ -15,58 +16,43 @@
|
|||
#define EM_PSIZE _EM_PSIZE
|
||||
#endif
|
||||
|
||||
#if EM_WSIZE==EM_PSIZE
|
||||
typedef unsigned pcnt;
|
||||
#else
|
||||
typedef unsigned long pcnt;
|
||||
#endif
|
||||
static struct stack_descr* descrs[10];
|
||||
static struct stack_descr** ppdescr = descrs;
|
||||
|
||||
struct descr {
|
||||
char *addr;
|
||||
int low;
|
||||
unsigned int highminlow;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
static struct descr *descrs[10];
|
||||
static struct descr **ppdescr = descrs;
|
||||
|
||||
pcnt
|
||||
new_stackptr(pdscr, a)
|
||||
struct descr *pdscr;
|
||||
size_t new_stackptr(struct stack_descr* pdescr, int a)
|
||||
{
|
||||
register struct descr *pdescr = pdscr;
|
||||
pcnt size = (((pdescr->highminlow + 1) * pdescr->size +
|
||||
(EM_WSIZE - 1)) & ~(EM_WSIZE - 1));
|
||||
size_t size = (((pdescr->highminlow + 1) * pdescr->size + (EM_WSIZE - 1)) & ~(EM_WSIZE - 1));
|
||||
|
||||
if (ppdescr >= &descrs[10]) {
|
||||
if (ppdescr >= &descrs[10])
|
||||
{
|
||||
/* to many nested traps + handlers ! */
|
||||
TRP(M2_TOOMANY);
|
||||
}
|
||||
*ppdescr++ = pdescr;
|
||||
if ((char *) &a - (char *) &pdscr > 0) {
|
||||
if ((char*)&a - (char*)&pdescr > 0)
|
||||
{
|
||||
/* stack grows downwards */
|
||||
return - size;
|
||||
return -size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
copy_array(pp, a)
|
||||
char *pp;
|
||||
void copy_array(char* p, int a)
|
||||
{
|
||||
register char *p = pp;
|
||||
register char *q;
|
||||
register pcnt sz;
|
||||
char* q;
|
||||
size_t sz;
|
||||
char dummy;
|
||||
|
||||
ppdescr--;
|
||||
sz = ((*ppdescr)->highminlow + 1) * (*ppdescr)->size;
|
||||
|
||||
if ((char *) &a - (char *) &pp > 0) {
|
||||
(*ppdescr)->addr = q = (char *) &a;
|
||||
if ((char*)&a - (char*)&p > 0)
|
||||
{
|
||||
(*ppdescr)->addr = q = (char*)&a;
|
||||
}
|
||||
else (*ppdescr)->addr = q = (char *) &a -
|
||||
((sz + (EM_WSIZE - 1)) & ~ (EM_WSIZE - 1));
|
||||
else
|
||||
(*ppdescr)->addr = q = (char*)&a - ((sz + (EM_WSIZE - 1)) & ~(EM_WSIZE - 1));
|
||||
|
||||
while (sz--) *q++ = *p++;
|
||||
while (sz--)
|
||||
*q++ = *p++;
|
||||
}
|
||||
|
|
|
@ -11,42 +11,49 @@
|
|||
and Modula-2 requires truncation
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <em_abs.h>
|
||||
|
||||
int
|
||||
dvi(j,i)
|
||||
int j,i;
|
||||
int dvi(int j, int i)
|
||||
{
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if ((i < 0) != (j < 0)) {
|
||||
if (i < 0) i = -i;
|
||||
else j = -j;
|
||||
return -((i+j-1)/j);
|
||||
if (j == 0)
|
||||
TRP(EIDIVZ);
|
||||
if ((i < 0) != (j < 0))
|
||||
{
|
||||
if (i < 0)
|
||||
i = -i;
|
||||
else
|
||||
j = -j;
|
||||
return -((i + j - 1) / j);
|
||||
}
|
||||
else return i/j;
|
||||
else
|
||||
return i / j;
|
||||
}
|
||||
|
||||
long
|
||||
dvil(j,i)
|
||||
long j,i;
|
||||
long dvil(long j, long i)
|
||||
{
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if ((i < 0) != (j < 0)) {
|
||||
if (i < 0) i = -i;
|
||||
else j = -j;
|
||||
return -((i+j-1)/j);
|
||||
if (j == 0)
|
||||
TRP(EIDIVZ);
|
||||
if ((i < 0) != (j < 0))
|
||||
{
|
||||
if (i < 0)
|
||||
i = -i;
|
||||
else
|
||||
j = -j;
|
||||
return -((i + j - 1) / j);
|
||||
}
|
||||
else return i/j;
|
||||
else
|
||||
return i / j;
|
||||
}
|
||||
|
||||
int
|
||||
rmi(j,i)
|
||||
int j,i;
|
||||
int rmi(int j, int i)
|
||||
{
|
||||
int m;
|
||||
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if (i == 0) return 0;
|
||||
if (j == 0)
|
||||
TRP(EIDIVZ);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
|
||||
m = i % j;
|
||||
if (m != 0 && (i < 0) != (j < 0))
|
||||
|
@ -54,14 +61,14 @@ rmi(j,i)
|
|||
return m;
|
||||
}
|
||||
|
||||
long
|
||||
rmil(j,i)
|
||||
long j,i;
|
||||
long rmil(long j, long i)
|
||||
{
|
||||
long m;
|
||||
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if (i == 0) return 0L;
|
||||
if (j == 0)
|
||||
TRP(EIDIVZ);
|
||||
if (i == 0)
|
||||
return 0L;
|
||||
|
||||
m = i % j;
|
||||
if (m != 0 && (i < 0) != (j < 0))
|
||||
|
|
|
@ -8,29 +8,32 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "libm2.h"
|
||||
#define MAXPROCS 32
|
||||
|
||||
static int callindex = 0;
|
||||
static int (*proclist[MAXPROCS])();
|
||||
static void (*proclist[MAXPROCS])(void);
|
||||
|
||||
_cleanup()
|
||||
void _cleanup(void)
|
||||
{
|
||||
while (--callindex >= 0)
|
||||
(*proclist[callindex])();
|
||||
callindex = 0;
|
||||
}
|
||||
|
||||
CallAtEnd(p)
|
||||
int (*p)();
|
||||
int CallAtEnd(void (*p)(void))
|
||||
{
|
||||
if (callindex >= MAXPROCS) {
|
||||
if (callindex >= MAXPROCS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
proclist[callindex++] = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
halt()
|
||||
void halt(void)
|
||||
{
|
||||
_cleanup();
|
||||
_exit(0);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <signal.h>
|
||||
#include <em_abs.h>
|
||||
#include <m2_traps.h>
|
||||
#include "libm2.h"
|
||||
|
||||
static const char signals_list[] = {
|
||||
#ifdef SIGHUP
|
||||
|
@ -57,7 +58,8 @@ static const char signals_list[] = {
|
|||
void init(void)
|
||||
{
|
||||
const char* p = signals_list;
|
||||
do {
|
||||
do
|
||||
{
|
||||
int i = *p++;
|
||||
if (i == -1)
|
||||
break;
|
||||
|
@ -70,7 +72,7 @@ void init(void)
|
|||
#endif
|
||||
}
|
||||
#if defined(__em22) || defined(__em24) || defined(__em44)
|
||||
killbss()
|
||||
void killbss(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
|
@ -81,18 +83,17 @@ static int blablabla; /* We cannot use end, because then also
|
|||
this helps ...
|
||||
*/
|
||||
|
||||
killbss()
|
||||
void killbss(void)
|
||||
{
|
||||
extern char *bkillbss;
|
||||
register char *p = (char *) &bkillbss;
|
||||
extern char* bkillbss;
|
||||
register char* p = (char*)&bkillbss;
|
||||
|
||||
while (p < (char *) &blablabla) *p++ = 0x66;
|
||||
while (p < (char*)&blablabla)
|
||||
*p++ = 0x66;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int catch();
|
||||
|
||||
int (*handler)() = catch;
|
||||
char **argv = 0;
|
||||
void (*handler)(int) = catch;
|
||||
char** argv = 0;
|
||||
int argc = 0;
|
||||
char *MainLB = 0;
|
||||
char* MainLB = 0;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <m2_traps.h>
|
||||
|
||||
#ifndef EM_WSIZE
|
||||
|
@ -16,30 +17,26 @@
|
|||
#define EM_PSIZE _EM_PSIZE
|
||||
#endif
|
||||
|
||||
#if EM_WSIZE==EM_PSIZE
|
||||
typedef unsigned pcnt;
|
||||
#else
|
||||
typedef long pcnt;
|
||||
#endif
|
||||
|
||||
load(siz, addr, p)
|
||||
register char *addr;
|
||||
register pcnt siz;
|
||||
void load(size_t siz, char* addr, int p)
|
||||
{
|
||||
/* Make sure, that a value with a size that could have been
|
||||
handled by the LOI instruction ends up at the same place,
|
||||
where it would, were the LOI instruction used.
|
||||
*/
|
||||
register char *q = (char *) &p;
|
||||
register char* q = (char*)&p;
|
||||
char t[4];
|
||||
|
||||
if (siz < EM_WSIZE && EM_WSIZE % siz == 0) {
|
||||
if (siz < EM_WSIZE && EM_WSIZE % siz == 0)
|
||||
{
|
||||
/* as long as EM_WSIZE <= 4 ... */
|
||||
if (siz != 2) TRP(M2_INTERNAL); /* internal error */
|
||||
if (siz != 2)
|
||||
TRP(M2_INTERNAL); /* internal error */
|
||||
q = &t[0];
|
||||
}
|
||||
while (siz--) *q++ = *addr++;
|
||||
if (q - t == 2) {
|
||||
*((unsigned *)(&p)) = *((unsigned short *) (&t[0]));
|
||||
while (siz--)
|
||||
*q++ = *addr++;
|
||||
if (q - t == 2)
|
||||
{
|
||||
*((unsigned*)(&p)) = *((unsigned short*)(&t[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,18 +8,11 @@
|
|||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <em_abs.h>
|
||||
|
||||
extern TRP();
|
||||
|
||||
struct array_descr {
|
||||
int lbound;
|
||||
int n_elts_min_one;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
rcka(descr, indx)
|
||||
struct array_descr *descr;
|
||||
void rcka(struct array_descr* descr, int indx)
|
||||
{
|
||||
if (indx < 0 || indx > descr->n_elts_min_one) TRP(EARRAY);
|
||||
if (indx < 0 || indx > descr->n_elts_min_one)
|
||||
TRP(EARRAY);
|
||||
}
|
||||
|
|
|
@ -8,16 +8,11 @@
|
|||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <em_abs.h>
|
||||
|
||||
extern TRP();
|
||||
|
||||
struct range_descr {
|
||||
int low, high;
|
||||
};
|
||||
|
||||
rcki(descr, val)
|
||||
struct range_descr *descr;
|
||||
void rcki(struct int_range_descr* descr, int val)
|
||||
{
|
||||
if (val < descr->low || val > descr->high) TRP(ERANGE);
|
||||
if (val < descr->low || val > descr->high)
|
||||
TRP(ERANGE);
|
||||
}
|
||||
|
|
|
@ -8,17 +8,11 @@
|
|||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <em_abs.h>
|
||||
|
||||
extern TRP();
|
||||
|
||||
struct range_descr {
|
||||
long low, high;
|
||||
};
|
||||
|
||||
rckil(descr, val)
|
||||
struct range_descr *descr;
|
||||
long val;
|
||||
void rckil(struct long_range_descr* descr, long val)
|
||||
{
|
||||
if (val < descr->low || val > descr->high) TRP(ERANGE);
|
||||
if (val < descr->low || val > descr->high)
|
||||
TRP(ERANGE);
|
||||
}
|
||||
|
|
|
@ -8,17 +8,11 @@
|
|||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <em_abs.h>
|
||||
|
||||
extern TRP();
|
||||
|
||||
struct range_descr {
|
||||
unsigned low, high;
|
||||
};
|
||||
|
||||
rcku(descr, val)
|
||||
struct range_descr *descr;
|
||||
unsigned val;
|
||||
void rcku(struct uint_range_descr* descr, unsigned int val)
|
||||
{
|
||||
if (val < descr->low || val > descr->high) TRP(ERANGE);
|
||||
if (val < descr->low || val > descr->high)
|
||||
TRP(ERANGE);
|
||||
}
|
||||
|
|
|
@ -8,17 +8,11 @@
|
|||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <em_abs.h>
|
||||
|
||||
extern TRP();
|
||||
|
||||
struct range_descr {
|
||||
unsigned long low, high;
|
||||
};
|
||||
|
||||
rckul(descr, val)
|
||||
struct range_descr *descr;
|
||||
unsigned long val;
|
||||
void rckul(struct ulong_range_descr* descr, unsigned long val)
|
||||
{
|
||||
if (val < descr->low || val > descr->high) TRP(ERANGE);
|
||||
if (val < descr->low || val > descr->high)
|
||||
TRP(ERANGE);
|
||||
}
|
||||
|
|
|
@ -14,30 +14,28 @@
|
|||
|
||||
#define EM_trap(n) TRP(n) /* define to whatever is needed to cause the trap */
|
||||
|
||||
#include "libm2.h"
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
int __signo;
|
||||
|
||||
static int __traps[] = {
|
||||
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||||
};
|
||||
|
||||
static void
|
||||
__ctchsig(signo)
|
||||
static void __ctchsig(int signo)
|
||||
{
|
||||
signal(signo,__ctchsig);
|
||||
signal(signo, __ctchsig);
|
||||
#ifdef __BSD4_2
|
||||
sigsetmask(sigblock(0) & ~(1<<(signo - 1)));
|
||||
sigsetmask(sigblock(0) & ~(1 << (signo - 1)));
|
||||
#endif
|
||||
__signo = signo;
|
||||
EM_trap(__traps[signo]);
|
||||
}
|
||||
|
||||
int
|
||||
sigtrp(trapno, signo)
|
||||
int sigtrp(int trapno, int signo)
|
||||
{
|
||||
/* Let Unix signal signo cause EM trap trapno to occur.
|
||||
If trapno = -2, restore default,
|
||||
|
@ -47,11 +45,12 @@ sigtrp(trapno, signo)
|
|||
indicates failure, with error number in errno.
|
||||
*/
|
||||
extern int errno;
|
||||
void (*ctch)() = __ctchsig;
|
||||
void (*oldctch)();
|
||||
void (*ctch)(int) = __ctchsig;
|
||||
void (*oldctch)(int);
|
||||
int oldtrap;
|
||||
|
||||
if (signo <= 0 || signo >= sizeof(__traps)/sizeof(__traps[0])) {
|
||||
if (signo <= 0 || signo >= sizeof(__traps) / sizeof(__traps[0]))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
@ -62,20 +61,23 @@ sigtrp(trapno, signo)
|
|||
ctch = SIG_DFL;
|
||||
else if (trapno >= 0 && trapno <= 252)
|
||||
;
|
||||
else {
|
||||
else
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
oldtrap = __traps[signo];
|
||||
|
||||
if ((oldctch = signal(signo, ctch)) == (void (*)())-1) /* errno set by signal */
|
||||
if ((oldctch = signal(signo, ctch)) == (void (*)()) - 1) /* errno set by signal */
|
||||
return -1;
|
||||
|
||||
else if (oldctch == SIG_IGN) {
|
||||
else if (oldctch == SIG_IGN)
|
||||
{
|
||||
signal(signo, SIG_IGN);
|
||||
}
|
||||
else __traps[signo] = trapno;
|
||||
else
|
||||
__traps[signo] = trapno;
|
||||
|
||||
return oldtrap;
|
||||
}
|
||||
|
|
|
@ -8,20 +8,20 @@
|
|||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Id$
|
||||
*/
|
||||
#include "libm2.h"
|
||||
|
||||
static unsigned prio = 0;
|
||||
|
||||
stackprio(n)
|
||||
unsigned n;
|
||||
int stackprio(unsigned int n)
|
||||
{
|
||||
unsigned old = prio;
|
||||
|
||||
if (n > prio) prio = n;
|
||||
if (n > prio)
|
||||
prio = n;
|
||||
return old;
|
||||
}
|
||||
|
||||
unstackprio(n)
|
||||
unsigned n;
|
||||
void unstackprio(unsigned int n)
|
||||
{
|
||||
prio = n;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
Version: $Id$
|
||||
*/
|
||||
|
||||
#include "libm2.h"
|
||||
#include <m2_traps.h>
|
||||
|
||||
#ifndef EM_WSIZE
|
||||
|
@ -16,28 +17,23 @@
|
|||
#define EM_PSIZE _EM_PSIZE
|
||||
#endif
|
||||
|
||||
#if EM_WSIZE==EM_PSIZE
|
||||
typedef unsigned pcnt;
|
||||
#else
|
||||
typedef long pcnt;
|
||||
#endif
|
||||
|
||||
store(siz, addr, p)
|
||||
register char *addr;
|
||||
register pcnt siz;
|
||||
void store(size_t siz, char* addr, int p)
|
||||
{
|
||||
/* Make sure, that a value with a size that could have been
|
||||
handled by the LOI instruction is handled as if it was
|
||||
loaded with the LOI instruction.
|
||||
*/
|
||||
register char *q = (char *) &p;
|
||||
register char* q = (char*)&p;
|
||||
char t[4];
|
||||
|
||||
if (siz < EM_WSIZE && EM_WSIZE % siz == 0) {
|
||||
if (siz < EM_WSIZE && EM_WSIZE % siz == 0)
|
||||
{
|
||||
/* as long as EM_WSIZE <= 4 ... */
|
||||
if (siz != 2) TRP(M2_INTERNAL); /* internal error */
|
||||
*((unsigned short *) (&t[0])) = *((unsigned *) q);
|
||||
if (siz != 2)
|
||||
TRP(M2_INTERNAL); /* internal error */
|
||||
*((unsigned short*)(&t[0])) = *((unsigned*)q);
|
||||
q = &t[0];
|
||||
}
|
||||
while (siz--) *addr++ = *q++;
|
||||
while (siz--)
|
||||
*addr++ = *q++;
|
||||
}
|
||||
|
|
|
@ -15,51 +15,52 @@
|
|||
#define EM_LSIZE _EM_LSIZE
|
||||
#endif
|
||||
|
||||
#include "libm2.h"
|
||||
#include <m2_traps.h>
|
||||
|
||||
#define MAXCARD ((unsigned)-1)
|
||||
#if EM_WSIZE < EM_LSIZE
|
||||
#define MAXLONGCARD ((unsigned long) -1L)
|
||||
#define MAXLONGCARD ((unsigned long)-1L)
|
||||
#endif
|
||||
|
||||
adduchk(a,b)
|
||||
unsigned a,b;
|
||||
void adduchk(unsigned int a, unsigned int b)
|
||||
{
|
||||
if (MAXCARD - a < b) TRP(M2_UOVFL);
|
||||
if (MAXCARD - a < b)
|
||||
TRP(M2_UOVFL);
|
||||
}
|
||||
|
||||
#if EM_WSIZE < EM_LSIZE
|
||||
addulchk(a,b)
|
||||
unsigned long a,b;
|
||||
void addulchk(unsigned long a, unsigned long b)
|
||||
{
|
||||
if (MAXLONGCARD - a < b) TRP(M2_UOVFL);
|
||||
if (MAXLONGCARD - a < b)
|
||||
TRP(M2_UOVFL);
|
||||
}
|
||||
#endif
|
||||
|
||||
muluchk(a,b)
|
||||
unsigned a,b;
|
||||
void muluchk(unsigned int a, unsigned int b)
|
||||
{
|
||||
if (a != 0 && MAXCARD/a < b) TRP(M2_UOVFL);
|
||||
if (a != 0 && MAXCARD / a < b)
|
||||
TRP(M2_UOVFL);
|
||||
}
|
||||
|
||||
#if EM_WSIZE < EM_LSIZE
|
||||
mululchk(a,b)
|
||||
unsigned long a,b;
|
||||
void mululchk(unsigned long a, unsigned long b)
|
||||
{
|
||||
if (a != 0 && MAXLONGCARD/a < b) TRP(M2_UOVFL);
|
||||
if (a != 0 && MAXLONGCARD / a < b)
|
||||
TRP(M2_UOVFL);
|
||||
}
|
||||
#endif
|
||||
|
||||
subuchk(a,b)
|
||||
unsigned a,b;
|
||||
void subuchk(unsigned int a, unsigned int b)
|
||||
{
|
||||
if (b < a) TRP(M2_UUVFL);
|
||||
if (b < a)
|
||||
TRP(M2_UUVFL);
|
||||
}
|
||||
|
||||
#if EM_WSIZE < EM_LSIZE
|
||||
subulchk(a,b)
|
||||
unsigned long a,b;
|
||||
void subulchk(unsigned long a, unsigned long b)
|
||||
{
|
||||
if (b < a) TRP(M2_UUVFL);
|
||||
if (b < a)
|
||||
TRP(M2_UUVFL);
|
||||
}
|
||||
#endif
|
||||
|
|
12
lib/descr/fe
12
lib/descr/fe
|
@ -72,18 +72,8 @@ name cem
|
|||
mapflag -V* CEM_F={CEM_F?} -V*
|
||||
rts .c
|
||||
need .c
|
||||
prep always
|
||||
args \
|
||||
{CPP_F?} \
|
||||
-D__{ARCH} -D__{PLATFORM} \
|
||||
-D__ACK \
|
||||
{SYSINCLUDES?} \
|
||||
{C_INCLUDES} \
|
||||
{INCLUDES?} \
|
||||
({ANSI_C?.xx}:.xx=-D{ARCH} \
|
||||
-DEM_WSIZE={w} -DEM_PSIZE={p} \
|
||||
-DEM_SSIZE={s} -DEM_LSIZE={l} -DEM_FSIZE={f} -DEM_DSIZE={d}) \
|
||||
-D_EM_WSIZE={w} -D_EM_PSIZE={p} \
|
||||
-D_EM_SSIZE={s} -D_EM_LSIZE={l} -D_EM_FSIZE={f} -D_EM_DSIZE={d} \
|
||||
-Vw{w}.{wa}i{w}.{wa}p{p}.{pa}f{f}.{fa}s{s}.{sa}l{l}.{la}d{d}.{da}x{x}.{xa} \
|
||||
{CC_ALIGN?} \
|
||||
{CEM_F?} {LFLAG?} < >
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue