~ubuntu-branches/ubuntu/lucid/tidy/lucid

« back to all changes in this revision

Viewing changes to src/istack.c

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2008-01-20 21:46:03 UTC
  • mfrom: (3.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080120214603-poklofici9og61tx
Tags: 20080116cvs-2
* debian/control: build depends on xsltproc
  (closes: #461608)
* debian/tidy.preinst,postinst: add code to move old config file
  (closes: #461623)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* istack.c -- inline stack for compatibility with Mosaic
2
2
 
3
 
  (c) 1998-2004 (W3C) MIT, ERCIM, Keio University
 
3
  (c) 1998-2006 (W3C) MIT, ERCIM, Keio University
4
4
  See tidy.h for the copyright notice.
5
5
  
6
6
  CVS Info :
7
7
 
8
8
    $Author: arnaud02 $ 
9
 
    $Date: 2004/12/06 12:53:25 $ 
10
 
    $Revision: 1.16 $ 
 
9
    $Date: 2006/12/29 16:31:08 $ 
 
10
    $Revision: 1.21 $ 
11
11
 
12
12
*/
13
13
 
18
18
#include "tmbstr.h"
19
19
 
20
20
/* duplicate attributes */
21
 
AttVal *DupAttrs( TidyDocImpl* doc, AttVal *attrs)
 
21
AttVal *TY_(DupAttrs)( TidyDocImpl* doc, AttVal *attrs)
22
22
{
23
23
    AttVal *newattrs;
24
24
 
25
25
    if (attrs == NULL)
26
26
        return attrs;
27
27
 
28
 
    newattrs = NewAttribute();
 
28
    newattrs = TY_(NewAttribute)(doc);
29
29
    *newattrs = *attrs;
30
 
    newattrs->next = DupAttrs( doc, attrs->next );
31
 
    newattrs->attribute = tmbstrdup(attrs->attribute);
32
 
    newattrs->value = tmbstrdup(attrs->value);
33
 
    newattrs->dict = FindAttribute(doc, newattrs);
34
 
    newattrs->asp = attrs->asp ? CloneNode(doc, attrs->asp) : NULL;
35
 
    newattrs->php = attrs->php ? CloneNode(doc, attrs->php) : NULL;
 
30
    newattrs->next = TY_(DupAttrs)( doc, attrs->next );
 
31
    newattrs->attribute = TY_(tmbstrdup)(doc->allocator, attrs->attribute);
 
32
    newattrs->value = TY_(tmbstrdup)(doc->allocator, attrs->value);
 
33
    newattrs->dict = TY_(FindAttribute)(doc, newattrs);
 
34
    newattrs->asp = attrs->asp ? TY_(CloneNode)(doc, attrs->asp) : NULL;
 
35
    newattrs->php = attrs->php ? TY_(CloneNode)(doc, attrs->php) : NULL;
36
36
    return newattrs;
37
37
}
38
38
 
 
39
static Bool IsNodePushable( Node *node )
 
40
{
 
41
    if (node->tag == NULL)
 
42
        return no;
 
43
 
 
44
    if (!(node->tag->model & CM_INLINE))
 
45
        return no;
 
46
 
 
47
    if (node->tag->model & CM_OBJECT)
 
48
        return no;
 
49
 
 
50
    return yes;
 
51
}
 
52
 
39
53
/*
40
54
  push a copy of an inline node onto stack
41
55
  but don't push if implicit or OBJECT or APPLET
52
66
      <p><em>text</em></p>
53
67
      <p><em><em>more text</em></em>
54
68
*/
55
 
void PushInline( TidyDocImpl* doc, Node *node)
 
69
void TY_(PushInline)( TidyDocImpl* doc, Node *node )
56
70
{
57
71
    Lexer* lexer = doc->lexer;
58
72
    IStack *istack;
60
74
    if (node->implicit)
61
75
        return;
62
76
 
63
 
    if (node->tag == NULL)
64
 
        return;
65
 
 
66
 
    if (!(node->tag->model & CM_INLINE))
67
 
        return;
68
 
 
69
 
    if (node->tag->model & CM_OBJECT)
70
 
        return;
71
 
 
72
 
    if ( !nodeIsFONT(node) && IsPushed(doc, node) )
 
77
    if ( !IsNodePushable(node) )
 
78
        return;
 
79
 
 
80
    if ( !nodeIsFONT(node) && TY_(IsPushed)(doc, node) )
73
81
        return;
74
82
 
75
83
    /* make sure there is enough space for the stack */
79
87
            lexer->istacklength = 6;   /* this is perhaps excessive */
80
88
 
81
89
        lexer->istacklength = lexer->istacklength * 2;
82
 
        lexer->istack = (IStack *)MemRealloc(lexer->istack,
 
90
        lexer->istack = (IStack *)TidyDocRealloc(doc, lexer->istack,
83
91
                            sizeof(IStack)*(lexer->istacklength));
84
92
    }
85
93
 
86
94
    istack = &(lexer->istack[lexer->istacksize]);
87
95
    istack->tag = node->tag;
88
96
 
89
 
    istack->element = tmbstrdup(node->element);
90
 
    istack->attributes = DupAttrs( doc, node->attributes );
 
97
    istack->element = TY_(tmbstrdup)(doc->allocator, node->element);
 
98
    istack->attributes = TY_(DupAttrs)( doc, node->attributes );
91
99
    ++(lexer->istacksize);
92
100
}
93
101
 
 
102
static void PopIStack( TidyDocImpl* doc )
 
103
{
 
104
    Lexer* lexer = doc->lexer;
 
105
    IStack *istack;
 
106
    AttVal *av;
 
107
 
 
108
    --(lexer->istacksize);
 
109
    istack = &(lexer->istack[lexer->istacksize]);
 
110
 
 
111
    while (istack->attributes)
 
112
    {
 
113
        av = istack->attributes;
 
114
        istack->attributes = av->next;
 
115
        TY_(FreeAttribute)( doc, av );
 
116
    }
 
117
    TidyDocFree(doc, istack->element);
 
118
}
 
119
 
 
120
static void PopIStackUntil( TidyDocImpl* doc, TidyTagId tid )
 
121
{
 
122
    Lexer* lexer = doc->lexer;
 
123
    IStack *istack;
 
124
 
 
125
    while (lexer->istacksize > 0)
 
126
    {
 
127
        PopIStack( doc );
 
128
        istack = &(lexer->istack[lexer->istacksize]);
 
129
        if ( istack->tag->id == tid )
 
130
            break;
 
131
    }
 
132
}
 
133
 
94
134
/* pop inline stack */
95
 
void PopInline( TidyDocImpl* doc, Node *node )
 
135
void TY_(PopInline)( TidyDocImpl* doc, Node *node )
96
136
{
97
137
    Lexer* lexer = doc->lexer;
98
 
    AttVal *av;
99
 
    IStack *istack;
100
138
 
101
139
    if (node)
102
140
    {
103
 
        if (node->tag == NULL)
104
 
            return;
105
 
 
106
 
        if (!(node->tag->model & CM_INLINE))
107
 
            return;
108
 
 
109
 
        if (node->tag->model & CM_OBJECT)
 
141
        if ( !IsNodePushable(node) )
110
142
            return;
111
143
 
112
144
        /* if node is </a> then pop until we find an <a> */
113
145
        if ( nodeIsA(node) )
114
146
        {
115
 
            while (lexer->istacksize > 0)
116
 
            {
117
 
                --(lexer->istacksize);
118
 
                istack = &(lexer->istack[lexer->istacksize]);
119
 
 
120
 
                while (istack->attributes)
121
 
                {
122
 
                    av = istack->attributes;
123
 
                    istack->attributes = av->next;
124
 
                    FreeAttribute( doc, av );
125
 
                }
126
 
 
127
 
                if ( istack->tag->id == TidyTag_A )
128
 
                {
129
 
                    MemFree(istack->element);
130
 
                    break;
131
 
                }
132
 
 
133
 
                MemFree(istack->element);
134
 
            }
135
 
 
 
147
            PopIStackUntil( doc, TidyTag_A );
136
148
            return;
137
149
        }
138
150
    }
139
151
 
140
152
    if (lexer->istacksize > 0)
141
153
    {
142
 
        --(lexer->istacksize);
143
 
        istack = &(lexer->istack[lexer->istacksize]);
144
 
 
145
 
        while (istack->attributes)
146
 
        {
147
 
            av = istack->attributes;
148
 
            istack->attributes = av->next;
149
 
            FreeAttribute( doc, av );
150
 
        }
151
 
 
152
 
        MemFree(istack->element);
 
154
        PopIStack( doc );
153
155
 
154
156
        /* #427822 - fix by Randy Waki 7 Aug 00 */
155
157
        if (lexer->insert >= lexer->istack + lexer->istacksize)
157
159
    }
158
160
}
159
161
 
160
 
Bool IsPushed( TidyDocImpl* doc, Node *node)
 
162
Bool TY_(IsPushed)( TidyDocImpl* doc, Node *node )
161
163
{
162
164
    Lexer* lexer = doc->lexer;
163
165
    int i;
172
174
}
173
175
 
174
176
/*
 
177
   Test whether the last element on the stack has the same type than "node".
 
178
*/
 
179
Bool TY_(IsPushedLast)( TidyDocImpl* doc, Node *element, Node *node )
 
180
{
 
181
    Lexer* lexer = doc->lexer;
 
182
 
 
183
    if ( element && !IsNodePushable(element) )
 
184
        return no;
 
185
 
 
186
    if (lexer->istacksize > 0) {
 
187
        if (lexer->istack[lexer->istacksize - 1].tag == node->tag) {
 
188
            return yes;
 
189
        }
 
190
    }
 
191
 
 
192
    return no;
 
193
}
 
194
 
 
195
/*
175
196
  This has the effect of inserting "missing" inline
176
197
  elements around the contents of blocklevel elements
177
198
  such as P, TD, TH, DIV, PRE etc. This procedure is
188
209
  where it gets tokens from the inline stack rather than
189
210
  from the input stream.
190
211
*/
191
 
int InlineDup( TidyDocImpl* doc, Node* node )
 
212
int TY_(InlineDup)( TidyDocImpl* doc, Node* node )
192
213
{
193
214
    Lexer* lexer = doc->lexer;
194
215
    int n;
206
227
 defer duplicates when entering a table or other
207
228
 element where the inlines shouldn't be duplicated
208
229
*/
209
 
void DeferDup( TidyDocImpl* doc )
 
230
void TY_(DeferDup)( TidyDocImpl* doc )
210
231
{
211
232
    doc->lexer->insert = NULL;
212
233
    doc->lexer->inode = NULL;
213
234
}
214
235
 
215
 
Node *InsertedToken( TidyDocImpl* doc )
 
236
Node *TY_(InsertedToken)( TidyDocImpl* doc )
216
237
{
217
238
    Lexer* lexer = doc->lexer;
218
239
    Node *node;
228
249
    }
229
250
 
230
251
    /*
231
 
    
232
 
      is this is the "latest" node then update
 
252
      If this is the "latest" node then update
233
253
      the position, otherwise use current values
234
254
    */
235
255
 
239
259
        lexer->columns = doc->docIn->curcol;
240
260
    }
241
261
 
242
 
    node = NewNode(lexer);
 
262
    node = TY_(NewNode)(doc->allocator, lexer);
243
263
    node->type = StartTag;
244
264
    node->implicit = yes;
245
265
    node->start = lexer->txtstart;
252
272
        fprintf( stderr, "0-size istack!\n" );
253
273
#endif
254
274
 
255
 
    node->element = tmbstrdup(istack->element);
 
275
    node->element = TY_(tmbstrdup)(doc->allocator, istack->element);
256
276
    node->tag = istack->tag;
257
 
    node->attributes = DupAttrs( doc, istack->attributes );
 
277
    node->attributes = TY_(DupAttrs)( doc, istack->attributes );
258
278
 
259
279
    /* advance lexer to next item on the stack */
260
280
    n = (uint)(lexer->insert - &(lexer->istack[0]));
269
289
}
270
290
 
271
291
 
272
 
 
273
 
 
 
292
/*
 
293
   We have two CM_INLINE elements pushed ... the first is closing,
 
294
   but, like the browser, the second should be retained ...
 
295
   Like <b>bold <i>bold and italics</b> italics only</i>
 
296
   This function switches the tag positions on the stack,
 
297
   returning 'yes' if both were found in the expected order.
 
298
*/
 
299
Bool TY_(SwitchInline)( TidyDocImpl* doc, Node* element, Node* node )
 
300
{
 
301
    Lexer* lexer = doc->lexer;
 
302
    if ( lexer
 
303
         && element && element->tag
 
304
         && node && node->tag
 
305
         && TY_(IsPushed)( doc, element )
 
306
         && TY_(IsPushed)( doc, node ) 
 
307
         && ((lexer->istacksize - lexer->istackbase) >= 2) )
 
308
    {
 
309
        /* we have a chance of succeeding ... */
 
310
        int i;
 
311
        for (i = (lexer->istacksize - lexer->istackbase - 1); i >= 0; --i)
 
312
        {
 
313
            if (lexer->istack[i].tag == element->tag) {
 
314
                /* found the element tag - phew */
 
315
                IStack *istack1 = &lexer->istack[i];
 
316
                IStack *istack2 = NULL;
 
317
                --i; /* back one more, and continue */
 
318
                for ( ; i >= 0; --i)
 
319
                {
 
320
                    if (lexer->istack[i].tag == node->tag)
 
321
                    {
 
322
                        /* found the element tag - phew */
 
323
                        istack2 = &lexer->istack[i];
 
324
                        break;
 
325
                    }
 
326
                }
 
327
                if ( istack2 )
 
328
                {
 
329
                    /* perform the swap */
 
330
                    IStack tmp_istack = *istack2;
 
331
                    *istack2 = *istack1;
 
332
                    *istack1 = tmp_istack;
 
333
                    return yes;
 
334
                }
 
335
            }
 
336
        }
 
337
    }
 
338
    return no;
 
339
}
 
340
 
 
341
/*
 
342
  We want to push a specific a specific element on the stack,
 
343
  but it may not be the last element, which InlineDup()
 
344
  would handle. Return yes, if found and inserted.
 
345
*/
 
346
Bool TY_(InlineDup1)( TidyDocImpl* doc, Node* node, Node* element )
 
347
{
 
348
    Lexer* lexer = doc->lexer;
 
349
    int n, i;
 
350
    if ( element
 
351
         && (element->tag != NULL)
 
352
         && ((n = lexer->istacksize - lexer->istackbase) > 0) )
 
353
    {
 
354
        for ( i = n - 1; i >=0; --i ) {
 
355
            if (lexer->istack[i].tag == element->tag) {
 
356
                /* found our element tag - insert it */
 
357
                lexer->insert = &(lexer->istack[i]);
 
358
                lexer->inode = node;
 
359
                return yes;
 
360
            }
 
361
        }
 
362
    }
 
363
    return no;
 
364
}
 
365
 
 
366
/*
 
367
 * local variables:
 
368
 * mode: c
 
369
 * indent-tabs-mode: nil
 
370
 * c-basic-offset: 4
 
371
 * eval: (c-set-offset 'substatement-open 0)
 
372
 * end:
 
373
 */