xref: /freebsd/contrib/bc/include/lang.h (revision fdc4a7c8012b214986cfa2e2fb6d99731f004b1b)
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2025 Gavin D. Howard and contributors.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * *****************************************************************************
31  *
32  * Definitions for program data.
33  *
34  */
35 
36 #ifndef BC_LANG_H
37 #define BC_LANG_H
38 
39 #include <stdbool.h>
40 
41 // These have to come first to silence a warning on BC_C11 below.
42 #include <status.h>
43 #include <vector.h>
44 #include <num.h>
45 
46 #if BC_C11
47 #include <assert.h>
48 #endif // BC_C11
49 
50 /// The instructions for bytecode.
51 typedef enum BcInst
52 {
53 #if BC_ENABLED
54 	/// Postfix increment and decrement. Prefix are translated into
55 	/// BC_INST_ONE with either BC_INST_ASSIGN_PLUS or BC_INST_ASSIGN_MINUS.
56 	BC_INST_INC = 0,
57 	BC_INST_DEC,
58 #endif // BC_ENABLED
59 
60 	/// Unary negation.
61 	BC_INST_NEG,
62 
63 	/// Boolean not.
64 	BC_INST_BOOL_NOT,
65 
66 #if BC_ENABLE_EXTRA_MATH
67 	/// Truncation operator.
68 	BC_INST_TRUNC,
69 #endif // BC_ENABLE_EXTRA_MATH
70 
71 	/// These should be self-explanatory.
72 	BC_INST_POWER,
73 	BC_INST_MULTIPLY,
74 	BC_INST_DIVIDE,
75 	BC_INST_MODULUS,
76 	BC_INST_PLUS,
77 	BC_INST_MINUS,
78 
79 #if BC_ENABLE_EXTRA_MATH
80 	/// Places operator.
81 	BC_INST_PLACES,
82 
83 	/// Shift operators.
84 	BC_INST_LSHIFT,
85 	BC_INST_RSHIFT,
86 #endif // BC_ENABLE_EXTRA_MATH
87 
88 	/// Comparison operators.
89 	BC_INST_REL_EQ,
90 	BC_INST_REL_LE,
91 	BC_INST_REL_GE,
92 	BC_INST_REL_NE,
93 	BC_INST_REL_LT,
94 	BC_INST_REL_GT,
95 
96 	/// Boolean or and and.
97 	BC_INST_BOOL_OR,
98 	BC_INST_BOOL_AND,
99 
100 #if BC_ENABLED
101 	/// Same as the normal operators, but assigment. So ^=, *=, /=, etc.
102 	BC_INST_ASSIGN_POWER,
103 	BC_INST_ASSIGN_MULTIPLY,
104 	BC_INST_ASSIGN_DIVIDE,
105 	BC_INST_ASSIGN_MODULUS,
106 	BC_INST_ASSIGN_PLUS,
107 	BC_INST_ASSIGN_MINUS,
108 #if BC_ENABLE_EXTRA_MATH
109 	/// Places and shift assignment operators.
110 	BC_INST_ASSIGN_PLACES,
111 	BC_INST_ASSIGN_LSHIFT,
112 	BC_INST_ASSIGN_RSHIFT,
113 #endif // BC_ENABLE_EXTRA_MATH
114 
115 	/// Normal assignment.
116 	BC_INST_ASSIGN,
117 
118 	/// bc and dc detect when the value from an assignment is not necessary.
119 	/// For example, a plain assignment statement means the value is never used.
120 	/// In those cases, we can get lots of performance back by not even creating
121 	/// a copy at all. In fact, it saves a copy, a push onto the results stack,
122 	/// a pop from the results stack, and a free. Definitely worth it to detect.
123 	BC_INST_ASSIGN_POWER_NO_VAL,
124 	BC_INST_ASSIGN_MULTIPLY_NO_VAL,
125 	BC_INST_ASSIGN_DIVIDE_NO_VAL,
126 	BC_INST_ASSIGN_MODULUS_NO_VAL,
127 	BC_INST_ASSIGN_PLUS_NO_VAL,
128 	BC_INST_ASSIGN_MINUS_NO_VAL,
129 #if BC_ENABLE_EXTRA_MATH
130 	/// Same as above.
131 	BC_INST_ASSIGN_PLACES_NO_VAL,
132 	BC_INST_ASSIGN_LSHIFT_NO_VAL,
133 	BC_INST_ASSIGN_RSHIFT_NO_VAL,
134 #endif // BC_ENABLE_EXTRA_MATH
135 #endif // BC_ENABLED
136 
137 	/// Normal assignment that pushes no value on the stack.
138 	BC_INST_ASSIGN_NO_VAL,
139 
140 	/// Push a constant onto the results stack.
141 	BC_INST_NUM,
142 
143 	/// Push a variable onto the results stack.
144 	BC_INST_VAR,
145 
146 	/// Push an array element onto the results stack.
147 	BC_INST_ARRAY_ELEM,
148 
149 	/// Push an array onto the results stack. This is different from pushing an
150 	/// array *element* onto the results stack; it pushes a reference to the
151 	/// whole array. This is needed in bc for function arguments that are
152 	/// arrays. It is also needed for returning the length of an array.
153 	BC_INST_ARRAY,
154 
155 	/// Push a zero or a one onto the stack. These are special cased because it
156 	/// does help performance, particularly for one since inc/dec operators
157 	/// use it.
158 	BC_INST_ZERO,
159 	BC_INST_ONE,
160 
161 #if BC_ENABLED
162 	/// Push the last printed value onto the stack.
163 	BC_INST_LAST,
164 #endif // BC_ENABLED
165 
166 	/// Push the value of any of the globals onto the stack.
167 	BC_INST_IBASE,
168 	BC_INST_OBASE,
169 	BC_INST_SCALE,
170 
171 #if BC_ENABLE_EXTRA_MATH
172 	/// Push the value of the seed global onto the stack.
173 	BC_INST_SEED,
174 #endif // BC_ENABLE_EXTRA_MATH
175 
176 	/// These are builtin functions.
177 	BC_INST_LENGTH,
178 	BC_INST_SCALE_FUNC,
179 	BC_INST_SQRT,
180 	BC_INST_ABS,
181 	BC_INST_IS_NUMBER,
182 	BC_INST_IS_STRING,
183 
184 #if BC_ENABLE_EXTRA_MATH
185 	/// Another builtin function.
186 	BC_INST_IRAND,
187 #endif // BC_ENABLE_EXTRA_MATH
188 
189 	/// Asciify.
190 	BC_INST_ASCIIFY,
191 
192 	/// Another builtin function.
193 	BC_INST_READ,
194 
195 #if BC_ENABLE_EXTRA_MATH
196 	/// Another builtin function.
197 	BC_INST_RAND,
198 #endif // BC_ENABLE_EXTRA_MATH
199 
200 	/// Return the max for the various globals.
201 	BC_INST_MAXIBASE,
202 	BC_INST_MAXOBASE,
203 	BC_INST_MAXSCALE,
204 #if BC_ENABLE_EXTRA_MATH
205 	/// Return the max value returned by rand().
206 	BC_INST_MAXRAND,
207 #endif // BC_ENABLE_EXTRA_MATH
208 
209 	/// bc line_length() builtin function.
210 	BC_INST_LINE_LENGTH,
211 
212 #if BC_ENABLED
213 
214 	/// bc global_stacks() builtin function.
215 	BC_INST_GLOBAL_STACKS,
216 
217 #endif // BC_ENABLED
218 
219 	/// bc leading_zero() builtin function.
220 	BC_INST_LEADING_ZERO,
221 
222 	/// This is slightly misnamed versus BC_INST_PRINT_POP. Well, it is in bc.
223 	/// dc uses this instruction to print, but not pop. That's valid in dc.
224 	/// However, in bc, it is *never* valid to print without popping. In bc,
225 	/// BC_INST_PRINT_POP is used to indicate when a string should be printed
226 	/// because of a print statement or whether it should be printed raw. The
227 	/// reason for this is because a print statement handles escaped characters.
228 	/// So BC_INST_PRINT_POP is for printing a string from a print statement,
229 	/// BC_INST_PRINT_STR is for printing a string by itself.
230 	///
231 	/// In dc, BC_INST_PRINT_POP prints and pops, and BC_INST_PRINT just prints.
232 	///
233 	/// Oh, and BC_INST_STR pushes a string onto the results stack.
234 	BC_INST_PRINT,
235 	BC_INST_PRINT_POP,
236 	BC_INST_STR,
237 #if BC_ENABLED
238 	BC_INST_PRINT_STR,
239 
240 	/// Jumps unconditionally.
241 	BC_INST_JUMP,
242 
243 	/// Jumps if the top of the results stack is zero (condition failed). It
244 	/// turns out that we only want to jump when conditions fail to "skip" code.
245 	BC_INST_JUMP_ZERO,
246 
247 	/// Call a function.
248 	BC_INST_CALL,
249 
250 	/// Return the top of the stack to the caller.
251 	BC_INST_RET,
252 
253 	/// Return 0 to the caller.
254 	BC_INST_RET0,
255 
256 	/// Special return instruction for void functions.
257 	BC_INST_RET_VOID,
258 
259 	/// Special halt instruction.
260 	BC_INST_HALT,
261 #endif // BC_ENABLED
262 
263 	/// Pop an item off of the results stack.
264 	BC_INST_POP,
265 
266 	/// Swaps the top two items on the results stack.
267 	BC_INST_SWAP,
268 
269 	/// Modular exponentiation.
270 	BC_INST_MODEXP,
271 
272 	/// Do divide and modulus at the same time.
273 	BC_INST_DIVMOD,
274 
275 	/// Turns a number into a string and prints it.
276 	BC_INST_PRINT_STREAM,
277 
278 #if DC_ENABLED
279 
280 	/// dc extended registers command.
281 	BC_INST_EXTENDED_REGISTERS,
282 
283 	/// dc's return; it pops an executing string off of the stack.
284 	BC_INST_POP_EXEC,
285 
286 	/// Unconditionally execute a string.
287 	BC_INST_EXECUTE,
288 
289 	/// Conditionally execute a string.
290 	BC_INST_EXEC_COND,
291 
292 	/// Prints each item on the results stack, separated by newlines.
293 	BC_INST_PRINT_STACK,
294 
295 	/// Pops everything off of the results stack.
296 	BC_INST_CLEAR_STACK,
297 
298 	/// Pushes the current length of a register stack onto the results stack.
299 	BC_INST_REG_STACK_LEN,
300 
301 	/// Pushes the current length of the results stack onto the results stack.
302 	BC_INST_STACK_LEN,
303 
304 	/// Pushes a copy of the item on the top of the results stack onto the
305 	/// results stack.
306 	BC_INST_DUPLICATE,
307 
308 	/// Copies the value in a register and pushes the copy onto the results
309 	/// stack.
310 	BC_INST_LOAD,
311 
312 	/// Pops an item off of a register stack and pushes it onto the results
313 	/// stack.
314 	BC_INST_PUSH_VAR,
315 
316 	/// Pops an item off of the results stack and pushes it onto a register's
317 	/// stack.
318 	BC_INST_PUSH_TO_VAR,
319 
320 	/// Quit.
321 	BC_INST_QUIT,
322 
323 	/// Quit executing some number of strings.
324 	BC_INST_NQUIT,
325 
326 	/// Push the depth of the execution stack onto the stack.
327 	BC_INST_EXEC_STACK_LEN,
328 
329 #endif // DC_ENABLED
330 
331 	/// Invalid instruction.
332 	BC_INST_INVALID,
333 
334 } BcInst;
335 
336 #if BC_C11
337 _Static_assert(BC_INST_INVALID <= UCHAR_MAX,
338                "Too many instructions to fit into an unsigned char");
339 #endif // BC_C11
340 
341 /// Used by maps to identify where items are in the array.
342 typedef struct BcId
343 {
344 	/// The name of the item.
345 	char* name;
346 
347 	/// The index into the array where the item is.
348 	size_t idx;
349 
350 } BcId;
351 
352 /// The location of a var, array, or array element.
353 typedef struct BcLoc
354 {
355 	/// The index of the var or array.
356 	size_t loc;
357 
358 	/// The index of the array or variable in the array stack. This is to
359 	/// prevent a bug with getting the wrong array element or variable after a
360 	/// function call. See the tests/bc/scripts/array.bc test for the array
361 	/// case; the variable case is in various variable tests.
362 	size_t stack_idx;
363 
364 	/// The index of the array element. Only used for array elements.
365 	size_t idx;
366 
367 } BcLoc;
368 
369 /// An entry for a constant.
370 typedef struct BcConst
371 {
372 	/// The original string as parsed from the source code.
373 	char* val;
374 
375 	/// The last base that the constant was parsed in.
376 	BcBigDig base;
377 
378 	/// The parsed constant.
379 	BcNum num;
380 
381 } BcConst;
382 
383 /// A function. This is also used in dc, not just bc. The reason is that strings
384 /// are executed in dc, and they are converted to functions in order to be
385 /// executed.
386 typedef struct BcFunc
387 {
388 	/// The bytecode instructions.
389 	BcVec code;
390 
391 #if BC_ENABLED
392 
393 	/// The labels. This is a vector of indices. The index is the index into
394 	/// the bytecode vector where the label is.
395 	BcVec labels;
396 
397 	/// The autos for the function. The first items are the parameters, and the
398 	/// arguments to the parameters must match the types in this vector.
399 	BcVec autos;
400 
401 	/// The number of parameters the function takes.
402 	size_t nparams;
403 
404 #endif // BC_ENABLED
405 
406 	/// The function's name.
407 	const char* name;
408 
409 #if BC_ENABLED
410 	/// True if the function is a void function.
411 	bool voidfn;
412 #endif // BC_ENABLED
413 
414 } BcFunc;
415 
416 /// Types of results that can be pushed onto the results stack.
417 typedef enum BcResultType
418 {
419 	/// Result is a variable.
420 	BC_RESULT_VAR,
421 
422 	/// Result is an array element.
423 	BC_RESULT_ARRAY_ELEM,
424 
425 	/// Result is an array. This is only allowed for function arguments or
426 	/// returning the length of the array.
427 	BC_RESULT_ARRAY,
428 
429 	/// Result is a string.
430 	BC_RESULT_STR,
431 
432 	/// Result is a temporary. This is used for the result of almost all
433 	/// expressions.
434 	BC_RESULT_TEMP,
435 
436 	/// Special casing the two below gave performance improvements.
437 
438 	/// Result is a 0.
439 	BC_RESULT_ZERO,
440 
441 	/// Result is a 1. Useful for inc/dec operators.
442 	BC_RESULT_ONE,
443 
444 #if BC_ENABLED
445 
446 	/// Result is the special "last" variable.
447 	BC_RESULT_LAST,
448 
449 	/// Result is the return value of a void function.
450 	BC_RESULT_VOID,
451 #endif // BC_ENABLED
452 
453 	/// Result is the value of ibase.
454 	BC_RESULT_IBASE,
455 
456 	/// Result is the value of obase.
457 	BC_RESULT_OBASE,
458 
459 	/// Result is the value of scale.
460 	BC_RESULT_SCALE,
461 
462 #if BC_ENABLE_EXTRA_MATH
463 
464 	/// Result is the value of seed.
465 	BC_RESULT_SEED,
466 
467 #endif // BC_ENABLE_EXTRA_MATH
468 
469 } BcResultType;
470 
471 /// A union to store data for various result types.
472 typedef union BcResultData
473 {
474 	/// A number. Strings are stored here too; they are numbers with
475 	/// cap == 0 && num == NULL. The string's index into the strings vector is
476 	/// stored in the scale field. But this is only used for strings stored in
477 	/// variables.
478 	BcNum n;
479 
480 	/// A vector.
481 	BcVec v;
482 
483 	/// A variable, array, or array element reference. This could also be a
484 	/// string if a string is not stored in a variable (dc only).
485 	BcLoc loc;
486 
487 } BcResultData;
488 
489 /// A tagged union for results.
490 typedef struct BcResult
491 {
492 	/// The tag. The type of the result.
493 	BcResultType t;
494 
495 	/// The data. The data for the result.
496 	BcResultData d;
497 
498 } BcResult;
499 
500 /// An instruction pointer. This is how bc knows where in the bytecode vector,
501 /// and which function, the current execution is.
502 typedef struct BcInstPtr
503 {
504 	/// The index of the currently executing function in the fns vector.
505 	size_t func;
506 
507 	/// The index into the bytecode vector of the *next* instruction.
508 	size_t idx;
509 
510 	/// The length of the results vector when this function started executing.
511 	/// This is mostly used for bc where functions should not affect the results
512 	/// of their callers.
513 	size_t len;
514 
515 } BcInstPtr;
516 
517 /// Types of identifiers.
518 typedef enum BcType
519 {
520 	/// Variable.
521 	BC_TYPE_VAR,
522 
523 	/// Array.
524 	BC_TYPE_ARRAY,
525 
526 #if BC_ENABLED
527 
528 	/// Array reference.
529 	BC_TYPE_REF,
530 
531 #endif // BC_ENABLED
532 
533 } BcType;
534 
535 #if BC_ENABLED
536 
537 /// Check if type array or array reference
538 #define BC_IS_ARRAY(e) (e == BC_TYPE_ARRAY || e == BC_TYPE_REF)
539 
540 /// An auto variable in bc.
541 typedef struct BcAuto
542 {
543 	/// The index of the variable in the vars or arrs vectors.
544 	size_t idx;
545 
546 	/// The type of the variable.
547 	BcType type;
548 
549 } BcAuto;
550 #endif // BC_ENABLED
551 
552 /// Forward declaration.
553 struct BcProgram;
554 
555 /**
556  * Initializes a function.
557  * @param f     The function to initialize.
558  * @param name  The name of the function. The string is assumed to be owned by
559  *              some other entity.
560  */
561 void
562 bc_func_init(BcFunc* f, const char* name);
563 
564 /**
565  * Inserts an auto into the function.
566  * @param f     The function to insert into.
567  * @param p     The program. This is to search for the variable or array name.
568  * @param name  The name of the auto to insert.
569  * @param type  The type of the auto.
570  * @param line  The line in the source code where the insert happened. This is
571  *              solely for error reporting.
572  */
573 void
574 bc_func_insert(BcFunc* f, struct BcProgram* p, char* name, BcType type,
575                size_t line);
576 
577 /**
578  * Resets a function in preparation for it to be reused. This can happen in bc
579  * because it is a dynamic language and functions can be redefined.
580  * @param f  The functio to reset.
581  */
582 void
583 bc_func_reset(BcFunc* f);
584 
585 #if BC_DEBUG
586 /**
587  * Frees a function. This is a destructor. This is only used in debug builds
588  * because all functions are freed at exit. We free them in debug builds to
589  * check for memory leaks.
590  * @param func  The function to free as a void pointer.
591  */
592 void
593 bc_func_free(void* func);
594 #endif // BC_DEBUG
595 
596 /**
597  * Initializes an array, which is the array type in bc and dc source code. Since
598  * variables and arrays are both arrays (see the development manual,
599  * manuals/development.md#execution, for more information), the @a nums
600  * parameter tells bc whether to initialize an array of numbers or an array of
601  * arrays of numbers. If the latter, it does a recursive call with nums set to
602  * true.
603  * @param a     The array to initialize.
604  * @param nums  True if the array should be for numbers, false if it should be
605  *              for vectors.
606  */
607 void
608 bc_array_init(BcVec* a, bool nums);
609 
610 /**
611  * Copies an array to another array. This is used to do pass arrays to functions
612  * that do not take references to arrays. The arrays are passed entirely by
613  * value, which means that they need to be copied.
614  * @param d  The destination array.
615  * @param s  The source array.
616  */
617 void
618 bc_array_copy(BcVec* d, const BcVec* s);
619 
620 /**
621  * Frees a string stored in a function. This is a destructor.
622  * @param string  The string to free as a void pointer.
623  */
624 void
625 bc_string_free(void* string);
626 
627 /**
628  * Frees a constant stored in a function. This is a destructor.
629  * @param constant  The constant to free as a void pointer.
630  */
631 void
632 bc_const_free(void* constant);
633 
634 /**
635  * Clears a result. It sets the type to BC_RESULT_TEMP and clears the union by
636  * clearing the BcNum in the union. This is to ensure that bc does not use
637  * uninitialized data.
638  * @param r  The result to clear.
639  */
640 void
641 bc_result_clear(BcResult* r);
642 
643 /**
644  * Copies a result into another. This is done for things like duplicating the
645  * top of the results stack or copying the result of an assignment to put back
646  * on the results stack.
647  * @param d    The destination result.
648  * @param src  The source result.
649  */
650 void
651 bc_result_copy(BcResult* d, BcResult* src);
652 
653 /**
654  * Frees a result. This is a destructor.
655  * @param result  The result to free as a void pointer.
656  */
657 void
658 bc_result_free(void* result);
659 
660 /**
661  * Expands an array to @a len. This can happen because in bc, you do not have to
662  * explicitly initialize elements of an array. If you access an element that is
663  * not initialized, the array is expanded to fit it, and all missing elements
664  * are initialized to 0 if they are numbers, or arrays with one element of 0.
665  * This function does that expansion.
666  * @param a    The array to expand.
667  * @param len  The length to expand to.
668  */
669 void
670 bc_array_expand(BcVec* a, size_t len);
671 
672 #if BC_ENABLED
673 
674 /**
675  * Returns non-zero if the bytecode instruction i is an assignment instruction.
676  * @param i  The instruction to test.
677  * @return   Non-zero if i is an assignment instruction, zero otherwise.
678  */
679 #define BC_INST_IS_ASSIGN(i) \
680 	((i) == BC_INST_ASSIGN || (i) == BC_INST_ASSIGN_NO_VAL)
681 
682 /**
683  * Returns true if the bytecode instruction @a i requires the value to be
684  * returned for use.
685  * @param i  The instruction to test.
686  * @return   True if @a i requires the value to be returned for use, false
687  *           otherwise.
688  */
689 #define BC_INST_USE_VAL(i) ((i) <= BC_INST_ASSIGN)
690 
691 #else // BC_ENABLED
692 
693 /**
694  * Returns non-zero if the bytecode instruction i is an assignment instruction.
695  * @param i  The instruction to test.
696  * @return   Non-zero if i is an assignment instruction, zero otherwise.
697  */
698 #define BC_INST_IS_ASSIGN(i) ((i) == BC_INST_ASSIGN_NO_VAL)
699 
700 /**
701  * Returns true if the bytecode instruction @a i requires the value to be
702  * returned for use.
703  * @param i  The instruction to test.
704  * @return   True if @a i requires the value to be returned for use, false
705  *           otherwise.
706  */
707 #define BC_INST_USE_VAL(i) (false)
708 
709 #endif // BC_ENABLED
710 
711 #if BC_DEBUG_CODE
712 /// Reference to string names for all of the instructions. For debugging.
713 extern const char* bc_inst_names[];
714 #endif // BC_DEBUG_CODE
715 
716 /// References to the names of the main and read functions.
717 extern const char bc_func_main[];
718 extern const char bc_func_read[];
719 
720 #endif // BC_LANG_H
721