source: proto/xmlschema/symtab_hash_template.cpp @ 2317

Last change on this file since 2317 was 2219, checked in by shiyangy, 7 years ago

project checkin

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