source: proto/parabix2/pablo_template.cpp @ 1230

Last change on this file since 1230 was 1230, checked in by cameron, 8 years ago

Inline error reporting in parabix2_pablo.py

File size: 12.9 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include "../lib/lib_simd.h"
7
8#define BLOCK_SIZE (sizeof(SIMD_type) * 8)
9#define SEGMENT_BLOCKS 12
10#define BUFFER_SIZE (BLOCK_SIZE * SEGMENT_BLOCKS)
11#define OVERLAP_BUFSIZE (sizeof(SIMD_type))
12
13typedef long ScanBlock;
14typedef SIMD_type BytePack;
15typedef SIMD_type BitBlock;
16
17#include "../lib/carryQ.h"
18#include "xmldecl.h"
19#include "xml_error.c"
20#include "xmldecl.c"
21#include "namechars.h"
22
23#include "../lib/perflib/perfsec.h"
24#include "../lib/s2p.h"
25
26#include "TagMatcher.h"
27#include "LineColTracker.h"
28
29
30#ifdef BUFFER_PROFILING
31        BOM_Table * parser_timer;
32
33#elif CODE_CLOCKER
34        #define NUM_EVENTS 1
35        int Events[NUM_EVENTS] = {PAPI_TOT_CYC};
36        //int Events[NUM_EVENTS] = {PAPI_L2_DCM};
37        //int Events[NUM_EVENTS] = {PAPI_TOT_CYC, PAPI_BR_MSP};
38        int cal_size = 20;
39        CC * parser_timer = new CC(Events,NUM_EVENTS,cal_size);
40#else
41        void * parser_timer;
42#endif
43
44int block_base=0;
45int buffer_base=0;
46int buffer_last;
47char * source;
48
49
50LineColTracker tracker;
51
52static inline void ReportError(const char * error_msg, int error_pos_in_block) {
53  int error_line, error_column;
54  tracker.get_Line_and_Column(error_pos_in_block, error_line, error_column);
55  fprintf(stderr, "%s at line %i, column %i\n", error_msg, error_line, error_column);
56}
57
58class ErrorTracker {
59public:
60        ErrorTracker() { noted_pos_in_block = -1;}
61
62        inline void NoteError(const char * error_msg, BitBlock err_strm) {
63          int pos_in_block = count_forward_zeroes(err_strm);
64          if ((noted_pos_in_block == -1) || (noted_pos_in_block > pos_in_block)) {
65            noted_pos_in_block = pos_in_block;
66            noted_error = error_msg;
67          }
68        }
69
70        inline void If_Error_Report_First() {
71          if (noted_pos_in_block > -1) {
72                  int error_line, error_column;
73                  ReportError(noted_error, noted_pos_in_block);
74                  exit(-1);
75          }
76        }
77 
78private:
79  const char * noted_error;
80  int noted_pos_in_block;       
81};
82
83
84TagMatcher matcher;
85BitBlock EOF_mask = simd_const_1(1);
86
87ErrorTracker error_tracker;
88
89static inline int StreamScan(ScanBlock * stream, int blk_count, int ProcessPos(int)) {
90        int blk;
91        int block_pos = 0;
92
93        for (blk = 0; blk < blk_count; blk++) {
94                ScanBlock s = stream[blk];
95                while(s) {
96                        int code = (ProcessPos(cfzl(s) + block_pos));
97                        if (code) return code;
98                        s = s & (s-1);  // clear rightmost bit.
99                }
100                block_pos += 8 * sizeof(ScanBlock);
101        }
102        return 0;
103}
104
105
106
107static inline int NameStrt_check(int pos) {
108        int block_pos = block_base + pos;
109        if(XML_10_UTF8_NameStrt_bytes((unsigned char*)&source[block_pos]) == 0){
110              ReportError("name start error", pos);
111              exit(-1);
112        }
113        return 0;
114}
115
116static inline int Name_check(int pos) {
117        int block_pos = block_base + pos;
118        if(XML_10_UTF8_NameChar_bytes((unsigned char*)&source[block_pos]) == 0){
119              ReportError("name error", pos);
120              exit(-1);
121        }
122        return 0;
123}
124
125static inline int PIName_check(int pos) {
126        int block_pos = block_base + pos;
127        int file_pos = block_pos+buffer_base;
128        if (at_XxMmLll<ASCII>((unsigned char*)&source[block_pos]) && (source[block_pos+3]=='?' || source[block_pos+3]<= ' ')) {
129              // "<?xml" legal at start of file.
130              if ((file_pos == 2) && at_XmlDecl_start<ASCII>((unsigned char*)&source[0])) return 0;
131              ReportError("[Xx][Mm][Ll] illegal as PI name", pos);
132              exit(-1);
133        }
134        return 0;
135}
136
137static inline int CD_check(int pos) {
138        int block_pos = block_base + pos;
139        if (!at_CDATA1<ASCII>((unsigned char*)&source[block_pos])){
140              ReportError("CDATA error", pos);
141              exit(-1);
142        }
143        return 0;
144}
145
146static inline int GenRef_check(int pos) {
147        int block_pos = block_base + pos;
148        unsigned char* s = (unsigned char*)&source[block_pos];
149        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))){
150              ReportError("Undefined reference", pos);
151              exit(-1);
152        }
153        return 0;
154}
155
156static inline int HexRef_check(int pos) {
157        int block_pos = block_base + pos;
158        unsigned char* s = (unsigned char*)&source[block_pos];
159        int ch_val = 0;
160        while(at_HexDigit<ASCII>(s)){
161          ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
162          if (ch_val> 0x10FFFF ){
163            ReportError("Illegal character reference", pos);
164            exit(-1);
165          }
166          s++;
167        }
168        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
169          ReportError("Illegal character reference", pos);
170          exit(-1);
171        }
172        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
173          ReportError("Illegal XML 1.0 character reference", pos);
174          exit(-1);
175        }
176        return 0;
177}
178
179static inline int DecRef_check(int pos) {
180        int block_pos = block_base + pos;
181        unsigned char* s = (unsigned char*)&source[block_pos];
182        int ch_val = 0;
183        while(at_HexDigit<ASCII>(s)){
184          ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
185          if (ch_val> 0x10FFFF ){
186            ReportError("Illegal character reference", pos);
187            exit(-1);
188          }
189          s++;
190        }
191        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
192          ReportError("Illegal character reference", pos);
193          exit(-1);
194        }
195        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
196          ReportError("Illegal XML 1.0 character reference", pos);
197          exit(-1);
198        }
199        return 0;
200}
201
202static inline int AttRef_check(int pos) {
203        int block_pos = block_base + pos;
204        unsigned char* s = (unsigned char*)&source[block_pos];
205        int ch_val = 0;
206        if(s[0]=='#'){
207          s++;
208          if(s[0]=='x' || s[0]=='X'){
209            s++;
210            while(at_HexDigit<ASCII>(s)){
211              ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
212              s++;
213            }
214          }
215          else{
216            while(at_HexDigit<ASCII>(s)){
217              ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
218              s++;
219            }
220          }
221          if (ch_val==60){
222            ReportError("Attribute values contain '<' characters after reference expansion", pos);
223            exit(-1);
224          }
225        }
226        else if(at_Ref_lt<ASCII>(s)){
227          ReportError("Attribute values contain '<' characters after reference expansion", pos);
228          exit(-1);
229        }
230        return 0;
231}
232
233
234
235@global
236
237static inline void s2p_do_block(BytePack U8[], Basis_bits & basis_bits) {
238  s2p(U8[0], U8[1], U8[2], U8[3], U8[4], U8[5], U8[6], U8[7],
239        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);
240}
241
242static inline void s2p_do_final_block(BytePack U8[], Basis_bits & basis_bits, BitBlock EOF_mask) {
243  s2p_do_block(U8, basis_bits);
244  basis_bits.bit_0 = simd_and(basis_bits.bit_0, EOF_mask);
245  basis_bits.bit_1 = simd_and(basis_bits.bit_1, EOF_mask);
246  basis_bits.bit_2 = simd_and(basis_bits.bit_2, EOF_mask);
247  basis_bits.bit_3 = simd_and(basis_bits.bit_3, EOF_mask);
248  basis_bits.bit_4 = simd_and(basis_bits.bit_4, EOF_mask);
249  basis_bits.bit_5 = simd_and(basis_bits.bit_5, EOF_mask);
250  basis_bits.bit_6 = simd_and(basis_bits.bit_6, EOF_mask);
251  basis_bits.bit_7 = simd_and(basis_bits.bit_7, EOF_mask);
252}
253
254static inline void postprocess_do_block(Lex & lex, CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts, Check_streams & check_streams, int chars_avail){
255            tracker.StoreNewlines(lex.LF);
256
257                if (bitblock_has_bit(simd_or(check_streams.non_ascii_name_starts, check_streams.non_ascii_names))) {
258                  StreamScan((ScanBlock *) &check_streams.non_ascii_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), NameStrt_check);
259                  StreamScan((ScanBlock *) &check_streams.non_ascii_names, sizeof(BitBlock)/sizeof(ScanBlock), Name_check);
260                }
261
262                if (bitblock_has_bit(ctCDPI_Callouts.PI_name_starts)){
263                  StreamScan((ScanBlock *) &ctCDPI_Callouts.PI_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), PIName_check);
264                }
265
266                if (bitblock_has_bit(ctCDPI_Callouts.CD_starts)){
267                  StreamScan((ScanBlock *) &ctCDPI_Callouts.CD_starts, sizeof(BitBlock)/sizeof(ScanBlock), CD_check);
268                }
269
270                if (bitblock_has_bit(ref_Callouts.GenRef_starts)){
271                  StreamScan((ScanBlock *) &ref_Callouts.GenRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), GenRef_check);
272                }
273
274                if (bitblock_has_bit(ref_Callouts.DecRef_starts)){
275                  StreamScan((ScanBlock *) &ref_Callouts.DecRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), DecRef_check);
276                }
277
278                if (bitblock_has_bit(ref_Callouts.HexRef_starts)){
279                  StreamScan((ScanBlock *) &ref_Callouts.HexRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), HexRef_check);
280                }
281
282                if (bitblock_has_bit(check_streams.att_refs)){
283                  StreamScan((ScanBlock *) &check_streams.att_refs, sizeof(BitBlock)/sizeof(ScanBlock), AttRef_check);
284                }
285
286                error_tracker.If_Error_Report_First();
287
288                matcher.store_streams(check_streams.tag_marks, check_streams.name_follows, check_streams.misc_mask, chars_avail);
289                tracker.AdvanceBlock();
290}
291
292void do_process(FILE *infile, FILE *outfile) {
293
294@decl
295
296  int buf_pos = 0;
297  int block_pos = 0;
298  int errpos = 0;
299  int chars_avail = 0;
300  int check_pos = 0;
301  int chars_read = 0;
302  BytePack buf[(BUFFER_SIZE+BLOCK_SIZE+OVERLAP_BUFSIZE*2)/sizeof(SIMD_type)];
303
304  char * srcbuf = ((char *) buf) + OVERLAP_BUFSIZE;
305  buffer_base = buf_pos;
306  source = srcbuf;
307
308  chars_read = fread((void *)srcbuf, 1, BUFFER_SIZE + OVERLAP_BUFSIZE, infile);
309  chars_avail = chars_read;
310  if (chars_avail > BUFFER_SIZE) chars_avail = BUFFER_SIZE;
311
312  matcher.setSrc(srcbuf);
313
314  if(chars_read<4){
315    fprintf(stderr,"File is too short. Not well formed.\n");
316    exit(-1);
317  }
318
319  Entity_Info * e = new Entity_Info;
320  e->AnalyzeSignature((unsigned char *)srcbuf);
321
322  if (e->code_unit_base == ASCII) {
323
324    XML_Decl_Parser<ASCII> decl_parser((unsigned char *)srcbuf);
325
326    decl_parser.ReadXMLInfo(*e);
327
328    if (e->code_unit_size != SingleByte || (e->has_encoding_decl && (!at_UTF_8(e->encoding)))){
329        fprintf(stderr,"Sorry, this xmlwf demo only works for UTF-8.\n");
330        exit(-1);
331    }
332  }
333  else {
334    fprintf(stderr,"Sorry, this xmlwf demo does not process EBCDIC.\n");
335        exit(-1);
336  }
337
338  if (e->content_start != 0) {
339        memmove(&srcbuf[0], &srcbuf[e->content_start], chars_read - e->content_start);
340        buf_pos = e->content_start;
341        if (chars_avail == BUFFER_SIZE) {
342                chars_read = chars_read - e->content_start +
343                             fread(&srcbuf[chars_read-e->content_start], 1, e->content_start, infile);
344                chars_avail = chars_read;
345                if (chars_avail > BUFFER_SIZE) chars_avail = BUFFER_SIZE;
346        }
347        else {
348          chars_read -=e->content_start;
349          chars_avail -=e->content_start;
350        }
351  }
352
353@stream_stmts
354
355/* Full Buffers */
356
357    while (chars_avail == BUFFER_SIZE) {
358      PERF_SEC_START(parser_timer);
359      for (int blk = 0; blk < SEGMENT_BLOCKS; blk++) {
360          block_base = blk*BLOCK_SIZE;
361          s2p_do_block((BytePack *) &srcbuf[block_base], basis_bits);
362          @block_stmts
363          postprocess_do_block(lex, ctCDPI_Callouts, ref_Callouts, check_streams, chars_avail);
364      }
365      matcher.StreamScan(chars_avail);
366      matcher.Advance_buffer();
367      tracker.Advance_buffer();
368      PERF_SEC_END(parser_timer, chars_avail);
369           
370      int bytes_left = chars_read - chars_avail;
371      memmove(srcbuf, &srcbuf[BUFFER_SIZE], bytes_left);
372      chars_read = fread(&srcbuf[bytes_left],1, BUFFER_SIZE + OVERLAP_BUFSIZE - bytes_left, infile) + bytes_left;
373      chars_avail = chars_read;
374      if (chars_avail > BUFFER_SIZE) chars_avail = BUFFER_SIZE;
375      buf_pos += chars_avail;
376      buffer_base = buf_pos;
377    }
378/* Final Partial Buffer */
379    PERF_SEC_START(parser_timer);
380
381    block_pos = 0;
382    int remaining = chars_avail;
383/* Full Blocks */
384    while (remaining >= BLOCK_SIZE) {
385          block_base = block_pos;
386          s2p_do_block((BytePack *) &srcbuf[block_pos], basis_bits);
387          @block_stmts
388          postprocess_do_block(lex, ctCDPI_Callouts, ref_Callouts, check_streams, chars_avail);
389          block_pos += BLOCK_SIZE;
390          remaining -= BLOCK_SIZE;
391    }
392    block_base = block_pos;
393    if (remaining > 0 || @any_carry) {
394          EOF_mask = sisd_srl(simd_const_1(1),sisd_from_int(BLOCK_SIZE-remaining));
395          s2p_do_final_block((BytePack *) &srcbuf[block_pos], basis_bits, EOF_mask);
396          @final_block_stmts
397          postprocess_do_block(lex, ctCDPI_Callouts, ref_Callouts, check_streams, chars_avail);
398    }
399    buf_pos += chars_avail;
400    buffer_base = buf_pos;
401
402    matcher.StreamScan(chars_avail);
403    matcher.Advance_buffer();
404    tracker.Advance_buffer();
405
406
407    PERF_SEC_END(parser_timer, chars_avail);
408    if (matcher.depth != 0) {
409      fprintf(stderr, "tag matching error (depth %i) at position %i\n", matcher.depth, buffer_base);
410      exit(-1);
411    }
412}
413
414
415
416int
417main(int argc, char * argv[]) {
418        char * infilename, * outfilename;
419        FILE *infile, *outfile;
420        struct stat fileinfo;
421
422        if (argc < 2) {
423                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
424                exit(-1);
425        }
426
427        infilename = argv[1];
428        stat(infilename, &fileinfo);
429        infile = fopen(infilename, "rb");
430        if (!infile) {
431                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
432                exit(-1);
433        }
434
435        if (argc < 3) outfile = stdout;
436        else {
437                outfilename = argv[2];
438                outfile = fopen(outfilename, "wb");
439                if (!outfile) {
440                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
441                        exit(-1);
442                }
443        }
444
445//      PERF_SEC_BIND(1);
446
447        PERF_SEC_INIT(parser_timer);
448
449        do_process(infile, outfile);
450
451        PERF_SEC_DUMP(parser_timer);
452
453        PERF_SEC_DESTROY(parser_timer);
454
455        fclose(infile);
456        fclose(outfile);
457        return(0);
458}
Note: See TracBrowser for help on using the repository browser.