| Commit | Line | Data |
|---|---|---|
| eeab7066 RT |
1 | /* |
| 2 | ||
| 3 | This code was written as part of the CMU Common Lisp project at | |
| 4 | Carnegie Mellon University, and has been placed in the public domain. | |
| 5 | ||
| 6 | */ | |
| 7 | ||
| 62957726 | 8 | #include <stdio.h> |
| 9 | #include <ctype.h> | |
| 10 | #include <signal.h> | |
| 0ac2c885 | 11 | #include <string.h> |
| 824dfde0 | 12 | #include <strings.h> |
| 0ac2c885 | 13 | #include <stdlib.h> |
| 62957726 | 14 | |
| 15 | #include "lisp.h" | |
| 16 | #include "internals.h" | |
| 17 | #include "globals.h" | |
| 18 | #include "vars.h" | |
| 19 | #include "parse.h" | |
| 3861a7bf | 20 | #include "os.h" |
| 62957726 | 21 | #include "interrupt.h" |
| 22 | #include "lispregs.h" | |
| 23 | #include "monitor.h" | |
| 24 | #include "arch.h" | |
| 62957726 | 25 | #include "search.h" |
| 26 | ||
| 2df7ff23 | 27 | /* |
| 28 | * What platforms DON'T have strcasecmp nowadays? Enable this if you | |
| 29 | * don't have it. | |
| 30 | */ | |
| 31 | #if 0 | |
| 62957726 | 32 | |
| 9a8c1c2f | 33 | static int |
| 34 | strcasecmp(s1, s2) | |
| 35 | char *s1, *s2; | |
| 62957726 | 36 | { |
| 37 | int c1, c2; | |
| 38 | ||
| 9a8c1c2f | 39 | do { |
| 40 | c1 = (*s1++); | |
| 41 | if (isupper(c1)) | |
| 42 | c1 = tolower(c1); | |
| 62957726 | 43 | |
| 9a8c1c2f | 44 | c2 = (*s2++); |
| 45 | if (isupper(c2)) | |
| 46 | c2 = tolower(c2); | |
| 47 | } while (c1 == c2 && c1 != 0); | |
| 62957726 | 48 | |
| 9a8c1c2f | 49 | return c1 - c2; |
| 62957726 | 50 | } |
| 51 | ||
| 52 | #endif | |
| 53 | ||
| 9a8c1c2f | 54 | static void |
| 55 | skip_ws(char **ptr) | |
| 62957726 | 56 | { |
| 57 | while (**ptr <= ' ' && **ptr != '\0') | |
| 9a8c1c2f | 58 | (*ptr)++; |
| 62957726 | 59 | } |
| 60 | ||
| 9a8c1c2f | 61 | static boolean |
| 62 | string_to_long(char *token, long *value) | |
| 62957726 | 63 | { |
| 64 | int base, digit; | |
| 65 | long num; | |
| 66 | char *ptr; | |
| 67 | ||
| 68 | if (token == 0) | |
| 9a8c1c2f | 69 | return FALSE; |
| 62957726 | 70 | |
| 71 | if (token[0] == '0') | |
| 9a8c1c2f | 72 | if (token[1] == 'x') { |
| 73 | base = 16; | |
| 74 | token += 2; | |
| 75 | } else { | |
| 76 | base = 8; | |
| 77 | token++; | |
| 78 | } else if (token[0] == '#') { | |
| 79 | switch (token[1]) { | |
| 80 | case 'x': | |
| 81 | case 'X': | |
| 82 | base = 16; | |
| 83 | token += 2; | |
| 84 | break; | |
| 85 | case 'o': | |
| 86 | case 'O': | |
| 87 | base = 8; | |
| 88 | token += 2; | |
| 89 | break; | |
| 90 | default: | |
| 91 | return FALSE; | |
| 92 | } | |
| 93 | } else | |
| 94 | base = 10; | |
| 62957726 | 95 | |
| 96 | num = 0; | |
| 97 | ptr = token; | |
| 98 | while (*ptr != '\0') { | |
| 9a8c1c2f | 99 | if (*ptr >= 'a' && *ptr <= 'f') |
| 100 | digit = *ptr + 10 - 'a'; | |
| 101 | else if (*ptr >= 'A' && *ptr <= 'F') | |
| 102 | digit = *ptr + 10 - 'A'; | |
| 103 | else if (*ptr >= '0' && *ptr <= '9') | |
| 104 | digit = *ptr - '0'; | |
| 105 | else | |
| 106 | return FALSE; | |
| 107 | if (digit < 0 || digit >= base) | |
| 108 | return FALSE; | |
| 109 | ||
| 110 | ptr++; | |
| 111 | num = num * base + digit; | |
| 62957726 | 112 | } |
| 113 | ||
| 114 | *value = num; | |
| 115 | return TRUE; | |
| 116 | } | |
| 117 | ||
| 9a8c1c2f | 118 | static boolean |
| 119 | lookup_variable(char *name, lispobj * result) | |
| 62957726 | 120 | { |
| 121 | struct var *var = lookup_by_name(name); | |
| 122 | ||
| 123 | if (var == NULL) | |
| 9a8c1c2f | 124 | return FALSE; |
| 62957726 | 125 | else { |
| 9a8c1c2f | 126 | *result = var_value(var); |
| 127 | return TRUE; | |
| 62957726 | 128 | } |
| 129 | } | |
| 130 | ||
| 131 | ||
| 9a8c1c2f | 132 | boolean |
| b8d0dfaf | 133 | more_p(char **ptr) |
| 62957726 | 134 | { |
| 135 | skip_ws(ptr); | |
| 136 | ||
| 137 | if (**ptr == '\0') | |
| 9a8c1c2f | 138 | return FALSE; |
| 62957726 | 139 | else |
| 9a8c1c2f | 140 | return TRUE; |
| 62957726 | 141 | } |
| 142 | ||
| 9a8c1c2f | 143 | char * |
| b8d0dfaf | 144 | parse_token(char **ptr) |
| 62957726 | 145 | { |
| 146 | char *token; | |
| 147 | ||
| 148 | skip_ws(ptr); | |
| 9a8c1c2f | 149 | |
| 62957726 | 150 | if (**ptr == '\0') |
| 9a8c1c2f | 151 | return NULL; |
| 62957726 | 152 | |
| 153 | token = *ptr; | |
| 154 | ||
| 155 | while (**ptr > ' ') | |
| 9a8c1c2f | 156 | (*ptr)++; |
| 62957726 | 157 | |
| 158 | if (**ptr != '\0') { | |
| 9a8c1c2f | 159 | **ptr = '\0'; |
| 160 | (*ptr)++; | |
| 62957726 | 161 | } |
| 162 | ||
| 163 | return token; | |
| 164 | } | |
| 165 | ||
| 166 | #if 0 | |
| 9a8c1c2f | 167 | static boolean |
| 168 | number_p(token) | |
| 169 | char *token; | |
| 62957726 | 170 | { |
| 171 | char *okay; | |
| 172 | ||
| 173 | if (token == NULL) | |
| 9a8c1c2f | 174 | return FALSE; |
| 62957726 | 175 | |
| 176 | okay = "abcdefABCDEF987654321d0"; | |
| 177 | ||
| 178 | if (token[0] == '0') | |
| 9a8c1c2f | 179 | if (token[1] == 'x' || token[1] == 'X') |
| 180 | token += 2; | |
| 181 | else { | |
| 182 | token++; | |
| 183 | okay += 14; | |
| 184 | } else if (token[0] == '#') { | |
| 185 | switch (token[1]) { | |
| 186 | case 'x': | |
| 187 | case 'X': | |
| 188 | break; | |
| 189 | case 'o': | |
| 190 | case 'O': | |
| 191 | okay += 14; | |
| 192 | break; | |
| 193 | default: | |
| 194 | return FALSE; | |
| 195 | } | |
| 196 | } else | |
| 197 | okay += 12; | |
| 62957726 | 198 | |
| 199 | while (*token != '\0') | |
| 9a8c1c2f | 200 | if (index(okay, *token++) == NULL) |
| 201 | return FALSE; | |
| 62957726 | 202 | return TRUE; |
| 203 | } | |
| 204 | #endif | |
| 205 | ||
| 9a8c1c2f | 206 | long |
| b8d0dfaf | 207 | parse_number(char **ptr) |
| 62957726 | 208 | { |
| 209 | char *token = parse_token(ptr); | |
| 210 | long result; | |
| 211 | ||
| 212 | if (token == NULL) { | |
| 9a8c1c2f | 213 | printf("Expected a number.\n"); |
| 214 | throw_to_monitor(); | |
| 215 | } else if (string_to_long(token, &result)) | |
| 216 | return result; | |
| 62957726 | 217 | else { |
| 9a8c1c2f | 218 | printf("Invalid number: ``%s''\n", token); |
| 219 | throw_to_monitor(); | |
| 62957726 | 220 | } |
| 221 | return 0; | |
| 222 | } | |
| 223 | ||
| 9a8c1c2f | 224 | char * |
| b8d0dfaf | 225 | parse_addr(char **ptr) |
| 62957726 | 226 | { |
| 227 | char *token = parse_token(ptr); | |
| 228 | long result; | |
| 229 | ||
| 230 | if (token == NULL) { | |
| 9a8c1c2f | 231 | printf("Expected an address.\n"); |
| 232 | throw_to_monitor(); | |
| 233 | } else if (token[0] == '$') { | |
| 234 | if (!lookup_variable(token + 1, (lispobj *) & result)) { | |
| 235 | printf("Unknown variable: ``%s''\n", token); | |
| 236 | throw_to_monitor(); | |
| 237 | } | |
| 238 | result &= ~7; | |
| 239 | } else { | |
| 240 | if (!string_to_long(token, &result)) { | |
| 241 | printf("Invalid number: ``%s''\n", token); | |
| 242 | throw_to_monitor(); | |
| 243 | } | |
| 244 | result &= ~3; | |
| 62957726 | 245 | } |
| 246 | ||
| 9a8c1c2f | 247 | if (!valid_addr((os_vm_address_t) result)) { |
| 248 | printf("Invalid address: 0x%lx\n", result); | |
| 249 | throw_to_monitor(); | |
| 62957726 | 250 | } |
| 251 | ||
| 9a8c1c2f | 252 | return (char *) result; |
| 62957726 | 253 | } |
| 254 | ||
| 9a8c1c2f | 255 | static boolean |
| 256 | lookup_symbol(char *name, lispobj * result) | |
| 62957726 | 257 | { |
| 258 | int count; | |
| 259 | lispobj *headerptr; | |
| 260 | ||
| 261 | /* Search static space */ | |
| 262 | headerptr = static_space; | |
| 9a8c1c2f | 263 | count = ((lispobj *) SymbolValue(STATIC_SPACE_FREE_POINTER) - static_space); |
| 62957726 | 264 | if (search_for_symbol(name, &headerptr, &count)) { |
| 9a8c1c2f | 265 | *result = (lispobj) headerptr | type_OtherPointer; |
| 266 | return TRUE; | |
| 62957726 | 267 | } |
| 268 | ||
| 269 | /* Search dynamic space */ | |
| 270 | headerptr = current_dynamic_space; | |
| 97c1178e | 271 | #if !defined(ibmrt) && !defined(i386) && !defined(__x86_64) |
| 62957726 | 272 | count = current_dynamic_space_free_pointer - current_dynamic_space; |
| 273 | #else | |
| 9a8c1c2f | 274 | count = (lispobj *) SymbolValue(ALLOCATION_POINTER) - current_dynamic_space; |
| 62957726 | 275 | #endif |
| 276 | if (search_for_symbol(name, &headerptr, &count)) { | |
| 9a8c1c2f | 277 | *result = (lispobj) headerptr | type_OtherPointer; |
| 278 | return TRUE; | |
| 62957726 | 279 | } |
| 280 | ||
| 281 | return FALSE; | |
| 282 | } | |
| 283 | ||
| 284 | static int | |
| 285 | parse_regnum(char *s) | |
| 286 | { | |
| 9a8c1c2f | 287 | if ((s[1] == 'R') || (s[1] == 'r')) { |
| 288 | int regnum; | |
| 289 | ||
| 290 | if (s[2] == '\0') | |
| 291 | return -1; | |
| 292 | ||
| 293 | /* skip the $R part and call atoi on the number */ | |
| 294 | regnum = atoi(s + 2); | |
| 295 | if ((regnum >= 0) && (regnum < NREGS)) | |
| 296 | return regnum; | |
| 297 | else | |
| 298 | return -1; | |
| 299 | } else { | |
| 300 | int i; | |
| 301 | ||
| 302 | for (i = 0; i < NREGS; i++) | |
| 303 | if (strcasecmp(s + 1, lisp_register_names[i]) == 0) | |
| cfe94c2e | 304 | #ifdef i386 |
| 9a8c1c2f | 305 | return i * 2; |
| cfe94c2e | 306 | #else |
| 9a8c1c2f | 307 | return i; |
| cfe94c2e | 308 | #endif |
| 9a8c1c2f | 309 | |
| 310 | return -1; | |
| 311 | } | |
| 62957726 | 312 | } |
| 313 | ||
| 9a8c1c2f | 314 | lispobj |
| b8d0dfaf | 315 | parse_lispobj(char **ptr) |
| 62957726 | 316 | { |
| 317 | char *token = parse_token(ptr); | |
| 318 | long pointer; | |
| 319 | lispobj result; | |
| 320 | ||
| 321 | if (token == NULL) { | |
| 9a8c1c2f | 322 | printf("Expected an object.\n"); |
| 323 | throw_to_monitor(); | |
| 62957726 | 324 | } else if (token[0] == '$') { |
| 325 | if (isalpha(token[1])) { | |
| 9a8c1c2f | 326 | int free; |
| 327 | int regnum; | |
| 328 | os_context_t *context; | |
| 329 | ||
| 330 | free = SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX) >> 2; | |
| 331 | ||
| 332 | if (free == 0) { | |
| 333 | printf | |
| 334 | ("Variable ``%s'' is not valid -- there is no current interrupt context.\n", | |
| 335 | token); | |
| 336 | throw_to_monitor(); | |
| 337 | } | |
| 338 | ||
| 339 | context = lisp_interrupt_contexts[free - 1]; | |
| 340 | ||
| 341 | regnum = parse_regnum(token); | |
| 342 | if (regnum < 0) { | |
| 343 | printf("Bogus register: ``%s''\n", token); | |
| 344 | throw_to_monitor(); | |
| 345 | } | |
| 346 | ||
| 347 | result = SC_REG(context, regnum); | |
| 348 | } else if (!lookup_variable(token + 1, &result)) { | |
| 349 | printf("Unknown variable: ``%s''\n", token); | |
| 350 | throw_to_monitor(); | |
| 351 | } | |
| 62957726 | 352 | } else if (token[0] == '@') { |
| 9a8c1c2f | 353 | if (string_to_long(token + 1, &pointer)) { |
| 354 | pointer &= ~3; | |
| 355 | if (valid_addr((os_vm_address_t) pointer)) | |
| 356 | result = *(lispobj *) pointer; | |
| 357 | else { | |
| 358 | printf("Invalid address: ``%s''\n", token + 1); | |
| 359 | throw_to_monitor(); | |
| 360 | } | |
| 361 | } else { | |
| 362 | printf("Invalid address: ``%s''\n", token + 1); | |
| 363 | throw_to_monitor(); | |
| 364 | } | |
| 365 | } else if (string_to_long(token, (long *) &result)); | |
| 366 | else if (lookup_symbol(token, &result)); | |
| 62957726 | 367 | else { |
| 9a8c1c2f | 368 | printf("Invalid lisp object: ``%s''\n", token); |
| 369 | throw_to_monitor(); | |
| 62957726 | 370 | } |
| 371 | ||
| 372 | return result; | |
| 373 | } |