source: icGREP/icgrep-devel/icgrep/icgrep.cpp @ 3969

Last change on this file since 3969 was 3969, checked in by daled, 5 years ago

A change to the way unicode categories are handled. This version supports the unicode categlry 'Nd'.

File size: 12.5 KB
Line 
1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "icgrep.h"
8
9#include "utf_encoding.h"
10#include "re_compiler.h"
11
12#include <fstream>
13#include <sstream>
14#include <iostream>
15#include <string>
16#include <stdint.h>
17
18#define assert_0_error(errkind, errstrm)
19
20// XMLWF application headers and definitions
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <errno.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27
28#include <simd-lib/bitblock.hpp>
29#include <simd-lib/carryQ.hpp>
30#include <simd-lib/pabloSupport.hpp>
31#include <simd-lib/s2p.hpp>
32#include <simd-lib/buffer.hpp>
33#include <simd-lib/bitblock_iterator.hpp>
34
35#define SEGMENT_BLOCKS 15
36#define SEGMENT_SIZE (BLOCK_SIZE * SEGMENT_BLOCKS)
37
38#define BUFFER_SEGMENTS 15
39#define BUFFER_SIZE (BUFFER_SEGMENTS * SEGMENT_SIZE)
40
41#define BitBlock_declare(name)  BitBlock name
42
43#define ubitblock_declare(name, n) \
44  ubitblock name[n];\
45  do {int i;\
46      for (i = 0; i < n; i++) name[i]._128 = simd<1>::constant<0>();\
47     }\
48  while (0)
49
50BitBlock EOF_mask = simd<1>::constant<1>();
51
52Nd* mNd = NULL;
53
54struct Output {
55    BitBlock matches;
56    BitBlock LF;
57};
58
59/*
60struct Basis_bits {
61    BitBlock bit_0;
62    BitBlock bit_1;
63    BitBlock bit_2;
64    BitBlock bit_3;
65    BitBlock bit_4;
66    BitBlock bit_5;
67    BitBlock bit_6;
68    BitBlock bit_7;
69};
70*/
71
72#include <simd-lib/transpose.hpp>
73
74using namespace std;
75
76typedef void (*process_block_fcn)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output);
77
78void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block);
79BitBlock get_category(Basis_bits &basis_bits, const char* category);
80
81int main(int argc, char *argv[])
82{
83    char * inregex, * fileregex, * infilename, * outfilename;
84    FILE *infile, *outfile, *regexfile;
85
86    int opt_code;
87    int count_only_option = 0;
88    int print_version_option = 0;
89    int regex_from_file_option = 0;
90    int ascii_only_option = 0;
91
92    int compile_time_option = 0;
93
94    unsigned long long cycles = 0;
95    double timer = 0;
96
97    long lSize = 0;
98
99    size_t result;
100
101    while ((opt_code = getopt(argc, argv, "cvfta")) != -1)
102    {
103        switch (opt_code)
104        {
105        case 'c':
106            count_only_option = 1;
107            break;
108        case 'v':
109            print_version_option = 1;
110            break;
111        case 'f':
112            regex_from_file_option = 1;
113            break;
114        case 't':
115            compile_time_option = 1;
116            break;
117        case 'a':
118            ascii_only_option = 1;
119            break;
120        case '?':
121            break;
122        default:
123            printf ("Invalid option: %c\n", opt_code);
124            printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
125                    exit(-1);
126        }
127    }
128
129    if (optind >= argc)
130    {
131        printf ("Too few arguments\n");
132        printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
133        exit(-1);
134    }
135
136    inregex = argv[optind++];
137    if (inregex == 0)
138    {
139        fprintf(stderr, "Error: cannot read the regular expression.\n");
140        exit(-1);
141    }
142
143    if (regex_from_file_option)
144    {
145        regexfile = fopen(inregex, "rb");
146        if (!regexfile){
147            fprintf(stderr, "Error: cannot open %s for processing.\n", inregex);
148            exit(-1);
149        }
150
151        fseek (regexfile , 0 , SEEK_END);
152        lSize = ftell (regexfile);
153        rewind (regexfile);
154
155        fileregex = (char*) malloc (sizeof(char)*lSize);
156        if (fileregex == NULL) {fputs ("Memory error",stderr); exit (2);}
157
158        result = fread (fileregex, 1, lSize, regexfile);
159        if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
160        fclose(regexfile);
161
162        if (fileregex[lSize - 1] == '\n') fileregex[lSize - 1] = '\0';
163    }
164
165    infilename = argv[optind++];
166    infile = fopen(infilename, "rb");
167    if (!infile) {
168        fprintf(stderr, "Error: cannot open %s for processing.\n", infilename);
169        exit(-1);
170    }
171
172    if (optind >= argc) outfile = stdout;
173    else
174    {
175        outfilename = argv[optind++];
176        if (optind != argc)
177        {
178            printf ("Too many arguments\n");
179            printf("Usage: %s [-c] [-v] [-f] [-t] [-a] <regex|regexfile> <inputfile> [<outputfile>]\n", argv[0]);
180            exit(-1);
181        }
182        outfile = fopen(outfilename, "wb");
183        if (!outfile)
184        {
185            fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
186            exit(-1);
187        }
188    }
189
190    if (print_version_option)
191    {
192        fprintf(outfile, "Parabix icgrep implementation: April 2014\n");
193    }
194
195    UTF_Encoding encoding;
196    encoding.setName("UTF-8");
197    encoding.setBits(8);
198    encoding.setMask(0xFF);
199
200    RE_Compiler* re_compiler = new RE_Compiler();
201    if (compile_time_option)
202    {
203        cycles = get_hrcycles();
204        timer = getElapsedTime();
205    }
206    LLVM_Gen_RetVal llvm_codegen = re_compiler->compile(compile_time_option,
207                                                        ascii_only_option,
208                                                        "basis_bits.bit_",
209                                                        "temp",
210                                                        encoding ,
211                                                        (regex_from_file_option ? fileregex : inregex));
212
213    if (compile_time_option)
214    {
215        cycles = get_hrcycles() - cycles;
216        timer = getElapsedTime() - timer;
217        std::cout << "Total compile time - cycles:       " << cycles << std::endl;
218        std::cout << "Total compile time - milliseconds: " << timer << std::endl;
219    }
220
221    if (llvm_codegen.process_block_fptr != 0)
222    {
223        void (*FP)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output) = (void (*)(const Basis_bits &basis_bits, BitBlock carry_q[], Output &output))(void*)llvm_codegen.process_block_fptr;
224        do_process(infile, outfile, count_only_option, llvm_codegen.carry_q_size, FP);
225    }
226
227    delete re_compiler;
228    fclose(infile);
229    fclose(outfile);
230    if (regex_from_file_option) free(fileregex);
231
232    return 0;
233}
234
235void do_process(FILE *infile, FILE *outfile, int count_only_option, int carry_count, process_block_fcn process_block) {
236
237    struct Basis_bits basis_bits;
238    struct Output output;
239
240    BitBlock carry_q[carry_count];
241    memset (carry_q, 0, sizeof(BitBlock) * carry_count);
242
243    BitBlock match_vector = simd<1>::constant<0>();
244    int match_count=0;
245    int blk = 0;
246    int block_base  = 0;
247    int block_pos   = 0;
248    int buffer_pos  = 0;
249    int chars_avail = 0;
250    int chars_read  = 0;
251
252    int line_start = 0;
253    int line_end = 0;
254    int match_pos = 0;
255    int line_no = 0;
256
257    int counter = 0;
258
259    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> LF_scanner;
260    BitStreamScanner<BitBlock, uint64_t, uint64_t, SEGMENT_BLOCKS> match_scanner;
261    ATTRIBUTE_SIMD_ALIGN char src_buffer[SEGMENT_SIZE];
262
263    chars_read = fread((void *)&src_buffer[0], 1, SEGMENT_SIZE, infile);
264    chars_avail = chars_read;
265    if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
266
267//////////////////////////////////////////////////////////////////////////////////////////
268// Full Segments
269//////////////////////////////////////////////////////////////////////////////////////////
270
271    while (chars_avail >= SEGMENT_SIZE) {
272
273        LF_scanner.init();
274        match_scanner.init();
275
276        counter++;
277
278        for (blk = 0; blk < SEGMENT_BLOCKS; blk++) {
279            block_base = blk*BLOCK_SIZE;
280            s2p_do_block((BytePack *) &src_buffer[block_base], basis_bits);
281            process_block(basis_bits, carry_q, output);
282
283            LF_scanner.load_block(output.LF, blk);
284            match_scanner.load_block(output.matches, blk);
285            if (count_only_option){
286                if (bitblock::any(output.matches))
287                {
288                    if (bitblock::any(simd_and(match_vector, output.matches))){
289                        match_count += bitblock::popcount(match_vector);
290                        match_vector = output.matches;
291                    }
292                    else
293                    {
294                        match_vector = simd_or(match_vector, output.matches);
295                    }
296                }
297            }
298        }
299
300        int copy_back_pos = 0;
301
302
303        if (LF_scanner.count() > 0) {
304            copy_back_pos = LF_scanner.get_final_pos() + 1;
305            memset (carry_q, 0, sizeof(BitBlock) * carry_count);
306        }
307        else {
308            copy_back_pos =  SEGMENT_SIZE;
309        }
310
311        int  copy_back_size = SEGMENT_SIZE - copy_back_pos;
312
313        if (!count_only_option) {
314            line_start = 0;
315
316            while (match_scanner.has_next()) {
317                match_pos = match_scanner.scan_to_next();
318                line_end = LF_scanner.scan_to_next();
319                while (line_end < match_pos) {
320                    line_start = line_end+1;
321                    line_no++;
322                    line_end = LF_scanner.scan_to_next();
323                }
324                fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
325                line_start = line_end+1;
326                line_no++;
327            }
328            while (LF_scanner.has_next()) {
329                line_end = LF_scanner.scan_to_next();
330                line_no++;
331            }
332
333        }
334
335        memmove(&src_buffer[0], &src_buffer[copy_back_pos], copy_back_size);
336
337        //Do another read.
338        chars_read = fread(&src_buffer[copy_back_size], 1, copy_back_pos, infile);
339        chars_avail = chars_read + copy_back_size;
340        if (chars_avail >= SEGMENT_SIZE) chars_avail = SEGMENT_SIZE;
341        buffer_pos += chars_avail;
342    }
343
344
345//////////////////////////////////////////////////////////////////////////////////////////
346// For the Final Partial Segment.
347//////////////////////////////////////////////////////////////////////////////////////////
348
349    block_pos = 0;
350    int remaining = chars_avail;
351
352    LF_scanner.init();
353    match_scanner.init();
354
355    /* Full Blocks */
356    blk = 0;
357    while (remaining >= BLOCK_SIZE) {
358        block_base = block_pos;
359        s2p_do_block((BytePack *) &src_buffer[block_pos], basis_bits);
360        process_block(basis_bits, carry_q, output);
361
362        LF_scanner.load_block(output.LF, blk);
363        match_scanner.load_block(output.matches, blk);
364        if (count_only_option)
365        {
366            if (bitblock::any(output.matches))
367            {
368                if (bitblock::any(simd_and(match_vector, output.matches)))
369                {
370                    match_count += bitblock::popcount(match_vector);
371                    match_vector = output.matches;
372                }
373                else
374                {
375                    match_vector = simd_or(match_vector, output.matches);
376                }
377            }
378        }
379
380        block_pos += BLOCK_SIZE;
381        remaining -= BLOCK_SIZE;
382        blk++;
383    }
384    block_base = block_pos;
385
386    //For the last partial block, or for any carry.
387    EOF_mask = bitblock::srl(simd<1>::constant<1>(), convert(BLOCK_SIZE-remaining));
388    s2p_do_final_block((BytePack *) &src_buffer[block_pos], basis_bits, EOF_mask);
389    process_block(basis_bits, carry_q, output);
390
391    if (count_only_option)
392    {
393        match_count += bitblock::popcount(match_vector);
394        if (bitblock::any(output.matches))
395        {
396            match_count += bitblock::popcount(output.matches);
397        }
398        fprintf(outfile, "Matching Lines:%d\n", match_count);
399    }
400    else
401    {
402        LF_scanner.load_block(output.LF, blk);
403        match_scanner.load_block(output.matches, blk);
404        blk++;
405        for (int i = blk; i < SEGMENT_BLOCKS; i++)
406        {
407            LF_scanner.load_block(simd<1>::constant<0>(), i);
408            match_scanner.load_block(simd<1>::constant<0>(), i);
409        }
410        line_start = 0;
411        while (match_scanner.has_next())
412        {
413            match_pos = match_scanner.scan_to_next();
414            line_end = LF_scanner.scan_to_next();
415            while(line_end < match_pos)
416            {
417                line_start = line_end + 1;
418                line_no++;
419                line_end = LF_scanner.scan_to_next();
420            }
421            fwrite(&src_buffer[line_start], 1, line_end - line_start + 1, outfile);
422            line_start = line_end + 1;
423            line_no++;
424        }
425        while(LF_scanner.has_next())
426        {
427            line_end = LF_scanner.scan_to_next();
428            line_no++;
429        }
430    }
431
432    buffer_pos += chars_avail;
433}
434
435
436
Note: See TracBrowser for help on using the repository browser.