home *** CD-ROM | disk | FTP | other *** search
- /*
- * File: tex2any.cc
- * Purpose: Conversion utility for LaTeX files
- *
- * wxWindows 1.40
- * Copyright (c) 1993 Artificial Intelligence Applications Institute,
- * The University of Edinburgh
- *
- * Author: Julian Smart
- * Date: 18-4-93
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose is hereby granted without fee, provided
- * that the above copyright notice, author statement and this permission
- * notice appear in all copies of this software and related documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
- * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
- * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
- * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
- * THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
- #include <windows.h> // Included only for benefit of MSC7 precompiled headers
- #include "tex2any.h"
-
- FILE *CurrentOutput1 = NULL;
- FILE *CurrentOutput2 = NULL;
- FILE *Input = NULL;
-
- TexChunk *TopLevel = NULL;
- wxList MacroDefs(wxKEY_STRING);
- char *BigBuffer = NULL; // For reading in large chunks of text
- TexMacroDef *SoloBlockDef = NULL;
-
- void TexOutput(char *s)
- {
- if (CurrentOutput1)
- fprintf(CurrentOutput1, "%s", s);
- if (CurrentOutput2)
- fprintf(CurrentOutput2, "%s", s);
- }
-
- TexMacroDef *MatchMacro(char *buffer, int *pos, char **env)
- {
- int i = (*pos);
- TexMacroDef *def = NULL;
-
- // First, try to find begin{thing}
- if (strncmp(buffer+i, "begin{", 6) == 0)
- {
- i += 6;
-
- wxNode *node = MacroDefs.First();
- while (node && !def)
- {
- if (strncmp(buffer+i, node->key.string, strlen(node->key.string)) == 0)
- { def = (TexMacroDef *)node->Data();
- i += strlen(node->key.string); }
- else node = node->Next();
- }
- if (def)
- {
- *pos = i + 1;
- *env = def->name;
- return def;
- }
- else return NULL;
- }
-
- // Failed, so try to find macro from definition list
- wxNode *node = MacroDefs.First();
- while (node && !def)
- {
- if (strncmp(buffer+i, node->key.string, strlen(node->key.string)) == 0)
- { def = (TexMacroDef *)node->Data();
- i += strlen(node->key.string); }
- else node = node->Next();
- }
- if (def)
- {
- // We want to check whether this is a space-consuming macro
- // (e.g. {\bf word})
- if (def->consume_space && (buffer[i] == 32))
- i ++;
- *pos = i;
- return def;
- }
- return NULL;
- }
-
- Bool FindEndEnvironment(char *buffer, int *pos, char *env)
- {
- int i = (*pos);
-
- // Try to find end{thing}
- if ((strncmp(buffer+i, "end{", 4) == 0) &&
- (strncmp(buffer+i+4, env, strlen(env)) == 0))
- {
- *pos = i + 5 + strlen(env);
- return TRUE;
- }
- else return FALSE;
- }
-
- Bool read_a_line(FILE *fd, char *buf)
- {
- int ch = -2;
- int i = 0;
- buf[0] = 0;
- while (ch != EOF && ch != '\n')
- {
- ch = getc(fd);
- if (ch != EOF)
- {
- buf[i] = ch;
- i ++;
- }
- }
- buf[i] = 0;
- return (ch == EOF);
- }
-
- // environment is only non-NULL is we're looking for the end
- // of an environment, e.g. \end{itemize}
- int ParseArg(wxList& children, char *buffer, int pos, char *environment)
- {
- Bool eof = FALSE;
- BigBuffer[0] = 0;
- int buf_ptr = 0;
- int len;
-
- // Consume leading brace
- if (buffer[pos] == '{')
- pos ++;
-
- while (!eof)
- {
- len = strlen(buffer);
- if (pos >= len)
- {
- eof = read_a_line(Input, buffer);
- pos = 0;
- len = strlen(buffer);
- // Check for verbatim
- if (strncmp(buffer, "\\begin{verbatim}", 16) == 0)
- {
- if (buf_ptr > 0)
- {
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
- BigBuffer[buf_ptr] = 0;
- buf_ptr = 0;
- chunk->value = copystring(BigBuffer);
- children.Append(chunk);
- }
- BigBuffer[0] = 0;
- buf_ptr = 0;
-
- eof = read_a_line(Input, buffer);
- while (!eof && (strncmp(buffer, "\\end{verbatim}", 14) != 0))
- {
- strcat(BigBuffer, buffer);
- buf_ptr += strlen(buffer);
- eof = read_a_line(Input, buffer);
- }
- eof = read_a_line(Input, buffer);
- buf_ptr = 0;
-
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
- chunk->no_args = 1;
- chunk->name = copystring("verbatim");
- TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG);
- arg->argn = 1;
- arg->name = copystring("verbatim");
- TexChunk *str = new TexChunk(CHUNK_TYPE_STRING);
- str->value = copystring(BigBuffer);
-
- children.Append(chunk);
- chunk->children.Append(arg);
- arg->children.Append(str);
- }
- }
- char ch = buffer[pos];
- switch (ch)
- {
- case '}':
- {
- if (buf_ptr > 0)
- {
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
- BigBuffer[buf_ptr] = 0;
- buf_ptr = 0;
- chunk->value = copystring(BigBuffer);
- children.Append(chunk);
- }
- return pos+1;
- break;
- }
- /* We want to treat this kind of construct:
-
- \begin{itemize}
- ...
- \end{itemize}
-
- as if it were this:
-
- \itemize{...}
-
- */
-
- case '\\':
- {
- if (buf_ptr > 0)
- {
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
- BigBuffer[buf_ptr] = 0;
- buf_ptr = 0;
- chunk->value = copystring(BigBuffer);
- children.Append(chunk);
- }
- pos ++;
-
- if (environment && FindEndEnvironment(buffer, &pos, environment))
- return pos;
-
- char *env = NULL;
- TexMacroDef *def = MatchMacro(buffer, &pos, &env);
- if (def)
- {
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
- chunk->no_args = def->no_args;
- chunk->name = copystring(def->name);
- children.Append(chunk);
- pos = ParseMacroBody(chunk->name, chunk->children, chunk->no_args,
- buffer, pos, env);
- }
- #ifdef wx_x
- else cerr << "Warning: could not find macro: " << buffer + pos << "\n";
- #endif
- break;
- }
- // Parse constructs like {\bf thing} as if they were
- // \bf{thing}
- case '{':
- {
- pos ++;
- if (buffer[pos] == '\\')
- {
- if (buf_ptr > 0)
- {
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
- BigBuffer[buf_ptr] = 0;
- buf_ptr = 0;
- chunk->value = copystring(BigBuffer);
- children.Append(chunk);
- }
- pos ++;
- char *env;
- TexMacroDef *def = MatchMacro(buffer, &pos, &env);
- if (def)
- {
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
- chunk->no_args = def->no_args;
- chunk->name = copystring(def->name);
- children.Append(chunk);
- pos = ParseMacroBody(chunk->name, chunk->children, chunk->no_args,
- buffer, pos);
- }
- }
- else
- {
- /*
- * If all else fails, we assume that we have
- * a pair of braces on their own, so return a `dummy' macro
- * definition with just one argument to parse.
- */
- if (!SoloBlockDef)
- {
- SoloBlockDef = new TexMacroDef("solo block", 1, FALSE);
- }
- TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
- chunk->no_args = SoloBlockDef->no_args;
- chunk->name = copystring(SoloBlockDef->name);
- children.Append(chunk);
- pos = ParseMacroBody(chunk->name, chunk->children, chunk->no_args,
- buffer, pos);
- }
- break;
- }
- default:
- {
- BigBuffer[buf_ptr] = ch;
- BigBuffer[buf_ptr+1] = 0;
- buf_ptr ++;
- pos ++;
- break;
- }
- }
- }
- return pos;
- }
-
- int ParseMacroBody(char *macro_name, wxList& children,
- int no_args, char *buffer, int pos,
- char *environment)
- {
- for (int i = 0; i < no_args; i++)
- {
- TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG);
-
- children.Append(arg);
- arg->name = copystring(macro_name);
- arg->argn = i+1;
- pos = ParseArg(arg->children, buffer, pos, environment);
- }
- return pos;
- }
-
- Bool TexLoadFile(char *filename)
- {
- static char line_buffer[500];
- Input = fopen(filename, "r");
- if (Input)
- {
- read_a_line(Input, line_buffer);
- ParseMacroBody("toplevel", TopLevel->children, 1, line_buffer, 0);
- fclose(Input);
- return TRUE;
- }
- else return FALSE;
- }
-
- TexMacroDef::TexMacroDef(char *the_name, int n, Bool ig, Bool consumeSpace)
- {
- name = copystring(the_name);
- no_args = n;
- ignore = ig;
- consume_space = consumeSpace;
- }
-
- TexMacroDef::~TexMacroDef(void)
- {
- if (name) delete name;
- }
-
- TexChunk::TexChunk(int the_type)
- {
- type = the_type;
- no_args = 0;
- argn = 0;
- name = NULL;
- value = NULL;
- children.DeleteContents(TRUE);
- }
-
- TexChunk::~TexChunk(void)
- {
- if (name) delete name;
- if (value) delete value;
- }
-
- /*
- * Traverses document calling functions to allow the client to
- * write out the appropriate stuff
- */
-
-
- void TraverseDocument1(TexChunk *chunk)
- {
- switch (chunk->type)
- {
- case CHUNK_TYPE_MACRO:
- {
- wxNode *node = MacroDefs.Find(chunk->name);
- if (node)
- {
- TexMacroDef *def = (TexMacroDef *)node->Data();
- if (def->ignore)
- return;
- }
-
- OnMacro(chunk->name, chunk->no_args, TRUE);
-
- node = chunk->children.First();
- while (node)
- {
- TexChunk *child_chunk = (TexChunk *)node->Data();
- TraverseDocument1(child_chunk);
- node = node->Next();
- }
-
- OnMacro(chunk->name, chunk->no_args, FALSE);
- break;
- }
- case CHUNK_TYPE_ARG:
- {
- OnArgument(chunk->name, chunk->argn, TRUE);
-
- wxNode *node = chunk->children.First();
- while (node)
- {
- TexChunk *child_chunk = (TexChunk *)node->Data();
- TraverseDocument1(child_chunk);
- node = node->Next();
- }
-
- OnArgument(chunk->name, chunk->argn, FALSE);
- break;
- }
- case CHUNK_TYPE_STRING:
- {
- if (chunk->value)
- TexOutput(chunk->value);
- break;
- }
- }
- }
-
- void TraverseDocument(void)
- {
- TraverseDocument1(TopLevel);
- }
-
- void SetCurrentOutput(FILE *fd)
- {
- CurrentOutput1 = fd;
- CurrentOutput2 = NULL;
- }
-
- void SetCurrentOutputs(FILE *fd1, FILE *fd2)
- {
- CurrentOutput1 = fd1;
- CurrentOutput2 = fd2;
- }
-
- void AddMacroDef(char *name, int n, Bool ignore, Bool consume_space)
- {
- MacroDefs.Append(name, new TexMacroDef(name, n, ignore, consume_space));
- }
-
- void TexInitialize(void)
- {
- BigBuffer = new char[20000];
- AddMacroDef("toplevel", 1);
- TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
- TopLevel->name = copystring("toplevel");
- TopLevel->no_args = 1;
- }
-