15
15
/* ASCII collating assumed in syswords.c */
19
19
static int smaller(int a, int b) { return a < b ? a : b; }
21
extern symbol * get_input(symbol * p)
21
extern symbol * get_input(symbol * p, char ** p_file) {
23
23
char * s = b_to_s(p);
24
{ FILE * input = fopen(s, "r");
26
if (input == 0) return 0;
27
{ symbol * u = create_b(STARTSIZE);
25
FILE * input = fopen(s, "r");
26
if (input == 0) { free(s); return 0; }
29
symbol * u = create_b(STARTSIZE);
30
32
{ int ch = getc(input);
41
static void error(struct tokeniser * t, char * s1, int n, symbol * p, char * s2)
43
static void error(struct tokeniser * t, char * s1, int n, symbol * p, char * s2) {
43
44
if (t->error_count == 20) { fprintf(stderr, "... etc\n"); exit(1); }
44
fprintf(stderr, "Line %d", t->line_number);
45
if (t->get_depth > 0) fprintf(stderr, " (of included file)");
46
fprintf(stderr, ": ");
45
fprintf(stderr, "%s:%d: ", t->file, t->line_number);
47
46
unless (s1 == 0) fprintf(stderr, "%s", s1);
50
49
for (i = 0; i < n; i++) fprintf(stderr, "%c", p[i]);
52
51
unless (s2 == 0) fprintf(stderr, "%s", s2);
57
static void error1(struct tokeniser * t, char * s)
58
{ error(t, s, 0,0, 0); }
60
static void error2(struct tokeniser * t, char * s)
61
{ error(t, "unexpected end of text after ", 0,0, s); }
63
static int compare_words(int m, symbol * p, int n, byte * q)
64
{ unless (m == n) return m - n;
65
{ int i; for (i = 0; i < n; i++)
66
{ int diff = p[i] - q[i];
56
static void error1(struct tokeniser * t, char * s) {
60
static void error2(struct tokeniser * t, char * s) {
61
error(t, "unexpected end of text after ", 0,0, s);
64
static int compare_words(int m, symbol * p, int n, byte * q) {
65
unless (m == n) return m - n;
67
int i; for (i = 0; i < n; i++) {
68
int diff = p[i] - q[i];
67
69
unless (diff == 0) return diff;
73
static int find_word(int n, symbol * p)
74
{ int i = 0; int j = vocab->code;
76
{ int k = i + (j - i)/2;
75
static int find_word(int n, symbol * p) {
76
int i = 0; int j = vocab->code;
78
int k = i + (j - i)/2;
77
79
struct system_word * w = vocab + k;
78
80
int diff = compare_words(n, p, w->s_size, w->s);
79
81
if (diff == 0) return w->code;
86
static int get_number(int n, symbol * p)
88
static int get_number(int n, symbol * p) {
88
90
int i; for (i = 0; i < n; i++) x = 10*x + p[i] - '0';
92
static int eq_s(struct tokeniser * t, char * s)
94
static int eq_s(struct tokeniser * t, char * s) {
94
96
if (SIZE(t->p) - t->c < l) return false;
96
99
for (i = 0; i < l; i++) if (t->p[t->c + i] != s[i]) return false;
98
101
t->c += l; return true;
101
static int white_space(struct tokeniser * t, int ch)
103
{ case '\n': t->line_number++;
104
static int white_space(struct tokeniser * t, int ch) {
106
case '\n': t->line_number++;
106
109
case ' ': return true;
111
static symbol * find_in_m(struct tokeniser * t, int n, symbol * p)
112
{ struct m_pair * q = t->m_pairs;
114
{ if (q == 0) return 0;
115
{ symbol * name = q->name;
114
static symbol * find_in_m(struct tokeniser * t, int n, symbol * p) {
115
struct m_pair * q = t->m_pairs;
117
if (q == 0) return 0;
119
symbol * name = q->name;
116
120
if (n == SIZE(name) && memcmp(name, p, n * sizeof(symbol)) == 0) return q->value;
122
static int read_literal_string(struct tokeniser * t, int c)
126
static int read_literal_string(struct tokeniser * t, int c) {
127
{ if (c >= SIZE(p)) { error2(t, "'"); return c; }
131
if (c >= SIZE(p)) { error2(t, "'"); return c; }
129
133
if (ch == '\n') { error1(t, "string not terminated"); return c; }
131
if (ch == t->m_start)
135
if (ch == t->m_start) {
133
137
int newlines = false; /* no newlines as yet */
134
138
int black_found = false; /* no printing chars as yet */
136
{ if (c >= SIZE(p)) { error2(t, "'"); return c; }
140
if (c >= SIZE(p)) { error2(t, "'"); return c; }
138
142
if (ch == t->m_end) break;
139
143
unless (white_space(t, ch)) black_found = true;
140
144
if (ch == '\n') newlines = true;
141
{ if (newlines && black_found)
142
{ error1(t, "string not terminated");
145
if (newlines && black_found) {
146
error1(t, "string not terminated");
149
151
int n = c - c0 - 1; /* macro size */
150
152
int firstch = p[c0];
151
153
symbol * q = find_in_m(t, n, p + c0);
153
{ if (n == 1 && (firstch == '\'' || firstch == t->m_start))
155
if (n == 1 && (firstch == '\'' || firstch == t->m_start))
154
156
t->b = add_to_b(t->b, 1, p + c0);
156
158
error(t, "string macro '", n, p + c0, "' undeclared");
159
160
t->b = add_to_b(t->b, SIZE(q), q);
162
{ if (ch == '\'') return c;
163
if (ch == '\'') return c;
163
164
t->b = add_to_b(t->b, 1, p + c - 1);
168
static int next_token(struct tokeniser * t)
169
static int next_token(struct tokeniser * t) {
174
{ if (c >= SIZE(p)) { t->c = c; return -1; }
175
if (c >= SIZE(p)) { t->c = c; return -1; }
176
177
if (white_space(t, ch)) { c++; continue; }
179
180
while (c < SIZE(p) && (isalnum(p[c]) || p[c] == '_')) c++;
180
181
code = find_word(c - c0, p + c0);
182
{ t->b = move_to_b(t->b, c - c0, p + c0);
183
t->b = move_to_b(t->b, c - c0, p + c0);
188
189
while (c < SIZE(p) && isdigit(p[c])) c++;
189
190
t->number = get_number(c - c0, p + c0);
193
{ c = read_literal_string(t, c + 1);
194
c = read_literal_string(t, c + 1);
194
195
code = c_literalstring;
196
{ int lim = smaller(2, SIZE(p) - c);
197
int i; for (i = lim; i > 0; i--)
198
{ code = find_word(i, p + c);
198
int lim = smaller(2, SIZE(p) - c);
200
for (i = lim; i > 0; i--) {
201
code = find_word(i, p + c);
199
202
if (code >= 0) { c += i; break; }
206
209
error(t, "'", 1, p + c, "' unknown");
212
static int next_char(struct tokeniser * t)
213
{ if (t->c >= SIZE(t->p)) return -1;
215
static int next_char(struct tokeniser * t) {
216
if (t->c >= SIZE(t->p)) return -1;
214
217
return t->p[t->c++];
217
static int next_real_char(struct tokeniser * t)
219
{ int ch = next_char(t);
220
static int next_real_char(struct tokeniser * t) {
222
int ch = next_char(t);
220
223
if (white_space(t, ch)) continue;
225
static void read_chars(struct tokeniser * t)
226
{ int ch = next_real_char(t);
228
{ error2(t, "stringdef"); return; }
228
static void read_chars(struct tokeniser * t) {
229
int ch = next_real_char(t);
230
if (ch < 0) { error2(t, "stringdef"); return; }
232
235
if (white_space(t, ch) || ch < 0) break;
234
237
t->b2 = move_to_b(t->b2, t->c - c0 - 1, t->p + c0);
238
static int decimal_to_num(int ch)
239
{ if ('0' <= ch && ch <= '9') return ch - '0';
241
static int decimal_to_num(int ch) {
242
if ('0' <= ch && ch <= '9') return ch - '0';
243
static int hex_to_num(int ch)
244
{ if ('0' <= ch && ch <= '9') return ch - '0';
246
static int hex_to_num(int ch) {
247
if ('0' <= ch && ch <= '9') return ch - '0';
245
248
if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
249
static void convert_numeric_string(struct tokeniser * t, symbol * p, int base)
252
static void convert_numeric_string(struct tokeniser * t, symbol * p, int base) {
251
253
int c = 0; int d = 0;
253
{ while (c < SIZE(p) && p[c] == ' ') c++;
255
while (c < SIZE(p) && p[c] == ' ') c++;
254
256
if (c == SIZE(p)) break;
258
261
if (c == SIZE(p) || ch == ' ') break;
260
{ ch = decimal_to_num(ch);
262
{ error1(t, "decimal string contains non-digits");
263
ch = decimal_to_num(ch);
265
error1(t, "decimal string contains non-digits");
266
{ ch = hex_to_num(tolower(ch));
268
{ error1(t, "hex string contains non-hex characters");
269
ch = hex_to_num(tolower(ch));
271
error1(t, "hex string contains non-hex characters");
272
275
number = base * number + ch;
275
if (t->widechars) unless (0 <= number && number <= 0xffff)
276
{ error1(t, "character values exceed 64K");
279
unless (t->widechars) unless (0 <= number && number <= 0xff)
280
{ error1(t, "character values exceed 256");
278
if (t->widechars || t->utf8) {
279
unless (0 <= number && number <= 0xffff) {
280
error1(t, "character values exceed 64K");
284
unless (0 <= number && number <= 0xff) {
285
error1(t, "character values exceed 256");
290
d += put_utf8(number, p + d);
289
extern int read_token(struct tokeniser * t)
298
extern int read_token(struct tokeniser * t) {
291
300
int held = t->token_held;
292
301
t->token_held = false;
293
302
if (held) return t->token;
295
{ int code = next_token(t);
297
{ case c_comment1: /* slash-slash comment */
304
int code = next_token(t);
306
case c_comment1: /* slash-slash comment */
298
307
while (t->c < SIZE(p) && p[t->c] != '\n') t->c++;
300
309
case c_comment2: /* slash-star comment */
302
{ if (t->c >= SIZE(p))
303
{ error1(t, "/* comment not terminated");
311
if (t->c >= SIZE(p)) {
312
error1(t, "/* comment not terminated");
341
{ code = read_token(t);
342
unless (code == c_literalstring)
343
{ error1(t, "string omitted after get"); continue; }
345
if (t->get_depth > 10)
346
{ fprintf(stderr, "get directives go 10 deep. Looping?\n");
352
code = read_token(t);
353
unless (code == c_literalstring) {
354
error1(t, "string omitted after get"); continue;
357
if (t->get_depth > 10) {
358
fprintf(stderr, "get directives go 10 deep. Looping?\n");
364
symbol * u = get_input(t->b, &file);
366
struct include * r = t->includes;
368
symbol * b = copy_b(r->b);
369
b = add_to_b(b, SIZE(t->b), t->b);
370
u = get_input(b, &file);
372
unless (u == 0) break;
377
error(t, "Can't get '", SIZE(t->b), t->b, "'");
350
symbol * u = get_input(t->b);
352
{ struct include * r = t->includes;
354
{ symbol * b = copy_b(r->b);
355
b = add_to_b(b, SIZE(t->b), t->b);
358
unless (u == 0) break;
363
{ error(t, "Can't get '", SIZE(t->b), t->b, "'");
366
memmove(q, t, sizeof(struct input));
380
memmove(q, t, sizeof(struct input));
376
unless (t->next == 0)
378
{ struct input * q = t->next;
390
unless (t->next == 0) {
393
struct input * q = t->next;
379
394
memmove(t, q, sizeof(struct input)); p = t->p;