/* Stack.C * * Adjusting the look and feel of the document in a recursive way is done * with a stack of Environments, where each environment holds variables such * as the current font and margin sizes. This describes the stack. * * Copyright 1992 Jonathan Monsarrat. Permission given to freely distribute, * edit and use as long as this copyright statement remains intact. * */ #include "Global.h" #include "Document.h" #include "Font.h" #include #include #include Environment *Stack::environments[MAXNESTING]; int Stack::level; Stack::Stack() { level=0; for(int x=0; x < MAXNESTING; x++) environments[x] = NULL; environments[0] = new Environment(); // Initialize the root environment } void Stack::push(int, int, float, char *) { if(level > MAXNESTING) Global::files->fatal_error("Too much nesting"); environments[level+1] = new Environment(environments[level]); level++; } void Stack::pop(int, int subtype, float, char *) { if(level == 0) Global::files->fatal_error("Too many \\end or } tokens"); Stack::get(Environment::PDocument, subtype, ""); environments[level-1]->revert(environments[level]); delete environments[level]; level--; } /* This functions sets a parameter in the current environment. When the '}' * character or the \end command is encountered, the current environment * will popped off the stack and this parameter will be reset to its former * value (the value previous to the last '{' character or \begin command * or the default value) */ void Stack::set(int paramtype, int subtype, float value, char *replacestr) { environments[level]->set(paramtype,subtype,value,replacestr); } /* This functions sets a parameter in the current environment, relative * to its current value. */ void Stack::relative_set(int paramtype, int subtype, float value, char *replacestr) { environments[level]-> set(paramtype, subtype, value + environments[level]->get(paramtype, subtype, replacestr), replacestr); } /* This function gets a parameter value from the current environment, * as indexed by the parameter type and subtype. */ float Stack::get(int paramtype, int subtype, char *comparestr) { return environments[level]->get(paramtype, subtype, comparestr); } void Stack::shutdown() { char commandname[MAXSTRING]; if(level > 0) Global::files->fatal_error("Missing \\end or }"); Global::files->outfile << endl; Global::files->outfile << "ENDPAGE" << endl; Stack::get(Environment::PDocument, Document::ShutDown, ""); Global::files->outfile.close(); Global::labels->shutdown(); char realname[MAXSTRING]; char srcdir[MAXSTRING]; // Take a trailing / off the source strcpy(srcdir,SRCDIR); // directory pathname, if needed. int last = strlen(srcdir) - 1; if(srcdir[last]=='/') srcdir[last]='\0'; strcpy(realname, Global::files->outfilename); char *p = strchr(realname,'.'); *p='\0'; if(Global::files->plain_text_output) { sprintf(commandname, "perl %s/plaintext.pl < %s > %s.txt", srcdir, Global::files->outfilename, Global::files->outfileroot); system(commandname); sprintf(commandname, "Output has been placed in %s.txt", Global::files->outfileroot); cerr << commandname << endl; sprintf(commandname,"rm %s", Global::files->outfilename); system(commandname); return; } Stack::get(Environment::PFont, Font::ShutDown, ""); /* A number of files have been created. It's time to merge them together into one big file */ // Concatenate all these library and temporary files into // the final rootname.ps file. sprintf(commandname, "cat %s/latex.header lametex.PS %s/format.ps %s/breakpath.ps %s %s/latex.footer > %s.ps", srcdir, srcdir, srcdir, Global::files->outfilename, srcdir, realname); system(commandname); // Execute the concatenate command cerr << "Created PostScript file " << realname << ".ps" << endl; sprintf(commandname,"rm lametex.PS lametex.aux lametex.log %s", Global::files->outfilename); system(commandname); // Execute the concatenate command } Length *Stack::get_length() { return (Length *)environments[level]->get_param(Environment::PLength); }