open-axiom repository from github
/*1Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.2All rights reserved.3Copyright (C) 2007-2010, Gabriel Dos Reis.4All rights reserved.56Redistribution and use in source and binary forms, with or without7modification, are permitted provided that the following conditions are8met:910- Redistributions of source code must retain the above copyright11notice, this list of conditions and the following disclaimer.1213- Redistributions in binary form must reproduce the above copyright14notice, this list of conditions and the following disclaimer in15the documentation and/or other materials provided with the16distribution.1718- Neither the name of The Numerical Algorithms Group Ltd. nor the19names of its contributors may be used to endorse or promote products20derived from this software without specific prior written permission.2122THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS23IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED24TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A25PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER26OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,27EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,28PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR29PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF30LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING31NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS32SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*/3435/******************************************************************************36*37* parse-types.h: HyperDoc parsing routines for node types.38*39* Copyright The Numerical Algorithms Group Limited 1991, 1992, 1993.40*41****************************************************************************/4243#include "openaxiom-c-macros.h"44#include "debug.h"45#include "halloc.h"46#include "sockio.h"47#include "parse.h"48#include "parse-types.h"49#include "hyper.h"50#include "lex.h"51#include "extent.h"52#include "cfuns.h"5354using namespace OpenAxiom;5556static void parse_condnode();57static void parse_hasreturnto();5859bool gInButton = false;60bool gInIf = false;61bool gInItems = false;62bool gInOptional = false;636465static const char* errmess[] = {66"place holder",67"parsing condition node",68"unrecognized keyword"69};707172/*73* htperror(): arguments: msg - like perror it accepts an error74* message to be printed erno - the erno which occurred. This is so an75* appropriate error message can be printed.76*77* The prints out the page name, and then the filename in which the error78* occurred. If possible it also tries to print out the next ten tokens.79*/8081static void82htperror(const char* msg, int erno)83{84char obuff[256];8586/* The first thing I do is create the error message */8788if (erno <= Numerrors) {89sprintf(obuff, "%s:%s\n", msg, errmess[erno]);90}91else {92sprintf(obuff, "%s:\n", msg);93fprintf(stderr, "Unknown error type %d\n", erno);94}95fprintf(stderr, "%s", obuff);9697print_page_and_filename();9899print_next_ten_tokens();100}101102void103parse_ifcond()104{105TextNode *ifnode = curr_node;106TextNode *endif;107TextNode *condnode;108109/*110* parse a conditional. At first I am just going to parse if111* <hypertext> fi112*/113if (gInIf) {114curr_node->type = openaxiom_Noop_token;115fprintf(stderr, "\\if found within \\if \n");116longjmp(jmpbuf, 1);117fprintf(stderr, "Longjump failed, Exiting\n");118exit(-1);119}120gInIf = true;121curr_node->type = openaxiom_Ifcond_token;122curr_node->space = token.id[-1];123curr_node->data.ifnode = alloc_ifnode();124/* Now get the cond node I hope */125126condnode = curr_node->data.ifnode->cond = alloc_node();127curr_node = condnode;128parse_condnode();129130endif = alloc_node();131endif->type = openaxiom_Endif_token;132ifnode->data.ifnode->thennode = alloc_node();133curr_node = ifnode->data.ifnode->thennode;134parse_HyperDoc();135if (token.type == openaxiom_Fi_token) {136curr_node->type = openaxiom_Fi_token;137curr_node->next = endif;138ifnode->data.ifnode->elsenode = endif;139}140else if (token.type == openaxiom_Else_token) {141/* first finish up the then part */142curr_node->type = openaxiom_Fi_token;143curr_node->next = endif;144/* the go and parse the else part */145ifnode->data.ifnode->elsenode = alloc_node();146curr_node = ifnode->data.ifnode->elsenode;147parse_HyperDoc();148if (token.type != openaxiom_Fi_token) {149token_name(token.type);150curr_node->type = openaxiom_Noop_token;151fprintf(stderr, "Expected a \\fi not a %s", ebuffer);152longjmp(jmpbuf, 1);153fprintf(stderr, "Longjump failed, Exiting\n");154exit(-1);155}156curr_node->type = openaxiom_Fi_token;157curr_node->next = endif;158}159else {160curr_node->type = openaxiom_Noop_token;161token_name(token.type);162fprintf(stderr, "Expected a \\fi not a %s", ebuffer);163longjmp(jmpbuf, 1);164fprintf(stderr, "Longjump failed, Exiting\n");165exit(-1);166}167ifnode->next = ifnode->data.ifnode->thennode;168ifnode->width = -1; /* A flag for compute if extents */169curr_node = endif;170gInIf = false;171}172173static void174parse_condnode()175{176get_token();177178switch (token.type) {179case openaxiom_Cond_token:180curr_node->type = openaxiom_Cond_token;181curr_node->data.text = alloc_string(token.id);182break;183case openaxiom_Haslisp_token:184case openaxiom_Hasreturn_token:185case openaxiom_Lastwindow_token:186case openaxiom_Hasup_token:187curr_node->type = token.type;188break;189case openaxiom_Boxcond_token:190curr_node->type = openaxiom_Boxcond_token;191curr_node->data.text = alloc_string(token.id);192break;193case openaxiom_Hasreturnto_token:194parse_hasreturnto();195break;196default:197{198char eb[128];199token_name(token.type);200sprintf(eb, "Unexpected Token %s\n", eb);201htperror(eb, HTCONDNODE);202}203break;204}205}206207static void208parse_hasreturnto()209{210TextNode *hrt = curr_node, *arg_node = alloc_node();211212curr_node->type = openaxiom_Hasreturnto_token;213curr_node = arg_node;214get_expected_token(openaxiom_Lbrace_token);215parse_HyperDoc();216curr_node->type = openaxiom_Endarg_token;217hrt->data.node = arg_node;218curr_node = hrt;219}220221void222parse_newcond()223{224char label[256];225226get_expected_token(openaxiom_Lbrace_token);227get_expected_token(openaxiom_Unkeyword_token);228strcpy(label, token.id);229get_expected_token(openaxiom_Rbrace_token);230insert_cond(label, "0");231curr_node->type = openaxiom_Noop_token;232}233234void235parse_setcond()236{237char label[256], cond[256];238239get_expected_token(openaxiom_Lbrace_token);240get_expected_token(openaxiom_Cond_token);241strcpy(label, token.id);242get_expected_token(openaxiom_Rbrace_token);243get_expected_token(openaxiom_Lbrace_token);244get_expected_token(openaxiom_Word_token);245strcpy(cond, token.id);246get_expected_token(openaxiom_Rbrace_token);247change_cond(label, cond);248curr_node->type = openaxiom_Noop_token;249}250251void252parse_begin_items()253{254TextNode *bi = curr_node;255256/*257* This procedure parses a begin item. It sets the current258* node and sees if there is an optional argument for the itemspace259*/260261bi->type = token.type;262get_token();263if (token.type == openaxiom_Lsquarebrace_token) {264bi->data.node = alloc_node();265curr_node = bi->data.node;266gInOptional = true;267parse_HyperDoc();268gInOptional = false;269curr_node->type = openaxiom_Enddescription_token;270if (token.type != openaxiom_Rsquarebrace_token) {271fprintf(stderr, "(HyperDoc) Optional arguments must end with ].\n");272print_next_ten_tokens();273print_page_and_filename();274jump();275}276curr_node = bi;277}278else279unget_token();280gInItems = true;281}282283void284parse_item()285{286if (!gInItems) {287fprintf(stderr, "\\item found outside an items environment\n");288print_page_and_filename();289print_next_ten_tokens();290jump();291}292curr_node->type = openaxiom_Item_token;293get_token();294if (token.type == openaxiom_Lsquarebrace_token) {295/* I should parse the optional argument */296curr_node->next = alloc_node();297curr_node = curr_node->next;298curr_node->type = openaxiom_Description_token;299curr_node->next = alloc_node();300curr_node = curr_node->next;301gInOptional = true;302parse_HyperDoc();303gInOptional = false;304curr_node->type = openaxiom_Enddescription_token;305if (token.type != openaxiom_Rsquarebrace_token) {306fprintf(stderr, "(HyperDoc) Optional arguments must end with ].\n");307print_next_ten_tokens();308print_page_and_filename();309jump();310}311}312else {313unget_token();314}315}316317void318parse_mitem()319{320if (!gInItems) {321fprintf(stderr, "\\mitem found outside an items environment\n");322print_page_and_filename();323print_next_ten_tokens();324jump();325}326curr_node->type = openaxiom_Mitem_token;327}328329char *vbuf = NULL;330int vbuf_size = 0;331332#define VbufSlop 10333#define resizeVbuf()\334if (size == vbuf_size) { \335vbuf = resizeBuffer(size + VbufSlop, vbuf, &vbuf_size); \336vb = vbuf + size; \337}338339#define new_verb_node() \340resizeVbuf(); \341*vb = '\0'; \342curr_node->data.text = alloc_string(vbuf); \343curr_node->next = alloc_node(); \344curr_node = curr_node->next; \345curr_node->type = openaxiom_Newline_token; \346curr_node->next = alloc_node(); \347curr_node = curr_node->next; \348curr_node->type = type; \349if (*end_string == '\n') es = end_string+1; \350else es = end_string; \351size = 0; \352vb = vbuf;353354void355parse_verbatim(int type)356{357int size = 0, c;358char *vb = vbuf;359const char *end_string;360const char* es;361362curr_node->type = type;363if (token.id[-1])364curr_node->space = 1;365if (type == openaxiom_Spadsrctxt_token) {366es = end_string = "\n\\end{spadsrc}";367}368else if (type == openaxiom_Math_token)369es = end_string = "$";370else371es = end_string = "\\end{verbatim}";372while ((c = get_char()) != EOF) {373resizeVbuf();374size++;375if (c == '\n') {376new_verb_node();377continue;378}379*vb++ = c;380if (*es++ != c)381es = end_string;382if (!*es)383break;384}385if (c == EOF) {386fprintf(stderr, "parse_verbatim: Unexpected EOF found\n");387longjmp(jmpbuf, 1);388}389resizeVbuf();390if (*end_string == '\n')391es = end_string + 1;392else393es = end_string;394vbuf[size - strlen(es)] = '\0';395if (*vbuf) {396curr_node->data.text = alloc_string(vbuf);397curr_node->next = alloc_node();398curr_node = curr_node->next;399}400if (type == openaxiom_Spadsrctxt_token)401curr_node->type = openaxiom_Endspadsrc_token;402else if (type == openaxiom_Math_token)403curr_node->type = openaxiom_Endmath_token;404else405curr_node->type = openaxiom_Endverbatim_token;406}407408void409parse_input_pix()410{411TextNode *pixnode;412char *filename;413414pixnode = curr_node;415pixnode->type = token.type;416pixnode->space = token.id[-1];417pixnode->width = -1;418get_expected_token(openaxiom_Lbrace_token);419filename = get_input_string();420pixnode->data.text = alloc_string(filename);421curr_node = pixnode;422if (pixnode->type == openaxiom_Inputimage_token) {423char f[256];424char *p;425426if ((gXDisplay && DisplayPlanes(gXDisplay, gXScreenNumber) == 1) || gSwitch_to_mono ==1) {427pixnode->type = openaxiom_Inputbitmap_token;428strcpy(f, pixnode->data.text);429strcat(f, ".bm");430p=pixnode->data.text;431pixnode->data.text = alloc_string(f);432free(p);433}434else {435pixnode->type = openaxiom_Inputpixmap_token;436strcpy(f, pixnode->data.text);437#ifdef OLD438strcat(f, ".pm");439#endif440strcat(f, ".xpm.Z");441p=pixnode->data.text;442pixnode->data.text = alloc_string(f);443free(p);444}445}446}447448void449parse_centerline()450{451curr_node->type = token.type;452curr_node->space = token.id[-1];453curr_node->width = -1;454curr_node->next = alloc_node();455curr_node = curr_node->next;456get_expected_token(openaxiom_Lbrace_token);457parse_HyperDoc();458if (token.type != openaxiom_Rbrace_token) {459curr_node->type = openaxiom_Noop_token;460fprintf(stderr, "(HyperdDoc) \\centerline was expecting a }\n");461print_page_and_filename();462print_next_ten_tokens();463longjmp(jmpbuf, 1);464}465curr_node->type = openaxiom_Endcenter_token;466}467468void469parse_command()470{471TextNode *link_node, *save_node, *arg_node;472473gInButton = true;474if (gParserMode == SimpleMode) {475curr_node->type = openaxiom_Noop_token;476fprintf(stderr, "Parser Error token %s unexpected\n",477token_table[token.type]);478longjmp(jmpbuf, 1);479}480gStringValueOk = 1;481482/* set the values for the current node */483curr_node->type = token.type;484curr_node->space = token.id[-1];485486/* now parse for the label */487link_node = curr_node;488curr_node->next = alloc_node();489curr_node = curr_node->next;490get_expected_token(openaxiom_Lbrace_token);491parse_HyperDoc();492curr_node->type = openaxiom_Endbutton_token;493save_node = curr_node;494arg_node = alloc_node();495curr_node = arg_node;496get_expected_token(openaxiom_Lbrace_token);497parse_HyperDoc();498curr_node->type = openaxiom_Endarg_token;499link_node->link = make_link_window(arg_node, link_node->type, 0);500gStringValueOk = 0;501curr_node = save_node;502gInButton = false;503}504505void506parse_button()507{508TextNode *link_node, *save_node;509510gInButton = true;511if (gParserMode == SimpleMode) {512curr_node->type = openaxiom_Noop_token;513fprintf(stderr, "Parser Error token %s unexpected\n",514token_table[token.type]);515longjmp(jmpbuf, 1);516}517/* fill the node */518curr_node->type = token.type;519curr_node->space = token.id[-1];520521/* the save the current node for creating the link and stuff */522link_node = curr_node;523524/* then parse the label */525curr_node->next = alloc_node();526curr_node = curr_node->next;527get_expected_token(openaxiom_Lbrace_token);528parse_HyperDoc();529curr_node->type = openaxiom_Endbutton_token;530531/* now try to get the argument node */532save_node = curr_node;533get_expected_token(openaxiom_Lbrace_token);534save_node->data.node = alloc_node();535curr_node = save_node->data.node;536parse_HyperDoc();537curr_node->type = openaxiom_Endarg_token;538539/*540* buffer[0] = '\0'; print_to_string(arg_node, buffer + 1);541*/542link_node->link =543make_link_window(save_node->data.node, link_node->type, 0);544curr_node = save_node;545gInButton = false;546}547548extern int example_number;549550void551parse_spadcommand(TextNode *spad_node)552{553/*TextNode *node = NULL;*/554555example_number++;556gInButton = true;557spad_node->type = token.type;558spad_node->space = token.id[-1];559get_expected_token(openaxiom_Lbrace_token);560cur_spadcom = curr_node;561562spad_node->next = alloc_node();563curr_node = spad_node->next;564parse_HyperDoc();565curr_node->type = openaxiom_Endspadcommand_token;566cur_spadcom = NULL;567spad_node->link = make_link_window(spad_node->next, spad_node->type, 1);568gInButton = false;569}570571void572parse_spadsrc(TextNode *spad_node)573{574char buf[512], *c = buf;575int ch, start_opts = 0;576/*TextNode *node = NULL;*/577578example_number++;579gInButton = true;580gInSpadsrc = true;581spad_node->type = openaxiom_Spadsrc_token;582spad_node->space = token.id[-1];583584cur_spadcom = curr_node;585spad_node->next = alloc_node();586curr_node = spad_node->next;587588do {589ch = get_char();590if (ch == ']')591start_opts = 0;592if (start_opts)593*c++ = ch;594if (ch == '[')595start_opts = 1;596} while (ch != '\n');597*c = '\0';598parse_verbatim(openaxiom_Spadsrctxt_token);599parse_from_string(buf);600601curr_node->type = openaxiom_Endspadsrc_token;602cur_spadcom = NULL;603spad_node->link = make_link_window(spad_node->next,604openaxiom_Spadsrc_token, 1);605gInButton = false;606gInSpadsrc = false;607}608609void610parse_env(TextNode *node)611{612char *env;613char buff[256];614char *buff_pntr = &buff[1];615int noEnv = 0;616617get_expected_token(openaxiom_Lbrace_token);618get_expected_token(openaxiom_Word_token);619env = oa_getenv(token.id);620621if (env == NULL) {622/** The environment variable was not found **/623624fprintf(stderr, "(HyperDoc) Warning: environment variable \'%s\' was not found.\n",625token.id);626627env = halloc(1, "string");628env[0] = '\0';629noEnv = 1;630}631632buff[0] = token.id[-1];633strcpy(buff_pntr, env);634635if (noEnv)636free(env);637638node->data.text = alloc_string(buff_pntr);639node->type = openaxiom_Word_token;640641get_expected_token(openaxiom_Rbrace_token);642}643644/*645* This parse_value routine accepts an empty {} but makes it a zero instead646* of a one. Thus \indent{} is equivelant to \indent{0}647*/648649void650parse_value1()651{652TextNode *value_node, *ocn = curr_node;653char *s;654655curr_node->type = token.type;656curr_node->space = token.id[-1];657658value_node = alloc_node();659value_node->type = openaxiom_Word_token;660curr_node->data.node = value_node;661get_expected_token(openaxiom_Lbrace_token);662s = get_input_string();663if (!is_number(s)) {664fprintf(stderr,665"Parser Error: parse for value was expecting a numeric value\n");666strcpy(value_node->data.text, "0");667}668else {669value_node->data.text = alloc_string(s);670}671curr_node = ocn;672}673674/*675* This command accepts an empty argument command. Thus \space{} is676* equivelant \space{1}677*/678679void680parse_value2()681{682TextNode *value_node, *ocn = curr_node;683char *s;684685curr_node->type = token.type;686curr_node->space = token.id[-1];687688value_node = alloc_node();689value_node->type = openaxiom_Word_token;690curr_node->data.node = value_node;691get_expected_token(openaxiom_Lbrace_token);692s = get_input_string();693if (!is_number(s)) {694fprintf(stderr,695"Parser Error: parse for value was expecting a numeric value\n");696strcpy(value_node->data.text, "1");697}698else {699value_node->data.text = alloc_string(s);700}701curr_node = ocn;702}703704705/* parse a \table sommand */706707void708parse_table()709{710TextNode *tn = curr_node;711712if (gParserMode != AllMode) {713curr_node->type = openaxiom_Noop_token;714fprintf(stderr, "Parser Error token %s unexpected\n",715token_table[token.type]);716longjmp(jmpbuf, 1);717}718curr_node->type = openaxiom_Table_token;719get_expected_token(openaxiom_Lbrace_token);720curr_node->next = alloc_node();721curr_node = curr_node->next;722723get_token();724if (token.type == openaxiom_Lbrace_token) {725while (token.type != openaxiom_Rbrace_token) {726curr_node->type = openaxiom_Tableitem_token;727curr_node->next = alloc_node();728curr_node = curr_node->next;729parse_HyperDoc();730curr_node->type = openaxiom_Endtableitem_token;731curr_node->next = alloc_node();732curr_node = curr_node->next;733get_token();734}735curr_node->type = openaxiom_Endtable_token;736}737else { /* a patch for SG for empty tables */738if (token.type != openaxiom_Rbrace_token) {739token_name(token.type);740fprintf(stderr,741"Unexpected Token %s found while parsing a table\n",742ebuffer);743print_page_and_filename();744jump();745}746tn->type = openaxiom_Noop_token;747tn->next = NULL;748free(curr_node);749curr_node = tn;750}751}752753void754parse_box()755{756curr_node->type = token.type;757curr_node->space = token.id[-1];758curr_node->width = -1;759curr_node->next = alloc_node();760curr_node = curr_node->next;761get_expected_token(openaxiom_Lbrace_token);762parse_HyperDoc();763curr_node->type = openaxiom_Endbox_token;764}765766void767parse_mbox()768{769curr_node->type = token.type;770curr_node->space = token.id[-1];771curr_node->width = -1;772curr_node->next = alloc_node();773curr_node = curr_node->next;774get_expected_token(openaxiom_Lbrace_token);775parse_HyperDoc();776curr_node->type = openaxiom_Endbox_token;777}778779void780parse_free()781{782TextNode *free_node = curr_node;783784curr_node->type = token.type;785curr_node->space = token.id[-1];786curr_node->width = -1;787curr_node->data.node = alloc_node();788curr_node = curr_node->data.node;789get_expected_token(openaxiom_Lbrace_token);790parse_HyperDoc();791curr_node->type = openaxiom_Endarg_token;792curr_node = free_node;793}794795void796parse_help()797{798curr_node->type = openaxiom_Noop_token;799get_token();800if (token.type != openaxiom_Lbrace_token) {801token_name(token.type);802fprintf(stderr, "\\helppage was expecting a { and not a %s\n", ebuffer);803print_page_and_filename();804jump();805}806807/* before we clobber this pointer we better free the contents (cf. alloc_page) */808free(gPageBeingParsed->helppage);809gPageBeingParsed->helppage = alloc_string(get_input_string());810811if (token.type != openaxiom_Rbrace_token) {812token_name(token.type);813fprintf(stderr, "\\helppage was expecting a } and not a %s\n",814ebuffer);815print_page_and_filename();816jump();817}818}819820821