Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
9259 libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/common/ficl/tools.c
+++ new/usr/src/common/ficl/tools.c
1 1 /*
2 2 * t o o l s . c
3 3 * Forth Inspired Command Language - programming tools
4 4 * Author: John Sadler (john_sadler@alum.mit.edu)
5 5 * Created: 20 June 2000
6 6 * $Id: tools.c,v 1.12 2010/08/12 13:57:22 asau Exp $
7 7 */
8 8 /*
9 9 * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
10 10 * All rights reserved.
11 11 *
12 12 * Get the latest Ficl release at http://ficl.sourceforge.net
13 13 *
14 14 * I am interested in hearing from anyone who uses Ficl. If you have
15 15 * a problem, a success story, a defect, an enhancement request, or
16 16 * if you would like to contribute to the Ficl release, please
17 17 * contact me by email at the address above.
18 18 *
19 19 * L I C E N S E and D I S C L A I M E R
20 20 *
21 21 * Redistribution and use in source and binary forms, with or without
22 22 * modification, are permitted provided that the following conditions
23 23 * are met:
24 24 * 1. Redistributions of source code must retain the above copyright
25 25 * notice, this list of conditions and the following disclaimer.
26 26 * 2. Redistributions in binary form must reproduce the above copyright
27 27 * notice, this list of conditions and the following disclaimer in the
28 28 * documentation and/or other materials provided with the distribution.
29 29 *
30 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
31 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
34 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 40 * SUCH DAMAGE.
41 41 */
42 42
43 43 /*
44 44 * NOTES:
45 45 * SEE needs information about the addresses of functions that
46 46 * are the CFAs of colon definitions, constants, variables, DOES>
47 47 * words, and so on. It gets this information from a table and supporting
48 48 * functions in words.c.
49 49 * fiColonParen fiDoDoes createParen fiVariableParen fiUserParen fiConstantParen
50 50 *
51 51 * Step and break debugger for Ficl
52 52 * debug ( xt -- ) Start debugging an xt
53 53 * Set a breakpoint
54 54 * Specify breakpoint default action
55 55 */
56 56
57 57 #include "ficl.h"
58 58
59 59 extern void exit(int);
60 60
61 61 static void ficlPrimitiveStepIn(ficlVm *vm);
62 62 static void ficlPrimitiveStepOver(ficlVm *vm);
63 63 static void ficlPrimitiveStepBreak(ficlVm *vm);
64 64
65 65 void
66 66 ficlCallbackAssert(ficlCallback *callback, int expression,
67 67 char *expressionString, char *filename, int line)
68 68 {
69 69 #if FICL_ROBUST >= 1
70 70 if (!expression) {
71 71 static char buffer[256];
72 72 sprintf(buffer, "ASSERTION FAILED at %s:%d: \"%s\"\n",
73 73 filename, line, expressionString);
74 74 ficlCallbackTextOut(callback, buffer);
75 75 exit(-1);
76 76 }
77 77 #else /* FICL_ROBUST >= 1 */
78 78 FICL_IGNORE(callback);
79 79 FICL_IGNORE(expression);
80 80 FICL_IGNORE(expressionString);
81 81 FICL_IGNORE(filename);
82 82 FICL_IGNORE(line);
83 83 #endif /* FICL_ROBUST >= 1 */
84 84 }
85 85
86 86 /*
87 87 * v m S e t B r e a k
88 88 * Set a breakpoint at the current value of IP by
89 89 * storing that address in a BREAKPOINT record
90 90 */
91 91 static void
92 92 ficlVmSetBreak(ficlVm *vm, ficlBreakpoint *pBP)
93 93 {
94 94 ficlWord *pStep = ficlSystemLookup(vm->callback.system, "step-break");
95 95 FICL_VM_ASSERT(vm, pStep);
96 96
97 97 pBP->address = vm->ip;
98 98 pBP->oldXT = *vm->ip;
99 99 *vm->ip = pStep;
100 100 }
101 101
102 102 /*
103 103 * d e b u g P r o m p t
104 104 */
105 105 static void
106 106 ficlDebugPrompt(ficlVm *vm, int debug)
107 107 {
108 108 if (debug)
109 109 setenv("prompt", "dbg> ", 1);
110 110 else
111 111 setenv("prompt", "${interpret}", 1);
112 112 }
113 113
114 114 #if 0
115 115 static int
116 116 isPrimitive(ficlWord *word)
117 117 {
118 118 ficlWordKind wk = ficlWordClassify(word);
119 119 return ((wk != COLON) && (wk != DOES));
120 120 }
121 121 #endif
122 122
123 123 /*
124 124 * d i c t H a s h S u m m a r y
125 125 * Calculate a figure of merit for the dictionary hash table based
126 126 * on the average search depth for all the words in the dictionary,
127 127 * assuming uniform distribution of target keys. The figure of merit
128 128 * is the ratio of the total search depth for all keys in the table
129 129 * versus a theoretical optimum that would be achieved if the keys
130 130 * were distributed into the table as evenly as possible.
131 131 * The figure would be worse if the hash table used an open
132 132 * addressing scheme (i.e. collisions resolved by searching the
133 133 * table for an empty slot) for a given size table.
134 134 */
135 135 #if FICL_WANT_FLOAT
136 136 void
137 137 ficlPrimitiveHashSummary(ficlVm *vm)
138 138 {
139 139 ficlDictionary *dictionary = ficlVmGetDictionary(vm);
140 140 ficlHash *pFHash;
141 141 ficlWord **hash;
142 142 unsigned size;
143 143 ficlWord *word;
144 144 unsigned i;
145 145 int nMax = 0;
146 146 int nWords = 0;
147 147 int nFilled;
148 148 double avg = 0.0;
149 149 double best;
150 150 int nAvg, nRem, nDepth;
151 151
152 152 FICL_VM_DICTIONARY_CHECK(vm, dictionary, 0);
153 153
154 154 pFHash = dictionary->wordlists[dictionary->wordlistCount - 1];
155 155 hash = pFHash->table;
156 156 size = pFHash->size;
157 157 nFilled = size;
158 158
159 159 for (i = 0; i < size; i++) {
160 160 int n = 0;
161 161 word = hash[i];
162 162
163 163 while (word) {
164 164 ++n;
165 165 ++nWords;
166 166 word = word->link;
167 167 }
168 168
169 169 avg += (double)(n * (n+1)) / 2.0;
170 170
171 171 if (n > nMax)
172 172 nMax = n;
173 173 if (n == 0)
174 174 --nFilled;
175 175 }
176 176
177 177 /* Calc actual avg search depth for this hash */
178 178 avg = avg / nWords;
179 179
180 180 /* Calc best possible performance with this size hash */
181 181 nAvg = nWords / size;
182 182 nRem = nWords % size;
183 183 nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem;
184 184 best = (double)nDepth/nWords;
185 185
186 186 sprintf(vm->pad, "%d bins, %2.0f%% filled, Depth: "
187 187 "Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%\n",
188 188 size, (double)nFilled * 100.0 / size, nMax,
189 189 avg, best, 100.0 * best / avg);
190 190
191 191 ficlVmTextOut(vm, vm->pad);
192 192 }
193 193 #endif
194 194
195 195 /*
196 196 * Here's the outer part of the decompiler. It's
197 197 * just a big nested conditional that checks the
198 198 * CFA of the word to decompile for each kind of
199 199 * known word-builder code, and tries to do
200 200 * something appropriate. If the CFA is not recognized,
201 201 * just indicate that it is a primitive.
202 202 */
203 203 static void
204 204 ficlPrimitiveSeeXT(ficlVm *vm)
205 205 {
206 206 ficlWord *word;
207 207 ficlWordKind kind;
208 208
209 209 word = (ficlWord *)ficlStackPopPointer(vm->dataStack);
210 210 kind = ficlWordClassify(word);
211 211
212 212 switch (kind) {
213 213 case FICL_WORDKIND_COLON:
214 214 sprintf(vm->pad, ": %.*s\n", word->length, word->name);
215 215 ficlVmTextOut(vm, vm->pad);
216 216 ficlDictionarySee(ficlVmGetDictionary(vm), word,
217 217 &(vm->callback));
218 218 break;
219 219 case FICL_WORDKIND_DOES:
220 220 ficlVmTextOut(vm, "does>\n");
221 221 ficlDictionarySee(ficlVmGetDictionary(vm),
222 222 (ficlWord *)word->param->p, &(vm->callback));
223 223 break;
224 224 case FICL_WORDKIND_CREATE:
225 225 ficlVmTextOut(vm, "create\n");
226 226 break;
227 227 case FICL_WORDKIND_VARIABLE:
228 228 sprintf(vm->pad, "variable = %ld (%#lx)\n",
229 229 (long)word->param->i, (long unsigned)word->param->u);
230 230 ficlVmTextOut(vm, vm->pad);
231 231 break;
232 232 #if FICL_WANT_USER
233 233 case FICL_WORDKIND_USER:
234 234 sprintf(vm->pad, "user variable %ld (%#lx)\n",
235 235 (long)word->param->i, (long unsigned)word->param->u);
236 236 ficlVmTextOut(vm, vm->pad);
237 237 break;
238 238 #endif
239 239 case FICL_WORDKIND_CONSTANT:
240 240 sprintf(vm->pad, "constant = %ld (%#lx)\n",
241 241 (long)word->param->i, (long unsigned)word->param->u);
242 242 ficlVmTextOut(vm, vm->pad);
243 243 break;
244 244 case FICL_WORDKIND_2CONSTANT:
245 245 sprintf(vm->pad, "constant = %ld %ld (%#lx %#lx)\n",
246 246 (long)word->param[1].i, (long)word->param->i,
247 247 (long unsigned)word->param[1].u,
248 248 (long unsigned)word->param->u);
249 249 ficlVmTextOut(vm, vm->pad);
250 250 break;
251 251
252 252 default:
253 253 sprintf(vm->pad, "%.*s is a primitive\n", word->length,
254 254 word->name);
255 255 ficlVmTextOut(vm, vm->pad);
256 256 break;
257 257 }
258 258
259 259 if (word->flags & FICL_WORD_IMMEDIATE) {
260 260 ficlVmTextOut(vm, "immediate\n");
261 261 }
262 262
263 263 if (word->flags & FICL_WORD_COMPILE_ONLY) {
264 264 ficlVmTextOut(vm, "compile-only\n");
265 265 }
266 266 }
267 267
268 268 static void
269 269 ficlPrimitiveSee(ficlVm *vm)
270 270 {
271 271 ficlPrimitiveTick(vm);
272 272 ficlPrimitiveSeeXT(vm);
273 273 }
274 274
275 275 /*
276 276 * f i c l D e b u g X T
277 277 * debug ( xt -- )
278 278 * Given an xt of a colon definition or a word defined by DOES>, set the
279 279 * VM up to debug the word: push IP, set the xt as the next thing to execute,
280 280 * set a breakpoint at its first instruction, and run to the breakpoint.
281 281 * Note: the semantics of this word are equivalent to "step in"
282 282 */
283 283 static void
284 284 ficlPrimitiveDebugXT(ficlVm *vm)
285 285 {
286 286 ficlWord *xt = ficlStackPopPointer(vm->dataStack);
287 287 ficlWordKind wk = ficlWordClassify(xt);
288 288
289 289 ficlStackPushPointer(vm->dataStack, xt);
290 290 ficlPrimitiveSeeXT(vm);
291 291
292 292 switch (wk) {
293 293 case FICL_WORDKIND_COLON:
294 294 case FICL_WORDKIND_DOES:
295 295 /*
296 296 * Run the colon code and set a breakpoint at the next
297 297 * instruction
298 298 */
299 299 ficlVmExecuteWord(vm, xt);
300 300 ficlVmSetBreak(vm, &(vm->callback.system->breakpoint));
301 301 break;
302 302 default:
303 303 ficlVmExecuteWord(vm, xt);
304 304 break;
305 305 }
306 306 }
307 307
308 308 /*
309 309 * s t e p I n
310 310 * Ficl
311 311 * Execute the next instruction, stepping into it if it's a colon definition
312 312 * or a does> word. This is the easy kind of step.
313 313 */
314 314 static void
315 315 ficlPrimitiveStepIn(ficlVm *vm)
316 316 {
317 317 /*
318 318 * Do one step of the inner loop
319 319 */
320 320 ficlVmExecuteWord(vm, *vm->ip++);
321 321
322 322 /*
323 323 * Now set a breakpoint at the next instruction
324 324 */
325 325 ficlVmSetBreak(vm, &(vm->callback.system->breakpoint));
326 326 }
327 327
328 328 /*
329 329 * s t e p O v e r
330 330 * Ficl
331 331 * Execute the next instruction atomically. This requires some insight into
332 332 * the memory layout of compiled code. Set a breakpoint at the next instruction
333 333 * in this word, and run until we hit it
334 334 */
335 335 static void
336 336 ficlPrimitiveStepOver(ficlVm *vm)
337 337 {
338 338 ficlWord *word;
339 339 ficlWordKind kind;
340 340 ficlWord *pStep = ficlSystemLookup(vm->callback.system, "step-break");
341 341 FICL_VM_ASSERT(vm, pStep);
342 342
343 343 word = *vm->ip;
344 344 kind = ficlWordClassify(word);
345 345
346 346 switch (kind) {
347 347 case FICL_WORDKIND_COLON:
348 348 case FICL_WORDKIND_DOES:
349 349 /*
350 350 * assume that the next ficlCell holds an instruction
351 351 * set a breakpoint there and return to the inner interpreter
352 352 */
353 353 vm->callback.system->breakpoint.address = vm->ip + 1;
354 354 vm->callback.system->breakpoint.oldXT = vm->ip[1];
355 355 vm->ip[1] = pStep;
356 356 break;
357 357 default:
358 358 ficlPrimitiveStepIn(vm);
359 359 break;
360 360 }
361 361 }
362 362
363 363 /*
364 364 * s t e p - b r e a k
365 365 * Ficl
366 366 * Handles breakpoints for stepped execution.
367 367 * Upon entry, breakpoint contains the address and replaced instruction
368 368 * of the current breakpoint.
369 369 * Clear the breakpoint
370 370 * Get a command from the console.
371 371 * i (step in) - execute the current instruction and set a new breakpoint
372 372 * at the IP
373 373 * o (step over) - execute the current instruction to completion and set
374 374 * a new breakpoint at the IP
375 375 * g (go) - execute the current instruction and exit
376 376 * q (quit) - abort current word
377 377 * b (toggle breakpoint)
378 378 */
379 379
380 380 extern char *ficlDictionaryInstructionNames[];
381 381
382 382 static void
383 383 ficlPrimitiveStepBreak(ficlVm *vm)
384 384 {
385 385 ficlString command;
386 386 ficlWord *word;
387 387 ficlWord *pOnStep;
388 388 int debug = 1;
389 389
390 390 if (!vm->restart) {
391 391 FICL_VM_ASSERT(vm, vm->callback.system->breakpoint.address);
392 392 FICL_VM_ASSERT(vm, vm->callback.system->breakpoint.oldXT);
393 393
394 394 /*
395 395 * Clear the breakpoint that caused me to run
396 396 * Restore the original instruction at the breakpoint,
397 397 * and restore the IP
398 398 */
399 399 vm->ip = (ficlIp)(vm->callback.system->breakpoint.address);
400 400 *vm->ip = vm->callback.system->breakpoint.oldXT;
401 401
402 402 /*
403 403 * If there's an onStep, do it
404 404 */
405 405 pOnStep = ficlSystemLookup(vm->callback.system, "on-step");
406 406 if (pOnStep)
407 407 ficlVmExecuteXT(vm, pOnStep);
408 408
409 409 /*
410 410 * Print the name of the next instruction
411 411 */
412 412 word = vm->callback.system->breakpoint.oldXT;
413 413
414 414 if ((((ficlInstruction)word) > ficlInstructionInvalid) &&
415 415 (((ficlInstruction)word) < ficlInstructionLast))
416 416 sprintf(vm->pad, "next: %s (instruction %ld)\n",
417 417 ficlDictionaryInstructionNames[(long)word],
418 418 (long)word);
419 419 else {
420 420 sprintf(vm->pad, "next: %s\n", word->name);
421 421 if (strcmp(word->name, "interpret") == 0)
422 422 debug = 0;
423 423 }
424 424
425 425 ficlVmTextOut(vm, vm->pad);
426 426 ficlDebugPrompt(vm, debug);
427 427 } else {
428 428 vm->restart = 0;
429 429 }
430 430
431 431 command = ficlVmGetWord(vm);
432 432
433 433 switch (command.text[0]) {
434 434 case 'i':
435 435 ficlPrimitiveStepIn(vm);
436 436 break;
437 437
438 438 case 'o':
439 439 ficlPrimitiveStepOver(vm);
440 440 break;
441 441
442 442 case 'g':
443 443 break;
444 444
445 445 case 'l': {
446 446 ficlWord *xt;
447 447 xt = ficlDictionaryFindEnclosingWord(
448 448 ficlVmGetDictionary(vm), (ficlCell *)(vm->ip));
449 449 if (xt) {
450 450 ficlStackPushPointer(vm->dataStack, xt);
451 451 ficlPrimitiveSeeXT(vm);
452 452 } else {
453 453 ficlVmTextOut(vm, "sorry - can't do that\n");
454 454 }
455 455 ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
456 456 break;
457 457 }
458 458
459 459 case 'q':
460 460 ficlDebugPrompt(vm, 0);
461 461 ficlVmThrow(vm, FICL_VM_STATUS_ABORT);
462 462 break;
463 463 case 'x': {
464 464 /*
465 465 * Take whatever's left in the TIB and feed it to a
466 466 * subordinate ficlVmExecuteString
467 467 */
468 468 int returnValue;
469 469 ficlString s;
470 470 ficlWord *oldRunningWord = vm->runningWord;
471 471
472 472 FICL_STRING_SET_POINTER(s,
473 473 vm->tib.text + vm->tib.index);
474 474 FICL_STRING_SET_LENGTH(s,
475 475 vm->tib.end - FICL_STRING_GET_POINTER(s));
476 476
477 477 returnValue = ficlVmExecuteString(vm, s);
478 478
479 479 if (returnValue == FICL_VM_STATUS_OUT_OF_TEXT) {
480 480 returnValue = FICL_VM_STATUS_RESTART;
481 481 vm->runningWord = oldRunningWord;
482 482 ficlVmTextOut(vm, "\n");
483 483 }
484 484 if (returnValue == FICL_VM_STATUS_ERROR_EXIT)
485 485 ficlDebugPrompt(vm, 0);
486 486
487 487 ficlVmThrow(vm, returnValue);
488 488 break;
489 489 }
490 490
491 491 default:
492 492 ficlVmTextOut(vm,
493 493 "i -- step In\n"
494 494 "o -- step Over\n"
495 495 "g -- Go (execute to completion)\n"
496 496 "l -- List source code\n"
497 497 "q -- Quit (stop debugging and abort)\n"
498 498 "x -- eXecute the rest of the line "
499 499 "as Ficl words\n");
500 500 ficlDebugPrompt(vm, 1);
501 501 ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
502 502 break;
503 503 }
504 504
505 505 ficlDebugPrompt(vm, 0);
506 506 }
507 507
508 508 /*
509 509 * b y e
510 510 * TOOLS
511 511 * Signal the system to shut down - this causes ficlExec to return
512 512 * VM_USEREXIT. The rest is up to you.
513 513 */
514 514 static void
515 515 ficlPrimitiveBye(ficlVm *vm)
516 516 {
517 517 ficlVmThrow(vm, FICL_VM_STATUS_USER_EXIT);
518 518 }
519 519
520 520 /*
521 521 * d i s p l a y S t a c k
522 522 * TOOLS
523 523 * Display the parameter stack (code for ".s")
524 524 */
525 525
526 526 struct stackContext
527 527 {
528 528 ficlVm *vm;
529 529 ficlDictionary *dictionary;
530 530 int count;
531 531 };
532 532
533 533 static ficlInteger
534 534 ficlStackDisplayCallback(void *c, ficlCell *cell)
535 535 {
536 536 struct stackContext *context = (struct stackContext *)c;
537 537 char buffer[80];
538 538
539 539 #ifdef _LP64
540 540 snprintf(buffer, sizeof (buffer), "[0x%016lx %3d]: %20ld (0x%016lx)\n",
541 541 (unsigned long)cell, context->count++, (long)cell->i,
542 542 (unsigned long)cell->u);
543 543 #else
544 544 snprintf(buffer, sizeof (buffer), "[0x%08x %3d]: %12d (0x%08x)\n",
545 545 (unsigned)cell, context->count++, cell->i, cell->u);
546 546 #endif
547 547
548 548 ficlVmTextOut(context->vm, buffer);
549 549 return (FICL_TRUE);
550 550 }
551 551
552 552 void
553 553 ficlStackDisplay(ficlStack *stack, ficlStackWalkFunction callback,
554 554 void *context)
555 555 {
556 556 ficlVm *vm = stack->vm;
557 557 char buffer[128];
558 558 struct stackContext myContext;
559 559
560 560 FICL_STACK_CHECK(stack, 0, 0);
561 561
562 562 #ifdef _LP64
563 563 sprintf(buffer, "[%s stack has %d entries, top at 0x%016lx]\n",
564 564 stack->name, ficlStackDepth(stack), (unsigned long)stack->top);
565 565 #else
566 566 sprintf(buffer, "[%s stack has %d entries, top at 0x%08x]\n",
567 567 stack->name, ficlStackDepth(stack), (unsigned)stack->top);
568 568 #endif
569 569 ficlVmTextOut(vm, buffer);
570 570
571 571 if (callback == NULL) {
572 572 myContext.vm = vm;
573 573 myContext.count = 0;
574 574 context = &myContext;
575 575 callback = ficlStackDisplayCallback;
576 576 }
577 577 ficlStackWalk(stack, callback, context, FICL_FALSE);
578 578
579 579 #ifdef _LP64
580 580 sprintf(buffer, "[%s stack base at 0x%016lx]\n", stack->name,
581 581 (unsigned long)stack->base);
582 582 #else
583 583 sprintf(buffer, "[%s stack base at 0x%08x]\n", stack->name,
584 584 (unsigned)stack->base);
585 585 #endif
586 586 ficlVmTextOut(vm, buffer);
587 587 }
588 588
589 589 void
590 590 ficlVmDisplayDataStack(ficlVm *vm)
591 591 {
592 592 ficlStackDisplay(vm->dataStack, NULL, NULL);
593 593 }
594 594
595 595 static ficlInteger
596 596 ficlStackDisplaySimpleCallback(void *c, ficlCell *cell)
597 597 {
598 598 struct stackContext *context = (struct stackContext *)c;
599 599 char buffer[32];
600 600
601 601 sprintf(buffer, "%s%ld", context->count ? " " : "", (long)cell->i);
602 602 context->count++;
603 603 ficlVmTextOut(context->vm, buffer);
604 604 return (FICL_TRUE);
605 605 }
606 606
607 607 void
608 608 ficlVmDisplayDataStackSimple(ficlVm *vm)
609 609 {
610 610 ficlStack *stack = vm->dataStack;
611 611 char buffer[32];
612 612 struct stackContext context;
613 613
614 614 FICL_STACK_CHECK(stack, 0, 0);
615 615
616 616 sprintf(buffer, "[%d] ", ficlStackDepth(stack));
617 617 ficlVmTextOut(vm, buffer);
618 618
619 619 context.vm = vm;
620 620 context.count = 0;
621 621 ficlStackWalk(stack, ficlStackDisplaySimpleCallback, &context,
622 622 FICL_TRUE);
623 623 }
624 624
625 625 static ficlInteger
626 626 ficlReturnStackDisplayCallback(void *c, ficlCell *cell)
627 627 {
628 628 struct stackContext *context = (struct stackContext *)c;
629 629 char buffer[128];
630 630
631 631 #ifdef _LP64
632 632 sprintf(buffer, "[0x%016lx %3d] %20ld (0x%016lx)", (unsigned long)cell,
633 633 context->count++, cell->i, cell->u);
634 634 #else
635 635 sprintf(buffer, "[0x%08x %3d] %12d (0x%08x)", (unsigned)cell,
636 636 context->count++, cell->i, cell->u);
637 637 #endif
638 638
639 639 /*
640 640 * Attempt to find the word that contains the return
641 641 * stack address (as if it is part of a colon definition).
642 642 * If this works, also print the name of the word.
643 643 */
644 644 if (ficlDictionaryIncludes(context->dictionary, cell->p)) {
645 645 ficlWord *word;
646 646 word = ficlDictionaryFindEnclosingWord(context->dictionary,
647 647 cell->p);
648 648 if (word) {
649 649 int offset = (ficlCell *)cell->p - &word->param[0];
650 650 sprintf(buffer + strlen(buffer), ", %s + %d ",
651 651 word->name, offset);
652 652 }
653 653 }
654 654 strcat(buffer, "\n");
655 655 ficlVmTextOut(context->vm, buffer);
656 656 return (FICL_TRUE);
657 657 }
658 658
659 659 void
660 660 ficlVmDisplayReturnStack(ficlVm *vm)
661 661 {
662 662 struct stackContext context;
663 663 context.vm = vm;
664 664 context.count = 0;
665 665 context.dictionary = ficlVmGetDictionary(vm);
666 666 ficlStackDisplay(vm->returnStack, ficlReturnStackDisplayCallback,
667 667 &context);
668 668 }
669 669
670 670 /*
671 671 * f o r g e t - w i d
672 672 */
673 673 static void
674 674 ficlPrimitiveForgetWid(ficlVm *vm)
675 675 {
676 676 ficlDictionary *dictionary = ficlVmGetDictionary(vm);
677 677 ficlHash *hash;
678 678
679 679 hash = (ficlHash *)ficlStackPopPointer(vm->dataStack);
680 680 ficlHashForget(hash, dictionary->here);
681 681 }
682 682
683 683 /*
684 684 * f o r g e t
685 685 * TOOLS EXT ( "<spaces>name" -- )
686 686 * Skip leading space delimiters. Parse name delimited by a space.
687 687 * Find name, then delete name from the dictionary along with all
688 688 * words added to the dictionary after name. An ambiguous
689 689 * condition exists if name cannot be found.
690 690 *
691 691 * If the Search-Order word set is present, FORGET searches the
692 692 * compilation word list. An ambiguous condition exists if the
693 693 * compilation word list is deleted.
694 694 */
695 695 static void
696 696 ficlPrimitiveForget(ficlVm *vm)
697 697 {
698 698 void *where;
699 699 ficlDictionary *dictionary = ficlVmGetDictionary(vm);
700 700 ficlHash *hash = dictionary->compilationWordlist;
701 701
702 702 ficlPrimitiveTick(vm);
703 703 where = ((ficlWord *)ficlStackPopPointer(vm->dataStack))->name;
704 704 ficlHashForget(hash, where);
705 705 dictionary->here = FICL_POINTER_TO_CELL(where);
706 706 }
707 707
708 708 /*
709 709 * w o r d s
710 710 */
711 711 #define nCOLWIDTH 8
712 712
713 713 static void
714 714 ficlPrimitiveWords(ficlVm *vm)
715 715 {
716 716 ficlDictionary *dictionary = ficlVmGetDictionary(vm);
|
↓ open down ↓ |
716 lines elided |
↑ open up ↑ |
717 717 ficlHash *hash = dictionary->wordlists[dictionary->wordlistCount - 1];
718 718 ficlWord *wp;
719 719 int nChars = 0;
720 720 int len;
721 721 unsigned i;
722 722 int nWords = 0;
723 723 char *cp;
724 724 char *pPad;
725 725 int columns;
726 726
727 - cp = getenv("COLUMNS");
727 + cp = getenv("screen-#cols");
728 728 /*
729 729 * using strtol for now. TODO: refactor number conversion from
730 730 * ficlPrimitiveToNumber() and use it instead.
731 731 */
732 732 if (cp == NULL)
733 733 columns = 80;
734 734 else
735 735 columns = strtol(cp, NULL, 0);
736 736
737 737 /*
738 738 * the pad is fixed size area, it's better to allocate
739 739 * dedicated buffer space to deal with custom terminal sizes.
740 740 */
741 741 pPad = malloc(columns + 1);
742 742 if (pPad == NULL)
743 743 ficlVmThrowError(vm, "Error: out of memory");
744 744
745 745 pager_open();
746 746 for (i = 0; i < hash->size; i++) {
747 747 for (wp = hash->table[i]; wp != NULL; wp = wp->link, nWords++) {
748 748 if (wp->length == 0) /* ignore :noname defs */
749 749 continue;
750 750
751 751 /* prevent line wrap due to long words */
752 752 if (nChars + wp->length >= columns) {
753 753 pPad[nChars++] = '\n';
754 754 pPad[nChars] = '\0';
755 755 nChars = 0;
756 756 if (pager_output(pPad))
757 757 goto pager_done;
758 758 }
759 759
760 760 cp = wp->name;
761 761 nChars += sprintf(pPad + nChars, "%s", cp);
762 762
763 763 if (nChars > columns - 10) {
764 764 pPad[nChars++] = '\n';
765 765 pPad[nChars] = '\0';
766 766 nChars = 0;
767 767 if (pager_output(pPad))
768 768 goto pager_done;
769 769 } else {
770 770 len = nCOLWIDTH - nChars % nCOLWIDTH;
771 771 while (len-- > 0)
772 772 pPad[nChars++] = ' ';
773 773 }
774 774
775 775 if (nChars > columns - 10) {
776 776 pPad[nChars++] = '\n';
777 777 pPad[nChars] = '\0';
778 778 nChars = 0;
779 779 if (pager_output(pPad))
780 780 goto pager_done;
781 781 }
782 782 }
783 783 }
784 784
785 785 if (nChars > 0) {
786 786 pPad[nChars++] = '\n';
787 787 pPad[nChars] = '\0';
788 788 nChars = 0;
789 789 ficlVmTextOut(vm, pPad);
790 790 }
791 791
792 792 sprintf(pPad, "Dictionary: %d words, %ld cells used of %u total\n",
793 793 nWords, (long)(dictionary->here - dictionary->base),
794 794 dictionary->size);
795 795 pager_output(pPad);
796 796
797 797 pager_done:
798 798 free(pPad);
799 799 pager_close();
800 800 }
801 801
802 802 /*
803 803 * l i s t E n v
804 804 * Print symbols defined in the environment
805 805 */
806 806 static void
807 807 ficlPrimitiveListEnv(ficlVm *vm)
808 808 {
809 809 ficlDictionary *dictionary = vm->callback.system->environment;
810 810 ficlHash *hash = dictionary->forthWordlist;
811 811 ficlWord *word;
812 812 unsigned i;
813 813 int counter = 0;
814 814
815 815 pager_open();
816 816 for (i = 0; i < hash->size; i++) {
817 817 for (word = hash->table[i]; word != NULL;
818 818 word = word->link, counter++) {
819 819 sprintf(vm->pad, "%s\n", word->name);
820 820 if (pager_output(vm->pad))
821 821 goto pager_done;
822 822 }
823 823 }
824 824
825 825 sprintf(vm->pad, "Environment: %d words, %ld cells used of %u total\n",
826 826 counter, (long)(dictionary->here - dictionary->base),
827 827 dictionary->size);
828 828 pager_output(vm->pad);
829 829
830 830 pager_done:
831 831 pager_close();
832 832 }
833 833
834 834 /*
835 835 * This word lists the parse steps in order
836 836 */
837 837 void
838 838 ficlPrimitiveParseStepList(ficlVm *vm)
839 839 {
840 840 int i;
841 841 ficlSystem *system = vm->callback.system;
842 842 FICL_VM_ASSERT(vm, system);
843 843
844 844 ficlVmTextOut(vm, "Parse steps:\n");
845 845 ficlVmTextOut(vm, "lookup\n");
846 846
847 847 for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) {
848 848 if (system->parseList[i] != NULL) {
849 849 ficlVmTextOut(vm, system->parseList[i]->name);
850 850 ficlVmTextOut(vm, "\n");
851 851 } else
852 852 break;
853 853 }
854 854 }
855 855
856 856 /*
857 857 * e n v C o n s t a n t
858 858 * Ficl interface to ficlSystemSetEnvironment and ficlSetEnvD - allow Ficl
859 859 * code to set environment constants...
860 860 */
861 861 static void
862 862 ficlPrimitiveEnvConstant(ficlVm *vm)
863 863 {
864 864 unsigned value;
865 865 FICL_STACK_CHECK(vm->dataStack, 1, 0);
866 866
867 867 ficlVmGetWordToPad(vm);
868 868 value = ficlStackPopUnsigned(vm->dataStack);
869 869 ficlDictionarySetConstant(ficlSystemGetEnvironment(vm->callback.system),
870 870 vm->pad, (ficlUnsigned)value);
871 871 }
872 872
873 873 static void
874 874 ficlPrimitiveEnv2Constant(ficlVm *vm)
875 875 {
876 876 ficl2Integer value;
877 877
878 878 FICL_STACK_CHECK(vm->dataStack, 2, 0);
879 879
880 880 ficlVmGetWordToPad(vm);
881 881 value = ficlStackPop2Integer(vm->dataStack);
882 882 ficlDictionarySet2Constant(
883 883 ficlSystemGetEnvironment(vm->callback.system), vm->pad, value);
884 884 }
885 885
886 886
887 887 /*
888 888 * f i c l C o m p i l e T o o l s
889 889 * Builds wordset for debugger and TOOLS optional word set
890 890 */
891 891 void
892 892 ficlSystemCompileTools(ficlSystem *system)
893 893 {
894 894 ficlDictionary *dictionary = ficlSystemGetDictionary(system);
895 895 ficlDictionary *environment = ficlSystemGetEnvironment(system);
896 896
897 897 FICL_SYSTEM_ASSERT(system, dictionary);
898 898 FICL_SYSTEM_ASSERT(system, environment);
899 899
900 900
901 901 /*
902 902 * TOOLS and TOOLS EXT
903 903 */
904 904 ficlDictionarySetPrimitive(dictionary, ".s", ficlVmDisplayDataStack,
905 905 FICL_WORD_DEFAULT);
906 906 ficlDictionarySetPrimitive(dictionary, ".s-simple",
907 907 ficlVmDisplayDataStackSimple, FICL_WORD_DEFAULT);
908 908 ficlDictionarySetPrimitive(dictionary, "bye", ficlPrimitiveBye,
909 909 FICL_WORD_DEFAULT);
910 910 ficlDictionarySetPrimitive(dictionary, "forget", ficlPrimitiveForget,
911 911 FICL_WORD_DEFAULT);
912 912 ficlDictionarySetPrimitive(dictionary, "see", ficlPrimitiveSee,
913 913 FICL_WORD_DEFAULT);
914 914 ficlDictionarySetPrimitive(dictionary, "words", ficlPrimitiveWords,
915 915 FICL_WORD_DEFAULT);
916 916
917 917 /*
918 918 * Set TOOLS environment query values
919 919 */
920 920 ficlDictionarySetConstant(environment, "tools", FICL_TRUE);
921 921 ficlDictionarySetConstant(environment, "tools-ext", FICL_FALSE);
922 922
923 923 /*
924 924 * Ficl extras
925 925 */
926 926 ficlDictionarySetPrimitive(dictionary, "r.s", ficlVmDisplayReturnStack,
927 927 FICL_WORD_DEFAULT);
928 928 ficlDictionarySetPrimitive(dictionary, ".env", ficlPrimitiveListEnv,
929 929 FICL_WORD_DEFAULT);
930 930 ficlDictionarySetPrimitive(dictionary, "env-constant",
931 931 ficlPrimitiveEnvConstant, FICL_WORD_DEFAULT);
932 932 ficlDictionarySetPrimitive(dictionary, "env-2constant",
933 933 ficlPrimitiveEnv2Constant, FICL_WORD_DEFAULT);
934 934 ficlDictionarySetPrimitive(dictionary, "debug-xt", ficlPrimitiveDebugXT,
935 935 FICL_WORD_DEFAULT);
936 936 ficlDictionarySetPrimitive(dictionary, "parse-order",
937 937 ficlPrimitiveParseStepList, FICL_WORD_DEFAULT);
938 938 ficlDictionarySetPrimitive(dictionary, "step-break",
939 939 ficlPrimitiveStepBreak, FICL_WORD_DEFAULT);
940 940 ficlDictionarySetPrimitive(dictionary, "forget-wid",
941 941 ficlPrimitiveForgetWid, FICL_WORD_DEFAULT);
942 942 ficlDictionarySetPrimitive(dictionary, "see-xt", ficlPrimitiveSeeXT,
943 943 FICL_WORD_DEFAULT);
944 944
945 945 #if FICL_WANT_FLOAT
946 946 ficlDictionarySetPrimitive(dictionary, ".hash",
947 947 ficlPrimitiveHashSummary, FICL_WORD_DEFAULT);
948 948 #endif
949 949 }
|
↓ open down ↓ |
212 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX