Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bc/include/vm.h
39507 views
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 bc's VM.
33
*
34
*/
35
36
#ifndef BC_VM_H
37
#define BC_VM_H
38
39
#include <assert.h>
40
#include <stddef.h>
41
#include <limits.h>
42
43
#include <signal.h>
44
45
#if BC_ENABLE_NLS
46
47
#ifdef _WIN32
48
#error NLS is not supported on Windows.
49
#endif // _WIN32
50
51
#include <nl_types.h>
52
53
#endif // BC_ENABLE_NLS
54
55
#include <status.h>
56
#include <num.h>
57
#include <lex.h>
58
#include <parse.h>
59
#include <program.h>
60
#include <history.h>
61
#include <bc.h>
62
63
// We don't want to include this file for the library because it's unused.
64
#if !BC_ENABLE_LIBRARY
65
#include <file.h>
66
#endif // !BC_ENABLE_LIBRARY
67
68
// This should be obvious. If neither calculator is enabled, barf.
69
#if !BC_ENABLED && !DC_ENABLED
70
#error Must define BC_ENABLED, DC_ENABLED, or both
71
#endif
72
73
// CHAR_BIT must be at least 6, for various reasons. I might want to bump this
74
// to 8 in the future.
75
#if CHAR_BIT < 6
76
#error CHAR_BIT must be at least 6.
77
#endif
78
79
// Set defaults.
80
81
#ifndef MAINEXEC
82
#define MAINEXEC bc
83
#endif // MAINEXEC
84
85
#ifndef _WIN32
86
#ifndef EXECPREFIX
87
#define EXECPREFIX
88
#endif // EXECPREFIX
89
#else // _WIN32
90
#undef EXECPREFIX
91
#endif // _WIN32
92
93
/**
94
* Generate a string from text.
95
* @parm V The text to generate a string for.
96
*/
97
#define GEN_STR(V) #V
98
99
/**
100
* Help generate a string from text. The preprocessor requires this two-step
101
* process. Trust me.
102
* @parm V The text to generate a string for.
103
*/
104
#define GEN_STR2(V) GEN_STR(V)
105
106
/// The version as a string. VERSION must be defined previously, usually by the
107
/// build system.
108
#define BC_VERSION GEN_STR2(VERSION)
109
110
/// The main executable name as a string. MAINEXEC must be defined previously,
111
/// usually by the build system.
112
#define BC_MAINEXEC GEN_STR2(MAINEXEC)
113
114
/// The build type as a string. BUILD_TYPE must be defined previously, usually
115
/// by the build system.
116
#define BC_BUILD_TYPE GEN_STR2(BUILD_TYPE)
117
118
// We only allow an empty executable prefix on Windows.
119
#ifndef _WIN32
120
#define BC_EXECPREFIX GEN_STR2(EXECPREFIX)
121
#else // _WIN32
122
#define BC_EXECPREFIX ""
123
#endif // _WIN32
124
125
#if !BC_ENABLE_LIBRARY
126
127
#if DC_ENABLED
128
129
/// The flag for the extended register option.
130
#define DC_FLAG_X (UINTMAX_C(1) << 0)
131
132
#endif // DC_ENABLED
133
134
#if BC_ENABLED
135
136
/// The flag for the POSIX warning option.
137
#define BC_FLAG_W (UINTMAX_C(1) << 1)
138
139
/// The flag for the POSIX error option.
140
#define BC_FLAG_S (UINTMAX_C(1) << 2)
141
142
/// The flag for the math library option.
143
#define BC_FLAG_L (UINTMAX_C(1) << 3)
144
145
/// The flag for the global stacks option.
146
#define BC_FLAG_G (UINTMAX_C(1) << 4)
147
148
#endif // BC_ENABLED
149
150
/// The flag for quiet, though this one is reversed; the option clears the flag.
151
#define BC_FLAG_Q (UINTMAX_C(1) << 5)
152
153
/// The flag for interactive.
154
#define BC_FLAG_I (UINTMAX_C(1) << 6)
155
156
/// The flag for prompt. This is also reversed; the option clears the flag.
157
#define BC_FLAG_P (UINTMAX_C(1) << 7)
158
159
/// The flag for read prompt. This is also reversed; the option clears the flag.
160
#define BC_FLAG_R (UINTMAX_C(1) << 8)
161
162
/// The flag for a leading zero.
163
#define BC_FLAG_Z (UINTMAX_C(1) << 9)
164
165
/// The flag for stdin being a TTY.
166
#define BC_FLAG_TTYIN (UINTMAX_C(1) << 10)
167
168
/// The flag for TTY mode.
169
#define BC_FLAG_TTY (UINTMAX_C(1) << 11)
170
171
/// The flag for reset on SIGINT.
172
#define BC_FLAG_SIGINT (UINTMAX_C(1) << 12)
173
174
/// The flag for exiting with expressions.
175
#define BC_FLAG_EXPR_EXIT (UINTMAX_C(1) << 13)
176
177
/// The flag for digit clamping.
178
#define BC_FLAG_DIGIT_CLAMP (UINTMAX_C(1) << 14)
179
180
/// A convenience macro for getting the TTYIN flag.
181
#define BC_TTYIN (vm->flags & BC_FLAG_TTYIN)
182
183
/// A convenience macro for getting the TTY flag.
184
#define BC_TTY (vm->flags & BC_FLAG_TTY)
185
186
/// A convenience macro for getting the SIGINT flag.
187
#define BC_SIGINT (vm->flags & BC_FLAG_SIGINT)
188
189
#if BC_ENABLED
190
191
/// A convenience macro for getting the POSIX error flag.
192
#define BC_S (vm->flags & BC_FLAG_S)
193
194
/// A convenience macro for getting the POSIX warning flag.
195
#define BC_W (vm->flags & BC_FLAG_W)
196
197
/// A convenience macro for getting the math library flag.
198
#define BC_L (vm->flags & BC_FLAG_L)
199
200
/// A convenience macro for getting the global stacks flag.
201
#define BC_G (vm->flags & BC_FLAG_G)
202
203
#endif // BC_ENABLED
204
205
#if DC_ENABLED
206
207
/// A convenience macro for getting the extended register flag.
208
#define DC_X (vm->flags & DC_FLAG_X)
209
210
#endif // DC_ENABLED
211
212
/// A convenience macro for getting the interactive flag.
213
#define BC_I (vm->flags & BC_FLAG_I)
214
215
/// A convenience macro for getting the prompt flag.
216
#define BC_P (vm->flags & BC_FLAG_P)
217
218
/// A convenience macro for getting the read prompt flag.
219
#define BC_R (vm->flags & BC_FLAG_R)
220
221
/// A convenience macro for getting the leading zero flag.
222
#define BC_Z (vm->flags & BC_FLAG_Z)
223
224
/// A convenience macro for getting the expression exit flag.
225
#define BC_EXPR_EXIT (vm->flags & BC_FLAG_EXPR_EXIT)
226
227
/// A convenience macro for getting the digit clamp flag.
228
#define BC_DIGIT_CLAMP (vm->flags & BC_FLAG_DIGIT_CLAMP)
229
230
#if BC_ENABLED
231
232
/// A convenience macro for checking if bc is in POSIX mode.
233
#define BC_IS_POSIX (BC_S || BC_W)
234
235
#if DC_ENABLED
236
237
/// Returns true if bc is running.
238
#define BC_IS_BC (vm->name[0] != 'd')
239
240
/// Returns true if dc is running.
241
#define BC_IS_DC (vm->name[0] == 'd')
242
243
/// Returns the correct read prompt.
244
#define BC_VM_READ_PROMPT (BC_IS_BC ? "read> " : "?> ")
245
246
/// Returns the string for the line length environment variable.
247
#define BC_VM_LINE_LENGTH_STR (BC_IS_BC ? "BC_LINE_LENGTH" : "DC_LINE_LENGTH")
248
249
/// Returns the string for the environment args environment variable.
250
#define BC_VM_ENV_ARGS_STR (BC_IS_BC ? "BC_ENV_ARGS" : "DC_ENV_ARGS")
251
252
/// Returns the string for the expression exit environment variable.
253
#define BC_VM_EXPR_EXIT_STR (BC_IS_BC ? "BC_EXPR_EXIT" : "DC_EXPR_EXIT")
254
255
/// Returns the default for the expression exit environment variable.
256
#define BC_VM_EXPR_EXIT_DEF \
257
(BC_IS_BC ? BC_DEFAULT_EXPR_EXIT : DC_DEFAULT_EXPR_EXIT)
258
259
/// Returns the string for the digit clamp environment variable.
260
#define BC_VM_DIGIT_CLAMP_STR (BC_IS_BC ? "BC_DIGIT_CLAMP" : "DC_DIGIT_CLAMP")
261
262
/// Returns the default for the digit clamp environment variable.
263
#define BC_VM_DIGIT_CLAMP_DEF \
264
(BC_IS_BC ? BC_DEFAULT_DIGIT_CLAMP : DC_DEFAULT_DIGIT_CLAMP)
265
266
/// Returns the string for the TTY mode environment variable.
267
#define BC_VM_TTY_MODE_STR (BC_IS_BC ? "BC_TTY_MODE" : "DC_TTY_MODE")
268
269
/// Returns the default for the TTY mode environment variable.
270
#define BC_VM_TTY_MODE_DEF \
271
(BC_IS_BC ? BC_DEFAULT_TTY_MODE : DC_DEFAULT_TTY_MODE)
272
273
/// Returns the string for the prompt environment variable.
274
#define BC_VM_PROMPT_STR (BC_IS_BC ? "BC_PROMPT" : "DC_PROMPT")
275
276
/// Returns the default for the prompt environment variable.
277
#define BC_VM_PROMPT_DEF (BC_IS_BC ? BC_DEFAULT_PROMPT : DC_DEFAULT_PROMPT)
278
279
/// Returns the string for the SIGINT reset environment variable.
280
#define BC_VM_SIGINT_RESET_STR \
281
(BC_IS_BC ? "BC_SIGINT_RESET" : "DC_SIGINT_RESET")
282
283
/// Returns the string for the SIGINT reset environment variable.
284
#define BC_VM_SIGINT_RESET_DEF \
285
(BC_IS_BC ? BC_DEFAULT_SIGINT_RESET : DC_DEFAULT_SIGINT_RESET)
286
287
/// Returns true if the calculator should run stdin.
288
#define BC_VM_RUN_STDIN(has_file) (BC_IS_BC || !(has_file))
289
290
#else // DC_ENABLED
291
292
/// Returns true if bc is running.
293
#define BC_IS_BC (1)
294
295
/// Returns true if dc is running.
296
#define BC_IS_DC (0)
297
298
/// Returns the correct read prompt.
299
#define BC_VM_READ_PROMPT ("read> ")
300
301
/// Returns the string for the line length environment variable.
302
#define BC_VM_LINE_LENGTH_STR ("BC_LINE_LENGTH")
303
304
/// Returns the string for the environment args environment variable.
305
#define BC_VM_ENV_ARGS_STR ("BC_ENV_ARGS")
306
307
/// Returns the string for the expression exit environment variable.
308
#define BC_VM_EXPR_EXIT_STR ("BC_EXPR_EXIT")
309
310
/// Returns the default for the expression exit environment variable.
311
#define BC_VM_EXPR_EXIT_DEF (BC_DEFAULT_EXPR_EXIT)
312
313
/// Returns the string for the digit clamp environment variable.
314
#define BC_VM_DIGIT_CLAMP_STR ("BC_DIGIT_CLAMP")
315
316
/// Returns the default for the digit clamp environment variable.
317
#define BC_VM_DIGIT_CLAMP_DEF (BC_DEFAULT_DIGIT_CLAMP)
318
319
/// Returns the string for the TTY mode environment variable.
320
#define BC_VM_TTY_MODE_STR ("BC_TTY_MODE")
321
322
/// Returns the default for the TTY mode environment variable.
323
#define BC_VM_TTY_MODE_DEF (BC_DEFAULT_TTY_MODE)
324
325
/// Returns the string for the prompt environment variable.
326
#define BC_VM_PROMPT_STR ("BC_PROMPT")
327
328
/// Returns the default for the SIGINT reset environment variable.
329
#define BC_VM_PROMPT_DEF (BC_DEFAULT_PROMPT)
330
331
/// Returns the string for the SIGINT reset environment variable.
332
#define BC_VM_SIGINT_RESET_STR ("BC_SIGINT_RESET")
333
334
/// Returns the string for the SIGINT reset environment variable.
335
#define BC_VM_SIGINT_RESET_DEF (BC_DEFAULT_SIGINT_RESET)
336
337
/// Returns true if the calculator should run stdin.
338
#define BC_VM_RUN_STDIN(has_file) (BC_IS_BC)
339
340
#endif // DC_ENABLED
341
342
#else // BC_ENABLED
343
344
/// A convenience macro for checking if bc is in POSIX mode.
345
#define BC_IS_POSIX (0)
346
347
/// Returns true if bc is running.
348
#define BC_IS_BC (0)
349
350
/// Returns true if dc is running.
351
#define BC_IS_DC (1)
352
353
/// Returns the correct read prompt.
354
#define BC_VM_READ_PROMPT ("?> ")
355
356
/// Returns the string for the line length environment variable.
357
#define BC_VM_LINE_LENGTH_STR ("DC_LINE_LENGTH")
358
359
/// Returns the string for the environment args environment variable.
360
#define BC_VM_ENV_ARGS_STR ("DC_ENV_ARGS")
361
362
/// Returns the string for the expression exit environment variable.
363
#define BC_VM_EXPR_EXIT_STR ("DC_EXPR_EXIT")
364
365
/// Returns the default for the expression exit environment variable.
366
#define BC_VM_EXPR_EXIT_DEF (DC_DEFAULT_EXPR_EXIT)
367
368
/// Returns the string for the digit clamp environment variable.
369
#define BC_VM_DIGIT_CLAMP_STR ("DC_DIGIT_CLAMP")
370
371
/// Returns the default for the digit clamp environment variable.
372
#define BC_VM_DIGIT_CLAMP_DEF (DC_DEFAULT_DIGIT_CLAMP)
373
374
/// Returns the string for the TTY mode environment variable.
375
#define BC_VM_TTY_MODE_STR ("DC_TTY_MODE")
376
377
/// Returns the default for the TTY mode environment variable.
378
#define BC_VM_TTY_MODE_DEF (DC_DEFAULT_TTY_MODE)
379
380
/// Returns the string for the prompt environment variable.
381
#define BC_VM_PROMPT_STR ("DC_PROMPT")
382
383
/// Returns the default for the SIGINT reset environment variable.
384
#define BC_VM_PROMPT_DEF (DC_DEFAULT_PROMPT)
385
386
/// Returns the string for the SIGINT reset environment variable.
387
#define BC_VM_SIGINT_RESET_STR ("DC_SIGINT_RESET")
388
389
/// Returns the string for the SIGINT reset environment variable.
390
#define BC_VM_SIGINT_RESET_DEF (DC_DEFAULT_SIGINT_RESET)
391
392
/// Returns true if the calculator should run stdin.
393
#define BC_VM_RUN_STDIN(has_file) (!(has_file))
394
395
#endif // BC_ENABLED
396
397
/// A convenience macro for checking if the prompt is enabled.
398
#define BC_PROMPT (BC_P)
399
400
#else // !BC_ENABLE_LIBRARY
401
402
#define BC_Z (vm->leading_zeroes)
403
404
#define BC_DIGIT_CLAMP (vm->digit_clamp)
405
406
#endif // !BC_ENABLE_LIBRARY
407
408
/**
409
* Returns the max of its two arguments. This evaluates arguments twice, so be
410
* careful what args you give it.
411
* @param a The first argument.
412
* @param b The second argument.
413
* @return The max of the two arguments.
414
*/
415
#define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
416
417
/**
418
* Returns the min of its two arguments. This evaluates arguments twice, so be
419
* careful what args you give it.
420
* @param a The first argument.
421
* @param b The second argument.
422
* @return The min of the two arguments.
423
*/
424
#define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
425
426
/// Returns the max obase that is allowed.
427
#define BC_MAX_OBASE ((BcBigDig) (BC_BASE_POW))
428
429
/// Returns the max array size that is allowed.
430
#define BC_MAX_DIM ((BcBigDig) (SIZE_MAX - 1))
431
432
/// Returns the max scale that is allowed.
433
#define BC_MAX_SCALE ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
434
435
/// Returns the max string length that is allowed.
436
#define BC_MAX_STRING ((BcBigDig) (BC_NUM_BIGDIG_MAX - 1))
437
438
/// Returns the max identifier length that is allowed.
439
#define BC_MAX_NAME BC_MAX_STRING
440
441
/// Returns the max number size that is allowed.
442
#define BC_MAX_NUM BC_MAX_SCALE
443
444
#if BC_ENABLE_EXTRA_MATH
445
446
/// Returns the max random integer that can be returned.
447
#define BC_MAX_RAND ((BcBigDig) (((BcRand) 0) - 1))
448
449
#endif // BC_ENABLE_EXTRA_MATH
450
451
/// Returns the max exponent that is allowed.
452
#define BC_MAX_EXP ((ulong) (BC_NUM_BIGDIG_MAX))
453
454
/// Returns the max number of variables that is allowed.
455
#define BC_MAX_VARS ((ulong) (SIZE_MAX - 1))
456
457
#if BC_ENABLE_LINE_LIB
458
459
/// The size of the global buffer.
460
#define BC_VM_BUF_SIZE (1 << 10)
461
462
/// The amount of the global buffer allocated to stdin.
463
#define BC_VM_STDIN_BUF_SIZE (BC_VM_BUF_SIZE - 1)
464
465
#else // BC_ENABLE_LINE_LIB
466
467
/// The size of the global buffer.
468
#define BC_VM_BUF_SIZE (1 << 12)
469
470
/// The amount of the global buffer allocated to stdout.
471
#define BC_VM_STDOUT_BUF_SIZE (1 << 11)
472
473
/// The amount of the global buffer allocated to stderr.
474
#define BC_VM_STDERR_BUF_SIZE (1 << 10)
475
476
/// The amount of the global buffer allocated to stdin.
477
#define BC_VM_STDIN_BUF_SIZE (BC_VM_STDERR_BUF_SIZE - 1)
478
479
#endif // BC_ENABLE_LINE_LIB
480
481
/// The max number of temporary BcNums that can be kept.
482
#define BC_VM_MAX_TEMPS (1 << 9)
483
484
/// The capacity of the one BcNum, which is a constant.
485
#define BC_VM_ONE_CAP (1)
486
487
/**
488
* Returns true if a BcResult is safe for garbage collection.
489
* @param r The BcResult to test.
490
* @return True if @a r is safe to garbage collect.
491
*/
492
#define BC_VM_SAFE_RESULT(r) ((r)->t >= BC_RESULT_TEMP)
493
494
/// The invalid locale catalog return value.
495
#define BC_VM_INVALID_CATALOG ((nl_catd) - 1)
496
497
/**
498
* Returns true if the *unsigned* multiplication overflows.
499
* @param a The first operand.
500
* @param b The second operand.
501
* @param r The product.
502
* @return True if the multiplication of @a a and @a b overflows.
503
*/
504
#define BC_VM_MUL_OVERFLOW(a, b, r) \
505
((r) >= SIZE_MAX || ((a) != 0 && (r) / (a) != (b)))
506
507
/// The global vm struct. This holds all of the global data besides the file
508
/// buffers.
509
typedef struct BcVm
510
{
511
/// The current status. This is volatile sig_atomic_t because it is also
512
/// used in the signal handler. See the development manual
513
/// (manuals/development.md#async-signal-safe-signal-handling) for more
514
/// information.
515
volatile sig_atomic_t status;
516
517
/// Non-zero if a jump series is in progress and items should be popped off
518
/// the jmp_bufs vector. This is volatile sig_atomic_t because it is also
519
/// used in the signal handler. See the development manual
520
/// (manuals/development.md#async-signal-safe-signal-handling) for more
521
/// information.
522
volatile sig_atomic_t sig_pop;
523
524
#if !BC_ENABLE_LIBRARY
525
526
/// The parser.
527
BcParse prs;
528
529
/// The program.
530
BcProgram prog;
531
532
/// A buffer for lines for stdin.
533
BcVec line_buf;
534
535
/// A buffer to hold a series of lines from stdin. Sometimes, multiple lines
536
/// are necessary for parsing, such as a comment that spans multiple lines.
537
BcVec buffer;
538
539
/// A parser to parse read expressions.
540
BcParse read_prs;
541
542
/// A buffer for read expressions.
543
BcVec read_buf;
544
545
#endif // !BC_ENABLE_LIBRARY
546
547
/// A vector of jmp_bufs for doing a jump series. This allows exception-type
548
/// error handling, while allowing me to do cleanup on the way.
549
BcVec jmp_bufs;
550
551
/// The number of temps in the temps array.
552
size_t temps_len;
553
554
#if BC_ENABLE_LIBRARY
555
556
/// The vector of contexts for the library.
557
BcVec ctxts;
558
559
/// The vector for creating strings to pass to the client.
560
BcVec out;
561
562
#if BC_ENABLE_EXTRA_MATH
563
564
/// The PRNG.
565
BcRNG rng;
566
567
#endif // BC_ENABLE_EXTRA_MATH
568
569
/// The current error.
570
BclError err;
571
572
/// Whether or not bcl should abort on fatal errors.
573
bool abrt;
574
575
/// Whether or not to print leading zeros.
576
bool leading_zeroes;
577
578
/// Whether or not to clamp digits that are greater than or equal to the
579
/// current ibase.
580
bool digit_clamp;
581
582
/// The number of "references," or times that the library was initialized.
583
unsigned int refs;
584
585
#else // BC_ENABLE_LIBRARY
586
587
/// A pointer to the filename of the current file. This is not owned by the
588
/// BcVm struct.
589
const char* file;
590
591
/// The message printed when SIGINT happens.
592
const char* sigmsg;
593
594
/// Non-zero when signals are "locked." This is volatile sig_atomic_t
595
/// because it is also used in the signal handler. See the development
596
/// manual (manuals/development.md#async-signal-safe-signal-handling) for
597
/// more information.
598
volatile sig_atomic_t sig_lock;
599
600
/// Non-zero when a signal has been received, but not acted on. This is
601
/// volatile sig_atomic_t because it is also used in the signal handler. See
602
/// the development manual
603
/// (manuals/development.md#async-signal-safe-signal-handling) for more
604
/// information.
605
volatile sig_atomic_t sig;
606
607
/// The length of sigmsg.
608
uchar siglen;
609
610
/// The instruction used for returning from a read() call.
611
uchar read_ret;
612
613
/// The flags field used by most macros above.
614
uint16_t flags;
615
616
/// The number of characters printed in the current line. This is used
617
/// because bc has a limit of the number of characters it can print per
618
/// line.
619
uint16_t nchars;
620
621
/// The length of the line we can print. The user can set this if they wish.
622
uint16_t line_len;
623
624
/// True if bc should error if expressions are encountered during option
625
/// parsing, false otherwise.
626
bool no_exprs;
627
628
/// True if bc should exit if expresions are encountered.
629
bool exit_exprs;
630
631
/// True if EOF was encountered.
632
bool eof;
633
634
/// The mode that the program is in.
635
uchar mode;
636
637
#if BC_ENABLED
638
639
/// True if keywords should not be redefined. This is only true for the
640
/// builtin math libraries for bc.
641
bool no_redefine;
642
643
#endif // BC_ENABLED
644
645
/// A vector of filenames to process.
646
BcVec files;
647
648
/// A vector of expressions to process.
649
BcVec exprs;
650
651
/// The name of the calculator under use. This is used by BC_IS_BC and
652
/// BC_IS_DC.
653
const char* name;
654
655
/// The help text for the calculator.
656
const char* help;
657
658
#if BC_ENABLE_HISTORY
659
660
/// The history data.
661
BcHistory history;
662
663
#endif // BC_ENABLE_HISTORY
664
665
/// The function to call to get the next lex token.
666
BcLexNext next;
667
668
/// The function to call to parse.
669
BcParseParse parse;
670
671
/// The function to call to parse expressions.
672
BcParseExpr expr;
673
674
/// The names of the categories of errors.
675
const char* err_ids[BC_ERR_IDX_NELEMS + BC_ENABLED];
676
677
/// The messages for each error.
678
const char* err_msgs[BC_ERR_NELEMS];
679
680
#if BC_ENABLE_NLS
681
/// The locale.
682
const char* locale;
683
#endif // BC_ENABLE_NLS
684
685
#endif // BC_ENABLE_LIBRARY
686
687
/// An array of maxes for the globals.
688
BcBigDig maxes[BC_PROG_GLOBALS_LEN + BC_ENABLE_EXTRA_MATH];
689
690
/// The last base used to parse.
691
BcBigDig last_base;
692
693
/// The last power of last_base used to parse.
694
BcBigDig last_pow;
695
696
/// The last exponent of base that equals last_pow.
697
BcBigDig last_exp;
698
699
/// BC_BASE_POW - last_pow.
700
BcBigDig last_rem;
701
702
#if !BC_ENABLE_LIBRARY
703
704
/// A buffer of environment arguments. This is the actual value of the
705
/// environment variable.
706
char* env_args_buffer;
707
708
/// A vector for environment arguments after parsing.
709
BcVec env_args;
710
711
/// A BcNum set to constant 0.
712
BcNum zero;
713
714
#endif // !BC_ENABLE_LIBRARY
715
716
/// A BcNum set to constant 1.
717
BcNum one;
718
719
/// A BcNum holding the max number held by a BcBigDig plus 1.
720
BcNum max;
721
722
/// A BcNum holding the max number held by a BcBigDig times 2 plus 1.
723
BcNum max2;
724
725
/// The BcDig array for max.
726
BcDig max_num[BC_NUM_BIGDIG_LOG10];
727
728
/// The BcDig array for max2.
729
BcDig max2_num[BC_NUM_BIGDIG_LOG10];
730
731
// The BcDig array for the one BcNum.
732
BcDig one_num[BC_VM_ONE_CAP];
733
734
#if !BC_ENABLE_LIBRARY
735
736
// The BcDig array for the zero BcNum.
737
BcDig zero_num[BC_VM_ONE_CAP];
738
739
/// The stdout file.
740
BcFile fout;
741
742
/// The stderr file.
743
BcFile ferr;
744
745
#if BC_ENABLE_NLS
746
747
/// The locale catalog.
748
nl_catd catalog;
749
750
#endif // BC_ENABLE_NLS
751
752
/// A pointer to the stdin buffer.
753
char* buf;
754
755
/// The number of items in the input buffer.
756
size_t buf_len;
757
758
/// The slabs vector for constants, strings, function names, and other
759
/// string-like things.
760
BcVec slabs;
761
762
#if BC_ENABLED
763
764
/// An array of booleans for which bc keywords have been redefined if
765
/// BC_REDEFINE_KEYWORDS is non-zero.
766
bool redefined_kws[BC_LEX_NKWS];
767
768
#endif // BC_ENABLED
769
#endif // !BC_ENABLE_LIBRARY
770
771
BcDig* temps_buf[BC_VM_MAX_TEMPS];
772
773
#if BC_DEBUG_CODE
774
775
/// The depth for BC_FUNC_ENTER and BC_FUNC_EXIT.
776
size_t func_depth;
777
778
#endif // BC_DEBUG_CODE
779
780
} BcVm;
781
782
/**
783
* Print the copyright banner and help if it's non-NULL.
784
* @param help The help message to print if it's non-NULL.
785
*/
786
void
787
bc_vm_info(const char* const help);
788
789
/**
790
* The entrance point for bc/dc together.
791
* @param argc The count of arguments.
792
* @param argv The argument array.
793
* @return A status.
794
*/
795
BcStatus
796
bc_vm_boot(int argc, const char* argv[]);
797
798
/**
799
* Initializes some of the BcVm global. This is separate to make things easier
800
* on the library code.
801
*/
802
void
803
bc_vm_init(void);
804
805
/**
806
* Frees the BcVm global.
807
*/
808
void
809
bc_vm_shutdown(void);
810
811
/**
812
* Add a temp to the temp array.
813
* @param num The BcDig array to add to the temp array.
814
*/
815
void
816
bc_vm_addTemp(BcDig* num);
817
818
/**
819
* Return the temp on the top of the temp stack, or NULL if there are none.
820
* @return A temp, or NULL if none exist.
821
*/
822
BcDig*
823
bc_vm_takeTemp(void);
824
825
/**
826
* Gets the top temp of the temp stack. This is separate from bc_vm_takeTemp()
827
* to quiet a GCC warning about longjmp() clobbering in bc_num_init().
828
* @return A temp, or NULL if none exist.
829
*/
830
BcDig*
831
bc_vm_getTemp(void);
832
833
/**
834
* Frees all temporaries.
835
*/
836
void
837
bc_vm_freeTemps(void);
838
839
#if !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
840
841
/**
842
* Erases the flush argument if history does not exist because it does not
843
* matter if history does not exist.
844
*/
845
#define bc_vm_putchar(c, t) bc_vm_putchar_impl(c)
846
847
#else // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
848
849
// This is here to satisfy a clang warning about recursive macros.
850
#define bc_vm_putchar(c, t) bc_vm_putchar_impl(c, t)
851
852
#endif // !BC_ENABLE_HISTORY || BC_ENABLE_LINE_LIB || BC_ENABLE_LIBRARY
853
854
/**
855
* Print to stdout with limited formating.
856
* @param fmt The format string.
857
*/
858
void
859
bc_vm_printf(const char* fmt, ...);
860
861
/**
862
* Puts a char into the stdout buffer.
863
* @param c The character to put on the stdout buffer.
864
* @param type The flush type.
865
*/
866
void
867
bc_vm_putchar(int c, BcFlushType type);
868
869
/**
870
* Multiplies @a n and @a size and throws an allocation error if overflow
871
* occurs.
872
* @param n The number of elements.
873
* @param size The size of each element.
874
* @return The product of @a n and @a size.
875
*/
876
size_t
877
bc_vm_arraySize(size_t n, size_t size);
878
879
/**
880
* Adds @a a and @a b and throws an error if overflow occurs.
881
* @param a The first operand.
882
* @param b The second operand.
883
* @return The sum of @a a and @a b.
884
*/
885
size_t
886
bc_vm_growSize(size_t a, size_t b);
887
888
/**
889
* Allocate @a n bytes and throw an allocation error if allocation fails.
890
* @param n The bytes to allocate.
891
* @return A pointer to the allocated memory.
892
*/
893
void*
894
bc_vm_malloc(size_t n);
895
896
/**
897
* Reallocate @a ptr to be @a n bytes and throw an allocation error if
898
* reallocation fails.
899
* @param ptr The pointer to a memory allocation to reallocate.
900
* @param n The bytes to allocate.
901
* @return A pointer to the reallocated memory.
902
*/
903
void*
904
bc_vm_realloc(void* ptr, size_t n);
905
906
/**
907
* Allocates space for, and duplicates, @a str.
908
* @param str The string to allocate.
909
* @return The allocated string.
910
*/
911
char*
912
bc_vm_strdup(const char* str);
913
914
/**
915
* Reads a line from stdin into BcVm's buffer field.
916
* @param clear True if the buffer should be cleared first, false otherwise.
917
* @return True if a line was read, false otherwise.
918
*/
919
bool
920
bc_vm_readLine(bool clear);
921
922
/**
923
* Reads a line from the command-line expressions into BcVm's buffer field.
924
* @param clear True if the buffer should be cleared first, false otherwise.
925
* @return True if a line was read, false otherwise.
926
*/
927
bool
928
bc_vm_readBuf(bool clear);
929
930
/**
931
* A convenience and portability function for OpenBSD's pledge().
932
* @param promises The promises to pledge().
933
* @param execpromises The exec promises to pledge().
934
*/
935
void
936
bc_pledge(const char* promises, const char* execpromises);
937
938
/**
939
* Returns the value of an environment variable.
940
* @param var The environment variable.
941
* @return The value of the environment variable.
942
*/
943
char*
944
bc_vm_getenv(const char* var);
945
946
/**
947
* Frees an environment variable value.
948
* @param val The value to free.
949
*/
950
void
951
bc_vm_getenvFree(char* val);
952
953
#if BC_DEBUG_CODE
954
955
/**
956
* Start executing a jump series.
957
* @param f The name of the function that started the jump series.
958
*/
959
void
960
bc_vm_jmp(const char* f);
961
962
#else // BC_DEBUG_CODE
963
964
/**
965
* Start executing a jump series.
966
*/
967
void
968
bc_vm_jmp(void);
969
970
#endif // BC_DEBUG_CODE
971
972
#if BC_ENABLE_LIBRARY
973
974
/**
975
* Handle an error. This is the true error handler. It will start a jump series
976
* if an error occurred. POSIX errors will not cause jumps when warnings are on
977
* or no POSIX errors are enabled.
978
* @param e The error.
979
*/
980
void
981
bc_vm_handleError(BcErr e);
982
983
/**
984
* Handle a fatal error.
985
* @param e The error.
986
*/
987
void
988
bc_vm_fatalError(BcErr e);
989
990
/**
991
* A function to call at exit.
992
*/
993
void
994
bc_vm_atexit(void);
995
996
#else // BC_ENABLE_LIBRARY
997
998
/**
999
* Calculates the number of decimal digits in the argument.
1000
* @param val The value to calculate the number of decimal digits in.
1001
* @return The number of decimal digits in @a val.
1002
*/
1003
size_t
1004
bc_vm_numDigits(size_t val);
1005
1006
#if BC_DEBUG
1007
1008
/**
1009
* Handle an error. This is the true error handler. It will start a jump series
1010
* if an error occurred. POSIX errors will not cause jumps when warnings are on
1011
* or no POSIX errors are enabled.
1012
* @param e The error.
1013
* @param file The source file where the error occurred.
1014
* @param fline The line in the source file where the error occurred.
1015
* @param line The bc source line where the error occurred.
1016
*/
1017
void
1018
bc_vm_handleError(BcErr e, const char* file, int fline, size_t line, ...);
1019
1020
#else // BC_DEBUG
1021
1022
/**
1023
* Handle an error. This is the true error handler. It will start a jump series
1024
* if an error occurred. POSIX errors will not cause jumps when warnings are on
1025
* or no POSIX errors are enabled.
1026
* @param e The error.
1027
* @param line The bc source line where the error occurred.
1028
*/
1029
void
1030
bc_vm_handleError(BcErr e, size_t line, ...);
1031
1032
#endif // BC_DEBUG
1033
1034
/**
1035
* Handle a fatal error.
1036
* @param e The error.
1037
*/
1038
#if !BC_ENABLE_MEMCHECK
1039
BC_NORETURN
1040
#endif // !BC_ENABLE_MEMCHECK
1041
void
1042
bc_vm_fatalError(BcErr e);
1043
1044
/**
1045
* A function to call at exit.
1046
* @param status The exit status.
1047
*/
1048
BcStatus
1049
bc_vm_atexit(BcStatus status);
1050
1051
#endif // BC_ENABLE_LIBRARY
1052
1053
/// A reference to the copyright header.
1054
extern const char bc_copyright[];
1055
1056
/// A reference to the array of default error category names.
1057
extern const char* bc_errs[];
1058
1059
/// A reference to the array of error category indices for each error.
1060
extern const uchar bc_err_ids[];
1061
1062
/// A reference to the array of default error messages.
1063
extern const char* const bc_err_msgs[];
1064
1065
/// A reference to the pledge() promises at start.
1066
extern const char bc_pledge_start[];
1067
1068
#if BC_ENABLE_HISTORY
1069
1070
/// A reference to the end pledge() promises when using history.
1071
extern const char bc_pledge_end_history[];
1072
1073
#endif // BC_ENABLE_HISTORY
1074
1075
/// A reference to the end pledge() promises when *not* using history.
1076
extern const char bc_pledge_end[];
1077
1078
#if !BC_ENABLE_LIBRARY
1079
1080
/// A reference to the global data.
1081
extern BcVm* vm;
1082
1083
/// The global data.
1084
extern BcVm vm_data;
1085
1086
/// A reference to the global output buffers.
1087
extern char output_bufs[BC_VM_BUF_SIZE];
1088
1089
#endif // !BC_ENABLE_LIBRARY
1090
1091
#endif // BC_VM_H
1092
1093