updated libxml2 to 2.5.10
[TestXSLT.git] / ragel_xmlscanner_out.c
1 /* Automatically generated by Ragel from "ragel_xmlscanner.c".
2  *
3  * Parts of this file are copied from Ragel source covered by the GNU
4  * GPL. As a special exception, you may use the parts of this file copied
5  * from Ragel source without restriction. The remainder is derived from
6  * "ragel_xmlscanner.c" and inherits the copyright status of that file.
7  */
8
9 # 1 "ragel_xmlscanner.c"
10
11 /*
12  * This is an input file for the "Ragel" finite state machine compiler utility.
13  * It produces output code which implements a tag scanner for XML data.
14  * It is used for intelligent xml tag completion in an XML editor interface.
15  * 
16  * See the Ragel online documentation for additional
17  * information about the format of this file.
18  *
19  * Written by Marc Liyanage <http://www.entropy.ch>
20  *
21  */
22  
23  
24 #include "ragel_xmlscanner.h"
25
26
27 /* modes for the scan, before or after cursor position */
28 enum {
29         BEFORE = 1,
30         AFTER
31 };
32
33
34 # 35 "ragel_xmlscanner_out.c"
35 /* Forward dec state for the transition structure. */
36 struct XMLScannerStateStruct;
37
38 /* Only non-static data: current state, acceptance indicator. */
39 struct XMLScannerStruct
40 {
41         int *curState;
42         int accept;
43 # 26 "ragel_xmlscanner.c"
44
45                 char *data;
46                 char *stack[STACKDEPTH];
47                 char *stack_e[STACKDEPTH];
48                 int sp;
49                 int sp_e;
50                 char *mark_namestart;
51                 char *mark_nameend;
52                 char *mark_attrstart;
53                 char *mark_attrend;
54                 char *before_toptag;
55                 int cursor;
56                 int in_comment;
57                 int in_cdata;
58                 int in_tag;
59                 int mode;
60         
61 # 62 "ragel_xmlscanner_out.c"
62 };
63 typedef struct XMLScannerStruct XMLScanner;
64
65 /* Init the fsm. */
66 void XMLScannerInit( XMLScanner *fsm );
67
68 /* Execute some chunk of data. */
69 void XMLScannerExecute( XMLScanner *fsm, char *data, int dlen );
70
71 /* Indicate to the fsm tha there is no more data. */
72 void XMLScannerFinish( XMLScanner *fsm );
73
74 /* Did the machine accept? */
75 int XMLScannerAccept( XMLScanner *fsm );
76
77 # 43 "ragel_xmlscanner.c"
78
79
80
81
82 void checkETag(XMLScanner *fsm);
83 void popTag(XMLScanner *fsm);
84 void pushTag(XMLScanner *fsm);
85
86 # 87 "ragel_xmlscanner_out.c"
87 #define f XMLScanner_f
88 #define s XMLScanner_s
89 #define k XMLScanner_k
90 #define i XMLScanner_i
91 #define t XMLScanner_t
92
93 #define SPEC_ANY_FLAT    0x01
94 #define SPEC_ANY_SINGLE  0x02
95 #define SPEC_ANY_RANGE   0x04
96 #define SPEC_ANY_DEF     0x08
97 #define SPEC_IS_FINAL    0x10
98 #define SPEC_OUT_FUNC    0x20
99
100 /* The array of functions. */
101 static int XMLScanner_f[] = {
102         1, 0, 1, 1, 1, 2, 1, 3, 
103         1, 4, 1, 5, 1, 9, 1, 10, 
104         2, 1, 1, 2, 3, 3, 2, 4, 
105         4, 2, 5, 7, 2, 5, 8, 2, 
106         11, 11, 2, 12, 13, 3, 10, 11, 
107         11, 4, 4, 4, 9, 4, 4, 12, 
108         13, 12, 13, 6, 12, 13, 11, 12, 
109         13, 11
110 };
111
112 /* The array of keys of transitions. */
113 static char XMLScanner_k[] = {
114         45, 45, 45, 45, 45, 62, 45, 60, 
115         45, 45, 62, 60, 67, 68, 65, 84, 
116         65, 91, 91, 93, 93, 93, 62, 93, 
117         60, 93, 93, 62, 93, 60, 60, 62, 
118         60, 32, 47, 58, 62, 95, 9, 13, 
119         65, 90, 97, 122, 32, 45, 46, 47, 
120         58, 62, 95, 9, 13, 48, 57, 65, 
121         90, 97, 122, 32, 45, 46, 47, 58, 
122         62, 95, 9, 13, 48, 57, 65, 90, 
123         97, 122, 32, 45, 46, 47, 58, 61, 
124         62, 95, 9, 13, 48, 57, 65, 90, 
125         97, 122, 32, 45, 46, 47, 58, 61, 
126         62, 95, 9, 13, 48, 57, 65, 90, 
127         97, 122, 32, 45, 46, 47, 58, 62, 
128         95, 9, 13, 48, 57, 65, 90, 97, 
129         122, 32, 45, 46, 47, 58, 61, 62, 
130         95, 9, 13, 48, 57, 65, 90, 97, 
131         122, 45, 46, 58, 61, 95, 48, 57, 
132         65, 90, 97, 122, 45, 46, 58, 61, 
133         95, 48, 57, 65, 90, 97, 122, 45, 
134         46, 58, 61, 95, 48, 57, 65, 90, 
135         97, 122, 32, 45, 46, 47, 58, 61, 
136         62, 95, 9, 13, 48, 57, 65, 90, 
137         97, 122, 32, 45, 46, 47, 58, 61, 
138         62, 95, 9, 13, 48, 57, 65, 90, 
139         97, 122, 32, 45, 46, 47, 58, 61, 
140         62, 95, 9, 13, 48, 57, 65, 90, 
141         97, 122, 34, 39, 32, 45, 46, 47, 
142         58, 61, 62, 95, 9, 13, 48, 57, 
143         65, 90, 97, 122, 32, 45, 46, 47, 
144         58, 61, 62, 95, 9, 13, 48, 57, 
145         65, 90, 97, 122, 32, 45, 46, 47, 
146         58, 61, 62, 95, 9, 13, 48, 57, 
147         65, 90, 97, 122, 45, 46, 58, 61, 
148         95, 48, 57, 65, 90, 97, 122, 45, 
149         46, 58, 61, 95, 48, 57, 65, 90, 
150         97, 122, 45, 46, 58, 61, 95, 48, 
151         57, 65, 90, 97, 122, 45, 46, 58, 
152         61, 95, 48, 57, 65, 90, 97, 122, 
153         45, 46, 58, 61, 95, 48, 57, 65, 
154         90, 97, 122, 45, 46, 58, 61, 95, 
155         48, 57, 65, 90, 97, 122, 34, 39, 
156         32, 47, 58, 62, 95, 9, 13, 65, 
157         90, 97, 122, 34, 32, 47, 58, 62, 
158         95, 9, 13, 65, 90, 97, 122, 39, 
159         45, 46, 58, 62, 95, 48, 57, 65, 
160         90, 97, 122, 45, 46, 58, 62, 95, 
161         48, 57, 65, 90, 97, 122, 45, 46, 
162         58, 62, 95, 48, 57, 65, 90, 97, 
163         122, 45, 46, 58, 62, 95, 48, 57, 
164         65, 90, 97, 122, 45, 46, 58, 62, 
165         95, 48, 57, 65, 90, 97, 122, 45, 
166         46, 58, 62, 95, 48, 57, 65, 90, 
167         97, 122, 45, 46, 58, 62, 95, 48, 
168         57, 65, 90, 97, 122, 45, 46, 58, 
169         62, 95, 48, 57, 65, 90, 97, 122, 
170         45, 46, 58, 62, 95, 48, 57, 65, 
171         90, 97, 122, 60, 33, 47, 58, 60, 
172         95, 65, 90, 97, 122, 60, 60, 45, 
173         60, 91, 58, 60, 95, 65, 90, 97, 
174         122, 32, 45, 46, 47, 58, 60, 62, 
175         95, 9, 13, 48, 57, 65, 90, 97, 
176         122, 32, 45, 46, 47, 58, 60, 62, 
177         95, 9, 13, 48, 57, 65, 90, 97, 
178         122, 32, 45, 46, 47, 58, 60, 62, 
179         95, 9, 13, 48, 57, 65, 90, 97, 
180         122, 0
181 };
182
183 /* The array of indicies into the transition array. */
184 static unsigned char XMLScanner_i[] = {
185         1, 2, 3, 4, 5, 6, 5, 6, 
186         7, 5, 8, 9, 8, 10, 5, 6, 
187         11, 5, 12, 13, 14, 15, 16, 17, 
188         18, 19, 20, 21, 22, 23, 24, 25, 
189         24, 26, 25, 24, 27, 28, 28, 29, 
190         24, 30, 25, 24, 31, 32, 33, 34, 
191         35, 36, 37, 38, 39, 40, 41, 42, 
192         38, 43, 43, 44, 45, 46, 39, 47, 
193         48, 49, 44, 50, 51, 51, 44, 45, 
194         46, 39, 47, 48, 49, 44, 50, 51, 
195         51, 44, 52, 53, 39, 54, 55, 48, 
196         56, 44, 57, 58, 58, 44, 52, 53, 
197         39, 54, 55, 48, 56, 44, 57, 58, 
198         58, 44, 45, 46, 39, 47, 48, 49, 
199         44, 50, 51, 51, 44, 52, 53, 39, 
200         54, 55, 48, 56, 44, 57, 58, 58, 
201         59, 60, 61, 55, 62, 63, 64, 64, 
202         59, 60, 61, 55, 62, 63, 64, 64, 
203         59, 60, 61, 55, 62, 63, 64, 64, 
204         44, 52, 53, 39, 54, 55, 48, 56, 
205         44, 57, 58, 58, 44, 52, 53, 39, 
206         54, 55, 48, 56, 44, 57, 58, 58, 
207         44, 52, 53, 39, 54, 55, 48, 56, 
208         44, 57, 58, 58, 65, 66, 44, 52, 
209         53, 39, 54, 55, 48, 56, 44, 57, 
210         58, 58, 44, 52, 53, 39, 54, 55, 
211         48, 56, 44, 57, 58, 58, 44, 52, 
212         53, 39, 54, 55, 48, 56, 44, 57, 
213         58, 58, 59, 60, 61, 55, 62, 63, 
214         64, 64, 59, 60, 61, 55, 62, 63, 
215         64, 64, 59, 60, 61, 55, 62, 63, 
216         64, 64, 59, 60, 61, 55, 62, 63, 
217         64, 64, 59, 60, 61, 55, 62, 63, 
218         64, 64, 59, 60, 61, 55, 62, 63, 
219         64, 64, 67, 68, 69, 70, 71, 72, 
220         73, 74, 75, 71, 76, 76, 67, 68, 
221         71, 72, 73, 74, 75, 71, 76, 76, 
222         69, 70, 77, 78, 79, 80, 81, 82, 
223         83, 83, 77, 78, 79, 80, 81, 82, 
224         83, 83, 77, 78, 79, 80, 81, 82, 
225         83, 83, 77, 78, 79, 80, 81, 82, 
226         83, 83, 77, 78, 79, 80, 81, 82, 
227         83, 83, 77, 78, 79, 80, 81, 82, 
228         83, 83, 77, 78, 79, 80, 81, 82, 
229         83, 83, 77, 78, 79, 80, 81, 82, 
230         83, 83, 77, 78, 79, 80, 81, 82, 
231         83, 83, 84, 85, 86, 87, 88, 89, 
232         90, 91, 91, 92, 93, 94, 93, 94, 
233         95, 93, 96, 94, 97, 93, 98, 99, 
234         99, 94, 44, 45, 46, 39, 47, 93, 
235         48, 49, 44, 50, 51, 51, 94, 44, 
236         45, 46, 39, 47, 93, 48, 49, 44, 
237         50, 51, 51, 94, 44, 45, 46, 39, 
238         47, 93, 48, 49, 44, 50, 51, 51, 
239         94, 0
240 };
241
242 /* The aray of states. */
243 static int XMLScanner_s[] = {
244         768, 0, 0, 1026, 0, 0, 1, 1034, 
245         1, 1, 1, 1034, 2, 3, 1, 1034, 
246         3, 5, 1, 1034, 4, 7, 2, 1338, 
247         6, 10, 2, 2, 1034, 8, 13, 1, 
248         1034, 9, 15, 2, 1338, 11, 18, 1, 
249         16, 1026, 12, 20, 1, 1026, 13, 21, 
250         1, 1026, 14, 22, 1, 1026, 15, 23, 
251         1, 1026, 16, 24, 1, 1026, 17, 25, 
252         1, 1026, 18, 26, 1, 1034, 19, 27, 
253         1, 1034, 20, 29, 1, 1034, 21, 31, 
254         1, 1034, 22, 33, 2, 1338, 24, 36, 
255         2, 6, 1034, 26, 39, 1, 1034, 27, 
256         41, 2, 1338, 29, 44, 1, 19, 1338, 
257         30, 46, 1, 25, 1026, 31, 48, 1, 
258         1338, 32, 49, 1, 10, 1286, 33, 51, 
259         5, 3, 1286, 44, 59, 7, 4, 1286, 
260         59, 70, 7, 4, 1286, 74, 81, 8, 
261         4, 1286, 90, 93, 8, 4, 1286, 106, 
262         105, 7, 4, 1286, 121, 116, 8, 4, 
263         1286, 137, 128, 5, 3, 1286, 148, 136, 
264         5, 3, 1286, 159, 144, 5, 3, 1286, 
265         170, 152, 8, 4, 1286, 186, 164, 8, 
266         4, 1286, 202, 176, 8, 4, 1026, 218, 
267         188, 2, 1286, 220, 190, 8, 4, 1286, 
268         236, 202, 8, 4, 1286, 252, 214, 8, 
269         4, 1286, 268, 226, 5, 3, 1286, 279, 
270         234, 5, 3, 1286, 290, 242, 5, 3, 
271         1286, 301, 250, 5, 3, 1286, 312, 258, 
272         5, 3, 1286, 323, 266, 5, 3, 1034, 
273         334, 274, 1, 1034, 335, 276, 1, 1286, 
274         336, 278, 5, 3, 1034, 347, 286, 1, 
275         1286, 348, 288, 5, 3, 1034, 359, 296, 
276         1, 1286, 360, 298, 5, 3, 1286, 371, 
277         306, 5, 3, 1286, 382, 314, 5, 3, 
278         1286, 393, 322, 5, 3, 1286, 404, 330, 
279         5, 3, 1286, 415, 338, 5, 3, 1286, 
280         426, 346, 5, 3, 1286, 437, 354, 5, 
281         3, 1286, 448, 362, 5, 3, 1338, 459, 
282         370, 1, 28, 1598, 460, 372, 5, 2, 
283         8, 1050, 469, 380, 1, 1050, 470, 382, 
284         1, 1050, 471, 384, 3, 1310, 474, 388, 
285         3, 2, 1310, 481, 394, 8, 4, 1310, 
286         497, 407, 8, 4, 1310, 513, 420, 8, 
287         4, 0
288 };
289
290 /* The array of transitions. */
291 static int *XMLScanner_t[] = {
292         0, 0, s+7, 0, s+28, f+0, s+11, f+0, 
293         s+15, 0, s+11, 0, s+19, 0, s+23, 0, 
294         s+313, f+2, s+307, f+2, s+32, 0, s+36, 0, 
295         s+307, f+16, s+313, f+16, s+45, 0, s+49, 0, 
296         s+53, 0, s+57, 0, s+61, 0, s+65, 0, 
297         s+69, 0, s+90, f+4, s+73, f+4, s+77, 0, 
298         s+73, 0, s+81, 0, s+85, 0, s+307, f+6, 
299         s+313, f+6, s+94, 0, s+98, 0, s+307, f+19, 
300         s+313, f+19, s+307, f+25, s+313, f+25, s+112, 0, 
301         s+307, f+10, s+313, f+10, s+117, 0, s+108, 0, 
302         s+152, f+31, s+103, 0, s+157, f+31, s+162, f+31, 
303         s+117, f+14, s+122, 0, s+127, 0, s+132, f+37, 
304         s+103, f+14, s+137, f+37, s+142, 0, s+147, f+37, 
305         s+167, 0, s+172, 0, s+177, f+37, s+182, 0, 
306         s+186, f+37, s+191, 0, s+196, f+37, s+201, 0, 
307         s+206, 0, s+211, 0, s+216, 0, s+221, 0, 
308         s+226, 0, s+231, 0, s+235, 0, s+239, 0, 
309         s+244, 0, s+248, 0, s+253, 0, s+117, f+46, 
310         s+108, f+34, s+152, f+51, s+103, f+34, s+157, f+51, 
311         s+162, f+51, s+287, 0, s+282, 0, s+297, 0, 
312         s+302, f+14, s+292, 0, s+277, 0, s+272, 0, 
313         s+307, f+28, s+313, f+28, s+321, f+8, s+325, f+22, 
314         s+330, f+41, s+307, f+8, s+335, f+41, s+340, f+41, 
315         s+313, f+8, s+307, 0, s+313, 0, s+3, 0, 
316         s+41, 0, s+267, f+12, s+262, f+12, s+257, f+12, 
317         0
318 };
319
320 /* The start state. */
321 static int *XMLScanner_start = s+317;
322
323 /* Init the fsm to a runnable state. */
324 void XMLScannerInit( XMLScanner *fsm )
325 {
326         fsm->curState = XMLScanner_start;
327         fsm->accept = 0;
328 # 53 "ragel_xmlscanner.c"
329
330                 fsm->sp = 0;
331                 fsm->sp_e = 0;
332                 fsm->mode = BEFORE;
333                 fsm->in_comment = 0;
334                 fsm->in_cdata = 0;
335                 fsm->in_tag = 0;
336          }
337 # 338 "ragel_xmlscanner_out.c"
338 }
339
340 /* Did the fsm accept? */
341 int XMLScannerAccept( XMLScanner *fsm )
342 {
343         return fsm->accept;
344 }
345
346 /* Binary search an array of keys looking for a key. */
347 static char *XMLScannerBSearch( char c, char *keys, int len )
348 {
349         char *lower = keys;
350         char *mid;
351         char *upper = keys + len - 1;
352         while (1) {
353                 if ( upper < lower )
354                         return 0;
355
356                 /* Find the midpoint. */
357                 mid = lower + ((upper-lower) >> 1);
358
359                 if ( c < *mid )
360                         upper = mid - 1;
361                 else if ( c > *mid )
362                         lower = mid + 1;
363                 else
364                         return mid;
365         }
366 }
367
368 /* Binary search an array of keys looking for a key. */
369 static char *XMLScannerRangeBSearch( char c, char *keys, int len )
370 {
371         char *lower = keys;
372         char *mid;
373         char *upper = keys + len - 2;
374         while (1) {
375                 if ( upper < lower )
376                         return 0;
377
378                 /* Find the midpoint. Be sure to settle on the
379                  * lower end of a range. */
380                 mid = lower + (((upper-lower) >> 1) & ~1);
381
382                 if ( c < mid[0] )
383                         upper = mid - 2;
384                 else if ( c > mid[1] )
385                         lower = mid + 2;
386                 else {
387                         /* The key was found in the range mid, return it. */
388                         return mid;
389                 }
390         }
391 }
392
393 /* Execute the fsm on some chunk of data. */
394 void XMLScannerExecute( XMLScanner *fsm, char *data, int dlen )
395 {
396         char *p = data;
397         int len = dlen;
398         int *cs = fsm->curState;
399         int specs, **trans, *funcs, nfuncs;
400         char *keys;
401         unsigned char *inds;
402
403         if ( data == 0 )
404                 goto finishInput;
405
406 again:
407         if ( cs == 0 || len == 0 )
408                 goto out;
409
410         /* Get required data. */
411         specs = *cs++;
412         keys = k + *cs++;
413         inds = i + *cs++;
414
415         /* Try flat index. */
416         if ( specs & SPEC_ANY_FLAT ) {
417                 int indsLen = *cs++;
418                 keys += 2;
419                 inds += indsLen;
420         }
421
422         /* Try binary search single. */
423         if ( specs & SPEC_ANY_SINGLE ) {
424                 /* Try to find the key. */
425                 int indsLen = *cs++;
426                 char *match = XMLScannerBSearch( *p, keys, indsLen );
427
428                 if ( match != 0 ) {
429                         trans = t + (inds[match - keys]<<1);
430                         goto match;
431                 }
432
433                 /* Advance over the keys and indicies. */
434                 keys += indsLen;
435                 inds += indsLen;
436         }
437
438         /* Try binary search range. */
439         if ( specs & SPEC_ANY_RANGE ) {
440                 /* Try to find the key. */
441                 int indsLen = *cs++;
442                 char *match = XMLScannerRangeBSearch( *p, keys, (indsLen<<1) );
443
444                 if ( match != 0 ) {
445                         trans = t + (inds[(match - keys)>>1]<<1);
446                         goto match;
447                 }
448
449                 /* Advance over the keys and indicies. */
450                 keys += (indsLen<<1);
451                 inds += indsLen;
452         }
453
454         /* Try the default transition. */
455         if ( specs & SPEC_ANY_DEF ) {
456                 trans = t + ((*inds)<<1);
457                 goto match;
458         }
459
460         /* No match. */
461         cs = 0;
462         goto out;
463
464 match:
465         /* Move to the new state. */
466         cs = *trans++;
467
468         /* Check for functions. */
469         if ( (funcs=*trans) == 0 )
470                 goto noFuncs;
471
472 execFuncs:
473         nfuncs = *funcs++;
474         while ( nfuncs-- > 0 ) {
475                 switch ( *funcs++ ) {
476         case 0:
477 # 63 "ragel_xmlscanner.c"
478         {
479                 DEBUG && fprintf(stderr, "commentstart: %d %c\n", p - data, *p);
480                 fsm->in_comment = 1;
481         } break;
482         case 1:
483 # 68 "ragel_xmlscanner.c"
484         {
485                 DEBUG && fprintf(stderr, "commentend: %d %c\n", p - data, *p);
486                 fsm->in_comment = 0;
487                 fsm->in_tag = 0;
488         } break;
489         case 2:
490 # 74 "ragel_xmlscanner.c"
491         {
492                 fsm->in_cdata = 1;
493         } break;
494         case 3:
495 # 78 "ragel_xmlscanner.c"
496         {
497                 fsm->in_cdata = 0;
498                 fsm->in_tag = 0;
499         } break;
500         case 4:
501 # 83 "ragel_xmlscanner.c"
502         {
503                 DEBUG && fprintf(stderr, "enter tag at %d\n", p - data);
504                 fsm->in_tag = 1;
505         } break;
506         case 5:
507 # 88 "ragel_xmlscanner.c"
508         {
509                 DEBUG && fprintf(stderr, "exit tag at %d\n", p - data);
510                 fsm->in_tag = 0;
511         } break;
512         case 6:
513 # 93 "ragel_xmlscanner.c"
514         {
515 //              fprintf(stderr, "name: %d %c\n", p - data, *p);
516         } break;
517         case 7:
518 # 97 "ragel_xmlscanner.c"
519         {
520                 DEBUG && fprintf(stderr, "stag\n");
521                 pushTag(fsm);
522         } break;
523         case 8:
524 # 102 "ragel_xmlscanner.c"
525         {
526                 DEBUG && fprintf(stderr, "stag: start: %d end: %d %c\n", fsm->mark_namestart - data, fsm->mark_nameend - data, *p);
527                 checkETag(fsm);
528         } break;
529         case 9:
530 # 107 "ragel_xmlscanner.c"
531         {
532                 DEBUG && fprintf(stderr, "markstart: %d %c\n", p - data, *p);
533                 fsm->mark_namestart = p;
534         } break;
535         case 10:
536 # 112 "ragel_xmlscanner.c"
537         {
538                 DEBUG && fprintf(stderr, "markend: %d %c\n", (p - 1) - data, *(p-1));
539                 fsm->mark_nameend = p;
540         } break;
541         case 11:
542 # 117 "ragel_xmlscanner.c"
543         {
544 //              fprintf(stderr, "attrstart: %d %c\n", p - data, *p);
545                 fsm->mark_attrstart = p;
546         } break;
547         case 12:
548 # 122 "ragel_xmlscanner.c"
549         {
550 //              fprintf(stderr, "attrend: %d %c\n", (p - 1) - data, *(p - 1));
551                 fsm->mark_attrend = p;
552         } break;
553         case 13:
554 # 128 "ragel_xmlscanner.c"
555         {
556         //              fprintf(stderr, "attr: start: %d end: %d %c\n", fsm->mark_attrstart - data, fsm->mark_attrend - data, *p);
557 } break;
558         case 14:
559 # 132 "ragel_xmlscanner.c"
560         {
561         DEBUG && fprintf(stderr, "pi: %d\n", p - data);
562 } break;
563 # 564 "ragel_xmlscanner_out.c"
564                 }
565         }
566
567 noFuncs:
568         p++, len--;
569         goto again;
570
571 finishInput:
572         if ( cs != 0 && *cs & SPEC_IS_FINAL ) {
573                 /* The machine accepts. */
574                 fsm->accept = 1;
575                 /* If finishing in a final state then execute the
576                  * out functions for it. (if any). */
577                 if ( *cs & SPEC_OUT_FUNC ) {
578                         funcs = f+*(cs + (*cs>>8)-1);
579                         len = 1;
580                         goto execFuncs;
581                 }
582         }
583         else {
584                 /* If we are not in a final state then this
585                  * is an error. Move to the error state. */
586                 fsm->curState = 0;
587         }
588
589 out:
590         fsm->curState = cs;
591 }
592
593 /* Indicate to the fsm that the input is done. Does cleanup tasks. */
594 void XMLScannerFinish( XMLScanner *fsm )
595 {
596         XMLScannerExecute( fsm, 0, 0 );
597 }
598
599 #undef f
600 #undef s
601 #undef k
602 #undef i
603 #undef t
604 #undef SPEC_ANY_FLAT
605 #undef SPEC_ANY_SINGLE
606 #undef SPEC_ANY_RANGE
607 #undef SPEC_ANY_DEF
608 #undef SPEC_IS_FINAL
609 #undef SPEC_OUT_FUNC
610
611 # 165 "ragel_xmlscanner.c"
612
613
614
615 /* 
616  * findCompletion does the actual work of driving the state machine
617  *
618  * Input:
619  *  data   - pointer to the buffer containing the XML data
620  *  len    - length of the data to analyze
621  *  cursor - logical position of the editing cursor in the data buffer
622  *  result - pointer to integer, which will contain a bit field with
623  *           additional status information after completion:
624  *           
625  * Completion rules:
626  *
627  * - The system builds a stack of tags which are open at the indicated cursor
628  *   position in the XML data.
629  * - If completion is possible at that cursor position, the integer
630  *   result will be 0. The caller should insert a closing tag for the
631  *   topmost tag name on the stack.
632  * - It can use the other elements of the
633  *   stack for GUI goodies, like display of a stack of currently open tags
634  *   in the editor. However, it should not assume that the tag stack can be
635  *   used to close all opening tags. Instead, it should re-evaluate
636  *   the document with this routine after the tag has been inserted and the
637  *   cursor position might have moved as a result.
638  * 
639  * - There are a few cases where completion should not be performed, this
640  *   will be indicated by the bitfield in the result int parameter:
641  *   - ERROR_IN_TAG: The cursor is in the middle of a tag. No useful completion
642  *                   is possible (maybe look at the prefix and complete
643  *                   accordingly, sometime in the future...)
644  *   - ERROR_IN_COMMENT: The cursor is inside a comment block.
645  *   - ERROR_IN_CDATA: The cursor is inside a cdata section.
646  *   - ERROR_NO_TAG: There's no unmatched opening tag to the left of the cursor
647  *   - ERROR_ALREADY_BALANCED_HERE: The currently open tags to the left of the
648  *                                  cursor are already balanced with an equal amount
649  *                                  of closing tags to the right of the cursor.
650  *
651  * Results:
652  * 
653  * Returns a pointer to an array of pointers to chars.
654  * Each array entry contains one tag from the stack
655  * tags open at the cursor position.
656  *
657  */
658 char (*findCompletion(char *data, int len, int cursor, int *result, int tagpositions[]))[] {
659
660         XMLScanner scanner, *machine = &scanner;
661         char toptag[MAXTAGLENGTH];
662         unsigned int i, lower, upper, openingcount, closingcount, identical_opening, identical_closing;
663
664         char (*resultstack)[MAXTAGLENGTH] = NULL;
665         char (*resultstack_e)[MAXTAGLENGTH] = NULL;
666         
667         *result = 0;
668
669         bzero(toptag, MAXTAGLENGTH);
670
671
672         // ------------ analyze data before cursor position ------------------
673
674         XMLScannerInit(machine);
675
676         machine->mode = BEFORE;
677         machine->cursor = cursor;
678         
679         XMLScannerExecute(machine, data, cursor);
680         XMLScannerFinish(machine);
681
682
683         /* Any unbalanced open tags on the stack at all? If so, allocate memory
684          * and copy the tags over to a newly allocated buffer, into a stack.
685          */
686         if (machine->sp) {
687                 resultstack = malloc(MAXTAGLENGTH * ((machine->sp/2) + 1));
688         } else {
689                 /* Nothing useful to return to caller */
690                 *result |= ERROR_NO_TAG;
691                 return NULL;
692         }
693         
694         openingcount = (machine->sp / 2);
695         
696         for (i = 0; i < openingcount; i++) {
697                 lower = i * 2;
698                 upper = lower + 1;
699                 bzero(resultstack[i], MAXTAGLENGTH);
700                 strncpy(resultstack[i], machine->stack[lower], machine->stack[upper] - machine->stack[lower]);
701                 if (tagpositions) {
702                         tagpositions[lower] = machine->stack[lower] - data;
703                         tagpositions[upper] = machine->stack[upper] - data;
704                 }
705         }
706         
707         /* make sure the slot after the topmost tag is zeroed out, so the
708          * calling code can use that as an end of stack marker.
709          */
710         bzero(resultstack[openingcount], MAXTAGLENGTH);
711
712         strncpy(toptag, resultstack[openingcount - 1], MAXTAGLENGTH);
713         
714         if (machine->in_tag)
715                 *result |= ERROR_IN_TAG;
716         if (machine->in_comment)
717                 *result |= ERROR_IN_COMMENT;
718         if (machine->in_cdata)
719                 *result |= ERROR_IN_CDATA;
720
721         if (*result) {
722                 return resultstack;
723         }
724
725         // count identical opening tags on the top of the stack.
726         identical_opening = 1;
727         for (i = (openingcount - 2); i >= 0; i--) {
728                 if (!strcmp(resultstack[i], resultstack[i + 1])) {
729                         identical_opening++;
730                 } else {
731                         break;
732                 }
733         }
734
735
736         // ------------ analyze data after cursor position ------------------
737         
738 //      fprintf(stderr, "accept: %d\n", XMLScannerAccept(machine)); 
739
740
741         /* Reinitialize and reconfigure the scanner, and run it again, but this time with
742          * the data from the cursor position until the end.
743          */
744         XMLScannerInit(machine);
745         machine->mode = AFTER;
746         machine->cursor = cursor;
747         XMLScannerExecute(machine, data + cursor, len - cursor);
748         XMLScannerFinish(machine);
749
750         /* If there are no closing tags, we don't need to check if
751          * the topmost opening tags on the stacks are already balanced
752          */
753         closingcount = (machine->sp_e / 2);
754         if (!closingcount) {
755                 return resultstack;
756         }
757
758         resultstack_e = malloc(MAXTAGLENGTH * ((machine->sp_e/2) + 1));
759
760         for (i = 0; i < closingcount; i++) {
761                 lower = i * 2;
762                 upper = lower + 1;
763                 
764                 bzero(resultstack_e[i], MAXTAGLENGTH);
765                 strncpy(resultstack_e[i], machine->stack_e[lower], machine->stack_e[upper] - machine->stack_e[lower]);
766
767         }
768         
769         DEBUG && fprintf(stderr, "closing count %d\n", closingcount);
770
771         identical_closing = closingcount ? 1 : 0;
772         for (i = 0; i < closingcount - 1; i++) {
773                 if (!strcmp(resultstack_e[i], resultstack_e[i + 1])) {
774                         identical_closing++;
775                 } else {
776                         break;
777                 }
778         }
779
780         DEBUG && fprintf(stderr, "identical_closing %d\n", identical_closing);
781
782         /* last opening tag before cursor and first closing tag after
783          * cursor have to be identical, otherwise we are not interested
784          * if they are balanced
785          */
786         if (strcmp(resultstack[openingcount - 1], resultstack_e[0])) {
787                 free(resultstack_e);
788                 return resultstack;
789         }
790         
791         /* ok, the adjacent opening and closing tags are identical, so we
792          * need to know if there are less closing tags than opening tags,
793          * because only then does tag completion make any sense at this location
794          */
795         
796         if (identical_opening <= identical_closing) {
797                 *result |= ERROR_ALREADY_BALANCED_HERE;
798         }
799         
800         free(resultstack_e);
801         
802         // caller needs to free() this...
803         return resultstack;
804
805 }
806
807
808
809
810
811 /*
812  * Push the current start and end buffer position markers onto our 
813  * stack of currently open tags. We're operating with position numbers
814  * only at this point, later there will be actual copies out of the buffer
815  */
816 void pushTag(XMLScanner *fsm) {
817
818         char buffer[MAXTAGLENGTH];
819         bzero(buffer, sizeof(buffer));
820
821         if (fsm->sp + 2 >= (STACKDEPTH - 1)) {
822                 fprintf(stderr, "pushTag: stack overflow at %d, can't push more!\n", STACKDEPTH);
823                 return;
824         }
825
826         fsm->stack[fsm->sp++] = fsm->mark_namestart;
827         fsm->stack[fsm->sp++] = fsm->mark_nameend;
828         
829         DEBUG && strncpy(buffer, fsm->stack[fsm->sp - 2], fsm->stack[fsm->sp - 1] - fsm->stack[fsm->sp - 2]);
830         DEBUG && fprintf(stderr, "pushTag: pushing '%s'\n", buffer);
831
832 }
833
834
835
836 /*
837  * Push the current start and end buffer position markers for
838  * *end* tags onto the stack.
839  */
840 void pushETag(XMLScanner *fsm) {
841
842         char buffer[MAXTAGLENGTH];
843         bzero(buffer, sizeof(buffer));
844
845         if (fsm->sp_e + 2 >= (STACKDEPTH - 1)) {
846                 fprintf(stderr, "pushETag: stack overflow at %d, can't push more!\n", STACKDEPTH);
847                 return;
848         }
849         
850         fsm->stack_e[fsm->sp_e++] = fsm->mark_namestart;
851         fsm->stack_e[fsm->sp_e++] = fsm->mark_nameend;
852         
853         DEBUG && strncpy(buffer, fsm->stack_e[fsm->sp_e - 2], fsm->stack_e[fsm->sp_e - 1] - fsm->stack_e[fsm->sp_e - 2]);
854         DEBUG && fprintf(stderr, "pushETag: pushing '%s'\n", buffer);
855 }
856
857
858
859 /* 
860  * pop the topmost element
861  */
862 void popTag(XMLScanner *fsm) {
863
864         char buffer[MAXTAGLENGTH];
865         bzero(buffer, sizeof(buffer));
866
867         if (fsm->sp < 2) {
868                 fprintf(stderr, "popTag: stack underflow, can't pop more!\n");
869                 return;
870         }
871
872         fsm->sp -= 2;
873         
874         DEBUG && strncpy(buffer, fsm->stack[fsm->sp], fsm->stack[fsm->sp + 1] - fsm->stack[fsm->sp]);
875         DEBUG && fprintf(stderr, "popTag: popping '%s'\n", buffer);
876 }
877
878
879 /*
880  * check out the end tag we just stumbled upon.
881  * the behavior is different here, according to the scan mode
882  * (before or after cursor position).
883  */
884 void checkETag(XMLScanner *fsm) {
885
886         char buffer[MAXTAGLENGTH];
887         bzero(buffer, sizeof(buffer));
888         int len;
889
890         /* return if the stack is empty in BEFORE mode, we can't do anything interesting */
891         if (!fsm->sp && fsm->mode == BEFORE) {
892                 return;
893         }
894
895         len = fsm->mark_nameend - fsm->mark_namestart;
896
897         strncpy(buffer, fsm->mark_namestart, len);
898
899         /* if topmost tag on stack is identical to current end tag, pop it */
900         if(fsm->sp && !strncmp(fsm->stack[fsm->sp - 2], buffer, len)) {
901 //              fprintf(stderr, "checkETag: popping, len = %d, etag = '%s'\n", len, buffer);
902                 popTag(fsm);                    
903         } else {
904                 pushETag(fsm);  
905         }
906
907
908 }
909