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-2016, Gabriel Dos Reis.
5
All rights reverved.
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
#include "openaxiom-c-macros.h"
37
#include "debug.h"
38
#include "halloc.h"
39
#include "sockio.h"
40
#include "parse.h"
41
#include "addfile.h"
42
#include "lex.h"
43
#include "hyper.h"
44
45
static void read_ht_file(HashTable * page_hash , HashTable * macro_hash , HashTable * patch_hash , FILE * db_fp , char * db_file);
46
static HyperDocPage * make_special_page(int type , const char * name);
47
48
extern int make_input_file;
49
extern int gverify_dates;
50
51
InputBox *rb_list;
52
InputBox *end_rb_list;
53
54
HashTable ht_gFileHashTable;
55
56
#define htfhSize 100
57
58
/* Hash functions for active link windows */
59
60
int
61
window_equal(Window *w1, Window *w2)
62
{
63
return *w1 == *w2;
64
}
65
66
/* hash code for a window */
67
68
int
69
window_code(Window *w, int size)
70
{
71
return (*w) % size;
72
}
73
74
char *
75
window_id(Window w)
76
{
77
char *ret;
78
char buff[32];
79
int length;
80
81
sprintf(buff, "%ld", w);
82
length = strlen(buff);
83
ret = (char *) halloc(length * sizeof(char) + 1, "windowid");
84
strcpy(ret, buff);
85
return (ret);
86
}
87
88
/*
89
* This procedure reads the ht database. It makes repeated calls to
90
* db_file_open, and while the returned pointer is not null, it continues to
91
* read the presented data base files
92
*/
93
void
94
read_ht_db(HashTable *page_hash, HashTable *macro_hash, HashTable *patch_hash)
95
{
96
FILE *db_fp;
97
char db_file[256];
98
int i = 0;
99
100
gDatabasePath = NULL;
101
102
hash_init(
103
page_hash,
104
PageHashSize,
105
(EqualFunction) string_equal,
106
(HashcodeFunction) string_hash);
107
hash_init(
108
macro_hash,
109
MacroHashSize,
110
(EqualFunction) string_equal,
111
(HashcodeFunction) string_hash);
112
hash_init(
113
patch_hash,
114
PatchHashSize,
115
(EqualFunction) string_equal,
116
(HashcodeFunction) string_hash);
117
118
/* Lets initialize the FileHashTable */
119
hash_init(
120
&ht_gFileHashTable,
121
htfhSize,
122
(EqualFunction) string_equal,
123
(HashcodeFunction) string_hash);
124
125
while ((db_fp = db_file_open(db_file)) != NULL) {
126
i++;
127
read_ht_file(page_hash, macro_hash, patch_hash, db_fp, db_file);
128
fclose(db_fp);
129
}
130
131
if (!i) {
132
fprintf(stderr,
133
"(HyperDoc) read_ht_db: No %s file found\n", db_file_name);
134
exit(-1);
135
}
136
137
free_hash(&ht_gFileHashTable, (FreeFunction)free_string);
138
}
139
140
/*
141
* This procedure reads a single HyperDoc database file. It is passed an already
142
* initilaized file pointer. It reads the whole file, updating the
143
* page hash, or the macro hash only when a previous entry with the same name
144
* is not found
145
*/
146
147
static void
148
read_ht_file(HashTable *page_hash, HashTable *macro_hash,
149
HashTable *patch_hash, FILE *db_fp, char *db_file)
150
{
151
char filename[256];
152
char *fullname = filename;
153
UnloadedPage *page;
154
MacroStore *macro;
155
PatchStore *patch;
156
int pages = 0, c, mtime, ret_val;
157
struct stat fstats;
158
/*short time_ok = 1;*/
159
/* fprintf(stderr,"parse_aux:read_ht_file: dp_file=%s\n",db_file);*/
160
cfile = db_fp;
161
init_scanner();
162
ret_val = strlen(db_file) - 1;
163
for (; ret_val >= 0; ret_val--)
164
if (db_file[ret_val] == '/') {
165
db_file[ret_val] = '\0';
166
break;
167
}
168
c = getc(db_fp);
169
do {
170
if (c == '\t') {
171
get_filename();
172
fullname = alloc_string(token.id);
173
if (fullname[0] != '/') {
174
strcpy(filename, db_file);
175
strcat(filename, "/");
176
strcat(filename, fullname);
177
free(fullname);
178
fullname = alloc_string(filename);
179
}
180
181
/*
182
* Until I get a filename that I have not seen before, just keep
183
* reading
184
*/
185
while (hash_find(&ht_gFileHashTable, fullname) != NULL) {
186
do {
187
c = getc(db_fp);
188
} while ((c != EOF) && (c != '\t'));
189
if (c == EOF)
190
return;
191
get_filename();
192
fullname = alloc_string(token.id);
193
if (fullname[0] != '/') {
194
strcpy(filename, db_file);
195
strcat(filename, "/");
196
strcat(filename, fullname);
197
free(fullname);
198
fullname = alloc_string(filename);
199
}
200
}
201
/* fprintf(stderr,"parse_aux:read_ht_file: fullname=%s\n",fullname);*/
202
/* If I got here, then I must have a good filename */
203
hash_insert(&ht_gFileHashTable, fullname, fullname);
204
205
ret_val = stat(fullname, &fstats);
206
if (ret_val == -1) {
207
char buffer[300];
208
209
sprintf(buffer, "(HyperDoc) read_ht_db: Unable To Open %s :", fullname);
210
perror(buffer);
211
exit(-1);
212
}
213
get_token();
214
mtime = atoi(token.id);
215
if (gverify_dates & (fstats.st_mtime > mtime)) {
216
fprintf(stderr, "(HyperDoc) read_ht_file: HyperDoc file %s has been updated\n",
217
218
fullname);
219
fprintf(stderr, "(HyperDoc) Issue htadd %s to update database\n", fullname);
220
exit(-1);
221
}
222
while ((c = getc(db_fp)) != EOF) {
223
if (c == '\t')
224
break;
225
ungetc(c, db_fp);
226
get_token();
227
switch (token.type) {
228
case openaxiom_Page_token:
229
get_token();
230
231
/*
232
* now check to see if the page has already been
233
* loaded
234
*/
235
page = (UnloadedPage *) halloc(sizeof(UnloadedPage),
236
"UnloadedPage");
237
page->fpos.name = alloc_string(fullname);
238
page->name = alloc_string(token.id);
239
get_token();
240
if (hash_find(page_hash, page->name) != NULL) {
241
fprintf(stderr, "(HyperDoc) Page name %s occurred twice\n", page->name);
242
fprintf(stderr, "(HyperDoc) The Version in %s is being ignored \n",
243
page->fpos.name);
244
free(page);
245
get_token();
246
break;
247
}
248
page->fpos.pos = atoi(token.id);
249
get_token();
250
page->fpos.ln = atoi(token.id);
251
page->type = UnloadedPageType;
252
hash_insert(page_hash, (char *)page, page->name);
253
pages++;
254
break;
255
case openaxiom_NewCommand_token:
256
get_token();
257
macro = (MacroStore *) halloc(sizeof(MacroStore), "MacroStore");
258
macro->fpos.name = alloc_string(fullname);
259
macro->name = alloc_string(token.id);
260
macro->macro_string = NULL;
261
get_token();
262
if (hash_find(macro_hash, macro->name) != NULL) {
263
if (strcmp(macro->name, "localinfo") != 0) {
264
fprintf(stderr, "(HyperDoc) Macro name %s occurred twice\n",
265
macro->name);
266
fprintf(stderr, "(HyperDoc) The Version in %s is being ignored \n",
267
macro->fpos.name);
268
}
269
get_token();
270
free(macro);
271
break;
272
}
273
macro->fpos.pos = atoi(token.id);
274
get_token();
275
macro->fpos.ln = atoi(token.id);
276
macro->loaded = 0;
277
hash_insert(macro_hash, (char *)macro, macro->name);
278
break;
279
case openaxiom_Patch_token:
280
get_token();
281
patch = (PatchStore *) alloc_patchstore();
282
patch->fpos.name = alloc_string(fullname);
283
patch->name = alloc_string(token.id);
284
get_token();
285
patch->fpos.pos = atoi(token.id);
286
get_token();
287
patch->fpos.ln = atoi(token.id);
288
if (hash_find(patch_hash, patch->name) != NULL) {
289
fprintf(stderr, "(HyperDoc) Patch name %s occurred twice\n", patch->name);
290
fprintf(stderr, "(HyperDoc) The version in %s is being ignored \n",
291
patch->fpos.name);
292
free_patch(patch);
293
break;
294
}
295
hash_insert(patch_hash, (char *)patch, patch->name);
296
break;
297
default:
298
fprintf(stderr, "(HyperDoc) read_ht_db: Unknown type %s in ht.db\n", token.id);
299
exit(-1);
300
break;
301
}
302
}
303
}
304
else
305
c = getc(db_fp);
306
} while (c != EOF);
307
/* fprintf(stderr,
308
"parse_aux:read_ht_file:read %d pages from database\n", pages); */
309
}
310
311
312
/* create an unmapped input-only window for an active screen area */
313
314
HyperLink *
315
make_link_window(TextNode *link_node, int type, int isSubWin)
316
{
317
HyperLink *link;
318
XSetWindowAttributes at;
319
320
if (make_input_file)
321
switch (type) {
322
case openaxiom_Downlink_token:
323
case openaxiom_Memolink_token:
324
case openaxiom_Windowlink_token: {
325
char *name;
326
HyperDocPage *p;
327
328
name = print_to_string(link_node);
329
p = (HyperDocPage *) hash_find(gWindow->fPageHashTable, name);
330
if (!p)
331
printf("undefined link to %s\n", name);
332
break;
333
}
334
}
335
else {
336
link = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
337
if (link == NULL) {
338
fprintf(stderr, "(HyperDoc) Ran out of memory allocating a hypertext link!\n");
339
exit(-1);
340
}
341
at.cursor = gActiveCursor;
342
at.event_mask = ButtonPress;
343
if (isSubWin)
344
link->win = XCreateWindow(gXDisplay, gWindow->fDisplayedWindow, 0, 0, 100, 100, 0,
345
0, InputOnly, CopyFromParent,
346
CWEventMask | CWCursor, &at);
347
else
348
link->win = 0;
349
link->type = type;
350
link->x = link->y = 0;
351
link->reference.node = link_node;
352
hash_insert(gLinkHashTable, (char *)link,(char *)&link->win);
353
return link;
354
}
355
return 0;
356
}
357
358
HyperLink *
359
make_paste_window(PasteNode *paste)
360
{
361
HyperLink *link;
362
XSetWindowAttributes at;
363
364
if (!make_input_file) {
365
link = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
366
if (link == NULL) {
367
fprintf(stderr, "(HyperDoc) Ran out of memory allocating a hypertext link!\n");
368
exit(-1);
369
}
370
at.cursor = gActiveCursor;
371
at.event_mask = ButtonPress;
372
link->win = XCreateWindow(gXDisplay, gWindow->fDisplayedWindow,
373
0, 0, 100, 100, 0,
374
0, InputOnly, CopyFromParent,
375
CWEventMask | CWCursor, &at);
376
link->type = openaxiom_Pastebutton_token;
377
link->x = link->y = 0;
378
link->reference.paste = paste;
379
hash_insert(gLinkHashTable, (char *)link,(char *) &link->win);
380
return link;
381
}
382
return 0;
383
}
384
385
386
387
/* create a HyperDoc page structure with the given type and name */
388
389
static HyperDocPage *
390
make_special_page(int type, const char *name)
391
{
392
HyperDocPage *page = alloc_page(name);
393
394
if (page == NULL) {
395
fprintf(stderr, "(HyperDoc) Ran out of memory allocating page.\n");
396
exit(-1);
397
}
398
page->type = type;
399
free(page->fLinkHashTable);
400
page->fLinkHashTable = NULL;
401
return page;
402
}
403
404
405
/* insert the special button page types into the page hash table */
406
407
void
408
make_special_pages(HashTable *pageHashTable)
409
{
410
hash_insert(pageHashTable,
411
(char *)make_special_page(openaxiom_Quitbutton_token,
412
"QuitPage"),
413
"QuitPage");
414
hash_insert(pageHashTable,
415
(char *)make_special_page(openaxiom_Returnbutton_token,
416
"ReturnPage"),
417
"ReturnPage");
418
hash_insert(pageHashTable,
419
(char *)make_special_page(openaxiom_Upbutton_token, "UpPage"),
420
"UpPage");
421
}
422
423
424
/* Here is where I put the item into the pages linked list */
425
426
/* Parse the \bound{varlist} command, and add vars to dependency table */
427
428
void
429
add_dependencies()
430
{
431
TextNode *bound_node = curr_node;
432
TextNode *node;
433
SpadcomDepend *depend;
434
435
if (cur_spadcom == NULL) {
436
fprintf(stderr, "(HyperDoc) \\bound occuring outside a \\spadcom\n");
437
print_page_and_filename();
438
exit(-1);
439
}
440
curr_node->type = openaxiom_Bound_token;
441
curr_node->data.node = alloc_node();
442
curr_node = curr_node->data.node;
443
get_expected_token(openaxiom_Lbrace_token);
444
parse_HyperDoc();
445
curr_node->type = openaxiom_Endarg_token;
446
curr_node = bound_node;
447
448
if (gPageBeingParsed->depend_hash == NULL) {
449
gPageBeingParsed->depend_hash =
450
(HashTable *) halloc(sizeof(HashTable), "Hash Table");
451
hash_init(
452
gPageBeingParsed->depend_hash,
453
DependHashSize,
454
(EqualFunction) string_equal,
455
(HashcodeFunction) string_hash);
456
}
457
for (node = bound_node->data.node;
458
node->type != openaxiom_Endarg_token;
459
node = node->next) {
460
if (node->type == openaxiom_Word_token) {
461
depend = (SpadcomDepend *) halloc(sizeof(SpadcomDepend), "SpadcomDepend");
462
depend->label = alloc_string(node->data.text);
463
depend->spadcom = cur_spadcom;
464
depend->executed = 0;
465
hash_insert(gPageBeingParsed->depend_hash, (char *)depend, depend->label);
466
}
467
}
468
}
469
470
/* Returns true iff the TextNode contains a single integer */
471
472
int
473
is_number(const char * str)
474
{
475
const char *s;
476
477
for (s = str; *s != '\0'; s++) {
478
if (!(isdigit(*s) || *s == '-'))
479
return 0;
480
}
481
return 1;
482
}
483
void
484
parser_error(char *str)
485
{
486
/** this procedure is called by the parser when an error occurs. It prints
487
the error message, followed by the next 10 tokens to ease finding the
488
error for the user. *****/
489
490
int i, v;
491
492
fprintf(stderr, " %s\n", str);
493
fprintf(stderr, "Here are the next 10 tokens:\n");
494
for (i = 0; i < 10; i++) {
495
v = get_token();
496
if (v == EOF)
497
break;
498
print_token();
499
}
500
fprintf(stderr, "\n");
501
exit(-1);
502
}
503
504
505
#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
506
#define delim(c) \
507
(whitespace(c))
508
509
510
/* advance token to the next token in the input stream. */
511
int
512
get_filename()
513
{
514
int c, ws;
515
static int seen_white = 0; /*UNUSED */
516
static char buffer[256];
517
char *buf = buffer;
518
519
if (last_token) {
520
last_token = 0;
521
return 0;
522
}
523
do {
524
keyword_fpos = fpos;
525
c = get_char();
526
ws = whitespace(c);
527
if (ws)
528
seen_white = 1;
529
} while (ws);
530
switch (c) {
531
case EOF:
532
fprintf(stderr, "(HyperDoc) Error trying to read %s, unexpected end-of-file.\n",db_file_name);
533
exit(-1);
534
case '%':
535
case '\\':
536
case '{':
537
case '}':
538
fprintf(stderr, "(HyperDoc) Error unexpected character %c.\n",c);
539
exit(-1);
540
default:
541
do {
542
*buf++ = c;
543
} while ((c = get_char()) != EOF && !delim(c));
544
unget_char(c);
545
*buf = '\0';
546
token.type = openaxiom_Word_token;
547
token.id = buffer;
548
seen_white = 0;
549
break;
550
}
551
return 1;
552
}
553
554
char *
555
get_input_string()
556
{
557
char *string;
558
TextNode *string_node,*save_node;
559
560
save_node = curr_node;
561
/* Get the nodes that make up the string */
562
string_node = alloc_node();
563
curr_node = string_node;
564
parse_HyperDoc();
565
curr_node->type = openaxiom_Endarg_token;
566
567
/* Once here we print to string to get the actual name */
568
string = print_to_string(string_node);
569
free_node(string_node, 0);
570
curr_node=save_node;
571
return string;
572
}
573
574
/*
575
* tries to determine if there is an optional argument for where I should be
576
* parsing from. If so it then tries to determine which
577
*/
578
SourceInputKind
579
get_where()
580
{
581
SourceInputKind tw;
582
583
get_token();
584
if (token.type != openaxiom_Word_token)
585
return SourceInputKind::Error;
586
587
/* Now try to determine if it is a good type */
588
if (!strcmp(token.id, "lisp")) {
589
tw = SourceInputKind::SpadSocket;
590
}
591
else if (!strcmp(token.id, "unix")) {
592
tw = SourceInputKind::UnixFD;
593
}
594
else if (!strcmp(token.id, "ht")) {
595
tw = SourceInputKind::File;
596
}
597
else {
598
return SourceInputKind::Error;
599
}
600
601
/* now check to see if I got a closing square brace */
602
get_token();
603
if (token.type != openaxiom_Rsquarebrace_token)
604
return SourceInputKind::Error;
605
606
return tw;
607
}
608
609
610
FILE *
611
find_fp(FilePosition fp)
612
{
613
FILE *lfile;
614
char fullname[256], addname[256];
615
int ret_val;
616
617
/* find the source file in the file hash table, if not there, open it */
618
lfile = (FILE *) hash_find(&gFileHashTable, fp.name);
619
if (lfile == NULL) {
620
lfile = ht_file_open(fullname, addname, fp.name);
621
hash_insert(&gFileHashTable, (char *)lfile, fp.name);
622
}
623
624
/* seek to beginning fp.pos */
625
ret_val = fseek(lfile, fp.pos, 0);
626
if (ret_val == -1) {
627
perror("fseeking to a page");
628
longjmp(jmpbuf, 1);
629
}
630
631
/* now set some global values */
632
page_start_fpos = fp.pos;
633
line_number = fp.ln;
634
return lfile;
635
}
636
637