Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 1 | /* |
| 2 | * ***************************************************************************** |
| 3 | * |
| 4 | * Copyright 2018 Gavin D. Howard |
| 5 | * |
| 6 | * Permission to use, copy, modify, and/or distribute this software for any |
| 7 | * purpose with or without fee is hereby granted. |
| 8 | * |
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
| 10 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
| 11 | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
| 12 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
| 13 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
| 14 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 15 | * PERFORMANCE OF THIS SOFTWARE. |
| 16 | * |
| 17 | * ***************************************************************************** |
| 18 | * |
| 19 | * Constant data for bc. |
| 20 | * |
| 21 | */ |
| 22 | |
Gavin Howard | 2949306 | 2018-03-20 19:57:37 -0600 | [diff] [blame] | 23 | #include <status.h> |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 24 | #include <lex.h> |
| 25 | #include <parse.h> |
| 26 | |
Gavin Howard | a280bde | 2018-03-13 13:49:12 -0600 | [diff] [blame] | 27 | const char *bc_header = |
Gavin Howard | 8495fe2 | 2018-03-24 15:09:59 -0600 | [diff] [blame] | 28 | "bc 0.5\n" |
Gavin Howard | 9d8285d | 2018-03-12 11:56:15 -0600 | [diff] [blame] | 29 | "bc copyright (c) 2018 Gavin D. Howard and contributors\n" |
Gavin Howard | a280bde | 2018-03-13 13:49:12 -0600 | [diff] [blame] | 30 | "Report bugs at: https://github.com/gavinhoward/bc\n\n" |
| 31 | "This is free software with ABSOLUTELY NO WARRANTY.\n\n"; |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 32 | |
| 33 | const char *bc_err_types[] = { |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 34 | "bc", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 35 | "Lex", |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 36 | "Parse", |
| 37 | "Math", |
| 38 | "Runtime", |
| 39 | "POSIX", |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 40 | }; |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 41 | |
Gavin Howard | 431435b | 2018-03-17 08:08:54 -0600 | [diff] [blame] | 42 | const uint8_t bc_err_type_indices[] = { |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 43 | |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 44 | BC_ERR_IDX_BC, |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 45 | BC_ERR_IDX_BC, |
| 46 | BC_ERR_IDX_BC, |
Gavin Howard | e77b83d | 2018-03-29 14:24:26 -0600 | [diff] [blame] | 47 | BC_ERR_IDX_BC, |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 48 | |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 49 | BC_ERR_IDX_LEX, |
| 50 | BC_ERR_IDX_LEX, |
| 51 | BC_ERR_IDX_LEX, |
| 52 | BC_ERR_IDX_LEX, |
| 53 | |
| 54 | BC_ERR_IDX_PARSE, |
| 55 | BC_ERR_IDX_PARSE, |
| 56 | BC_ERR_IDX_PARSE, |
| 57 | BC_ERR_IDX_PARSE, |
| 58 | BC_ERR_IDX_PARSE, |
| 59 | BC_ERR_IDX_PARSE, |
| 60 | BC_ERR_IDX_PARSE, |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 61 | |
| 62 | BC_ERR_IDX_MATH, |
| 63 | BC_ERR_IDX_MATH, |
| 64 | BC_ERR_IDX_MATH, |
| 65 | BC_ERR_IDX_MATH, |
| 66 | BC_ERR_IDX_MATH, |
| 67 | BC_ERR_IDX_MATH, |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 68 | |
| 69 | BC_ERR_IDX_EXEC, |
| 70 | BC_ERR_IDX_EXEC, |
| 71 | BC_ERR_IDX_EXEC, |
| 72 | BC_ERR_IDX_EXEC, |
| 73 | BC_ERR_IDX_EXEC, |
| 74 | BC_ERR_IDX_EXEC, |
| 75 | BC_ERR_IDX_EXEC, |
| 76 | BC_ERR_IDX_EXEC, |
| 77 | BC_ERR_IDX_EXEC, |
| 78 | BC_ERR_IDX_EXEC, |
| 79 | BC_ERR_IDX_EXEC, |
| 80 | BC_ERR_IDX_EXEC, |
| 81 | BC_ERR_IDX_EXEC, |
Gavin Howard | 9a65a4e | 2018-03-15 18:26:57 -0600 | [diff] [blame] | 82 | |
| 83 | BC_ERR_IDX_POSIX, |
| 84 | BC_ERR_IDX_POSIX, |
| 85 | BC_ERR_IDX_POSIX, |
| 86 | BC_ERR_IDX_POSIX, |
| 87 | BC_ERR_IDX_POSIX, |
| 88 | BC_ERR_IDX_POSIX, |
| 89 | BC_ERR_IDX_POSIX, |
| 90 | BC_ERR_IDX_POSIX, |
| 91 | BC_ERR_IDX_POSIX, |
| 92 | BC_ERR_IDX_POSIX, |
| 93 | BC_ERR_IDX_POSIX, |
| 94 | BC_ERR_IDX_POSIX, |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 95 | |
| 96 | }; |
| 97 | |
| 98 | const char *bc_err_descs[] = { |
| 99 | |
| 100 | NULL, |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 101 | "memory allocation error", |
| 102 | "I/O error", |
Gavin Howard | ddaa4c1 | 2018-03-24 14:50:12 -0600 | [diff] [blame] | 103 | "file is not text", |
Gavin Howard | e77b83d | 2018-03-29 14:24:26 -0600 | [diff] [blame] | 104 | |
| 105 | "bad character", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 106 | "string end could not be found", |
| 107 | "comment end could not be found", |
| 108 | "end of file", |
| 109 | |
Gavin Howard | bdb2f92 | 2018-03-15 09:25:18 -0600 | [diff] [blame] | 110 | "bad token", |
| 111 | "bad expression", |
| 112 | "bad print statement", |
| 113 | "bad function definition", |
| 114 | "bad assignment: left must be scale, ibase, " |
| 115 | "obase, last, var, or array element", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 116 | "no auto variable found", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 117 | "function parameter or auto var has the same name as another", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 118 | |
| 119 | "negative number", |
| 120 | "non integer number", |
| 121 | "overflow", |
| 122 | "divide by zero", |
| 123 | "negative square root", |
Gavin Howard | bdb2f92 | 2018-03-15 09:25:18 -0600 | [diff] [blame] | 124 | "bad number string", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 125 | |
Gavin Howard | 27fdfb9 | 2018-03-21 07:56:59 -0600 | [diff] [blame] | 126 | "could not open file", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 127 | "mismatched parameters", |
| 128 | "undefined function", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 129 | "file is not executable", |
| 130 | "could not install signal handler", |
Gavin Howard | 293aec9 | 2018-03-13 12:29:18 -0600 | [diff] [blame] | 131 | "bad scale; must be [0, BC_SCALE_MAX]", |
| 132 | "bad ibase; must be [2, 16]", |
| 133 | "bad obase; must be [2, BC_BASE_MAX]", |
Gavin Howard | bdb2f92 | 2018-03-15 09:25:18 -0600 | [diff] [blame] | 134 | "string too long: must be [1, BC_STRING_MAX]", |
| 135 | "array too long; must be [1, BC_DIM_MAX]", |
| 136 | "bad read() expression", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 137 | "read() call inside of a read() call", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 138 | "variable is wrong type", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 139 | |
Gavin Howard | bdb2f92 | 2018-03-15 09:25:18 -0600 | [diff] [blame] | 140 | "POSIX only allows one character names; the following is bad:", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 141 | "POSIX does not allow '#' script comments", |
| 142 | "POSIX does not allow the following keyword:", |
| 143 | "POSIX does not allow a period ('.') as a shortcut for the last result", |
| 144 | "POSIX requires parentheses around return expressions", |
Gavin Howard | bdb2f92 | 2018-03-15 09:25:18 -0600 | [diff] [blame] | 145 | "POSIX does not allow boolean operators; the following is bad:", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 146 | "POSIX does not allow comparison operators outside if or loops", |
Gavin Howard | 5aff504 | 2018-03-23 08:08:19 -0600 | [diff] [blame] | 147 | "POSIX requires exactly one comparison operator per condition", |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 148 | "POSIX does not allow an empty init expression in a for loop", |
| 149 | "POSIX does not allow an empty condition expression in a for loop", |
| 150 | "POSIX does not allow an empty update expression in a for loop", |
| 151 | "POSIX requires the left brace be on the same line as the function header", |
| 152 | |
| 153 | }; |
| 154 | |
Gavin Howard | ff66e29 | 2018-03-28 12:47:58 -0600 | [diff] [blame] | 155 | const char bc_sig_msg[36] = "\n\ninterrupt (type \"quit\" to exit)\n\n"; |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 156 | |
Gavin Howard | ff66e29 | 2018-03-28 12:47:58 -0600 | [diff] [blame] | 157 | const char bc_lang_func_main[7] = "(main)"; |
| 158 | const char bc_lang_func_read[7] = "(read)"; |
| 159 | |
Gavin Howard | e0eec66 | 2018-03-29 17:53:20 -0600 | [diff] [blame^] | 160 | #ifndef NDEBUG |
Gavin Howard | ff66e29 | 2018-03-28 12:47:58 -0600 | [diff] [blame] | 161 | const char bc_lang_inst_chars[] = |
Gavin Howard | e0eec66 | 2018-03-29 17:53:20 -0600 | [diff] [blame^] | 162 | "edED_^*/%+-=;?~<>!|&`{}@[],NVACaI.LlrOqpQsSJjPR$H"; |
| 163 | #endif // NDEBUG |
Gavin Howard | 101b5e6 | 2018-03-26 07:46:27 -0600 | [diff] [blame] | 164 | |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 165 | const BcLexKeyword bc_lex_keywords[20] = { |
Gavin Howard | 665a993 | 2018-03-26 13:04:58 -0600 | [diff] [blame] | 166 | BC_LEX_KW_ENTRY("auto", 4, true), |
| 167 | BC_LEX_KW_ENTRY("break", 5, true), |
| 168 | BC_LEX_KW_ENTRY("continue", 8, false), |
| 169 | BC_LEX_KW_ENTRY("define", 6, true), |
| 170 | BC_LEX_KW_ENTRY("else", 4, false), |
| 171 | BC_LEX_KW_ENTRY("for", 3, true), |
| 172 | BC_LEX_KW_ENTRY("halt", 4, false), |
| 173 | BC_LEX_KW_ENTRY("ibase", 5, true), |
| 174 | BC_LEX_KW_ENTRY("if", 2, true), |
| 175 | BC_LEX_KW_ENTRY("last", 4, false), |
| 176 | BC_LEX_KW_ENTRY("length", 6, true), |
| 177 | BC_LEX_KW_ENTRY("limits", 6, false), |
| 178 | BC_LEX_KW_ENTRY("obase", 5, true), |
| 179 | BC_LEX_KW_ENTRY("print", 5, false), |
| 180 | BC_LEX_KW_ENTRY("quit", 4, true), |
| 181 | BC_LEX_KW_ENTRY("read", 4, false), |
| 182 | BC_LEX_KW_ENTRY("return", 6, true), |
| 183 | BC_LEX_KW_ENTRY("scale", 5, true), |
| 184 | BC_LEX_KW_ENTRY("sqrt", 4, true), |
| 185 | BC_LEX_KW_ENTRY("while", 5, true), |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 186 | }; |
| 187 | |
| 188 | const char bc_num_hex_digits[] = "0123456789ABCDEF"; |
| 189 | |
| 190 | // This is an array that corresponds to token types. An entry is |
| 191 | // true if the token is valid in an expression, false otherwise. |
| 192 | const bool bc_parse_token_exprs[] = { |
| 193 | |
| 194 | true, |
| 195 | true, |
| 196 | |
| 197 | true, |
| 198 | |
| 199 | true, |
| 200 | true, |
| 201 | true, |
| 202 | |
| 203 | true, |
| 204 | true, |
| 205 | |
| 206 | true, |
| 207 | true, |
| 208 | true, |
| 209 | true, |
| 210 | true, |
| 211 | true, |
| 212 | true, |
| 213 | |
| 214 | true, |
| 215 | true, |
| 216 | true, |
| 217 | true, |
| 218 | true, |
| 219 | true, |
| 220 | |
| 221 | true, |
| 222 | |
| 223 | true, |
| 224 | true, |
| 225 | |
| 226 | true, |
| 227 | |
| 228 | false, |
| 229 | |
| 230 | false, |
| 231 | |
| 232 | true, |
| 233 | true, |
| 234 | |
| 235 | false, |
| 236 | false, |
| 237 | |
| 238 | false, |
| 239 | false, |
| 240 | |
| 241 | false, |
| 242 | false, |
| 243 | |
| 244 | false, |
| 245 | true, |
| 246 | true, |
| 247 | |
| 248 | false, |
| 249 | false, |
| 250 | false, |
| 251 | false, |
| 252 | false, |
| 253 | false, |
| 254 | false, |
| 255 | true, |
| 256 | false, |
| 257 | true, |
| 258 | true, |
| 259 | true, |
| 260 | true, |
| 261 | false, |
| 262 | false, |
| 263 | true, |
| 264 | false, |
| 265 | true, |
| 266 | true, |
| 267 | false, |
| 268 | |
| 269 | false, |
| 270 | |
| 271 | false, |
| 272 | }; |
| 273 | |
| 274 | // This is an array of data for operators that correspond to token types. |
| 275 | // The last corresponds to BC_PARSE_OP_NEGATE_IDX since it doesn't have |
| 276 | // its own token type (it is the same token at the binary minus operator). |
| 277 | const BcOp bc_parse_ops[] = { |
| 278 | |
| 279 | { 0, false }, |
| 280 | { 0, false }, |
| 281 | |
| 282 | { 1, false }, |
| 283 | |
| 284 | { 2, false }, |
| 285 | |
| 286 | { 3, true }, |
| 287 | { 3, true }, |
| 288 | { 3, true }, |
| 289 | |
| 290 | { 4, true }, |
| 291 | { 4, true }, |
| 292 | |
| 293 | { 6, true }, |
| 294 | { 6, true }, |
| 295 | { 6, true }, |
| 296 | { 6, true }, |
| 297 | { 6, true }, |
| 298 | { 6, true }, |
| 299 | |
| 300 | { 7, false }, |
| 301 | |
| 302 | { 8, true }, |
| 303 | { 8, true }, |
| 304 | |
| 305 | { 5, false }, |
| 306 | { 5, false }, |
| 307 | { 5, false }, |
| 308 | { 5, false }, |
| 309 | { 5, false }, |
| 310 | { 5, false }, |
| 311 | { 5, false }, |
| 312 | |
| 313 | }; |
| 314 | |
Gavin Howard | ff66e29 | 2018-03-28 12:47:58 -0600 | [diff] [blame] | 315 | const char bc_program_byte_fmt[] = "%02x"; |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 316 | |
| 317 | const BcNumBinaryFunc bc_program_math_ops[] = { |
| 318 | |
Gavin Howard | 101b5e6 | 2018-03-26 07:46:27 -0600 | [diff] [blame] | 319 | bc_num_pow, |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 320 | bc_num_mul, |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 321 | bc_num_div, |
Gavin Howard | 101b5e6 | 2018-03-26 07:46:27 -0600 | [diff] [blame] | 322 | bc_num_mod, |
| 323 | bc_num_add, |
| 324 | bc_num_sub, |
Gavin Howard | f456d37 | 2018-03-10 20:11:41 -0700 | [diff] [blame] | 325 | |
| 326 | }; |
| 327 | |
Gavin Howard | ff66e29 | 2018-03-28 12:47:58 -0600 | [diff] [blame] | 328 | const char bc_program_stdin_name[] = "<stdin>"; |
| 329 | const char bc_program_ready_prompt[] = "ready for more input\n\n"; |