1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
/* stack.c - code that implements a stack to handle braces and recursive calls
created by environments, and open and closing-braces
Copyright (C) 1994-2002 The Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
This file is available from http://sourceforge.net/projects/latex2rtf/
Authors:
1994-1997 Ralf Schlatterbeck
1998-2000 Georg Lehner
2001-2002 Scott Prahl
*/
#include <stdlib.h>
#include "main.h"
#include "stack.h"
#define STACKSIZE 1000
static int stack[STACKSIZE];
static int top = 0;
int BraceLevel = 0;
int BasicPush(int lev, int brack);
int BasicPop(int *lev, int *brack);
int getStackRecursionLevel(void);
void myprintStack(void)
{
int i, lev, brack;
fprintf(stderr, "\nStack Status top=%d\n", top);
i = 0;
while (2 * i < top) {
lev = stack[2 * i + 1];
brack = stack[2 * i + 2];
i++;
fprintf(stderr, " #%d lev=%d bracket=%d\n", i, lev, brack);
}
}
void InitializeStack(void)
/******************************************************************************
purpose: pushes 0,1 and 1,1 on the stack to start things out
******************************************************************************/
{
BraceLevel = 0;
RecursionLevel = 1;
PushLevels();
BraceLevel = 1;
}
int BasicPush(int lev, int brack)
/******************************************************************************
purpose: pushes the parameters lev and brack on the stack
return: top of stack
******************************************************************************/
{
/* diagnostics(5,"pushing rec=%d and bra=%d on stack",lev,brack);*/
++top;
stack[top] = lev;
++top;
stack[top] = brack;
if (top >= STACKSIZE)
diagnostics(ERROR, "Nesting too deep. latex2rtf bug, if file TeXs properly");
return top;
}
int BasicPop(int *lev, int *brack)
/******************************************************************************
purpose: pops the parameters lev and brack from the stack
return: top of stack
******************************************************************************/
{
*brack = stack[top];
--top;
*lev = stack[top];
--top;
if (top < 0)
diagnostics(ERROR, "Nesting problem. latex2rtf bug, if file TeXs properly");
/* diagnostics(5,"popped rec=%d and bra=%d off stack",*lev,*brack); */
return top;
}
void PushLevels(void)
/******************************************************************************
purpose: wrapper to hide BraceLevel from rest of program
******************************************************************************/
{
diagnostics(5, "PushLevels");
CleanStack();
(void) BasicPush(RecursionLevel, BraceLevel);
/* myprintStack(); */
}
int PopLevels(void)
/******************************************************************************
purpose: wrapper to hide BraceLevel from rest of program
******************************************************************************/
{
int level;
(void) BasicPop(&level, &BraceLevel);
return level;
}
int getStackRecursionLevel(void)
/******************************************************************************
purpose: returns the recursion level for the current BraceLevel
******************************************************************************/
{
int PopLevel, PopBrack, PPopLevel, PPopBrack, size;
PPopLevel = RecursionLevel;
PPopBrack = BraceLevel;
size = BasicPop(&PopLevel, &PopBrack);
while ((size = BasicPop(&PopLevel, &PopBrack)) >= 0) {
if (PopBrack < BraceLevel) {
break;
}
PPopLevel = PopLevel;
PPopBrack = PopBrack;
} /* while */
(void) BasicPush(PopLevel, PopBrack); /* push back */
(void) BasicPush(PPopLevel, BraceLevel);
return PPopLevel;
}
void CleanStack(void)
/******************************************************************************
purpose: removes multiple identical copies on top of stack
******************************************************************************/
{
int PopLevel, PopBrack, PPopLevel, PPopBrack;
diagnostics(5, "Cleaning Stack");
if (top < 4)
return;
BasicPop(&PPopLevel, &PPopBrack);
BasicPop(&PopLevel, &PopBrack);
while (PPopLevel == PopLevel && PPopBrack == PopBrack && top > 0)
BasicPop(&PopLevel, &PopBrack);
BasicPush(PopLevel, PopBrack);
if (PPopLevel != PopLevel || PPopBrack != PopBrack)
BasicPush(PPopLevel, PPopBrack);
/* myprintStack(); */
}
void PushBrace(void)
/******************************************************************************
purpose: sets up the stack so that a closing brace will cause all commands
enclosed by the braces to be completed
******************************************************************************/
{
/* diagnostics(5,"Pushing Brace Level");*/
BasicPush(RecursionLevel, BraceLevel);
++BraceLevel;
}
int PopBrace(void)
/******************************************************************************
purpose: to return the recursion level of the matching open brace
search down through the stack for the lowest recursionlevel
that matches the current bracelevel-1.
******************************************************************************/
{
int PopLevel, PopBrack, PPopLevel;
diagnostics(6, "Popping Brace Level");
BraceLevel--;
PPopLevel = RecursionLevel;
BasicPop(&PopLevel, &PopBrack);
while (PopBrack >= BraceLevel) {
if (PopLevel < PPopLevel)
PPopLevel = PopLevel;
BasicPop(&PopLevel, &PopBrack);
}
BasicPush(PopLevel, PopBrack); /* push back */
BasicPush(PPopLevel, BraceLevel);
return PPopLevel;
}
/*
The stack keeps track of the RecursionLevel and BraceLevel for each command.
RecursionLevel is the number of recursive calls to Convert()
BraceLevel is the number of open braces '{'
The top of stack has the current values of RecursionLevel and BraceLevel.
The initial value of RecusionLevel is 1
The initial value of BraceLevel is 0
Before each command and before each opening brace the current values
of RecursionLevel and BraceLevel are pushed on the stack.
Each closing brace triggers a search of the stack to find
the RecursionLevel for the matching open brace.
It is the lowest
RecursionLevel with the same BraceLevel as now (after subtract of the 1
closing brace found). The initial values for the RecursionLevel and
BraceLevel (1,0) always remain on the stack.
The begin document command Pushes 1,1
For example:
{ Text {\em Text} Text }
1 2 3 4 5
1 Push 12
2 Push 13
3 Push 23
4 Bracket 3->2 Pop 23 Pop 13 Pop 12 Pop 11 -found- Push back 11
return to level 1
5 Bracket 2->1
return to level 1 = current -> no return
\mbox{\em Text}
1 2 3 4
1 Push 11 RecursionLevel+1
2 Push 22
3 Push 32
4 Bracket 2->1 Pop 32 Pop 22 Pop 11 -found-
return to level 1 from level 3 -> double return from convert
The necessary Push before every command increases the stack size. If the
commands don't include a recursive call the stack is not cleaned up.
After every TranslateCommand-function the stack is cleaned
For example:
\ldots \LaTeX \today \TeX
1 2 3 4
1 Push 11
2 Push 11
3 Push 11
4 Push 11
The clean-up loop pops till the values are not identical and pushes back the last
Therefore 11 will only occur once on the stack.
*/
|