aboutsummaryrefslogtreecommitdiff
path: root/miscutils/bc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils/bc.c')
-rw-r--r--miscutils/bc.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 38ae7f7d1..4eb0f2d30 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -138,11 +138,54 @@
138//usage: 138//usage:
139//usage:#define dc_full_usage "\n" 139//usage:#define dc_full_usage "\n"
140//usage: "\nTiny RPN calculator. Operations:" 140//usage: "\nTiny RPN calculator. Operations:"
141//usage: "\n+, -, *, /, %, ~, ^," IF_FEATURE_DC_BIG(" |,") 141//usage: "\nArithmetic: + - * / % ^"
142//usage: IF_FEATURE_DC_BIG(
143//usage: "\n~ - divide with remainder"
144//usage: "\n| - modular exponentiation"
145//usage: "\nv - square root"
146//////// "\nA-F - digits 10..15
147//////// "\n_NNN - push negative number -NNN
148//////// "\n[string] - push string (in FreeBSD, \[, \] and \\ are escapes, not implemented here and in GNU)
149//////// "\nR - DC_LEX_POP pop and discard
150//////// "\nc - DC_LEX_CLEAR_STACK clear stack
151//////// "\nd - DC_LEX_DUPLICATE duplicate top-of-stack
152//////// "\nr - DC_LEX_SWAP swap top-of-stack
153//////// "\n:r - DC_LEX_COLON pop index, pop value, store to array 'r'
154//////// "\n;r - DC_LEX_SCOLON pop index, fetch from array 'r', push
155//////// "\nLr - DC_LEX_LOAD_POP pop register 'r', push
156//////// "\nSr - DC_LEX_STORE_PUSH pop, push to register 'r'
157//////// "\nlr - DC_LEX_LOAD read register 'r', push
158//////// "\nsr - DC_LEX_OP_ASSIGN pop, assign to register 'r'
159//////// "\n? - DC_LEX_READ read line and execute
160//////// "\nx - DC_LEX_EXECUTE pop string and execute
161//////// "\n<r - XC_LEX_OP_REL_GT pop, pop, execute register 'r' if top-of-stack was less
162//////// "\n>r - XC_LEX_OP_REL_LT pop, pop, execute register 'r' if top-of-stack was greater
163//////// "\n=r - XC_LEX_OP_REL_EQ pop, pop, execute register 'r' if equal
164//////// "\n !<r !>r !=r - negated forms
165//////// "\n >tef - "if greater execute register 't' else execute 'f'"
166//////// "\nQ - DC_LEX_NQUIT pop, "break N" from macro invocations
167//////// "\nq - DC_LEX_QUIT "break 2" (if less than 2 levels of macros, exit dc)
168//////// "\nX - DC_LEX_SCALE_FACTOR pop, push number of fractional digits
169//////// "\nZ - DC_LEX_LENGTH pop, push number of digits it has (or number of characters in string)
170//////// "\na - DC_LEX_ASCIIFY pop, push low-order byte as char or 1st char of string
171//////// "\n( - DC_LEX_LPAREN (FreeBSD, not in GNU) pop, pop, if top-of-stack was less push 1 else push 0
172//////// "\n{ - DC_LEX_LBRACE (FreeBSD, not in GNU) pop, pop, if top-of-stack was less-or-equal push 1 else push 0
173//////// "\nG - DC_LEX_EQ_NO_REG (FreeBSD, not in GNU) pop, pop, if equal push 1 else push 0
174//////// "\nN - DC_LEX_OP_BOOL_NOT (FreeBSD, not in GNU) pop, if 0 push 1 else push 0
175//////// FreeBSD also has J and M commands, used internally by bc
176//////// "\nn - DC_LEX_PRINT_POP pop, print without newline
177//////// "\nP - DC_LEX_PRINT_STREAM pop, print string or hex bytes
178//usage: )
142//usage: "\np - print top of the stack without popping" 179//usage: "\np - print top of the stack without popping"
143//usage: "\nf - print entire stack" 180//usage: "\nf - print entire stack"
144//usage: "\nk - pop the value and set the precision" 181//////// "\nz - DC_LEX_STACK_LEVEL push stack depth
182//////// "\nK - DC_LEX_SCALE push precision
183//////// "\nI - DC_LEX_IBASE push input radix
184//////// "\nO - DC_LEX_OBASE push output radix
185//usage: IF_FEATURE_DC_BIG(
186//usage: "\nk - pop the value and set precision"
145//usage: "\ni - pop the value and set input radix" 187//usage: "\ni - pop the value and set input radix"
188//usage: )
146//usage: "\no - pop the value and set output radix" 189//usage: "\no - pop the value and set output radix"
147//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16" 190//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16"
148//usage: 191//usage:
@@ -6217,13 +6260,20 @@ static unsigned long xc_program_len(BcNum *n)
6217{ 6260{
6218 size_t len = n->len; 6261 size_t len = n->len;
6219 6262
6220 if (n->rdx != len) return len; 6263 if (n->rdx != len)
6264 // length(100): rdx 0 len 3, return 3
6265 // length(0.01-0.01): rdx 2 len 0, return 2
6266 // dc: 0.01 0.01 - Zp: rdx 2 len 0, return 1
6267 return len != 0 ? len : (IS_BC ? n->rdx : 1);
6268
6269 // length(0): return 1
6270 // length(0.000nnn): count nnn
6221 for (;;) { 6271 for (;;) {
6222 if (len == 0) break; 6272 if (len == 0) break;
6223 len--; 6273 len--;
6224 if (n->num[len] != 0) break; 6274 if (n->num[len] != 0) break;
6225 } 6275 }
6226 return len; 6276 return len + 1;
6227} 6277}
6228 6278
6229static BC_STATUS zxc_program_builtin(char inst) 6279static BC_STATUS zxc_program_builtin(char inst)
@@ -6251,12 +6301,12 @@ static BC_STATUS zxc_program_builtin(char inst)
6251 if (inst == XC_INST_SQRT) 6301 if (inst == XC_INST_SQRT)
6252 s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); 6302 s = zbc_num_sqrt(num, &res.d.n, G.prog.scale);
6253#if ENABLE_BC 6303#if ENABLE_BC
6254 else if (len != 0 && opnd->t == XC_RESULT_ARRAY) { 6304 else if (len && opnd->t == XC_RESULT_ARRAY) {
6255 bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); 6305 bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
6256 } 6306 }
6257#endif 6307#endif
6258#if ENABLE_DC 6308#if ENABLE_DC
6259 else if (len != 0 && !BC_PROG_NUM(opnd, num)) { 6309 else if (len && !BC_PROG_NUM(opnd, num)) {
6260 char **str; 6310 char **str;
6261 size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx; 6311 size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx;
6262 6312
@@ -6265,6 +6315,8 @@ static BC_STATUS zxc_program_builtin(char inst)
6265 } 6315 }
6266#endif 6316#endif
6267 else { 6317 else {
6318//TODO: length(.00) and scale(.00) should return 2, they return 1 and 0 now
6319//(don't forget to check that dc Z and X commands do not break)
6268 bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num)); 6320 bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num));
6269 } 6321 }
6270 6322