mittens 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +4 -4
  5. data/lib/mittens/version.rb +1 -1
  6. data/mittens.gemspec +1 -1
  7. data/vendor/snowball/.github/workflows/ci.yml +216 -0
  8. data/vendor/snowball/CONTRIBUTING.rst +111 -62
  9. data/vendor/snowball/GNUmakefile +194 -136
  10. data/vendor/snowball/NEWS +798 -3
  11. data/vendor/snowball/README.rst +50 -1
  12. data/vendor/snowball/ada/src/stemmer.adb +25 -13
  13. data/vendor/snowball/ada/src/stemmer.ads +9 -9
  14. data/vendor/snowball/ada/stemmer_config.gpr +7 -7
  15. data/vendor/snowball/algorithms/basque.sbl +4 -19
  16. data/vendor/snowball/algorithms/catalan.sbl +2 -9
  17. data/vendor/snowball/algorithms/danish.sbl +1 -1
  18. data/vendor/snowball/algorithms/dutch.sbl +284 -122
  19. data/vendor/snowball/algorithms/dutch_porter.sbl +178 -0
  20. data/vendor/snowball/algorithms/english.sbl +52 -37
  21. data/vendor/snowball/algorithms/esperanto.sbl +157 -0
  22. data/vendor/snowball/algorithms/estonian.sbl +269 -0
  23. data/vendor/snowball/algorithms/finnish.sbl +2 -3
  24. data/vendor/snowball/algorithms/french.sbl +42 -16
  25. data/vendor/snowball/algorithms/german.sbl +35 -14
  26. data/vendor/snowball/algorithms/greek.sbl +76 -76
  27. data/vendor/snowball/algorithms/hungarian.sbl +8 -6
  28. data/vendor/snowball/algorithms/indonesian.sbl +14 -8
  29. data/vendor/snowball/algorithms/italian.sbl +11 -21
  30. data/vendor/snowball/algorithms/lithuanian.sbl +36 -37
  31. data/vendor/snowball/algorithms/lovins.sbl +0 -1
  32. data/vendor/snowball/algorithms/nepali.sbl +138 -37
  33. data/vendor/snowball/algorithms/norwegian.sbl +19 -5
  34. data/vendor/snowball/algorithms/porter.sbl +2 -2
  35. data/vendor/snowball/algorithms/portuguese.sbl +9 -13
  36. data/vendor/snowball/algorithms/romanian.sbl +17 -4
  37. data/vendor/snowball/algorithms/serbian.sbl +467 -468
  38. data/vendor/snowball/algorithms/spanish.sbl +5 -7
  39. data/vendor/snowball/algorithms/swedish.sbl +60 -6
  40. data/vendor/snowball/algorithms/tamil.sbl +207 -176
  41. data/vendor/snowball/algorithms/turkish.sbl +461 -445
  42. data/vendor/snowball/algorithms/yiddish.sbl +36 -38
  43. data/vendor/snowball/compiler/analyser.c +445 -192
  44. data/vendor/snowball/compiler/driver.c +109 -101
  45. data/vendor/snowball/compiler/generator.c +853 -464
  46. data/vendor/snowball/compiler/generator_ada.c +404 -366
  47. data/vendor/snowball/compiler/generator_csharp.c +297 -260
  48. data/vendor/snowball/compiler/generator_go.c +323 -254
  49. data/vendor/snowball/compiler/generator_java.c +326 -252
  50. data/vendor/snowball/compiler/generator_js.c +362 -252
  51. data/vendor/snowball/compiler/generator_pascal.c +349 -197
  52. data/vendor/snowball/compiler/generator_python.c +257 -240
  53. data/vendor/snowball/compiler/generator_rust.c +423 -251
  54. data/vendor/snowball/compiler/header.h +117 -71
  55. data/vendor/snowball/compiler/space.c +137 -68
  56. data/vendor/snowball/compiler/syswords.h +2 -2
  57. data/vendor/snowball/compiler/tokeniser.c +125 -107
  58. data/vendor/snowball/csharp/Snowball/Among.cs +14 -14
  59. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +7 -7
  60. data/vendor/snowball/csharp/Snowball/Stemmer.cs +57 -37
  61. data/vendor/snowball/csharp/Stemwords/App.config +2 -2
  62. data/vendor/snowball/csharp/Stemwords/Program.cs +16 -12
  63. data/vendor/snowball/doc/libstemmer_c_README +7 -4
  64. data/vendor/snowball/doc/libstemmer_csharp_README +4 -1
  65. data/vendor/snowball/doc/libstemmer_java_README +12 -1
  66. data/vendor/snowball/doc/libstemmer_js_README +6 -4
  67. data/vendor/snowball/doc/libstemmer_python_README +9 -4
  68. data/vendor/snowball/examples/stemwords.c +12 -12
  69. data/vendor/snowball/go/env.go +107 -31
  70. data/vendor/snowball/go/util.go +0 -4
  71. data/vendor/snowball/include/libstemmer.h +4 -0
  72. data/vendor/snowball/java/org/tartarus/snowball/Among.java +32 -15
  73. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +347 -261
  74. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +3 -0
  75. data/vendor/snowball/java/org/tartarus/snowball/TestApp.java +52 -37
  76. data/vendor/snowball/javascript/base-stemmer.js +186 -2
  77. data/vendor/snowball/javascript/stemwords.js +3 -6
  78. data/vendor/snowball/libstemmer/libstemmer_c.in +1 -1
  79. data/vendor/snowball/libstemmer/mkalgorithms.pl +6 -6
  80. data/vendor/snowball/libstemmer/mkmodules.pl +2 -2
  81. data/vendor/snowball/libstemmer/modules.txt +13 -10
  82. data/vendor/snowball/libstemmer/test.c +1 -1
  83. data/vendor/snowball/pascal/SnowballProgram.pas +84 -2
  84. data/vendor/snowball/pascal/generate.pl +13 -13
  85. data/vendor/snowball/python/create_init.py +4 -1
  86. data/vendor/snowball/python/setup.cfg +0 -3
  87. data/vendor/snowball/python/setup.py +8 -3
  88. data/vendor/snowball/python/snowballstemmer/basestemmer.py +20 -54
  89. data/vendor/snowball/python/stemwords.py +8 -12
  90. data/vendor/snowball/runtime/api.c +10 -5
  91. data/vendor/snowball/runtime/header.h +10 -9
  92. data/vendor/snowball/runtime/utilities.c +9 -9
  93. data/vendor/snowball/rust/build.rs +1 -1
  94. data/vendor/snowball/rust/src/snowball/snowball_env.rs +83 -5
  95. data/vendor/snowball/tests/stemtest.c +7 -4
  96. metadata +8 -12
  97. data/vendor/snowball/.travis.yml +0 -112
  98. data/vendor/snowball/algorithms/german2.sbl +0 -145
  99. data/vendor/snowball/algorithms/kraaij_pohlmann.sbl +0 -240
  100. data/vendor/snowball/compiler/syswords2.h +0 -13
@@ -1,14 +1,13 @@
1
+ #include <assert.h>
1
2
  #include <stdlib.h> /* for exit */
2
3
  #include <string.h> /* for strlen */
3
4
  #include <stdio.h> /* for fprintf etc */
4
5
  #include <ctype.h>
5
- #include <limits.h>
6
6
  #include "header.h"
7
7
 
8
8
  /* prototypes */
9
9
 
10
10
  static void generate(struct generator * g, struct node * p);
11
- static void generate_next(struct generator * g, struct node * p);
12
11
  static void w(struct generator * g, const char * s);
13
12
  static void writef(struct generator * g, const char * s, struct node * p);
14
13
 
@@ -17,7 +16,6 @@ static int new_label(struct generator * g) {
17
16
  }
18
17
 
19
18
  static struct str * vars_newname(struct generator * g) {
20
-
21
19
  struct str * output;
22
20
  g->var_number++;
23
21
  output = str_new();
@@ -29,17 +27,19 @@ static struct str * vars_newname(struct generator * g) {
29
27
  /* Write routines for items from the syntax tree */
30
28
 
31
29
  static void write_varname(struct generator * g, struct name * p) {
32
-
33
- int ch = p->b[0];
34
30
  if (p->type != t_external) {
35
31
  write_char(g, "SBIRXG"[p->type]);
36
32
  write_char(g, '_');
37
- }
38
- write_char(g, toupper(ch));
39
- str_append_b_tail(g->outbuf, p->b, 1);
33
+ }
40
34
 
41
- ch = p->b[SIZE(p->b) - 1];
42
- if (ch == '_') {
35
+ {
36
+ char save_initial = p->s[0];
37
+ p->s[0] = toupper(save_initial);
38
+ str_append_s(g->outbuf, p->s);
39
+ p->s[0] = save_initial;
40
+ }
41
+
42
+ if (p->s[SIZE(p->s) - 1] == '_') {
43
43
  write_char(g, 'E');
44
44
  }
45
45
  }
@@ -50,11 +50,10 @@ static void write_varref(struct generator * g, struct name * p) { /* reference
50
50
  }
51
51
 
52
52
  static void write_literal_string(struct generator * g, symbol * p) {
53
- int i;
54
53
  // Ada supports UTF-8 literal strings, we only need to escape the quote and
55
54
  // special characters.
56
55
  write_char(g, '"');
57
- for (i = 0; i < SIZE(p); i++) {
56
+ for (int i = 0; i < SIZE(p); i++) {
58
57
  int ch = p[i];
59
58
  if (ch == '"') {
60
59
  write_string(g, "\"\"");
@@ -72,17 +71,30 @@ static void write_literal_string(struct generator * g, symbol * p) {
72
71
  }
73
72
 
74
73
  static void write_margin(struct generator * g) {
75
- int i;
76
- for (i = 0; i < g->margin; i++) write_string(g, " ");
74
+ for (int i = 0; i < g->margin; i++) write_string(g, " ");
75
+ }
76
+
77
+ static void write_relop(struct generator * g, int relop) {
78
+ switch (relop) {
79
+ case c_eq: write_string(g, " = "); break;
80
+ case c_ne: write_string(g, " /= "); break;
81
+ case c_gt: write_string(g, " > "); break;
82
+ case c_ge: write_string(g, " >= "); break;
83
+ case c_lt: write_string(g, " < "); break;
84
+ case c_le: write_string(g, " <= "); break;
85
+ default:
86
+ fprintf(stderr, "Unexpected type #%d in generate_integer_test\n", relop);
87
+ exit(1);
88
+ }
77
89
  }
78
90
 
79
91
  /* Write a variable declaration. */
80
92
  static void write_declare(struct generator * g,
81
- char * declaration,
93
+ const char * declaration,
82
94
  struct node * p) {
83
95
  struct str * temp = g->outbuf;
84
96
  g->outbuf = g->declarations;
85
- write_string(g, " ");
97
+ write_string(g, " ");
86
98
  writef(g, declaration, p);
87
99
  write_string(g, ";");
88
100
  write_newline(g);
@@ -90,54 +102,44 @@ static void write_declare(struct generator * g,
90
102
  }
91
103
 
92
104
  static void write_comment(struct generator * g, struct node * p) {
93
- if (g->options->comments) {
94
- write_margin(g);
95
- write_string(g, "-- ");
96
- write_comment_content(g, p);
97
- write_newline(g);
98
- }
105
+ if (!g->options->comments) return;
106
+ write_margin(g);
107
+ write_string(g, "-- ");
108
+ write_comment_content(g, p);
109
+ write_newline(g);
99
110
  }
100
111
 
101
112
  static void write_block_start(struct generator * g) {
102
113
  w(g, "~Mbegin~+~N");
103
114
  }
104
115
 
105
- static void write_block_end(struct generator * g) { /* block end */
116
+ static void write_block_end(struct generator * g) {
106
117
  w(g, "~-~Mend;~N");
107
118
  }
108
119
 
109
- static void restore_string(struct node * p, struct str * out, struct str * savevar) {
110
-
111
- str_clear(out);
112
- str_append_string(out, "Z.C := ");
113
- if (p->mode != m_forward) str_append_string(out, "Z.L - ");
114
- str_append(out, savevar);
115
- str_append_string(out, ";");
116
- }
117
-
118
120
  static void write_savecursor(struct generator * g, struct node * p,
119
121
  struct str * savevar) {
120
122
  g->B[0] = str_data(savevar);
121
123
  g->S[1] = "";
122
124
  if (p->mode != m_forward) g->S[1] = "Z.L - ";
123
- write_declare(g, " ~B0 : Char_Index", p);
125
+ write_declare(g, "~B0 : Char_Index", p);
124
126
  writef(g, "~M~B0 := ~S1Z.C;~N" , p);
125
127
  }
126
128
 
129
+ static void append_restore_string(struct node * p, struct str * out, struct str * savevar) {
130
+ str_append_string(out, "Z.C := ");
131
+ if (p->mode != m_forward) str_append_string(out, "Z.L - ");
132
+ str_append(out, savevar);
133
+ str_append_string(out, ";");
134
+ }
135
+
127
136
  static void write_restorecursor(struct generator * g, struct node * p, struct str * savevar) {
128
137
  write_margin(g);
129
- if (p->mode == m_forward) {
130
- write_string(g, "Z.C := ");
131
- } else {
132
- write_string(g, "Z.C := Z.L - ");
133
- }
134
- write_str(g, savevar);
135
- write_string(g, ";");
138
+ append_restore_string(p, g->outbuf, savevar);
136
139
  write_newline(g);
137
140
  }
138
141
 
139
142
  static void wsetl(struct generator * g, int n) {
140
-
141
143
  write_newline(g);
142
144
  write_margin(g);
143
145
  write_string(g, "<<lab");
@@ -156,7 +158,6 @@ static void wgotol(struct generator * g, int n) {
156
158
  }
157
159
 
158
160
  static void write_failure(struct generator * g) {
159
-
160
161
  if (str_len(g->failure_str) != 0) {
161
162
  write_margin(g);
162
163
  write_str(g, g->failure_str);
@@ -180,8 +181,7 @@ static void write_failure(struct generator * g) {
180
181
  g->unreachable = true;
181
182
  }
182
183
 
183
- static void write_failure_if(struct generator * g, char * s, struct node * p) {
184
-
184
+ static void write_failure_if(struct generator * g, const char * s, struct node * p) {
185
185
  writef(g, "~Mif ", p);
186
186
  writef(g, s, p);
187
187
  writef(g, " then~N~+", p);
@@ -201,19 +201,19 @@ static void write_check_limit(struct generator * g, struct node * p) {
201
201
 
202
202
  /* Formatted write. */
203
203
  static void writef(struct generator * g, const char * input, struct node * p) {
204
+ (void)p;
204
205
  int i = 0;
205
- int l = strlen(input);
206
206
 
207
- while (i < l) {
207
+ while (input[i]) {
208
208
  int ch = input[i++];
209
209
  if (ch != '~') {
210
210
  write_char(g, ch);
211
211
  continue;
212
212
  }
213
- switch (input[i++]) {
214
- default: write_char(g, input[i - 1]); continue;
215
- case 'C': write_comment(g, p); continue;
216
- case 'f':
213
+ ch = input[i++];
214
+ switch (ch) {
215
+ case '~': write_char(g, '~'); continue;
216
+ case 'f':
217
217
  write_failure(g);
218
218
  g->unreachable = false;
219
219
  continue;
@@ -221,47 +221,80 @@ static void writef(struct generator * g, const char * input, struct node * p) {
221
221
  case 'N': write_newline(g); continue;
222
222
  case '{': write_block_start(g); continue;
223
223
  case '}': write_block_end(g); continue;
224
- case 'S': write_string(g, g->S[input[i++] - '0']); continue;
225
- case 'B': write_b(g, g->B[input[i++] - '0']); continue;
226
- case 'I': write_int(g, g->I[input[i++] - '0']); continue;
227
- case 'V': write_varref(g, g->V[input[i++] - '0']); continue;
228
- case 'W': write_varname(g, g->V[input[i++] - '0']); continue;
229
- case 'L': write_literal_string(g, g->L[input[i++] - '0']); continue;
224
+ case 'S': {
225
+ int j = input[i++] - '0';
226
+ if (j < 0 || j > (int)(sizeof(g->S) / sizeof(g->S[0]))) {
227
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
228
+ ch, input[i - 1], input);
229
+ exit(1);
230
+ }
231
+ write_string(g, g->S[j]);
232
+ continue;
233
+ }
234
+ case 'B': {
235
+ int j = input[i++] - '0';
236
+ if (j < 0 || j > (int)(sizeof(g->B) / sizeof(g->B[0])))
237
+ goto invalid_escape2;
238
+ write_s(g, g->B[j]);
239
+ continue;
240
+ }
241
+ case 'I': {
242
+ int j = input[i++] - '0';
243
+ if (j < 0 || j > (int)(sizeof(g->I) / sizeof(g->I[0])))
244
+ goto invalid_escape2;
245
+ write_int(g, g->I[j]);
246
+ continue;
247
+ }
248
+ case 'V':
249
+ case 'W': {
250
+ int j = input[i++] - '0';
251
+ if (j < 0 || j > (int)(sizeof(g->V) / sizeof(g->V[0])))
252
+ goto invalid_escape2;
253
+ if (ch == 'V')
254
+ write_varref(g, g->V[j]);
255
+ else
256
+ write_varname(g, g->V[j]);
257
+ continue;
258
+ }
259
+ case 'L': {
260
+ int j = input[i++] - '0';
261
+ if (j < 0 || j > (int)(sizeof(g->L) / sizeof(g->L[0])))
262
+ goto invalid_escape2;
263
+ write_literal_string(g, g->L[j]);
264
+ continue;
265
+ }
230
266
  case '+': g->margin++; continue;
231
267
  case '-': g->margin--; continue;
232
268
  case 'n': write_string(g, g->options->name); continue;
269
+ default:
270
+ printf("Invalid escape sequence ~%c in writef(g, \"%s\", p)\n",
271
+ ch, input);
272
+ exit(1);
273
+ invalid_escape2:
274
+ printf("Invalid escape sequence ~%c%c in writef(g, \"%s\", p)\n",
275
+ ch, input[i - 1], input);
276
+ exit(1);
233
277
  }
234
278
  }
235
279
  }
236
280
 
237
281
  static void w(struct generator * g, const char * s) {
238
- writef(g, s, 0);
282
+ writef(g, s, NULL);
239
283
  }
240
284
 
241
285
  static int need_among_var(struct node *p) {
242
-
243
286
  while (p) {
244
- if (p->type == c_substring || p->type == c_among) {
287
+ if (p->type == c_among) {
245
288
  return 1;
246
289
  }
247
- if (p->right && need_among_var(p->right)) {
290
+ if (p->left && need_among_var(p->left)) {
248
291
  return 1;
249
292
  }
250
- p = p->left;
251
- }
252
- return 0;
253
- }
254
-
255
- static int need_among_handler(struct among *a) {
256
- int i;
257
- struct amongvec * v = a->b;
258
-
259
- for (i = 0; i < a->literalstring_count; i++, v++) {
260
- if (v->function != 0) {
293
+ if (p->aux && need_among_var(p->aux)) {
261
294
  return 1;
262
295
  }
296
+ p = p->right;
263
297
  }
264
-
265
298
  return 0;
266
299
  }
267
300
 
@@ -303,12 +336,15 @@ static void generate_AE(struct generator * g, struct node * p) {
303
336
  w(g, "Length_Utf8 (Z)");
304
337
  break;
305
338
  case c_size:
306
- w(g, "Length (Z)");
339
+ w(g, "Z.Len");
307
340
  break;
308
341
  case c_lenof:
342
+ g->V[0] = p->name;
343
+ w(g, "Length_Utf8 (Ada.Strings.Unbounded.To_String (~V0))");
344
+ break;
309
345
  case c_sizeof:
310
346
  g->V[0] = p->name;
311
- w(g, "Length_Utf8 (~V0)");
347
+ w(g, "Ada.Strings.Unbounded.Length (~V0)");
312
348
  break;
313
349
  default:
314
350
  break;
@@ -325,27 +361,34 @@ static void generate_bra(struct generator * g, struct node * p) {
325
361
  }
326
362
 
327
363
  static void generate_and(struct generator * g, struct node * p) {
328
- struct str * savevar = vars_newname(g);
329
- int keep_c = K_needed(g, p->left);
364
+ struct str * savevar = NULL;
365
+ if (K_needed(g, p->left)) {
366
+ savevar = vars_newname(g);
367
+ }
330
368
 
331
369
  write_comment(g, p);
332
370
 
333
- if (keep_c) write_savecursor(g, p, savevar);
371
+ if (savevar) write_savecursor(g, p, savevar);
334
372
 
335
373
  p = p->left;
336
374
  while (p) {
337
375
  generate(g, p);
338
376
  if (g->unreachable) break;
339
- if (keep_c && p->right != 0) write_restorecursor(g, p, savevar);
377
+ if (savevar && p->right != NULL) write_restorecursor(g, p, savevar);
340
378
  p = p->right;
341
379
  }
342
- str_delete(savevar);
380
+
381
+ if (savevar) {
382
+ str_delete(savevar);
383
+ }
343
384
  }
344
385
 
345
386
  static void generate_or(struct generator * g, struct node * p) {
346
- struct str * savevar = vars_newname(g);
387
+ struct str * savevar = NULL;
388
+ if (K_needed(g, p->left)) {
389
+ savevar = vars_newname(g);
390
+ }
347
391
  int used = g->label_used;
348
- int keep_c = K_needed(g, p->left);
349
392
 
350
393
  int a0 = g->failure_label;
351
394
  struct str * a1 = str_copy(g->failure_str);
@@ -355,13 +398,13 @@ static void generate_or(struct generator * g, struct node * p) {
355
398
 
356
399
  write_comment(g, p);
357
400
 
358
- if (keep_c) write_savecursor(g, p, savevar);
401
+ if (savevar) write_savecursor(g, p, savevar);
359
402
 
360
403
  p = p->left;
361
404
  str_clear(g->failure_str);
362
405
 
363
- if (p == 0) {
364
- /* p should never be 0 after an or: there should be at least two
406
+ if (p == NULL) {
407
+ /* p should never be NULL after an or: there should be at least two
365
408
  * sub nodes. */
366
409
  fprintf(stderr, "Error: \"or\" node without children nodes.");
367
410
  exit(1);
@@ -374,13 +417,11 @@ static void generate_or(struct generator * g, struct node * p) {
374
417
  wgotol(g, out_lab);
375
418
  end_unreachable = false;
376
419
  }
377
-
420
+
378
421
  if (g->label_used)
379
422
  wsetl(g, g->failure_label);
380
423
  g->unreachable = false;
381
- if (keep_c) {
382
- write_restorecursor(g, p, savevar);
383
- }
424
+ if (savevar) write_restorecursor(g, p, savevar);
384
425
  p = p->right;
385
426
  }
386
427
  g->label_used = used;
@@ -393,32 +434,37 @@ static void generate_or(struct generator * g, struct node * p) {
393
434
  if (!end_unreachable) {
394
435
  g->unreachable = false;
395
436
  }
396
- str_delete(savevar);
437
+
438
+ if (savevar) {
439
+ str_delete(savevar);
440
+ }
397
441
  }
398
442
 
399
443
  static void generate_backwards(struct generator * g, struct node * p) {
400
- writef(g, "~MZ.Lb := Z.C; Z.C := Z.L;~C~N", p);
444
+ write_comment(g, p);
445
+ writef(g, "~MZ.Lb := Z.C; Z.C := Z.L;~N", p);
401
446
  generate(g, p->left);
402
447
  w(g, "~MZ.C := Z.Lb;~N");
403
448
  }
404
449
 
405
-
406
450
  static void generate_not(struct generator * g, struct node * p) {
407
- struct str * savevar = vars_newname(g);
408
- int keep_c = K_needed(g, p->left);
451
+ struct str * savevar = NULL;
452
+ if (K_needed(g, p->left)) {
453
+ savevar = vars_newname(g);
454
+ }
409
455
 
410
- int a0 = g->failure_label, l;
456
+ int a0 = g->failure_label;
411
457
  struct str * a1 = str_copy(g->failure_str);
412
458
 
413
459
  write_comment(g, p);
414
- if (keep_c) {
460
+ if (savevar) {
415
461
  write_savecursor(g, p, savevar);
416
462
  }
417
463
 
418
464
  g->failure_label = new_label(g);
419
465
  str_clear(g->failure_str);
420
466
 
421
- l = g->failure_label;
467
+ int l = g->failure_label;
422
468
 
423
469
  generate(g, p->left);
424
470
 
@@ -433,32 +479,34 @@ static void generate_not(struct generator * g, struct node * p) {
433
479
 
434
480
  g->unreachable = false;
435
481
 
436
- if (keep_c) write_restorecursor(g, p, savevar);
437
- str_delete(savevar);
482
+ if (savevar) {
483
+ write_restorecursor(g, p, savevar);
484
+ str_delete(savevar);
485
+ }
438
486
  }
439
487
 
440
-
441
488
  static void generate_try(struct generator * g, struct node * p) {
442
- struct str * savevar;
443
- int keep_c = K_needed(g, p->left);
489
+ struct str * savevar = NULL;
490
+ if (K_needed(g, p->left)) {
491
+ savevar = vars_newname(g);
492
+ }
444
493
 
445
494
  g->failure_label = new_label(g);
446
495
  g->label_used = 0;
447
496
  str_clear(g->failure_str);
448
497
 
449
498
  write_comment(g, p);
450
- if (keep_c) {
451
- savevar = vars_newname(g);
499
+ if (savevar) {
452
500
  write_savecursor(g, p, savevar);
453
- restore_string(p, g->failure_str, savevar);
454
- }
501
+ append_restore_string(p, g->failure_str, savevar);
502
+ }
455
503
 
456
504
  generate(g, p->left);
457
505
  if (g->label_used)
458
506
  wsetl(g, g->failure_label);
459
507
  g->unreachable = false;
460
508
 
461
- if (keep_c) {
509
+ if (savevar) {
462
510
  str_delete(savevar);
463
511
  }
464
512
  }
@@ -484,30 +532,35 @@ static void generate_fail(struct generator * g, struct node * p) {
484
532
  /* generate_test() also implements 'reverse' */
485
533
 
486
534
  static void generate_test(struct generator * g, struct node * p) {
487
- struct str * savevar = vars_newname(g);
488
- int keep_c = K_needed(g, p->left);
535
+ struct str * savevar = NULL;
536
+ if (K_needed(g, p->left)) {
537
+ savevar = vars_newname(g);
538
+ }
489
539
 
490
540
  write_comment(g, p);
491
541
 
492
- if (keep_c) {
542
+ if (savevar) {
493
543
  write_savecursor(g, p, savevar);
494
544
  }
495
545
 
496
546
  generate(g, p->left);
497
547
 
498
- if (!g->unreachable) {
499
- if (keep_c) {
548
+ if (savevar) {
549
+ if (!g->unreachable) {
500
550
  write_restorecursor(g, p, savevar);
501
551
  }
552
+ str_delete(savevar);
502
553
  }
503
- str_delete(savevar);
504
554
  }
505
555
 
506
556
  static void generate_do(struct generator * g, struct node * p) {
507
- struct str * savevar = vars_newname(g);
508
- int keep_c = K_needed(g, p->left);
557
+ struct str * savevar = NULL;
558
+ if (K_needed(g, p->left)) {
559
+ savevar = vars_newname(g);
560
+ }
561
+
509
562
  write_comment(g, p);
510
- if (keep_c) write_savecursor(g, p, savevar);
563
+ if (savevar) write_savecursor(g, p, savevar);
511
564
 
512
565
  if (p->left->type == c_call) {
513
566
  /* Optimise do <call> */
@@ -524,62 +577,60 @@ static void generate_do(struct generator * g, struct node * p) {
524
577
  g->unreachable = false;
525
578
  }
526
579
 
527
- if (keep_c) write_restorecursor(g, p, savevar);
528
- str_delete(savevar);
580
+ if (savevar) {
581
+ write_restorecursor(g, p, savevar);
582
+ str_delete(savevar);
583
+ }
584
+ }
585
+
586
+ static void generate_next(struct generator * g, struct node * p) {
587
+ write_comment(g, p);
588
+ if (p->mode == m_forward)
589
+ w(g, "~MC := Skip_Utf8 (Z);~N");
590
+ else
591
+ w(g, "~MC := Skip_Utf8_Backward (Z);~N");
592
+ write_failure_if(g, "C < 0", p);
593
+ w(g, "~MZ.C := C;~N");
594
+ g->temporary_used = true;
529
595
  }
530
596
 
531
597
  static void generate_GO_grouping(struct generator * g, struct node * p, int is_goto, int complement) {
598
+ write_comment(g, p);
532
599
 
533
600
  struct grouping * q = p->name->grouping;
534
601
  g->S[0] = p->mode == m_forward ? "" : "_Backward";
535
602
  g->S[1] = complement ? "In" : "Out";
536
- g->S[2] = g->options->encoding == ENC_UTF8 ? "" : "";
537
603
  g->V[0] = p->name;
538
604
  g->I[0] = q->smallest_ch;
539
605
  g->I[1] = q->largest_ch;
540
606
  if (is_goto) {
541
- writef(g, "~M~S1_Grouping~S0~S2 (Z, ~V0, ~I0, ~I1, True, C);", p);
607
+ writef(g, "~M~S1_Grouping~S0 (Z, ~V0, ~I0, ~I1, True, C);~N", p);
542
608
  write_failure_if(g, "C < 0", p);
543
609
  } else {
544
- writef(g, "~C"
545
- "~M~S1_Grouping~S0~S2 (Z, ~V0, ~I0, ~I1, True, C);~N", p);
610
+ writef(g, "~M~S1_Grouping~S0 (Z, ~V0, ~I0, ~I1, True, C);~N", p);
546
611
  write_failure_if(g, "C < 0", p);
547
-
612
+
548
613
  if (p->mode == m_forward)
549
614
  w(g, "~MZ.C := Z.C + C;~N");
550
615
  else
551
616
  w(g, "~MZ.C := Z.C - C;~N");
552
617
  }
618
+ g->temporary_used = true;
553
619
  }
554
620
 
555
621
  static void generate_GO(struct generator * g, struct node * p, int style) {
556
- int end_unreachable = false;
622
+ write_comment(g, p);
623
+
557
624
  int used = g->label_used;
558
- /* Initialise to NULL to suppress bogus "may be used uninitialised" warning. */
559
- struct str * savevar = NULL;
560
- int keep_c = style == 1 || repeat_restore(g, p->left);
625
+
561
626
  int a0 = g->failure_label;
562
627
 
628
+ int end_unreachable = false;
563
629
  int golab = new_label(g);
564
-
565
- if (p->left->type == c_grouping || p->left->type == c_non) {
566
- /* Special case for "goto" or "gopast" when used on a grouping or an
567
- * inverted grouping - the movement of c by the matching action is
568
- * exactly what we want! */
569
- #ifdef OPTIMISATION_WARNINGS
570
- printf("Optimising %s %s\n", style ? "goto" : "gopast", p->left->type == c_non ? "non" : "grouping");
571
- #endif
572
- if (g->options->comments) {
573
- writef(g, "~M~C", p);
574
- }
575
- generate_GO_grouping(g, p->left, style, p->left->type == c_non);
576
- return;
577
- }
578
-
579
- write_comment(g, p);
580
630
  w(g, "~Mloop~N~+");
581
631
 
582
- if (keep_c) {
632
+ struct str * savevar = NULL;
633
+ if (style == 1 || repeat_restore(g, p->left)) {
583
634
  savevar = vars_newname(g);
584
635
  write_savecursor(g, p, savevar);
585
636
  }
@@ -602,7 +653,7 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
602
653
  g->unreachable = false;
603
654
  if (g->label_used)
604
655
  wsetl(g, g->failure_label);
605
- if (keep_c) {
656
+ if (savevar) {
606
657
  write_restorecursor(g, p, savevar);
607
658
  str_delete(savevar);
608
659
  }
@@ -612,8 +663,8 @@ static void generate_GO(struct generator * g, struct node * p, int style) {
612
663
  write_check_limit(g, p);
613
664
  generate_next(g, p);
614
665
 
615
- g->I[0] = golab;
616
666
  w(g, "~-~Mend loop;~N");
667
+
617
668
  g->unreachable = end_unreachable;
618
669
  }
619
670
 
@@ -621,35 +672,34 @@ static void generate_loop(struct generator * g, struct node * p) {
621
672
  struct str * loopvar = vars_newname(g);
622
673
  write_comment(g, p);
623
674
  g->B[0] = str_data(loopvar);
624
- write_declare(g, " ~B0 : Integer", p);
625
- w(g, "~MFor ~B0 := ");
675
+ w(g, "~Mfor ~B0 in reverse 1 .. ");
626
676
  generate_AE(g, p->AE);
627
- writef(g, " DownTo 1 Do~N", p);
628
- writef(g, "~{", p);
677
+ writef(g, " loop~N~+", p);
629
678
 
630
679
  generate(g, p->left);
631
680
 
632
- w(g, "~}");
681
+ w(g, "~-~Mend loop;~N");
633
682
  str_delete(loopvar);
634
683
  g->unreachable = false;
635
684
  }
636
685
 
637
686
  static void generate_repeat_or_atleast(struct generator * g, struct node * p, struct str * loopvar) {
638
- struct str * savevar = vars_newname(g);
639
- int keep_c = repeat_restore(g, p->left);
640
687
  int replab = new_label(g);
641
- g->I[0] = replab;
642
688
  wsetl(g, replab);
643
689
  writef(g, "~N~Mloop~N~+", p);
644
690
 
645
- if (keep_c) write_savecursor(g, p, savevar);
691
+ struct str * savevar = NULL;
692
+ if (repeat_restore(g, p->left)) {
693
+ savevar = vars_newname(g);
694
+ write_savecursor(g, p, savevar);
695
+ }
646
696
 
647
697
  g->failure_label = new_label(g);
648
698
  g->label_used = 0;
649
699
  generate(g, p->left);
650
700
 
651
701
  if (!g->unreachable) {
652
- if (loopvar != 0) {
702
+ if (loopvar != NULL) {
653
703
  g->B[0] = str_data(loopvar);
654
704
  w(g, "~M~B0 := ~B0 - 1;~N");
655
705
  }
@@ -661,10 +711,12 @@ static void generate_repeat_or_atleast(struct generator * g, struct node * p, st
661
711
  wsetl(g, g->failure_label);
662
712
  g->unreachable = false;
663
713
 
664
- if (keep_c) write_restorecursor(g, p, savevar);
714
+ if (savevar) {
715
+ write_restorecursor(g, p, savevar);
716
+ str_delete(savevar);
717
+ }
665
718
 
666
719
  w(g, "~N~Mexit;~N~-~Mend loop;~N");
667
- str_delete(savevar);
668
720
  }
669
721
 
670
722
  static void generate_repeat(struct generator * g, struct node * p) {
@@ -678,8 +730,7 @@ static void generate_atleast(struct generator * g, struct node * p) {
678
730
  write_comment(g, p);
679
731
  w(g, "~{");
680
732
  g->B[0] = str_data(loopvar);
681
-
682
- write_declare(g, " ~B0 : Integer", p);
733
+ write_declare(g, "~B0 : Integer", p);
683
734
  w(g, "~M~B0 := ");
684
735
  generate_AE(g, p->AE);
685
736
  w(g, ";~N");
@@ -722,22 +773,14 @@ static void generate_atmark(struct generator * g, struct node * p) {
722
773
  }
723
774
 
724
775
  static void generate_hop(struct generator * g, struct node * p) {
776
+ write_comment(g, p);
725
777
  g->S[0] = p->mode == m_forward ? "" : "_Backward";
726
- if (g->options->encoding == ENC_UTF8) {
727
- w(g, "~MC := Skip_Utf8~S0 (Z, ");
728
- generate_AE(g, p->AE); writef(g, ");~C~N", p);
729
- write_failure_if(g, "C < 0", p);
730
- } else {
731
- w(g, "~MC := Z.C ~S0 ");
732
- generate_AE(g, p->AE);
733
- writef(g, ";~C~N", p);
734
- if (p->mode == m_forward) {
735
- write_failure_if(g, "C > Z.L or C < Z.C", p);
736
- } else {
737
- write_failure_if(g, "C < Z.Lb or C > Z.C", p);
738
- }
739
- }
778
+
779
+ w(g, "~MC := Skip_Utf8~S0 (Z, ");
780
+ generate_AE(g, p->AE); writef(g, ");~N", p);
781
+ write_failure_if(g, "C < 0", p);
740
782
  writef(g, "~MZ.C := C;~N", p);
783
+ g->temporary_used = true;
741
784
  }
742
785
 
743
786
  static void generate_delete(struct generator * g, struct node * p) {
@@ -745,19 +788,10 @@ static void generate_delete(struct generator * g, struct node * p) {
745
788
  writef(g, "~MSlice_Del (Z);~N", p);
746
789
  }
747
790
 
748
- static void generate_next(struct generator * g, struct node * p) {
749
- write_comment(g, p);
750
- if (p->mode == m_forward)
751
- w(g, "~MC := Skip_Utf8 (Z);~N");
752
- else
753
- w(g, "~MC := Skip_Utf8_Backward (Z);~N");
754
- write_failure_if(g, "C < 0", p);
755
- w(g, "~MZ.C := C;~N");
756
- }
757
-
758
791
  static void generate_tolimit(struct generator * g, struct node * p) {
792
+ write_comment(g, p);
759
793
  g->S[0] = p->mode == m_forward ? "" : "b";
760
- writef(g, "~MZ.C := Z.L~S0;~C~N", p);
794
+ writef(g, "~MZ.C := Z.L~S0;~N", p);
761
795
  }
762
796
 
763
797
  static void generate_atlimit(struct generator * g, struct node * p) {
@@ -768,18 +802,21 @@ static void generate_atlimit(struct generator * g, struct node * p) {
768
802
  }
769
803
 
770
804
  static void generate_leftslice(struct generator * g, struct node * p) {
805
+ write_comment(g, p);
771
806
  g->S[0] = p->mode == m_forward ? "Bra" : "Ket";
772
- writef(g, "~MZ.~S0 := Z.C;~C~N", p);
807
+ writef(g, "~MZ.~S0 := Z.C;~N", p);
773
808
  }
774
809
 
775
810
  static void generate_rightslice(struct generator * g, struct node * p) {
811
+ write_comment(g, p);
776
812
  g->S[0] = p->mode == m_forward ? "Ket" : "Bra";
777
- writef(g, "~MZ.~S0 := Z.C;~C~N", p);
813
+ writef(g, "~MZ.~S0 := Z.C;~N", p);
778
814
  }
779
815
 
780
816
  static void generate_assignto(struct generator * g, struct node * p) {
817
+ write_comment(g, p);
781
818
  g->V[0] = p->name;
782
- writef(g, "~M~V0 := Assign_To (Z, ~V0);~C~N", p);
819
+ writef(g, "~M~V0 := Assign_To (Z, ~V0);~N", p);
783
820
  write_failure_if(g, "~V0 == 0", p);
784
821
  }
785
822
 
@@ -791,15 +828,16 @@ static void generate_sliceto(struct generator * g, struct node * p) {
791
828
 
792
829
  static void generate_address(struct generator * g, struct node * p) {
793
830
  symbol * b = p->literalstring;
794
- if (b != 0) {
831
+ if (b != NULL) {
795
832
  write_literal_string(g, b);
796
833
  } else {
797
- write_varname(g, p->name);
834
+ w(g, "Ada.Strings.Unbounded.To_String (");
835
+ write_varref(g, p->name);
836
+ w(g, ")");
798
837
  }
799
838
  }
800
839
 
801
840
  static void generate_insert(struct generator * g, struct node * p, int style) {
802
-
803
841
  int keep_c = style == c_attach;
804
842
  write_comment(g, p);
805
843
  if (p->mode == m_backward) keep_c = !keep_c;
@@ -807,7 +845,10 @@ static void generate_insert(struct generator * g, struct node * p, int style) {
807
845
  writef(g, "~MInsert (Z, Z.C, Z.C, ", p);
808
846
  generate_address(g, p);
809
847
  writef(g, ");~N", p);
810
- if (keep_c) w(g, "~MZ.C := C;~N");
848
+ if (keep_c) {
849
+ w(g, "~MZ.C := C;~N");
850
+ g->temporary_used = true;
851
+ }
811
852
  }
812
853
 
813
854
  static void generate_assignfrom(struct generator * g, struct node * p) {
@@ -822,7 +863,10 @@ static void generate_assignfrom(struct generator * g, struct node * p) {
822
863
  }
823
864
  generate_address(g, p);
824
865
  writef(g, ");~N", p);
825
- if (keep_c) w(g, "~MZ.C := C;~N");
866
+ if (keep_c) {
867
+ w(g, "~MZ.C := C;~N");
868
+ g->temporary_used = true;
869
+ }
826
870
  }
827
871
 
828
872
  static void generate_slicefrom(struct generator * g, struct node * p) {
@@ -833,11 +877,11 @@ static void generate_slicefrom(struct generator * g, struct node * p) {
833
877
  }
834
878
 
835
879
  static void generate_setlimit(struct generator * g, struct node * p) {
836
- struct str * savevar = vars_newname(g);
837
880
  struct str * varname = vars_newname(g);
881
+ write_comment(g, p);
838
882
 
839
883
  g->B[0] = str_data(varname);
840
- write_declare(g, " ~B0 : Integer", p);
884
+ write_declare(g, "~B0 : Integer", p);
841
885
  if (p->left && p->left->type == c_tomark) {
842
886
  /* Special case for:
843
887
  *
@@ -848,8 +892,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
848
892
  * restore c.
849
893
  */
850
894
  struct node * q = p->left;
851
-
852
- ++g->keep_count;
895
+ write_comment(g, q);
853
896
 
854
897
  g->S[0] = q->mode == m_forward ? ">" : "<";
855
898
 
@@ -877,8 +920,8 @@ static void generate_setlimit(struct generator * g, struct node * p) {
877
920
  str_append(g->failure_str, varname);
878
921
  str_append_ch(g->failure_str, ';');
879
922
  }
880
-
881
923
  } else {
924
+ struct str * savevar = vars_newname(g);
882
925
  write_savecursor(g, p, savevar);
883
926
 
884
927
  generate(g, p->left);
@@ -904,6 +947,7 @@ static void generate_setlimit(struct generator * g, struct node * p) {
904
947
  str_append_ch(g->failure_str, ';');
905
948
  }
906
949
  }
950
+ str_delete(savevar);
907
951
  }
908
952
 
909
953
  if (!g->unreachable) {
@@ -916,15 +960,15 @@ static void generate_setlimit(struct generator * g, struct node * p) {
916
960
  }
917
961
  }
918
962
  str_delete(varname);
919
- str_delete(savevar);
920
963
  }
921
964
 
922
965
  /* dollar sets snowball up to operate on a string variable as if it were the
923
966
  * current string */
924
967
  static void generate_dollar(struct generator * g, struct node * p) {
968
+ write_comment(g, p);
969
+
925
970
  struct str * savevar = vars_newname(g);
926
971
  g->B[0] = str_data(savevar);
927
- write_comment(g, p);
928
972
  g->V[0] = p->name;
929
973
 
930
974
  {
@@ -969,12 +1013,12 @@ static void generate_dollar(struct generator * g, struct node * p) {
969
1013
  str_delete(savevar);
970
1014
  }
971
1015
 
972
- static void generate_integer_assign(struct generator * g, struct node * p, char * s) {
973
-
1016
+ static void generate_integer_assign(struct generator * g, struct node * p, const char * s) {
1017
+ write_comment(g, p);
974
1018
  g->V[0] = p->name;
975
1019
  w(g, "~M~V0 := ");
976
1020
 
977
- if (s != 0) {
1021
+ if (s != NULL) {
978
1022
  g->S[0] = s;
979
1023
  w(g, "~V0 ~S0 ");
980
1024
  }
@@ -983,60 +1027,82 @@ static void generate_integer_assign(struct generator * g, struct node * p, char
983
1027
  w(g, ";~N");
984
1028
  }
985
1029
 
986
- static void generate_integer_test(struct generator * g, struct node * p, char * s) {
987
-
988
- w(g, "~Mif not (");
989
- generate_AE(g, p->left);
990
- write_char(g, ' ');
991
- write_string(g, s);
992
- write_char(g, ' ');
993
- generate_AE(g, p->AE);
994
- w(g, ") then~+~N");
995
- write_failure(g);
996
- w(g, "~-~Mend if;~N");
997
- g->unreachable = false;
998
- }
999
-
1000
- static void generate_integer_function(struct generator * g, struct node * p, char * s) {
1001
-
1002
- w(g, "~MResult := (");
1030
+ static void generate_integer_test(struct generator * g, struct node * p) {
1031
+ write_comment(g, p);
1032
+ int relop = p->type;
1033
+ int optimise_to_return = (g->failure_label == x_return && p->right && p->right->type == c_functionend);
1034
+ if (optimise_to_return) {
1035
+ w(g, "~MResult := (");
1036
+ p->right = NULL;
1037
+ } else {
1038
+ w(g, "~Mif ");
1039
+ // We want the inverse of the snowball test here.
1040
+ relop ^= 1;
1041
+ }
1003
1042
  generate_AE(g, p->left);
1004
- write_char(g, ' ');
1005
- write_string(g, s);
1006
- write_char(g, ' ');
1043
+ write_relop(g, relop);
1007
1044
  generate_AE(g, p->AE);
1008
- w(g, ");~N");
1009
- g->unreachable = false;
1045
+ if (optimise_to_return) {
1046
+ w(g, ");~N");
1047
+ } else {
1048
+ w(g, " then~+~N");
1049
+ write_failure(g);
1050
+ w(g, "~-~Mend if;~N");
1051
+ g->unreachable = false;
1052
+ }
1010
1053
  }
1011
1054
 
1012
1055
  static void generate_call(struct generator * g, struct node * p) {
1013
-
1056
+ int signals = check_possible_signals_list(g, p->name->definition, c_define, 0);
1014
1057
  write_comment(g, p);
1015
1058
  g->V[0] = p->name;
1016
- writef(g, "~M~V0 (Z, Result);~N", p);
1017
- write_failure_if(g, "not Result", p);
1059
+ if (g->failure_label == x_return) {
1060
+ if (p->right && p->right->type == c_functionend) {
1061
+ /* Tail call. */
1062
+ writef(g, "~M~V0 (Z, Result);~N", p);
1063
+ return;
1064
+ }
1065
+ if (signals == 0) {
1066
+ /* Always fails. */
1067
+ writef(g, "~M~V0 (Z, Result);~N", p);
1068
+ w(g, "~Mreturn~N");
1069
+ return;
1070
+ }
1071
+ }
1072
+ if (signals == 1) {
1073
+ /* Always succeeds. */
1074
+ writef(g, "~M~V0 (Z, Result);~N", p);
1075
+ } else if (signals == 0) {
1076
+ /* Always fails. */
1077
+ writef(g, "~M~V0 (Z, Result);~N", p);
1078
+ write_failure(g);
1079
+ } else {
1080
+ writef(g, "~M~V0 (Z, Result);~N", p);
1081
+ write_failure_if(g, "not Result", p);
1082
+ }
1018
1083
  }
1019
1084
 
1020
1085
  static void generate_grouping(struct generator * g, struct node * p, int complement) {
1086
+ write_comment(g, p);
1021
1087
 
1022
1088
  struct grouping * q = p->name->grouping;
1023
1089
  g->S[0] = p->mode == m_forward ? "" : "_Backward";
1024
1090
  g->S[1] = complement ? "Out_" : "In_";
1025
- g->S[2] = g->options->encoding == ENC_UTF8 ? "" : "";
1026
1091
  g->V[0] = p->name;
1027
1092
  g->I[0] = q->smallest_ch;
1028
1093
  g->I[1] = q->largest_ch;
1029
- writef(g, "~M~S1Grouping~S0~S2 (Z, ~V0, ~I0, ~I1, False, C);~N", p);
1094
+ writef(g, "~M~S1Grouping~S0 (Z, ~V0, ~I0, ~I1, False, C);~N", p);
1030
1095
  write_failure_if(g, "C /= 0", p);
1096
+ g->temporary_used = true;
1031
1097
  }
1032
1098
 
1033
1099
  static void generate_namedstring(struct generator * g, struct node * p) {
1034
-
1035
1100
  write_comment(g, p);
1036
1101
  g->S[0] = p->mode == m_forward ? "" : "_Backward";
1037
1102
  g->V[0] = p->name;
1038
1103
  writef(g, "~MC := Eq_S~S0 (Z, Ada.Strings.Unbounded.To_String (~V0));", p);
1039
1104
  write_failure_if(g, "C = 0", p);
1105
+ g->temporary_used = true;
1040
1106
  }
1041
1107
 
1042
1108
  static void generate_literalstring(struct generator * g, struct node * p) {
@@ -1051,20 +1117,23 @@ static void generate_literalstring(struct generator * g, struct node * p) {
1051
1117
  } else {
1052
1118
  writef(g, "~MZ.C := Z.C - C;~N", p);
1053
1119
  }
1120
+ g->temporary_used = true;
1054
1121
  }
1055
1122
 
1056
1123
  static void generate_define(struct generator * g, struct node * p) {
1057
- struct str *saved_output;
1058
- struct str *saved_declarations;
1124
+ struct name * q = p->name;
1125
+ if (q->type == t_routine && !q->used) return;
1059
1126
 
1060
- /* Generate function header. */
1061
- g->V[0] = p->name;
1062
- w(g, "~N~Mprocedure ~W0 (Z : in out Context_Type; Result : out Boolean) is~N");
1127
+ write_newline(g);
1128
+ write_comment(g, p);
1063
1129
 
1064
- /* Save output*/
1065
- saved_output = g->outbuf;
1066
- saved_declarations = g->declarations;
1130
+ /* Generate function header. */
1131
+ g->V[0] = q;
1132
+ w(g, "~Mprocedure ~W0 (Z : in out Context_Type; Result : out Boolean) is~N");
1067
1133
 
1134
+ /* Save output. */
1135
+ struct str *saved_output = g->outbuf;
1136
+ struct str *saved_declarations = g->declarations;
1068
1137
  g->outbuf = str_new();
1069
1138
  g->declarations = str_new();
1070
1139
 
@@ -1076,25 +1145,26 @@ static void generate_define(struct generator * g, struct node * p) {
1076
1145
 
1077
1146
  /* Generate function body. */
1078
1147
  w(g, "~{");
1079
- switch (p->left->type) {
1080
- case c_eq: generate_integer_function(g, p->left, "="); break;
1081
- case c_ne: generate_integer_function(g, p->left, "/="); break;
1082
- case c_gr: generate_integer_function(g, p->left, ">"); break;
1083
- case c_ge: generate_integer_function(g, p->left, ">="); break;
1084
- case c_ls: generate_integer_function(g, p->left, "<"); break;
1085
- case c_le: generate_integer_function(g, p->left, "<="); break;
1086
- default:
1087
- generate(g, p->left);
1088
- if (!g->unreachable) w(g, "~N~MResult := True;~N");
1089
- str_append_string(saved_output, " C : Result_Index;\n");
1090
- if (need_among_var(p->left) || 1) {
1091
- str_append_string(saved_output, " A : Integer;\n");
1092
- }
1093
- break;
1148
+ int signals = check_possible_signals_list(g, p->left, c_define, 0);
1149
+ g->temporary_used = false;
1150
+ generate(g, p->left);
1151
+ if (p->left->right) {
1152
+ assert(p->left->right->type == c_functionend);
1153
+ if (signals) {
1154
+ generate(g, p->left->right);
1155
+ }
1094
1156
  }
1095
- g->V[0] = p->name;
1157
+ g->V[0] = q;
1096
1158
  w(g, "~-~Mend ~W0;~N");
1097
1159
 
1160
+ if (g->temporary_used) {
1161
+ str_append_string(saved_output, " C : Result_Index;\n");
1162
+ }
1163
+
1164
+ if (need_among_var(p->left)) {
1165
+ str_append_string(saved_output, " A : Integer;\n");
1166
+ }
1167
+
1098
1168
  if (g->var_number) {
1099
1169
  str_append(saved_output, g->declarations);
1100
1170
  }
@@ -1106,39 +1176,36 @@ static void generate_define(struct generator * g, struct node * p) {
1106
1176
  g->outbuf = saved_output;
1107
1177
  }
1108
1178
 
1179
+ static void generate_functionend(struct generator * g, struct node * p) {
1180
+ (void)p;
1181
+ w(g, "~MResult := True;~N");
1182
+ }
1183
+
1109
1184
  static void generate_substring(struct generator * g, struct node * p) {
1185
+ write_comment(g, p);
1186
+
1110
1187
  struct among * x = p->among;
1111
1188
  int block = -1;
1112
1189
  unsigned int bitmap = 0;
1113
1190
  struct amongvec * among_cases = x->b;
1114
- int c;
1115
1191
  int empty_case = -1;
1116
1192
  int n_cases = 0;
1117
1193
  symbol cases[2];
1118
- int shortest_size = INT_MAX;
1194
+ int shortest_size = x->shortest_size;
1119
1195
  int call_done = 0;
1120
- int need_handler = need_among_handler(x);
1121
-
1122
- write_comment(g, p);
1196
+ int need_among_handler = (x->function_count > 0);
1123
1197
 
1124
1198
  g->S[0] = p->mode == m_forward ? "" : "_Backward";
1125
1199
  g->I[0] = x->number;
1126
1200
 
1127
- /* In forward mode with non-ASCII UTF-8 characters, the first character
1201
+ /* In forward mode with non-ASCII UTF-8 characters, the first byte
1128
1202
  * of the string will often be the same, so instead look at the last
1129
- * common character position.
1203
+ * common byte position.
1130
1204
  *
1131
1205
  * In backward mode, we can't match if there are fewer characters before
1132
1206
  * the current position than the minimum length.
1133
1207
  */
1134
- for (c = 0; c < x->literalstring_count; ++c) {
1135
- int size = among_cases[c].size;
1136
- if (size != 0 && size < shortest_size) {
1137
- shortest_size = size;
1138
- }
1139
- }
1140
-
1141
- for (c = 0; c < x->literalstring_count; ++c) {
1208
+ for (int c = 0; c < x->literalstring_count; ++c) {
1142
1209
  symbol ch;
1143
1210
  if (among_cases[c].size == 0) {
1144
1211
  empty_case = c;
@@ -1225,16 +1292,18 @@ static void generate_substring(struct generator * g, struct node * p) {
1225
1292
  * so not matching the bitmap means we match the empty string.
1226
1293
  */
1227
1294
  g->I[4] = among_cases[empty_case].result;
1228
- writef(g, "~MA := ~I4;~-~N~Melse~+~C", p);
1229
- if (need_handler) {
1295
+ writef(g, "~MA := ~I4;~-~N~Melse~+~N", p);
1296
+ if (need_among_handler) {
1230
1297
  writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, Among_Handler'Access, A);~N", p);
1231
1298
  } else {
1232
1299
  writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, null, A);~N", p);
1233
1300
  }
1234
- write_failure_if(g, "A = 0", p);
1301
+ if (!x->always_matches) {
1302
+ write_failure_if(g, "A = 0", p);
1303
+ }
1235
1304
  call_done = 1;
1236
1305
  } else {
1237
- writef(g, "~f~C", p);
1306
+ write_failure(g);
1238
1307
  }
1239
1308
  writef(g, "~-~Mend if;~N", p);
1240
1309
  } else {
@@ -1244,31 +1313,32 @@ static void generate_substring(struct generator * g, struct node * p) {
1244
1313
  }
1245
1314
 
1246
1315
  if (!call_done) {
1247
- if (need_handler) {
1316
+ if (need_among_handler) {
1248
1317
  writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, Among_Handler'Access, A);~N", p);
1249
1318
  } else {
1250
1319
  writef(g, "~MFind_Among~S0 (Z, A_~I0, Among_String, null, A);~N", p);
1251
1320
  }
1252
- write_failure_if(g, "A = 0", p);
1321
+ if (!x->always_matches) {
1322
+ write_failure_if(g, "A = 0", p);
1323
+ }
1253
1324
  }
1254
1325
  }
1255
1326
 
1256
1327
  static void generate_among(struct generator * g, struct node * p) {
1257
-
1258
1328
  struct among * x = p->among;
1259
1329
 
1260
- if (x->substring == 0) generate_substring(g, p);
1261
-
1262
- if (x->starter != 0) generate(g, x->starter);
1330
+ if (x->substring == NULL) {
1331
+ generate_substring(g, p);
1332
+ } else {
1333
+ write_comment(g, p);
1334
+ }
1263
1335
 
1264
1336
  if (x->command_count == 1 && x->nocommand_count == 0) {
1265
1337
  /* Only one outcome ("no match" already handled). */
1266
1338
  generate(g, x->commands[0]);
1267
1339
  } else if (x->command_count > 0) {
1268
- int i;
1269
- write_comment(g, p);
1270
1340
  w(g, "~Mcase A is~N~+");
1271
- for (i = 1; i <= x->command_count; i++) {
1341
+ for (int i = 1; i <= x->command_count; i++) {
1272
1342
  g->I[0] = i;
1273
1343
  w(g, "~Mwhen ~I0 =>~N");
1274
1344
  g->margin++;
@@ -1283,20 +1353,17 @@ static void generate_among(struct generator * g, struct node * p) {
1283
1353
  }
1284
1354
 
1285
1355
  static void generate_booltest(struct generator * g, struct node * p) {
1286
-
1287
1356
  write_comment(g, p);
1288
1357
  g->V[0] = p->name;
1289
1358
  write_failure_if(g, "not ~V0", p);
1290
1359
  }
1291
1360
 
1292
1361
  static void generate_false(struct generator * g, struct node * p) {
1293
-
1294
1362
  write_comment(g, p);
1295
1363
  write_failure(g);
1296
1364
  }
1297
1365
 
1298
1366
  static void generate_debug(struct generator * g, struct node * p) {
1299
-
1300
1367
  write_comment(g, p);
1301
1368
  g->I[0] = g->debug_count++;
1302
1369
  g->I[1] = p->line_number;
@@ -1304,14 +1371,10 @@ static void generate_debug(struct generator * g, struct node * p) {
1304
1371
  }
1305
1372
 
1306
1373
  static void generate(struct generator * g, struct node * p) {
1307
-
1308
- int a0;
1309
- struct str * a1;
1310
-
1311
1374
  if (g->unreachable) return;
1312
1375
 
1313
- a0 = g->failure_label;
1314
- a1 = str_copy(g->failure_str);
1376
+ int a0 = g->failure_label;
1377
+ struct str * a1 = str_copy(g->failure_str);
1315
1378
 
1316
1379
  switch (p->type) {
1317
1380
  case c_define: generate_define(g, p); break;
@@ -1329,6 +1392,11 @@ static void generate(struct generator * g, struct node * p) {
1329
1392
  case c_do: generate_do(g, p); break;
1330
1393
  case c_goto: generate_GO(g, p, 1); break;
1331
1394
  case c_gopast: generate_GO(g, p, 0); break;
1395
+ case c_goto_grouping: generate_GO_grouping(g, p, 1, 0); break;
1396
+ case c_gopast_grouping:
1397
+ generate_GO_grouping(g, p, 0, 0); break;
1398
+ case c_goto_non: generate_GO_grouping(g, p, 1, 1); break;
1399
+ case c_gopast_non: generate_GO_grouping(g, p, 0, 1); break;
1332
1400
  case c_repeat: generate_repeat(g, p); break;
1333
1401
  case c_loop: generate_loop(g, p); break;
1334
1402
  case c_atleast: generate_atleast(g, p); break;
@@ -1355,12 +1423,14 @@ static void generate(struct generator * g, struct node * p) {
1355
1423
  case c_minusassign: generate_integer_assign(g, p, "-"); break;
1356
1424
  case c_multiplyassign:generate_integer_assign(g, p, "*"); break;
1357
1425
  case c_divideassign: generate_integer_assign(g, p, "/"); break;
1358
- case c_eq: generate_integer_test(g, p, "="); break;
1359
- case c_ne: generate_integer_test(g, p, "/="); break;
1360
- case c_gr: generate_integer_test(g, p, ">"); break;
1361
- case c_ge: generate_integer_test(g, p, ">="); break;
1362
- case c_ls: generate_integer_test(g, p, "<"); break;
1363
- case c_le: generate_integer_test(g, p, "<="); break;
1426
+ case c_eq:
1427
+ case c_ne:
1428
+ case c_gt:
1429
+ case c_ge:
1430
+ case c_lt:
1431
+ case c_le:
1432
+ generate_integer_test(g, p);
1433
+ break;
1364
1434
  case c_call: generate_call(g, p); break;
1365
1435
  case c_grouping: generate_grouping(g, p, false); break;
1366
1436
  case c_non: generate_grouping(g, p, true); break;
@@ -1372,6 +1442,7 @@ static void generate(struct generator * g, struct node * p) {
1372
1442
  case c_false: generate_false(g, p); break;
1373
1443
  case c_true: break;
1374
1444
  case c_debug: generate_debug(g, p); break;
1445
+ case c_functionend: generate_functionend(g, p); break;
1375
1446
  default: fprintf(stderr, "%d encountered\n", p->type);
1376
1447
  exit(1);
1377
1448
  }
@@ -1393,51 +1464,31 @@ static void generate_method_decl(struct generator * g, struct name * q) {
1393
1464
  }
1394
1465
 
1395
1466
  static void generate_method_decls(struct generator * g, enum name_types type) {
1396
- struct name * q;
1397
1467
  struct among * a = g->analyser->amongs;
1398
- int need_handler = 0;
1468
+ int need_among_handler = 0;
1399
1469
 
1400
- for (q = g->analyser->names; q; q = q->next) {
1470
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1401
1471
  if ((enum name_types)q->type == type) {
1402
1472
  generate_method_decl(g, q);
1403
1473
  }
1404
1474
  }
1405
1475
 
1406
- while (a != 0 && need_handler == 0) {
1407
- need_handler = need_among_handler(a);
1476
+ while (a != NULL && need_among_handler == 0) {
1477
+ need_among_handler = (a->function_count > 0);
1408
1478
  a = a->next;
1409
1479
  }
1410
- if (need_handler) {
1480
+ if (need_among_handler) {
1411
1481
  w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean);~N");
1412
1482
  }
1413
1483
  }
1414
1484
 
1415
- static int has_string_variable(struct generator * g) {
1416
- struct name * q;
1417
- for (q = g->analyser->names; q; q = q->next) {
1418
- g->V[0] = q;
1419
- if (q->type == t_string) {
1420
- return 1;
1421
- }
1422
- }
1423
-
1424
- return 0;
1425
- }
1426
-
1427
1485
  static void generate_member_decls(struct generator * g) {
1428
- struct name * q;
1429
- int count = 0;
1430
-
1431
-
1432
- for (q = g->analyser->names; q; q = q->next) {
1433
- if (q->type == t_string || q->type == t_integer || q->type == t_boolean)
1434
- count++;
1435
- }
1436
-
1437
1486
  w(g, " type Context_Type is new Stemmer.Context_Type with");
1438
- if (count > 0) {
1487
+ if (g->analyser->name_count[t_string] > 0 ||
1488
+ g->analyser->name_count[t_integer] > 0 ||
1489
+ g->analyser->name_count[t_boolean] > 0) {
1439
1490
  w(g, " record~N~+");
1440
- for (q = g->analyser->names; q; q = q->next) {
1491
+ for (struct name * q = g->analyser->names; q; q = q->next) {
1441
1492
  g->V[0] = q;
1442
1493
  switch (q->type) {
1443
1494
  case t_string:
@@ -1460,13 +1511,12 @@ static void generate_member_decls(struct generator * g) {
1460
1511
  }
1461
1512
 
1462
1513
  static int generate_among_string(struct generator * g, struct among * x, int count) {
1463
- int i;
1464
1514
  struct amongvec * v = x->b;
1465
1515
  int limit = count == 0 ? 38 : 80;
1466
1516
 
1467
1517
  g->I[0] = x->number;
1468
1518
 
1469
- for (i = 0; i < x->literalstring_count; i++, v++) {
1519
+ for (int i = 0; i < x->literalstring_count; i++, v++) {
1470
1520
  /* Write among's string. */
1471
1521
  g->L[0] = v->b;
1472
1522
  g->I[1] = i;
@@ -1484,7 +1534,8 @@ static int generate_among_string(struct generator * g, struct among * x, int cou
1484
1534
  }
1485
1535
 
1486
1536
  static int generate_among_table(struct generator * g, struct among * x, int start_pos, int *operation) {
1487
- int i;
1537
+ write_comment(g, x->node);
1538
+
1488
1539
  struct amongvec * v = x->b;
1489
1540
 
1490
1541
  g->I[0] = x->number;
@@ -1493,7 +1544,7 @@ static int generate_among_table(struct generator * g, struct among * x, int star
1493
1544
  w(g, "~MA_~I0 : constant Among_Array_Type (0 .. ~I1) := ~+(~N");
1494
1545
 
1495
1546
  v = x->b;
1496
- for (i = 0; i < x->literalstring_count; i++, v++) {
1547
+ for (int i = 0; i < x->literalstring_count; i++) {
1497
1548
  g->I[1] = start_pos;
1498
1549
 
1499
1550
  /* Write among's string position. */
@@ -1502,18 +1553,18 @@ static int generate_among_table(struct generator * g, struct among * x, int star
1502
1553
  } else {
1503
1554
  w(g, "~M(~I1, ");
1504
1555
  }
1505
- start_pos = start_pos + SIZE(v->b);
1556
+ start_pos = start_pos + SIZE(v[i].b);
1506
1557
  g->I[1] = start_pos - 1;
1507
1558
  w(g, "~I1, ");
1508
1559
 
1509
1560
  /* Write among's index & result. */
1510
- g->I[2] = v->i;
1561
+ g->I[2] = v[i].i;
1511
1562
  w(g, "~I2, ");
1512
- g->I[2] = v->result;
1563
+ g->I[2] = v[i].result;
1513
1564
  w(g, "~I2, ");
1514
1565
 
1515
1566
  /* Write among's handler. */
1516
- if (v->function == 0) {
1567
+ if (v[i].function == NULL) {
1517
1568
  w(g, "0)");
1518
1569
  } else {
1519
1570
  *operation = *operation + 1;
@@ -1530,12 +1581,13 @@ static int generate_among_table(struct generator * g, struct among * x, int star
1530
1581
 
1531
1582
  static int generate_amongs(struct generator * g) {
1532
1583
  struct among * a = g->analyser->amongs;
1584
+ if (!a) return 0;
1533
1585
  int count;
1534
1586
  int start_pos;
1535
-
1587
+
1536
1588
  w(g, "~MAmong_String : constant String := ~+");
1537
1589
  count = 0;
1538
- while (a != 0) {
1590
+ while (a != NULL) {
1539
1591
  count = generate_among_string(g, a, count);
1540
1592
  a = a->next;
1541
1593
  }
@@ -1544,7 +1596,7 @@ static int generate_amongs(struct generator * g) {
1544
1596
  int operation = 0;
1545
1597
  start_pos = 1;
1546
1598
  a = g->analyser->amongs;
1547
- while (a != 0) {
1599
+ while (a != NULL) {
1548
1600
  start_pos = generate_among_table(g, a, start_pos, &operation);
1549
1601
  a = a->next;
1550
1602
  }
@@ -1556,34 +1608,29 @@ static int generate_constructor(struct generator * g) {
1556
1608
  }
1557
1609
 
1558
1610
  static void generate_methods(struct generator * g) {
1559
- struct node * p = g->analyser->program;
1560
- while (p != 0) {
1611
+ for (struct node * p = g->analyser->program; p; p = p->right) {
1561
1612
  generate(g, p);
1562
- p = p->right;
1613
+ g->unreachable = false;
1563
1614
  }
1564
1615
  }
1565
1616
 
1566
1617
  static int generate_operations_dispatcher(struct generator * g) {
1567
- struct among * a = g->analyser->amongs;
1568
- int i;
1569
1618
  int operation = 0;
1570
1619
 
1571
1620
  w(g, "~N~Mprocedure Among_Handler (Context : in out Stemmer.Context_Type'Class; Operation : in Operation_Index; Result : out Boolean) is~N");
1572
1621
  w(g, "~Mbegin~+~N~M");
1573
1622
  w(g, "case Operation is~+~N~M");
1574
- a = g->analyser->amongs;
1575
- while (a != 0) {
1576
- struct amongvec * v = a->b;
1577
- for (i = 0; i < a->literalstring_count; i++, v++) {
1578
- if (v->function != 0) {
1623
+ for (struct among * x = g->analyser->amongs; x; x = x->next) {
1624
+ struct amongvec * v = x->b;
1625
+ for (int i = 0; i < x->literalstring_count; i++) {
1626
+ if (v[i].function != NULL) {
1579
1627
  operation++;
1580
1628
  g->I[2] = operation;
1581
1629
  w(g, "when ~I2 =>~N~M");
1582
- g->V[0] = v->function;
1630
+ g->V[0] = v[i].function;
1583
1631
  w(g, " ~W0 (Context_Type (Context), Result);~N~M");
1584
1632
  }
1585
1633
  }
1586
- a = a->next;
1587
1634
  }
1588
1635
  w(g, "when others =>~N~M");
1589
1636
  w(g, " Result := False;~-~N~Mend case;~-~N~M");
@@ -1594,36 +1641,29 @@ static int generate_operations_dispatcher(struct generator * g) {
1594
1641
  static void set_bit(symbol * b, int i) { b[i/8] |= 1 << i%8; }
1595
1642
 
1596
1643
  static void generate_grouping_table(struct generator * g, struct grouping * q) {
1597
-
1598
1644
  int range = q->largest_ch - q->smallest_ch + 1;
1599
1645
  int size = (range + 7)/ 8; /* assume 8 bits per symbol */
1600
1646
  symbol * b = q->b;
1601
1647
  symbol * map = create_b(size);
1602
- int i;
1603
- int count = 0;
1604
1648
  int need_comma = 0;
1605
1649
 
1606
- for (i = 0; i < size; i++) map[i] = 0;
1650
+ for (int i = 0; i < size; i++) map[i] = 0;
1607
1651
 
1608
- /* Using unicode would require revision here */
1609
-
1610
- for (i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1652
+ for (int i = 0; i < SIZE(b); i++) set_bit(map, b[i] - q->smallest_ch);
1611
1653
 
1612
1654
  g->V[0] = q->name;
1613
1655
  g->I[0] = 8 * size - 1;
1614
1656
  w(g, "~N~M~W0 : constant Grouping_Array (0 .. ~I0) := (~N~+~M");
1615
- for (i = 0; i < size; i++) {
1657
+ for (int i = 0; i < size; i++) {
1616
1658
  unsigned char m = map[i];
1617
- int j;
1618
- count++;
1619
1659
  if (i != 0) {
1620
1660
  w(g, ",~N~M");
1621
1661
  need_comma = 0;
1622
1662
  }
1623
- for (j = 0; j < 8; j++) {
1663
+ for (int j = 0; j < 8; j++) {
1624
1664
  if (need_comma)
1625
1665
  w(g, ", ");
1626
-
1666
+
1627
1667
  if (m & (1 << j)) {
1628
1668
  w(g, "True");
1629
1669
  } else {
@@ -1633,20 +1673,18 @@ static void generate_grouping_table(struct generator * g, struct grouping * q) {
1633
1673
  }
1634
1674
  }
1635
1675
  w(g, "~N~-~M);~N");
1636
-
1676
+
1637
1677
  lose_b(map);
1638
1678
  }
1639
1679
 
1640
1680
  static void generate_groupings(struct generator * g) {
1641
- struct grouping * q;
1642
- for (q = g->analyser->groupings; q; q = q->next) {
1681
+ for (struct grouping * q = g->analyser->groupings; q; q = q->next) {
1643
1682
  if (q->name->used)
1644
1683
  generate_grouping_table(g, q);
1645
1684
  }
1646
1685
  }
1647
1686
 
1648
1687
  extern void generate_program_ada(struct generator * g) {
1649
-
1650
1688
  g->outbuf = str_new();
1651
1689
  g->failure_str = str_new();
1652
1690
 
@@ -1683,7 +1721,7 @@ extern void generate_program_ada(struct generator * g) {
1683
1721
 
1684
1722
  g->margin = 0;
1685
1723
  write_start_comment(g, "-- ", NULL);
1686
- if (has_string_variable(g)) {
1724
+ if (g->analyser->name_count[t_string]) {
1687
1725
  w(g, "private with Ada.Strings.Unbounded;~N");
1688
1726
  }
1689
1727
  w(g, "package Stemmer.");