Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

open-axiom repository from github

24005 views
1
/*
2
Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.
3
All rights reserved.
4
Copyright (C) 2007-2008, Gabriel Dos Reis.
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are
9
met:
10
11
- Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
14
- Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in
16
the documentation and/or other materials provided with the
17
distribution.
18
19
- Neither the name of The Numerical Algorithms Group Ltd. nor the
20
names of its contributors may be used to endorse or promote products
21
derived from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
/*
37
* Lexical analyzer stuff. Exported functions: parser_init() --
38
* initialize the parser tables with keywords init_scanner() --
39
* initialize scanner for reading a new page get_token() --
40
* sets the "token" variable to be the next -- token in the current input
41
* stream save_scanner_state( ) -- save the current state of scanner so
42
* that -- the scanner input mode may be switched restore_scanner_state() --
43
* undo the saved state
44
*
45
* Note: The scanner reads from three seperate input locations depending on the
46
* value of the variable "input_type". If this variable is:
47
*
48
* FromFile -- it read from the file pointed to by "cfile". FromString
49
* -- It reads from the string "input_string". FromSpadSocket -- It reads
50
* from the socket pointed to by spad_socket FromFD -- It reads from a
51
* file descriptor
52
*
53
*
54
* New variable useAscii -- tells us if we we should translate
55
* graphics characters on the fly
56
* initialised in init_scanner
57
*
58
*/
59
#define _LEX_C
60
#include "openaxiom-c-macros.h"
61
62
#include <ctype.h>
63
#include <setjmp.h>
64
#include <stdlib.h>
65
#include <string.h>
66
67
#include "debug.h"
68
#include "sockio.h"
69
70
#define PARSER 1
71
72
#include "halloc.h"
73
#include "lex.h"
74
#include "node.h"
75
#include "cfuns.h"
76
77
using namespace OpenAxiom;
78
79
static int get_char1(void );
80
static void spad_error_handler(void );
81
static int keyword_type(void );
82
83
84
85
int useAscii;
86
87
extern int gTtFontIs850;
88
extern HDWindow *gWindow;
89
90
91
92
StateNode *top_state_node;
93
HyperDocPage *gPageBeingParsed; /* page currently being parsed */
94
jmp_buf jmpbuf;
95
char ebuffer[128];
96
short int gInSpadsrc = 0;
97
short int gInVerbatim;
98
openaxiom_sio* spad_socket;
99
100
/* Parser variables */
101
long fpos; /* Position of pointer in file in characters */
102
long page_start_fpos; /* where the current pages fpos started */
103
long keyword_fpos; /* fpos of beginning of most recent keyword */
104
Token token; /* most recently read token */
105
int last_token; /* most recently read token for unget_token */
106
SourceInputKind input_type; /* indicates where to read input */
107
char *input_string; /* input string read when from_string is true */
108
int last_ch; /* last character read, for unget_char */
109
int last_command; /* the last socket command */
110
int keyword; /* the last command was a keyword, or a group */
111
int cfd; /* current file decriptor */
112
FILE *cfile; /* currently active file pointer */
113
FILE *unixfd;
114
int line_number;
115
116
char sock_buf[1024]; /* buffer for socket input */
117
118
#define TokenHashSize 100
119
120
static HashTable tokenHashTable; /* hash table of parser tokens */
121
122
const char* token_table[] = {
123
"", /* Dummy token name */
124
"word",
125
"page",
126
"lispcommandquit",
127
"bf",
128
"link",
129
"downlink",
130
"beginscroll",
131
"spadcommand",
132
"nolines",
133
"env",
134
"par",
135
"centerline",
136
"begin",
137
"beginitems",
138
"item",
139
"table",
140
"fbox",
141
"tab",
142
"space",
143
"indent",
144
"horizontalline",
145
"newline",
146
"enditems",
147
"returnbutton",
148
"memolink",
149
"upbutton",
150
"endscroll",
151
"thispage",
152
"returnto",
153
"free",
154
"bound",
155
"lisplink",
156
"unixlink",
157
"mbox",
158
"inputstring",
159
"stringvalue",
160
"spadlink",
161
"inputbitmap",
162
"inputpixmap",
163
"unixcommand",
164
"em",
165
"lispcommand",
166
"lispmemolink",
167
"lispdownlink",
168
"spadcall",
169
"spadcallquit",
170
"spaddownlink",
171
"spadmemolink",
172
"qspadcall",
173
"qspadcallquit",
174
"inputbox",
175
"radioboxes",
176
"boxvalue",
177
"vspace",
178
"hspace",
179
"newcommand",
180
"windowid",
181
"beep",
182
"quitbutton",
183
"begintitems",
184
"titem",
185
"end",
186
"it",
187
"sl",
188
"tt",
189
"rm",
190
"ifcond",
191
"else",
192
"fi",
193
"newcond",
194
"setcond" ,
195
"button",
196
"windowlink",
197
"haslisp",
198
"hasup",
199
"hasreturn",
200
"hasreturnto",
201
"lastwindow",
202
"endtitems",
203
"lispwindowlink",
204
"beginpile",
205
"endpile",
206
"nextline",
207
"pastebutton",
208
"color",
209
"helppage",
210
"patch",
211
"radiobox",
212
"ifrecond",
213
"math",
214
"mitem",
215
"pagename",
216
"examplenumber",
217
"replacepage",
218
"inputimage",
219
"spadgraph",
220
"indentrel",
221
"controlbitmap"
222
};
223
224
void
225
dumpToken(char *caller, Token t)
226
{ fprintf(stderr,"%s:dumpToken type=%s id=%s\n",
227
caller,token_table[t.type],t.id);
228
}
229
230
231
/* initialize the parser keyword hash table */
232
void
233
parser_init()
234
{
235
int i;
236
Token *toke;
237
238
/* First I initialize the hash table for the tokens */
239
240
hash_init(
241
&tokenHashTable,
242
TokenHashSize,
243
(EqualFunction)string_equal,
244
(HashcodeFunction)string_hash);
245
for (i = 2; i <= openaxiom_NumberUserTokens_token; i++) {
246
toke = (Token *) halloc(sizeof(Token), "Token");
247
toke->type = i;
248
toke->id = token_table[i];
249
hash_insert(&tokenHashTable, (char *)toke, toke->id);
250
}
251
252
}
253
254
/* initialize the lexical scanner to read from a file */
255
void
256
init_scanner()
257
{
258
if (oa_getenv("HTASCII")) {
259
useAscii = (strcmp(oa_getenv("HTASCII"), "yes") == 0);
260
}
261
else {
262
if(gTtFontIs850==1) useAscii = 0;
263
else useAscii = 1;
264
}
265
keyword = 0;
266
last_ch = NoChar;
267
last_token = 0;
268
input_type = SourceInputKind::File;
269
fpos = 0;
270
keyword_fpos = 0;
271
last_command = -1;
272
line_number = 1;
273
}
274
275
/*
276
* variables to save current state of scanner. Currently only one level of
277
* saving is allowed. In the future we should allow nested saves
278
*/
279
280
/* save the current state of the scanner */
281
void
282
save_scanner_state()
283
{
284
StateNode *new_item = (StateNode *) halloc((sizeof(StateNode)), "StateNode");
285
286
new_item->page_start_fpos = page_start_fpos;
287
new_item->fpos = fpos;
288
new_item->keyword_fpos = keyword_fpos;
289
new_item->last_ch = last_ch;
290
new_item->last_token = last_token;
291
new_item->token = token;
292
new_item->input_type = input_type;
293
new_item->input_string = input_string;
294
new_item->cfile = cfile;
295
new_item->next = top_state_node;
296
new_item->keyword = keyword;
297
top_state_node = new_item;
298
}
299
300
/* restore the saved scanner state */
301
void
302
restore_scanner_state()
303
{
304
StateNode *x = top_state_node;
305
306
if (top_state_node == NULL) {
307
fprintf(stderr, "Restore Scanner State: State empty\n");
308
exit(-1);
309
}
310
top_state_node = top_state_node->next;
311
page_start_fpos = x->page_start_fpos;
312
fpos = x->fpos;
313
keyword_fpos = x->keyword_fpos;
314
last_ch = x->last_ch;
315
last_token = x->last_token;
316
token = x->token;
317
input_type = x->input_type;
318
input_string = x->input_string;
319
cfile = x->cfile;
320
keyword = x->keyword;
321
if (cfile != NULL)
322
fseek(cfile, fpos + page_start_fpos, 0);
323
/** Once that is done, lets throw away some memory **/
324
free(x);
325
}
326
327
/* return the character to the input stream. */
328
void
329
unget_char(int c)
330
{
331
if (c == '\n')
332
line_number--;
333
last_ch = c;
334
}
335
336
int
337
get_char()
338
{
339
int c;
340
341
c = get_char1();
342
if (useAscii) {
343
switch (c) {
344
case '�':
345
c = '-';
346
break;
347
case '�':
348
c = '+';
349
break;
350
case '�':
351
c = '[';
352
break;
353
case '�':
354
c = '+';
355
break;
356
case '�':
357
c = '-';
358
break;
359
case '�':
360
c = '+';
361
break;
362
case '�':
363
c = '-';
364
break;
365
case '�':
366
c = '+';
367
break;
368
case '�':
369
c = ']';
370
break;
371
case '�':
372
c = '+';
373
break;
374
case '�':
375
c = '|';
376
break;
377
default:
378
break;
379
}
380
}
381
return c;
382
}
383
384
/* return the next character in the input stream */
385
static int
386
get_char1()
387
{
388
int c;
389
int cmd;
390
391
if (last_ch != NoChar) {
392
c = last_ch;
393
last_ch = NoChar;
394
if (c == '\n')
395
line_number++;
396
return c;
397
}
398
switch (input_type) {
399
case SourceInputKind::UnixFD:
400
c = getc(unixfd);
401
if (c == '\n')
402
line_number++;
403
return c;
404
case SourceInputKind::String:
405
c = (*input_string ? *input_string++ : EOF);
406
if (c == '\n')
407
line_number++;
408
return c;
409
case SourceInputKind::File:
410
c = getc(cfile);
411
fpos++;
412
if (c == '\n')
413
line_number++;
414
return c;
415
case SourceInputKind::SpadSocket:
416
AGAIN:
417
if (*input_string) {
418
/* this should never happen for the first character */
419
c = *input_string++;
420
if (c == '\n')
421
line_number++;
422
return c;
423
}
424
if (last_command == EndOfPage)
425
return EOF;
426
if (spad_socket->nbytes_pending == 0) {
427
last_command = cmd = get_int(spad_socket);
428
if (cmd == EndOfPage)
429
return EOF;
430
if (cmd == SpadError)
431
spad_error_handler();
432
}
433
get_string_buf(spad_socket, sock_buf, 1023);
434
/* this will be null if this is the last time*/
435
input_string = sock_buf;
436
goto AGAIN;
437
default:
438
fprintf(stderr, "Get Char: Unknown type of input: %d\n", input_type);
439
return -1;
440
}
441
}
442
443
444
#define special(c) ((c) == '{' || (c) == '}' || (c) == '#' || (c) == '%' || \
445
(c) == '\\' || (c) == '[' || (c) == ']' || (c) == '_' || \
446
(c) == ' ' || (c) == '$' || (c) == '~' || (c) == '^' || \
447
(c) == '&')
448
449
#define punctuation(c) ((c)== '`' || (c) == '\'' || (c) == ',' || \
450
(c) == '.' || (c) == '?' || (c) == '"' || \
451
(c) == ';' || (c) == ':' || (c) == '-')
452
453
#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
454
#define delim(c) \
455
(whitespace(c) || special(c) || punctuation(c))
456
457
458
459
Token unget_toke;
460
461
/* return current token to the input stream */
462
void
463
unget_token()
464
{
465
last_token = 1;
466
unget_toke.type = token.type;
467
unget_toke.id = alloc_string(token.id - 1);
468
}
469
470
471
int
472
get_token()
473
{
474
int c, ws;
475
int nls = 0;
476
static int seen_white = 0;
477
static char buffer[1024];
478
char *buf = buffer;
479
480
if (last_token) {
481
last_token = 0;
482
token.type = unget_toke.type;
483
strcpy(buffer, unget_toke.id);
484
free((char*) unget_toke.id);
485
token.id = buffer + 1;
486
if (token.type == EOF)
487
return EOF;
488
else
489
return 0;
490
}
491
seen_white = nls = 0;
492
do {
493
c = get_char();
494
ws = whitespace(c);
495
if (ws)
496
seen_white++;
497
if (c == '\n') {
498
if (nls) {
499
token.type = openaxiom_Par_token;
500
return 0;
501
}
502
else
503
nls++;
504
}
505
} while (ws);
506
507
/* first character of string indicates number of spaces before token */
508
509
if (!keyword)
510
*buf++ = seen_white;
511
else
512
*buf++ = 0;
513
514
keyword = 0;
515
if (input_type != SourceInputKind::SpadSocket && c == '%') {
516
while ((c = get_char()) != '\n' && c != EOF);
517
/* trying to fix the comment problem: a comment line forces words on either side together*/
518
/* try returning the eol */
519
unget_char(c);
520
return get_token();
521
}
522
if (input_type == SourceInputKind::File && c == '$') {
523
token.type = openaxiom_Dollar_token;
524
return 0;
525
}
526
switch (c) {
527
case EOF:
528
token.type = -1;
529
return EOF;
530
case '\\':
531
keyword_fpos = fpos - 1;
532
c = get_char();
533
if (!isalpha(c)) {
534
*buf++ = c;
535
token.type = openaxiom_Word_token;
536
*buf = '\0';
537
seen_white = 0;
538
}
539
else {
540
do {
541
*buf++ = c;
542
} while ((c = get_char()) != EOF && isalpha(c));
543
544
unget_char(c);
545
*buf = '\0';
546
keyword = 1;
547
token.id = buffer + 1;
548
return (keyword_type());
549
}
550
break;
551
case '{':
552
token.type = openaxiom_Lbrace_token;
553
break;
554
case '}':
555
token.type = openaxiom_Rbrace_token;
556
break;
557
case '[':
558
token.type = openaxiom_Lsquarebrace_token;
559
*buf++ = c;
560
*buf = '\0';
561
token.id = buffer + 1;
562
break;
563
case ']':
564
token.type = openaxiom_Rsquarebrace_token;
565
*buf++ = c;
566
*buf = '\0';
567
token.id = buffer + 1;
568
break;
569
case '#':
570
token.type = openaxiom_Pound_token;
571
572
/*
573
* if I get a pound then what I do is parse until I get something
574
* that is not an integer
575
*/
576
c = get_char();
577
while (isdigit(c) && (c != EOF)) {
578
*buf++ = c;
579
c = get_char();
580
}
581
unget_char(c);
582
*buf = '\0';
583
token.id = buffer + 1;
584
break;
585
case '`':
586
case '\'':
587
case ',':
588
case '.':
589
case '!':
590
case '?':
591
case '"':
592
case ':':
593
case ';':
594
token.type = openaxiom_Punctuation_token;
595
*buf++ = c;
596
*buf = '\0';
597
/** Now I should set the buffer[0] as my flag for whether I had
598
white-space in front of me, and whether I had white space
599
behind me **/
600
if (buffer[0])
601
buffer[0] = FRONTSPACE;
602
c = get_char();
603
if (whitespace(c))
604
buffer[0] |= BACKSPACE;
605
unget_char(c);
606
token.id = buffer + 1;
607
break;
608
case '-':
609
do {
610
*buf++ = c;
611
} while (((c = get_char()) != EOF) && (c == '-'));
612
unget_char(c);
613
*buf = '\0';
614
token.type = openaxiom_Dash_token;
615
token.id = buffer + 1;
616
break;
617
default:
618
do {
619
*buf++ = c;
620
} while ((c = get_char()) != EOF && !delim(c));
621
unget_char(c);
622
*buf = '\0';
623
token.type = openaxiom_Word_token;
624
token.id = buffer + 1;
625
break;
626
}
627
/* dumpToken("get_token",token);*/
628
return 0;
629
}
630
631
632
/*
633
* Here are the structures and stuff needed for the begin and end routines.
634
* The stack stores the begin types that have been seen and the end
635
* pops them off and checks to insure that they are reversed properly.
636
*/
637
638
typedef struct be_struct {
639
int type;
640
char *id;
641
struct be_struct *next;
642
} BeStruct;
643
644
BeStruct *top_be_stack;
645
646
void
647
jump()
648
{
649
if (gWindow == NULL)
650
exit(-1);
651
longjmp(jmpbuf, 1);
652
fprintf(stderr, "(HyperDoc) Long Jump failed, Exiting\n");
653
exit(-1);
654
}
655
656
void
657
push_be_stack(int type, const char* id)
658
{
659
BeStruct *be = (BeStruct *) halloc(sizeof(BeStruct), "BeginENd stack");
660
661
if (gWindow != NULL) {
662
be->type = type;
663
be->next = top_be_stack;
664
be->id = alloc_string(id);
665
top_be_stack = be;
666
}
667
return;
668
}
669
void
670
check_and_pop_be_stack(int type, const char* id)
671
{
672
BeStruct *x;
673
674
/*
675
* this routine pops the be stack and compares types. If they are
676
* the same then I am okay and return a 1. Else I return a two and try to
677
* print a meaningful message
678
*/
679
if (gWindow == NULL)
680
return;
681
if (top_be_stack == NULL) { /* tried to pop when I shouldn't have */
682
fprintf(stderr, "Unexpected \\end{%s} \n", token.id);
683
print_page_and_filename();
684
print_next_ten_tokens();
685
jump();
686
}
687
x = top_be_stack;
688
if (x->type == type) {
689
top_be_stack = top_be_stack->next;
690
free(x->id);
691
free(x);
692
return;
693
}
694
/* else I didn't have a match. Lets try to write a sensible message */
695
fprintf(stderr, "\\begin{%s} ended with \\end{%s} \n", x->id, id);
696
print_page_and_filename();
697
print_next_ten_tokens();
698
jump();
699
}
700
701
int
702
clear_be_stack()
703
{
704
BeStruct *x = top_be_stack, *y;
705
706
top_be_stack = NULL;
707
while (x != NULL) {
708
y = x->next;
709
free(x);
710
x = y;
711
}
712
return 1;
713
}
714
715
int
716
be_type(const char* which)
717
{
718
Token store;
719
720
get_expected_token(openaxiom_Lbrace_token);
721
get_expected_token(openaxiom_Word_token);
722
switch (token.id[0]) {
723
case 't':
724
if (!strcmp(token.id, "titems")) {
725
token.type = openaxiom_Begintitems_token;
726
}
727
else {
728
return -1;
729
}
730
break;
731
case 'p':
732
if (!strcmp(token.id, "page")) {
733
token.type = openaxiom_Page_token;
734
}
735
else if (!strcmp(token.id, "paste")) {
736
token.type = openaxiom_Paste_token;
737
}
738
else if (!strcmp(token.id, "patch")) {
739
token.type = openaxiom_Patch_token;
740
}
741
else {
742
return -1;
743
}
744
break;
745
case 'v': /* possibly a verbatim mode */
746
if (!strcmp(token.id, "verbatim")) {
747
token.type = openaxiom_Verbatim_token;
748
}
749
else {
750
return -1;
751
}
752
break;
753
case 's': /* possibly a scroll mode */
754
if (!strcmp("scroll", token.id)) {
755
token.type = openaxiom_Beginscroll_token;
756
}
757
else if (!strcmp(token.id, "spadsrc")) {
758
token.type = openaxiom_Spadsrc_token;
759
}
760
else {
761
return -1;
762
}
763
break;
764
case 'i': /* possibly a item */
765
if (!strcmp("items", token.id)) {
766
token.type = openaxiom_Beginitems_token;
767
}
768
else {
769
return -1;
770
}
771
break;
772
default:
773
return -1;
774
}
775
store.type = token.type;
776
/* store.id = alloc_string(token.id); */
777
get_expected_token(openaxiom_Rbrace_token);
778
token.type = store.type;
779
780
/*
781
* strcpy(token.id, store.id); free(store.id);
782
*/
783
return 0;
784
785
}
786
int
787
begin_type()
788
{
789
/*Token store;*/
790
int ret_val;
791
792
/*
793
* This routine parses a statement of the form \begin{word}. Once it has
794
* read the word it tries to assign it a type. Once that is done it sends
795
* the word id, and the type to push_be_stack and then returns the type.
796
* For the moment I amnot even going to use a has_table, although in the
797
* future this may be needed
798
*/
799
ret_val = be_type("begin");
800
if (ret_val == -1) {
801
if (gWindow == NULL || gInVerbatim)
802
return 1;
803
else {
804
fprintf(stderr, "Unknown begin type \\begin{%s} \n", token.id);
805
print_page_and_filename();
806
print_next_ten_tokens();
807
jump();
808
}
809
}
810
else {
811
if (gWindow != NULL && !gInVerbatim
812
&& token.type != openaxiom_Verbatim_token
813
&& token.type != openaxiom_Spadsrc_token) {
814
/* Now here I should push the needed info and then get */
815
push_be_stack(token.type, token.id);
816
}
817
return 1;
818
}
819
return 1;
820
}
821
822
823
int
824
end_type()
825
{
826
int ret;
827
828
/*
829
* This routine gets the end type just as the begin_type routine does,
830
* But then it checks to see if recieved the proper end_type. By a clever
831
* trick, the proper end type is 3000 + type. When environments this will
832
* have to change
833
*/
834
ret = be_type("end");
835
if (ret == -1) {
836
/* unrecognized end token */
837
if (gWindow == NULL || gInVerbatim) {
838
return 1;
839
}
840
else {
841
fprintf(stderr, "Unknown begin type \\begin{%s} \n", token.id);
842
print_page_and_filename();
843
print_next_ten_tokens();
844
jump();
845
}
846
}
847
else {
848
if (gWindow != NULL && !gInVerbatim) {
849
check_and_pop_be_stack(token.type, token.id);
850
token.type += 3000;
851
return 1;
852
}
853
else {
854
if (gWindow != NULL
855
&& ((gInVerbatim && token.type == openaxiom_Verbatim_token)
856
|| (gInSpadsrc && token.type == openaxiom_Spadsrc_token))) {
857
check_and_pop_be_stack(token.type, token.id);
858
token.type += 3000;
859
return 1;
860
}
861
else {
862
token.type += 3000;
863
return 1;
864
}
865
}
866
}
867
return 1;
868
}
869
870
871
void
872
token_name(int type)
873
{
874
if (type <= openaxiom_NumberUserTokens_token)
875
strcpy(ebuffer, token_table[type]);
876
else {
877
switch (type) {
878
case openaxiom_Lbrace_token:
879
strcpy(ebuffer, "{");
880
break;
881
case openaxiom_Rbrace_token:
882
strcpy(ebuffer, "}");
883
break;
884
case openaxiom_Macro_token:
885
strcpy(ebuffer, token.id);
886
break;
887
case openaxiom_Group_token:
888
strcpy(ebuffer, "{");
889
break;
890
case openaxiom_Pound_token:
891
strcpy(ebuffer, "#");
892
break;
893
case openaxiom_Lsquarebrace_token:
894
strcpy(ebuffer, "[");
895
break;
896
case openaxiom_Rsquarebrace_token:
897
strcpy(ebuffer, "]");
898
break;
899
case openaxiom_Punctuation_token:
900
strcpy(ebuffer, token.id);
901
break;
902
case openaxiom_Dash_token:
903
strcpy(ebuffer, token.id);
904
break;
905
case openaxiom_Verbatim_token:
906
strcpy(ebuffer, "\\begin{verbatim}");
907
break;
908
case openaxiom_Scroll_token:
909
strcpy(ebuffer, "\\begin{scroll}");
910
break;
911
case openaxiom_Dollar_token:
912
strcpy(ebuffer, "$");
913
break;
914
case openaxiom_Percent_token:
915
strcpy(ebuffer, "%");
916
break;
917
case openaxiom_Carrot_token:
918
strcpy(ebuffer, "^");
919
break;
920
case openaxiom_Underscore_token:
921
strcpy(ebuffer, "_");
922
break;
923
case openaxiom_Tilde_token:
924
strcpy(ebuffer, "~");
925
break;
926
case openaxiom_Cond_token:
927
sprintf(ebuffer, "\\%s", token.id);
928
break;
929
case openaxiom_Icorrection_token:
930
strcpy(ebuffer, "\\/");
931
break;
932
case openaxiom_Paste_token:
933
strcpy(ebuffer, "\\begin{paste}");
934
break;
935
case openaxiom_Patch_token:
936
strcpy(ebuffer, "\\begin{patch}");
937
break;
938
default:
939
sprintf(ebuffer, " %d ", type);
940
}
941
/*return 1;*/
942
}
943
}
944
945
946
/* print out a token value */
947
void
948
print_token()
949
{
950
if (token.type == openaxiom_Word_token)
951
printf("%s ", token.id);
952
else {
953
token_name(token.type);
954
printf("\\%s ", ebuffer);
955
}
956
fflush(stdout);
957
}
958
959
void
960
print_next_ten_tokens()
961
{
962
int i;
963
int v;
964
965
fprintf(stderr, "Trying to print the next ten tokens\n");
966
for (i = 0; i < 10; i++) {
967
v = get_token();
968
if (v == EOF)
969
break;
970
print_token();
971
}
972
fprintf(stderr, "\n");
973
}
974
975
void
976
print_page_and_filename()
977
{
978
char obuff[128];
979
980
if (gPageBeingParsed->type == Normal) {
981
982
/*
983
* Now try to inform the user as close to possible where the error
984
* occurred
985
*/
986
sprintf(obuff, "(HyperDoc) While parsing %s on line %d\n\tin the file %s\n",
987
gPageBeingParsed->name, line_number,
988
gPageBeingParsed->filename);
989
}
990
else if (gPageBeingParsed->type == SpadGen) {
991
sprintf(obuff, "While parsing %s from the Spad socket\n",
992
gPageBeingParsed->name);
993
}
994
else if (gPageBeingParsed->type == Unixfd) {
995
sprintf(obuff, "While parsing %s from a Unixpipe\n",
996
gPageBeingParsed->name);
997
}
998
else {
999
/* Unknown page type */
1000
sprintf(obuff, "While parsing %s\n", gPageBeingParsed->name);
1001
}
1002
fprintf(stderr, "%s", obuff);
1003
}
1004
1005
1006
static int
1007
keyword_type()
1008
{
1009
Token *token_ent;
1010
1011
/* first check to see if it is a reserved token */
1012
token_ent = (Token *) hash_find(&tokenHashTable, token.id);
1013
if (token_ent != NULL) {
1014
token.type = token_ent->type;
1015
1016
/*
1017
* if I am a keyword I also have to check to see if I am a begin or
1018
* an end
1019
*/
1020
if (token.type == openaxiom_Begin_token)
1021
return begin_type();
1022
if (token.type == openaxiom_End_token)
1023
return end_type();
1024
/* next check to see if it is a macro */
1025
}
1026
else if (gWindow != NULL) {
1027
if (hash_find(gWindow->fMacroHashTable, token.id) != NULL)
1028
token.type = openaxiom_Macro_token;
1029
else if (gPageBeingParsed->box_hash != NULL &&
1030
hash_find(gPageBeingParsed->box_hash, token.id) != NULL)
1031
{
1032
token.type = openaxiom_Boxcond_token;
1033
}
1034
else if (hash_find(gWindow->fCondHashTable, token.id) != NULL)
1035
token.type = openaxiom_Cond_token;
1036
else /* We have no idea what we've got */
1037
token.type = openaxiom_Unkeyword_token;
1038
}
1039
else { /* We am probably in htadd so just return. It
1040
* is only concerned with pages anyway */
1041
token.type = openaxiom_Unkeyword_token;
1042
}
1043
return 0;
1044
}
1045
1046
/* read a token, and report a syntax error if it has the wrong type */
1047
void
1048
get_expected_token(int type)
1049
{
1050
get_token();
1051
if (token.type != type) {
1052
token_name(type);
1053
fprintf(stderr, "syntax error: expected a %s\n", ebuffer);
1054
if (token.type == EOF) {
1055
print_page_and_filename();
1056
fprintf(stderr, "Unexpected EOF\n");
1057
}
1058
else {
1059
token_name(token.type);
1060
fprintf(stderr, "not a %s\n", ebuffer);
1061
print_page_and_filename();
1062
print_next_ten_tokens();
1063
}
1064
longjmp(jmpbuf, 1);
1065
fprintf(stderr, "Could not jump to Error Page\n");
1066
exit(-1);
1067
}
1068
}
1069
1070
static void
1071
spad_error_handler()
1072
{
1073
/* fprintf(stderr, "got a spad error\n"); */
1074
longjmp(jmpbuf, 1);
1075
fprintf(stderr, "(HyperDoc) Fatal Error: Could not jump to Error Page.\n");
1076
exit(-1);
1077
}
1078
1079
1080