diff options
Diffstat (limited to 'miscutils/bc.c')
-rw-r--r-- | miscutils/bc.c | 64 |
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 | ||
6229 | static BC_STATUS zxc_program_builtin(char inst) | 6279 | static 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 | ||