Skip to content

Commit 614f851

Browse files
committed
bake ragel.tmpl into re2r executable
this allows a systemwide install without having to look around for the template file. also add option -t which allows the user to specify a custom template file.
1 parent b6a27bf commit 614f851

File tree

4 files changed

+139
-9
lines changed

4 files changed

+139
-9
lines changed

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ OBJS = lexer.o y.tab.o sblist.o sblist_pop.o hsearch.o tokens.o
77

88
-include config.mak
99

10+
HOSTCC ?= $(CC)
11+
1012
all: re2r re2r_test
1113

1214
lexer.c: y.tab.h
13-
main.c: y.tab.h
15+
main.c: y.tab.h template.h
1416
tokens.c: y.tab.h
1517

18+
template.h: file2hdr ragel.tmpl
19+
./file2hdr ragel.tmpl > template.h
20+
21+
file2hdr: file2hdr.c
22+
$(HOSTCC) $(HOSTCFLAGS) $< -o $@
23+
1624
y.tab.h: y.tab.c
1725

1826
y.tab.c: ere.y

README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ EXAMPLES
1313
ipv4 [0-9]+[.][0-9]+[.][0-9]+[.][0-9]+
1414

1515
OPTIONS
16+
-t template.txt: use template.txt instead of builtin (ragel.tmpl)
1617
-o outfile: write output to outfile instead of stdout
1718

1819
BUGS

file2hdr.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* (C) 2019 rofl0r */
2+
/* released into the public domain, or at your choice 0BSD or WTFPL */
3+
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <ctype.h>
8+
#include <unistd.h>
9+
10+
static int usage() {
11+
printf( "file2hdr - converts a file into a C string\n"
12+
"the output is written to stdout.\n"
13+
"usage: file2hdr filename\n"
14+
);
15+
return 1;
16+
}
17+
18+
static int isprintable(int ch) {
19+
#define PRINTABLE " ;,:.^-+=*/%|&[](){}<>#_"
20+
return ch > 0 && (isdigit(ch) || isalpha(ch) || strchr(PRINTABLE, ch));
21+
}
22+
23+
static int escape_char(int ch, char buf[5], int *dirty) {
24+
int len = 0;
25+
*dirty = 0;
26+
buf[len++] = '\\';
27+
switch(ch) {
28+
case '\a': /* 0x07 */
29+
buf[len++] = 'a'; break;
30+
case '\b': /* 0x08 */
31+
buf[len++] = 'b'; break;
32+
case '\t': /* 0x09 */
33+
buf[len++] = 't'; break;
34+
case '\n': /* 0x0a */
35+
buf[len++] = 'n'; break;
36+
case '\v': /* 0x0b */
37+
buf[len++] = 'v'; break;
38+
case '\f': /* 0x0c */
39+
buf[len++] = 'f'; break;
40+
case '\r': /* 0x0d */
41+
buf[len++] = 'r'; break;
42+
case '\"': /* 0x22 */
43+
buf[len++] = '\"'; break;
44+
case '\'': /* 0x27 */
45+
buf[len++] = '\''; break;
46+
case '\?': /* 0x3f */
47+
buf[len++] = '\?'; break;
48+
case '\\': /* 0x5c */
49+
buf[len++] = '\\'; break;
50+
default:
51+
if(isprintable(ch)) buf[0] = ch;
52+
else {
53+
if (ch <= 077) *dirty = 1;
54+
len += sprintf(buf+len, "%o", ch);
55+
}
56+
}
57+
buf[len] = 0;
58+
return len;
59+
}
60+
61+
int main(int argc, char** argv) {
62+
int f_arg = 1;
63+
unsigned cpl = 77;
64+
if(argc-1 < f_arg) return usage();
65+
FILE *f = fopen(argv[f_arg], "r");
66+
if(!f) { perror("fopen"); return 1; }
67+
{
68+
off_t end, start = ftello(f);
69+
size_t insize, outsize;
70+
fseeko(f, 0, SEEK_END);
71+
end = ftello(f);
72+
fseeko(f, start, SEEK_SET);
73+
insize = end - start;
74+
outsize = insize;
75+
76+
char *p = strrchr(argv[f_arg], '/');
77+
if(!p) p = argv[f_arg];
78+
else p++;
79+
char *fn = strdup(p);
80+
p = fn;
81+
while(*p) { if(*p == '.') *p = '_'; ++p; }
82+
printf( "const struct { unsigned clen, ulen;\n"
83+
"const unsigned char data[]; } %s = { %zu, %zu,\n",
84+
fn, outsize, insize);
85+
free(fn);
86+
}
87+
88+
int ch, dirty;
89+
unsigned cnt = 0;
90+
while((ch = fgetc(f)) != EOF) {
91+
if(cnt == 0) { printf("\""); dirty = 0; }
92+
char buf[5];
93+
int cdirty;
94+
cnt += escape_char(ch, buf, &cdirty);
95+
// dirty and cdirty: ok
96+
// dirty and not cdirty: ok if buf[0] not in '0'..'7'
97+
if(dirty && !cdirty && buf[0] >= '0' && buf[0] <= '7') {
98+
printf("\"\"");
99+
cnt += 2;
100+
}
101+
dirty = cdirty;
102+
printf("%s", buf);
103+
if(cnt >= cpl) {
104+
printf("\"\n");
105+
cnt = 0;
106+
}
107+
}
108+
if(cnt) printf("\"\n");
109+
printf("};\n");
110+
fclose(f);
111+
return 0;
112+
}
113+

main.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "sblist.h"
1010
#include "hsearch.h"
1111
#include "tokens.h"
12+
#include "template.h"
1213

1314
extern int yyerror(const char*);
1415

@@ -94,8 +95,7 @@ static void dump_parents(char *buf, sblist *tokens, const char* org_regex) {
9495
fprintf(yyout, "%s", replace(buf, "%PARENTARRAY%", parbuf));
9596
}
9697

97-
static void dump_ragel_parser(const char *machinename, const char* org_regex, const char* org_regex_end, int *maxgroups) {
98-
FILE *f = fopen("ragel.tmpl", "r");
98+
static void dump_ragel_parser(FILE *f, const char *machinename, const char* org_regex, const char* org_regex_end, int *maxgroups) {
9999
char buf[4096];
100100
int groups, cgroup = 0;
101101
sblist *tokens = lex_and_transform(org_regex, org_regex_end);
@@ -142,7 +142,6 @@ static void dump_ragel_parser(const char *machinename, const char* org_regex, co
142142
fprintf(yyout, "%s", buf);
143143
}
144144
}
145-
fclose(f);
146145
sblist_free(group_order);
147146
sblist_free(tokens);
148147
}
@@ -160,7 +159,9 @@ static int usage() {
160159
"EXAMPLES\n"
161160
"\tipv4 [0-9]+[.][0-9]+[.][0-9]+[.][0-9]+\n\n"
162161
"OPTIONS\n"
163-
"\t-o outfile: write output to outfile instead of stdout\n\n"
162+
"\t-t template.txt: use template.txt instead of builtin (ragel.tmpl)\n"
163+
"\t-o outfile: write output to outfile instead of stdout\n"
164+
"\n"
164165
"BUGS\n"
165166
"\tPOSIX collation, equivalence, and character classes support is not implemented\n"
166167
"\tyou can replace character classes like [[:digit:]] with [0-9] using some sort\n"
@@ -174,20 +175,23 @@ int main(int argc, char**argv) {
174175
extern int yydebug;
175176
yydebug = 1;
176177
#endif
177-
char buf[4096];
178+
char buf[4096], *template = 0;
178179
size_t lineno = 0;
179180
yyin = stdin;
180181
yyout = stdout;
181182
int maxgroups = 0, err = 0, c;
182183
struct htab *remap = htab_create(32);
183-
while((c = getopt(argc, argv, "o:")) != EOF) switch(c) {
184+
while((c = getopt(argc, argv, "t:o:")) != EOF) switch(c) {
184185
case 'o':
185186
yyout = fopen(optarg, "w");
186187
if(!yyout) {
187188
perror("open");
188189
return 1;
189190
}
190191
break;
192+
case 't':
193+
template = optarg;
194+
break;
191195
default:
192196
return usage();
193197
}
@@ -211,9 +215,13 @@ int main(int argc, char**argv) {
211215
}
212216
lex_init(p, pe, LEXFLAG_SILENT);
213217
if(yyparse() == 0) {
214-
htab_insert(remap, strdup(p), HTV_P(strdup(buf)));
215218
/* syntax check OK */
216-
dump_ragel_parser(buf, p, pe, &maxgroups);
219+
htab_insert(remap, strdup(p), HTV_P(strdup(buf)));
220+
FILE *f;
221+
if(template) f = fopen(template, "r");
222+
else f = fmemopen((void*)ragel_tmpl.data, ragel_tmpl.ulen, "r");
223+
dump_ragel_parser(f, buf, p, pe, &maxgroups);
224+
fclose(f);
217225
} else {
218226
++err;
219227
size_t errpos = lex_errpos();

0 commit comments

Comments
 (0)