1 #include <stdio.h> /* for fprintf etc */
2 #include <stdlib.h> /* for free etc */
3 #include <string.h> /* for strcmp */
6 #define DEFAULT_PACKAGE "org.tartarus.snowball.ext"
7 #define DEFAULT_BASE_CLASS "org.tartarus.snowball.SnowballProgram"
8 #define DEFAULT_AMONG_CLASS "org.tartarus.snowball.Among"
9 #define DEFAULT_STRING_CLASS "java.lang.StringBuilder"
10 #define DEFAULT_GO_PACKAGE "snowball"
11 #define DEFAULT_GO_SNOWBALL_RUNTIME "github.com/snowballstem/snowball/go"
13 #define DEFAULT_CS_NAMESPACE "Snowball"
14 #define DEFAULT_CS_BASE_CLASS "Stemmer"
15 #define DEFAULT_CS_AMONG_CLASS "Among"
16 #define DEFAULT_CS_STRING_CLASS "StringBuilder"
18 static int eq(const char * s1
, const char * s2
) {
19 return strcmp(s1
, s2
) == 0;
22 static void print_arglist(void) {
23 fprintf(stderr
, "Usage: snowball <file>... [options]\n\n"
24 "options are: [-o[utput] file]\n"
29 #ifndef DISABLE_CSHARP
33 #ifndef DISABLE_PYTHON
47 " [-n[ame] class name]\n"
48 " [-ep[refix] string]\n"
49 " [-vp[refix] string]\n"
50 " [-i[nclude] directory]\n"
51 " [-r[untime] path to runtime headers]\n"
52 " [-p[arentclassname] fully qualified parent class name]\n"
53 #if !defined(DISABLE_JAVA) || !defined(DISABLE_CSHARP)
54 " [-P[ackage] package name for stemmers]\n"
55 " [-S[tringclass] StringBuffer-compatible class]\n"
56 " [-a[mongclass] fully qualified name of the Among class]\n"
59 " [-gop[ackage] Go package name for stemmers]\n"
60 " [-gor[untime] Go snowball runtime package]\n"
66 static void check_lim(int i
, int argc
) {
68 fprintf(stderr
, "argument list is one short\n");
73 static FILE * get_output(symbol
* b
) {
75 FILE * output
= fopen(s
, "w");
77 fprintf(stderr
, "Can't open output %s\n", s
);
84 static int read_options(struct options
* o
, int argc
, char * argv
[]) {
92 o
->syntax_tree
= false;
93 o
->externals_prefix
= NULL
;
94 o
->variables_prefix
= 0;
96 o
->parent_class_name
= DEFAULT_BASE_CLASS
;
97 o
->string_class
= DEFAULT_STRING_CLASS
;
98 o
->among_class
= DEFAULT_AMONG_CLASS
;
99 o
->package
= DEFAULT_PACKAGE
;
100 o
->go_package
= DEFAULT_GO_PACKAGE
;
101 o
->go_snowball_runtime
= DEFAULT_GO_SNOWBALL_RUNTIME
;
103 o
->make_lang
= LANG_C
;
106 o
->encoding
= ENC_SINGLEBYTE
;
113 /* Non-option argument - shuffle down. */
114 argv
[new_argc
++] = s
;
119 if (eq(s
, "-o") || eq(s
, "-output")) {
121 o
->output_file
= argv
[i
++];
124 if (eq(s
, "-n") || eq(s
, "-name")) {
131 o
->make_lang
= LANG_JAVASCRIPT
;
132 o
->encoding
= ENC_WIDECHARS
;
137 if (eq(s
, "-rust")) {
138 o
->make_lang
= LANG_RUST
;
139 o
->encoding
= ENC_UTF8
;
145 o
->make_lang
= LANG_GO
;
146 o
->encoding
= ENC_UTF8
;
151 if (eq(s
, "-j") || eq(s
, "-java")) {
152 o
->make_lang
= LANG_JAVA
;
153 o
->encoding
= ENC_WIDECHARS
;
157 #ifndef DISABLE_CSHARP
158 if (eq(s
, "-cs") || eq(s
, "-csharp")) {
159 o
->make_lang
= LANG_CSHARP
;
160 o
->encoding
= ENC_WIDECHARS
;
161 o
->parent_class_name
= DEFAULT_CS_BASE_CLASS
;
162 o
->string_class
= DEFAULT_CS_STRING_CLASS
;
163 o
->among_class
= DEFAULT_CS_AMONG_CLASS
;
164 o
->package
= DEFAULT_CS_NAMESPACE
;
169 o
->make_lang
= LANG_CPLUSPLUS
;
172 #ifndef DISABLE_PYTHON
173 if (eq(s
, "-py") || eq(s
, "-python")) {
174 o
->make_lang
= LANG_PYTHON
;
175 o
->encoding
= ENC_WIDECHARS
;
179 if (eq(s
, "-w") || eq(s
, "-widechars")) {
180 o
->encoding
= ENC_WIDECHARS
;
183 if (eq(s
, "-s") || eq(s
, "-syntax")) {
184 o
->syntax_tree
= true;
187 if (eq(s
, "-ep") || eq(s
, "-eprefix")) {
189 o
->externals_prefix
= argv
[i
++];
192 if (eq(s
, "-vp") || eq(s
, "-vprefix")) {
194 o
->variables_prefix
= argv
[i
++];
197 if (eq(s
, "-i") || eq(s
, "-include")) {
202 symbol
* b
= add_s_to_b(0, argv
[i
++]);
203 b
= add_s_to_b(b
, "/");
204 p
->next
= 0; p
->b
= b
;
206 if (o
->includes
== 0) o
->includes
= p
; else
207 o
->includes_end
->next
= p
;
212 if (eq(s
, "-r") || eq(s
, "-runtime")) {
214 o
->runtime_path
= argv
[i
++];
217 if (eq(s
, "-u") || eq(s
, "-utf8")) {
218 o
->encoding
= ENC_UTF8
;
221 if (eq(s
, "-p") || eq(s
, "-parentclassname")) {
223 o
->parent_class_name
= argv
[i
++];
226 #if !defined(DISABLE_JAVA) || !defined(DISABLE_CSHARP)
227 if (eq(s
, "-P") || eq(s
, "-Package")) {
229 o
->package
= argv
[i
++];
232 if (eq(s
, "-S") || eq(s
, "-stringclass")) {
234 o
->string_class
= argv
[i
++];
237 if (eq(s
, "-a") || eq(s
, "-amongclass")) {
239 o
->among_class
= argv
[i
++];
244 if (eq(s
, "-gop") || eq(s
, "-gopackage")) {
246 o
->go_package
= argv
[i
++];
249 if (eq(s
, "-gor") || eq(s
, "-goruntime")) {
251 o
->go_snowball_runtime
= argv
[i
++];
255 fprintf(stderr
, "'%s' misplaced\n", s
);
260 fprintf(stderr
, "no source files specified\n");
263 argv
[new_argc
] = NULL
;
265 if (o
->make_lang
!= LANG_C
&& o
->make_lang
!= LANG_CPLUSPLUS
) {
266 if (o
->runtime_path
) {
267 fprintf(stderr
, "warning: -r/-runtime only meaningful for C and C++\n");
269 if (o
->externals_prefix
) {
270 fprintf(stderr
, "warning: -ep/-eprefix only meaningful for C and C++\n");
273 if (!o
->externals_prefix
) o
->externals_prefix
= "";
277 extern int main(int argc
, char * argv
[]) {
281 argc
= read_options(o
, argc
, argv
);
283 symbol
* filename
= add_s_to_b(0, argv
[1]);
285 symbol
* u
= get_input(filename
, &file
);
288 fprintf(stderr
, "Can't open input %s\n", argv
[1]);
292 struct tokeniser
* t
= create_tokeniser(u
, file
);
293 struct analyser
* a
= create_analyser(t
);
294 struct input
** next_input_ptr
= &(t
->next
);
295 a
->encoding
= t
->encoding
= o
->encoding
;
296 t
->includes
= o
->includes
;
297 /* If multiple source files are specified, set up the others to be
298 * read after the first in order, using the same mechanism as
300 for (i
= 2; i
!= argc
; ++i
) {
302 filename
= add_s_to_b(0, argv
[i
]);
303 u
= get_input(filename
, &file
);
306 fprintf(stderr
, "Can't open input %s\n", argv
[i
]);
314 next_input_ptr
= &(q
->next
);
316 *next_input_ptr
= NULL
;
318 if (t
->error_count
> 0) exit(1);
319 if (o
->syntax_tree
) print_program(a
);
321 if (!o
->syntax_tree
) {
322 struct generator
* g
;
324 const char * s
= o
->output_file
;
326 fprintf(stderr
, "Please include the -o option\n");
330 g
= create_generator(a
, o
);
331 if (o
->make_lang
== LANG_C
|| o
->make_lang
== LANG_CPLUSPLUS
) {
332 symbol
* b
= add_s_to_b(0, s
);
333 b
= add_s_to_b(b
, ".h");
334 o
->output_h
= get_output(b
);
335 b
[SIZE(b
) - 1] = 'c';
336 if (o
->make_lang
== LANG_CPLUSPLUS
) {
337 b
= add_s_to_b(b
, "c");
339 o
->output_src
= get_output(b
);
342 generate_program_c(g
);
343 fclose(o
->output_src
);
347 if (o
->make_lang
== LANG_JAVA
) {
348 symbol
* b
= add_s_to_b(0, s
);
349 b
= add_s_to_b(b
, ".java");
350 o
->output_src
= get_output(b
);
352 generate_program_java(g
);
353 fclose(o
->output_src
);
356 #ifndef DISABLE_PYTHON
357 if (o
->make_lang
== LANG_PYTHON
) {
358 symbol
* b
= add_s_to_b(0, s
);
359 b
= add_s_to_b(b
, ".py");
360 o
->output_src
= get_output(b
);
362 generate_program_python(g
);
363 fclose(o
->output_src
);
367 if (o
->make_lang
== LANG_JAVASCRIPT
) {
368 symbol
* b
= add_s_to_b(0, s
);
369 b
= add_s_to_b(b
, ".js");
370 o
->output_src
= get_output(b
);
372 generate_program_js(g
);
373 fclose(o
->output_src
);
376 #ifndef DISABLE_CSHARP
377 if (o
->make_lang
== LANG_CSHARP
) {
378 symbol
* b
= add_s_to_b(0, s
);
379 b
= add_s_to_b(b
, ".cs");
380 o
->output_src
= get_output(b
);
382 generate_program_csharp(g
);
383 fclose(o
->output_src
);
387 if (o
->make_lang
== LANG_RUST
) {
388 symbol
* b
= add_s_to_b(0, s
);
389 b
= add_s_to_b(b
, ".rs");
390 o
->output_src
= get_output(b
);
392 generate_program_rust(g
);
393 fclose(o
->output_src
);
397 if (o
->make_lang
== LANG_GO
) {
398 symbol
* b
= add_s_to_b(0, s
);
399 b
= add_s_to_b(b
, ".go");
400 o
->output_src
= get_output(b
);
402 generate_program_go(g
);
403 fclose(o
->output_src
);
412 { struct include
* p
= o
->includes
;
414 struct include
* q
= p
->next
;
415 lose_b(p
->b
); FREE(p
); p
= q
;
419 if (space_count
) fprintf(stderr
, "%d blocks unfreed\n", space_count
);