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