1 /*
2 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 - Neither the name of The Numerical ALgorithms Group Ltd. nor the
18 names of its contributors may be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /******************************************************************************
35 *
36 * parse-types.h: HyperDoc parsing routines for node types.
37 *
38 * Copyright The Numerical Algorithms Group Limited 1991, 1992, 1993.
39 *
40 ****************************************************************************/
41
42 #include "fricas_c_macros.h"
43 #include "debug.h"
44
45 #include "parse.h"
46 #include "parse-types.h"
47 #include "hyper.h"
48 #include "lex.h"
49 #include "extent.h"
50 #include "hterror.h"
51
52 #include "all_hyper_proto.H1"
53
54 static void parse_condnode(void);
55 static void parse_hasreturnto(void);
56
57 boolean gInButton = FALSE;
58 boolean gInIf = FALSE;
59 boolean gInItems = FALSE;
60 boolean gInOptional = FALSE;
61
62 void
parse_ifcond(void)63 parse_ifcond(void)
64 {
65 TextNode *ifnode = curr_node;
66 TextNode *endif;
67 TextNode *condnode;
68
69 /*
70 * parse a conditional. At first I am just going to parse if
71 * <hypertext> fi
72 */
73 if (gInIf) {
74 curr_node->type = Noop;
75 fprintf(stderr, "\\if found within \\if \n");
76 longjmp(jmpbuf, 1);
77 fprintf(stderr, "Longjump failed, Exiting\n");
78 exit(-1);
79 }
80 gInIf++;
81 curr_node->type = Ifcond;
82 curr_node->space = token.id[-1];
83 curr_node->data.ifnode = alloc_ifnode();
84 /* Now get the cond node I hope */
85
86 condnode = curr_node->data.ifnode->cond = alloc_node();
87 curr_node = condnode;
88 parse_condnode();
89
90 endif = alloc_node();
91 endif->type = Endif;
92 ifnode->data.ifnode->thennode = alloc_node();
93 curr_node = ifnode->data.ifnode->thennode;
94 parse_HyperDoc();
95 if (token.type == Fi) {
96 curr_node->type = Fi;
97 curr_node->next = endif;
98 ifnode->data.ifnode->elsenode = endif;
99 }
100 else if (token.type == Else) {
101 /* first finish up the then part */
102 curr_node->type = Fi;
103 curr_node->next = endif;
104 /* the go and parse the else part */
105 ifnode->data.ifnode->elsenode = alloc_node();
106 curr_node = ifnode->data.ifnode->elsenode;
107 parse_HyperDoc();
108 if (token.type != Fi) {
109 token_name(token.type);
110 curr_node->type = Noop;
111 fprintf(stderr, "Expected a \\fi not a %s", ebuffer);
112 longjmp(jmpbuf, 1);
113 fprintf(stderr, "Longjump failed, Exiting\n");
114 exit(-1);
115 }
116 curr_node->type = Fi;
117 curr_node->next = endif;
118 }
119 else {
120 curr_node->type = Noop;
121 token_name(token.type);
122 fprintf(stderr, "Expected a \\fi not a %s", ebuffer);
123 longjmp(jmpbuf, 1);
124 fprintf(stderr, "Longjump failed, Exiting\n");
125 exit(-1);
126 }
127 ifnode->next = ifnode->data.ifnode->thennode;
128 ifnode->width = -1; /* A flag for compute if extents */
129 curr_node = endif;
130 gInIf--;
131 }
132
133 static void
parse_condnode(void)134 parse_condnode(void)
135 {
136 get_token();
137
138 switch (token.type) {
139 case Cond:
140 curr_node->type = Cond;
141 curr_node->data.text = alloc_string(token.id);
142 break;
143 case Haslisp:
144 case Hasreturn:
145 case Lastwindow:
146 case Hasup:
147 curr_node->type = token.type;
148 break;
149 case Boxcond:
150 curr_node->type = Boxcond;
151 curr_node->data.text = alloc_string(token.id);
152 break;
153 case Hasreturnto:
154 parse_hasreturnto();
155 break;
156 default:
157 {
158 char eb[128];
159 token_name(token.type);
160 sprintf(eb, "Unexpected Token %s\n", ebuffer);
161 htperror(eb, HTCONDNODE);
162 }
163 break;
164 }
165 }
166
167 static void
parse_hasreturnto(void)168 parse_hasreturnto(void)
169 {
170 TextNode *hrt = curr_node, *arg_node = alloc_node();
171
172 curr_node->type = Hasreturnto;
173 curr_node = arg_node;
174 get_expected_token(Lbrace);
175 parse_HyperDoc();
176 curr_node->type = Endarg;
177 hrt->data.node = arg_node;
178 curr_node = hrt;
179 }
180
181 void
parse_newcond(void)182 parse_newcond(void)
183 {
184 char label[256];
185
186 get_expected_token(Lbrace);
187 get_expected_token(Unkeyword);
188 strcpy(label, token.id);
189 get_expected_token(Rbrace);
190 insert_cond(label, "0");
191 curr_node->type = Noop;
192 }
193
194 void
parse_setcond(void)195 parse_setcond(void)
196 {
197 char label[256], cond[256];
198
199 get_expected_token(Lbrace);
200 get_expected_token(Cond);
201 strcpy(label, token.id);
202 get_expected_token(Rbrace);
203 get_expected_token(Lbrace);
204 get_expected_token(Word);
205 strcpy(cond, token.id);
206 get_expected_token(Rbrace);
207 change_cond(label, cond);
208 curr_node->type = Noop;
209 }
210
211 void
parse_begin_items(void)212 parse_begin_items(void)
213 {
214 TextNode *bi = curr_node;
215
216 /*
217 * This procedure parses a begin item. It sets the current
218 * node and sees if there is an optional argument for the itemspace
219 */
220
221 bi->type = token.type;
222 get_token();
223 if (token.type == Lsquarebrace) {
224 bi->data.node = alloc_node();
225 curr_node = bi->data.node;
226 gInOptional++;
227 parse_HyperDoc();
228 gInOptional--;
229 curr_node->type = Enddescription;
230 if (token.type != Rsquarebrace) {
231 fprintf(stderr, "(HyperDoc) Optional arguments must end with ].\n");
232 print_next_ten_tokens();
233 print_page_and_filename();
234 jump();
235 }
236 curr_node = bi;
237 }
238 else
239 unget_token();
240 gInItems++;
241 }
242
243 void
parse_item(void)244 parse_item(void)
245 {
246 if (!gInItems) {
247 fprintf(stderr, "\\item found outside an items environment\n");
248 print_page_and_filename();
249 print_next_ten_tokens();
250 jump();
251 }
252 curr_node->type = Item;
253 get_token();
254 if (token.type == Lsquarebrace) {
255 /* I should parse the optional argument */
256 curr_node->next = alloc_node();
257 curr_node = curr_node->next;
258 curr_node->type = Description;
259 curr_node->next = alloc_node();
260 curr_node = curr_node->next;
261 gInOptional++;
262 parse_HyperDoc();
263 gInOptional--;
264 curr_node->type = Enddescription;
265 if (token.type != Rsquarebrace) {
266 fprintf(stderr, "(HyperDoc) Optional arguments must end with ].\n");
267 print_next_ten_tokens();
268 print_page_and_filename();
269 jump();
270 }
271 }
272 else {
273 unget_token();
274 }
275 }
276
277 void
parse_mitem(void)278 parse_mitem(void)
279 {
280 if (!gInItems) {
281 fprintf(stderr, "\\mitem found outside an items environment\n");
282 print_page_and_filename();
283 print_next_ten_tokens();
284 jump();
285 }
286 curr_node->type = Mitem;
287 }
288
289 char *vbuf = NULL;
290 int vbuf_size = 0;
291
292 #define VbufSlop 10
293 #define resizeVbuf()\
294 if (size == vbuf_size) { \
295 vbuf = resizeBuffer(size + VbufSlop, vbuf, &vbuf_size); \
296 vb = vbuf + size; \
297 }
298
299 #define new_verb_node() \
300 resizeVbuf(); \
301 *vb = '\0'; \
302 curr_node->data.text = alloc_string(vbuf); \
303 curr_node->next = alloc_node(); \
304 curr_node = curr_node->next; \
305 curr_node->type = Newline; \
306 curr_node->next = alloc_node(); \
307 curr_node = curr_node->next; \
308 curr_node->type = type; \
309 if (*end_string == '\n') es = end_string+1; \
310 else es = end_string; \
311 size = 0; \
312 vb = vbuf;
313
314 void
parse_verbatim(int type)315 parse_verbatim(int type)
316 {
317 int size = 0, c;
318 char *end_string, *vb = vbuf, *es;
319
320 curr_node->type = type;
321 if (token.id[-1])
322 curr_node->space = 1;
323 if (type == Spadsrctxt) {
324 es = end_string = "\n\\end{spadsrc}";
325 }
326 else if (type == Math)
327 es = end_string = "$";
328 else
329 es = end_string = "\\end{verbatim}";
330 while ((c = get_char()) != EOF) {
331 resizeVbuf();
332 size++;
333 if (c == '\n') {
334 new_verb_node();
335 continue;
336 }
337 *vb++ = c;
338 if (*es++ != c)
339 es = end_string;
340 if (!*es)
341 break;
342 }
343 if (c == EOF) {
344 fprintf(stderr, "parse_verbatim: Unexpected EOF found\n");
345 longjmp(jmpbuf, 1);
346 }
347 resizeVbuf();
348 if (*end_string == '\n')
349 es = end_string + 1;
350 else
351 es = end_string;
352 vbuf[size - strlen(es)] = '\0';
353 if (*vbuf) {
354 curr_node->data.text = alloc_string(vbuf);
355 curr_node->next = alloc_node();
356 curr_node = curr_node->next;
357 }
358 if (type == Spadsrctxt)
359 curr_node->type = Endspadsrc;
360 else if (type == Math)
361 curr_node->type = Endmath;
362 else
363 curr_node->type = Endverbatim;
364 }
365
366 void
parse_input_pix(void)367 parse_input_pix(void)
368 {
369 TextNode *pixnode;
370 char *filename;
371
372 pixnode = curr_node;
373 pixnode->type = token.type;
374 pixnode->space = token.id[-1];
375 pixnode->width = -1;
376 get_expected_token(Lbrace);
377 filename = get_input_string();
378 pixnode->data.text = alloc_string(filename);
379 curr_node = pixnode;
380 if (pixnode->type == Inputimage) {
381 char f[256];
382 char *p;
383
384 if ((gXDisplay && DisplayPlanes(gXDisplay, gXScreenNumber) == 1) || gSwitch_to_mono ==1) {
385 pixnode->type = Inputbitmap;
386 strcpy(f, pixnode->data.text);
387 strcat(f, ".bm");
388 p=pixnode->data.text;
389 pixnode->data.text = alloc_string(f);
390 free(p);
391 }
392 else {
393 pixnode->type = Inputpixmap;
394 strcpy(f, pixnode->data.text);
395 #ifdef OLD
396 strcat(f, ".pm");
397 #endif
398 strcat(f, ".xpm");
399 p=pixnode->data.text;
400 pixnode->data.text = alloc_string(f);
401 free(p);
402 }
403 }
404 }
405
406 void
parse_centerline(void)407 parse_centerline(void)
408 {
409 curr_node->type = token.type;
410 curr_node->space = token.id[-1];
411 curr_node->width = -1;
412 curr_node->next = alloc_node();
413 curr_node = curr_node->next;
414 get_expected_token(Lbrace);
415 parse_HyperDoc();
416 if (token.type != Rbrace) {
417 curr_node->type = Noop;
418 fprintf(stderr, "(HyperdDoc) \\centerline was expecting a }\n");
419 print_page_and_filename();
420 print_next_ten_tokens();
421 longjmp(jmpbuf, 1);
422 }
423 curr_node->type = Endcenter;
424 }
425
426 void
parse_command(void)427 parse_command(void)
428 {
429 TextNode *link_node, *save_node, *arg_node;
430
431 gInButton++;
432 if (gParserMode == SimpleMode) {
433 curr_node->type = Noop;
434 fprintf(stderr, "Parser Error token %s unexpected\n",
435 token_table[token.type]);
436 longjmp(jmpbuf, 1);
437 }
438 gStringValueOk = 1;
439
440 /* set the values for the current node */
441 curr_node->type = token.type;
442 curr_node->space = token.id[-1];
443
444 /* now parse for the label */
445 link_node = curr_node;
446 curr_node->next = alloc_node();
447 curr_node = curr_node->next;
448 get_expected_token(Lbrace);
449 parse_HyperDoc();
450 curr_node->type = Endbutton;
451 save_node = curr_node;
452 arg_node = alloc_node();
453 curr_node = arg_node;
454 get_expected_token(Lbrace);
455 parse_HyperDoc();
456 curr_node->type = Endarg;
457 link_node->link = make_link_window(arg_node, link_node->type, 0);
458 gStringValueOk = 0;
459 curr_node = save_node;
460 gInButton--;
461 }
462
463 void
parse_button(void)464 parse_button(void)
465 {
466 TextNode *link_node, *save_node;
467
468 gInButton++;
469 if (gParserMode == SimpleMode) {
470 curr_node->type = Noop;
471 fprintf(stderr, "Parser Error token %s unexpected\n",
472 token_table[token.type]);
473 longjmp(jmpbuf, 1);
474 }
475 /* fill the node */
476 curr_node->type = token.type;
477 curr_node->space = token.id[-1];
478
479 /* the save the current node for creating the link and stuff */
480 link_node = curr_node;
481
482 /* then parse the label */
483 curr_node->next = alloc_node();
484 curr_node = curr_node->next;
485 get_expected_token(Lbrace);
486 parse_HyperDoc();
487 curr_node->type = Endbutton;
488
489 /* now try to get the argument node */
490 save_node = curr_node;
491 get_expected_token(Lbrace);
492 save_node->data.node = alloc_node();
493 curr_node = save_node->data.node;
494 parse_HyperDoc();
495 curr_node->type = Endarg;
496
497 /*
498 * buffer[0] = '\0'; print_to_string(arg_node, buffer + 1);
499 */
500 link_node->link =
501 make_link_window(save_node->data.node, link_node->type, 0);
502 curr_node = save_node;
503 gInButton--;
504 }
505
506 extern int example_number;
507
508 void
parse_spadcommand(TextNode * spad_node)509 parse_spadcommand(TextNode *spad_node)
510 {
511 /*TextNode *node = NULL;*/
512
513 example_number++;
514 gInButton++;
515 spad_node->type = token.type;
516 spad_node->space = token.id[-1];
517 get_expected_token(Lbrace);
518 cur_spadcom = curr_node;
519
520 spad_node->next = alloc_node();
521 curr_node = spad_node->next;
522 parse_HyperDoc();
523 curr_node->type = Endspadcommand;
524 cur_spadcom = NULL;
525 spad_node->link = make_link_window(spad_node->next, spad_node->type, 1);
526 gInButton--;
527 }
528
529 void
parse_spadsrc(TextNode * spad_node)530 parse_spadsrc(TextNode *spad_node)
531 {
532 char buf[512], *c = buf;
533 int ch, start_opts = 0;
534 /*TextNode *node = NULL;*/
535
536 example_number++;
537 gInButton++;
538 gInSpadsrc++;
539 spad_node->type = Spadsrc;
540 spad_node->space = token.id[-1];
541
542 cur_spadcom = curr_node;
543 spad_node->next = alloc_node();
544 curr_node = spad_node->next;
545
546 do {
547 ch = get_char();
548 if (ch == ']')
549 start_opts = 0;
550 if (start_opts)
551 *c++ = ch;
552 if (ch == '[')
553 start_opts = 1;
554 } while (ch != '\n');
555 *c = '\0';
556 parse_verbatim(Spadsrctxt);
557 parse_from_string(buf);
558
559 curr_node->type = Endspadsrc;
560 cur_spadcom = NULL;
561 spad_node->link = make_link_window(spad_node->next, Spadsrc, 1);
562 gInButton--;
563 gInSpadsrc--;
564 }
565
566 void
parse_env(TextNode * node)567 parse_env(TextNode *node)
568 {
569 char *env;
570 int noEnv = 0;
571
572 get_expected_token(Lbrace);
573 get_expected_token(Word);
574 env = getenv(token.id);
575
576 if (env == NULL) {
577 /** The environment variable was not found **/
578
579 fprintf(stderr, "(HyperDoc) Warning: environment variable \'%s\' was not found.\n",
580 token.id);
581
582 env = halloc(1, "string");
583 env[0] = '\0';
584 noEnv = 1;
585 }
586
587 node->data.text = alloc_string(env);
588 node->type = Word;
589
590 if (noEnv) {
591 free(env);
592 }
593 get_expected_token(Rbrace);
594 }
595
596 /*
597 * This parse_value routine accepts an empty {} but makes it a zero instead
598 * of a one. Thus \indent{} is equivalent to \indent{0}
599 */
600
601 void
parse_value1(void)602 parse_value1(void)
603 {
604 TextNode *value_node, *ocn = curr_node;
605 char *s;
606
607 curr_node->type = token.type;
608 curr_node->space = token.id[-1];
609
610 value_node = alloc_node();
611 value_node->type = Word;
612 curr_node->data.node = value_node;
613 get_expected_token(Lbrace);
614 s = get_input_string();
615 if (!is_number(s)) {
616 fprintf(stderr,
617 "Parser Error: parse for value was expecting a numeric value\n");
618 strcpy(value_node->data.text, "0");
619 }
620 else {
621 value_node->data.text = alloc_string(s);
622 }
623 curr_node = ocn;
624 }
625
626 /*
627 * This command accepts an empty argument command. Thus \space{} is
628 * equivalent to \space{1}
629 */
630
631 void
parse_value2(void)632 parse_value2(void)
633 {
634 TextNode *value_node, *ocn = curr_node;
635 char *s;
636
637 curr_node->type = token.type;
638 curr_node->space = token.id[-1];
639
640 value_node = alloc_node();
641 value_node->type = Word;
642 curr_node->data.node = value_node;
643 get_expected_token(Lbrace);
644 s = get_input_string();
645 if (!is_number(s)) {
646 fprintf(stderr,
647 "Parser Error: parse for value was expecting a numeric value\n");
648 strcpy(value_node->data.text, "1");
649 }
650 else {
651 value_node->data.text = alloc_string(s);
652 }
653 curr_node = ocn;
654 }
655
656
657 /* parse a \table sommand */
658
659 void
parse_table(void)660 parse_table(void)
661 {
662 TextNode *tn = curr_node;
663
664 if (gParserMode != AllMode) {
665 curr_node->type = Noop;
666 fprintf(stderr, "Parser Error token %s unexpected\n",
667 token_table[token.type]);
668 longjmp(jmpbuf, 1);
669 }
670 curr_node->type = Table;
671 get_expected_token(Lbrace);
672 curr_node->next = alloc_node();
673 curr_node = curr_node->next;
674
675 get_token();
676 if (token.type == Lbrace) {
677 while (token.type != Rbrace) {
678 curr_node->type = Tableitem;
679 curr_node->next = alloc_node();
680 curr_node = curr_node->next;
681 parse_HyperDoc();
682 curr_node->type = Endtableitem;
683 curr_node->next = alloc_node();
684 curr_node = curr_node->next;
685 get_token();
686 }
687 curr_node->type = Endtable;
688 }
689 else { /* a patch for SG for empty tables */
690 if (token.type != Rbrace) {
691 token_name(token.type);
692 fprintf(stderr,
693 "Unexpected Token %s found while parsing a table\n",
694 ebuffer);
695 print_page_and_filename();
696 jump();
697 }
698 tn->type = Noop;
699 tn->next = NULL;
700 free(curr_node);
701 curr_node = tn;
702 }
703 }
704
705 void
parse_box(void)706 parse_box(void)
707 {
708 curr_node->type = token.type;
709 curr_node->space = token.id[-1];
710 curr_node->width = -1;
711 curr_node->next = alloc_node();
712 curr_node = curr_node->next;
713 get_expected_token(Lbrace);
714 parse_HyperDoc();
715 curr_node->type = Endbox;
716 }
717
718 void
parse_mbox(void)719 parse_mbox(void)
720 {
721 curr_node->type = token.type;
722 curr_node->space = token.id[-1];
723 curr_node->width = -1;
724 curr_node->next = alloc_node();
725 curr_node = curr_node->next;
726 get_expected_token(Lbrace);
727 parse_HyperDoc();
728 curr_node->type = Endbox;
729 }
730
731 void
parse_free(void)732 parse_free(void)
733 {
734 TextNode *free_node = curr_node;
735
736 curr_node->type = token.type;
737 curr_node->space = token.id[-1];
738 curr_node->width = -1;
739 curr_node->data.node = alloc_node();
740 curr_node = curr_node->data.node;
741 get_expected_token(Lbrace);
742 parse_HyperDoc();
743 curr_node->type = Endarg;
744 curr_node = free_node;
745 }
746
747 void
parse_help(void)748 parse_help(void)
749 {
750 curr_node->type = Noop;
751 get_token();
752 if (token.type != Lbrace) {
753 token_name(token.type);
754 fprintf(stderr, "\\helppage was expecting a { and not a %s\n", ebuffer);
755 print_page_and_filename();
756 jump();
757 }
758
759 /* before we clobber this pointer we better free the contents (cf. alloc_page) */
760 free(gPageBeingParsed->helppage);
761 gPageBeingParsed->helppage = alloc_string(get_input_string());
762
763 if (token.type != Rbrace) {
764 token_name(token.type);
765 fprintf(stderr, "\\helppage was expecting a } and not a %s\n",
766 ebuffer);
767 print_page_and_filename();
768 jump();
769 }
770 }
771