~ubuntu-branches/ubuntu/gutsy/tidy/gutsy

« back to all changes in this revision

Viewing changes to src/istack.c

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2002-03-08 10:58:30 UTC
  • Revision ID: james.westby@ubuntu.com-20020308105830-he5azqenf1sq4jak
Tags: 20020301-1
* New upstream version.
* fix '--add-xml-decl yes --add-xml-space yes' crash bug
  thanks to  Cesar Eduardo Barros <cesarb@nitnet.com.br>
  and upstream.
  (closes: #137124)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  ilstack.c - inline stack for compatibility with Mosaic
 
3
 
 
4
  (c) 1998-2001 (W3C) MIT, INRIA, Keio University
 
5
  See tidy.c for the copyright notice.
 
6
  
 
7
  CVS Info :
 
8
 
 
9
    $Author: terry_teague $ 
 
10
    $Date: 2001/08/19 19:19:20 $ 
 
11
    $Revision: 1.6 $ 
 
12
 
 
13
*/
 
14
 
 
15
#include "platform.h"
 
16
#include "html.h"
 
17
 
 
18
extern Bool   debug_flag;
 
19
extern Node  *debug_element;
 
20
extern Lexer *debug_lexer;
 
21
 
 
22
/* duplicate attributes */
 
23
AttVal *DupAttrs(AttVal *attrs)
 
24
{
 
25
    AttVal *newattrs;
 
26
 
 
27
    if (attrs == null)
 
28
        return attrs;
 
29
 
 
30
    newattrs = NewAttribute();
 
31
    *newattrs = *attrs;
 
32
    newattrs->next = DupAttrs(attrs->next);
 
33
    newattrs->attribute = wstrdup(attrs->attribute);
 
34
    newattrs->value = wstrdup(attrs->value);
 
35
    newattrs->dict = FindAttribute(newattrs);
 
36
    return newattrs;
 
37
}
 
38
 
 
39
/*
 
40
  push a copy of an inline node onto stack
 
41
  but don't push if implicit or OBJECT or APPLET
 
42
  (implicit tags are ones generated from the istack)
 
43
 
 
44
  One issue arises with pushing inlines when
 
45
  the tag is already pushed. For instance:
 
46
 
 
47
      <p><em>text
 
48
      <p><em>more text
 
49
 
 
50
  Shouldn't be mapped to
 
51
 
 
52
      <p><em>text</em></p>
 
53
      <p><em><em>more text</em></em>
 
54
*/
 
55
void PushInline(Lexer *lexer, Node *node)
 
56
{
 
57
    IStack *istack;
 
58
 
 
59
    if (node->implicit)
 
60
        return;
 
61
 
 
62
    if (node->tag == null)
 
63
        return;
 
64
 
 
65
    if (!(node->tag->model & CM_INLINE))
 
66
        return;
 
67
 
 
68
    if (node->tag->model & CM_OBJECT)
 
69
        return;
 
70
 
 
71
    if (node->tag != tag_font && IsPushed(lexer, node))
 
72
        return;
 
73
 
 
74
    /* make sure there is enough space for the stack */
 
75
    if (lexer->istacksize + 1 > lexer->istacklength)
 
76
    {
 
77
        if (lexer->istacklength == 0)
 
78
            lexer->istacklength = 6;   /* this is perhaps excessive */
 
79
 
 
80
        lexer->istacklength = lexer->istacklength * 2;
 
81
        lexer->istack = (IStack *)MemRealloc(lexer->istack,
 
82
                            sizeof(IStack)*(lexer->istacklength));
 
83
    }
 
84
 
 
85
    istack = &(lexer->istack[lexer->istacksize]);
 
86
    istack->tag = node->tag;
 
87
 
 
88
    istack->element = wstrdup(node->element);
 
89
    istack->attributes = DupAttrs(node->attributes);
 
90
    ++(lexer->istacksize);
 
91
}
 
92
 
 
93
/* pop inline stack */
 
94
void PopInline(Lexer *lexer, Node *node)
 
95
{
 
96
    AttVal *av;
 
97
    IStack *istack;
 
98
 
 
99
    if (node)
 
100
    {
 
101
        if (node->tag == null)
 
102
            return;
 
103
 
 
104
        if (!(node->tag->model & CM_INLINE))
 
105
            return;
 
106
 
 
107
        if (node->tag->model & CM_OBJECT)
 
108
            return;
 
109
 
 
110
        /* if node is </a> then pop until we find an <a> */
 
111
        if (node->tag == tag_a)
 
112
        {
 
113
            while (lexer->istacksize > 0)
 
114
            {
 
115
                --(lexer->istacksize);
 
116
                istack = &(lexer->istack[lexer->istacksize]);
 
117
 
 
118
                while (istack->attributes)
 
119
                {
 
120
                    av = istack->attributes;
 
121
 
 
122
                    if (av->attribute)
 
123
                        MemFree(av->attribute);
 
124
                    if (av->value)
 
125
                        MemFree(av->value);
 
126
 
 
127
                    istack->attributes = av->next;
 
128
                    MemFree(av);
 
129
                }
 
130
 
 
131
                if (istack->tag == tag_a)
 
132
                {
 
133
                    MemFree(istack->element);
 
134
                    break;
 
135
                }
 
136
 
 
137
                MemFree(istack->element);
 
138
            }
 
139
 
 
140
            return;
 
141
        }
 
142
    }
 
143
 
 
144
    if (lexer->istacksize > 0)
 
145
    {
 
146
        --(lexer->istacksize);
 
147
        istack = &(lexer->istack[lexer->istacksize]);
 
148
 
 
149
        while (istack->attributes)
 
150
        {
 
151
            av = istack->attributes;
 
152
 
 
153
            if (av->attribute)
 
154
                MemFree(av->attribute);
 
155
            if (av->value)
 
156
                MemFree(av->value);
 
157
 
 
158
            istack->attributes = av->next;
 
159
            MemFree(av);
 
160
        }
 
161
 
 
162
        MemFree(istack->element);
 
163
 
 
164
        /* #427822 - fix by Randy Waki 7 Aug 00 */
 
165
        if (lexer->insert >= lexer->istack + lexer->istacksize)
 
166
            lexer->insert = null;
 
167
    }
 
168
}
 
169
 
 
170
Bool IsPushed(Lexer *lexer, Node *node)
 
171
{
 
172
    int i;
 
173
 
 
174
    for (i = lexer->istacksize - 1; i >= 0; --i)
 
175
    {
 
176
        if (lexer->istack[i].tag == node->tag)
 
177
            return yes;
 
178
    }
 
179
 
 
180
    return no;
 
181
}
 
182
 
 
183
/*
 
184
  This has the effect of inserting "missing" inline
 
185
  elements around the contents of blocklevel elements
 
186
  such as P, TD, TH, DIV, PRE etc. This procedure is
 
187
  called at the start of ParseBlock. when the inline
 
188
  stack is not empty, as will be the case in:
 
189
 
 
190
    <i><h1>italic heading</h1></i>
 
191
 
 
192
  which is then treated as equivalent to
 
193
 
 
194
    <h1><i>italic heading</i></h1>
 
195
 
 
196
  This is implemented by setting the lexer into a mode
 
197
  where it gets tokens from the inline stack rather than
 
198
  from the input stream.
 
199
*/
 
200
int InlineDup(Lexer *lexer, Node *node)
 
201
{
 
202
    int n;
 
203
 
 
204
    if ((n = lexer->istacksize - lexer->istackbase) > 0)
 
205
    {
 
206
        lexer->insert = &(lexer->istack[lexer->istackbase]);
 
207
        lexer->inode = node;
 
208
    }
 
209
 
 
210
    return n;
 
211
}
 
212
 
 
213
/*
 
214
 defer duplicates when entering a table or other
 
215
 element where the inlines shouldn't be duplicated
 
216
*/
 
217
void DeferDup(Lexer *lexer)
 
218
{
 
219
    lexer->insert = null;
 
220
    lexer->inode = null;
 
221
}
 
222
 
 
223
Node *InsertedToken(Lexer *lexer)
 
224
{
 
225
    Node *node;
 
226
    IStack *istack;
 
227
    uint n;
 
228
 
 
229
    /* this will only be null if inode != null */
 
230
    if (lexer->insert == null)
 
231
    {
 
232
        node = lexer->inode;
 
233
        lexer->inode = null;
 
234
        return node;
 
235
    }
 
236
 
 
237
    /*
 
238
    
 
239
      is this is the "latest" node then update
 
240
      the position, otherwise use current values
 
241
    */
 
242
 
 
243
    if (lexer->inode == null)
 
244
    {
 
245
        lexer->lines = lexer->in->curline;
 
246
        lexer->columns = lexer->in->curcol;
 
247
    }
 
248
 
 
249
    node = NewNode();
 
250
    node->type = StartTag;
 
251
    node->implicit = yes;
 
252
    node->start = lexer->txtstart;
 
253
    /* #431734 [JTidy bug #226261 (was 126261)] - fix by Gary Peskin 20 Dec 00 */ 
 
254
    node->end = lexer->txtend; /* was : lexer->txtstart; */
 
255
    istack = lexer->insert;
 
256
    if (lexer->istacksize == 0) /* Andy Quick 13 Jun 99 */
 
257
        tidy_out(lexer->errout, "0-size istack!\n");
 
258
    node->element = wstrdup(istack->element);
 
259
    node->tag = istack->tag;
 
260
    node->attributes = DupAttrs(istack->attributes);
 
261
 
 
262
    /* advance lexer to next item on the stack */
 
263
    n = lexer->insert - &(lexer->istack[0]);
 
264
 
 
265
    /* and recover state if we have reached the end */
 
266
    if (++n < lexer->istacksize)
 
267
        lexer->insert = &(lexer->istack[n]);
 
268
    else
 
269
        lexer->insert = null;
 
270
 
 
271
    return node;
 
272
}
 
273
 
 
274
 
 
275
 
 
276