Add :IMMOBILE-CODE feature.
[sbcl.git] / src / runtime / parse.c
blobe31e015b773935d5a7b58e25f1b6a9a40140154e
1 /* parsing for LDB monitor */
3 /*
4 * This software is part of the SBCL system. See the README file for
5 * more information.
7 * This software is derived from the CMU CL system, which was
8 * written at Carnegie Mellon University and released into the
9 * public domain. The software is in the public domain and is
10 * provided with absolutely no warranty. See the COPYING and CREDITS
11 * files for more information.
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <ctype.h>
18 #include "sbcl.h"
19 #if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
20 #include "pthreads_win32.h"
21 #else
22 #include <signal.h>
23 #endif
24 #include "runtime.h"
26 #if defined(LISP_FEATURE_SB_LDB)
28 #include "globals.h"
29 #include "vars.h"
30 #include "parse.h"
31 #include "os.h"
32 #include "interrupt.h"
33 #include "lispregs.h"
34 #include "monitor.h"
35 #include "validate.h"
36 #include "arch.h"
37 #include "search.h"
38 #include "thread.h"
39 #include "pseudo-atomic.h"
41 #include "genesis/simple-fun.h"
42 #include "genesis/fdefn.h"
43 #include "genesis/symbol.h"
44 #include "genesis/static-symbols.h"
46 static void skip_ws(char **ptr)
48 while (**ptr <= ' ' && **ptr != '\0')
49 (*ptr)++;
52 static boolean string_to_long(char *token, uword_t *value)
54 int base, digit;
55 uword_t num;
56 char *ptr;
58 if (token == 0)
59 return 0;
61 if (token[0] == '0')
62 if (token[1] == 'x') {
63 base = 16;
64 token += 2;
66 else {
67 base = 8;
68 token++;
70 else if (token[0] == '#') {
71 switch (token[1]) {
72 case 'x':
73 case 'X':
74 base = 16;
75 token += 2;
76 break;
77 case 'o':
78 case 'O':
79 base = 8;
80 token += 2;
81 break;
82 default:
83 return 0;
86 else
87 base = 10;
89 num = 0;
90 ptr = token;
91 while (*ptr != '\0') {
92 if (*ptr >= 'a' && *ptr <= 'f')
93 digit = *ptr + 10 - 'a';
94 else if (*ptr >= 'A' && *ptr <= 'F')
95 digit = *ptr + 10 - 'A';
96 else if (*ptr >= '0' && *ptr <= '9')
97 digit = *ptr - '0';
98 else
99 return 0;
100 if (digit < 0 || digit >= base)
101 return 0;
103 ptr++;
104 num = num * base + digit;
107 *value = num;
108 return 1;
111 static boolean lookup_variable(char *name, lispobj *result)
113 struct var *var = lookup_by_name(name);
115 if (var == NULL)
116 return 0;
117 else {
118 *result = var_value(var);
119 return 1;
124 boolean more_p(ptr)
125 char **ptr;
127 skip_ws(ptr);
129 if (**ptr == '\0')
130 return 0;
131 else
132 return 1;
135 char *parse_token(ptr)
136 char **ptr;
138 char *token;
140 skip_ws(ptr);
142 if (**ptr == '\0')
143 return NULL;
145 token = *ptr;
147 while (**ptr > ' ')
148 (*ptr)++;
150 if (**ptr != '\0') {
151 **ptr = '\0';
152 (*ptr)++;
155 return token;
158 uword_t parse_number(ptr)
159 char **ptr;
161 char *token = parse_token(ptr);
162 uword_t result;
164 if (token == NULL) {
165 printf("expected a number\n");
166 throw_to_monitor();
168 else if (string_to_long(token, &result))
169 return result;
170 else {
171 printf("invalid number: ``%s''\n", token);
172 throw_to_monitor();
174 return 0;
177 char *parse_addr(ptr)
178 char **ptr;
180 char *token = parse_token(ptr);
181 lispobj result;
183 if (token == NULL) {
184 printf("expected an address\n");
185 throw_to_monitor();
187 else if (token[0] == '$') {
188 if (!lookup_variable(token+1, &result)) {
189 printf("unknown variable: ``%s''\n", token);
190 throw_to_monitor();
192 result &= ~7;
194 else {
195 uword_t value;
196 if (!string_to_long(token, &value)) {
197 printf("invalid number: ``%s''\n", token);
198 throw_to_monitor();
200 result = (value & ~3);
203 if (!is_valid_lisp_addr((os_vm_address_t)result)) {
204 printf("invalid Lisp-level address: %p\n", (void *)result);
205 throw_to_monitor();
208 return (char *)result;
211 static boolean lookup_symbol(char *name, lispobj *result)
213 int count;
214 lispobj *headerptr;
216 /* Search static space. */
217 headerptr = (lispobj *)STATIC_SPACE_START;
218 count =
219 (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0) -
220 (lispobj *)STATIC_SPACE_START;
221 if (search_for_symbol(name, &headerptr, &count)) {
222 *result = make_lispobj(headerptr,OTHER_POINTER_LOWTAG);
223 return 1;
226 #ifdef LISP_FEATURE_IMMOBILE_SPACE
227 /* Search immobile space. */
228 headerptr = (lispobj *)IMMOBILE_SPACE_START;
229 count = IMMOBILE_FIXEDOBJ_SUBSPACE_SIZE / N_WORD_BYTES;
230 if (search_for_symbol(name, &headerptr, &count)) {
231 *result = make_lispobj(headerptr,OTHER_POINTER_LOWTAG);
232 return 1;
234 #endif
236 /* Search dynamic space. */
237 #if defined(LISP_FEATURE_GENCGC)
238 headerptr = (lispobj *)DYNAMIC_SPACE_START;
239 count = (lispobj *)get_alloc_pointer() - headerptr;
240 #else
241 headerptr = (lispobj *)current_dynamic_space;
242 count = dynamic_space_free_pointer - headerptr;
243 #endif
245 if (search_for_symbol(name, &headerptr, &count)) {
246 *result = make_lispobj(headerptr, OTHER_POINTER_LOWTAG);
247 return 1;
250 return 0;
253 static int
254 parse_regnum(char *s)
256 if ((s[1] == 'R') || (s[1] == 'r')) {
257 int regnum;
259 if (s[2] == '\0')
260 return -1;
262 /* skip the $R part and call atoi on the number */
263 regnum = atoi(s + 2);
264 if ((regnum >= 0) && (regnum < NREGS))
265 return regnum;
266 else
267 return -1;
268 } else {
269 int i;
271 for (i = 0; i < NREGS ; i++)
272 if (strcasecmp(s + 1, lisp_register_names[i]) == 0)
273 #ifdef LISP_FEATURE_X86
274 return i*2;
275 #else
276 return i;
277 #endif
279 return -1;
283 lispobj parse_lispobj(ptr)
284 char **ptr;
286 struct thread *thread=arch_os_get_current_thread();
287 char *token = parse_token(ptr);
288 uword_t pointer;
289 lispobj result;
290 uword_t value;
292 if (token == NULL) {
293 printf("expected an object\n");
294 throw_to_monitor();
295 } else if (token[0] == '$') {
296 if (isalpha(token[1])) {
297 int free_ici;
298 int regnum;
299 os_context_t *context;
301 free_ici = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,thread));
303 if (free_ici == 0) {
304 printf("Variable ``%s'' is not valid -- there is no current interrupt context.\n", token);
305 throw_to_monitor();
308 context = thread->interrupt_contexts[free_ici - 1];
310 regnum = parse_regnum(token);
311 if (regnum < 0) {
312 printf("bogus register: ``%s''\n", token);
313 throw_to_monitor();
316 result = *os_context_register_addr(context, regnum);
317 } else if (!lookup_variable(token+1, &result)) {
318 printf("unknown variable: ``%s''\n", token);
319 throw_to_monitor();
321 } else if (token[0] == '@') {
322 if (string_to_long(token+1, &pointer)) {
323 pointer &= ~3;
324 if (is_valid_lisp_addr((os_vm_address_t)pointer))
325 result = *(lispobj *)pointer;
326 else {
327 printf("invalid Lisp-level address: ``%s''\n", token+1);
328 throw_to_monitor();
331 else {
332 printf("invalid address: ``%s''\n", token+1);
333 throw_to_monitor();
336 else if (string_to_long(token, &value))
337 result = value;
338 else if (lookup_symbol(token, &result))
340 else {
341 printf("invalid Lisp object: ``%s''\n", token);
342 throw_to_monitor();
345 return result;
348 #endif /* defined(LISP_FEATURE_SB_LDB) */