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