1 /* pMARS -- a portable Memory Array Redcode Simulator
2 * Copyright (C) 1993-1996 Albert Ma, Na'ndor Sieben, Stefan Strack and Mintardjo Wangsawidjaja
3 * Copyright (C) 2000 Ilmari Karonen
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * cdb.c: debugger
22 * $Id: cdb.c,v 1.3 2000/12/25 00:49:07 iltzu Exp $
23 *
24 * cdb - line-oriented core debugger by Stefan Strack
25 */
26
27 #include <ctype.h>
28 #include <string.h>
29 #include "global.h"
30 #include "sim.h"
31 #if defined(DOS16)
32 #include <conio.h>
33 #endif
34 #if defined(DJGPP) && defined(DOSTXTGRAPHX)
35 #include <pc.h>
36 #endif
37
38 #ifndef SERVER
39
40 #define VERBLEN 3
41 #define SKIP_SPACE(s) while(isspace(*s)) ++s
42 #if defined(XWINGRAPHX) /* need this string externally */
43 char *CDB_PROMPT = "(cdb) ";
44 #else
45 #define CDB_PROMPT "(cdb) "
46 #endif
47 #define CMDSEP '~' /* chain command separator */
48 #define CMDREP '!' /* chain command repeator */
49 #define MAXSTR 255 /* 80 */ /* general buffer length */
50 #define MAXCMDSTR 500 /* max. chars in inputStr, lastCmdStr */
51 #define MAXMACROS 200 /* maximum number of macros */
52 #define MAXLOOPNESTING 12 /* max. nesting depth of cdb command loops
53 * !!~..~!n */
54 #define TEXTLINES 23 /* number of lines to list before pausing */
55 #define MAXCMD 80
56 #define MAXARG 80
57 #define RANGE_T 0
58 #define TEXT_T 1
59 #define FORCE 1 /* force STDOUT output */
60 #define COND 0 /* allow '@' supression */
61 #define CORE 0 /* Core list mode */
62 #define QUEUE 1 /* Queue list mode */
63 #define WARRIOR 2 /* Warrior list mode */
64 #define PSP 3 /* P-space list mode */
65 #define FOLD(n) ((ADDR_T) (((n) % (long) targetSize) + targetSize) % targetSize)
66 #define TERMINAL(s) (! *(s))
67 #ifndef MIN
68 #define MIN(a,b) ((a) < (b) ? (a) : (b))
69 #endif
70 #define NOEOL(s) do {\
71 register char *ch=(s);\
72 while (*ch && (*ch != '\n') && (*ch != '\r')) ++ch;\
73 *ch=0; } while(0)
74 #define targetSelect(index) (targetID == CORE || targetID == PSP ?\
75 index : (targetID == QUEUE ?\
76 queue(index) : (W-warrior==index ? progCnt : *warrior[index].taskHead)))
77 #ifdef NEW_STYLE
78 #define toupper_(x) (toupper(x))
79 #else
80 #define toupper_(x) (isalpha(x) && islower(x) ? toupper(x) : (x))
81 #endif
82
83 /* hash value constants */
84 #define NULL_H 0
85 #define ON_H 419
86 #define OF_H 411
87 #define ARE_H 1220
88 #define CAL_H 2226
89 #define CA_H 2214
90 #define CLS_H 2530
91 #define CLE_H 2516
92 #define CL_H 2511
93 #define CLO_H 2526
94 #define CON_H 2606
95 #define CO_H 2592
96 #define C_H 2187
97 #define DIS_H 3178
98 #define DI_H 3159
99 #define D_H 2916
100 #define ECH_H 3734
101 #define EC_H 3726
102 #define EDI_H 3762
103 #define ED_H 3753
104 #define E_H 3645
105 #define EXE_H 4298
106 #define EX_H 4293
107 #define FIL_H 4629
108 #define FI_H 4617
109 #define F_H 4374
110 #define GO_H 5508
111 #define G_H 5103
112 #define HAS_H 5878
113 #define HEL_H 5979
114 #define HE_H 5967
115 #define H_H 5832
116 #define IF_H 6723
117 #define LIS_H 9010
118 #define LI_H 8991
119 #define L_H 8748
120 #define LSE_H 9266
121 #define LS_H 9261
122 #define MOV_H 9904
123 #define MO_H 9882
124 #define MAC_H 9507
125 #define MA_H 9504
126 #define M_H 9477
127 #define PRO_H 12165
128 #define PR_H 12150
129 #define P_H 11664
130 #define PQU_H 12144
131 #define PQ_H 12123
132 #define PSP_H 12193
133 #define PS_H 12177
134 #define QUI_H 12969
135 #define QU_H 12960
136 #define Q_H 12393
137 #define REG_H 13264
138 #define RE_H 13257
139 #define R_H 13122
140 #define REM_H 13270
141 #define RES_H 13276
142 #define SEA_H 13987
143 #define SE_H 13986
144 #define SHE_H 14072
145 #define SH_H 14067
146 #define STE_H 14396
147 #define ST_H 14391
148 #define S_H 13851
149 #define SKI_H 14157
150 #define SK_H 14148
151 #define SWI_H 14481
152 #define SW_H 14472
153 #define THR_H 14814
154 #define TH_H 14796
155 #define TRA_H 15067
156 #define TR_H 15066
157 #define T_H 14580
158 #define UNT_H 15707
159 #define UN_H 15687
160 #define U_H 15309
161 #define WRI_H 17262
162 #define WR_H 17253
163 #define W_H 16767
164 #define WQU_H 17247
165 #define WQ_H 17226
166 #define XEC_H 17634
167 #define XE_H 17631
168 #define X_H 17496
169
170 /*
171 * prototypes
172 */
173 #ifdef NEW_STYLE
174 int cdb(char *msg);
175 char *get_cmd(char *prompt);
176 int
177 parse_cmd(char *cmd, char *verb, long *start,
178 long *stop, char *arg);
179 int subst_eval(char *expr, long *result);
180 void substitute(char *in, char *repl, char *with, char *out);
181 void help(void);
182 void print_core(ADDR_T start, ADDR_T stop);
183 void set_trace(ADDR_T start, ADDR_T stop);
184 void unset_trace(ADDR_T start, ADDR_T stop);
185 void print_registers(void);
186 void edit_core(ADDR_T start, ADDR_T stop);
187 void fill_core(ADDR_T start, ADDR_T stop);
188 unsigned int hash_str(char *s, int len);
189 void cdb_fputs(char *s, int out);
190 int wildsearch(char *pattern, char *target);
191 void load_macros(char *fileName);
192 char *match_macro(char *macro, char *definition);
193 void print_macros(void);
194 void exec_macro(char *macro);
195 void bad_arg(char *argStr);
196 ADDR_T queue(int index);
197 char *queueview(ADDR_T index, char *buf);
198 char *warriorview(ADDR_T index, char *buf);
199 char *pspaceview(ADDR_T index, char *buf);
200 static char *(*targetview) (ADDR_T loc, char *buf) = locview;
201 #if defined(DOSALLGRAPHX)
202 extern void display_init(void);
203 #endif
204 #ifdef DOSGRXGRAPHX
205 extern char *grgets(char *s, int maxstr);
206 extern void grputs(char *s);
207 extern void bgi_display_close(int wait);
208 extern void write_menu(void);
209 extern void open_graphics(void);
210 extern void grclear(void);
211 extern void bgi_clear_arena(void);
212 extern void grupdate(int curPanel);
213 #endif
214 #ifdef DOSTXTGRAPHX
215 extern void SetCursor(int x, int y);
216 extern void switch_page(int page);
217 extern void aputs5(char *str, int attr);
218 extern char *agets5(char *str, int maxchar, int attr);
219 extern void clear_page5(void);
220 extern void text_display_clear(void);
221 extern void text_panel_update(int curPanel);
222 #endif
223 #ifdef CURSESGRAPHX
224 extern void init_curses(void);
225 extern void end_curses(void);
226 extern void winupdate(void);
227 #endif
228 #ifdef MACGRAPHX
229 extern void macputs(char *str);
230 extern void macgets(char *str, int maxchar);
231 extern void mac_display_close(void);
232 extern void mac_clear_screen(void);
233 extern int mac_text_lines(void);
234 #endif
235 #ifdef LINUXGRAPHX
236 /* all the prototypes have already been declared in global.h */
237 #endif
238 #ifdef DOS16
239 extern int parse(char *expr, mem_struct far * c, ADDR_T loc);
240 #else
241 extern int parse(char *expr, mem_struct * c, ADDR_T loc);
242 #endif
243
244 #if defined(DJGPP)
245 extern void sighandler(int dummy);
246 #if defined(DOSTXTGRAPHX) && !defined(CURSESGRAPHX)
247 #if defined(CONIOGRAPHX)
248 extern void CacheScreenUpdate(short *buf);
249 #define SCREENUPDATE CacheScreenUpdate
250 #else
251 #define SCREENUPDATE ScreenUpdate
252 #endif /* CONIOGRAPHX */
253 #endif /* DOSTXTGRAPHX */
254 #endif /* DJGPP */
255
256 #else
257 int cdb();
258 char *get_cmd();
259 int parse_cmd();
260 int subst_eval();
261 void substitute();
262 void help();
263 void print_core();
264 void set_trace();
265 void unset_trace();
266 void print_registers();
267 void edit_core();
268 void fill_core();
269 unsigned int hash_str();
270 void cdb_fputs();
271 int wildsearch();
272 void load_macros();
273 char *match_macro();
274 void print_macros();
275 void exec_macro();
276 void bad_arg();
277 ADDR_T queue();
278 char *pspaceview();
279 char *queueview();
280 char *warriorview();
281 static char *(*targetview) () = locview;
282 char *strstr();
283 extern int parse();
284 #ifdef CURSESGRAPHX
285 extern void init_curses();
286 extern void end_curses();
287 extern void winupdate();
288 extern char *agets5();
289 #endif
290 #endif
291
292 /* strings */
293 extern char *pagePrompt, *exitingCdbToFinishSimulation, *usageDisplay, *usageExecute,
294 *usageMoveable, *pressAnyKeyToContinue, *usageSkip, *usageWrite,
295 *closingLogfile, *cannotOpenLogfile, *openingLogfile, *unknownCommand,
296 *macroStringExpansionTooLong, *EOFreadingCommandInput, *maximumLoopNestingExceeded,
297 *badRepeatCountExpression, *writeErrorDiskFull, *badArgument, *helpText[],
298 *roundOfCycle, *currentlyExecutingWarrior, *processesActive, *otherWarrior,
299 *warriorAtAddressHasActiveProcesses, *pluralEndingOfProcess, *ofWarriorsAreAlive,
300 *fillWith, *dotByItselfEndsKeyboardInput, *cannotOpenMacroFile,
301 *maximumNumberOfMacrosExceeded, *outOfMacroMemory, *unknownMacro,
302 *badExprErr, *divZeroErr, *overflowErr;
303
304 /* global variables */
305 static FILE *logfile = 0;
306 ADDR_T curAddr;
307 static long skipCounter = 0;
308 unsigned char commaSep; /* parse_cmd flag indicating 2 argument
309 * command, also used by CALC_H */
310 static int silent = 0;
311 static ADDR_T targetSize;
312 static int targetID = CORE;
313 #if defined(DJGPP) && !defined(CURSESGRAPHX) && defined(DOSTXTGRAPHX)
314 extern short *Screen[];
315 #endif
316 #if defined(DOSTXTGRAPHX)
317 extern int screenY;
318 #endif
319
320 #ifdef CYCLE_CHECK
321 static char *nextMacro = NULL, *macroTab[MAXMACROS], macroCycle[MAXMACROS];
322 #else
323 static char *nextMacro = NULL, *macroTab[MAXMACROS];
324 #endif
325
326 warrior_struct *W2, *QW;
327 char outs[MAXSTR + 1], buffer1[MAXSTR + 1], buffer2[MAXSTR + 1];
328 char *xInpP; /* pointer to inputStr[], used by
329 * input-requiring functions called by cdb() */
330 #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) || defined(LINUXGRAPHX) \
331 || defined(XWINGRAPHX)
332 int printAttr;
333 int curPanel = 0;
334 ADDR_T curAddr2;
335 #endif
336
337 #if !defined(NEW_STYLE) && !defined(VMS)
338 char *
strstr(cs,ct)339 strstr(cs, ct)
340 char *cs, *ct;
341 {
342 char *p, *q, *r;
343
344 for (p = cs; *p != 0; ++p) {
345 for (q = p, r = ct; *r != 0; ++q, ++r) {
346 if (*q != *r)
347 goto next_sub;
348 }
349 return p;
350 next_sub:;
351 }
352 return NULL;
353 }
354 #endif
355 /*---------------------------------------------------------------------------
356 cdb - main debugger loop, command dispatcher
357 ---------------------------------------------------------------------------*/
358 int
cdb(message)359 cdb(message)
360 char *message;
361 {
362 char *cmdStr, *fnStr, verbStr[MAXCMD + 1], argStr[MAXARG + 1];
363 static long start, stop;
364 int argType, returnValue;
365 unsigned int i;
366
367 /* skip execution */
368 if (skipCounter > 0) {
369 --skipCounter;
370 return STEP;
371 }
372 inCdb = TRUE;
373 /* do some display related stuff */
374 #if defined(DOSALLGRAPHX)
375 if (displayMode == TEXT) {
376 switch_page(CDB_PAGE);
377 /* show_cursor(); */
378 } else
379 write_menu();
380 #else
381 #if defined(DOSTXTGRAPHX)
382 switch_page(CDB_PAGE);
383 /* show_cursor(); */
384 #else
385 #if defined(DOSGRXGRAPHX)
386 write_menu();
387 #else
388 #if defined(LINUXGRAPHX)
389 svga_write_menu();
390 #else
391 #if defined(XWINGRAPHX)
392 xWin_write_menu();
393 #endif
394 #endif
395 #endif
396 #endif
397 #endif
398
399 W2 = W->nextWarrior;
400 if (targetID == QUEUE) {
401 curAddr = 0;
402 QW = W;
403 targetSize = (QW->tasks ? QW->tasks : 1); /* at least 1, otherwise
404 * we'll get an exception in
405 * pqueue mode */
406 #ifdef QUEUEDEBUG
407 for (i = 0; i < targetSize; i++)
408 printf("%d ", queue(i));
409 printf("\n");
410 #endif
411 } else if (targetID == WARRIOR) {
412 curAddr = W - warrior;
413 /* targetSize = warriors; */
414 } else if (targetID == PSP) {
415 QW = W;
416 } else {
417 curAddr = progCnt;
418 targetSize = coreSize;
419 }
420
421 cdb_fputs(message, COND);
422 print_core(curAddr, curAddr);
423 do { /* command interpreter loop */
424 cmdStr = get_cmd(CDB_PROMPT); /* get (chained) command */
425 argType = parse_cmd(cmdStr, verbStr, &start, &stop, argStr);
426 switch (hash_str(verbStr, VERBLEN)) { /* decode on hash value for
427 * speed */
428 case CAL_H:
429 case CA_H: /* calculate */
430 if (argType == RANGE_T) {
431 if (!commaSep)
432 sprintf(outs, "%ld\n", start);
433 else
434 sprintf(outs, "%ld,%ld\n", start, stop);
435 cdb_fputs(outs, COND);
436 } else
437 bad_arg(argStr);
438 break;
439 case CLS_H:
440 case CLE_H:
441 case CL_H:
442 #if defined(DOSALLGRAPHX)
443 if (displayMode == TEXT)
444 clear_page5();
445 else
446 grclear();
447 #else
448 #if defined(DOSTXTGRAPHX)
449 clear_page5();
450 #else
451 #if defined(DOSGRXGRAPHX)
452 grclear();
453 #else
454 #ifdef DOS16
455 clrscr();
456 #else
457 #if defined(MACGRAPHX)
458 mac_clear_screen();
459 #else
460 #if defined(LINUXGRAPHX)
461 svga_clear();
462 #else
463 #if defined(XWINGRAPHX)
464 xWin_clear();
465 #else
466 cdb_fputs(CLRSCR, COND); /* escape sequence for your terminal */
467 #endif /* XWINGRAPHX */
468 #endif /* LINUXGRAPHX */
469 #endif /* MACGRAPHX */
470 #endif /* MSDOS */
471 #endif /* GRX */
472 #endif /* TXT */
473 #endif /* ALL */
474 break;
475 #if defined(DOSGRXGRAPHX) || defined(DOSTXTGRAPHX) || defined(LINUXGRAPHX) \
476 || defined(XWINGRAPHX)
477 case CLO_H: /* close display panel 2 */
478 if (curPanel == 2) {
479 i = curAddr;
480 curAddr = curAddr2;
481 curAddr2 = i;
482 }
483 #if defined(DOSALLGRAPHX)
484 if (displayMode == TEXT)
485 text_panel_update(0);
486 else
487 grupdate(0);
488 #else
489 #if defined(DOSTXTGRAPHX)
490 text_panel_update(0);
491 #else
492 #if defined(LINUXGRAPHX)
493 svga_update(0);
494 #else
495 #if defined(XWINGRAPHX)
496 xWin_update(0);
497 #else
498 grupdate(0);
499 #endif /* XWINGRAPHX */
500 #endif /* LINUXGRAPHX */
501 #endif /* DOSTXTGRAPHX */
502 #endif /* DOSALLGRAPHX */
503 break;
504 #endif /* DOSTXTGRAPHX || DOSGRXGRAPHX */
505 case CON_H:
506 case CO_H:
507 case C_H:
508 cdb_fputs(exitingCdbToFinishSimulation, COND);
509 if (logfile) {
510 fclose(logfile);
511 logfile = NULL;
512 }
513 if (*argStr && ((start = FOLD(start)) == FOLD(stop)))
514 progCnt = start;
515 returnValue = NOBREAK;
516 inCdb = FALSE;
517 break;
518 #if defined(CURSESGRAPHX) || defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) \
519 || defined(LINUXGRAPHX) || defined(XWINGRAPHX)
520 case DIS_H:
521 case DI_H:
522 case D_H:
523 if (argStr) {
524 if (((i = hash_str(argStr, 3)) == CLE_H) || (i == CLS_H)) {
525 #if defined(DOSALLGRAPHX)
526 if (displayMode == TEXT)
527 text_display_clear();
528 else
529 bgi_clear_arena();
530 #else
531 #if defined(DOSTXTGRAPHX)
532 text_display_clear();
533 #else
534 #if defined(DOSGRXGRAPHX)
535 bgi_clear_arena();
536 #else
537 #if defined(LINUXGRAPHX)
538 svga_clear_arena();
539 #endif /* SVGA */
540 #endif /* GRX */
541 #endif /* TXT */
542 #endif /* ALL */
543 } else {
544 if ((i = hash_str(argStr, 2)) == ON_H)
545 displayLevel = 3;
546 else if (i == OF_H)
547 displayLevel = 0;
548 else if (FOLD(start) == FOLD(stop)) {
549 #if defined(DOSALLGRAPHX)
550 if (displayMode != TEXT)
551 bgi_display_close(NOWAIT);
552 #else
553 #if defined(LINUXGRAPHX)
554 svga_display_close(NOWAIT);
555 #endif
556 #endif
557 decode_vopt(start);
558 #if defined(DOSALLGRAPHX)
559 display_init();
560 if (displayMode == TEXT)
561 switch_page(CDB_PAGE);
562 #else
563 #if defined(LINUXGRAPHX)
564 svga_open_graphics();
565 #endif
566 #endif
567 #if defined(XWINGRAPHX)
568 xWin_resize();
569 #endif
570 }
571 }
572 } else
573 cdb_fputs(usageDisplay, FORCE);
574 break;
575 #endif
576 case ECH_H:
577 case EC_H:
578 sprintf(outs, "%s\n", argStr);
579 cdb_fputs(outs, COND);
580 break;
581 case EDI_H:
582 case ED_H:
583 case E_H:
584 curAddr = FOLD(stop);
585 edit_core(FOLD(start), curAddr);
586 break;
587 case EXE_H:
588 case EX_H:
589 case XEC_H:
590 case XE_H:
591 case X_H:
592 if ((start = FOLD(start)) == FOLD(stop)) {
593 W->taskHead = W->taskTail;
594 W->tasks = 1;
595 progCnt = start;
596 returnValue = STEP;
597 inCdb = FALSE;
598 } else
599 cdb_fputs(usageExecute, FORCE);
600 break;
601 case FIL_H:
602 case FI_H:
603 case F_H:
604 fill_core(FOLD(start), FOLD(stop));
605 break;
606 case GO_H:
607 case G_H:
608 if (*argStr && ((start = FOLD(start)) == FOLD(stop)))
609 progCnt = start;
610 returnValue = BREAK;
611 inCdb = FALSE;
612 break;
613 case HAS_H: /* HASH: developer hook for adding new *
614 * commands */
615 for (i = 0; argStr[i]; ++i)
616 argStr[i] = toupper_(argStr[i]);
617 sprintf(outs, "#define %s_H %d\n", argStr, hash_str(argStr, VERBLEN));
618 cdb_fputs(outs, COND);
619 break;
620 case HEL_H:
621 case HE_H:
622 case H_H:
623 help();
624 break;
625 case IF_H:
626 if (argType == RANGE_T) {
627 if (!start)
628 cmdMod = SKIP;
629 } else
630 bad_arg(argStr);
631 break;
632 case LIS_H:
633 case LI_H:
634 case L_H:
635 case NULL_H: /* no command, use default */
636 if (argType == RANGE_T) {
637 curAddr = FOLD(stop);
638 print_core(FOLD(start), curAddr);
639 } else if (argStr[0] != CMDREP && argStr[1] != CMDREP) /* kludge to make !!~!!
640 * work */
641 bad_arg(argStr);
642 break;
643 #ifdef VMS
644 case LSE_H:
645 case LS_H:
646 cdb_fputs("Currently not implemented\n", FORCE);
647 break;
648 #endif
649 case MAC_H:
650 case MA_H:
651 case M_H:
652 /* filename ? */
653 for (fnStr = argStr; *fnStr && (*fnStr != ',') && !isspace(*fnStr); ++fnStr);
654 while (*fnStr && ((*fnStr == ',') || isspace(*fnStr)))
655 *fnStr++ = 0;
656 if (!macroTab[0] || *fnStr)
657 load_macros(fnStr);
658 if (!*argStr)
659 print_macros();
660 else
661 exec_macro(argStr);
662 break;
663 case MOV_H:
664 case MO_H:
665 if ((i = hash_str(argStr, 2)) == ON_H)
666 copyDebugInfo = TRUE;
667 else if (i == OF_H)
668 copyDebugInfo = FALSE;
669 else
670 cdb_fputs(usageMoveable, FORCE);
671 break;
672 case PRO_H:
673 case PR_H:
674 case P_H:
675 #if defined(DOSALLGRAPHX)
676 if (displayMode == TEXT)
677 results(NULL);
678 else
679 results(STDOUT);
680 #else
681 #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) || defined(LINUXGRAPHX) \
682 || defined(XWINGRAPHX)
683 results(NULL);
684 #else
685 results(STDOUT);
686 #endif
687 #endif
688 if (logfile)
689 results(logfile);
690 break;
691 case PQU_H:
692 case PQ_H:
693 if ((i = hash_str(argStr, 2)) == OF_H) {
694 curAddr = targetSelect(curAddr);
695 targetSize = coreSize;
696 targetID = CORE;
697 targetview = locview;
698 } else {
699 if (*argStr && start == stop && start >= 1 && start <= warriors)
700 QW = warrior + start - 1;
701 else
702 QW = W;
703 curAddr = 0;
704 targetSize = (QW->tasks ? QW->tasks : 1);
705 targetID = QUEUE;
706 targetview = queueview;
707 }
708 print_core(curAddr, curAddr);
709 break;
710 #ifdef PSPACE
711 case PSP_H: /* P-space list mode */
712 case PS_H:
713 if ((i = hash_str(argStr, 2)) == OF_H) {
714 curAddr = targetSelect(curAddr);
715 targetSize = coreSize;
716 targetID = CORE;
717 targetview = locview;
718 } else {
719 if (*argStr && start == stop && start >= 1 && start <= warriors)
720 QW = warrior + start - 1;
721 else
722 QW = W;
723 curAddr = 0;
724 targetSize = pSpaceSize;
725 targetID = PSP;
726 targetview = pspaceview;
727 }
728 print_core(curAddr, curAddr);
729 break;
730 #endif
731 case QUI_H:
732 case QU_H:
733 case Q_H:
734 if (logfile) {
735 fclose(logfile);
736 logfile = NULL;
737 }
738 #if defined(DOSALLGRAPHX)
739 if (displayMode != TEXT)
740 bgi_display_close(NOWAIT);
741 else {
742 show_cursor();
743 switch_page(DEF_PAGE);
744 }
745 #else
746 #if defined(DOSGRXGRAPHX)
747 bgi_display_close(NOWAIT);
748 #else
749 #if defined(DOSTXTGRAPHX)
750 switch_page(DEF_PAGE);
751 show_cursor();
752 #else
753 #if defined(MACGRAPHX)
754 mac_display_close();
755 #else
756 #if defined(LINUXGRAPHX)
757 svga_display_close(NOWAIT);
758 #else
759 #if defined(XWINGRAPHX)
760 xWin_display_close(NOWAIT);
761 #endif
762 #endif
763 #endif
764 #endif
765 #endif
766 #endif
767 #if defined(__MAC__) || defined(__AMIGA__)
768 /* DOS taskQueue may not be free'd because of segment wrap-around */
769 if (alloc_p) {
770 free(memory);
771 free(taskQueue);
772 alloc_p = 0;
773 }
774 #endif
775
776 Exit(USERABORT);
777
778 case REM_H: /* macro comment */
779 break;
780 case REG_H:
781 case RE_H:
782 case R_H:
783 print_registers();
784 break;
785 case RES_H: /* reset command chain/macro execution */
786 cmdMod = RESET;
787 break;
788 case SEA_H: /* wildcard search for pattern in disassembly */
789 case SE_H:
790 for (i = 0; argStr[i]; ++i)
791 argStr[i] = toupper_(argStr[i]);
792 for (i = curAddr + 1; !cmdMod && i != curAddr; ++i) {
793 if (i == targetSize)
794 i = 0;
795 if (!wildsearch(argStr, (*targetview) (i, outs))) {
796 curAddr = i;
797 break;
798 }
799 }
800 cdb_fputs((*targetview) (curAddr, outs), COND);
801 break;
802 #if !defined(__MAC__) && !defined(XWINGRAPHX)
803 case SHE_H: /* execute shell (command) */
804 case SH_H:
805 #if defined(DOSALLGRAPHX)
806 if (displayMode == TEXT) {
807 switch_page(DEF_PAGE);
808 show_cursor();
809 } else {
810 bgi_display_close(NOWAIT);
811 displayMode = GRX;
812 }
813 #else
814 #if defined(DOSGRXGRAPHX)
815 bgi_display_close(NOWAIT);
816 #else
817 #if defined(DOSTXTGRAPHX)
818 switch_page(DEF_PAGE);
819 show_cursor();
820 #if defined(CURSESGRAPHX) && !defined(__PDCURSES__)
821 endwin();
822 #endif
823 #else
824 #if defined(LINUXGRAPHX)
825 svga_display_close(NOWAIT);
826 #endif
827 #endif
828 #endif
829 #endif
830 system(argStr);
831 #if defined(DOSALLGRAPHX)
832 if (displayMode == TEXT) {
833 switch_page(CDB_PAGE);
834 hide_cursor();
835 } else
836 open_graphics();
837 #else
838 #if defined(DOSGRXGRAPHX)
839 open_graphics();
840 #else
841 #if defined(LINUXGRAPHX)
842 printf(pressAnyKeyToContinue);
843 fflush(stdout);
844 svga_getch();
845 svga_open_graphics();
846 #else
847 #if defined(DOSTXTGRAPHX)
848 #if defined(CURSESGRAPHX)
849 printf(pressAnyKeyToContinue);
850 getch();
851 clear_page5();
852 #endif
853 switch_page(CDB_PAGE);
854 hide_cursor();
855 #endif
856 #endif
857 #endif
858 #endif
859 break;
860 #endif
861 case SKI_H:
862 case SK_H:
863 if (start == stop) { /* we don't fold here */
864 skipCounter = start;
865 returnValue = STEP;
866 inCdb = FALSE;
867 } else
868 cdb_fputs(usageSkip, FORCE);
869 break;
870 case STE_H:
871 case ST_H:
872 case S_H:
873 if (*argStr && ((start = FOLD(start)) == FOLD(stop)))
874 progCnt = start;
875 returnValue = STEP;
876 inCdb = FALSE;
877 break;
878 #if defined(DOSGRXGRAPHX) || defined(DOSTXTGRAPHX) || defined(LINUXGRAPHX) \
879 || defined(XWINGRAPHX)
880 case SWI_H: /* switch display panels */
881 case SW_H:
882 if (*argStr && (start == stop) && ((start == 1) || (start == 2))) {
883 if (curPanel == start)
884 break;
885 else
886 i = start;
887 } else if (curPanel < 2)
888 i = 2;
889 else
890 i = 1;
891 #if defined(DOSALLGRAPHX)
892 if (displayMode == TEXT)
893 text_panel_update(i);
894 else
895 grupdate(i);
896 #else
897 #if defined(DOSTXTGRAPHX)
898 text_panel_update(i);
899 #else
900 #if defined(LINUXGRAPHX)
901 svga_update(i);
902 #else
903 #if defined(XWINGRAPHX)
904 xWin_update(i);
905 #else
906 grupdate(i);
907 #endif /* XWINGRAPHX */
908 #endif /* LINUXGRAPHX */
909 #endif /* DOSTXTGRAPHX */
910 #endif /* DOSALLGRAPHX */
911 i = curAddr;
912 curAddr = curAddr2;
913 curAddr2 = i;
914 break;
915 #endif /* DOSTXTGRAPHX || DOSGRXGRAPHX */
916 case TRA_H:
917 case TR_H:
918 case T_H:
919 if (argType == RANGE_T)
920 set_trace(FOLD(start), FOLD(stop));
921 else
922 bad_arg(argStr);
923 break;
924 case THR_H:
925 case TH_H:
926 if (*argStr && ((start = FOLD(start)) == FOLD(stop)))
927 progCnt = start;
928 skipCounter = (W->tasks * warriors) - 1;
929 returnValue = STEP;
930 inCdb = FALSE;
931 break;
932 case UNT_H:
933 case UN_H:
934 case U_H:
935 if (argType == RANGE_T)
936 unset_trace(FOLD(start), FOLD(stop));
937 else
938 bad_arg(argStr);
939 break;
940 case WRI_H:
941 case WR_H:
942 case W_H:
943 if (TERMINAL(argStr) && !logfile)
944 cdb_fputs(usageWrite, FORCE);
945 if (logfile) {
946 cdb_fputs(closingLogfile, COND);
947 fclose(logfile);
948 logfile = NULL;
949 }
950 if (!TERMINAL(argStr)) {
951 if ((logfile = fopen(argStr, "a")) == NULL)
952 cdb_fputs(cannotOpenLogfile, FORCE);
953 else
954 cdb_fputs(openingLogfile, COND);
955 }
956 break;
957 case WQU_H:
958 case WQ_H:
959 if ((i = hash_str(argStr, 2)) == OF_H) {
960 curAddr = targetSelect(curAddr);
961 targetSize = coreSize;
962 targetID = CORE;
963 targetview = locview;
964 } else {
965 curAddr = W - warrior;
966 targetSize = warriors;
967 targetID = WARRIOR;
968 targetview = warriorview;
969 }
970 print_core(curAddr, curAddr);
971 break;
972 default:
973 sprintf(outs, unknownCommand, cmdStr);
974 cdb_fputs(outs, FORCE);
975 break;
976 } /* switch */
977 } while (inCdb); /* do */
978 #if defined(DOSALLGRAPHX)
979 if (displayMode == TEXT) {
980 switch_page(CORE_PAGE);
981 hide_cursor();
982 } else
983 write_menu();
984 #else
985 #if defined(DOSTXTGRAPHX)
986 switch_page(CORE_PAGE);
987 hide_cursor();
988 #else
989 #if defined(DOSGRXGRAPHX)
990 write_menu();
991 #else
992 #if defined(LINUXGRAPHX)
993 svga_write_menu();
994 #else
995 #if defined(XWINGRAPHX)
996 xWin_write_menu();
997 #endif
998 #endif
999 #endif
1000 #endif
1001 #endif
1002 return returnValue;
1003 }
1004 /*---------------------------------------------------------------------------
1005 queue - return address at process queue position
1006 ---------------------------------------------------------------------------*/
1007 ADDR_T
queue(index)1008 queue(index)
1009 int index;
1010 {
1011 if (!index)
1012 return progCnt;
1013 else
1014 #ifdef DOS16
1015 return *(QW->taskHead + index - 1);
1016 #else
1017 return *(QW->taskHead + ((QW->taskHead + index - 1 >= endQueue) ?
1018 (index - 1 - totaltask) : index - 1));
1019 #endif
1020 }
1021 /*---------------------------------------------------------------------------
1022 get_cmd - get command from user or from command chain (cmd1~cmd2~cmd3..)
1023 returns null-term cmd?
1024 <return> recalls last cmd (chain)
1025 <space>.... supresses saving cmd (chain) to last-cmd
1026 ~~ (empty cmd) repeats last cmd in chain (also ~\0)
1027 ~ ~ is same as \n (used in print/edit/fill_core())
1028 !e repeats the chain before e times (no e, repeat forever)
1029 expands macro "flat" by a rather obscure method
1030 Warning: this is probably the worst spaghetti code in pmars; change at your
1031 your own risk!
1032 ---------------------------------------------------------------------------*/
1033 char *
get_cmd(prompt)1034 get_cmd(prompt)
1035 char *prompt;
1036 {
1037 static int curCmd = 0, nextCmd = 0, loopNesting;
1038 static long repeating = 0, loopStack[MAXLOOPNESTING];
1039 static char holding[MAXCMDSTR + 1], inputStr[MAXCMDSTR + 1], lastCmdStr[MAXCMDSTR + 1];
1040 int inpPtr, marking, loopStart, conLine, i;
1041 char *rv, *ptr; /* return value for *gets */
1042
1043 if (cmdMod == RESET) /* "reset" command was issued to terminate
1044 * macro */
1045 cmdMod = curCmd = nextCmd = 0;
1046 new_input:
1047
1048 #if 0
1049 printf("entering with inputStr+(curCmd=%d)=\"%s\",inputStr+(nextCmd=%d)=\"%s\"\n",
1050 curCmd, inputStr + curCmd, nextCmd, inputStr + nextCmd);
1051 #endif
1052 if (nextMacro) { /* last command was "macro <name>"" */
1053 #if defined(CURSESGRAPHX)
1054 winupdate();
1055 #else
1056 #if defined(DJGPP)
1057 #if defined(DOSALLGRAPHX)
1058 if (displayLevel == TEXT)
1059 SCREENUPDATE(Screen[CDB_PAGE]);
1060 #else
1061 #if defined(DOSTXTGRAPHX)
1062 SCREENUPDATE(Screen[CDB_PAGE]);
1063 #endif /* DOSTXTGRAPHX */
1064 #endif /* DOSALLGRAPHX */
1065 #endif /* DJGPP */
1066 #endif /* CURSESGRAPHX */
1067 if (strlen(inputStr + nextCmd) + nextCmd + strlen(nextMacro)
1068 <= MAXCMDSTR) { /* check for buffer overflow */
1069 if (nextCmd) { /* save remaining chain for later appending */
1070 *holding = CMDSEP;
1071 strcpy(holding + 1, inputStr + nextCmd);
1072 } else
1073 *holding = 0;
1074 #ifdef CYCLE_CHECK
1075 if ((tmpEnd = curCmd + strlen(nextMacro)) > macroEnd) {
1076 /* done with last macro, clear cycle-check array */
1077 for (macroIdx = 0; macroTab[macroIdx]; ++macroIdx)
1078 macroCycle[macroIdx] = 0;
1079 macroEnd = tmpEnd;
1080 }
1081 #endif
1082 nextCmd = curCmd; /* reset */
1083 strcpy(inputStr + curCmd, nextMacro);
1084 /* insert macro string in place of "macro <name>" command */
1085 strcat(inputStr + curCmd, holding);
1086 nextMacro = NULL;
1087 } else {
1088 cdb_fputs(macroStringExpansionTooLong, FORCE);
1089 nextCmd = curCmd = 0;
1090 nextMacro = NULL;
1091 goto new_input;
1092 }
1093 } else if (!nextCmd) {
1094 /* command string exhausted; get new from user */
1095 for (loopNesting = 0; loopNesting < MAXLOOPNESTING; ++loopNesting)
1096 loopStack[loopNesting] = 0;
1097 loopNesting = 0;
1098 repeating = 0;
1099 #ifdef CYCLE_CHECK
1100 /* clear cycle-check array */
1101 for (macroIdx = 0; macroTab[macroIdx]; ++macroIdx)
1102 macroCycle[macroIdx] = 0;
1103 #endif
1104 cdb_fputs(prompt, FORCE); /* display prompt */
1105 conLine = FALSE;
1106 i = 0; /* buffer index */
1107 do { /* while not continuation line */
1108 #if defined(CURSESGRAPHX)
1109 winupdate();
1110 #else
1111 #if defined(DJGPP)
1112 #if defined(DOSALLGRAPHX)
1113 if (displayLevel == TEXT)
1114 SCREENUPDATE(Screen[CDB_PAGE]);
1115 #else
1116 #if defined(DOSTXTGRAPHX)
1117 SCREENUPDATE(Screen[CDB_PAGE]);
1118 #endif /* DOSTXTGRAPHX */
1119 #endif /* DOSALLGRAPHX */
1120 #endif /* DJGPP */
1121 #endif /* CURSESGRAPHX */
1122 #if defined(DOSALLGRAPHX)
1123 if (displayMode == TEXT)
1124 rv = agets5(inputStr + i, MAXCMDSTR - i, NORMAL_ATTR); /* read command line */
1125 else
1126 rv = grgets(inputStr + i, MAXCMDSTR - i);
1127 #else
1128 #if defined(DOSTXTGRAPHX)
1129 rv = agets5(inputStr + i, MAXCMDSTR - i, NORMAL_ATTR); /* read command line */
1130 #else
1131 #if defined(DOSGRXGRAPHX)
1132 rv = grgets(inputStr + i, MAXCMDSTR - i);
1133 #else
1134 #if defined(MACGRAPHX)
1135 rv = macgets(inputStr + i, MAXCMDSTR - i);
1136 #else
1137 #if defined(LINUXGRAPHX)
1138 rv = svga_gets(inputStr + i, MAXCMDSTR - i);
1139 #else
1140 #if defined(XWINGRAPHX)
1141 rv = xWin_gets(inputStr + i, MAXCMDSTR - i);
1142 #else
1143 rv = fgets(inputStr + i, MAXCMDSTR - i + 1, stdin);
1144 #endif
1145 #endif
1146 #endif
1147 #endif
1148 #endif
1149 #endif
1150 if (!rv) {
1151 cdb_fputs(EOFreadingCommandInput, FORCE);
1152 strcpy(inputStr, "con\n"); /* leave cdb */
1153 break;
1154 }
1155 if (logfile)
1156 fputs(inputStr + i, logfile); /* echo to logfile if logging */
1157 NOEOL(inputStr + i);
1158 if (inputStr[i = strlen(inputStr) - 1] == '\\') {
1159 conLine = TRUE;
1160 inputStr[i] = 0;
1161 } else
1162 conLine = FALSE;
1163 } while (conLine == TRUE);
1164
1165 if (TERMINAL(inputStr)) /* if return was pressed, recall last command */
1166 strcpy(inputStr, lastCmdStr);
1167 /* if leading space, don't save as last command */
1168 else if (!isspace(inputStr[0]))
1169 strcpy(lastCmdStr, inputStr);
1170 nextCmd = curCmd = 0;
1171 #ifdef CYCLE_CHECK
1172 macroEnd = 0;
1173 #endif
1174 } /* if (! nextCmd) */
1175 #if defined(CURSESGRAPHX)
1176 else
1177 winupdate();
1178 #else
1179 #if defined(DJGPP)
1180 #if defined(DOSALLGRAPHX)
1181 else if (displayLevel == TEXT)
1182 SCREENUPDATE(Screen[CDB_PAGE]);
1183 #else
1184 #if defined(DOSTXTGRAPHX)
1185 else
1186 SCREENUPDATE(Screen[CDB_PAGE]);
1187 #endif /* DOSTXTGRAPHX */
1188 #endif /* DOSALLGRAPHX */
1189 #endif /* DJGPP */
1190 #endif /* CURSESGRAPHX */
1191 /* advance to next ~,! or \0 */
1192 advance:
1193 marking = 0;
1194 for (inpPtr = nextCmd; inputStr[inpPtr] && (inputStr[inpPtr] != CMDSEP)
1195 && ((nextCmd == 0 && inputStr[inpPtr + 1] != CMDREP) ||
1196 inputStr[inpPtr] != CMDREP || marking); ++inpPtr)
1197 if (!isspace(inputStr[inpPtr]))
1198 marking = 1;
1199
1200 if (!inputStr[inpPtr] && (nextCmd != inpPtr)) {
1201 /* last (or only) cmd in chain */
1202 curCmd = nextCmd;
1203 nextCmd = 0;
1204 } else if ((nextCmd == inpPtr) && (inputStr[inpPtr] != CMDREP)) {
1205 /* ~[~\0] = empty cmd, recall last in chain */
1206 if (inputStr[inpPtr]) /* ~~ */
1207 nextCmd = inpPtr + 1;
1208 else /* ~\0 */
1209 nextCmd = 0;
1210 if (inpPtr > 0)
1211 inputStr[inpPtr - 1] = ' ';
1212 inputStr[inpPtr] = 0;
1213 } else if (inputStr[inpPtr] == CMDSEP) {
1214 curCmd = nextCmd;
1215 nextCmd = inpPtr + 1;
1216 inputStr[inpPtr] = 0;
1217 } else { /* if (inputStr[inpPtr] == CMDREP) */
1218 register int i, j;
1219
1220 if (inputStr[inpPtr + 1] == CMDREP) { /* !! loop start */
1221 i = inpPtr + 2;
1222 if (cmdMod == SKIP) { /* skip next block !!....!n */
1223 cmdMod = 0;
1224 marking = 1;
1225 for (; inputStr[i]; ++i)
1226 if (inputStr[i] == CMDREP) {
1227 if (inputStr[i + 1] == CMDREP) { /* possible loop start!! */
1228 loopStart = 1;
1229 } else
1230 loopStart = 0;
1231 for (j = i - 1; isspace(inputStr[j]); --j);
1232 if (inputStr[j] == CMDSEP) { /* ~ ! */
1233 if (loopStart)
1234 ++marking;
1235 else
1236 --marking;
1237 if (!marking && !loopStart)
1238 break;
1239 else if (loopStart)
1240 i = i + 2;
1241 } else if (loopStart)
1242 i = i + 2;
1243 }
1244 loopStack[loopNesting] = repeating; /* undo stack pushing */
1245 repeating = loopStack[--loopNesting];
1246 }
1247 /* advance to next ~ or \0 */
1248 for (; inputStr[i] && (inputStr[i] != CMDSEP); ++i);
1249 if (inputStr[i]) {
1250 nextCmd = i + 1;
1251 loopStack[loopNesting] = repeating;
1252 if (loopNesting < MAXLOOPNESTING) {
1253 repeating = loopStack[++loopNesting];
1254 goto advance;
1255 } else {
1256 cdb_fputs(maximumLoopNestingExceeded, FORCE);
1257 curCmd = nextCmd = 0;
1258 goto new_input;
1259 }
1260 } else {
1261 nextCmd = 0;
1262 goto new_input;
1263 }
1264 } else { /* !# loop end */
1265 #if defined(DOS16) && !defined(DJGPP)
1266 putc('\r', stdout); /* to check for Ctrl-C press */
1267 #else
1268 #if defined(DJGPP)
1269 if (kbhit())
1270 sighandler(0);
1271 #endif
1272 #endif
1273 if (cmdMod == SKIP) {
1274 cmdMod = 0;
1275 repeating = 1;
1276 }
1277 if (!repeating) {
1278 repeating = -1; /* flag for "empty repeat count" */
1279 for (i = inpPtr + 1; inputStr[i] && inputStr[i] != CMDSEP; ++i)
1280 if (!isspace(inputStr[i]))
1281 repeating = 0L;
1282 if ((j = (inputStr[i] == CMDSEP)) == 1)
1283 inputStr[i] = 0;
1284 for (ptr = inputStr + inpPtr + 1; *ptr; ++ptr) /* capitalize */
1285 *ptr = toupper(*ptr);
1286 if (!repeating && subst_eval(inputStr + inpPtr + 1, &repeating) == TEXT_T) {
1287 cdb_fputs(badRepeatCountExpression, FORCE);
1288 curCmd = nextCmd = 0;
1289 goto new_input;
1290 }
1291 if (j)
1292 inputStr[i] = CMDSEP;
1293 }
1294 if (!--repeating) { /* done */
1295 /* advance to next ~ or \0 */
1296 for (i = inpPtr + 1; inputStr[i] && (inputStr[i] != CMDSEP); ++i);
1297 if (inputStr[i]) {
1298 nextCmd = i + 1;
1299 loopStack[loopNesting] = repeating;
1300 if (loopNesting)
1301 repeating = loopStack[--loopNesting];
1302 #if 0
1303 else {
1304 cdb_fputs(maximumLoopNestingExceeded, FORCE);
1305 curCmd = nextCmd = 0;
1306 goto new_input;
1307 }
1308 #endif
1309 goto advance;
1310 } else {
1311 nextCmd = 0;
1312 goto new_input;
1313 }
1314 }
1315 marking = 1;
1316 for (i = inpPtr - 1; i >= 0; --i)
1317 if (!inputStr[i]) { /* reverse */
1318 inputStr[i] = CMDSEP;
1319 nextCmd = i + 1;
1320 } else if (inputStr[i] == CMDREP) {
1321 if (inputStr[i - 1] == CMDREP) { /* possible loop start!! */
1322 loopStart = 1;
1323 --i;
1324 } else
1325 loopStart = 0;
1326 for (j = i - 1; isspace(inputStr[j]) && j >= 0; --j);
1327 if (!inputStr[j] || inputStr[j] == CMDSEP) { /* ~ ! */
1328 inputStr[j] = CMDSEP;
1329 if (loopStart)
1330 --marking;
1331 else
1332 ++marking;
1333 if ((!marking && loopStart) || !loopNesting)
1334 break;
1335 else {
1336 nextCmd = j + 1;
1337 i = j; /* continue past inner nested loop */
1338 }
1339 } else
1340 i = j; /* not a loop, continue reversing */
1341 }
1342 if (inputStr[i] == CMDREP) {
1343 for (++i; inputStr[i] && (inputStr[i] != CMDSEP); ++i);
1344 if (inputStr[i])
1345 curCmd = i + 1;
1346 } else
1347 curCmd = 0;
1348 if (nextCmd > 0)
1349 inputStr[nextCmd - 1] = 0;
1350 } /* !# loop end */
1351 }
1352 if (cmdMod == SKIP) {
1353 cmdMod = 0;
1354 goto new_input;
1355 }
1356 return inputStr + curCmd;
1357 }
1358 /*---------------------------------------------------------------------------
1359 cdb_fputs(str, wout) - screen output with file logging
1360 wout==FORCE always output to STDOUT
1361 wout==COND output to STDOUT may be supressed by '@' or '&'
1362 ---------------------------------------------------------------------------*/
1363 void
cdb_fputs(str,wout)1364 cdb_fputs(str, wout)
1365 char *str;
1366 int wout;
1367 {
1368 if ((silent != 2 || wout == FORCE) && logfile && (fputs(str, logfile) == EOF))
1369 #if defined(DOSALLGRAPHX)
1370 if (displayMode == TEXT)
1371 aputs5(writeErrorDiskFull, NORMAL_ATTR);
1372 else
1373 grputs(writeErrorDiskFull);
1374 #else
1375 #if defined(DOSTXTGRAPHX)
1376 aputs5(writeErrorDiskFull, NORMAL_ATTR);
1377 #else
1378 #if defined(DOSGRXGRAPHX)
1379 grputs(writeErrorDiskFull);
1380 #else
1381 #if defined(MACGRAPHX)
1382 macputs(writeErrorDiskFull);
1383 #else
1384 #if defined(LINUXGRAPHX)
1385 svga_puts(writeErrorDiskFull);
1386 #else
1387 #if defined(XWINGRAPHX)
1388 xWin_puts(writeErrorDiskFull);
1389 #else
1390 fputs(writeErrorDiskFull, stderr);
1391 #endif
1392 #endif
1393 #endif
1394 #endif
1395 #endif
1396 #endif
1397
1398 if ((!silent) || (wout == FORCE))
1399 #if defined(DOSALLGRAPHX)
1400 if (displayMode == TEXT) {
1401 if (printAttr)
1402 aputs5(str, printAttr << 12);
1403 else
1404 aputs5(str, NORMAL_ATTR);
1405 } else
1406 grputs(str);
1407 printAttr = 0;
1408 #else
1409 #if defined(DOSTXTGRAPHX)
1410 if (printAttr)
1411 aputs5(str, printAttr << 12);
1412 else
1413 aputs5(str, NORMAL_ATTR);
1414 printAttr = 0;
1415 #else
1416 #if defined(DOSGRXGRAPHX)
1417 grputs(str);
1418 printAttr = 0;
1419 #else
1420 #if defined(MACGRAPHX)
1421 macputs(str);
1422 #else
1423 #if defined(LINUXGRAPHX)
1424 svga_puts(str);
1425 printAttr = 0;
1426 #else
1427 #if defined(XWINGRAPHX)
1428 xWin_puts(str);
1429 printAttr = 0;
1430 #else
1431 fputs(str, STDOUT);
1432 #endif
1433 #endif
1434 #endif
1435 #endif
1436 #endif
1437 #endif
1438 }
1439 /*---------------------------------------------------------------------------
1440 bad_arg - report argument error
1441 ---------------------------------------------------------------------------*/
1442 void
bad_arg(argStr)1443 bad_arg(argStr)
1444 char *argStr;
1445 {
1446 sprintf(outs, badArgument, argStr);
1447 cdb_fputs(outs, FORCE);
1448 }
1449 /*---------------------------------------------------------------------------
1450 hash_str(str,length) - calculate hash value for length chars of str
1451 length<=3 to fit in int
1452 ---------------------------------------------------------------------------*/
1453 unsigned int
hash_str(str,length)1454 hash_str(str, length)
1455 char *str;
1456 int length;
1457 {
1458 int hash = 0, mul, i, j;
1459
1460 for (i = 0; i < length && str[i]; ++i) {
1461 for (j = i + 1, mul = 1; j < length; ++j)
1462 mul *= 'Z' - 'A' + 2;
1463 hash += (toupper_(str[i]) - 'A' + 1) * mul;
1464 }
1465 return (hash);
1466 }
1467 /*---------------------------------------------------------------------------
1468 substitute(in,repl,with,out) - substitute all "repl" in "in" with "with"
1469 ---------------------------------------------------------------------------*/
1470 void
substitute(in,repl,with,out)1471 substitute(in, repl, with, out)
1472 char *in, *repl, *with, *out;
1473 {
1474 /* caller is using all three global buffers */
1475 char out2[MAXARG + 1];
1476 char *pos;
1477
1478 if ((pos = strstr(in, repl)) != NULL) {
1479 substitute(pos + strlen(repl), repl, with, out2);
1480 *pos = 0;
1481 strcat(in, with);
1482 strcat(in, out2);
1483 }
1484 strcpy(out, in);
1485 return;
1486 }
1487 /*---------------------------------------------------------------------------
1488 subst_eval(inpStr,result) - evaluate range field argument after substitution
1489 of special address symbols. Currently handles:
1490 . current address
1491 $ targetSize-1 = -1
1492 A A-value of current instruction
1493 B B-value of current instruction
1494 PC progCnt of current warrior
1495 PC# progCnt of warrior1,..
1496 LINES number of cdb display lines
1497
1498 (others can be easily added)
1499 ---------------------------------------------------------------------------*/
1500 int
subst_eval(inpStr,result)1501 subst_eval(inpStr, result)
1502 char *inpStr;
1503 long *result;
1504 {
1505 int evalerr;
1506 char buf[2][MAXARG + 1], outs2[MAXARG + 1], *pos;
1507 int bi1 = 0, bi2 = 1, tmp, i;
1508 #define SWITCHBI do {bi1 = !bi1; bi2 = !bi2;} while(0)
1509
1510 if (TERMINAL(inpStr))
1511 return RANGE_T;
1512
1513 /* relative address +-expr is just .+-expr */
1514 if ((*inpStr == '-') || (*inpStr == '+')) {
1515 buf[bi1][0] = '.';
1516 buf[bi1][1] = 0;
1517 strcat(buf[bi1], inpStr);
1518 } else
1519 strcpy(buf[bi1], inpStr);
1520
1521 sprintf(outs, "%d", curAddr);
1522 substitute(buf[bi1], ".", outs, buf[bi2]);
1523
1524 SWITCHBI;
1525 sprintf(outs, "%d", (targetID == QUEUE && !QW->tasks ?
1526 targetSize - 2 : targetSize - 1));
1527 substitute(buf[bi1], "$", outs, buf[bi2]);
1528
1529 /* short cut: skip replacements if there are no letters in buffer */
1530 for (pos = buf[bi2]; *pos && !isupper(*pos); ++pos);
1531 if (*pos) {
1532
1533 SWITCHBI;
1534 sprintf(outs, "%d", targetID == PSP ? QW->pSpaceIndex : memory[targetSelect(curAddr)].A_value);
1535 substitute(buf[bi1], "A", outs, buf[bi2]);
1536
1537 SWITCHBI;
1538 sprintf(outs, "%d", targetID == PSP ? QW->pSpaceIndex : memory[targetSelect(curAddr)].B_value);
1539 substitute(buf[bi1], "B", outs, buf[bi2]);
1540
1541 for (i = warriors - 1; i >= 0; --i) {
1542 sprintf(outs, "%d", (targetID == QUEUE || targetID == PSP ?
1543 0 : (targetID == WARRIOR ?
1544 i : (W - warrior == i ? progCnt : *warrior[i].taskHead))));
1545 sprintf(outs2, "PC%d", i + 1);
1546 SWITCHBI;
1547 substitute(buf[bi1], outs2, outs, buf[bi2]);
1548 }
1549 if (warriors < MAXWARRIOR) {/* PCN where N==warriors is PC */
1550 sprintf(outs, "%d", (targetID == QUEUE || targetID == PSP ?
1551 0 : (targetID == WARRIOR ?
1552 W - warrior : progCnt)));
1553 sprintf(outs2, "PC%d", warriors);
1554 SWITCHBI;
1555 substitute(buf[bi1], outs2, outs, buf[bi2]);
1556 }
1557 SWITCHBI;
1558 sprintf(outs, "%d", (targetID == QUEUE || targetID == PSP ?
1559 0 : (targetID == WARRIOR ?
1560 W - warrior : progCnt)));
1561 substitute(buf[bi1], "PC", outs, buf[bi2]);
1562 SWITCHBI;
1563 sprintf(outs, "%d", (cycle + (warriorsLeft ? warriorsLeft : 1) - 1) /
1564 (warriorsLeft ? warriorsLeft : 1));
1565 substitute(buf[bi1], "CYCLE", outs, buf[bi2]);
1566 SWITCHBI;
1567 sprintf(outs, "%d", round);
1568 substitute(buf[bi1], "ROUND", outs, buf[bi2]);
1569
1570 SWITCHBI;
1571 #if defined(DOSALLGRAPHX)
1572 if (displayMode != TEXT)
1573 sprintf(outs, "%d", bgiTextLines - 1);
1574 else
1575 sprintf(outs, "%d", screenY - 2);
1576 #else
1577 #if defined(DOSGRXGRAPHX)
1578 sprintf(outs, "%d", bgiTextLines - 1);
1579 #else
1580 #if defined(CURSESGRAPHX)
1581 sprintf(outs, "%d", LINES);
1582 #else
1583 #if defined(DOSTXTGRAPHX)
1584 sprintf(outs, "%d", screenY - 2);
1585 #else
1586 #if defined(MACGRAPHX)
1587 sprintf(outs, "%d", mac_text_lines());
1588 #else
1589 #if defined(LINUXGRAPHX)
1590 sprintf(outs, "%d", svgaTextLines);
1591 #else
1592 #if defined(XWINGRAPHX)
1593 sprintf(outs, "%d", xWinTextLines);
1594 #else
1595 sprintf(outs, "%d", TEXTLINES);
1596 #endif
1597 #endif
1598 #endif
1599 #endif
1600 #endif
1601 #endif
1602 #endif
1603 substitute(buf[bi1], "LINES", outs, buf[bi2]);
1604
1605 } /* if (*pos) */
1606 if ((evalerr = eval_expr(buf[bi2], result)) >= OK_EXPR) {
1607 if (evalerr == OVERFLOW) {
1608 cdb_fputs(overflowErr, COND);
1609 cdb_fputs("\n", COND);
1610 }
1611 return RANGE_T;
1612 } else {
1613 return TEXT_T; /* this is somewhat poorly handled */
1614 }
1615 }
1616 /*---------------------------------------------------------------------------
1617 parse_cmd - into verb,range,argument string
1618 ---------------------------------------------------------------------------*/
1619 int
parse_cmd(inpStr,verbStr,start,stop,argStr)1620 parse_cmd(inpStr, verbStr, start, stop, argStr)
1621 char *inpStr, *verbStr, *argStr;
1622 long *start, *stop;
1623 {
1624 register S32_T i;
1625 long result1, result2;
1626
1627 SKIP_SPACE(inpStr);
1628
1629 if (*inpStr == '@') {
1630 inpStr++;
1631 silent = 1;
1632 SKIP_SPACE(inpStr); /* advance to argument */
1633 } else if (*inpStr == '&') { /* even logfile output is disabled */
1634 inpStr++;
1635 silent = 2;
1636 SKIP_SPACE(inpStr); /* advance to argument */
1637 } else
1638 silent = 0;
1639
1640 /* get verb, inpStr starts with non-whitespace char */
1641 for (i = 0; isalpha(*inpStr) && i < MAXARG; ++i, ++inpStr)
1642 verbStr[i] = *inpStr;
1643 verbStr[i] = 0;
1644
1645 SKIP_SPACE(inpStr); /* advance to argument */
1646
1647 /* if string argument, we're done */
1648 strncpy(argStr, inpStr, MAXARG);
1649
1650 /* we don't want trailing spaces in file names */
1651 for (i = strlen(argStr) - 1; i >= 0 && isspace(*(argStr + i)); --i)
1652 *(argStr + i) = 0;
1653
1654 /* range or address? - scan first value */
1655 for (i = 0; (*inpStr != ',') && !TERMINAL(inpStr); ++i, ++inpStr)
1656 buffer1[i] = toupper_(*inpStr);
1657 buffer1[i] = 0;
1658 if (*inpStr == ',') { /* remember if we encountered a comma */
1659 commaSep = 1;
1660 ++inpStr; /* and spool ahead */
1661 } else
1662 commaSep = 0;
1663 SKIP_SPACE(inpStr);
1664 for (i = 0; !TERMINAL(inpStr); ++i, ++inpStr) /* scan 2nd value */
1665 buffer2[i] = toupper_(*inpStr);
1666 buffer2[i] = 0;
1667
1668 /* replace all special address symbols and evaluate expressions */
1669 if ((subst_eval(buffer1, &result1) == TEXT_T)
1670 || (subst_eval(buffer2, &result2) == TEXT_T))
1671 return TEXT_T;
1672
1673 if (!(*buffer1) && !(*buffer2)) { /* _ , */
1674 return RANGE_T;
1675 } else if ((*buffer1) && (*buffer2)) { /* 1,2 */
1676 *start = result1;
1677 *stop = result2;
1678 return RANGE_T;
1679 } else if ((*buffer1) && !(*buffer2) && commaSep) { /* 1, */
1680 *start = result1;
1681 *stop = curAddr;
1682 return RANGE_T;
1683 } else if ((*buffer1)) { /* 1 */
1684 *start = result1;
1685 *stop = result1;
1686 return RANGE_T;
1687 } else if ((*buffer2)) { /* ,2 */
1688 *start = curAddr;
1689 *stop = result2;
1690 return RANGE_T;
1691 } else
1692 return TEXT_T;
1693 }
1694 /*---------------------------------------------------------------------------
1695 help - show command help
1696 ---------------------------------------------------------------------------*/
1697 void
help()1698 help()
1699 {
1700 int count = 0, showLines, helpIdx;
1701 #if defined(DOSALLGRAPHX)
1702 if (displayMode != TEXT)
1703 showLines = bgiTextLines - 1;
1704 else
1705 showLines = screenY - 2;
1706 #else
1707 #if defined(DOSGRXGRAPHX)
1708 showLines = bgiTextLines - 1;
1709 #else
1710 #if defined(LINUXGRAPHX)
1711 showLines = svgaTextLines - 1;
1712 #else
1713 #if defined(XWINGRAPHX)
1714 showLines = xWinTextLines - 1;
1715 #else
1716 #if defined(CURSESGRAPHX)
1717 showLines = LINES - 1;
1718 #else
1719 #if defined(DOSTXTGRAPHX)
1720 showLines = screenY - 2;
1721 #else
1722 #if defined(MACGRAPHX)
1723 showLines = mac_text_lines();
1724 #else
1725 showLines = TEXTLINES;
1726 #endif
1727 #endif
1728 #endif
1729 #endif
1730 #endif
1731 #endif
1732 #endif
1733
1734 for (helpIdx = 0; *helpText[helpIdx]; ++helpIdx) {
1735 if ((!silent) && (++count == showLines)) {
1736 xInpP = get_cmd(pagePrompt);
1737 SKIP_SPACE(xInpP);
1738 if ((*xInpP == 'q') || (*xInpP == 'Q')) {
1739 cdb_fputs("\n", COND);
1740 break; /* sin! break out of loop efficiently */
1741 }
1742 if ((*xInpP != 'a') && (*xInpP != 'A'))
1743 count = 0;
1744 }
1745 cdb_fputs(helpText[helpIdx], COND);
1746 }
1747
1748 }
1749 /*---------------------------------------------------------------------------
1750 print_core - list core addresses in range start-stop
1751 ---------------------------------------------------------------------------*/
1752 void
print_core(start,stop)1753 print_core(start, stop)
1754 ADDR_T start, stop;
1755 {
1756 int count = 0;
1757 int showLines;
1758 #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) || defined(LINUXGRAPHX) \
1759 || defined(XWINGRAPHX)
1760 int i;
1761 #endif
1762 #if defined(DOSALLGRAPHX)
1763 if (displayMode != TEXT)
1764 showLines = bgiTextLines - 1;
1765 else
1766 showLines = screenY - 2;;
1767 #else
1768 #if defined(DOSGRXGRAPHX)
1769 showLines = bgiTextLines - 1;
1770 #else
1771 #if defined(LINUXGRAPHX)
1772 showLines = svgaTextLines - 1;
1773 #else
1774 #if defined(XWINGRAPHX)
1775 showLines = xWinTextLines - 1;
1776 #else
1777 #if defined(CURSESGRAPHX)
1778 showLines = LINES - 1;
1779 #else
1780 #if defined(DOSTXTGRAPHX)
1781 showLines = screenY - 2;
1782 #else
1783 #if defined(MACGRAPHX)
1784 showLines = mac_text_lines();
1785 #else
1786 showLines = TEXTLINES;
1787 #endif
1788 #endif
1789 #endif
1790 #endif
1791 #endif
1792 #endif
1793 #endif
1794 #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) || defined(LINUXGRAPHX) \
1795 || defined(XWINGRAPHX)
1796 if (targetID == QUEUE && start == 0)
1797 printAttr = QW - warrior + 1;
1798 else if (targetID == WARRIOR && start == W - warrior)
1799 printAttr = W - warrior + 1;
1800 else if (targetID == CORE)
1801 for (i = 0; i < warriors; ++i)
1802 if (warrior[i].tasks && (W - warrior == i ? progCnt : *warrior[i].taskHead) == start) {
1803 printAttr = i + 1;
1804 break;
1805 }
1806 #endif /* to distinguish these by reverse video,
1807 * etc. */
1808 cdb_fputs((*targetview) (start, outs), COND);
1809 for (; start != stop;) {
1810 if (++start == targetSize)
1811 start = 0;
1812 if ((!silent) && (++count == showLines) && (start != stop)) {
1813 xInpP = get_cmd(pagePrompt);
1814 SKIP_SPACE(xInpP);
1815 if ((*xInpP == 'q') || (*xInpP == 'Q')) {
1816 cdb_fputs("\n", COND);
1817 break; /* sin! break out of loop efficiently */
1818 }
1819 if ((*xInpP != 'a') && (*xInpP != 'A'))
1820 count = 0;
1821 }
1822 #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) || defined(LINUXGRAPHX) \
1823 || defined(XWINGRAPHX)
1824 if (targetID == QUEUE && start == 0)
1825 printAttr = QW - warrior + 1;
1826 else if (targetID == WARRIOR && start == W - warrior)
1827 printAttr = W - warrior + 1;
1828 else if (targetID == CORE)
1829 for (i = 0; i < warriors; ++i)
1830 if (warrior[i].tasks && (W - warrior == i ? progCnt : *warrior[i].taskHead) == start) {
1831 printAttr = i + 1;
1832 break;
1833 }
1834 #endif /* to distinguish these by reverse video,
1835 * etc. */
1836 cdb_fputs((*targetview) (start, outs), COND);
1837 }
1838 }
1839 /*---------------------------------------------------------------------------
1840 set_trace - set trace bit of addresses in range start-stop
1841 ---------------------------------------------------------------------------*/
1842 void
set_trace(start,stop)1843 set_trace(start, stop)
1844 ADDR_T start, stop;
1845 {
1846 do {
1847 if (start == targetSize)
1848 start = 0;
1849 memory[targetSelect(start)].debuginfo |= 1;
1850 } while (start++ != stop);
1851 }
1852 /*---------------------------------------------------------------------------
1853 unset_trace - clear trace bit of addresses in range start-stop
1854 ---------------------------------------------------------------------------*/
1855 void
unset_trace(start,stop)1856 unset_trace(start, stop)
1857 ADDR_T start, stop;
1858 {
1859 do {
1860 if (start == targetSize)
1861 start = 0;
1862 memory[targetSelect(start)].debuginfo &= ~1;
1863 } while (start++ != stop);
1864 }
1865 /*---------------------------------------------------------------------------
1866 print_registers - show simulator status
1867 ---------------------------------------------------------------------------*/
1868 void
print_registers()1869 print_registers()
1870 {
1871 #ifdef DOS16
1872 ADDR_T far *thisProc;
1873 #else
1874 ADDR_T *thisProc;
1875 #endif
1876 int nFuture, nPast, count, taskHalf = (coreSize <= 10000 ? 7 : 5);
1877
1878 sprintf(outs, roundOfCycle, round, rounds,
1879 (cycle + (warriorsLeft ? warriorsLeft : 1) - 1) /
1880 (warriorsLeft ? warriorsLeft : 1));
1881 cdb_fputs(outs, COND);
1882 sprintf(outs, currentlyExecutingWarrior, W - warrior, W->name);
1883 cdb_fputs(outs, COND);
1884 sprintf(outs, processesActive, W->tasks);
1885 cdb_fputs(outs, COND);
1886
1887 if (W->tasks > (taskHalf * 2)) {
1888 nPast = nFuture = taskHalf;
1889 cdb_fputs(".. ", COND);
1890 } else {
1891 nPast = W->tasks >> 1;
1892 nFuture = W->tasks - nPast;
1893 }
1894 if (W->taskTail < taskQueue + nPast)
1895 thisProc = W->taskTail + (totaltask - nPast);
1896 else
1897 thisProc = W->taskTail - nPast;
1898 for (; thisProc < W->taskTail;) {
1899 sprintf(outs, "%d ", *thisProc);
1900 cdb_fputs(outs, COND);
1901 #ifdef DOS16
1902 ++thisProc;
1903 #else
1904 if (++thisProc == endQueue)
1905 thisProc = taskQueue;
1906 #endif
1907 }
1908 if (W->tasks) {
1909 sprintf(outs, "[%d]-> ", progCnt);
1910 cdb_fputs(outs, COND);
1911 for (thisProc = W->taskHead, count = 1; count < nFuture; count++) {
1912 sprintf(outs, "%d ", *thisProc);
1913 cdb_fputs(outs, COND);
1914 #ifdef DOS16
1915 ++thisProc;
1916 #else
1917 if (++thisProc == endQueue)
1918 thisProc = taskQueue;
1919 #endif
1920 }
1921 }
1922 if (W->tasks > (taskHalf * 2))
1923 cdb_fputs("..", COND);
1924 cdb_fputs("\n", COND);
1925 #ifdef PSPACE
1926 sprintf(outs, "P-space[%d]: <%d> ", W->pSpaceIndex, W->lastResult);
1927 cdb_fputs(outs, COND);
1928 for (count = 1; count < 10; ++count) {
1929 sprintf(outs, "%d ", *(pSpace[W->pSpaceIndex] + count));
1930 cdb_fputs(outs, COND);
1931 }
1932 cdb_fputs("..\n", COND);
1933 #endif
1934 if (warriors == 2) {
1935 sprintf(outs, otherWarrior, W2->name);
1936 cdb_fputs(outs, COND);
1937 sprintf(outs, processesActive, W2->tasks);
1938 cdb_fputs(outs, COND);
1939 if (W2->tasks < (taskHalf * 2)) {
1940 nPast = W2->tasks >> 1;
1941 nFuture = W2->tasks - nPast;
1942 } else {
1943 nPast = nFuture = taskHalf;
1944 cdb_fputs(".. ", COND);
1945 }
1946 if (W2->taskTail < taskQueue + nPast)
1947 thisProc = W2->taskTail + (totaltask - nPast);
1948 else
1949 thisProc = W2->taskTail - nPast;
1950 for (; thisProc < W2->taskTail;) {
1951 sprintf(outs, "%d ", *thisProc);
1952 cdb_fputs(outs, COND);
1953 #ifdef DOS16
1954 ++thisProc;
1955 #else
1956 if (++thisProc == endQueue)
1957 thisProc = taskQueue;
1958 #endif
1959 }
1960 thisProc = W2->taskHead;
1961 sprintf(outs, "[%d]-> ", *thisProc);
1962 cdb_fputs(outs, COND);
1963 for (count = 1; count < nFuture; count++) {
1964 #ifdef DOS16
1965 ++thisProc;
1966 #else
1967 if (++thisProc == endQueue)
1968 thisProc = taskQueue;
1969 #endif
1970 sprintf(outs, "%d ", *thisProc);
1971 cdb_fputs(outs, COND);
1972 }
1973 if (W2->tasks > (taskHalf * 2))
1974 cdb_fputs("..", COND);
1975 cdb_fputs("\n", COND);
1976 #ifdef PSPACE
1977 sprintf(outs, "P-space[%d]: <%d> ", W2->pSpaceIndex, W2->lastResult);
1978 cdb_fputs(outs, COND);
1979 for (count = 1; count < 10; ++count) {
1980 sprintf(outs, "%d ", *(pSpace[W2->pSpaceIndex] + count));
1981 cdb_fputs(outs, COND);
1982 }
1983 cdb_fputs("..\n", COND);
1984 #endif
1985
1986 } else if (warriors > 2) {
1987 warrior_struct *TW;
1988 for (TW = warrior; TW < warrior + warriors; ++TW)
1989 if (TW != W) {
1990 sprintf(outs, warriorAtAddressHasActiveProcesses, TW - warrior,
1991 TW->name, *TW->taskHead, TW->tasks,
1992 (TW->tasks == 1 ? "" : pluralEndingOfProcess));
1993 cdb_fputs(outs, COND);
1994 }
1995 sprintf(outs, ofWarriorsAreAlive, warriorsLeft, warriors);
1996 cdb_fputs(outs, COND);
1997 }
1998 }
1999 /*---------------------------------------------------------------------------
2000 edit_core - modify range of core addresses
2001 ---------------------------------------------------------------------------*/
2002 void
edit_core(start,stop)2003 edit_core(start, stop)
2004 ADDR_T start, stop;
2005 {
2006 int evalerr;
2007 long result;
2008 long sstart, sstop;
2009
2010 sstart = start;
2011 sstop = (start <= stop) ? stop : (long) stop + targetSize;
2012
2013 do {
2014 cdb_fputs((*targetview) (start, outs), COND);
2015 if (targetID == QUEUE)
2016 sprintf(outs, "%-4d->%05d ", start, queue(start));
2017 else if (targetID == WARRIOR)
2018 sprintf(outs, "#%-2d: %05d ", start,
2019 (W - warrior == start ? progCnt : *warrior[start].taskHead));
2020 else if (targetID == PSP)
2021 sprintf(outs, "[%4d]=", start);
2022 else /* targetID == CORE */
2023 sprintf(outs, "%05d ", start);
2024
2025 cdb_fputs(outs, COND);
2026 xInpP = get_cmd("");
2027 SKIP_SPACE(xInpP);
2028
2029 if (!TERMINAL(xInpP)) {
2030 if (targetID == PSP) { /* edit P-cell */
2031 if ((evalerr = eval_expr(xInpP, &result)) < OK_EXPR) {
2032 if (evalerr == DIV_ZERO)
2033 cdb_fputs(divZeroErr, FORCE);
2034 else
2035 cdb_fputs(badExprErr, FORCE);
2036 cdb_fputs("\n", FORCE);
2037 return;
2038 }
2039 if (evalerr == OVERFLOW) {
2040 cdb_fputs(overflowErr, COND);
2041 cdb_fputs("\n", COND);
2042 }
2043 result = ((ADDR_T) (((result) % (long) coreSize) + coreSize) % coreSize);
2044 if (start)
2045 *(pSpace[QW->pSpaceIndex] + start) = result;
2046 else
2047 QW->lastResult = result;
2048 result = 1;
2049 } else if ((result = parse(xInpP, memory + targetSelect(start),
2050 targetSelect(start))) < 0)
2051 return;
2052 } result = 1; /* empty input */
2053
2054 sstart += (long) result;
2055 while (result--) {
2056 cdb_fputs((*targetview) (start++, outs), COND);
2057 if (start == targetSize)
2058 start -= targetSize;
2059 }
2060 } while (sstart <= sstop);
2061 }
2062 /*---------------------------------------------------------------------------
2063 fill_core - fill range of core addresses with instruction
2064 ---------------------------------------------------------------------------*/
2065 void
fill_core(start,stop)2066 fill_core(start, stop)
2067 ADDR_T start, stop;
2068 {
2069 int evalerr;
2070 long sstart, sstop;
2071 int result;
2072 long evalres;
2073
2074 sstart = start;
2075 sstop = (start <= stop ? stop : (long) stop + targetSize);
2076
2077 cdb_fputs(fillWith, COND);
2078 xInpP = get_cmd("");
2079 SKIP_SPACE(xInpP);
2080 if (targetID == PSP) {
2081 if ((evalerr = eval_expr(xInpP, &evalres)) < OK_EXPR) {
2082 if (evalerr == DIV_ZERO)
2083 cdb_fputs(divZeroErr, FORCE);
2084 else
2085 cdb_fputs(badExprErr, FORCE);
2086 cdb_fputs("\n", FORCE);
2087 return;
2088 }
2089 if (evalerr == OVERFLOW) {
2090 cdb_fputs(overflowErr, COND);
2091 cdb_fputs("\n", COND);
2092 }
2093 evalres = ((ADDR_T) (((evalres) % (long) coreSize) + coreSize) % coreSize);
2094 }
2095 if (!TERMINAL(xInpP))
2096 do {
2097 if (targetID == PSP) {
2098 if (start)
2099 *(pSpace[W->pSpaceIndex] + start) = evalres;
2100 else
2101 W->lastResult = evalres;
2102 result = 1;
2103 } else if ((result = parse(xInpP, memory + targetSelect(start), targetSelect(start))) <= 0)
2104 return;
2105
2106 sstart += (long) result;
2107 while (result--) {
2108 if (++start == targetSize)
2109 start -= targetSize;
2110 }
2111 } while (sstart <= sstop);
2112 }
2113 /*---------------------------------------------------------------------------
2114 wildsearch() - search pattern in target with wildcards
2115 returns 0 if match, 1 if not
2116 spaces are not significant
2117 wildcards: * matches any number of chars in target
2118 ? matches one char in target
2119 ---------------------------------------------------------------------------*/
2120 int
wildsearch(pattern,target)2121 wildsearch(pattern, target)
2122 char *pattern, *target;
2123 {
2124 register char *pat = pattern, *tar = target; /* local copies */
2125 while (1) {
2126 SKIP_SPACE(pat); /* remove this and the next line to make */
2127 SKIP_SPACE(tar); /* the search space-sensitive */
2128 if (TERMINAL(pat))
2129 return 0; /* match! */
2130 else if (*pat == '*')
2131 return wildsearch(++pat, tar);
2132 else if ((*pat == *tar) || (*pat == '?')) {
2133 ++pat;
2134 ++tar;
2135 } else if (TERMINAL(tar))
2136 return 1; /* no match */
2137 else { /* mismatch, reset pattern to start */
2138 pat = pattern;
2139 ++tar;
2140 }
2141 } /* while (1) */
2142 }
2143 /*---------------------------------------------------------------------------
2144 load_macros() - load macros from file
2145 ---------------------------------------------------------------------------*/
2146 void
load_macros(fnStr)2147 load_macros(fnStr)
2148 char *fnStr;
2149 {
2150 int i, j, tabIdx, macroLen, conLine;
2151 FILE *mfp;
2152 char *rv;
2153
2154 if (!*fnStr)
2155 strcpy(++fnStr, "pmars.mac");
2156 if (!strcmp(fnStr, "user")) { /* special symbol, read from stdin */
2157 mfp = stdin;
2158 cdb_fputs(dotByItselfEndsKeyboardInput, COND);
2159 #if defined(CURSESGRAPHX)
2160 winupdate();
2161 #else
2162 #if defined(DJGPP)
2163 #if defined(DOSALLGRAPHX)
2164 if (displayLevel == TEXT)
2165 SCREENUPDATE(Screen[CDB_PAGE]);
2166 #else
2167 #if defined(DOSTXTGRAPHX)
2168 SCREENUPDATE(Screen[CDB_PAGE]);
2169 #endif /* DOSTXTGRAPHX */
2170 #endif /* DOSALLGRAPHX */
2171 #endif /* DJGPP */
2172 #endif
2173 } else if ((mfp = fopen(fnStr, "r")) == NULL) {
2174 sprintf(outs, cannotOpenMacroFile, fnStr);
2175 cdb_fputs(outs, FORCE);
2176 return;
2177 }
2178 while (1) {
2179 i = 0; /* buffer index */
2180 conLine = FALSE;
2181 do {
2182 #if defined(DOSALLGRAPHX)
2183 if ((mfp == stdin) && (displayMode == TEXT))
2184 rv = agets5(outs + i, MAXSTR - i, NORMAL_ATTR);
2185 else if (mfp == stdin)
2186 rv = grgets(outs + i, MAXSTR - i);
2187 else
2188 #else
2189 #if defined(DOSTXTGRAPHX)
2190 if (mfp == stdin)
2191 rv = agets5(outs + i, MAXSTR - i, NORMAL_ATTR);
2192 else
2193 #else
2194 #if defined(DOSGRXGRAPHX)
2195 if (mfp == stdin)
2196 rv = grgets(outs + i, MAXSTR - i);
2197 else
2198 #else
2199 #if defined(LINUXGRAPHX)
2200 if (mfp == stdin)
2201 rv = svga_gets(outs + i, MAXSTR - i);
2202 else
2203 #else
2204 #if defined(XWINGRAPHX)
2205 if (mfp == stdin)
2206 rv = xWin_gets(outs + i, MAXSTR - i);
2207 else
2208 #endif
2209 #endif
2210 #endif
2211 #endif
2212 #endif
2213 rv = fgets(outs + i, MAXSTR - i + 1, mfp);
2214 for (; outs[i]; i++)
2215 if (outs[i] == '\n' || outs[i] == '\r')
2216 break;
2217 outs[i] = 0;
2218 if (outs[i - 1] == '\\') {/* line continued */
2219 conLine = TRUE;
2220 outs[--i] = 0; /* reset */
2221 } else
2222 conLine = FALSE;
2223 } while (conLine == TRUE);
2224
2225 if (!rv || ((outs[0] == '.') && (outs[1] <= 13)))
2226 break; /* user input */
2227 /* capitalize name and "normalize" */
2228 for (i = 0, j = 0; outs[i] && outs[i] != '='; ++i)
2229 if (!isspace(outs[i]))
2230 buffer1[j++] = toupper_(outs[i]);
2231 if (outs[i]) {
2232 if ((macroLen = strlen(outs)) == MAXSTR) {
2233 buffer1[j] = 0;
2234 sprintf(buffer1 + j + 1, " echo Macro %s is too long (>= %d chars)~reset",
2235 buffer1, MAXSTR);
2236 buffer1[j] = '=';
2237 } else {
2238 while (outs[i])
2239 buffer1[j++] = outs[i++];
2240 buffer1[j] = 0;
2241 }
2242 } else
2243 continue; /* we hit a "comment" line -> ignore */
2244
2245 for (tabIdx = 0; (tabIdx < MAXMACROS) && macroTab[tabIdx]
2246 && !match_macro(buffer1, macroTab[tabIdx]); ++tabIdx);
2247
2248 if (tabIdx == MAXMACROS) {
2249 cdb_fputs(maximumNumberOfMacrosExceeded, FORCE);
2250 break;
2251 }
2252 if ((macroTab[tabIdx] && /* previous macro with same name exists */
2253 ((macroTab[tabIdx] = (char *) realloc(macroTab[tabIdx], macroLen + 1)) == NULL))
2254 || (!macroTab[tabIdx] &&
2255 ((macroTab[tabIdx] = (char *) malloc(macroLen + 1)) == NULL))) {
2256 cdb_fputs(outOfMacroMemory, FORCE);
2257 break;
2258 }
2259 #if 0
2260 if (!macroTab[tabIdx] &&
2261 ((macroTab[tabIdx] = (char *) malloc(macroLen + 1)) == NULL)) {
2262 cdb_fputs(outOfMacroMemory, FORCE);
2263 break;
2264 }
2265 #endif
2266 strcpy(macroTab[tabIdx], buffer1);
2267 }
2268 if (mfp != stdin)
2269 fclose(mfp);
2270 return;
2271 }
2272 /*---------------------------------------------------------------------------
2273 match_macro - compare macro name to macro definition, return ptr to
2274 first char after "=" in definition if match, NULL if not.
2275 ---------------------------------------------------------------------------*/
2276 char *
match_macro(match,macroDef)2277 match_macro(match, macroDef)
2278 char *match, *macroDef;
2279 {
2280 register int i;
2281
2282 for (i = 0; (match[i] == macroDef[i]) && (macroDef[i] != '='); ++i);
2283 if ((macroDef[i] == '=') && (!match[i] || (match[i] == '=')))
2284 return macroDef + i + 1;
2285 else
2286 return NULL;
2287 }
2288 /*---------------------------------------------------------------------------
2289 print_macros - list all macros currently in memory
2290 ---------------------------------------------------------------------------*/
2291 void
print_macros()2292 print_macros()
2293 {
2294 int count = 0, showLines, macroIdx;
2295 #if defined(DOSALLGRAPHX)
2296 if (displayMode != TEXT)
2297 showLines = bgiTextLines - 1;
2298 else
2299 showLines = screenY - 2;
2300 #else
2301 #if defined(DOSGRXGRAPHX)
2302 showLines = bgiTextLines - 1;
2303 #else
2304 #if defined(LINUXGRAPHX)
2305 showLines = svgaTextLines - 1;
2306 #else
2307 #if defined(XWINGRAPHX)
2308 showLines = xWinTextLines - 1;
2309 #else
2310 #if defined(CURSESGRAPHX)
2311 showLines = LINES - 1;
2312 #else
2313 #if defined(DOSTXTGRAPHX)
2314 showLines = screenY - 2;
2315 #else
2316 #if defined(MACGRAPHX)
2317 showLines = mac_text_lines();
2318 #else
2319 showLines = TEXTLINES;
2320 #endif
2321 #endif
2322 #endif
2323 #endif
2324 #endif
2325 #endif
2326 #endif
2327
2328 for (macroIdx = 0; macroTab[macroIdx]; ++macroIdx) {
2329 if ((!silent) && (++count == showLines)) {
2330 xInpP = get_cmd(pagePrompt);
2331 SKIP_SPACE(xInpP);
2332 if ((*xInpP == 'q') || (*xInpP == 'Q')) {
2333 cdb_fputs("\n", COND);
2334 break; /* sin! break out of loop efficiently */
2335 }
2336 if ((*xInpP != 'a') && (*xInpP != 'A'))
2337 count = 0;
2338 }
2339 cdb_fputs(macroTab[macroIdx], COND);
2340 cdb_fputs("\n", COND);
2341 }
2342 }
2343 /*---------------------------------------------------------------------------
2344 exec_macro - execute macro by queuing as a command line
2345 ---------------------------------------------------------------------------*/
2346 void
exec_macro(macro)2347 exec_macro(macro)
2348 char *macro;
2349 {
2350 int macroIdx;
2351
2352 for (macroIdx = 0; macro[macroIdx]; ++macroIdx) /* make capital */
2353 macro[macroIdx] = toupper_(macro[macroIdx]);
2354
2355 for (macroIdx = 0; macroTab[macroIdx]; ++macroIdx)
2356 if ((nextMacro = match_macro(macro, macroTab[macroIdx])) != NULL)
2357 break;
2358 if (!nextMacro) {
2359 sprintf(outs, unknownMacro, macro);
2360 cdb_fputs(outs, FORCE);
2361 }
2362 #ifdef CYCLE_CHECK
2363 else if (macroCycle[macroIdx]) { /* detected circular macro defintion,
2364 * abort */
2365 cdb_fputs("Circular macro definition\n", FORCE);
2366 nextMacro = NULL;
2367 } else
2368 macroCycle[macroIdx] = 1; /* mark as visited */
2369 #endif
2370 }
2371 /*---------------------------------------------------------------------------
2372 queueview - locview for queue mode: return instruction at queue(loc)
2373 ---------------------------------------------------------------------------*/
2374 char *
queueview(loc,outp)2375 queueview(loc, outp)
2376 ADDR_T loc;
2377 char *outp;
2378 {
2379 char buf[MAXSTR];
2380 ADDR_T qloc = queue(loc);
2381
2382 sprintf(outp, "%-4d->%05d %s\n", loc, qloc, cellview(memory + qloc, buf, 0));
2383 return (outp);
2384 }
2385
2386 /*---------------------------------------------------------------------------
2387 warriorview - locview for warrior mode: return instruction at warrior[loc].taskHead
2388 ---------------------------------------------------------------------------*/
2389 char *
warriorview(loc,outp)2390 warriorview(loc, outp)
2391 ADDR_T loc;
2392 char *outp;
2393 {
2394 char buf[MAXSTR];
2395 ADDR_T wloc = (W - warrior == loc ? progCnt : *warrior[loc].taskHead);
2396
2397 sprintf(outp, "#%-2d: %05d %s\n", loc, wloc, cellview(memory + wloc, buf, 0));
2398 return (outp);
2399 }
2400
2401 char
2402 *
pspaceview(loc,outp)2403 pspaceview(loc, outp)
2404 ADDR_T loc;
2405 char *outp;
2406 {
2407 loc %= pSpaceSize;
2408 sprintf(outp, "[%4d]=%-5d\n", loc, loc ? *(pSpace[QW->pSpaceIndex] + loc) :
2409 QW->lastResult);
2410 return outp;
2411 }
2412 #endif
2413
2414 int
score(warnum)2415 score(warnum)
2416 int warnum;
2417 {
2418 int surv, accu = 0;
2419 long res;
2420
2421 for (surv = 1; surv <= warriors; ++surv) {
2422 set_reg('S', (long) surv);
2423 if (eval_expr(SWITCH_eq, &res) < OK_EXPR)
2424 return INT_MIN; /* hopefully clparse will catch errors
2425 * earlier */
2426 else
2427 accu += warrior[warnum].score[surv - 1] * res;
2428 }
2429 return accu;
2430 }
2431
2432 /* total the number of deaths for warrior[warnum]; the "order of death"
2433 array is currently neither reported nor used for the score calculation */
2434 int
deaths(warnum)2435 deaths(warnum)
2436 int warnum;
2437 {
2438 int i, accu = 0;
2439 for (i = warriors; i < 2 * warriors - 1; ++i)
2440 accu += warrior[warnum].score[i];
2441 return accu;
2442 }
2443
2444 void
sort_by_score(idxV,scrV)2445 sort_by_score(idxV, scrV)
2446 int *idxV, *scrV;
2447 {
2448 int sorted, tmp, i;
2449 do {
2450 sorted = 1;
2451 for (i = 0; i < warriors - 1; ++i)
2452 if (scrV[idxV[i]] < scrV[idxV[i + 1]]) {
2453 tmp = idxV[i];
2454 idxV[i] = idxV[i + 1];
2455 idxV[i + 1] = tmp;
2456 sorted = 0;
2457 }
2458 } while (!sorted);
2459 }
2460
2461 extern char *nameByAuthorScores;
2462 extern char *resultsAre;
2463 extern char *resultsWLT;
2464
2465 void
results(outp)2466 results(outp)
2467 FILE *outp;
2468 {
2469 int idxV[MAXWARRIOR], scrV[MAXWARRIOR];
2470 int i, j;
2471 char outs[80];
2472 long saveW, saveS;
2473
2474 eval_expr("W", &saveW); /* save these registers if in use */
2475 eval_expr("S", &saveS);
2476 set_reg('W', (long) warriors);/* 'W' used in score calculation */
2477
2478 for (i = 0; i < warriors; ++i) {
2479 idxV[i] = i;
2480 scrV[i] = score(i);
2481 }
2482 if (SWITCH_o)
2483 sort_by_score(idxV, scrV);
2484 #if defined(DOSALLGRAPHX)
2485 if ((displayMode == TEXT) && !outp) {
2486 for (i = 0; i < warriors; ++i) {
2487 sprintf(outs, nameByAuthorScores, warrior[idxV[i]].name, warrior[idxV[i]].authorName,
2488 scrV[idxV[i]]);
2489 aputs5(outs, NORMAL_ATTR);
2490 if (warriors > 2) {
2491 aputs5(resultsAre, NORMAL_ATTR);
2492 for (j = 0; j < warriors; ++j) {
2493 sprintf(outs, " %d", warrior[idxV[i]].score[j]);
2494 aputs5(outs, NORMAL_ATTR);
2495 }
2496 sprintf(outs, " %d\n", deaths(idxV[i]));
2497 aputs5(outs, NORMAL_ATTR);
2498 }
2499 }
2500 if (warriors == 2) {
2501 sprintf(outs, resultsWLT, warrior[idxV[0]].score[0],
2502 warrior[idxV[0]].score[2], warrior[idxV[0]].score[1]);
2503 aputs5(outs, NORMAL_ATTR);
2504 }
2505 } else if ((displayMode == TEXT) || (outp != STDOUT)) {
2506 for (i = 0; i < warriors; ++i) {
2507 fprintf(outp, nameByAuthorScores, warrior[idxV[i]].name, warrior[idxV[i]].authorName,
2508 scrV[idxV[i]]);
2509 if (warriors > 2) {
2510 fprintf(outp, resultsAre);
2511 for (j = 0; j < warriors; ++j) {
2512 fprintf(outp, " %d", warrior[idxV[i]].score[j]);
2513 }
2514 fprintf(outp, " %d\n", deaths(idxV[i]));
2515 }
2516 }
2517 if (warriors == 2) {
2518 fprintf(outp, resultsWLT, warrior[idxV[0]].score[0],
2519 warrior[idxV[0]].score[2], warrior[idxV[0]].score[1]);
2520 }
2521 } else {
2522 for (i = 0; i < warriors; ++i) {
2523 sprintf(outs, nameByAuthorScores, warrior[idxV[i]].name, warrior[idxV[i]].authorName,
2524 scrV[idxV[i]]);
2525 grputs(outs);
2526 if (warriors > 2) {
2527 grputs(resultsAre);
2528 for (j = 0; j < warriors; ++j) {
2529 sprintf(outs, " %d", warrior[idxV[i]].score[j]);
2530 grputs(outs);
2531 }
2532 sprintf(outs, " %d\n", deaths(idxV[i]));
2533 grputs(outs);
2534 }
2535 }
2536 if (warriors == 2) {
2537 sprintf(outs, resultsWLT, warrior[idxV[0]].score[0],
2538 warrior[idxV[0]].score[2], warrior[idxV[0]].score[1]);
2539 grputs(outs);
2540 }
2541 }
2542 #else
2543 #if defined(DOSGRXGRAPHX) || defined(DOSTXTGRAPHX) || defined(LINUXGRAPHX) \
2544 || defined(XWINGRAPHX)
2545 #if defined(DOSGRXGRAPHX)
2546 #define OUTTEXT(s) grputs(s)
2547 #else
2548 #if defined(LINUXGRAPHX)
2549 #define OUTTEXT(s) svga_puts(s)
2550 #else
2551 #if defined(XWINGRAPHX)
2552 #define OUTTEXT(s) xWin_puts(s)
2553 #else
2554 #define OUTTEXT(s) aputs5(s, NORMAL_ATTR)
2555 #endif
2556 #endif
2557 #endif
2558
2559 if (!outp) {
2560 for (i = 0; i < warriors; ++i) {
2561 sprintf(outs, nameByAuthorScores, warrior[idxV[i]].name, warrior[idxV[i]].authorName,
2562 scrV[idxV[i]]);
2563 OUTTEXT(outs);
2564 if (warriors > 2) {
2565 OUTTEXT(resultsAre);
2566 for (j = 0; j < warriors; ++j) {
2567 sprintf(outs, " %d", warrior[idxV[i]].score[j]);
2568 OUTTEXT(outs);
2569 }
2570 OUTTEXT("\n");
2571 sprintf(outs, " %d\n", deaths(idxV[i]));
2572 OUTTEXT(outs);
2573 }
2574 }
2575 if (warriors == 2) {
2576 sprintf(outs, resultsWLT, warrior[idxV[0]].score[0],
2577 warrior[idxV[0]].score[2], warrior[idxV[0]].score[1]);
2578 OUTTEXT(outs);
2579 }
2580 } else {
2581 for (i = 0; i < warriors; ++i) {
2582 fprintf(outp, nameByAuthorScores, warrior[idxV[i]].name, warrior[idxV[i]].authorName,
2583 scrV[idxV[i]]);
2584 if (warriors > 2) {
2585 fprintf(outp, resultsAre);
2586 for (j = 0; j < warriors; ++j) {
2587 fprintf(outp, " %d", warrior[idxV[i]].score[j]);
2588 }
2589 fprintf(outp, " %d\n", deaths(idxV[i]));
2590 }
2591 }
2592 if (warriors == 2) {
2593 fprintf(outp, resultsWLT, warrior[idxV[0]].score[0],
2594 warrior[idxV[0]].score[2], warrior[idxV[0]].score[1]);
2595 }
2596 }
2597 #else
2598 for (i = 0; i < warriors; ++i) {
2599 fprintf(outp, nameByAuthorScores, warrior[idxV[i]].name, warrior[idxV[i]].authorName,
2600 scrV[idxV[i]]);
2601 if (warriors > 2) {
2602 fprintf(outp, resultsAre);
2603 for (j = 0; j < warriors; ++j) {
2604 fprintf(outp, " %d", warrior[idxV[i]].score[j]);
2605 }
2606 fprintf(outp, " %d\n", deaths(idxV[i]));
2607 }
2608 }
2609 if (warriors == 2) {
2610 fprintf(outp, resultsWLT, warrior[idxV[0]].score[0],
2611 warrior[idxV[0]].score[2], warrior[idxV[0]].score[1]);
2612 }
2613 #endif
2614 #endif
2615 set_reg('W', saveW); /* restore previous value of register */
2616 set_reg('S', saveS);
2617 }
2618