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

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

The framework for the unicode categories is in place. The static c++ code for each of the categories just needs to be placed into the stub unicode categories class.

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