diff options
author | Gavin D. Howard <gavin@gavinhoward.com> | 2023-02-22 22:13:37 -0700 |
---|---|---|
committer | Gavin D. Howard <gavin@gavinhoward.com> | 2023-02-22 22:19:09 -0700 |
commit | 63ab894472d0bfa6127659e8912b46467044b1d2 (patch) | |
tree | ac20ec5a3ea2d7583f3803a647359eca23243bd6 | |
parent | 1a5a0bfa8788ea5ccdd45eb399da14a9d7892175 (diff) | |
download | bc-63ab894472d0bfa6127659e8912b46467044b1d2.tar.gz |
Add the gx command to dc
This command pushes 1 if extended registers are on, 0 otherwise.
This commit includes the tests, the changes to the manpages, the works.
I still have to run through the release process, but I think this is
pretty safe.
Signed-off-by: Gavin D. Howard <gavin@gavinhoward.com>
-rw-r--r-- | include/lang.h | 3 | ||||
-rw-r--r-- | include/lex.h | 3 | ||||
-rw-r--r-- | include/program.h | 4 | ||||
-rw-r--r-- | manuals/dc.1.md.in | 5 | ||||
-rw-r--r-- | manuals/dc/A.1 | 4 | ||||
-rw-r--r-- | manuals/dc/A.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/E.1 | 4 | ||||
-rw-r--r-- | manuals/dc/E.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/EH.1 | 4 | ||||
-rw-r--r-- | manuals/dc/EH.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/EHN.1 | 4 | ||||
-rw-r--r-- | manuals/dc/EHN.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/EN.1 | 4 | ||||
-rw-r--r-- | manuals/dc/EN.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/H.1 | 4 | ||||
-rw-r--r-- | manuals/dc/H.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/HN.1 | 4 | ||||
-rw-r--r-- | manuals/dc/HN.1.md | 5 | ||||
-rw-r--r-- | manuals/dc/N.1 | 4 | ||||
-rw-r--r-- | manuals/dc/N.1.md | 5 | ||||
-rw-r--r-- | src/bc_parse.c | 2 | ||||
-rw-r--r-- | src/data.c | 12 | ||||
-rw-r--r-- | src/dc_lex.c | 1 | ||||
-rw-r--r-- | src/dc_parse.c | 1 | ||||
-rw-r--r-- | src/program.c | 11 | ||||
-rwxr-xr-x | tests/other.sh | 36 |
26 files changed, 141 insertions, 9 deletions
diff --git a/include/lang.h b/include/lang.h index 9eee3279..97aeeaa9 100644 --- a/include/lang.h +++ b/include/lang.h @@ -277,6 +277,9 @@ typedef enum BcInst #if DC_ENABLED + /// dc extended registers command. + BC_INST_EXTENDED_REGISTERS, + /// dc's return; it pops an executing string off of the stack. BC_INST_POP_EXEC, diff --git a/include/lex.h b/include/lex.h index 060f5bea..ac9b7b6e 100644 --- a/include/lex.h +++ b/include/lex.h @@ -409,6 +409,9 @@ typedef enum BcLexType #if DC_ENABLED + /// dc extended registers keyword. + BC_LEX_EXTENDED_REGISTERS, + /// A special token for dc to calculate equal without a register. BC_LEX_EQ_NO_REG, diff --git a/include/program.h b/include/program.h index 93621d4d..ff32d5db 100644 --- a/include/program.h +++ b/include/program.h @@ -608,6 +608,7 @@ extern const char bc_program_esc_seqs[]; &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ + &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, \ &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, \ @@ -701,6 +702,7 @@ extern const char bc_program_esc_seqs[]; &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ + &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, \ &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, \ @@ -959,6 +961,7 @@ extern const char bc_program_esc_seqs[]; &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ + &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, \ &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, \ @@ -1027,6 +1030,7 @@ extern const char bc_program_esc_seqs[]; &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ + &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, \ &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, \ diff --git a/manuals/dc.1.md.in b/manuals/dc.1.md.in index 6e88a643..0750a6d8 100644 --- a/manuals/dc.1.md.in +++ b/manuals/dc.1.md.in @@ -1123,6 +1123,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/A.1 b/manuals/dc/A.1 index ba401cb3..277bd48d 100644 --- a/manuals/dc/A.1 +++ b/manuals/dc/A.1 @@ -1251,6 +1251,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/A.1.md b/manuals/dc/A.1.md index 51a8335f..ece5aba3 100644 --- a/manuals/dc/A.1.md +++ b/manuals/dc/A.1.md @@ -1083,6 +1083,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/E.1 b/manuals/dc/E.1 index bcce9f87..0bc1a6dc 100644 --- a/manuals/dc/E.1 +++ b/manuals/dc/E.1 @@ -1036,6 +1036,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/E.1.md b/manuals/dc/E.1.md index e11381cf..867928b2 100644 --- a/manuals/dc/E.1.md +++ b/manuals/dc/E.1.md @@ -914,6 +914,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/EH.1 b/manuals/dc/EH.1 index 4b3ba915..6dadcdc5 100644 --- a/manuals/dc/EH.1 +++ b/manuals/dc/EH.1 @@ -1036,6 +1036,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/EH.1.md b/manuals/dc/EH.1.md index fd2a28f8..3c04a0cb 100644 --- a/manuals/dc/EH.1.md +++ b/manuals/dc/EH.1.md @@ -914,6 +914,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/EHN.1 b/manuals/dc/EHN.1 index 01ca772f..a756a1e8 100644 --- a/manuals/dc/EHN.1 +++ b/manuals/dc/EHN.1 @@ -1036,6 +1036,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/EHN.1.md b/manuals/dc/EHN.1.md index b24c8790..26638cbd 100644 --- a/manuals/dc/EHN.1.md +++ b/manuals/dc/EHN.1.md @@ -914,6 +914,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/EN.1 b/manuals/dc/EN.1 index 555ad7e1..b297bfcb 100644 --- a/manuals/dc/EN.1 +++ b/manuals/dc/EN.1 @@ -1036,6 +1036,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/EN.1.md b/manuals/dc/EN.1.md index 5025bb0e..97e41e42 100644 --- a/manuals/dc/EN.1.md +++ b/manuals/dc/EN.1.md @@ -914,6 +914,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/H.1 b/manuals/dc/H.1 index 94d2e73d..69b030c8 100644 --- a/manuals/dc/H.1 +++ b/manuals/dc/H.1 @@ -1251,6 +1251,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/H.1.md b/manuals/dc/H.1.md index f9b45468..d56372d6 100644 --- a/manuals/dc/H.1.md +++ b/manuals/dc/H.1.md @@ -1083,6 +1083,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/HN.1 b/manuals/dc/HN.1 index ac06c37d..0b92b983 100644 --- a/manuals/dc/HN.1 +++ b/manuals/dc/HN.1 @@ -1251,6 +1251,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/HN.1.md b/manuals/dc/HN.1.md index 44805105..28a7b379 100644 --- a/manuals/dc/HN.1.md +++ b/manuals/dc/HN.1.md @@ -1083,6 +1083,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/manuals/dc/N.1 b/manuals/dc/N.1 index fef82c51..1a160a4b 100644 --- a/manuals/dc/N.1 +++ b/manuals/dc/N.1 @@ -1251,6 +1251,10 @@ section). Pushes the line length set by \f[B]DC_LINE_LENGTH\f[R] (see the \f[B]ENVIRONMENT VARIABLES\f[R] section) onto the stack. .TP +\f[B]gx\f[R] +Pushes \f[B]1\f[R] onto the stack if extended register mode is on, +\f[B]0\f[R] otherwise. +.TP \f[B]gz\f[R] Pushes \f[B]0\f[R] onto the stack if the leading zero setting has not been enabled with the \f[B]-z\f[R] or \f[B]--leading-zeroes\f[R] options diff --git a/manuals/dc/N.1.md b/manuals/dc/N.1.md index 3b9dfbeb..f5ef42d6 100644 --- a/manuals/dc/N.1.md +++ b/manuals/dc/N.1.md @@ -1083,6 +1083,11 @@ other character produces a parse error (see the **ERRORS** section). : Pushes the line length set by **DC_LINE_LENGTH** (see the **ENVIRONMENT VARIABLES** section) onto the stack. +**gx** + +: Pushes **1** onto the stack if extended register mode is on, **0** + otherwise. + **gz** : Pushes **0** onto the stack if the leading zero setting has not been enabled diff --git a/src/bc_parse.c b/src/bc_parse.c index 13e03a49..4cf886ef 100644 --- a/src/bc_parse.c +++ b/src/bc_parse.c @@ -1888,6 +1888,7 @@ bc_parse_stmt(BcParse* p) case BC_LEX_KW_AUTO: case BC_LEX_KW_DEFINE: #if DC_ENABLED + case BC_LEX_EXTENDED_REGISTERS: case BC_LEX_EQ_NO_REG: case BC_LEX_COLON: case BC_LEX_EXECUTE: @@ -2436,6 +2437,7 @@ bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next) case BC_LEX_KW_STREAM: case BC_LEX_KW_ELSE: #if DC_ENABLED + case BC_LEX_EXTENDED_REGISTERS: case BC_LEX_EQ_NO_REG: case BC_LEX_COLON: case BC_LEX_EXECUTE: @@ -1199,12 +1199,12 @@ const uchar dc_parse_insts[] = { #if BC_ENABLED BC_INST_INVALID, #endif // BC_ENABLED - BC_INST_LEADING_ZERO, BC_INST_PRINT_STREAM, BC_INST_INVALID, - BC_INST_REL_EQ, BC_INST_INVALID, BC_INST_EXECUTE, - BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, BC_INST_INVALID, - BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, - BC_INST_POP, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, + BC_INST_LEADING_ZERO, BC_INST_PRINT_STREAM, BC_INST_INVALID, + BC_INST_EXTENDED_REGISTERS, BC_INST_REL_EQ, BC_INST_INVALID, + BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, + BC_INST_INVALID, BC_INST_STACK_LEN, BC_INST_DUPLICATE, + BC_INST_SWAP, BC_INST_POP, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, #if BC_ENABLE_EXTRA_MATH BC_INST_INVALID, #endif // BC_ENABLE_EXTRA_MATH diff --git a/src/dc_lex.c b/src/dc_lex.c index cf737ea3..963e3f13 100644 --- a/src/dc_lex.c +++ b/src/dc_lex.c @@ -278,6 +278,7 @@ dc_lex_token(BcLex* l) c2 = l->buf[l->i]; if (c2 == 'l') l->t = BC_LEX_KW_LINE_LENGTH; + else if (c2 == 'x') l->t = BC_LEX_EXTENDED_REGISTERS; else if (c2 == 'z') l->t = BC_LEX_KW_LEADING_ZERO; else bc_lex_invalidChar(l, c2); diff --git a/src/dc_parse.c b/src/dc_parse.c index 638ccfb7..2a6f387a 100644 --- a/src/dc_parse.c +++ b/src/dc_parse.c @@ -349,6 +349,7 @@ dc_parse_token(BcParse* p, BcLexType t, uint8_t flags) case BC_LEX_KW_LEADING_ZERO: case BC_LEX_KW_STREAM: case BC_LEX_KW_ELSE: + case BC_LEX_EXTENDED_REGISTERS: case BC_LEX_EQ_NO_REG: case BC_LEX_EXECUTE: case BC_LEX_PRINT_STACK: diff --git a/src/program.c b/src/program.c index 5ede93d5..b6fac12c 100644 --- a/src/program.c +++ b/src/program.c @@ -2689,12 +2689,20 @@ bc_program_globalSetting(BcProgram* p, uchar inst) BcBigDig val; // Make sure the instruction is valid. +#if DC_ENABLED + assert((inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO) || + (BC_IS_DC && inst == BC_INST_EXTENDED_REGISTERS)); +#else // DC_ENABLED assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO); +#endif // DC_ENABLED if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm->line_len; #if BC_ENABLED else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0); #endif // BC_ENABLED +#if DC_ENABLED + else if (inst == BC_INST_EXTENDED_REGISTERS) val = (DC_X != 0); +#endif // DC_ENABLED else val = (BC_Z != 0); // Push the global. @@ -3246,6 +3254,9 @@ bc_program_exec(BcProgram* p) #if BC_ENABLED BC_PROG_LBL(BC_INST_GLOBAL_STACKS): #endif // BC_ENABLED +#if DC_ENABLED + BC_PROG_LBL(BC_INST_EXTENDED_REGISTERS): +#endif // DC_ENABLE BC_PROG_LBL(BC_INST_LEADING_ZERO): // clang-format on { diff --git a/tests/other.sh b/tests/other.sh index de4059b9..04dbf98d 100755 --- a/tests/other.sh +++ b/tests/other.sh @@ -273,8 +273,8 @@ else printf 'Running dc Easter script...' - easter_res="$outputdir/dc_outputs/easter.txt" - easter_out="$outputdir/dc_outputs/easter_results.txt" + easter_out="$outputdir/dc_outputs/easter.txt" + easter_res="$outputdir/dc_outputs/easter_results.txt" outdir=$(dirname "$easter_out") @@ -287,11 +287,41 @@ else "$testdir/dc/scripts/easter.sh" "$exe" 2021 "$@" 2> /dev/null | cut -c1-12 > "$easter_out" err="$?" - checktest "$d" "$err" "Easter script" "$easter_res" "$easter_out" + checktest "$d" "$err" "Easter script" "$easter_out" "$easter_res" printf 'pass\n' fi + unset DC_ENV_ARGS + unset DC_EXPR_EXIT + + printf 'Running dc extended register command tests...' + + ext_reg_out="$outputdir/dc_outputs/ext_reg.txt" + ext_reg_res="$outputdir/dc_outputs/ext_reg_results.txt" + + outdir=$(dirname "$ext_reg_out") + + if [ ! -d "$outdir" ]; then + mkdir -p "$outdir" + fi + + printf '0\n' > "$ext_reg_res" + + "$exe" -e "gxpR" "$@" 2> /dev/null > "$ext_reg_out" + err="$?" + + checktest "$d" "$err" "Extended register command" "$ext_reg_out" "$ext_reg_res" + + printf '1\n' > "$ext_reg_res" + + "$exe" -x -e "gxpR" "$@" 2> /dev/null > "$ext_reg_out" + err="$?" + + checktest "$d" "$err" "Extended register command" "$ext_reg_out" "$ext_reg_res" + + printf 'pass\n' + fi out1="$outputdir/${d}_outputs/${d}_other.txt" |