]> git.saurik.com Git - bison.git/blame - src/muscle-tab.c
errors: indent "invalid value for %define" context
[bison.git] / src / muscle-tab.c
CommitLineData
e00b6826
PE
1/* Muscle table manager for Bison.
2
c932d613 3 Copyright (C) 2001-2012 Free Software Foundation, Inc.
f753cd62
MA
4
5 This file is part of Bison, the GNU Compiler Compiler.
6
f16b0819 7 This program is free software: you can redistribute it and/or modify
f753cd62 8 it under the terms of the GNU General Public License as published by
f16b0819
PE
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
f753cd62 11
f16b0819 12 This program is distributed in the hope that it will be useful,
f753cd62
MA
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
f16b0819 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
f753cd62 19
2cec9080 20#include <config.h>
f753cd62 21#include "system.h"
8322e8f5
PE
22
23#include <hash.h>
8322e8f5 24
9611cfa2 25#include "complain.h"
f753cd62 26#include "files.h"
f508cb0a 27#include "getargs.h"
4c787a31
AD
28#include "muscle-tab.h"
29#include "quote.h"
f753cd62 30
eb095650
PE
31/* A key-value pair, along with storage that can be reclaimed when
32 this pair is no longer needed. */
8322e8f5
PE
33typedef struct
34{
eb095650
PE
35 char const *key;
36 char const *value;
37 char *storage;
8322e8f5 38} muscle_entry;
592e8d4d
AD
39
40/* An obstack used to create some entries. */
41struct obstack muscle_obstack;
42
beda758b
AD
43/* Initial capacity of muscles hash table. */
44#define HT_INITIAL_CAPACITY 257
f753cd62 45
04098407 46static struct hash_table *muscle_table = NULL;
f753cd62 47
beda758b
AD
48static bool
49hash_compare_muscles (void const *x, void const *y)
f753cd62 50{
8322e8f5
PE
51 muscle_entry const *m1 = x;
52 muscle_entry const *m2 = y;
5dd5fd4a 53 return strcmp (m1->key, m2->key) == 0;
f753cd62
MA
54}
55
233a88ad
PE
56static size_t
57hash_muscle (const void *x, size_t tablesize)
f753cd62 58{
8322e8f5 59 muscle_entry const *m = x;
beda758b 60 return hash_string (m->key, tablesize);
f753cd62
MA
61}
62
592e8d4d
AD
63/*-----------------------------------------------------------------.
64| Create the MUSCLE_TABLE, and initialize it with default values. |
65| Also set up the MUSCLE_OBSTACK. |
66`-----------------------------------------------------------------*/
67
eb095650
PE
68static void
69muscle_entry_free (void *entry)
70{
71 muscle_entry *mentry = entry;
72 free (mentry->storage);
73 free (mentry);
74}
75
f753cd62
MA
76void
77muscle_init (void)
78{
ae7453f2
AD
79 /* Initialize the muscle obstack. */
80 obstack_init (&muscle_obstack);
81
beda758b 82 muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
eb095650 83 hash_compare_muscles, muscle_entry_free);
f753cd62
MA
84
85 /* Version and input file. */
ae7453f2 86 MUSCLE_INSERT_STRING ("version", VERSION);
f753cd62
MA
87}
88
592e8d4d
AD
89
90/*------------------------------------------------------------.
91| Free all the memory consumed by the muscle machinery only. |
92`------------------------------------------------------------*/
93
94void
95muscle_free (void)
96{
97 hash_free (muscle_table);
98 obstack_free (&muscle_obstack, NULL);
99}
100
101
102
ae7453f2
AD
103/*------------------------------------------------------------.
104| Insert (KEY, VALUE). If KEY already existed, overwrite the |
105| previous value. |
106`------------------------------------------------------------*/
107
a870c567 108void
eb095650 109muscle_insert (char const *key, char const *value)
f753cd62 110{
8322e8f5 111 muscle_entry probe;
da2a7671 112 muscle_entry *entry;
e9bca3ad 113
ae7453f2
AD
114 probe.key = key;
115 entry = hash_lookup (muscle_table, &probe);
beda758b
AD
116
117 if (!entry)
118 {
119 /* First insertion in the hash. */
da2a7671 120 entry = xmalloc (sizeof *entry);
beda758b 121 entry->key = key;
75c7a52a
AD
122 if (!hash_insert (muscle_table, entry))
123 xalloc_die ();
beda758b 124 }
4502eadc
JD
125 else
126 free (entry->storage);
beda758b 127 entry->value = value;
4502eadc 128 entry->storage = NULL;
f753cd62
MA
129}
130
ae7453f2
AD
131
132/*-------------------------------------------------------------------.
ff5150d9
PE
133| Append VALUE to the current value of KEY. If KEY did not already |
134| exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously |
135| associated value. Copy VALUE and SEPARATOR. |
ae7453f2
AD
136`-------------------------------------------------------------------*/
137
138void
139muscle_grow (const char *key, const char *val, const char *separator)
140{
8322e8f5
PE
141 muscle_entry probe;
142 muscle_entry *entry = NULL;
ae7453f2
AD
143
144 probe.key = key;
145 entry = hash_lookup (muscle_table, &probe);
146
147 if (!entry)
148 {
149 /* First insertion in the hash. */
da2a7671 150 entry = xmalloc (sizeof *entry);
ae7453f2 151 entry->key = key;
75c7a52a
AD
152 if (!hash_insert (muscle_table, entry))
153 xalloc_die ();
eb095650 154 entry->value = entry->storage = xstrdup (val);
ae7453f2
AD
155 }
156 else
157 {
158 /* Grow the current value. */
159 char *new_val;
ae7453f2 160 obstack_sgrow (&muscle_obstack, entry->value);
eb095650 161 free (entry->storage);
ae7453f2
AD
162 obstack_sgrow (&muscle_obstack, separator);
163 obstack_sgrow (&muscle_obstack, val);
164 obstack_1grow (&muscle_obstack, 0);
165 new_val = obstack_finish (&muscle_obstack);
eb095650 166 entry->value = entry->storage = xstrdup (new_val);
ae7453f2
AD
167 obstack_free (&muscle_obstack, new_val);
168 }
169}
170
cd3684cf 171/*------------------------------------------------------------------.
35b8730d
JD
172| Using muscle_grow, append a synchronization line for the location |
173| LOC to the current value of KEY. |
cd3684cf
AD
174`------------------------------------------------------------------*/
175
35b8730d
JD
176static void
177muscle_syncline_grow (char const *key, location loc)
cd3684cf
AD
178{
179 char *extension = NULL;
aaf63e45 180 obstack_printf (&muscle_obstack, "]b4_syncline(%d, ", loc.start.line);
0601c3bf
AD
181 obstack_quote (&muscle_obstack,
182 quotearg_style (c_quoting_style, loc.start.file));
183 obstack_sgrow (&muscle_obstack, ")[");
cd3684cf
AD
184 obstack_1grow (&muscle_obstack, 0);
185 extension = obstack_finish (&muscle_obstack);
186 muscle_grow (key, extension, "");
eb095650 187 obstack_free (&muscle_obstack, extension);
cd3684cf
AD
188}
189
35b8730d
JD
190/*------------------------------------------------------------------.
191| Append VALUE to the current value of KEY, using muscle_grow. But |
192| in addition, issue a synchronization line for the location LOC |
193| using muscle_syncline_grow. |
194`------------------------------------------------------------------*/
195
196void
197muscle_code_grow (const char *key, const char *val, location loc)
198{
199 muscle_syncline_grow (key, loc);
200 muscle_grow (key, val, "\n");
201}
202
cd3684cf 203
ae7453f2
AD
204void muscle_pair_list_grow (const char *muscle,
205 const char *a1, const char *a2)
206{
66d30cd4 207 char *pair;
0601c3bf
AD
208 obstack_sgrow (&muscle_obstack, "[");
209 obstack_quote (&muscle_obstack, a1);
210 obstack_sgrow (&muscle_obstack, ", ");
211 obstack_quote (&muscle_obstack, a2);
212 obstack_sgrow (&muscle_obstack, "]");
ae7453f2 213 obstack_1grow (&muscle_obstack, 0);
66d30cd4
AD
214 pair = obstack_finish (&muscle_obstack);
215 muscle_grow (muscle, pair, ",\n");
216 obstack_free (&muscle_obstack, pair);
ae7453f2
AD
217}
218
7eb8a0bc
JD
219
220/*----------------------------------------------------------------------------.
221| Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always reliable |
222| to determine whether KEY has a value. |
223`----------------------------------------------------------------------------*/
224
225char const *
226muscle_find_const (char const *key)
227{
228 muscle_entry probe;
229 muscle_entry *result = NULL;
230
231 probe.key = key;
232 result = hash_lookup (muscle_table, &probe);
233 if (result)
234 return result->value;
235 return NULL;
236}
237
238
4502eadc
JD
239/*----------------------------------------------------------------------------.
240| Find the value of muscle KEY. Abort if muscle_insert was invoked more |
241| recently than muscle_grow for KEY since muscle_find can't return a |
242| char const *. |
243`----------------------------------------------------------------------------*/
ae7453f2 244
ff5150d9 245char *
7eb8a0bc 246muscle_find (char const *key)
f753cd62 247{
8322e8f5
PE
248 muscle_entry probe;
249 muscle_entry *result = NULL;
e9bca3ad 250
ae7453f2
AD
251 probe.key = key;
252 result = hash_lookup (muscle_table, &probe);
4502eadc
JD
253 if (result)
254 {
255 aver (result->value == result->storage);
256 return result->storage;
257 }
258 return NULL;
f753cd62 259}
be2a1a68
AD
260
261
e5878229
AD
262/* In the format `file_name:line.column', append BOUND to MUSCLE. Use
263 digraphs for special characters in the file name. */
264
265static void
9611cfa2
JD
266muscle_boundary_grow (char const *key, boundary bound)
267{
268 char *extension;
eea7239a 269 obstack_sgrow (&muscle_obstack, "[[");
13b712d7 270 obstack_escape (&muscle_obstack, bound.file);
eea7239a 271 obstack_1grow (&muscle_obstack, ':');
aaf63e45 272 obstack_printf (&muscle_obstack, "%d", bound.line);
eea7239a 273 obstack_1grow (&muscle_obstack, '.');
aaf63e45 274 obstack_printf (&muscle_obstack, "%d", bound.column);
eea7239a
AD
275 obstack_sgrow (&muscle_obstack, "]]");
276 obstack_1grow (&muscle_obstack, '\0');
9611cfa2
JD
277 extension = obstack_finish (&muscle_obstack);
278 muscle_grow (key, extension, "");
279 obstack_free (&muscle_obstack, extension);
280}
281
e5878229
AD
282
283/* In the format `[[file_name:line.column]], [[file_name:line.column]]',
284 append LOC to MUSCLE. Use digraphs for special characters in each
285 file name. */
286
287static void
9611cfa2
JD
288muscle_location_grow (char const *key, location loc)
289{
9611cfa2 290 muscle_boundary_grow (key, loc.start);
eea7239a 291 muscle_grow (key, "", ", ");
9611cfa2 292 muscle_boundary_grow (key, loc.end);
9611cfa2
JD
293}
294
c1cc91bd 295#define COMMON_DECODE(Value) \
9b858541
AD
296 case '$': \
297 aver (*++(Value) == ']'); \
298 aver (*++(Value) == '['); \
299 obstack_sgrow (&muscle_obstack, "$"); \
300 break; \
301 case '@': \
302 switch (*++(Value)) \
303 { \
304 case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \
305 case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \
306 case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \
307 default: aver (false); break; \
308 } \
309 break; \
310 default: \
311 obstack_1grow (&muscle_obstack, *(Value)); \
f124d423
JD
312 break;
313
c1cc91bd 314/* Reverse of obstack_escape. */
f124d423 315static char *
c1cc91bd 316string_decode (char const *key)
f124d423
JD
317{
318 char const *value;
319 char *value_decoded;
320 char *result;
321
322 value = muscle_find_const (key);
323 if (!value)
324 return NULL;
325 do {
326 switch (*value)
327 {
c1cc91bd 328 COMMON_DECODE (value)
f124d423
JD
329 case '[':
330 case ']':
331 aver (false);
332 break;
333 }
334 } while (*value++);
335 value_decoded = obstack_finish (&muscle_obstack);
336 result = xstrdup (value_decoded);
337 obstack_free (&muscle_obstack, value_decoded);
338 return result;
339}
340
9611cfa2
JD
341/* Reverse of muscle_location_grow. */
342static location
c1cc91bd 343location_decode (char const *key)
9611cfa2
JD
344{
345 location loc;
346 char const *value = muscle_find_const (key);
347 aver (value);
348 aver (*value == '[');
349 aver (*++value == '[');
350 while (*++value)
351 switch (*value)
352 {
c1cc91bd 353 COMMON_DECODE (value)
9611cfa2
JD
354 case '[':
355 aver (false);
356 break;
357 case ']':
358 {
359 char *boundary_str;
360 aver (*++value == ']');
361 obstack_1grow (&muscle_obstack, '\0');
362 boundary_str = obstack_finish (&muscle_obstack);
363 switch (*++value)
364 {
365 case ',':
366 boundary_set_from_string (&loc.start, boundary_str);
367 obstack_free (&muscle_obstack, boundary_str);
368 aver (*++value == ' ');
369 aver (*++value == '[');
370 aver (*++value == '[');
371 break;
372 case '\0':
373 boundary_set_from_string (&loc.end, boundary_str);
374 obstack_free (&muscle_obstack, boundary_str);
375 return loc;
376 break;
377 default:
378 aver (false);
379 break;
380 }
381 }
382 break;
9611cfa2
JD
383 }
384 aver (false);
385 return loc;
386}
387
388void
389muscle_user_name_list_grow (char const *key, char const *user_name,
390 location loc)
391{
392 muscle_grow (key, "[[[[", ",");
393 muscle_grow (key, user_name, "");
394 muscle_grow (key, "]], ", "");
395 muscle_location_grow (key, loc);
396 muscle_grow (key, "]]", "");
397}
398
9611cfa2
JD
399void
400muscle_percent_define_insert (char const *variable, location variable_loc,
34d41938
JD
401 char const *value,
402 muscle_percent_define_how how)
9611cfa2 403{
812775a0 404 char *variable_tr = NULL;
9611cfa2
JD
405 char const *name;
406 char const *loc_name;
35b8730d 407 char const *syncline_name;
34d41938 408 char const *how_name;
9611cfa2 409
812775a0
JD
410 /* Permit certain names with underscores for backward compatibility. */
411 if (0 == strcmp (variable, "api.push_pull")
412 || 0 == strcmp (variable, "lr.keep_unreachable_states"))
413 {
414 variable_tr = strdup (variable);
415 tr (variable_tr, '_', '-');
416 variable = variable_tr;
417 }
418
0ab402b4
JD
419 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
420 loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
421 syncline_name =
422 UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
423 how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
9611cfa2 424
34d41938
JD
425 /* Command-line options are processed before the grammar file. */
426 if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
427 && muscle_find_const (name))
9611cfa2 428 {
6b1e1872 429 unsigned i = 0;
34d41938
JD
430 muscle_percent_define_how how_old =
431 atoi (muscle_find_const (how_name));
432 if (how_old == MUSCLE_PERCENT_DEFINE_F)
433 {
434 free (variable_tr);
435 return;
436 }
6b1e1872
TR
437 complain_at_indent (variable_loc, &i,
438 _("%%define variable %s redefined"), quote (variable));
439 i += SUB_INDENT;
440 complain_at_indent (muscle_percent_define_get_loc (variable), &i,
441 _("previous definition"));
9611cfa2 442 }
9611cfa2 443
34d41938 444 MUSCLE_INSERT_STRING (name, value);
9611cfa2
JD
445 muscle_insert (loc_name, "");
446 muscle_location_grow (loc_name, variable_loc);
35b8730d
JD
447 muscle_insert (syncline_name, "");
448 muscle_syncline_grow (syncline_name, variable_loc);
9611cfa2
JD
449 muscle_user_name_list_grow ("percent_define_user_variables", variable,
450 variable_loc);
34d41938 451 MUSCLE_INSERT_INT (how_name, how);
812775a0
JD
452
453 free (variable_tr);
9611cfa2
JD
454}
455
f124d423
JD
456char *
457muscle_percent_define_get (char const *variable)
458{
459 char const *name;
460 char const *usage_name;
461 char *value;
462
0ab402b4
JD
463 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
464 usage_name = UNIQSTR_CONCAT ("percent_define_bison_variables(",
465 variable, ")");
f124d423
JD
466
467 muscle_insert (usage_name, "");
c1cc91bd 468 value = string_decode (name);
f124d423
JD
469 if (!value)
470 value = xstrdup ("");
471 return value;
472}
473
35b8730d
JD
474location
475muscle_percent_define_get_loc (char const *variable)
476{
477 char const *loc_name;
0ab402b4 478 loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
35b8730d 479 if (!muscle_find_const (loc_name))
4c787a31
AD
480 fatal(_("%s: undefined %%define variable %s"),
481 "muscle_percent_define_get_loc", quote (variable));
c1cc91bd 482 return location_decode (loc_name);
35b8730d
JD
483}
484
485char const *
486muscle_percent_define_get_syncline (char const *variable)
487{
488 char const *syncline_name;
489 char const *syncline;
0ab402b4
JD
490 syncline_name =
491 UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
35b8730d
JD
492 syncline = muscle_find_const (syncline_name);
493 if (!syncline)
4c787a31
AD
494 fatal(_("%s: undefined %%define variable %s"),
495 "muscle_percent_define_get_syncline", quote (variable));
35b8730d
JD
496 return syncline;
497}
498
f124d423
JD
499bool
500muscle_percent_define_ifdef (char const *variable)
501{
502 char const *name;
503 char const *usage_name;
504 char const *value;
505
0ab402b4
JD
506 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
507 usage_name =
508 UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
f124d423
JD
509
510 value = muscle_find_const (name);
511 if (value)
512 {
513 muscle_insert (usage_name, "");
514 return true;
515 }
516
517 return false;
518}
519
9611cfa2
JD
520bool
521muscle_percent_define_flag_if (char const *variable)
522{
cbd50549 523 char const *invalid_boolean_name;
9611cfa2
JD
524 bool result = false;
525
0ab402b4
JD
526 invalid_boolean_name =
527 UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
9611cfa2 528
f124d423 529 if (muscle_percent_define_ifdef (variable))
9611cfa2 530 {
f124d423 531 char *value = muscle_percent_define_get (variable);
9611cfa2
JD
532 if (value[0] == '\0' || 0 == strcmp (value, "true"))
533 result = true;
534 else if (0 == strcmp (value, "false"))
535 result = false;
cbd50549
JD
536 else if (!muscle_find_const (invalid_boolean_name))
537 {
538 muscle_insert (invalid_boolean_name, "");
35b8730d 539 complain_at(muscle_percent_define_get_loc (variable),
4c787a31
AD
540 _("invalid value for %%define Boolean variable %s"),
541 quote (variable));
cbd50549 542 }
f124d423 543 free (value);
9611cfa2
JD
544 }
545 else
4c787a31
AD
546 fatal(_("%s: undefined %%define variable %s"),
547 "muscle_percent_define_flag", quote (variable));
9611cfa2 548
9611cfa2
JD
549 return result;
550}
551
552void
553muscle_percent_define_default (char const *variable, char const *value)
554{
555 char const *name;
556 char const *loc_name;
35b8730d 557 char const *syncline_name;
0ab402b4
JD
558 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
559 loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
560 syncline_name =
561 UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
9611cfa2
JD
562 if (!muscle_find_const (name))
563 {
564 location loc;
565 MUSCLE_INSERT_STRING (name, value);
580c075d
JD
566 loc.start.file = loc.end.file = "<default value>";
567 loc.start.line = loc.end.line = -1;
568 loc.start.column = loc.end.column = -1;
9611cfa2
JD
569 muscle_insert (loc_name, "");
570 muscle_location_grow (loc_name, loc);
35b8730d 571 muscle_insert (syncline_name, "");
9611cfa2
JD
572 }
573}
574
f124d423 575void
b1a81613 576muscle_percent_define_check_values (char const * const *values)
f124d423 577{
b1a81613
JD
578 for (; *values; ++values)
579 {
25029e16 580 char const * const *variablep = values;
b1a81613 581 char const *name;
b1a81613
JD
582 char *value;
583
0ab402b4 584 name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
b1a81613 585
c1cc91bd 586 value = string_decode (name);
b1a81613
JD
587 if (value)
588 {
b1a81613
JD
589 for (++values; *values; ++values)
590 {
591 if (0 == strcmp (value, *values))
25029e16
JD
592 break;
593 }
594 if (!*values)
595 {
a974c1ec 596 unsigned i = 0;
25029e16 597 location loc = muscle_percent_define_get_loc (*variablep);
a974c1ec
TR
598 complain_at_indent (loc, &i,
599 _("invalid value for %%define variable %s: %s"),
600 quote (*variablep), quote_n (1, value));
601 i += SUB_INDENT;
25029e16 602 for (values = variablep + 1; *values; ++values)
a974c1ec
TR
603 complain_at_indent (loc, &i, _("accepted value: %s"),
604 quote (*values));
25029e16
JD
605 }
606 else
607 {
608 while (*values)
609 ++values;
b1a81613 610 }
b1a81613
JD
611 free (value);
612 }
613 else
4c787a31
AD
614 fatal (_("%s: undefined %%define variable %s"),
615 "muscle_percent_define_check_values", quote (*variablep));
b1a81613 616 }
f124d423
JD
617}
618
9611cfa2
JD
619void
620muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
621 char const *code, location code_loc)
622{
623 char const *name;
0ab402b4 624 name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
9611cfa2
JD
625 muscle_code_grow (name, code, code_loc);
626 muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
627 qualifier_loc);
628}
629
630
ae7453f2
AD
631/*------------------------------------------------.
632| Output the definition of ENTRY as a m4_define. |
633`------------------------------------------------*/
be2a1a68 634
e00b6826 635static inline bool
8322e8f5 636muscle_m4_output (muscle_entry *entry, FILE *out)
be2a1a68
AD
637{
638 fprintf (out, "m4_define([b4_%s],\n", entry->key);
ae7453f2 639 fprintf (out, "[[%s]])\n\n\n", entry->value);
e00b6826
PE
640 return true;
641}
642
643static bool
644muscle_m4_output_processor (void *entry, void *out)
645{
646 return muscle_m4_output (entry, out);
be2a1a68
AD
647}
648
649
ae7453f2
AD
650/*----------------------------------------------------------------.
651| Output the definition of all the current muscles into a list of |
652| m4_defines. |
653`----------------------------------------------------------------*/
be2a1a68
AD
654
655void
656muscles_m4_output (FILE *out)
657{
e00b6826 658 hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
be2a1a68 659}