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

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

The Unicode category 'Nd' is in place and it is working.

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