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

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

remove mask

File size: 49.5 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"
28BitBlock EOF_mask = simd_const_1(1);
29
30#ifdef BUFFER_PROFILING
31        BOM_Table * parser_timer;
32#endif
33LineColTracker tracker;
34TagMatcher matcher;
35
36int block_base=0;
37int buffer_base=0;
38char * source;
39
40static inline int StreamScan(ScanBlock * stream, int blk_count, int ProcessPos(int)) {
41        int blk;
42        int block_pos = 0;
43
44        for (blk = 0; blk < blk_count; blk++) {
45                ScanBlock s = stream[blk];
46                while(s) {
47                        int code = (ProcessPos(cfzl(s) + block_pos));
48                        if (code) return code;
49                        s = s & (s-1);  // clear rightmost bit.
50                }
51                block_pos += 8 * sizeof(ScanBlock);
52        }
53
54        return 0;
55}
56
57static inline void ReportError(const char * error_msg, int error_pos_in_block) {
58  int error_line, error_column;
59  tracker.get_Line_and_Column(error_pos_in_block, error_line, error_column);
60  fprintf(stderr, "%s at line %i, column %i\n", error_msg, error_line, error_column);
61}
62
63
64static inline int NameStrt_check(int pos) {
65        int block_pos = block_base + pos;
66        if(XML_10_UTF8_NameStrt_bytes((unsigned char*)&source[block_pos]) == 0){
67              ReportError("name start error", pos);
68              exit(-1);
69        }
70        return 0;
71}
72
73static inline int Name_check(int pos) {
74        int block_pos = block_base + pos;
75        if(XML_10_UTF8_NameChar_bytes((unsigned char*)&source[block_pos]) == 0){
76              ReportError("name error", pos);
77              exit(-1);
78        }
79        return 0;
80}
81
82static inline int PIName_check(int pos) {
83        int block_pos = block_base + pos;
84        int file_pos = block_pos+buffer_base;
85        if (at_XxMmLll<ASCII>((unsigned char*)&source[block_pos]) && (source[block_pos+3]=='?' || source[block_pos+3]<= ' ')) {
86              // "<?xml" legal at start of file.
87              if ((file_pos == 2) && at_XmlDecl_start<ASCII>((unsigned char*)&source[0])) return 0;
88              ReportError("[Xx][Mm][Ll] illegal as PI name", pos);
89              exit(-1);
90        }
91        return 0;
92}
93
94static inline int CD_check(int pos) {
95        int block_pos = block_base + pos;
96        if (!at_CDATA1<ASCII>((unsigned char*)&source[block_pos])){
97              ReportError("CDATA error", pos);
98              exit(-1);
99        }
100        return 0;
101}
102
103static inline int GenRef_check(int pos) {
104        int block_pos = block_base + pos;
105        unsigned char* s = (unsigned char*)&source[block_pos];
106        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))){
107              ReportError("Undefined reference", pos);
108              exit(-1);
109        }
110        return 0;
111}
112
113static inline int HexRef_check(int pos) {
114        int block_pos = block_base + pos;
115        unsigned char* s = (unsigned char*)&source[block_pos];
116        int ch_val = 0;
117        while(at_HexDigit<ASCII>(s)){
118          ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
119          if (ch_val> 0x10FFFF ){
120            ReportError("Illegal character reference", pos);
121            exit(-1);
122          }
123          s++;
124        }
125        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
126          ReportError("Illegal character reference", pos);
127          exit(-1);
128        }
129        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
130          ReportError("Illegal XML 1.0 character reference", pos);
131          exit(-1);
132        }
133        return 0;
134}
135
136static inline int DecRef_check(int pos) {
137        int block_pos = block_base + pos;
138        unsigned char* s = (unsigned char*)&source[block_pos];
139        int ch_val = 0;
140        while(at_HexDigit<ASCII>(s)){
141          ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
142          if (ch_val> 0x10FFFF ){
143            ReportError("Illegal character reference", pos);
144            exit(-1);
145          }
146          s++;
147        }
148        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
149          ReportError("Illegal character reference", pos);
150          exit(-1);
151        }
152        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
153          ReportError("Illegal XML 1.0 character reference", pos);
154          exit(-1);
155        }
156        return 0;
157}
158
159static inline int AttRef_check(int pos) {
160        int block_pos = block_base + pos;
161        unsigned char* s = (unsigned char*)&source[block_pos];
162        int ch_val = 0;
163        if(s[0]=='#'){
164          s++;
165          if(s[0]=='x' || s[0]=='X'){
166            s++;
167            while(at_HexDigit<ASCII>(s)){
168              ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
169              s++;
170            }
171          }
172          else{
173            while(at_HexDigit<ASCII>(s)){
174              ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
175              s++;
176            }
177          }
178          if (ch_val==60){
179            ReportError("Attribute values contain '<' characters after reference expansion", pos);
180            exit(-1);
181          }
182        }
183        else if(at_Ref_lt<ASCII>(s)){
184          ReportError("Attribute values contain '<' characters after reference expansion", pos);
185          exit(-1);
186        }
187        return 0;
188}
189
190  struct U8 {
191  BitBlock unibyte;
192  BitBlock prefix;
193  BitBlock prefix2;
194  BitBlock prefix3;
195  BitBlock prefix4;
196  BitBlock suffix;
197  BitBlock badprefix;
198  BitBlock xE0;
199  BitBlock xED;
200  BitBlock xF0;
201  BitBlock xF4;
202  BitBlock xA0_xBF;
203  BitBlock x80_x9F;
204  BitBlock x90_xBF;
205  BitBlock x80_x8F;
206  BitBlock xEF;
207  BitBlock xBF;
208  BitBlock xBE;
209  BitBlock scope22;
210  BitBlock scope32;
211  BitBlock scope33;
212  BitBlock scope42;
213  BitBlock scope43;
214  BitBlock scope44;
215  BitBlock xE0_scope;
216  BitBlock xED_scope;
217  BitBlock xF0_scope;
218  BitBlock xF4_scope;
219  BitBlock xEF_scope;
220  BitBlock FFFE_FFFF;
221  BitBlock error;
222};
223
224  struct Lex {
225  BitBlock CR;
226  BitBlock LF;
227  BitBlock HT;
228  BitBlock SP;
229  BitBlock CRLF;
230  BitBlock RefStart;
231  BitBlock Semicolon;
232  BitBlock Colon;
233  BitBlock LAngle;
234  BitBlock RAngle;
235  BitBlock LBracket;
236  BitBlock RBracket;
237  BitBlock Exclam;
238  BitBlock QMark;
239  BitBlock Hyphen;
240  BitBlock Equals;
241  BitBlock SQuote;
242  BitBlock DQuote;
243  BitBlock Slash;
244  BitBlock Hash;
245  BitBlock x;
246  BitBlock ASCII_name_start;
247  BitBlock ASCII_name_char;
248  BitBlock NameScan;
249  BitBlock Digit;
250  BitBlock Hex;
251  BitBlock WS;
252  BitBlock error;
253};
254
255  struct Scope1 {
256  BitBlock RefStart;
257  BitBlock LAngle;
258  BitBlock Hyphen;
259  BitBlock QMark;
260  BitBlock RBracket;
261};
262
263  struct CtCDPI_Callouts {
264  BitBlock CD_end;
265  BitBlock Ct_starts;
266  BitBlock Ct_ends;
267  BitBlock CD_starts;
268  BitBlock CD_ends;
269  BitBlock PI_starts;
270  BitBlock PI_name_starts;
271  BitBlock PI_name_ends;
272  BitBlock PI_ends;
273  BitBlock CtCDPI_mask;
274  BitBlock error;
275};
276
277  struct Ref_Callouts {
278  BitBlock GenRef_starts;
279  BitBlock GenRef_ends;
280  BitBlock DecRef_starts;
281  BitBlock DecRef_ends;
282  BitBlock HexRef_starts;
283  BitBlock HexRef_ends;
284  BitBlock error;
285};
286
287  struct Tag_Callouts {
288  BitBlock ElemName_starts;
289  BitBlock ElemName_ends;
290  BitBlock AttName_starts;
291  BitBlock AttName_ends;
292  BitBlock AttVal_starts;
293  BitBlock AttVal_ends;
294  BitBlock AttVal_spans;
295  BitBlock EmptyTag_marks;
296  BitBlock EndTag_marks;
297  BitBlock LAngleFollow;
298  BitBlock error;
299};
300
301  struct Basis_bits {
302  BitBlock bit_0;
303  BitBlock bit_1;
304  BitBlock bit_2;
305  BitBlock bit_3;
306  BitBlock bit_4;
307  BitBlock bit_5;
308  BitBlock bit_6;
309  BitBlock bit_7;
310};
311
312  struct Check_streams {
313  BitBlock misc_mask;
314  BitBlock non_ascii_name_starts;
315  BitBlock non_ascii_names;
316  BitBlock tag_marks;
317  BitBlock name_follows;
318  BitBlock att_refs;
319  BitBlock error_mask;
320};
321
322  struct Xml_names {
323  BitBlock namespace_error;
324};
325
326  struct Parse_refs {
327  Parse_refs() { CarryInit(carryQ, 6); }
328  void do_block(Lex & lex, Scope1 & scope1, CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts) {
329                BitBlock Ref1, NumRef2, NumRef3, HexRef3, ref_error1, ref_error2, ref_ends;
330                BitBlock ref_error3;
331
332
333        ref_Callouts.GenRef_starts = simd_const_1(0);
334        ref_Callouts.GenRef_ends = simd_const_1(0);
335        ref_Callouts.DecRef_starts = simd_const_1(0);
336        ref_Callouts.DecRef_ends = simd_const_1(0);
337        ref_Callouts.HexRef_starts = simd_const_1(0);
338        ref_Callouts.HexRef_ends = simd_const_1(0);
339        ref_Callouts.error = simd_const_1(0);
340        Ref1 = simd_andc(lex.RefStart, ctCDPI_Callouts.CtCDPI_mask);
341        if ((bitblock_has_bit(Ref1) || CarryTest(carryQ, 0, 6))) {
342          scope1.RefStart = BitBlock_advance_ci_co(Ref1, carryQ, 0);
343          NumRef2 = simd_and(scope1.RefStart, lex.Hash);
344          ref_Callouts.GenRef_starts = simd_andc(scope1.RefStart, lex.Hash);
345          NumRef3 = BitBlock_advance_ci_co(NumRef2, carryQ, 1);
346          HexRef3 = simd_and(NumRef3, lex.x);
347          ref_Callouts.DecRef_starts = simd_andc(NumRef3, lex.x);
348          ref_Callouts.HexRef_starts = BitBlock_advance_ci_co(HexRef3, carryQ, 2);
349          ref_Callouts.GenRef_ends = BitBlock_scanthru_ci_co(ref_Callouts.GenRef_starts, lex.NameScan, carryQ, 3);
350          ref_Callouts.DecRef_ends = BitBlock_scanthru_ci_co(ref_Callouts.DecRef_starts, lex.Digit, carryQ, 4);
351          ref_Callouts.HexRef_ends = BitBlock_scanthru_ci_co(ref_Callouts.HexRef_starts, lex.Hex, carryQ, 5);
352          ref_error1 = simd_andc(ref_Callouts.DecRef_starts, lex.Digit);
353          ref_error2 = simd_andc(ref_Callouts.HexRef_starts, lex.Hex);
354          ref_ends = simd_or(simd_or(ref_Callouts.GenRef_ends, ref_Callouts.DecRef_ends), ref_Callouts.HexRef_ends);
355          ref_error3 = simd_andc(ref_ends, lex.Semicolon);
356          ref_Callouts.error = simd_or(simd_or(ref_error1, ref_error2), ref_error3);
357        }
358        else {
359          CarryDequeueEnqueue(carryQ, 0, 6);
360        }
361        CarryQ_Adjust(carryQ, 6);
362  }
363  void do_segment(Lex lex[], Scope1 scope1[], CtCDPI_Callouts ctCDPI_Callouts[], Ref_Callouts ref_Callouts[]) {
364  for (int i = 0; i < SEGMENT_BLOCKS; i++)
365    do_block(lex[i], scope1[i], ctCDPI_Callouts[i], ref_Callouts[i]);
366  }
367  CarryDeclare(carryQ, 6);
368  };
369
370  struct Parse_tags {
371  Parse_tags() { CarryInit(carryQ, 13); }
372  void do_block(Lex & lex, Scope1 & scope1, CtCDPI_Callouts & ctCDPI_Callouts, Tag_Callouts & tag_Callouts) {
373                BitBlock DQuoteDelim, SQuoteDelim, AttListDelim, ParseError, EqToCheck;
374                BitBlock AttValEnds, AfterWS, AttListEnd, AttNameStart, AttNameFollow;
375                BitBlock EqExpected, AttValPos, DQuoteAttVal, SQuoteAttVal, DQuoteAttEnd;
376                BitBlock SQuoteAttEnd, AttValEnd, AttValFollow, STagEnds, EndTagEnds;
377
378
379        DQuoteDelim = simd_or(lex.DQuote, lex.LAngle);
380        SQuoteDelim = simd_or(lex.SQuote, lex.LAngle);
381        AttListDelim = simd_or(lex.Slash, lex.RAngle);
382        tag_Callouts.LAngleFollow = simd_andc(scope1.LAngle, ctCDPI_Callouts.CtCDPI_mask);
383        tag_Callouts.ElemName_starts = simd_andc(tag_Callouts.LAngleFollow, lex.Slash);
384        tag_Callouts.EndTag_marks = simd_and(tag_Callouts.LAngleFollow, lex.Slash);
385        tag_Callouts.ElemName_ends = BitBlock_scanthru_ci_co(tag_Callouts.ElemName_starts, lex.NameScan, carryQ, 0);
386        ParseError = simd_and(tag_Callouts.ElemName_starts, tag_Callouts.ElemName_ends);
387        tag_Callouts.AttName_starts = simd_const_1(0);
388        tag_Callouts.AttName_ends = simd_const_1(0);
389        EqToCheck = simd_const_1(0);
390        tag_Callouts.AttVal_starts = simd_const_1(0);
391        AttValEnds = simd_const_1(0);
392        tag_Callouts.AttVal_ends = simd_const_1(0);
393        AfterWS = BitBlock_scanthru_ci_co(tag_Callouts.ElemName_ends, lex.WS, carryQ, 1);
394        AttListEnd = simd_and(AfterWS, AttListDelim);
395        AttNameStart = simd_andc(AfterWS, AttListDelim);
396        ParseError = simd_or(ParseError, simd_and(tag_Callouts.ElemName_ends, AttNameStart));
397        if ((bitblock_has_bit(AttNameStart) || CarryTest(carryQ, 2, 7))) {
398          tag_Callouts.AttName_starts = simd_or(tag_Callouts.AttName_starts, AttNameStart);
399          AttNameFollow = BitBlock_scanthru_ci_co(AttNameStart, lex.NameScan, carryQ, 2);
400          tag_Callouts.AttName_ends = simd_or(tag_Callouts.AttName_ends, AttNameFollow);
401          EqExpected = BitBlock_scanthru_ci_co(AttNameFollow, lex.WS, carryQ, 3);
402          EqToCheck = simd_or(EqToCheck, EqExpected);
403          AttValPos = BitBlock_scanthru_ci_co(EqExpected, simd_or(EqExpected, lex.WS), carryQ, 4);
404          tag_Callouts.AttVal_starts = simd_or(tag_Callouts.AttVal_starts, AttValPos);
405          DQuoteAttVal = simd_and(AttValPos, lex.DQuote);
406          SQuoteAttVal = simd_and(AttValPos, lex.SQuote);
407          DQuoteAttEnd = BitBlock_scanto_ci_co(DQuoteAttVal, simd_andc(DQuoteDelim, DQuoteAttVal), carryQ, 5);
408          SQuoteAttEnd = BitBlock_scanto_ci_co(SQuoteAttVal, simd_andc(SQuoteDelim, SQuoteAttVal), carryQ, 6);
409          AttValEnd = simd_or(DQuoteAttEnd, SQuoteAttEnd);
410          AttValEnds = simd_or(AttValEnds, AttValEnd);
411          AttValFollow = BitBlock_advance_ci_co(AttValEnd, carryQ, 7);
412          tag_Callouts.AttVal_ends = simd_or(tag_Callouts.AttVal_ends, AttValFollow);
413          AfterWS = BitBlock_scanthru_ci_co(AttValFollow, lex.WS, carryQ, 8);
414          AttListEnd = simd_or(AttListEnd, simd_and(AfterWS, AttListDelim));
415          AttNameStart = simd_andc(AfterWS, AttListDelim);
416          while (bitblock_has_bit(AttNameStart)) {
417            CarryDeclare(subcarryQ, 7);
418            CarryInit(subcarryQ, 7);
419            tag_Callouts.AttName_starts = simd_or(tag_Callouts.AttName_starts, AttNameStart);
420            AttNameFollow = BitBlock_scanthru_co(AttNameStart, lex.NameScan, subcarryQ, 0);
421            tag_Callouts.AttName_ends = simd_or(tag_Callouts.AttName_ends, AttNameFollow);
422            EqExpected = BitBlock_scanthru_co(AttNameFollow, lex.WS, subcarryQ, 1);
423            EqToCheck = simd_or(EqToCheck, EqExpected);
424            AttValPos = BitBlock_scanthru_co(EqExpected, simd_or(EqExpected, lex.WS), subcarryQ, 2);
425            tag_Callouts.AttVal_starts = simd_or(tag_Callouts.AttVal_starts, AttValPos);
426            DQuoteAttVal = simd_and(AttValPos, lex.DQuote);
427            SQuoteAttVal = simd_and(AttValPos, lex.SQuote);
428            DQuoteAttEnd = BitBlock_scanto_co(DQuoteAttVal, simd_andc(DQuoteDelim, DQuoteAttVal), subcarryQ, 3);
429            SQuoteAttEnd = BitBlock_scanto_co(SQuoteAttVal, simd_andc(SQuoteDelim, SQuoteAttVal), subcarryQ, 4);
430            AttValEnd = simd_or(DQuoteAttEnd, SQuoteAttEnd);
431            AttValEnds = simd_or(AttValEnds, AttValEnd);
432            AttValFollow = BitBlock_advance_co(AttValEnd, subcarryQ, 5);
433            tag_Callouts.AttVal_ends = simd_or(tag_Callouts.AttVal_ends, AttValFollow);
434            AfterWS = BitBlock_scanthru_co(AttValFollow, lex.WS, subcarryQ, 6);
435            AttListEnd = simd_or(AttListEnd, simd_and(AfterWS, AttListDelim));
436            AttNameStart = simd_andc(AfterWS, AttListDelim);
437            CarryCombine(carryQ, subcarryQ, 2, 7);
438          }
439        }
440        else {
441          CarryDequeueEnqueue(carryQ, 2, 7);
442        }
443        STagEnds = simd_and(AttListEnd, lex.RAngle);
444        tag_Callouts.EmptyTag_marks = BitBlock_advance_ci_co(simd_and(AttListEnd, lex.Slash), carryQ, 9);
445        ParseError = simd_or(ParseError, simd_and(tag_Callouts.AttVal_ends, tag_Callouts.AttName_starts));
446        ParseError = simd_or(ParseError, simd_and(tag_Callouts.AttName_starts, tag_Callouts.AttName_ends));
447        ParseError = simd_or(ParseError, simd_andc(EqToCheck, lex.Equals));
448        ParseError = simd_or(ParseError, simd_andc(tag_Callouts.AttVal_starts, simd_or(lex.DQuote, lex.SQuote)));
449        ParseError = simd_or(ParseError, simd_andc(AttValEnds, simd_or(lex.DQuote, lex.SQuote)));
450        ParseError = simd_or(ParseError, simd_andc(tag_Callouts.EmptyTag_marks, lex.RAngle));
451        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);
452        ParseError = simd_or(ParseError, simd_andc(EndTagEnds, lex.RAngle));
453        tag_Callouts.error = ParseError;
454        tag_Callouts.AttVal_spans = BitBlock_sub_ci_co(tag_Callouts.AttVal_ends, tag_Callouts.AttVal_starts, carryQ, 12);
455        CarryQ_Adjust(carryQ, 13);
456  }
457  void do_segment(Lex lex[], Scope1 scope1[], CtCDPI_Callouts ctCDPI_Callouts[], Tag_Callouts tag_Callouts[]) {
458  for (int i = 0; i < SEGMENT_BLOCKS; i++)
459    do_block(lex[i], scope1[i], ctCDPI_Callouts[i], tag_Callouts[i]);
460  }
461  CarryDeclare(carryQ, 13);
462  };
463
464  struct Classify_bytes_Validate_utf8 {
465  Classify_bytes_Validate_utf8() { CarryInit(carryQ, 12); }
466  void do_block(Basis_bits & basis_bits, Lex & lex, U8 & u8) {
467                BitBlock temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10;
468                BitBlock temp11, temp12, temp13, temp14, temp15, temp16, temp17, temp18;
469                BitBlock temp19, temp20, temp21, temp22, temp23, temp24, temp25, temp26;
470                BitBlock temp27, temp28, temp29, temp30, temp31, temp32, temp33, temp34;
471                BitBlock temp35, temp36, temp37, temp38, temp39, temp40, temp41, temp42;
472                BitBlock temp43, temp44, temp45, temp46, temp47, temp48, x00_x1F, temp49;
473                BitBlock temp50, temp51, temp52, temp53, temp54, temp55, temp56, temp57;
474                BitBlock temp58, temp59, temp60, temp61, temp62, temp63, temp64, temp65;
475                BitBlock u8anyscope, temp66, temp67, temp68, temp69, temp70, temp71, xE0, xED;
476                BitBlock xF0, temp72, xF4, xEF, temp73, u8lastscope, u8error1, u8error2;
477                BitBlock u8error3, u8error4, EF_BF_pending, u8mismatch;
478
479
480        temp1 = simd_or(basis_bits.bit_0, basis_bits.bit_1);
481        temp2 = simd_andc(basis_bits.bit_2, basis_bits.bit_3);
482        temp3 = simd_andc(temp2, temp1);
483        temp4 = simd_andc(basis_bits.bit_5, basis_bits.bit_4);
484        temp5 = simd_andc(basis_bits.bit_6, basis_bits.bit_7);
485        temp6 = simd_and(temp4, temp5);
486        lex.RefStart = simd_and(temp3, temp6);
487        temp7 = simd_and(basis_bits.bit_2, basis_bits.bit_3);
488        temp8 = simd_andc(temp7, temp1);
489        temp9 = simd_andc(basis_bits.bit_4, basis_bits.bit_5);
490        temp10 = simd_and(basis_bits.bit_6, basis_bits.bit_7);
491        temp11 = simd_and(temp9, temp10);
492        lex.Semicolon = simd_and(temp8, temp11);
493        temp12 = simd_and(basis_bits.bit_4, basis_bits.bit_5);
494        temp13 = simd_or(basis_bits.bit_6, basis_bits.bit_7);
495        temp14 = simd_andc(temp12, temp13);
496        lex.LAngle = simd_and(temp8, temp14);
497        temp15 = simd_and(temp12, temp5);
498        lex.RAngle = simd_and(temp8, temp15);
499        temp16 = simd_andc(basis_bits.bit_1, basis_bits.bit_0);
500        temp17 = simd_andc(basis_bits.bit_3, basis_bits.bit_2);
501        temp18 = simd_and(temp16, temp17);
502        lex.LBracket = simd_and(temp18, temp11);
503        temp19 = simd_andc(basis_bits.bit_7, basis_bits.bit_6);
504        temp20 = simd_and(temp12, temp19);
505        lex.RBracket = simd_and(temp18, temp20);
506        temp21 = simd_or(basis_bits.bit_4, basis_bits.bit_5);
507        temp22 = simd_andc(temp19, temp21);
508        lex.Exclam = simd_and(temp3, temp22);
509        temp23 = simd_and(temp12, temp10);
510        lex.QMark = simd_and(temp8, temp23);
511        lex.Hyphen = simd_and(temp3, temp20);
512        lex.Equals = simd_and(temp8, temp20);
513        temp24 = simd_and(temp4, temp10);
514        lex.SQuote = simd_and(temp3, temp24);
515        temp25 = simd_andc(temp5, temp21);
516        lex.DQuote = simd_and(temp3, temp25);
517        lex.Slash = simd_and(temp3, temp23);
518        temp26 = simd_andc(temp10, temp21);
519        lex.Hash = simd_and(temp3, temp26);
520        temp27 = simd_and(temp16, temp7);
521        temp28 = simd_andc(temp9, temp13);
522        lex.x = simd_and(temp27, temp28);
523        temp29 = simd_and(temp9, temp5);
524        lex.Colon = simd_and(temp8, temp29);
525        temp30 = simd_and(temp18, temp23);
526        temp31 = simd_or(temp30, lex.Colon);
527        temp32 = simd_andc(temp16, basis_bits.bit_2);
528        temp33 = simd_or(basis_bits.bit_5, temp10);
529        temp34 = simd_and(basis_bits.bit_4, temp33);
530        temp35 = simd_not(temp34);
531        temp36 = simd_or(temp21, temp13);
532        temp37 = simd_or(simd_and(basis_bits.bit_3, temp35), simd_andc(temp36, basis_bits.bit_3));
533        temp38 = simd_and(temp32, temp37);
534        temp39 = simd_or(temp31, temp38);
535        temp40 = simd_and(temp16, basis_bits.bit_2);
536        temp41 = simd_and(temp40, temp37);
537        lex.ASCII_name_start = simd_or(temp39, temp41);
538        temp42 = simd_or(temp30, lex.Hyphen);
539        temp43 = simd_and(temp3, temp15);
540        temp44 = simd_or(temp42, temp43);
541        temp45 = simd_andc(temp8, temp34);
542        temp46 = simd_or(temp44, temp45);
543        temp47 = simd_or(temp46, temp38);
544        lex.ASCII_name_char = simd_or(temp47, temp41);
545        lex.NameScan = simd_or(lex.ASCII_name_char, basis_bits.bit_0);
546        temp48 = simd_or(temp1, basis_bits.bit_2);
547        x00_x1F = simd_not(temp48);
548        temp49 = simd_or(basis_bits.bit_2, basis_bits.bit_3);
549        temp50 = simd_or(temp1, temp49);
550        lex.CR = simd_andc(temp20, temp50);
551        lex.LF = simd_andc(temp29, temp50);
552        temp51 = simd_and(temp9, temp19);
553        lex.HT = simd_andc(temp51, temp50);
554        lex.SP = simd_andc(temp3, temp36);
555        temp52 = simd_or(temp20, temp29);
556        temp53 = simd_or(temp52, temp51);
557        temp54 = simd_andc(temp53, temp50);
558        lex.WS = simd_or(temp54, lex.SP);
559        temp55 = simd_or(basis_bits.bit_5, basis_bits.bit_6);
560        temp56 = simd_and(basis_bits.bit_4, temp55);
561        lex.Digit = simd_andc(temp8, temp56);
562        temp57 = simd_andc(temp16, temp49);
563        temp58 = simd_andc(temp57, basis_bits.bit_4);
564        temp59 = simd_not(temp10);
565        temp60 = simd_or(simd_and(basis_bits.bit_5, temp59), simd_andc(temp13, basis_bits.bit_5));
566        temp61 = simd_and(temp58, temp60);
567        temp62 = simd_or(lex.Digit, temp61);
568        temp63 = simd_and(temp16, temp2);
569        temp64 = simd_andc(temp63, basis_bits.bit_4);
570        temp65 = simd_and(temp64, temp60);
571        lex.Hex = simd_or(temp62, temp65);
572        lex.error = simd_andc(x00_x1F, lex.WS);
573        u8.unibyte = simd_not(basis_bits.bit_0);
574        u8.suffix = simd_const_1(0);
575        u8.error = simd_const_1(0);
576        u8.FFFE_FFFF = simd_const_1(0);
577        u8anyscope = simd_const_1(0);
578        if ((bitblock_has_bit(basis_bits.bit_0) || CarryTest(carryQ, 0, 12))) {
579          u8.prefix = simd_and(basis_bits.bit_0, basis_bits.bit_1);
580          u8.prefix2 = simd_andc(u8.prefix, basis_bits.bit_2);
581          u8.prefix3 = simd_and(u8.prefix, temp2);
582          u8.prefix4 = simd_and(u8.prefix, temp7);
583          u8.suffix = simd_andc(basis_bits.bit_0, basis_bits.bit_1);
584          temp66 = simd_andc(u8.prefix, temp49);
585          temp67 = simd_or(temp21, basis_bits.bit_6);
586          temp68 = simd_andc(temp66, temp67);
587          temp69 = simd_and(basis_bits.bit_5, temp13);
588          temp70 = simd_or(basis_bits.bit_4, temp69);
589          temp71 = simd_and(u8.prefix4, temp70);
590          u8.badprefix = simd_or(temp68, temp71);
591          u8.error = u8.badprefix;
592          u8.scope22 = BitBlock_advance_ci_co(u8.prefix2, carryQ, 0);
593          u8anyscope = u8.scope22;
594          if ((bitblock_has_bit(simd_or(u8.prefix3, u8.prefix4)) || CarryTest(carryQ, 1, 11))) {
595            xE0 = simd_andc(u8.prefix3, temp36);
596            xED = simd_and(u8.prefix3, temp20);
597            xF0 = simd_andc(u8.prefix4, temp36);
598            temp72 = simd_andc(temp4, temp13);
599            xF4 = simd_and(u8.prefix4, temp72);
600            u8.xA0_xBF = simd_and(u8.suffix, basis_bits.bit_2);
601            u8.x80_x9F = simd_andc(u8.suffix, basis_bits.bit_2);
602            u8.x90_xBF = simd_and(u8.suffix, temp49);
603            u8.x80_x8F = simd_andc(u8.suffix, temp49);
604            xEF = simd_and(u8.prefix3, temp23);
605            temp73 = simd_and(u8.suffix, temp7);
606            u8.xBF = simd_and(temp73, temp23);
607            u8.xBE = simd_and(temp73, temp15);
608            u8.xE0_scope = BitBlock_advance_ci_co(xE0, carryQ, 1);
609            u8.xED_scope = BitBlock_advance_ci_co(xED, carryQ, 2);
610            u8.xF0_scope = BitBlock_advance_ci_co(xF0, carryQ, 3);
611            u8.xF4_scope = BitBlock_advance_ci_co(xF4, carryQ, 4);
612            u8.xEF_scope = BitBlock_advance_ci_co(xEF, carryQ, 5);
613            u8.scope32 = BitBlock_advance_ci_co(u8.prefix3, carryQ, 6);
614            u8.scope33 = BitBlock_advance_ci_co(u8.scope32, carryQ, 7);
615            u8.scope42 = BitBlock_advance_ci_co(u8.prefix4, carryQ, 8);
616            u8.scope43 = BitBlock_advance_ci_co(u8.scope42, carryQ, 9);
617            u8.scope44 = BitBlock_advance_ci_co(u8.scope43, carryQ, 10);
618            u8lastscope = simd_or(simd_or(u8.scope22, u8.scope33), u8.scope44);
619            u8anyscope = simd_or(simd_or(simd_or(u8lastscope, u8.scope32), u8.scope42), u8.scope43);
620            u8error1 = simd_and(u8.xE0_scope, u8.x80_x9F);
621            u8error2 = simd_and(u8.xED_scope, u8.xA0_xBF);
622            u8error3 = simd_and(u8.xF0_scope, u8.x80_x8F);
623            u8error4 = simd_and(u8.xF4_scope, u8.x90_xBF);
624            u8.error = simd_or(u8.error, simd_or(simd_or(simd_or(u8error1, u8error2), u8error3), u8error4));
625            EF_BF_pending = BitBlock_advance_ci_co(simd_and(u8.xEF_scope, u8.xBF), carryQ, 11);
626            u8.FFFE_FFFF = simd_and(EF_BF_pending, simd_or(u8.xBE, u8.xBF));
627          }
628          else {
629            CarryDequeueEnqueue(carryQ, 1, 11);
630          }
631        }
632        else {
633          CarryDequeueEnqueue(carryQ, 0, 12);
634        }
635        u8mismatch = simd_xor(u8anyscope, u8.suffix);
636        u8.error = simd_or(u8.error, u8mismatch);
637        CarryQ_Adjust(carryQ, 12);
638  }
639  void do_segment(Basis_bits basis_bits[], Lex lex[], U8 u8[]) {
640  for (int i = 0; i < SEGMENT_BLOCKS; i++)
641    do_block(basis_bits[i], lex[i], u8[i]);
642  }
643  CarryDeclare(carryQ, 12);
644  };
645
646  struct Parse_CtCDPI {
647  Parse_CtCDPI() { CarryInit(carryQ, 19); }
648  void do_block(CtCDPI_Callouts & ctCDPI_Callouts, Lex & lex, Scope1 & scope1, Check_streams & check_streams) {
649                BitBlock CtCDPI_starts, Ct_errors, PI_start, CtCD_start, CtCDPI_start;
650                BitBlock DoubleHyphen, PI_end, CtCDPI_Cursor, PI_Cursor, CD_Ct_Cursor;
651                BitBlock CD_Cursor, Ct_Cursor, PI_name_end;
652
653  CtCDPI_Cursor = sisd_from_int(1);
654
655        ctCDPI_Callouts.CD_end = simd_const_1(0);
656        ctCDPI_Callouts.Ct_starts = simd_const_1(0);
657        ctCDPI_Callouts.Ct_ends = simd_const_1(0);
658        ctCDPI_Callouts.CD_starts = simd_const_1(0);
659        ctCDPI_Callouts.CD_ends = simd_const_1(0);
660        ctCDPI_Callouts.PI_starts = simd_const_1(0);
661        ctCDPI_Callouts.PI_name_starts = simd_const_1(0);
662        ctCDPI_Callouts.PI_name_ends = simd_const_1(0);
663        ctCDPI_Callouts.PI_ends = simd_const_1(0);
664        ctCDPI_Callouts.CtCDPI_mask = simd_const_1(0);
665        ctCDPI_Callouts.error = simd_const_1(0);
666        CtCDPI_starts = simd_const_1(0);
667        Ct_errors = simd_const_1(0);
668        if ((bitblock_has_bit(lex.RBracket) || CarryTest(carryQ, 0, 2))) {
669          scope1.RBracket = BitBlock_advance_ci_co(lex.RBracket, carryQ, 0);
670          ctCDPI_Callouts.CD_end = simd_and(BitBlock_advance_ci_co(simd_and(scope1.RBracket, lex.RBracket), carryQ, 1), lex.RAngle);
671        }
672        else {
673          CarryDequeueEnqueue(carryQ, 0, 2);
674        }
675        PI_start = simd_and(scope1.LAngle, lex.QMark);
676        CtCD_start = simd_and(scope1.LAngle, lex.Exclam);
677        CtCDPI_start = simd_or(PI_start, CtCD_start);
678        DoubleHyphen = simd_and(scope1.Hyphen, lex.Hyphen);
679        PI_end = simd_and(scope1.QMark, lex.RAngle);
680        CtCDPI_Cursor = BitBlock_scanto_ci_co(CtCDPI_Cursor, CtCDPI_start, carryQ, 2);
681        CtCDPI_Cursor = simd_and(CtCDPI_Cursor, EOF_mask);
682        if ((bitblock_has_bit(CtCDPI_Cursor) || CarryTest(carryQ, 3, 14))) {
683          CtCDPI_starts = simd_or(CtCDPI_starts, CtCDPI_Cursor);
684          PI_Cursor = simd_and(CtCDPI_Cursor, PI_start);
685          CD_Ct_Cursor = BitBlock_advance_ci_co(simd_andc(CtCDPI_Cursor, PI_Cursor), carryQ, 3);
686          CD_Cursor = simd_and(CD_Ct_Cursor, lex.LBracket);
687          Ct_Cursor = simd_and(CD_Ct_Cursor, lex.Hyphen);
688          ctCDPI_Callouts.PI_starts = simd_or(ctCDPI_Callouts.PI_starts, PI_Cursor);
689          ctCDPI_Callouts.CD_starts = simd_or(ctCDPI_Callouts.CD_starts, CD_Cursor);
690          ctCDPI_Callouts.Ct_starts = simd_or(ctCDPI_Callouts.Ct_starts, Ct_Cursor);
691          Ct_Cursor = BitBlock_advance_ci_co(Ct_Cursor, carryQ, 4);
692          Ct_errors = simd_or(Ct_errors, simd_andc(Ct_Cursor, lex.Hyphen));
693          Ct_Cursor = BitBlock_advance_ci_co(BitBlock_advance_ci_co(Ct_Cursor, carryQ, 5), carryQ, 6);
694          PI_Cursor = BitBlock_advance_ci_co(PI_Cursor, carryQ, 7);
695          ctCDPI_Callouts.PI_name_starts = simd_or(ctCDPI_Callouts.PI_name_starts, PI_Cursor);
696          PI_name_end = BitBlock_scanthru_ci_co(PI_Cursor, lex.NameScan, carryQ, 8);
697          ctCDPI_Callouts.PI_name_ends = simd_or(ctCDPI_Callouts.PI_name_ends, PI_name_end);
698          PI_Cursor = BitBlock_scanto_ci_co(PI_name_end, PI_end, carryQ, 9);
699          CD_Cursor = BitBlock_scanto_ci_co(CD_Cursor, ctCDPI_Callouts.CD_end, carryQ, 10);
700          Ct_Cursor = BitBlock_advance_ci_co(BitBlock_scanto_ci_co(Ct_Cursor, DoubleHyphen, carryQ, 11), carryQ, 12);
701          ctCDPI_Callouts.PI_ends = simd_or(ctCDPI_Callouts.PI_ends, PI_Cursor);
702          ctCDPI_Callouts.CD_ends = simd_or(ctCDPI_Callouts.CD_ends, CD_Cursor);
703          ctCDPI_Callouts.Ct_ends = simd_or(ctCDPI_Callouts.Ct_ends, Ct_Cursor);
704          CtCDPI_Cursor = simd_or(simd_or(PI_Cursor, CD_Cursor), Ct_Cursor);
705          CtCDPI_Cursor = BitBlock_scanto_ci_co(CtCDPI_Cursor, CtCDPI_start, carryQ, 13);
706          CtCDPI_Cursor = simd_and(CtCDPI_Cursor, EOF_mask);
707          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, 14), CtCDPI_starts, carryQ, 15);
708          ctCDPI_Callouts.error = simd_or(Ct_errors, simd_andc(ctCDPI_Callouts.Ct_ends, lex.RAngle));
709          ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(BitBlock_advance_ci_co(simd_andc(ctCDPI_Callouts.PI_name_ends, lex.WS), carryQ, 16), PI_end));
710          ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_and(ctCDPI_Callouts.PI_name_starts, ctCDPI_Callouts.PI_name_ends));
711          ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(ctCDPI_Callouts.CtCDPI_mask, EOF_mask));
712          while (bitblock_has_bit(CtCDPI_Cursor)) {
713            CarryDeclare(subcarryQ, 14);
714            CarryInit(subcarryQ, 14);
715            CtCDPI_starts = simd_or(CtCDPI_starts, CtCDPI_Cursor);
716            PI_Cursor = simd_and(CtCDPI_Cursor, PI_start);
717            CD_Ct_Cursor = BitBlock_advance_co(simd_andc(CtCDPI_Cursor, PI_Cursor), subcarryQ, 0);
718            CD_Cursor = simd_and(CD_Ct_Cursor, lex.LBracket);
719            Ct_Cursor = simd_and(CD_Ct_Cursor, lex.Hyphen);
720            ctCDPI_Callouts.PI_starts = simd_or(ctCDPI_Callouts.PI_starts, PI_Cursor);
721            ctCDPI_Callouts.CD_starts = simd_or(ctCDPI_Callouts.CD_starts, CD_Cursor);
722            ctCDPI_Callouts.Ct_starts = simd_or(ctCDPI_Callouts.Ct_starts, Ct_Cursor);
723            Ct_Cursor = BitBlock_advance_co(Ct_Cursor, subcarryQ, 1);
724            Ct_errors = simd_or(Ct_errors, simd_andc(Ct_Cursor, lex.Hyphen));
725            Ct_Cursor = BitBlock_advance_co(BitBlock_advance_co(Ct_Cursor, subcarryQ, 2), subcarryQ, 3);
726            PI_Cursor = BitBlock_advance_co(PI_Cursor, subcarryQ, 4);
727            ctCDPI_Callouts.PI_name_starts = simd_or(ctCDPI_Callouts.PI_name_starts, PI_Cursor);
728            PI_name_end = BitBlock_scanthru_co(PI_Cursor, lex.NameScan, subcarryQ, 5);
729            ctCDPI_Callouts.PI_name_ends = simd_or(ctCDPI_Callouts.PI_name_ends, PI_name_end);
730            PI_Cursor = BitBlock_scanto_co(PI_name_end, PI_end, subcarryQ, 6);
731            CD_Cursor = BitBlock_scanto_co(CD_Cursor, ctCDPI_Callouts.CD_end, subcarryQ, 7);
732            Ct_Cursor = BitBlock_advance_co(BitBlock_scanto_co(Ct_Cursor, DoubleHyphen, subcarryQ, 8), subcarryQ, 9);
733            ctCDPI_Callouts.PI_ends = simd_or(ctCDPI_Callouts.PI_ends, PI_Cursor);
734            ctCDPI_Callouts.CD_ends = simd_or(ctCDPI_Callouts.CD_ends, CD_Cursor);
735            ctCDPI_Callouts.Ct_ends = simd_or(ctCDPI_Callouts.Ct_ends, Ct_Cursor);
736            CtCDPI_Cursor = simd_or(simd_or(PI_Cursor, CD_Cursor), Ct_Cursor);
737            CtCDPI_Cursor = BitBlock_scanto_co(CtCDPI_Cursor, CtCDPI_start, subcarryQ, 10);
738            CtCDPI_Cursor = simd_and(CtCDPI_Cursor, EOF_mask);
739            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, 11), CtCDPI_starts, subcarryQ, 12);
740            ctCDPI_Callouts.error = simd_or(Ct_errors, simd_andc(ctCDPI_Callouts.Ct_ends, lex.RAngle));
741            ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(BitBlock_advance_co(simd_andc(ctCDPI_Callouts.PI_name_ends, lex.WS), subcarryQ, 13), PI_end));
742            ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_and(ctCDPI_Callouts.PI_name_starts, ctCDPI_Callouts.PI_name_ends));
743            ctCDPI_Callouts.error = simd_or(ctCDPI_Callouts.error, simd_andc(ctCDPI_Callouts.CtCDPI_mask, EOF_mask));
744            CarryCombine(carryQ, subcarryQ, 3, 14);
745          }
746        }
747        else {
748          CarryDequeueEnqueue(carryQ, 3, 14);
749        }
750        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, 17), simd_or(ctCDPI_Callouts.Ct_starts, ctCDPI_Callouts.PI_starts), carryQ, 18)), CtCDPI_starts), EOF_mask);
751        CarryQ_Adjust(carryQ, 19);
752  }
753  void do_segment(CtCDPI_Callouts ctCDPI_Callouts[], Lex lex[], Scope1 scope1[], Check_streams check_streams[]) {
754  for (int i = 0; i < SEGMENT_BLOCKS; i++)
755    do_block(ctCDPI_Callouts[i], lex[i], scope1[i], check_streams[i]);
756  }
757  CarryDeclare(carryQ, 19);
758  };
759
760  struct Do_check_streams {
761
762  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) {
763                BitBlock CD_end_error;
764
765
766        CD_end_error = simd_andc(ctCDPI_Callouts.CD_end, simd_or(ctCDPI_Callouts.CtCDPI_mask, tag_Callouts.AttVal_spans));
767        check_streams.error_mask = simd_or(simd_or(simd_or(simd_or(simd_or(simd_or(simd_or(simd_and(lex.error, EOF_mask), u8.error), u8.FFFE_FFFF), ctCDPI_Callouts.error), tag_Callouts.error), CD_end_error), ref_Callouts.error), xml_names.namespace_error);
768        check_streams.tag_marks = simd_or(simd_or(tag_Callouts.EmptyTag_marks, tag_Callouts.LAngleFollow), tag_Callouts.AttName_starts);
769        check_streams.name_follows = simd_or(tag_Callouts.ElemName_ends, tag_Callouts.AttName_ends);
770        check_streams.att_refs = simd_and(tag_Callouts.AttVal_spans, scope1.RefStart);
771  }
772  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[]) {
773  for (int i = 0; i < SEGMENT_BLOCKS; i++)
774    do_block(ctCDPI_Callouts[i], tag_Callouts[i], lex[i], u8[i], scope1[i], ref_Callouts[i], xml_names[i], check_streams[i]);
775  }
776
777  };
778
779  struct Validate_xml_names {
780  Validate_xml_names() { CarryInit(carryQ, 9); }
781  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) {
782                BitBlock PI_names, GenRefs, ElemNames, AttNames, qname_stream, ncname_stream;
783                BitBlock name_stream, name_start, name_cursor, void_prefix_err, namespace_sep;
784                BitBlock local_part_start, local_part_err, colon2_err, ncname_err;
785
786
787        PI_names = BitBlock_sub_ci_co(ctCDPI_Callouts.PI_name_ends, ctCDPI_Callouts.PI_name_starts, carryQ, 0);
788        GenRefs = BitBlock_sub_ci_co(ref_Callouts.GenRef_ends, ref_Callouts.GenRef_starts, carryQ, 1);
789        ElemNames = BitBlock_sub_ci_co(tag_Callouts.ElemName_ends, tag_Callouts.ElemName_starts, carryQ, 2);
790        AttNames = BitBlock_sub_ci_co(tag_Callouts.AttName_ends, tag_Callouts.AttName_starts, carryQ, 3);
791        qname_stream = simd_or(ElemNames, AttNames);
792        ncname_stream = simd_or(PI_names, GenRefs);
793        name_stream = simd_or(qname_stream, ncname_stream);
794        name_start = simd_andc(name_stream, BitBlock_advance_ci_co(name_stream, carryQ, 4));
795        name_cursor = simd_andc(name_stream, BitBlock_advance_ci_co(name_stream, carryQ, 5));
796        void_prefix_err = simd_and(name_cursor, lex.Colon);
797        namespace_sep = simd_and(BitBlock_scanthru_ci_co(name_cursor, simd_andc(lex.NameScan, lex.Colon), carryQ, 6), lex.Colon);
798        local_part_start = BitBlock_advance_ci_co(namespace_sep, carryQ, 7);
799        local_part_err = simd_andc(local_part_start, lex.NameScan);
800        colon2_err = simd_and(BitBlock_scanthru_ci_co(local_part_start, simd_andc(lex.NameScan, lex.Colon), carryQ, 8), lex.Colon);
801        ncname_err = simd_and(ncname_stream, lex.Colon);
802        xml_names.namespace_error = simd_or(simd_or(simd_or(void_prefix_err, local_part_err), colon2_err), ncname_err);
803        check_streams.non_ascii_name_starts = simd_andc(name_start, lex.ASCII_name_start);
804        check_streams.non_ascii_names = simd_andc(simd_andc(simd_andc(name_stream, name_start), lex.ASCII_name_char), u8.suffix);
805        CarryQ_Adjust(carryQ, 9);
806  }
807  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[]) {
808  for (int i = 0; i < SEGMENT_BLOCKS; i++)
809    do_block(ctCDPI_Callouts[i], ref_Callouts[i], tag_Callouts[i], lex[i], u8[i], xml_names[i], check_streams[i]);
810  }
811  CarryDeclare(carryQ, 9);
812  };
813
814  struct Add_scope_streams {
815  Add_scope_streams() { CarryInit(carryQ, 2); }
816  void do_block(Lex & lex, Scope1 & scope1) {
817                BitBlock v, w, v1, w1;
818
819
820        v = simd_or(lex.LAngle, lex.Hyphen);
821        w = simd_or(lex.Hyphen, lex.QMark);
822        v1 = BitBlock_advance_ci_co(v, carryQ, 0);
823        w1 = BitBlock_advance_ci_co(w, carryQ, 1);
824        scope1.LAngle = simd_andc(v1, w1);
825        scope1.Hyphen = simd_and(v1, w1);
826        scope1.QMark = simd_andc(w1, v1);
827        CarryQ_Adjust(carryQ, 2);
828  }
829  void do_segment(Lex lex[], Scope1 scope1[]) {
830  for (int i = 0; i < SEGMENT_BLOCKS; i++)
831    do_block(lex[i], scope1[i]);
832  }
833  CarryDeclare(carryQ, 2);
834  };
835
836
837static inline void s2p_do_block(BytePack U8[], Basis_bits & basis_bits) {
838  s2p(U8[0], U8[1], U8[2], U8[3], U8[4], U8[5], U8[6], U8[7],
839        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);
840}
841
842static inline void s2p_do_final_block(BytePack U8[], Basis_bits & basis_bits, BitBlock EOF_mask) {
843  s2p_do_block(U8, basis_bits);
844  basis_bits.bit_0 = simd_and(basis_bits.bit_0, EOF_mask);
845  basis_bits.bit_1 = simd_and(basis_bits.bit_1, EOF_mask);
846  basis_bits.bit_2 = simd_and(basis_bits.bit_2, EOF_mask);
847  basis_bits.bit_3 = simd_and(basis_bits.bit_3, EOF_mask);
848  basis_bits.bit_4 = simd_and(basis_bits.bit_4, EOF_mask);
849  basis_bits.bit_5 = simd_and(basis_bits.bit_5, EOF_mask);
850  basis_bits.bit_6 = simd_and(basis_bits.bit_6, EOF_mask);
851  basis_bits.bit_7 = simd_and(basis_bits.bit_7, EOF_mask);
852}
853
854static inline void s2p_do_segment(BytePack U8[], Basis_bits basis_bits[]) {
855  for (int i = 0; i < SEGMENT_BLOCKS; i++)
856           s2p_do_block(&U8[8*i], basis_bits[i]);
857}
858
859static inline void postprocess_do_block(Lex & lex, CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts, Check_streams & check_streams, int chars_avail){
860            tracker.StoreNewlines(lex.LF);
861
862                if (bitblock_has_bit(simd_or(check_streams.non_ascii_name_starts, check_streams.non_ascii_names))) {
863                  StreamScan((ScanBlock *) &check_streams.non_ascii_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), NameStrt_check);
864                  StreamScan((ScanBlock *) &check_streams.non_ascii_names, sizeof(BitBlock)/sizeof(ScanBlock), Name_check);
865                }
866
867                if (bitblock_has_bit(ctCDPI_Callouts.PI_name_starts)){
868                  StreamScan((ScanBlock *) &ctCDPI_Callouts.PI_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), PIName_check);
869                }
870
871                if (bitblock_has_bit(ctCDPI_Callouts.CD_starts)){
872                  StreamScan((ScanBlock *) &ctCDPI_Callouts.CD_starts, sizeof(BitBlock)/sizeof(ScanBlock), CD_check);
873                }
874
875                if (bitblock_has_bit(ref_Callouts.GenRef_starts)){
876                  StreamScan((ScanBlock *) &ref_Callouts.GenRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), GenRef_check);
877                }
878
879                if (bitblock_has_bit(ref_Callouts.DecRef_starts)){
880                  StreamScan((ScanBlock *) &ref_Callouts.DecRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), DecRef_check);
881                }
882
883                if (bitblock_has_bit(ref_Callouts.HexRef_starts)){
884                  StreamScan((ScanBlock *) &ref_Callouts.HexRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), HexRef_check);
885                }
886
887                if (bitblock_has_bit(check_streams.att_refs)){
888                  StreamScan((ScanBlock *) &check_streams.att_refs, sizeof(BitBlock)/sizeof(ScanBlock), AttRef_check);
889                }
890
891                if (bitblock_has_bit(check_streams.error_mask)) {
892                  int errpos = count_forward_zeroes(check_streams.error_mask);
893                  ReportError("error found", errpos);
894              exit(-1);
895                }
896
897                matcher.store_streams(check_streams.tag_marks, check_streams.name_follows, check_streams.misc_mask, chars_avail);
898                tracker.AdvanceBlock();
899}
900
901static inline void postprocess_do_segment(Lex lex[], CtCDPI_Callouts ctCDPI_Callouts[], Ref_Callouts ref_Callouts[], Check_streams check_streams[]){
902
903  for (int i = 0; i < SEGMENT_BLOCKS; i++){
904           postprocess_do_block(lex[i], ctCDPI_Callouts[i], ref_Callouts[i], check_streams[i], SEGMENT_SIZE);
905           block_base += BLOCK_SIZE;
906  }
907
908        matcher.StreamScan(SEGMENT_SIZE);
909        matcher.Advance_segment();
910        tracker.Advance_buffer();
911}
912
913struct Para_data{
914
915          char srcbuf[BLOCK_SIZE * (SEGMENT_BLOCKS+1) + OVERLAP_BUFSIZE*2];
916
917          struct U8 u8[SEGMENT_BLOCKS];
918
919          struct Lex lex[SEGMENT_BLOCKS];
920
921          struct Scope1 scope1[SEGMENT_BLOCKS];
922
923          struct CtCDPI_Callouts ctCDPI_Callouts[SEGMENT_BLOCKS];
924
925          struct Ref_Callouts ref_Callouts[SEGMENT_BLOCKS];
926
927          struct Tag_Callouts tag_Callouts[SEGMENT_BLOCKS];
928
929          struct Basis_bits basis_bits[SEGMENT_BLOCKS];
930
931          struct Check_streams check_streams[SEGMENT_BLOCKS];
932
933          struct Xml_names xml_names[SEGMENT_BLOCKS];
934};
935
936Parse_refs parse_refs;
937Parse_tags parse_tags;
938Classify_bytes_Validate_utf8 classify_bytes_Validate_utf8;
939Parse_CtCDPI parse_CtCDPI;
940Do_check_streams do_check_streams;
941Validate_xml_names validate_xml_names;
942Add_scope_streams add_scope_streams;
943
944int file_segs=0;
945FILE *infile;
946FILE *outfile;
947// load with 'consume' (data-dependent) memory ordering
948template<typename T>
949T load_consume(T const* addr)
950{
951  // hardware fence is implicit on x86
952  T v = *const_cast<T const volatile*>(addr);
953#ifdef GCC
954 __sync_synchronize(); // compiler fence
955#endif
956#ifdef ICC
957 __memory_barrier(); // compiler fence
958#endif
959  return v;
960}
961
962// store with 'release' memory ordering
963template<typename T>
964void store_release(T* addr, T v)
965{
966  // hardware fence is implicit on x86
967#ifdef GCC
968 __sync_synchronize(); // compiler fence
969#endif
970#ifdef ICC
971 __memory_barrier(); // compiler fence
972#endif
973  *const_cast<T volatile*>(addr) = v;
974}
975
976// cache line size on modern x86 processors (in bytes)
977size_t const cache_line_size = 64;
978
979// single-producer/single-consumer queue
980template<typename T>
981class spsc_queue
982{
983public:
984  spsc_queue()
985  {
986      node* n = new node;
987      n->next_ = 0;
988      overlap_bytes = 0;
989      tail_ = head1_ = head2_ = head3_ = first_= tail_copy_ = n;
990      count=0;
991  }
992
993  ~spsc_queue()
994  {
995      node* n = first_;
996      do
997      {
998          node* next = n->next_;
999          delete n;
1000          n = next;
1001      }
1002      while (n);
1003  }
1004
1005  void pass1()
1006  {
1007      node* n = alloc_node();
1008      n->next_ = 0;
1009      //do pass1
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.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);
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);
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}
Note: See TracBrowser for help on using the repository browser.