source: proto/parabix2/src/xmlwf_multithreads.cpp @ 1049

Last change on this file since 1049 was 1049, checked in by lindanl, 8 years ago

multithread version

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