source: proto/parabix2/src/xmlwf_multipass.cpp @ 917

Last change on this file since 917 was 917, checked in by lindanl, 9 years ago

Add multipass.

File size: 51.0 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include "../lib/lib_simd.h"
7
8#define BLOCK_SIZE 128
9#define SEGMENT_BLOCKS 24
10#define BUFFER_SIZE (BLOCK_SIZE * SEGMENT_BLOCKS * 1)
11#define OVERLAP_BUFSIZE 16
12
13typedef long ScanBlock;
14typedef SIMD_type BytePack;
15typedef SIMD_type BitBlock;
16
17#include "../lib/carryQ.h"
18#include "xmldecl.h"
19#include "xml_error.c"
20#include "xmldecl.c"
21#include "namechars.h"
22
23#include "../lib/perflib/perfsec.h"
24#include "../lib/s2p.h"
25
26#include "TagMatcher.h"
27#include "LineColTracker.h"
28
29#define TOTAL 0
30#define S2P 1
31#define CLASSIFY 2
32#define SCOPE 3
33#define CTCDPI 4
34#define TAGS 5
35#define REFS 6
36#define VALIDATE 7
37#define CHECK 8
38#define POSTPROCESS 9
39
40#ifdef BUFFER_PROFILING
41        BOM_Table * parser_timer;
42        BOM_Table * s2p_timer;
43        BOM_Table * classify_timer;
44        BOM_Table * scope_timer;
45        BOM_Table * tags_timer;
46        BOM_Table * refs_timer;
47        BOM_Table * CtCDPI_timer;
48        BOM_Table * validate_timer;
49        BOM_Table * check_timer;
50        BOM_Table * postprocess_timer;
51
52#elif CODE_CLOCKER
53        #define NUM_EVENTS 1
54        int Events[NUM_EVENTS] = {PAPI_TOT_CYC};
55        //int Events[NUM_EVENTS] = {PAPI_L2_DCM};
56        //int Events[NUM_EVENTS] = {PAPI_TOT_CYC, PAPI_BR_MSP};
57        int cal_size = 20;
58        CC * parser_timer = new CC(Events,NUM_EVENTS,cal_size);
59#else
60        void * parser_timer;
61#endif
62
63int block_base=0;
64int buffer_base=0;
65int buffer_last;
66char * source;
67LineColTracker tracker;
68TagMatcher matcher;
69
70
71static inline int StreamScan(ScanBlock * stream, int blk_count, int ProcessPos(int)) {
72        int blk;
73        int block_pos = 0;
74
75        for (blk = 0; blk < blk_count; blk++) {
76                ScanBlock s = stream[blk];
77                while(s) {
78                        int code = (ProcessPos(cfzl(s) + block_pos));
79                        if (code) return code;
80                        s = s & (s-1);  // clear rightmost bit.
81                }
82                block_pos += 8 * sizeof(ScanBlock);
83        }
84        return 0;
85}
86
87
88static inline void ReportError(const char * error_msg, int error_pos_in_block) {
89  int error_line, error_column;
90  tracker.get_Line_and_Column(error_pos_in_block, error_line, error_column);
91  fprintf(stderr, "%s at line %i, column %i\n", error_msg, error_line, error_column);
92}
93
94
95static inline int NameStrt_check(int pos) {
96        int block_pos = block_base + pos;
97        if(XML_10_UTF8_NameStrt_bytes((unsigned char*)&source[block_pos]) == 0){
98              ReportError("name start error", pos);
99              exit(-1);
100        }
101        return 0;
102}
103
104static inline int Name_check(int pos) {
105        int block_pos = block_base + pos;
106        if(XML_10_UTF8_NameChar_bytes((unsigned char*)&source[block_pos]) == 0){
107              ReportError("name error", pos);
108              exit(-1);
109        }
110        return 0;
111}
112
113static inline int PIName_check(int pos) {
114        int block_pos = block_base + pos;
115        int file_pos = block_pos+buffer_base;
116        if (at_XxMmLll<ASCII>((unsigned char*)&source[block_pos]) && (source[block_pos+3]=='?' || source[block_pos+3]<= ' ')) {
117              // "<?xml" legal at start of file.
118              if ((file_pos == 2) && at_XmlDecl_start<ASCII>((unsigned char*)&source[0])) return 0;
119              ReportError("[Xx][Mm][Ll] illegal as PI name", pos);
120              exit(-1);
121        }
122        return 0;
123}
124
125static inline int CD_check(int pos) {
126        int block_pos = block_base + pos;
127        if (!at_CDATA1<ASCII>((unsigned char*)&source[block_pos])){
128              ReportError("CDATA error", pos);
129              exit(-1);
130        }
131        return 0;
132}
133
134static inline int GenRef_check(int pos) {
135        int block_pos = block_base + pos;
136        unsigned char* s = (unsigned char*)&source[block_pos];
137        if (!(at_Ref_gt<ASCII>(s)||at_Ref_lt<ASCII>(s)||at_Ref_amp<ASCII>(s)||at_Ref_quot<ASCII>(s)||at_Ref_apos<ASCII>(s))){
138              ReportError("Undefined reference", pos);
139              exit(-1);
140        }
141        return 0;
142}
143
144static inline int HexRef_check(int pos) {
145        int block_pos = block_base + pos;
146        unsigned char* s = (unsigned char*)&source[block_pos];
147        int ch_val = 0;
148        while(at_HexDigit<ASCII>(s)){
149          ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
150          if (ch_val> 0x10FFFF ){
151            ReportError("Illegal character reference", pos);
152            exit(-1);
153          }
154          s++;
155        }
156        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
157          ReportError("Illegal character reference", pos);
158          exit(-1);
159        }
160        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
161          ReportError("Illegal XML 1.0 character reference", pos);
162          exit(-1);
163        }
164        return 0;
165}
166
167static inline int DecRef_check(int pos) {
168        int block_pos = block_base + pos;
169        unsigned char* s = (unsigned char*)&source[block_pos];
170        int ch_val = 0;
171        while(at_HexDigit<ASCII>(s)){
172          ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
173          if (ch_val> 0x10FFFF ){
174            ReportError("Illegal character reference", pos);
175            exit(-1);
176          }
177          s++;
178        }
179        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
180          ReportError("Illegal character reference", pos);
181          exit(-1);
182        }
183        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
184          ReportError("Illegal XML 1.0 character reference", pos);
185          exit(-1);
186        }
187        return 0;
188}
189
190static inline int AttRef_check(int pos) {
191        int block_pos = block_base + pos;
192        unsigned char* s = (unsigned char*)&source[block_pos];
193        int ch_val = 0;
194        if(s[0]=='#'){
195          s++;
196          if(s[0]=='x' || s[0]=='X'){
197            s++;
198            while(at_HexDigit<ASCII>(s)){
199              ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
200              s++;
201            }
202          }
203          else{
204            while(at_HexDigit<ASCII>(s)){
205              ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
206              s++;
207            }
208          }
209          if (ch_val==60){
210            ReportError("Attribute values contain '<' characters after reference expansion", pos);
211            exit(-1);
212          }
213        }
214        else if(at_Ref_lt<ASCII>(s)){
215          ReportError("Attribute values contain '<' characters after reference expansion", pos);
216          exit(-1);
217        }
218        return 0;
219}
220
221
222
223  struct U8 {
224  BitBlock unibyte;
225  BitBlock prefix;
226  BitBlock prefix2;
227  BitBlock prefix3;
228  BitBlock prefix4;
229  BitBlock suffix;
230  BitBlock badprefix;
231  BitBlock xE0;
232  BitBlock xED;
233  BitBlock xF0;
234  BitBlock xF4;
235  BitBlock xA0_xBF;
236  BitBlock x80_x9F;
237  BitBlock x90_xBF;
238  BitBlock x80_x8F;
239  BitBlock xEF;
240  BitBlock xBF;
241  BitBlock xBE;
242  BitBlock scope22;
243  BitBlock scope32;
244  BitBlock scope33;
245  BitBlock scope42;
246  BitBlock scope43;
247  BitBlock scope44;
248  BitBlock xE0_scope;
249  BitBlock xED_scope;
250  BitBlock xF0_scope;
251  BitBlock xF4_scope;
252  BitBlock xEF_scope;
253  BitBlock FFFE_FFFF;
254  BitBlock error;
255};
256
257  struct Lex {
258  BitBlock CR;
259  BitBlock LF;
260  BitBlock HT;
261  BitBlock SP;
262  BitBlock CRLF;
263  BitBlock RefStart;
264  BitBlock Semicolon;
265  BitBlock Colon;
266  BitBlock LAngle;
267  BitBlock RAngle;
268  BitBlock LBracket;
269  BitBlock RBracket;
270  BitBlock Exclam;
271  BitBlock QMark;
272  BitBlock Hyphen;
273  BitBlock Equals;
274  BitBlock SQuote;
275  BitBlock DQuote;
276  BitBlock Slash;
277  BitBlock Hash;
278  BitBlock x;
279  BitBlock ASCII_name_start;
280  BitBlock ASCII_name_char;
281  BitBlock NameScan;
282  BitBlock Digit;
283  BitBlock Hex;
284  BitBlock WS;
285  BitBlock error;
286};
287
288  struct Scope1 {
289  BitBlock RefStart;
290  BitBlock LAngle;
291  BitBlock Hyphen;
292  BitBlock QMark;
293  BitBlock RBracket;
294};
295
296  struct CtCDPI_Callouts {
297  BitBlock CD_end;
298  BitBlock Ct_starts;
299  BitBlock Ct_ends;
300  BitBlock CD_starts;
301  BitBlock CD_ends;
302  BitBlock PI_starts;
303  BitBlock PI_name_starts;
304  BitBlock PI_name_ends;
305  BitBlock PI_ends;
306  BitBlock CtCDPI_mask;
307  BitBlock error;
308};
309
310  struct Ref_Callouts {
311  BitBlock GenRef_starts;
312  BitBlock GenRef_ends;
313  BitBlock DecRef_starts;
314  BitBlock DecRef_ends;
315  BitBlock HexRef_starts;
316  BitBlock HexRef_ends;
317  BitBlock error;
318};
319
320  struct Tag_Callouts {
321  BitBlock ElemName_starts;
322  BitBlock ElemName_ends;
323  BitBlock AttName_starts;
324  BitBlock AttName_ends;
325  BitBlock AttVal_starts;
326  BitBlock AttVal_ends;
327  BitBlock AttVal_spans;
328  BitBlock EmptyTag_marks;
329  BitBlock EndTag_marks;
330  BitBlock LAngleFollow;
331  BitBlock error;
332};
333
334  struct Basis_bits {
335  BitBlock bit_0;
336  BitBlock bit_1;
337  BitBlock bit_2;
338  BitBlock bit_3;
339  BitBlock bit_4;
340  BitBlock bit_5;
341  BitBlock bit_6;
342  BitBlock bit_7;
343};
344
345  struct Masks {
346  BitBlock EOF_mask;
347};
348
349  struct Check_streams {
350  BitBlock misc_mask;
351  BitBlock non_ascii_name_starts;
352  BitBlock non_ascii_names;
353  BitBlock tag_marks;
354  BitBlock name_follows;
355  BitBlock att_refs;
356  BitBlock error_mask;
357};
358
359  struct Xml_names {
360  BitBlock namespace_error;
361};
362
363  struct Parse_refs {
364  Parse_refs() { CarryInit(carryQ, 6); }
365  void do_block(Lex & lex, Scope1 & scope1, CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts) {
366                BitBlock Ref1, NumRef2, NumRef3, HexRef3, ref_error1, ref_error2, ref_ends;
367                BitBlock ref_error3;
368
369
370        ref_Callouts.GenRef_starts = simd_const_1(0);
371        ref_Callouts.GenRef_ends = simd_const_1(0);
372        ref_Callouts.DecRef_starts = simd_const_1(0);
373        ref_Callouts.DecRef_ends = simd_const_1(0);
374        ref_Callouts.HexRef_starts = simd_const_1(0);
375        ref_Callouts.HexRef_ends = simd_const_1(0);
376        ref_Callouts.error = simd_const_1(0);
377        Ref1 = simd_andc(lex.RefStart, ctCDPI_Callouts.CtCDPI_mask);
378        if ((bitblock_has_bit(Ref1) || CarryTest(carryQ, 0, 6))) {
379          scope1.RefStart = BitBlock_advance_ci_co(Ref1, carryQ, 0);
380          NumRef2 = simd_and(scope1.RefStart, lex.Hash);
381          ref_Callouts.GenRef_starts = simd_andc(scope1.RefStart, lex.Hash);
382          NumRef3 = BitBlock_advance_ci_co(NumRef2, carryQ, 1);
383          HexRef3 = simd_and(NumRef3, lex.x);
384          ref_Callouts.DecRef_starts = simd_andc(NumRef3, lex.x);
385          ref_Callouts.HexRef_starts = BitBlock_advance_ci_co(HexRef3, carryQ, 2);
386          ref_Callouts.GenRef_ends = BitBlock_scanthru_ci_co(ref_Callouts.GenRef_starts, lex.NameScan, carryQ, 3);
387          ref_Callouts.DecRef_ends = BitBlock_scanthru_ci_co(ref_Callouts.DecRef_starts, lex.Digit, carryQ, 4);
388          ref_Callouts.HexRef_ends = BitBlock_scanthru_ci_co(ref_Callouts.HexRef_starts, lex.Hex, carryQ, 5);
389          ref_error1 = simd_andc(ref_Callouts.DecRef_starts, lex.Digit);
390          ref_error2 = simd_andc(ref_Callouts.HexRef_starts, lex.Hex);
391          ref_ends = simd_or(simd_or(ref_Callouts.GenRef_ends, ref_Callouts.DecRef_ends), ref_Callouts.HexRef_ends);
392          ref_error3 = simd_andc(ref_ends, lex.Semicolon);
393          ref_Callouts.error = simd_or(simd_or(ref_error1, ref_error2), ref_error3);
394        }
395        else {
396          CarryDequeueEnqueue(carryQ, 0, 6);
397        }
398        CarryQ_Adjust(carryQ, 6);
399  }
400  void do_segment(Lex lex[], Scope1 scope1[], CtCDPI_Callouts ctCDPI_Callouts[], Ref_Callouts ref_Callouts[]) {
401  for (int i = 0; i < SEGMENT_BLOCKS; i++)
402    do_block(lex[i], scope1[i], ctCDPI_Callouts[i], ref_Callouts[i]);
403  }
404  CarryDeclare(carryQ, 6);
405  };
406
407  struct Parse_tags {
408  Parse_tags() { CarryInit(carryQ, 13); }
409  void do_block(Lex & lex, Scope1 & scope1, CtCDPI_Callouts & ctCDPI_Callouts, Tag_Callouts & tag_Callouts, Masks & masks) {
410                BitBlock DQuoteScan, SQuoteScan, AttListDelim, ParseError, EqToCheck;
411                BitBlock AttValEnds, AfterWS, AttListEnd, AttNameStart, AttNameFollow;
412                BitBlock EqExpected, AttValPos, DQuoteAttVal, SQuoteAttVal, DQuoteAttEnd;
413                BitBlock SQuoteAttEnd, AttValEnd, AttValFollow, STagEnds, EndTagEnds;
414
415
416        DQuoteScan = simd_andc(masks.EOF_mask, simd_or(lex.DQuote, lex.LAngle));
417        SQuoteScan = simd_andc(masks.EOF_mask, simd_or(lex.SQuote, lex.LAngle));
418        AttListDelim = simd_or(lex.Slash, lex.RAngle);
419        tag_Callouts.LAngleFollow = simd_andc(scope1.LAngle, ctCDPI_Callouts.CtCDPI_mask);
420        tag_Callouts.ElemName_starts = simd_andc(tag_Callouts.LAngleFollow, lex.Slash);
421        tag_Callouts.EndTag_marks = simd_and(tag_Callouts.LAngleFollow, lex.Slash);
422        tag_Callouts.ElemName_ends = BitBlock_scanthru_ci_co(tag_Callouts.ElemName_starts, lex.NameScan, carryQ, 0);
423        ParseError = simd_and(tag_Callouts.ElemName_starts, tag_Callouts.ElemName_ends);
424        tag_Callouts.AttName_starts = simd_const_1(0);
425        tag_Callouts.AttName_ends = simd_const_1(0);
426        EqToCheck = simd_const_1(0);
427        tag_Callouts.AttVal_starts = simd_const_1(0);
428        AttValEnds = simd_const_1(0);
429        tag_Callouts.AttVal_ends = simd_const_1(0);
430        AfterWS = BitBlock_scanthru_ci_co(tag_Callouts.ElemName_ends, lex.WS, carryQ, 1);
431        AttListEnd = simd_and(AfterWS, AttListDelim);
432        AttNameStart = simd_andc(AfterWS, AttListDelim);
433        ParseError = simd_or(ParseError, simd_and(tag_Callouts.ElemName_ends, AttNameStart));
434        if ((bitblock_has_bit(AttNameStart) || CarryTest(carryQ, 2, 7))) {
435          tag_Callouts.AttName_starts = simd_or(tag_Callouts.AttName_starts, AttNameStart);
436          AttNameFollow = BitBlock_scanthru_ci_co(AttNameStart, lex.NameScan, carryQ, 2);
437          tag_Callouts.AttName_ends = simd_or(tag_Callouts.AttName_ends, AttNameFollow);
438          EqExpected = BitBlock_scanthru_ci_co(AttNameFollow, lex.WS, carryQ, 3);
439          EqToCheck = simd_or(EqToCheck, EqExpected);
440          AttValPos = BitBlock_scanthru_ci_co(EqExpected, simd_or(EqExpected, lex.WS), carryQ, 4);
441          tag_Callouts.AttVal_starts = simd_or(tag_Callouts.AttVal_starts, AttValPos);
442          DQuoteAttVal = simd_and(AttValPos, lex.DQuote);
443          SQuoteAttVal = simd_and(AttValPos, lex.SQuote);
444          DQuoteAttEnd = BitBlock_scanthru_ci_co(DQuoteAttVal, simd_or(DQuoteAttVal, DQuoteScan), carryQ, 5);
445          SQuoteAttEnd = BitBlock_scanthru_ci_co(SQuoteAttVal, simd_or(SQuoteAttVal, SQuoteScan), carryQ, 6);
446          AttValEnd = simd_or(DQuoteAttEnd, SQuoteAttEnd);
447          AttValEnds = simd_or(AttValEnds, AttValEnd);
448          AttValFollow = BitBlock_advance_ci_co(AttValEnd, carryQ, 7);
449          tag_Callouts.AttVal_ends = simd_or(tag_Callouts.AttVal_ends, AttValFollow);
450          AfterWS = BitBlock_scanthru_ci_co(AttValFollow, lex.WS, carryQ, 8);
451          AttListEnd = simd_or(AttListEnd, simd_and(AfterWS, AttListDelim));
452          AttNameStart = simd_andc(AfterWS, AttListDelim);
453          while (bitblock_has_bit(AttNameStart)) {
454            CarryDeclare(subcarryQ, 7);
455            CarryInit(subcarryQ, 7);
456            tag_Callouts.AttName_starts = simd_or(tag_Callouts.AttName_starts, AttNameStart);
457            AttNameFollow = BitBlock_scanthru_co(AttNameStart, lex.NameScan, subcarryQ, 0);
458            tag_Callouts.AttName_ends = simd_or(tag_Callouts.AttName_ends, AttNameFollow);
459            EqExpected = BitBlock_scanthru_co(AttNameFollow, lex.WS, subcarryQ, 1);
460            EqToCheck = simd_or(EqToCheck, EqExpected);
461            AttValPos = BitBlock_scanthru_co(EqExpected, simd_or(EqExpected, lex.WS), subcarryQ, 2);
462            tag_Callouts.AttVal_starts = simd_or(tag_Callouts.AttVal_starts, AttValPos);
463            DQuoteAttVal = simd_and(AttValPos, lex.DQuote);
464            SQuoteAttVal = simd_and(AttValPos, lex.SQuote);
465            DQuoteAttEnd = BitBlock_scanthru_co(DQuoteAttVal, simd_or(DQuoteAttVal, DQuoteScan), subcarryQ, 3);
466            SQuoteAttEnd = BitBlock_scanthru_co(SQuoteAttVal, simd_or(SQuoteAttVal, SQuoteScan), subcarryQ, 4);
467            AttValEnd = simd_or(DQuoteAttEnd, SQuoteAttEnd);
468            AttValEnds = simd_or(AttValEnds, AttValEnd);
469            AttValFollow = BitBlock_advance_co(AttValEnd, subcarryQ, 5);
470            tag_Callouts.AttVal_ends = simd_or(tag_Callouts.AttVal_ends, AttValFollow);
471            AfterWS = BitBlock_scanthru_co(AttValFollow, lex.WS, subcarryQ, 6);
472            AttListEnd = simd_or(AttListEnd, simd_and(AfterWS, AttListDelim));
473            AttNameStart = simd_andc(AfterWS, AttListDelim);
474            CarryCombine(carryQ, subcarryQ, 2, 7);
475          }
476        }
477        else {
478          CarryDequeueEnqueue(carryQ, 2, 7);
479        }
480        STagEnds = simd_and(AttListEnd, lex.RAngle);
481        tag_Callouts.EmptyTag_marks = BitBlock_advance_ci_co(simd_and(AttListEnd, lex.Slash), carryQ, 9);
482        ParseError = simd_or(ParseError, simd_and(tag_Callouts.AttVal_ends, tag_Callouts.AttName_starts));
483        ParseError = simd_or(ParseError, simd_and(tag_Callouts.AttName_starts, tag_Callouts.AttName_ends));
484        ParseError = simd_or(ParseError, simd_andc(EqToCheck, lex.Equals));
485        ParseError = simd_or(ParseError, simd_andc(tag_Callouts.AttVal_starts, simd_or(lex.DQuote, lex.SQuote)));
486        ParseError = simd_or(ParseError, simd_andc(AttValEnds, simd_or(lex.DQuote, lex.SQuote)));
487        ParseError = simd_or(ParseError, simd_andc(tag_Callouts.EmptyTag_marks, lex.RAngle));
488        EndTagEnds = BitBlock_scanthru_ci_co(BitBlock_scanthru_ci_co(tag_Callouts.EndTag_marks, simd_or(tag_Callouts.EndTag_marks, lex.NameScan), carryQ, 10), lex.WS, carryQ, 11);
489        ParseError = simd_or(ParseError, simd_andc(EndTagEnds, lex.RAngle));
490        tag_Callouts.error = ParseError;
491        tag_Callouts.AttVal_spans = BitBlock_sub_ci_co(tag_Callouts.AttVal_ends, tag_Callouts.AttVal_starts, carryQ, 12);
492        CarryQ_Adjust(carryQ, 13);
493  }
494  void do_segment(Lex lex[], Scope1 scope1[], CtCDPI_Callouts ctCDPI_Callouts[], Tag_Callouts tag_Callouts[], Masks masks[]) {
495  for (int i = 0; i < SEGMENT_BLOCKS; i++)
496    do_block(lex[i], scope1[i], ctCDPI_Callouts[i], tag_Callouts[i], masks[i]);
497  }
498  CarryDeclare(carryQ, 13);
499  };
500
501  struct Classify_bytes_Validate_utf8 {
502  Classify_bytes_Validate_utf8() { CarryInit(carryQ, 12); }
503  void do_block(Basis_bits & basis_bits, Lex & lex, U8 & u8) {
504                BitBlock temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
505                BitBlock temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
506                BitBlock temp19, temp20, temp21, temp22, temp23, temp24, temp25, temp26;
507                BitBlock temp27, temp28, temp29, temp30, temp31, temp32, temp33, temp34;
508                BitBlock temp35, temp36, temp37, temp38, temp39, temp40, temp41, temp42;
509                BitBlock temp43, temp44, temp45, temp46, temp47, temp48, x00_x1F, temp49;
510                BitBlock temp50, temp51, temp52, temp53, temp54, temp55, temp56, temp57;
511                BitBlock temp58, temp59, temp60, temp61, temp62, temp63, temp64, temp65;
512                BitBlock u8anyscope, temp66, temp67, temp68, temp69, temp70, temp71, xE0, xED;
513                BitBlock xF0, temp72, xF4, xEF, temp73, u8lastscope, u8error1, u8error2;
514                BitBlock u8error3, u8error4, EF_BF_pending, u8mismatch;
515
516
517        temp1 = simd_or(basis_bits.bit_0, basis_bits.bit_1);
518        temp2 = simd_andc(basis_bits.bit_2, basis_bits.bit_3);
519        temp3 = simd_andc(temp2, temp1);
520        temp4 = simd_andc(basis_bits.bit_5, basis_bits.bit_4);
521        temp5 = simd_andc(basis_bits.bit_6, basis_bits.bit_7);
522        temp6 = simd_and(temp4, temp5);
523        lex.RefStart = simd_and(temp3, temp6);
524        temp7 = simd_and(basis_bits.bit_2, basis_bits.bit_3);
525        temp8 = simd_andc(temp7, temp1);
526        temp9 = simd_andc(basis_bits.bit_4, basis_bits.bit_5);
527        temp10 = simd_and(basis_bits.bit_6, basis_bits.bit_7);
528        temp11 = simd_and(temp9, temp10);
529        lex.Semicolon = simd_and(temp8, temp11);
530        temp12 = simd_and(basis_bits.bit_4, basis_bits.bit_5);
531        temp13 = simd_or(basis_bits.bit_6, basis_bits.bit_7);
532        temp14 = simd_andc(temp12, temp13);
533        lex.LAngle = simd_and(temp8, temp14);
534        temp15 = simd_and(temp12, temp5);
535        lex.RAngle = simd_and(temp8, temp15);
536        temp16 = simd_andc(basis_bits.bit_1, basis_bits.bit_0);
537        temp17 = simd_andc(basis_bits.bit_3, basis_bits.bit_2);
538        temp18 = simd_and(temp16, temp17);
539        lex.LBracket = simd_and(temp18, temp11);
540        temp19 = simd_andc(basis_bits.bit_7, basis_bits.bit_6);
541        temp20 = simd_and(temp12, temp19);
542        lex.RBracket = simd_and(temp18, temp20);
543        temp21 = simd_or(basis_bits.bit_4, basis_bits.bit_5);
544        temp22 = simd_andc(temp19, temp21);
545        lex.Exclam = simd_and(temp3, temp22);
546        temp23 = simd_and(temp12, temp10);
547        lex.QMark = simd_and(temp8, temp23);
548        lex.Hyphen = simd_and(temp3, temp20);
549        lex.Equals = simd_and(temp8, temp20);
550        temp24 = simd_and(temp4, temp10);
551        lex.SQuote = simd_and(temp3, temp24);
552        temp25 = simd_andc(temp5, temp21);
553        lex.DQuote = simd_and(temp3, temp25);
554        lex.Slash = simd_and(temp3, temp23);
555        temp26 = simd_andc(temp10, temp21);
556        lex.Hash = simd_and(temp3, temp26);
557        temp27 = simd_and(temp16, temp7);
558        temp28 = simd_andc(temp9, temp13);
559        lex.x = simd_and(temp27, temp28);
560        temp29 = simd_and(temp9, temp5);
561        lex.Colon = simd_and(temp8, temp29);
562        temp30 = simd_and(temp18, temp23);
563        temp31 = simd_or(temp30, lex.Colon);
564        temp32 = simd_andc(temp16, basis_bits.bit_2);
565        temp33 = simd_or(basis_bits.bit_5, temp10);
566        temp34 = simd_and(basis_bits.bit_4, temp33);
567        temp35 = simd_not(temp34);
568        temp36 = simd_or(temp21, temp13);
569        temp37 = simd_or(simd_and(basis_bits.bit_3, temp35), simd_andc(temp36, basis_bits.bit_3));
570        temp38 = simd_and(temp32, temp37);
571        temp39 = simd_or(temp31, temp38);
572        temp40 = simd_and(temp16, basis_bits.bit_2);
573        temp41 = simd_and(temp40, temp37);
574        lex.ASCII_name_start = simd_or(temp39, temp41);
575        temp42 = simd_or(temp30, lex.Hyphen);
576        temp43 = simd_and(temp3, temp15);
577        temp44 = simd_or(temp42, temp43);
578        temp45 = simd_andc(temp8, temp34);
579        temp46 = simd_or(temp44, temp45);
580        temp47 = simd_or(temp46, temp38);
581        lex.ASCII_name_char = simd_or(temp47, temp41);
582        lex.NameScan = simd_or(lex.ASCII_name_char, basis_bits.bit_0);
583        temp48 = simd_or(temp1, basis_bits.bit_2);
584        x00_x1F = simd_not(temp48);
585        temp49 = simd_or(basis_bits.bit_2, basis_bits.bit_3);
586        temp50 = simd_or(temp1, temp49);
587        lex.CR = simd_andc(temp20, temp50);
588        lex.LF = simd_andc(temp29, temp50);
589        temp51 = simd_and(temp9, temp19);
590        lex.HT = simd_andc(temp51, temp50);
591        lex.SP = simd_andc(temp3, temp36);
592        temp52 = simd_or(temp20, temp29);
593        temp53 = simd_or(temp52, temp51);
594        temp54 = simd_andc(temp53, temp50);
595        lex.WS = simd_or(temp54, lex.SP);
596        temp55 = simd_or(basis_bits.bit_5, basis_bits.bit_6);
597        temp56 = simd_and(basis_bits.bit_4, temp55);
598        lex.Digit = simd_andc(temp8, temp56);
599        temp57 = simd_andc(temp16, temp49);
600        temp58 = simd_andc(temp57, basis_bits.bit_4);
601        temp59 = simd_not(temp10);
602        temp60 = simd_or(simd_and(basis_bits.bit_5, temp59), simd_andc(temp13, basis_bits.bit_5));
603        temp61 = simd_and(temp58, temp60);
604        temp62 = simd_or(lex.Digit, temp61);
605        temp63 = simd_and(temp16, temp2);
606        temp64 = simd_andc(temp63, basis_bits.bit_4);
607        temp65 = simd_and(temp64, temp60);
608        lex.Hex = simd_or(temp62, temp65);
609        lex.error = simd_andc(x00_x1F, lex.WS);
610        u8.unibyte = simd_not(basis_bits.bit_0);
611        u8.suffix = simd_const_1(0);
612        u8.error = simd_const_1(0);
613        u8.FFFE_FFFF = simd_const_1(0);
614        u8anyscope = simd_const_1(0);
615        if ((bitblock_has_bit(basis_bits.bit_0) || CarryTest(carryQ, 0, 12))) {
616          u8.prefix = simd_and(basis_bits.bit_0, basis_bits.bit_1);
617          u8.prefix2 = simd_andc(u8.prefix, basis_bits.bit_2);
618          u8.prefix3 = simd_and(u8.prefix, temp2);
619          u8.prefix4 = simd_and(u8.prefix, temp7);
620          u8.suffix = simd_andc(basis_bits.bit_0, basis_bits.bit_1);
621          temp66 = simd_andc(u8.prefix, temp49);
622          temp67 = simd_or(temp21, basis_bits.bit_6);
623          temp68 = simd_andc(temp66, temp67);
624          temp69 = simd_and(basis_bits.bit_5, temp13);
625          temp70 = simd_or(basis_bits.bit_4, temp69);
626          temp71 = simd_and(u8.prefix4, temp70);
627          u8.badprefix = simd_or(temp68, temp71);
628          u8.error = u8.badprefix;
629          u8.scope22 = BitBlock_advance_ci_co(u8.prefix2, carryQ, 0);
630          u8anyscope = u8.scope22;
631          if ((bitblock_has_bit(simd_or(u8.prefix3, u8.prefix4)) || CarryTest(carryQ, 1, 11))) {
632            xE0 = simd_andc(u8.prefix3, temp36);
633            xED = simd_and(u8.prefix3, temp20);
634            xF0 = simd_andc(u8.prefix4, temp36);
635            temp72 = simd_andc(temp4, temp13);
636            xF4 = simd_and(u8.prefix4, temp72);
637            u8.xA0_xBF = simd_and(u8.suffix, basis_bits.bit_2);
638            u8.x80_x9F = simd_andc(u8.suffix, basis_bits.bit_2);
639            u8.x90_xBF = simd_and(u8.suffix, temp49);
640            u8.x80_x8F = simd_andc(u8.suffix, temp49);
641            xEF = simd_and(u8.prefix3, temp23);
642            temp73 = simd_and(u8.suffix, temp7);
643            u8.xBF = simd_and(temp73, temp23);
644            u8.xBE = simd_and(temp73, temp15);
645            u8.xE0_scope = BitBlock_advance_ci_co(xE0, carryQ, 1);
646            u8.xED_scope = BitBlock_advance_ci_co(xED, carryQ, 2);
647            u8.xF0_scope = BitBlock_advance_ci_co(xF0, carryQ, 3);
648            u8.xF4_scope = BitBlock_advance_ci_co(xF4, carryQ, 4);
649            u8.xEF_scope = BitBlock_advance_ci_co(xEF, carryQ, 5);
650            u8.scope32 = BitBlock_advance_ci_co(u8.prefix3, carryQ, 6);
651            u8.scope33 = BitBlock_advance_ci_co(u8.scope32, carryQ, 7);
652            u8.scope42 = BitBlock_advance_ci_co(u8.prefix4, carryQ, 8);
653            u8.scope43 = BitBlock_advance_ci_co(u8.scope42, carryQ, 9);
654            u8.scope44 = BitBlock_advance_ci_co(u8.scope43, carryQ, 10);
655            u8lastscope = simd_or(simd_or(u8.scope22, u8.scope33), u8.scope44);
656            u8anyscope = simd_or(simd_or(simd_or(u8lastscope, u8.scope32), u8.scope42), u8.scope43);
657            u8error1 = simd_and(u8.xE0_scope, u8.x80_x9F);
658            u8error2 = simd_and(u8.xED_scope, u8.xA0_xBF);
659            u8error3 = simd_and(u8.xF0_scope, u8.x80_x8F);
660            u8error4 = simd_and(u8.xF4_scope, u8.x90_xBF);
661            u8.error = simd_or(u8.error, simd_or(simd_or(simd_or(u8error1, u8error2), u8error3), u8error4));
662            EF_BF_pending = BitBlock_advance_ci_co(simd_and(u8.xEF_scope, u8.xBF), carryQ, 11);
663            u8.FFFE_FFFF = simd_and(EF_BF_pending, simd_or(u8.xBE, u8.xBF));
664          }
665          else {
666            CarryDequeueEnqueue(carryQ, 1, 11);
667          }
668        }
669        else {
670          CarryDequeueEnqueue(carryQ, 0, 12);
671        }
672        u8mismatch = simd_xor(u8anyscope, u8.suffix);
673        u8.error = simd_or(u8.error, u8mismatch);
674        CarryQ_Adjust(carryQ, 12);
675  }
676  void do_segment(Basis_bits basis_bits[], Lex lex[], U8 u8[]) {
677  for (int i = 0; i < SEGMENT_BLOCKS; i++)
678    do_block(basis_bits[i], lex[i], u8[i]);
679  }
680  CarryDeclare(carryQ, 12);
681  };
682
683  struct Parse_CtCDPI {
684  Parse_CtCDPI() { CarryInit(carryQ, 18); }
685  void do_block(CtCDPI_Callouts & ctCDPI_Callouts, Lex & lex, Scope1 & scope1, Masks & masks, Check_streams & check_streams) {
686                BitBlock CtCDPI_starts, PI_start, CtCD_start, CtCDPI_start, DoubleHyphen;
687                BitBlock PI_end, CtCDPI_scan, Ct_end_scan, CD_end_scan, PI_end_scan;
688                BitBlock CtCDPI_Cursor, PI_Cursor, CD_Ct_Cursor, CD_Cursor, Ct_Cursor;
689                BitBlock Ct_errors, PI_name_end;
690
691  CtCDPI_Cursor = sisd_from_int(1);
692
693        ctCDPI_Callouts.CD_end = simd_const_1(0);
694        ctCDPI_Callouts.Ct_starts = simd_const_1(0);
695        ctCDPI_Callouts.Ct_ends = simd_const_1(0);
696        ctCDPI_Callouts.CD_starts = simd_const_1(0);
697        ctCDPI_Callouts.CD_ends = simd_const_1(0);
698        ctCDPI_Callouts.PI_starts = simd_const_1(0);
699        ctCDPI_Callouts.PI_name_starts = simd_const_1(0);
700        ctCDPI_Callouts.PI_name_ends = simd_const_1(0);
701        ctCDPI_Callouts.PI_ends = simd_const_1(0);
702        ctCDPI_Callouts.CtCDPI_mask = simd_const_1(0);
703        ctCDPI_Callouts.error = simd_const_1(0);
704        CtCDPI_starts = simd_const_1(0);
705        if ((bitblock_has_bit(lex.RBracket) || CarryTest(carryQ, 0, 2))) {
706          scope1.RBracket = BitBlock_advance_ci_co(lex.RBracket, carryQ, 0);
707          ctCDPI_Callouts.CD_end = simd_and(BitBlock_advance_ci_co(simd_and(scope1.RBracket, lex.RBracket), carryQ, 1), lex.RAngle);
708        }
709        else {
710          CarryDequeueEnqueue(carryQ, 0, 2);
711        }
712        PI_start = simd_and(scope1.LAngle, lex.QMark);
713        CtCD_start = simd_and(scope1.LAngle, lex.Exclam);
714        CtCDPI_start = simd_or(PI_start, CtCD_start);
715        DoubleHyphen = simd_and(scope1.Hyphen, lex.Hyphen);
716        PI_end = simd_and(scope1.QMark, lex.RAngle);
717        CtCDPI_scan = simd_andc(masks.EOF_mask, CtCDPI_start);
718        Ct_end_scan = simd_andc(masks.EOF_mask, DoubleHyphen);
719        CD_end_scan = simd_andc(masks.EOF_mask, ctCDPI_Callouts.CD_end);
720        PI_end_scan = simd_andc(masks.EOF_mask, PI_end);
721        CtCDPI_Cursor = BitBlock_scanthru_ci_co(CtCDPI_Cursor, CtCDPI_scan, carryQ, 2);
722        CtCDPI_Cursor = simd_and(CtCDPI_Cursor, masks.EOF_mask);
723        if ((bitblock_has_bit(CtCDPI_Cursor) || CarryTest(carryQ, 3, 13))) {
724          CtCDPI_starts = simd_or(CtCDPI_starts, CtCDPI_Cursor);
725          PI_Cursor = simd_and(CtCDPI_Cursor, PI_start);
726          CD_Ct_Cursor = BitBlock_advance_ci_co(simd_andc(CtCDPI_Cursor, PI_Cursor), carryQ, 3);
727          CD_Cursor = simd_and(CD_Ct_Cursor, lex.LBracket);
728          Ct_Cursor = simd_and(CD_Ct_Cursor, lex.Hyphen);
729          ctCDPI_Callouts.PI_starts = simd_or(ctCDPI_Callouts.PI_starts, PI_Cursor);
730          ctCDPI_Callouts.CD_starts = simd_or(ctCDPI_Callouts.CD_starts, CD_Cursor);
731          ctCDPI_Callouts.Ct_starts = simd_or(ctCDPI_Callouts.Ct_starts, Ct_Cursor);
732          Ct_Cursor = BitBlock_advance_ci_co(Ct_Cursor, carryQ, 4);
733          Ct_errors = simd_or(Ct_errors, simd_andc(Ct_Cursor, lex.Hyphen));
734          Ct_Cursor = BitBlock_advance_ci_co(Ct_Cursor, carryQ, 5);
735          Ct_end_scan = simd_or(Ct_end_scan, Ct_Cursor);
736          PI_Cursor = BitBlock_advance_ci_co(PI_Cursor, carryQ, 6);
737          ctCDPI_Callouts.PI_name_starts = simd_or(ctCDPI_Callouts.PI_name_starts, PI_Cursor);
738          PI_name_end = BitBlock_scanthru_ci_co(PI_Cursor, lex.NameScan, carryQ, 7);
739          ctCDPI_Callouts.PI_name_ends = simd_or(ctCDPI_Callouts.PI_name_ends, PI_name_end);
740          PI_Cursor = BitBlock_scanthru_ci_co(PI_name_end, PI_end_scan, carryQ, 8);
741          CD_Cursor = BitBlock_scanthru_ci_co(CD_Cursor, CD_end_scan, carryQ, 9);
742          Ct_Cursor = BitBlock_advance_ci_co(BitBlock_scanthru_ci_co(Ct_Cursor, Ct_end_scan, carryQ, 10), carryQ, 11);
743          ctCDPI_Callouts.PI_ends = simd_or(ctCDPI_Callouts.PI_ends, PI_Cursor);
744          ctCDPI_Callouts.CD_ends = simd_or(ctCDPI_Callouts.CD_ends, CD_Cursor);
745          ctCDPI_Callouts.Ct_ends = simd_or(ctCDPI_Callouts.Ct_ends, Ct_Cursor);
746          CtCDPI_Cursor = simd_or(simd_or(PI_Cursor, CD_Cursor), Ct_Cursor);
747          CtCDPI_Cursor = BitBlock_scanthru_ci_co(CtCDPI_Cursor, CtCDPI_scan, carryQ, 12);
748          CtCDPI_Cursor = simd_and(CtCDPI_Cursor, masks.EOF_mask);
749          ctCDPI_Callouts.CtCDPI_mask = BitBlock_sub_ci_co(BitBlock_advance_ci_co(simd_or(simd_or(ctCDPI_Callouts.CD_ends, ctCDPI_Callouts.Ct_ends), ctCDPI_Callouts.PI_ends), carryQ, 13), CtCDPI_starts, carryQ, 14);
750          ctCDPI_Callouts.error = simd_or(Ct_errors, simd_andc(ctCDPI_Callouts.Ct_ends, lex.RAngle));
751          ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(BitBlock_advance_ci_co(simd_andc(ctCDPI_Callouts.PI_name_ends, lex.WS), carryQ, 15), PI_end));
752          ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_and(ctCDPI_Callouts.PI_name_starts, ctCDPI_Callouts.PI_name_ends));
753          ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(ctCDPI_Callouts.CtCDPI_mask, masks.EOF_mask));
754          while (bitblock_has_bit(CtCDPI_Cursor)) {
755            CarryDeclare(subcarryQ, 13);
756            CarryInit(subcarryQ, 13);
757            CtCDPI_starts = simd_or(CtCDPI_starts, CtCDPI_Cursor);
758            PI_Cursor = simd_and(CtCDPI_Cursor, PI_start);
759            CD_Ct_Cursor = BitBlock_advance_co(simd_andc(CtCDPI_Cursor, PI_Cursor), subcarryQ, 0);
760            CD_Cursor = simd_and(CD_Ct_Cursor, lex.LBracket);
761            Ct_Cursor = simd_and(CD_Ct_Cursor, lex.Hyphen);
762            ctCDPI_Callouts.PI_starts = simd_or(ctCDPI_Callouts.PI_starts, PI_Cursor);
763            ctCDPI_Callouts.CD_starts = simd_or(ctCDPI_Callouts.CD_starts, CD_Cursor);
764            ctCDPI_Callouts.Ct_starts = simd_or(ctCDPI_Callouts.Ct_starts, Ct_Cursor);
765            Ct_Cursor = BitBlock_advance_co(Ct_Cursor, subcarryQ, 1);
766            Ct_errors = simd_or(Ct_errors, simd_andc(Ct_Cursor, lex.Hyphen));
767            Ct_Cursor = BitBlock_advance_co(Ct_Cursor, subcarryQ, 2);
768            Ct_end_scan = simd_or(Ct_end_scan, Ct_Cursor);
769            PI_Cursor = BitBlock_advance_co(PI_Cursor, subcarryQ, 3);
770            ctCDPI_Callouts.PI_name_starts = simd_or(ctCDPI_Callouts.PI_name_starts, PI_Cursor);
771            PI_name_end = BitBlock_scanthru_co(PI_Cursor, lex.NameScan, subcarryQ, 4);
772            ctCDPI_Callouts.PI_name_ends = simd_or(ctCDPI_Callouts.PI_name_ends, PI_name_end);
773            PI_Cursor = BitBlock_scanthru_co(PI_name_end, PI_end_scan, subcarryQ, 5);
774            CD_Cursor = BitBlock_scanthru_co(CD_Cursor, CD_end_scan, subcarryQ, 6);
775            Ct_Cursor = BitBlock_advance_co(BitBlock_scanthru_co(Ct_Cursor, Ct_end_scan, subcarryQ, 7), subcarryQ, 8);
776            ctCDPI_Callouts.PI_ends = simd_or(ctCDPI_Callouts.PI_ends, PI_Cursor);
777            ctCDPI_Callouts.CD_ends = simd_or(ctCDPI_Callouts.CD_ends, CD_Cursor);
778            ctCDPI_Callouts.Ct_ends = simd_or(ctCDPI_Callouts.Ct_ends, Ct_Cursor);
779            CtCDPI_Cursor = simd_or(simd_or(PI_Cursor, CD_Cursor), Ct_Cursor);
780            CtCDPI_Cursor = BitBlock_scanthru_co(CtCDPI_Cursor, CtCDPI_scan, subcarryQ, 9);
781            CtCDPI_Cursor = simd_and(CtCDPI_Cursor, masks.EOF_mask);
782            ctCDPI_Callouts.CtCDPI_mask = BitBlock_sub_co(BitBlock_advance_co(simd_or(simd_or(ctCDPI_Callouts.CD_ends, ctCDPI_Callouts.Ct_ends), ctCDPI_Callouts.PI_ends), subcarryQ, 10), CtCDPI_starts, subcarryQ, 11);
783            ctCDPI_Callouts.error = simd_or(Ct_errors, simd_andc(ctCDPI_Callouts.Ct_ends, lex.RAngle));
784            ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(BitBlock_advance_co(simd_andc(ctCDPI_Callouts.PI_name_ends, lex.WS), subcarryQ, 12), PI_end));
785            ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_and(ctCDPI_Callouts.PI_name_starts, ctCDPI_Callouts.PI_name_ends));
786            ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(ctCDPI_Callouts.CtCDPI_mask, masks.EOF_mask));
787            CarryCombine(carryQ, subcarryQ, 3, 13);
788          }
789        }
790        else {
791          CarryDequeueEnqueue(carryQ, 3, 13);
792        }
793        check_streams.misc_mask = simd_and(simd_or(simd_or(simd_or(lex.WS, lex.LAngle), BitBlock_sub_ci_co(BitBlock_advance_ci_co(simd_or(ctCDPI_Callouts.Ct_ends, ctCDPI_Callouts.PI_ends), carryQ, 16), simd_or(ctCDPI_Callouts.Ct_starts, ctCDPI_Callouts.PI_starts), carryQ, 17)), CtCDPI_starts), masks.EOF_mask);
794        CarryQ_Adjust(carryQ, 18);
795  }
796  void do_segment(CtCDPI_Callouts ctCDPI_Callouts[], Lex lex[], Scope1 scope1[], Masks masks[], Check_streams check_streams[]) {
797  for (int i = 0; i < SEGMENT_BLOCKS; i++)
798    do_block(ctCDPI_Callouts[i], lex[i], scope1[i], masks[i], check_streams[i]);
799  }
800  CarryDeclare(carryQ, 18);
801  };
802
803  struct Do_check_streams {
804
805  void do_block(CtCDPI_Callouts & ctCDPI_Callouts, Tag_Callouts & tag_Callouts, Lex & lex, U8 & u8, Scope1 & scope1, Ref_Callouts & ref_Callouts, Xml_names & xml_names, Check_streams & check_streams, Masks & masks) {
806                BitBlock CD_end_error;
807
808
809        CD_end_error = simd_andc(ctCDPI_Callouts.CD_end, simd_or(ctCDPI_Callouts.CtCDPI_mask, tag_Callouts.AttVal_spans));
810        check_streams.error_mask = simd_or(simd_or(simd_or(simd_or(simd_or(simd_or(simd_or(simd_and(lex.error, masks.EOF_mask), u8.error), u8.FFFE_FFFF), ctCDPI_Callouts.error), tag_Callouts.error), CD_end_error), ref_Callouts.error), xml_names.namespace_error);
811        check_streams.tag_marks = simd_or(simd_or(tag_Callouts.EmptyTag_marks, tag_Callouts.LAngleFollow), tag_Callouts.AttName_starts);
812        check_streams.name_follows = simd_or(tag_Callouts.ElemName_ends, tag_Callouts.AttName_ends);
813        check_streams.att_refs = simd_and(tag_Callouts.AttVal_spans, scope1.RefStart);
814  }
815  void do_segment(CtCDPI_Callouts ctCDPI_Callouts[], Tag_Callouts tag_Callouts[], Lex lex[], U8 u8[], Scope1 scope1[], Ref_Callouts ref_Callouts[], Xml_names xml_names[], Check_streams check_streams[], Masks masks[]) {
816  for (int i = 0; i < SEGMENT_BLOCKS; i++)
817    do_block(ctCDPI_Callouts[i], tag_Callouts[i], lex[i], u8[i], scope1[i], ref_Callouts[i], xml_names[i], check_streams[i], masks[i]);
818  }
819
820  };
821
822  struct Validate_xml_names {
823  Validate_xml_names() { CarryInit(carryQ, 9); }
824  void do_block(CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts, Tag_Callouts & tag_Callouts, Lex & lex, U8 & u8, Xml_names & xml_names, Check_streams & check_streams) {
825                BitBlock PI_names, GenRefs, ElemNames, AttNames, qname_stream, ncname_stream;
826                BitBlock name_stream, name_start, name_cursor, void_prefix_err, namespace_sep;
827                BitBlock local_part_start, local_part_err, colon2_err, ncname_err;
828
829
830        PI_names = BitBlock_sub_ci_co(ctCDPI_Callouts.PI_name_ends, ctCDPI_Callouts.PI_name_starts, carryQ, 0);
831        GenRefs = BitBlock_sub_ci_co(ref_Callouts.GenRef_ends, ref_Callouts.GenRef_starts, carryQ, 1);
832        ElemNames = BitBlock_sub_ci_co(tag_Callouts.ElemName_ends, tag_Callouts.ElemName_starts, carryQ, 2);
833        AttNames = BitBlock_sub_ci_co(tag_Callouts.AttName_ends, tag_Callouts.AttName_starts, carryQ, 3);
834        qname_stream = simd_or(ElemNames, AttNames);
835        ncname_stream = simd_or(PI_names, GenRefs);
836        name_stream = simd_or(qname_stream, ncname_stream);
837        name_start = simd_andc(name_stream, BitBlock_advance_ci_co(name_stream, carryQ, 4));
838        name_cursor = simd_andc(name_stream, BitBlock_advance_ci_co(name_stream, carryQ, 5));
839        void_prefix_err = simd_and(name_cursor, lex.Colon);
840        namespace_sep = simd_and(BitBlock_scanthru_ci_co(name_cursor, simd_andc(lex.NameScan, lex.Colon), carryQ, 6), lex.Colon);
841        local_part_start = BitBlock_advance_ci_co(namespace_sep, carryQ, 7);
842        local_part_err = simd_andc(local_part_start, lex.NameScan);
843        colon2_err = simd_and(BitBlock_scanthru_ci_co(local_part_start, simd_andc(lex.NameScan, lex.Colon), carryQ, 8), lex.Colon);
844        ncname_err = simd_and(ncname_stream, lex.Colon);
845        xml_names.namespace_error = simd_or(simd_or(simd_or(void_prefix_err, local_part_err), colon2_err), ncname_err);
846        check_streams.non_ascii_name_starts = simd_andc(name_start, lex.ASCII_name_start);
847        check_streams.non_ascii_names = simd_andc(simd_andc(simd_andc(name_stream, name_start), lex.ASCII_name_char), u8.suffix);
848        CarryQ_Adjust(carryQ, 9);
849  }
850  void do_segment(CtCDPI_Callouts ctCDPI_Callouts[], Ref_Callouts ref_Callouts[], Tag_Callouts tag_Callouts[], Lex lex[], U8 u8[], Xml_names xml_names[], Check_streams check_streams[]) {
851  for (int i = 0; i < SEGMENT_BLOCKS; i++)
852    do_block(ctCDPI_Callouts[i], ref_Callouts[i], tag_Callouts[i], lex[i], u8[i], xml_names[i], check_streams[i]);
853  }
854  CarryDeclare(carryQ, 9);
855  };
856
857  struct Add_scope_streams {
858  Add_scope_streams() { CarryInit(carryQ, 2); }
859  void do_block(Lex & lex, Scope1 & scope1) {
860                BitBlock v, w, v1, w1;
861
862
863        v = simd_or(lex.LAngle, lex.Hyphen);
864        w = simd_or(lex.Hyphen, lex.QMark);
865        v1 = BitBlock_advance_ci_co(v, carryQ, 0);
866        w1 = BitBlock_advance_ci_co(w, carryQ, 1);
867        scope1.LAngle = simd_andc(v1, w1);
868        scope1.Hyphen = simd_and(v1, w1);
869        scope1.QMark = simd_andc(w1, v1);
870        CarryQ_Adjust(carryQ, 2);
871  }
872  void do_segment(Lex lex[], Scope1 scope1[]) {
873  for (int i = 0; i < SEGMENT_BLOCKS; i++)
874    do_block(lex[i], scope1[i]);
875  }
876  CarryDeclare(carryQ, 2);
877  };
878
879
880
881static inline void s2p_do_block(BytePack U8[], Basis_bits & basis_bits) {
882  s2p(U8[0], U8[1], U8[2], U8[3], U8[4], U8[5], U8[6], U8[7],
883        basis_bits.bit_0, basis_bits.bit_1, basis_bits.bit_2, basis_bits.bit_3, basis_bits.bit_4, basis_bits.bit_5, basis_bits.bit_6, basis_bits.bit_7);
884}
885
886static inline void s2p_do_segment(BytePack U8[], Basis_bits basis_bits[]) {
887  for (int i = 0; i < SEGMENT_BLOCKS; i++)
888           s2p_do_block(&U8[8*i], basis_bits[i]);
889}
890
891static inline void postprocess_do_block(Lex & lex, CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts, Check_streams & check_streams, int chars_avail){
892            tracker.StoreNewlines(lex.LF);
893
894                if (bitblock_has_bit(simd_or(check_streams.non_ascii_name_starts, check_streams.non_ascii_names))) {
895                  StreamScan((ScanBlock *) &check_streams.non_ascii_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), NameStrt_check);
896                  StreamScan((ScanBlock *) &check_streams.non_ascii_names, sizeof(BitBlock)/sizeof(ScanBlock), Name_check);
897                }
898
899                if (bitblock_has_bit(ctCDPI_Callouts.PI_name_starts)){
900                  StreamScan((ScanBlock *) &ctCDPI_Callouts.PI_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), PIName_check);
901                }
902
903                if (bitblock_has_bit(ctCDPI_Callouts.CD_starts)){
904                  StreamScan((ScanBlock *) &ctCDPI_Callouts.CD_starts, sizeof(BitBlock)/sizeof(ScanBlock), CD_check);
905                }
906
907                if (bitblock_has_bit(ref_Callouts.GenRef_starts)){
908                  StreamScan((ScanBlock *) &ref_Callouts.GenRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), GenRef_check);
909                }
910
911                if (bitblock_has_bit(ref_Callouts.DecRef_starts)){
912                  StreamScan((ScanBlock *) &ref_Callouts.DecRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), DecRef_check);
913                }
914
915                if (bitblock_has_bit(ref_Callouts.HexRef_starts)){
916                  StreamScan((ScanBlock *) &ref_Callouts.HexRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), HexRef_check);
917                }
918
919                if (bitblock_has_bit(check_streams.att_refs)){
920                  StreamScan((ScanBlock *) &check_streams.att_refs, sizeof(BitBlock)/sizeof(ScanBlock), AttRef_check);
921                }
922
923                if (bitblock_has_bit(check_streams.error_mask)) {
924                  int errpos = count_forward_zeroes(check_streams.error_mask);
925                  ReportError("error found", errpos);
926              exit(-1);
927                }
928
929                matcher.store_streams(check_streams.tag_marks, check_streams.name_follows, check_streams.misc_mask, chars_avail);
930                tracker.AdvanceBlock();
931}
932
933static inline void postprocess_do_segment(Lex lex[], CtCDPI_Callouts ctCDPI_Callouts[], Ref_Callouts ref_Callouts[], Check_streams check_streams[], int chars_avail){
934
935  for (int i = 0; i < SEGMENT_BLOCKS; i++){
936           postprocess_do_block(lex[i], ctCDPI_Callouts[i], ref_Callouts[i], check_streams[i], chars_avail);
937           block_base += BLOCK_SIZE;
938  }
939
940        matcher.StreamScan(chars_avail);
941        matcher.Advance_buffer();
942        tracker.Advance_buffer();
943}
944
945void do_process(FILE *infile, FILE *outfile) {
946
947  struct U8 u8[SEGMENT_BLOCKS];
948
949  struct Lex lex[SEGMENT_BLOCKS];
950
951  struct Scope1 scope1[SEGMENT_BLOCKS];
952
953  struct CtCDPI_Callouts ctCDPI_Callouts[SEGMENT_BLOCKS];
954
955  struct Ref_Callouts ref_Callouts[SEGMENT_BLOCKS];
956
957  struct Tag_Callouts tag_Callouts[SEGMENT_BLOCKS];
958
959  struct Basis_bits basis_bits[SEGMENT_BLOCKS];
960
961  struct Masks masks[SEGMENT_BLOCKS];
962
963  struct Check_streams check_streams[SEGMENT_BLOCKS];
964
965  struct Xml_names xml_names[SEGMENT_BLOCKS];
966
967
968  for(int i=0;i<SEGMENT_BLOCKS;i++)
969          masks[i].EOF_mask = simd_const_1(1);
970  BitBlock EOF_mask = simd_const_1(1);
971
972  int buf_pos = 0;
973  int block_pos = 0;
974  int errpos = 0;
975  int chars_avail = 0;
976  int check_pos = 0;
977  int chars_read = 0;
978  BytePack buf[(BUFFER_SIZE+BLOCK_SIZE+OVERLAP_BUFSIZE*2)/sizeof(SIMD_type)];
979
980  char * srcbuf = ((char *) buf) + OVERLAP_BUFSIZE;
981  buffer_base = buf_pos;
982  source = srcbuf;
983
984  chars_read = fread((void *)srcbuf, 1, BUFFER_SIZE + OVERLAP_BUFSIZE, infile);
985  chars_avail = min(chars_read,BUFFER_SIZE);
986
987  matcher.setSrc(srcbuf);
988
989  if(chars_read<4){
990    fprintf(stderr,"File is too short. Not well formed.\n");
991    exit(-1);
992  }
993
994  Entity_Info * e = new Entity_Info;
995  e->AnalyzeSignature((unsigned char *)srcbuf);
996
997  if (e->code_unit_base == ASCII) {
998
999    XML_Decl_Parser<ASCII> decl_parser((unsigned char *)srcbuf);
1000
1001    decl_parser.ReadXMLInfo(*e);
1002
1003    if (e->code_unit_size != SingleByte || (e->has_encoding_decl && (!at_UTF_8(e->encoding)))){
1004        fprintf(stderr,"Sorry, this xmlwf demo only works for UTF-8.\n");
1005        exit(-1);
1006    }
1007  }
1008  else {
1009    fprintf(stderr,"Sorry, this xmlwf demo does not process EBCDIC.\n");
1010        exit(-1);
1011  }
1012
1013  if (e->content_start != 0) {
1014        memmove(&srcbuf[0], &srcbuf[e->content_start], chars_read - e->content_start);
1015        buf_pos = e->content_start;
1016        if (chars_avail == BUFFER_SIZE) {
1017                chars_read = chars_read - e->content_start +
1018                             fread(&srcbuf[chars_read-e->content_start], 1, e->content_start, infile);
1019                chars_avail = min(chars_read,BUFFER_SIZE);
1020        }
1021        else {
1022          chars_read -=e->content_start;
1023          chars_avail -=e->content_start;
1024        }
1025  }
1026
1027  Parse_refs parse_refs;
1028  Parse_tags parse_tags;
1029  Classify_bytes_Validate_utf8 classify_bytes_Validate_utf8;
1030  Parse_CtCDPI parse_CtCDPI;
1031  Do_check_streams do_check_streams;
1032  Validate_xml_names validate_xml_names;
1033  Add_scope_streams add_scope_streams;
1034
1035
1036  while(1){
1037#if PASS == TOTAL
1038    PERF_SEC_START(parser_timer);
1039#endif
1040    block_pos = 0;
1041
1042    if(chars_avail < BUFFER_SIZE){
1043
1044                int i=0;
1045                while (block_pos <= chars_avail || CarryTest(parse_refs.carryQ, 0, 6) || CarryTest(parse_tags.carryQ, 0, 13) || CarryTest(classify_bytes_Validate_utf8.carryQ, 0, 12) || CarryTest(parse_CtCDPI.carryQ, 0, 18) || CarryTest(validate_xml_names.carryQ, 0, 9) || CarryTest(add_scope_streams.carryQ, 0, 2)){
1046
1047                        int bytes = chars_avail - block_pos;
1048                        block_base = block_pos;
1049
1050                        if(bytes < BLOCK_SIZE){
1051                          masks[i].EOF_mask = sisd_srl(simd_const_1(1),sisd_from_int(BLOCK_SIZE-bytes));
1052                          EOF_mask = sisd_srl(simd_const_1(1),sisd_from_int(BLOCK_SIZE-bytes));
1053                        }
1054
1055                        s2p_do_block((BytePack *) &srcbuf[block_pos], basis_bits[i]);
1056
1057                        basis_bits[i].bit_0 = simd_and(basis_bits[i].bit_0, masks[i].EOF_mask);
1058                        basis_bits[i].bit_1 = simd_and(basis_bits[i].bit_1, masks[i].EOF_mask);
1059                        basis_bits[i].bit_2 = simd_and(basis_bits[i].bit_2, masks[i].EOF_mask);
1060                        basis_bits[i].bit_3 = simd_and(basis_bits[i].bit_3, masks[i].EOF_mask);
1061                        basis_bits[i].bit_4 = simd_and(basis_bits[i].bit_4, masks[i].EOF_mask);
1062                        basis_bits[i].bit_5 = simd_and(basis_bits[i].bit_5, masks[i].EOF_mask);
1063                        basis_bits[i].bit_6 = simd_and(basis_bits[i].bit_6, masks[i].EOF_mask);
1064                        basis_bits[i].bit_7 = simd_and(basis_bits[i].bit_7, masks[i].EOF_mask);
1065
1066                       
1067  classify_bytes_Validate_utf8.do_block(basis_bits[i], lex[i], u8[i]);
1068  add_scope_streams.do_block(lex[i], scope1[i]);
1069  parse_CtCDPI.do_block(ctCDPI_Callouts[i], lex[i], scope1[i], masks[i], check_streams[i]);
1070  parse_tags.do_block(lex[i], scope1[i], ctCDPI_Callouts[i], tag_Callouts[i], masks[i]);
1071  parse_refs.do_block(lex[i], scope1[i], ctCDPI_Callouts[i], ref_Callouts[i]);
1072  validate_xml_names.do_block(ctCDPI_Callouts[i], ref_Callouts[i], tag_Callouts[i], lex[i], u8[i], xml_names[i], check_streams[i]);
1073  do_check_streams.do_block(ctCDPI_Callouts[i], tag_Callouts[i], lex[i], u8[i], scope1[i], ref_Callouts[i], xml_names[i], check_streams[i], masks[i]);
1074
1075                        postprocess_do_block(lex[i], ctCDPI_Callouts[i], ref_Callouts[i], check_streams[i], chars_avail);
1076
1077                        block_pos += BLOCK_SIZE;
1078                }
1079                i++;
1080
1081            matcher.StreamScan(chars_avail);
1082            matcher.Advance_buffer();
1083            tracker.Advance_buffer();
1084    }
1085    else{
1086      while (block_pos < chars_avail){
1087
1088          block_base = block_pos;
1089
1090#if PASS == S2P
1091          PERF_SEC_START(s2p_timer);
1092#endif
1093          s2p_do_segment((BytePack *) &srcbuf[block_pos], basis_bits);
1094#if PASS == S2P
1095          PERF_SEC_END(s2p_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1096#endif
1097
1098#if PASS == CLASSIFY
1099          PERF_SEC_START(classify_timer);
1100#endif
1101                  classify_bytes_Validate_utf8.do_segment(basis_bits, lex, u8);
1102#if PASS == CLASSIFY
1103                  PERF_SEC_END(classify_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1104#endif
1105
1106#if PASS == SCOPE
1107                  PERF_SEC_START(scope_timer);
1108#endif
1109                  add_scope_streams.do_segment(lex, scope1);
1110#if PASS == SCOPE
1111                  PERF_SEC_END(scope_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1112#endif
1113
1114#if PASS == CTCDPI
1115                  PERF_SEC_START(CtCDPI_timer);
1116#endif
1117                  parse_CtCDPI.do_segment(ctCDPI_Callouts, lex, scope1, masks, check_streams);
1118#if PASS == CTCDPI
1119                  PERF_SEC_END(CtCDPI_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1120#endif
1121
1122#if PASS == TAGS
1123                  PERF_SEC_START(tags_timer);
1124#endif
1125                  parse_tags.do_segment(lex, scope1, ctCDPI_Callouts, tag_Callouts, masks);
1126#if PASS == TAGS
1127                  PERF_SEC_END(tags_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1128#endif
1129
1130#if PASS == REFS
1131                  PERF_SEC_START(refs_timer);
1132#endif
1133                  parse_refs.do_segment(lex, scope1, ctCDPI_Callouts, ref_Callouts);
1134#if PASS == REFS
1135                  PERF_SEC_END(refs_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1136#endif
1137
1138#if PASS == VALIDATE
1139                  PERF_SEC_START(validate_timer);
1140#endif
1141                  validate_xml_names.do_segment(ctCDPI_Callouts, ref_Callouts, tag_Callouts, lex, u8, xml_names, check_streams);
1142#if PASS == VALIDATE
1143                  PERF_SEC_END(validate_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1144#endif
1145                 
1146#if PASS == CHECK
1147                  PERF_SEC_START(check_timer);
1148#endif
1149                  do_check_streams.do_segment(ctCDPI_Callouts, tag_Callouts, lex, u8, scope1, ref_Callouts, xml_names, check_streams, masks);
1150#if PASS == CHECK
1151                  PERF_SEC_END(check_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1152#endif
1153
1154#if PASS == POSTPROCESS
1155                  PERF_SEC_START(postprocess_timer);
1156#endif
1157                  postprocess_do_segment(lex, ctCDPI_Callouts, ref_Callouts, check_streams, chars_avail);
1158#if PASS == POSTPROCESS
1159                  PERF_SEC_END(postprocess_timer, BLOCK_SIZE * SEGMENT_BLOCKS);
1160#endif
1161
1162                  block_pos += BLOCK_SIZE * SEGMENT_BLOCKS;
1163      }
1164    }
1165
1166
1167
1168#if PASS == TOTAL
1169    PERF_SEC_END(parser_timer, chars_avail);
1170#endif
1171    buf_pos += chars_avail;
1172    buffer_base = buf_pos;
1173    if(chars_avail!=chars_read){
1174      int bytes_left = chars_read-chars_avail;
1175      memmove(srcbuf, &srcbuf[BUFFER_SIZE], bytes_left);
1176      chars_read = fread(&srcbuf[bytes_left],1, BUFFER_SIZE , infile)+bytes_left;
1177      chars_avail = min(chars_read,BUFFER_SIZE);
1178    }
1179    else
1180      break;
1181  }
1182  if(matcher.depth!=0){
1183    fprintf(stderr, "tag matching error (depth %i) at position %i\n", matcher.depth, buffer_base);
1184    exit(-1);
1185  }
1186
1187}
1188
1189
1190
1191int
1192main(int argc, char * argv[]) {
1193        char * infilename, * outfilename;
1194        FILE *infile, *outfile;
1195        struct stat fileinfo;
1196
1197        if (argc < 2) {
1198                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
1199                exit(-1);
1200        }
1201
1202        infilename = argv[1];
1203        stat(infilename, &fileinfo);
1204        infile = fopen(infilename, "rb");
1205        if (!infile) {
1206                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
1207                exit(-1);
1208        }
1209
1210        if (argc < 3) outfile = stdout;
1211        else {
1212                outfilename = argv[2];
1213                outfile = fopen(outfilename, "wb");
1214                if (!outfile) {
1215                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
1216                        exit(-1);
1217                }
1218        }
1219
1220//      PERF_SEC_BIND(1);
1221
1222        PERF_SEC_INIT(parser_timer);
1223        PERF_SEC_INIT(s2p_timer);
1224        PERF_SEC_INIT(classify_timer);
1225        PERF_SEC_INIT(scope_timer);
1226        PERF_SEC_INIT(postprocess_timer);
1227        PERF_SEC_INIT(tags_timer);
1228        PERF_SEC_INIT(CtCDPI_timer);
1229        PERF_SEC_INIT(refs_timer);
1230        PERF_SEC_INIT(check_timer);
1231        PERF_SEC_INIT(validate_timer);
1232
1233        do_process(infile, outfile);
1234#if PASS == TOTAL
1235//    printf("This is the total time.\n");
1236        PERF_SEC_DUMP(parser_timer);
1237#endif
1238#if PASS == S2P
1239//      printf("This is the transposition time.\n");
1240        PERF_SEC_DUMP(s2p_timer);
1241#endif
1242#if PASS == CLASSIFY
1243//      printf("This is the classification and utf8 validation time.\n");
1244        PERF_SEC_DUMP(classify_timer);
1245#endif
1246#if PASS == SCOPE
1247//      printf("This is the time for generating scope treams.\n");
1248        PERF_SEC_DUMP(scope_timer);
1249#endif
1250#if PASS == CTCDPI
1251//      printf("This is the CtCDPI parsing time.\n");
1252        PERF_SEC_DUMP(CtCDPI_timer);
1253#endif
1254#if PASS == TAGS
1255//      printf("This is the tags parsing time.\n");
1256        PERF_SEC_DUMP(tags_timer);
1257#endif
1258#if PASS == REFS
1259//      printf("This is the reference parsing time.\n");
1260        PERF_SEC_DUMP(refs_timer);
1261#endif
1262#if PASS == VALIDATE
1263//      printf("This is the XML names validation time.\n");
1264        PERF_SEC_DUMP(validate_timer);
1265#endif
1266#if PASS == CHECK
1267//      printf("This is the time for generating check streams.\n");
1268        PERF_SEC_DUMP(check_timer);
1269#endif
1270#if PASS == POSTPROCESS
1271//      printf("This is the post processing time.\n");
1272        PERF_SEC_DUMP(postprocess_timer);
1273#endif
1274
1275        PERF_SEC_DESTROY(parser_timer);
1276        PERF_SEC_DESTROY(s2p_timer);
1277        PERF_SEC_DESTROY(classify_timer);
1278        PERF_SEC_DESTROY(scope_timer);
1279        PERF_SEC_DESTROY(postprocess_timer);
1280        PERF_SEC_DESTROY(CtCDPI_timer);
1281        PERF_SEC_DESTROY(refs_timer);
1282        PERF_SEC_DESTROY(check_timer);
1283        PERF_SEC_DESTROY(validate_timer);
1284        PERF_SEC_DESTROY(tags_timer);
1285
1286        fclose(infile);
1287        fclose(outfile);
1288        return(0);
1289}
Note: See TracBrowser for help on using the repository browser.