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 * asm.c: assembler
22 * $Id: asm.c,v 1.3 2000/12/25 00:49:07 iltzu Exp $
23 *
24 * usage: int assemble(char *filename, FIELD_T warriornum);
25 * parameters:
26 * filename: name of file to be assembled
27 * warriornum: num of warrior[num]
28 * return:
29 * errorcode: its definitions are defined in global.h
30 * globals:
31 * if errorcode is not SUCCESS, errmsg[] contains the last error
32 * message and errorlevel is set
33 */
34
35 #if defined(MPW)
36 #pragma segment Asm
37 #endif
38
39 #include <ctype.h>
40 #include <string.h>
41 #include <stdio.h>
42
43 #include "global.h"
44 #include "asm.h"
45
46 #ifdef MACGRAPHX
47 extern void macputs(char *);
48 #endif
49
50 #define concat(a,b) (strlen(a)+strlen(b)<MAXALLCHAR?pstrcat((a),(b)):NULL)
51
52 /*
53 #define ASM_DEBUG
54 */
55
56 /* *************************** external strings ************************** */
57
58 extern char *logicErr, *reference, *labelRefMsg, *groupLabel, *textMsg,
59 *stackMsg, *labelMsg, *endOfChart, *afterPass, *instrMsg, *endOfPass,
60 *unknown, *anonymous, *illegalAppendErr, *bufferOverflowErr, *badOffsetErr,
61 *illegalConcatErr, *tooManyLabelsErr, *unopenedFORErr, *unclosedROFErr,
62 *bad88FormatErr, *noInstErr, *tokenErr, *undefinedSymErr, *expectNumberErr,
63 *syntaxErr, *tooManyInstrErr, *missingErr, *recursiveErr, *badExprErr,
64 *missingAssertErr, *concatErr, *ignoreENDErr, *invalidAssertErr,
65 *tooMuchStuffErr, *extraTokenErr, *improperPlaceErr, *invalid88Err,
66 *incompleteOpErr, *redefinitionErr, *undefinedLabelErr, *discardLabelErr,
67 *assertionFailErr, *tooManyMsgErr, *fileOpenErr, *fileReadErr, *notEnoughMemErr,
68 *warning, *error, *inLine, *opcodeMsg, *modifierMsg, *aTerm, *bTerm,
69 *currentAssertMsg, *currentFORMsg, *CURLINEErr, *paramCheckMsg,
70 *errNumMsg, *warNumMsg, *duplicateMsg, *divZeroErr, *overflowErr;
71
72 #ifdef VMS /* VMS LSE strings ( "-D" option) */
73 extern char *StartDia, *Region, *AllLine, *LineQualifier, *Label, *LSEWarn,
74 *LSEErr, *Message, *EndDia, *StartMod, *Opening, *EndMod;
75 #endif /* VMS */
76
77 /* ********************** macros + type definitions ********************** */
78
79 #define LOGICERROR do { fprintf(STDOUT, logicErr, __FILE__, __LINE__); \
80 Exit(PARSEERR); } while(0)
81
82 #define MEMORYERROR errprn(MLCERR, (line_st *) NULL, "")
83
84 typedef enum RType {
85 RTEXT, RSTACK, RLABEL
86 } RType;
87
88 typedef enum errType {
89 BUFERR, M88ERR, TOKERR, SYNERR, SNFERR, F88ERR, NOPERR,
90 EVLERR, EXPERR, RECERR, ANNERR, LINERR, APPERR, IGNORE,
91 ZLNERR, NUMERR, IDNERR, ROFERR, FORERR, ERVERR, GRPERR,
92 CHKERR, NASERR, BASERR, EXXERR, FNFERR, UDFERR, CATERR,
93 DLBERR, OFSERR, DOEERR, DSKERR, MLCERR, DIVERR, OFLERR,
94 MISC
95 } errType;
96
97 typedef enum stateCol {
98 S_OP, S_MOD_ADDR_EXP, S_MODF, S_ADDR_EXP_A,
99 S_EXP_FS, S_ADDR_EXP_B, S_EXPR
100 } stateCol;
101
102 typedef struct src_st {
103 char *src;
104 uShrt loc;
105 struct src_st *nextsrc;
106 } src_st;
107
108 typedef struct line_st {
109 char *vline;
110 FIELD_T dbginfo;
111 src_st *linesrc;
112 struct line_st *nextline;
113 } line_st;
114
115 typedef struct grp_st {
116 char *symn;
117 struct grp_st *nextsym;
118 } grp_st;
119
120 typedef struct ref_st {
121 grp_st *grpsym;
122 line_st *sline;
123 uShrt value, visit;
124 RType reftype;
125 struct ref_st *nextref;
126 } ref_st;
127
128 typedef struct err_st {
129 uShrt code, loc, num;
130 } err_st;
131 /* ************************* some globals *************************** */
132
133 #ifdef NEW_MODES
134 char addr_sym[] = {'#', '$', '@', '<', '>', '*', '{', '}', '\0'};
135 char expr_sym[] =
136 {'(', ')', '/', '+', '-', '%', '!', '=', '\0'};
137 #else
138 char addr_sym[] = {'#', '$', '@', '<', '>', '\0'};
139 char expr_sym[] =
140 {'(', ')', '*', '/', '+', '-', '%', '!', '=', '\0'};
141 #endif
142
143 char *opname[] =
144 {"MOV", "ADD", "SUB", "MUL", "DIV", "MOD", "JMZ", /* op */
145 "JMN", "DJN", "CMP", "SLT", "SPL", "DAT", "JMP", /* op */
146 #ifdef NEW_OPCODES
147 "SEQ", "SNE", "NOP", /* ext op */
148 #endif
149 #ifdef PSPACE
150 "LDP", "STP",
151 #endif
152 "ORG", "END", /* pseudo-opcodes */
153 #ifdef SHARED_PSPACE
154 "PIN", ""};
155 #else
156 ""};
157 #endif
158
159 char *modname[] = {"A", "B", "AB", "BA", "F", "X", "I", ""};
160 #ifndef SERVER
161 char *swname[] = {"DEBUG", "TRACE", "BREAK", "ASSERT", ""};
162 #else
163 char *swname[] = {"ASSERT", ""};
164 #endif
165
166 #ifdef SHARED_PSPACE
167 #define PSEOPNUM 4 /* also PIN */
168 #else
169 #define PSEOPNUM 3
170 #endif /* SHARED_PSPACE */
171
172 #define OPNUM (sizeof(opname)/sizeof(opname[0])) - PSEOPNUM
173
174 #define ORGOP (OPNUM + 0)
175 #define ENDOP (OPNUM + 1)
176 #define PINOP (OPNUM + 2)
177 #define EQUOP (OPNUM + 3) /* this has to be the last */
178
179 #define MODNUM ((sizeof(modname)/sizeof(modname[0])) - 1)
180 #define SWNUM ((sizeof(swname)/sizeof(swname[0])) - 1)
181
182 #define ERRMAX 9 /* max error */
183 #define GRPMAX 7 /* max group */
184 #define LEXCMAX 50 /* max number of excess lines */
185
186 static char noassert;
187 static uChar errnum, warnum; /* Number of error and warning */
188 static uChar symnum;
189
190 static ref_st *reftbl;
191 static grp_st *symtbl;
192 static src_st *srctbl;
193 static line_st *sline[2], *lline[2];
194 static err_st *errkeep;
195
196 static FIELD_T dbginfo;
197 static int dbgproceed;
198 static unsigned int curWarrior;
199 static unsigned int pass;
200 static int ierr;
201
202 static char buf[MAXALLCHAR], buf2[MAXALLCHAR];
203 static char token[MAXALLCHAR], outs[MAXALLCHAR];
204
205
206 #ifdef VMS
207 FILE *dias;
208 #endif
209
210 /* ****************** required local prototypes ********************* */
211
212 #ifdef NEW_STYLE
213 static void textout(char *);
214 static void errprn(errType, line_st *, char *);
215 #else
216 static void textout(), errprn();
217 #endif
218
219 /* ***************** conforming local prototypes ******************** */
220
221 #ifdef NEW_STYLE
222 #ifndef SERVER
223 static void lineswitch(char *, uShrt, line_st *);
224 #endif
225 static int globalswitch(char *, uShrt, uShrt, uShrt);
226 static int trav2(char *, char *, int);
227 static int normalize(long);
228 static int blkfor(char *, char *);
229 static int equtbl(char *);
230 static int equsub(char *, char *, int, ref_st *);
231 static ref_st *lookup(char *);
232 static grp_st *addsym(char *, grp_st *);
233 static src_st *addlinesrc(char *, uShrt);
234 static void newtbl(void);
235 static void addpredef(char *, U32_T);
236 static void addpredefs(void);
237 static void addline(char *, src_st *, uShrt);
238 static void show_info(uShrt), show_lbl(void);
239 static void disposeline(line_st *), disposegrp(grp_st *);
240 static void disposetbl(ref_st *, ref_st *);
241 static void cleanmem(void);
242 static void nocmnt(char *);
243 static void automaton(char *, stateCol, mem_struct *);
244 static void dfashell(char *, mem_struct *);
245 static void expand(uShrt), encode(uShrt);
246 #else
247 #ifndef SERVER
248 static void lineswitch();
249 #endif
250 static int globalswitch(), trav2(), normalize();
251 static int blkfor(), equtbl(), equsub();
252 static ref_st *lookup();
253 static grp_st *addsym();
254 static src_st *addlinesrc();
255 static void newtbl(), addpredef(), addline();
256 static void addpredefs();
257 static void show_info(), show_lbl();
258 static void disposeline(), disposegrp(), disposetbl();
259 static void cleanmem(), nocmnt();
260 static void automaton(), dfashell(), expand(), encode();
261 #endif
262
263 /* ************************** Functions ***************************** */
264
265 static ref_st *
lookup(symn)266 lookup(symn)
267 char *symn;
268 {
269 ref_st *curtbl;
270 grp_st *symtable;
271
272 for (curtbl = reftbl; curtbl; curtbl = curtbl->nextref)
273 for (symtable = curtbl->grpsym; symtable;
274 symtable = symtable->nextsym)
275 if (!strcmp(symtable->symn, symn))
276 return curtbl;
277
278 return NULL;
279 }
280
281 /* ******************************************************************* */
282
283 static void
newtbl()284 newtbl()
285 {
286 ref_st *curtbl;
287 if ((curtbl = (ref_st *) MALLOC(sizeof(ref_st))) != NULL) {
288 curtbl->grpsym = NULL;
289 curtbl->sline = NULL;
290 curtbl->visit = FALSE; /* needed to detect recursive reference */
291 curtbl->nextref = reftbl;
292 reftbl = curtbl;
293 } else
294 MEMORYERROR;
295 }
296
297 /* ******************************************************************* */
298
299 static grp_st *
addsym(symn,curgroup)300 addsym(symn, curgroup)
301 char *symn;
302 grp_st *curgroup;
303 {
304 grp_st *symgrp;
305
306 if ((symgrp = (grp_st *) MALLOC(sizeof(grp_st))) != NULL)
307 if ((symgrp->symn = pstrdup(symn)) != NULL)
308 symgrp->nextsym = curgroup;
309 else {
310 FREE(symgrp);
311 MEMORYERROR;
312 }
313
314 return symgrp;
315 }
316
317 /* ******************************************************************* */
318
319 static void
addpredef(symn,value)320 addpredef(symn, value)
321 char *symn;
322 U32_T value;
323 {
324 grp_st *lsymtbl = NULL;
325 line_st *aline;
326
327 lsymtbl = addsym(symn, lsymtbl);
328 sprintf(token, "%lu", (unsigned long) value);
329 newtbl();
330 reftbl->grpsym = lsymtbl;
331 reftbl->reftype = RTEXT;
332 if (((aline = (line_st *) MALLOC(sizeof(line_st))) != NULL) &&
333 ((aline->vline = pstrdup(token)) != NULL)) {
334 aline->nextline = NULL;
335 reftbl->sline = aline;
336 } else
337 MEMORYERROR;
338 }
339
340 /* ******************************************************************* */
341
342 static void
addpredefs()343 addpredefs()
344 {
345 /* predefined constants */
346 addpredef("CORESIZE", (U32_T) coreSize);
347 addpredef("MAXPROCESSES", (U32_T) taskNum);
348 addpredef("MAXCYCLES", (U32_T) cycles);
349 addpredef("MAXLENGTH", (U32_T) instrLim);
350 addpredef("MINDISTANCE", (U32_T) separation);
351 addpredef("VERSION", (U32_T) PMARSVER);
352 addpredef("WARRIORS", (U32_T) warriors);
353 addpredef("ROUNDS", (U32_T) rounds);
354 #ifdef PSPACE
355 addpredef("PSPACESIZE", (U32_T) pSpaceSize);
356 #endif
357 }
358
359 /* ******************************************************************* */
360
361 /* Add line, with sline and lline, it is possible to add line to multiple
362 group of inst */
363 static void
addline(vline,src,lspnt)364 addline(vline, src, lspnt)
365 char *vline;
366 src_st *src;
367 uShrt lspnt;
368 {
369 line_st *temp;
370 if ((temp = (line_st *) MALLOC(sizeof(line_st))) != NULL)
371 if ((temp->vline = pstrdup(vline)) != NULL) {
372 temp->dbginfo = (dbginfo ? TRUE : FALSE);
373 temp->linesrc = src;
374 temp->nextline = NULL;
375 if (sline[lspnt]) /* First come first serve */
376 lline[lspnt] = lline[lspnt]->nextline = temp;
377 else /* lline init depends on sline */
378 sline[lspnt] = lline[lspnt] = temp;
379 } else {
380 FREE(temp);
381 MEMORYERROR;
382 }
383 }
384
385 /* ******************************************************************* */
386
387 static src_st *
addlinesrc(src,loc)388 addlinesrc(src, loc)
389 char *src;
390 uShrt loc;
391 {
392 src_st *alinesrc;
393
394 if ((alinesrc = (src_st *) MALLOC(sizeof(src_st))) == NULL)
395 MEMORYERROR;
396 else {
397 alinesrc->src = pstrdup(src);
398 alinesrc->loc = loc;
399 alinesrc->nextsrc = srctbl;
400 srctbl = alinesrc;
401 }
402
403 return alinesrc;
404 }
405
406 /* ******************************************************************* */
407
408 static void
disposeline(aline)409 disposeline(aline)
410 line_st *aline;
411 {
412 line_st *tmp;
413
414 while ((tmp = aline) != NULL) {
415 FREE(tmp->vline);
416 aline = aline->nextline;
417 FREE(tmp);
418 }
419 }
420
421 /* ******************************************************************* */
422
423 static void
disposegrp(agrp)424 disposegrp(agrp)
425 grp_st *agrp;
426 {
427 grp_st *tmp;
428
429 while ((tmp = agrp) != NULL) {
430 FREE(tmp->symn);
431 agrp = agrp->nextsym;
432 FREE(tmp);
433 }
434 }
435
436 /* ******************************************************************* */
437
438 static void
disposetbl(atbl,btbl)439 disposetbl(atbl, btbl)
440 ref_st *atbl, *btbl;
441 {
442 ref_st *tmp;
443
444 while ((tmp = atbl) != btbl) {
445 disposegrp(tmp->grpsym);
446 atbl = atbl->nextref;
447 FREE(tmp);
448 }
449 }
450
451 /* ******************************************************************* */
452
453 /* clear all allocated mem */
454 static void
cleanmem()455 cleanmem()
456 {
457 disposeline(sline[0]);
458 disposeline(sline[1]);
459 sline[0] = sline[1] = NULL;
460 disposetbl(reftbl, NULL);
461 reftbl = NULL;
462 disposegrp(symtbl);
463 symtbl = NULL;
464 symnum = 0;
465 }
466
467 /* ******************************************************************* */
468
469 /* show symbol informations */
470 static void
show_lbl()471 show_lbl()
472 {
473 ref_st *aref;
474 grp_st *agrp;
475 line_st *aline;
476
477 textout(labelRefMsg);
478
479 for (aref = reftbl; aref; aref = aref->nextref) {
480 textout(groupLabel);
481 buf[0] = '\0';
482 if (aref->grpsym == NULL)
483 textout("<NONE>\n");
484 else {
485 for (agrp = aref->grpsym; agrp; agrp = agrp->nextsym) {
486 textout(agrp->symn);
487 textout(" ");
488 }
489 textout("\n");
490 }
491
492 textout("Reference:\n");
493 switch (aref->reftype) {
494 case RTEXT:
495 textout(textMsg);
496 textout("\n");
497 for (aline = aref->sline; aline; aline = aline->nextline) {
498 textout(aline->vline);
499 textout("\n");
500 }
501 textout("\n");
502 break;
503 case RSTACK:
504 textout(stackMsg);
505 sprintf(outs, "%5d\n\n", aref->value);
506 textout(outs);
507 break;
508 case RLABEL:
509 textout(labelMsg);
510 sprintf(outs, "%5d\n\n", aref->value);
511 textout(outs);
512 break;
513 }
514 }
515
516 textout(endOfChart);
517 }
518
519 /* ******************************************************************* */
520
521 /* Show information about the EQU processing */
522 static void
show_info(sspnt)523 show_info(sspnt)
524 uShrt sspnt;
525 {
526 line_st *aline;
527
528 sprintf(outs, afterPass, pass);
529 textout(outs);
530
531 textout(instrMsg);
532
533 for (aline = sline[sspnt]; aline; aline = aline->nextline) {
534 sprintf(outs, "(%5d) %s\n", aline->linesrc->loc, aline->vline);
535 textout(outs);
536 }
537 textout(endOfPass);
538 }
539
540 /* ******************************************************************* */
541
542 /* Remove trailing comment from str */
543 static void
nocmnt(str)544 nocmnt(str)
545 char *str;
546 {
547 while (*str && (*str != com_sym))
548 str++;
549 *str = '\0';
550 }
551
552 /* ******************************************************************* */
553
554 static int
globalswitch(str,idx,loc,lspnt)555 globalswitch(str, idx, loc, lspnt)
556 char *str;
557 uShrt idx, loc, lspnt;
558 {
559 uChar i;
560 i = (uChar) idx;
561
562 get_token(str, &i, token);
563 to_upper(token);
564
565 if (!strcmp(token, "REDCODE") && i == idx + 7) /* no leading spaces */
566 return -1;
567
568 while (isspace(str[i]))
569 i++;
570
571 if (strcmp(token, "NAME") == 0) {
572 FREE(warrior[curWarrior].name);
573 if (str[i] == '\0')
574 warrior[curWarrior].name = pstrdup(unknown);
575 else
576 warrior[curWarrior].name = pstrdup((char *) str + i);
577 } else if (strcmp(token, "AUTHOR") == 0) {
578 FREE(warrior[curWarrior].authorName);
579 if (str[i] == '\0')
580 warrior[curWarrior].authorName = pstrdup(anonymous);
581 else
582 warrior[curWarrior].authorName = pstrdup((char *) str + i);
583 } else if (strcmp(token, "DATE") == 0) {
584 FREE(warrior[curWarrior].date);
585 if (str[i] == '\0')
586 warrior[curWarrior].date = pstrdup("");
587 else
588 warrior[curWarrior].date = pstrdup((char *) str + i);
589 } else if (strcmp(token, "VERSION") == 0) {
590 FREE(warrior[curWarrior].version);
591 if (str[i] == '\0')
592 warrior[curWarrior].version = pstrdup("");
593 else
594 warrior[curWarrior].version = pstrdup((char *) str + i);
595 } else if (str_in_set(token, swname) < SWNUM) {
596 nocmnt(str + i); /* don't remove first comment */
597 addline(str, addlinesrc(str, loc), lspnt);
598 }
599 return 0;
600 }
601
602 /* ******************************************************************* */
603
604 #ifndef SERVER
605 static void
lineswitch(str,idx,aline)606 lineswitch(str, idx, aline) /* line switch */
607 char *str;
608 uShrt idx;
609 line_st *aline;
610 {
611 uChar i;
612 i = (uChar) idx;
613 get_token(str, &i, token);
614 to_upper(token);
615
616 if (strcmp(token, "DEBUG") == 0) {
617 get_token(str, &i, token);
618 to_upper(token);
619 if ((dbgproceed = strcmp(token, "OFF")) != 0) {
620 debugState = BREAK;
621 if ((copyDebugInfo = strcmp(token, "STATIC") ? TRUE : FALSE) == TRUE)
622 if (*token)
623 errprn(IGNORE, aline, str);
624 }
625 } else if (strcmp(token, "TRACE") == 0) {
626 if (dbgproceed) {
627 get_token(str, &i, token);
628 to_upper(token);
629 if ((dbginfo = strcmp(token, "OFF") ? TRUE : FALSE) == TRUE)
630 if (*token)
631 errprn(IGNORE, aline, str);
632 }
633 } else if (strcmp(token, "BREAK") == 0) {
634 if (dbgproceed) {
635 get_token(str, &i, token);
636 dbginfo = 2;
637 if (*token)
638 errprn(IGNORE, aline, str);
639 }
640 }
641 }
642 #endif
643
644 /* ******************************************************************* */
645
646 /* stst && wangsawm v0.4.0: output for different displays */
647 static void
textout(str)648 textout(str)
649 char *str;
650 {
651 #ifdef MACGRAPHX
652 macputs(str);
653 #else
654 if (!inCdb)
655 fprintf(stderr, str);
656 #if defined DOSALLGRAPHX
657 else {
658 if (displayMode == TEXT)
659 aputs5(str, NORMAL_ATTR);
660 else
661 grputs(str);
662 }
663 #else
664 #if defined DOSTXTGRAPHX
665 else
666 aputs5(str, NORMAL_ATTR);
667 #else
668 #if defined DOSGRXGRAPHX
669 else
670 grputs(str);
671 #else
672 #if defined LINUXGRAPHX
673 else
674 svga_puts(str);
675 #else
676 #if defined XWINGRAPHX
677 else
678 xWin_puts(str);
679 #else
680 #if defined(SDLGRAPHX)
681 else
682 sdlgr_puts(str);
683 #else
684 #if defined STDGRAPHX
685 else
686 stdio_puts(str);
687 #else /* no display */
688 else
689 fprintf(stderr, str);
690 #endif /* STDGRAPHX */
691 #endif /* SDLGRAPHX */
692 #endif /* XWINGRAPHX */
693 #endif /* LINUXGRAPHX */
694 #endif /* DOSGRXGRAPHX */
695 #endif /* DOSTXTGRAPHX */
696 #endif /* DOSALLGRAPHX */
697 #endif /* MACGRAPHX */
698 }
699
700 /* ******************************************************************* */
701
702 static void
errprn(code,aline,arg)703 errprn(code, aline, arg)
704 errType code;
705 line_st *aline;
706 char *arg;
707 {
708 char abuf[MAXALLCHAR];
709
710 errorcode = PARSEERR;
711 errorlevel = SERIOUS;
712
713 switch (code) {
714 case ANNERR:
715 strcpy(abuf, illegalAppendErr);
716 errorlevel = WARNING;
717 break;
718 case BUFERR:
719 strcpy(abuf, bufferOverflowErr);
720 break;
721 case ERVERR:
722 sprintf(abuf, illegalConcatErr, arg);
723 break;
724 case GRPERR:
725 sprintf(abuf, tooManyLabelsErr, arg);
726 break;
727 case FORERR:
728 strcpy(abuf, unopenedFORErr);
729 break;
730 case ROFERR:
731 strcpy(abuf, unclosedROFErr);
732 errorlevel = WARNING;
733 break;
734 case M88ERR:
735 sprintf(abuf, bad88FormatErr, arg);
736 break;
737 case ZLNERR:
738 strcpy(abuf, noInstErr);
739 errorlevel = WARNING;
740 break;
741 case DLBERR:
742 sprintf(abuf, discardLabelErr, arg);
743 errorlevel = WARNING;
744 break;
745 case TOKERR:
746 sprintf(abuf, tokenErr, arg);
747 break;
748 case SNFERR:
749 sprintf(abuf, undefinedSymErr, arg);
750 break;
751 case NUMERR:
752 strcpy(abuf, expectNumberErr);
753 break;
754 case SYNERR:
755 strcpy(abuf, syntaxErr);
756 break;
757 case LINERR:
758 sprintf(abuf, tooManyInstrErr, arg);
759 break;
760 case EXPERR:
761 sprintf(abuf, missingErr, arg);
762 break;
763 case RECERR:
764 sprintf(abuf, recursiveErr, arg);
765 break;
766 case EVLERR:
767 strcpy(abuf, badExprErr);
768 break;
769 case DIVERR:
770 strcpy(abuf, divZeroErr);
771 break;
772 case OFLERR:
773 strcpy(abuf, overflowErr);
774 errorlevel = WARNING;
775 break;
776 case NASERR:
777 strcpy(abuf, missingAssertErr);
778 errorlevel = WARNING;
779 break;
780 case OFSERR:
781 strcpy(abuf, badOffsetErr);
782 errorlevel = WARNING;
783 break;
784 case CATERR:
785 sprintf(abuf, concatErr, arg);
786 break;
787 case DOEERR:
788 strcpy(abuf, ignoreENDErr);
789 errorlevel = WARNING;
790 break;
791 case BASERR:
792 strcpy(abuf, invalidAssertErr);
793 errorlevel = WARNING;
794 break;
795 case EXXERR:
796 sprintf(abuf, tooMuchStuffErr, MAXINSTR);
797 break;
798 case IGNORE:
799 sprintf(abuf, extraTokenErr, arg);
800 errorlevel = WARNING;
801 break;
802 case APPERR:
803 sprintf(abuf, improperPlaceErr, arg);
804 break;
805 case F88ERR:
806 sprintf(abuf, invalid88Err, arg);
807 break;
808 case NOPERR:
809 sprintf(abuf, incompleteOpErr, arg);
810 break;
811 case IDNERR:
812 sprintf(abuf, redefinitionErr, arg);
813 errorlevel = WARNING;
814 break;
815 case UDFERR:
816 sprintf(abuf, undefinedLabelErr, arg);
817 errorlevel = WARNING;
818 break;
819 case CHKERR:
820 strcpy(abuf, assertionFailErr);
821 break;
822 case MISC:
823 strcpy(abuf, arg);
824 break;
825 case FNFERR:
826 sprintf(abuf, fileOpenErr, arg);
827 break;
828 case DSKERR:
829 sprintf(abuf, fileReadErr, arg);
830 break;
831 case MLCERR:
832 cleanmem(); /* refresh memory for fprintf and system */
833 #ifdef __MAC__
834 textout(notEnoughMemErr);
835 #else
836 fprintf(stderr, notEnoughMemErr);
837 #endif
838 Exit(MEMERR);
839 break;
840 }
841
842 if (errorlevel == WARNING)
843 warnum++;
844 else
845 errnum++;
846
847 if (aline) {
848
849 int i = 0;
850
851 if (aline->linesrc == NULL)
852 LOGICERROR;
853
854 while ((i < ierr) && ((errkeep[i].loc != aline->linesrc->loc) ||
855 (errkeep[i].code != code)))
856 i++;
857
858 if (i == ierr) {
859 sprintf(outs, "%s", errorlevel == WARNING ? warning : error);
860 #ifndef VMS
861 textout(outs);
862 #else /* if defined(VMS) */
863 if (!SWITCH_D)
864 textout(outs);
865 else {
866 fprintf(dias, "%s", StartDia);
867 fprintf(dias, "%s %s %s %s %d %s\"%s\"\n", Region,
868 warrior[curWarrior].fileName, AllLine, LineQualifier, aline->
869 linesrc->loc, Label, errorlevel == WARNING ? LSEWarn : LSEErr);
870 }
871
872 if (!SWITCH_D) {
873 #endif
874 sprintf(outs, inLine, aline->linesrc->loc, aline->linesrc->src);
875 textout(outs);
876 sprintf(outs, " %s\n", abuf);
877 textout(outs);
878 #ifdef VMS
879 } else {
880 fprintf(dias, "%s \"%s\"\n", Message, abuf);
881 fprintf(dias, "%s", EndDia);
882 }
883 #endif
884 errkeep[ierr].num = 1;
885 errkeep[ierr].loc = aline->linesrc->loc;
886 errkeep[ierr++].code = code;
887 } else
888 errkeep[i].num++;
889 } else {
890 sprintf(outs, "%s:\n",
891 errorlevel == WARNING ? warning : error);
892
893 #ifndef VMS
894 textout(outs);
895 #else
896 if (!SWITCH_D)
897 textout(outs);
898 else {
899 fprintf(dias, "%s", StartDia);
900 fprintf(dias, "%s %s %s %s\"%s\"\n", Region,
901 warrior[curWarrior].fileName, AllLine, Label,
902 errorlevel == WARNING ? LSEWarn : LSEErr);
903 }
904 #endif
905 sprintf(outs, " %s\n", abuf);
906 #ifndef VMS
907 textout(outs);
908 #else
909 if (!SWITCH_D)
910 textout(outs);
911 else {
912 fprintf(dias, "%s \"%s\"\n", Message, abuf);
913 fprintf(dias, "%s", EndDia);
914 }
915 #endif
916 }
917
918 if (ierr >= ERRMAX) {
919 sprintf(outs, tooManyMsgErr);
920 #ifndef VMS
921 textout(outs);
922 #else
923 if (!SWITCH_D)
924 textout(outs);
925 else {
926 fprintf(dias, "%s", StartDia);
927 fprintf(dias, "Message \"%s\"\n", Message, outs);
928 fprintf(dias, "%s", EndDia);
929 }
930 #endif
931
932 Exit(PARSEERR);
933
934 }
935 strcpy(errmsg, abuf);
936 }
937
938 /* ******************************************************************* */
939
940 #define A_expr buf
941 #define B_expr buf2
942 #define vallen 8
943 static uChar opcode, modifier;
944 static uChar statefine;
945 static stateCol laststate;
946
947 static uShrt line, linemax;
948 static uChar vcont;
949 static uShrt dspnt;
950 static line_st *aline;
951
952 /* ******************************************************************* */
953
954 /* Here is the automaton */
955 static void
automaton(expr,state,cell)956 automaton(expr, state, cell)
957 char *expr;
958 stateCol state;
959 mem_struct *cell;
960 {
961 uChar idx = 0;
962 char *tmp;
963 ref_st *atbl;
964
965 switch (laststate = state) {
966
967 case S_OP:
968 statefine = FALSE;
969 if (get_token(expr, &idx, token) == CHARTOKEN) {
970 to_upper(token);
971 if ((opcode = str_in_set(token, opname)) < OPNUM)
972 automaton((char *) expr + idx, S_MOD_ADDR_EXP, cell);
973 else if (opcode < EQUOP)
974 automaton((char *) expr + idx, S_EXPR, cell);
975 else
976 /* This should be toggled as error. No label should appear at this point */
977 LOGICERROR;
978 } else
979 errprn(EXPERR, aline, opcodeMsg);
980 break;
981
982 case S_MOD_ADDR_EXP:
983 statefine = FALSE;
984 switch (get_token(expr, &idx, token)) {
985 case MODFTOKEN:
986 automaton((char *) expr + idx, S_MODF, cell);
987 break;
988 case ADDRTOKEN:
989 cell->A_mode = (FIELD_T) ch_in_set(*token, addr_sym);
990 #ifdef NEW_MODES
991 if (cell->A_mode > 4) {
992 if (SWITCH_8)
993 errprn(M88ERR, aline, "[*{}]");
994 else
995 cell->A_mode = SYM_TO_INDIR_A(cell->A_mode);
996 }
997 #endif
998 automaton((char *) expr + idx, S_EXP_FS, cell);
999 break;
1000 case NUMBTOKEN:
1001 case EXPRTOKEN:
1002 automaton(expr, S_EXP_FS, cell);
1003 break;
1004 case CHARTOKEN:
1005 if ((atbl = lookup(token)) != NULL)
1006 if (atbl->visit)
1007 errprn(RECERR, aline, token);
1008 else if (atbl->reftype == RTEXT)
1009 if (atbl->sline) {
1010 atbl->visit = TRUE;
1011 automaton(atbl->sline->vline, S_MOD_ADDR_EXP, cell);
1012 atbl->visit = FALSE;
1013 automaton((char *) expr + idx, laststate, cell);
1014 } else
1015 /* all slines should've been filled */
1016 LOGICERROR;
1017 else if ((tmp = (char *) MALLOC(sizeof(char) * vallen)) != NULL) {
1018 sprintf(tmp, "%d", (int) atbl->value - line);
1019 atbl->visit = TRUE;
1020 automaton(tmp, S_MOD_ADDR_EXP, cell);
1021 FREE(tmp);
1022 atbl->visit = FALSE;
1023 automaton((char *) expr + idx, laststate, cell);
1024 } else
1025 MEMORYERROR;
1026 else if (!token[1])
1027 automaton(expr, S_EXP_FS, cell);
1028 else
1029 errprn(SNFERR, aline, token);
1030 break;
1031 case NONE:
1032 break;
1033 default:
1034 errprn(APPERR, aline, token);
1035 }
1036 break;
1037
1038 case S_MODF:
1039 statefine = FALSE;
1040 switch (get_token(expr, &idx, token)) {
1041 case CHARTOKEN:
1042 to_upper(token);
1043 if ((modifier = str_in_set(token, modname)) < MODNUM)
1044 automaton((char *) expr + idx, S_ADDR_EXP_A, cell);
1045 else
1046 errprn(EXPERR, aline, modifierMsg);
1047 break;
1048 case NONE:
1049 break;
1050 default:
1051 errprn(EXPERR, aline, modifierMsg);
1052 }
1053 break;
1054
1055 case S_ADDR_EXP_A:
1056 statefine = FALSE;
1057 switch (get_token(expr, &idx, token)) {
1058 case ADDRTOKEN:
1059 cell->A_mode = (FIELD_T) ch_in_set(*token, addr_sym);
1060 #ifdef NEW_MODES
1061 if (cell->A_mode > 4) {
1062 if (SWITCH_8)
1063 errprn(M88ERR, aline, "[*{}]");
1064 else
1065 cell->A_mode = SYM_TO_INDIR_A(cell->A_mode);
1066 }
1067 #endif
1068 automaton((char *) expr + idx, S_EXP_FS, cell);
1069 break;
1070 case NUMBTOKEN:
1071 case EXPRTOKEN:
1072 automaton(expr, S_EXP_FS, cell);
1073 break;
1074 case CHARTOKEN:
1075 if ((atbl = lookup(token)) != NULL)
1076 if (atbl->visit)
1077 errprn(RECERR, aline, token);
1078 else if (atbl->reftype == RTEXT)
1079 if (atbl->sline) {
1080 atbl->visit = TRUE;
1081 automaton(atbl->sline->vline, S_ADDR_EXP_A, cell);
1082 atbl->visit = FALSE;
1083 automaton((char *) expr + idx, laststate, cell);
1084 } else
1085 /* all slines should've been filled */
1086 LOGICERROR;
1087 else if ((tmp = (char *) MALLOC(sizeof(char) * vallen)) != NULL) {
1088 sprintf(tmp, "%d", (int) atbl->value - line);
1089 atbl->visit = TRUE;
1090 automaton(tmp, S_ADDR_EXP_A, cell);
1091 FREE(tmp);
1092 atbl->visit = FALSE;
1093 automaton((char *) expr + idx, laststate, cell);
1094 } else
1095 MEMORYERROR;
1096 else if (!token[1])
1097 automaton(expr, S_EXP_FS, cell);
1098 else
1099 errprn(SNFERR, aline, token);
1100 break;
1101 case NONE:
1102 break;
1103 default:
1104 errprn(EXPERR, aline, aTerm);
1105 }
1106 break;
1107
1108 case S_EXP_FS:
1109 switch (get_token(expr, &idx, token)) {
1110 case FSEPTOKEN:
1111 automaton((char *) expr + idx, S_ADDR_EXP_B, cell);
1112 break;
1113 case ADDRTOKEN:
1114 if ((token[0] != '>') && (token[0] != '<') && (token[0] != '*'))
1115 errprn(APPERR, aline, token);
1116 else {
1117 if (!concat(A_expr, token))
1118 errprn(BUFERR, aline, "");
1119 statefine = TRUE;
1120 automaton((char *) expr + idx, S_EXP_FS, cell);
1121 }
1122 break;
1123 case NUMBTOKEN:
1124 if (!concat(token, " "))
1125 errprn(BUFERR, aline, "");
1126 /* FALLTHROUGH */
1127 case EXPRTOKEN:
1128 if (!concat(A_expr, token))
1129 errprn(BUFERR, aline, "");
1130 statefine = TRUE;
1131 automaton((char *) expr + idx, S_EXP_FS, cell);
1132 break;
1133 case CHARTOKEN:
1134 if ((atbl = lookup(token)) != NULL)
1135 if (atbl->visit)
1136 errprn(RECERR, aline, token);
1137 else if (atbl->reftype == RTEXT)
1138 if (atbl->sline) {
1139 atbl->visit = TRUE;
1140 automaton(atbl->sline->vline, S_EXP_FS, cell);
1141 atbl->visit = FALSE;
1142 automaton((char *) expr + idx, laststate, cell);
1143 } else
1144 /* all slines should've been filled */
1145 LOGICERROR;
1146 else if ((tmp = (char *) MALLOC(sizeof(char) * vallen)) != NULL) {
1147 sprintf(tmp, "%d", (int) atbl->value - line);
1148 atbl->visit = TRUE;
1149 automaton(tmp, S_EXP_FS, cell);
1150 FREE(tmp);
1151 atbl->visit = FALSE;
1152 automaton((char *) expr + idx, laststate, cell);
1153 } else
1154 MEMORYERROR;
1155 else if (!token[1]) /* check if it's a register. */
1156 if (concat(A_expr, token)) {
1157 statefine = TRUE;
1158 automaton((char *) expr + idx, S_EXP_FS, cell);
1159 } else
1160 errprn(BUFERR, aline, "");
1161 else
1162 errprn(SNFERR, aline, token);
1163 break;
1164 case NONE:
1165 break;
1166 default:
1167 errprn(APPERR, aline, token);
1168 }
1169 break;
1170
1171 case S_ADDR_EXP_B:
1172 statefine = FALSE;
1173 switch (get_token(expr, &idx, token)) {
1174 case ADDRTOKEN:
1175 cell->B_mode = (FIELD_T) ch_in_set(*token, addr_sym);
1176 #ifdef NEW_MODES
1177 if (cell->B_mode > 4) {
1178 if (SWITCH_8)
1179 errprn(M88ERR, aline, "[*{}]");
1180 else
1181 cell->B_mode = SYM_TO_INDIR_A(cell->B_mode);
1182 }
1183 #endif
1184 automaton((char *) expr + idx, S_EXPR, cell);
1185 break;
1186 case NUMBTOKEN:
1187 case EXPRTOKEN:
1188 automaton(expr, S_EXPR, cell);
1189 break;
1190 case CHARTOKEN:
1191 if ((atbl = lookup(token)) != NULL)
1192 if (atbl->visit)
1193 errprn(RECERR, aline, token);
1194 else if (atbl->reftype == RTEXT)
1195 if (atbl->sline) {
1196 atbl->visit = TRUE;
1197 automaton(atbl->sline->vline, S_ADDR_EXP_B, cell);
1198 atbl->visit = FALSE;
1199 automaton((char *) expr + idx, laststate, cell);
1200 } else
1201 /* all slines should've been filled */
1202 LOGICERROR;
1203 else if ((tmp = (char *) MALLOC(sizeof(char) * vallen)) != NULL) {
1204 sprintf(tmp, "%d", (int) atbl->value - line);
1205 atbl->visit = TRUE;
1206 automaton(tmp, S_ADDR_EXP_B, cell);
1207 FREE(tmp);
1208 atbl->visit = FALSE;
1209 automaton((char *) expr + idx, laststate, cell);
1210 } else
1211 MEMORYERROR;
1212 else if (!token[1])
1213 automaton(expr, S_EXPR, cell);
1214 else
1215 errprn(SNFERR, aline, token);
1216 break;
1217 case NONE:
1218 break;
1219 default:
1220 errprn(EXPERR, aline, bTerm);
1221 }
1222 break;
1223
1224 case S_EXPR:
1225 switch (get_token(expr, &idx, token)) {
1226 case ADDRTOKEN:
1227 if ((token[0] != '>') && (token[0] != '<') && (token[0] != '*'))
1228 errprn(APPERR, aline, token);
1229 else {
1230 if (!concat(B_expr, token))
1231 errprn(BUFERR, aline, "");
1232 statefine = TRUE;
1233 automaton((char *) expr + idx, S_EXPR, cell);
1234 }
1235 break;
1236 case NUMBTOKEN:
1237 if (!concat(token, " "))
1238 errprn(BUFERR, aline, "");
1239 /* FALLTHROUGH */
1240 case EXPRTOKEN:
1241 if (!concat(B_expr, token))
1242 errprn(BUFERR, aline, "");
1243 statefine = TRUE;
1244 automaton((char *) expr + idx, S_EXPR, cell);
1245 break;
1246 case CHARTOKEN:
1247 if ((atbl = lookup(token)) != NULL)
1248 if (atbl->visit)
1249 errprn(RECERR, aline, token);
1250 else if (atbl->reftype == RTEXT)
1251 if (atbl->sline) {
1252 atbl->visit = TRUE;
1253 automaton(atbl->sline->vline, S_EXPR, cell);
1254 atbl->visit = FALSE;
1255 automaton((char *) expr + idx, S_EXPR, cell);
1256 } else
1257 /* all slines should've been filled */
1258 LOGICERROR;
1259 else if ((tmp = (char *) MALLOC(sizeof(char) * vallen)) != NULL) {
1260 if (opcode < OPNUM)
1261 sprintf(tmp, "%d", (int) atbl->value - line);
1262 else
1263 sprintf(tmp, "%d", (int) atbl->value);
1264 atbl->visit = TRUE;
1265 automaton(tmp, S_EXPR, cell);
1266 FREE(tmp);
1267 atbl->visit = FALSE;
1268 automaton((char *) expr + idx, S_EXPR, cell);
1269 } else
1270 MEMORYERROR;
1271 else if (!token[1]) /* check for register use */
1272 if (concat(B_expr, token)) {
1273 statefine = TRUE;
1274 automaton((char *) expr + idx, S_EXPR, cell);
1275 } else
1276 errprn(BUFERR, aline, "");
1277 else
1278 errprn(SNFERR, aline, token);
1279 break;
1280 case NONE:
1281 break;
1282 default:
1283 errprn(APPERR, aline, token);
1284 }
1285 break;
1286 }
1287 }
1288
1289 /* ******************************************************************* */
1290
1291 static void
dfashell(expr,cell)1292 dfashell(expr, cell)
1293 char *expr;
1294 mem_struct *cell;
1295 {
1296 cell->A_mode = (FIELD_T) ch_in_set('$', addr_sym);
1297 cell->B_mode = (FIELD_T) ch_in_set('$', addr_sym);
1298 modifier = MODNUM; /* marked as not used */
1299 A_expr[0] = B_expr[0] = '\0';
1300
1301 errorcode = SUCCESS;
1302 automaton(expr, S_OP, cell);
1303
1304 if (opcode < OPNUM) {
1305
1306 /* This is also represented in a NONE case in automaton function call */
1307 if ((statefine == FALSE) && (errorcode == SUCCESS))
1308 errprn(SYNERR, aline, opname[opcode]);
1309
1310 else if (B_expr[0] == '\0') /* If there's only one argument */
1311 switch (opcode) {
1312 case DAT: /* The default in DAT statement is #0 */
1313 cell->B_mode = cell->A_mode;
1314 strcpy(B_expr, A_expr);
1315 cell->A_mode = (FIELD_T) ch_in_set('#', addr_sym);
1316 strcpy(A_expr, "0");
1317 break;
1318 case SPL: /* The default in SPL/JMP statement is $0 */
1319 case JMP:
1320 #ifdef NEW_OPCODES
1321 case NOP:
1322 #endif
1323 cell->B_mode = (FIELD_T) ch_in_set('$', addr_sym);
1324 strcpy(B_expr, "0");
1325 break;
1326 default:
1327 errprn(NOPERR, aline, opname[opcode]); /* opcode < OPNUM */
1328 }
1329
1330 if (SWITCH_8) {
1331 switch (opcode) {
1332 case DAT:
1333 if (((cell->A_mode != (FIELD_T) IMMEDIATE) &&
1334 (cell->A_mode != (FIELD_T) PREDECR)) ||
1335 ((cell->B_mode != (FIELD_T) IMMEDIATE) &&
1336 (cell->B_mode != (FIELD_T) PREDECR)))
1337 errprn(F88ERR, aline, "DAT [#<] [#<]");
1338 break;
1339 case MOV:
1340 case ADD:
1341 case SUB:
1342 case CMP:
1343 if (cell->B_mode == (FIELD_T) IMMEDIATE) {
1344 sprintf(token, "%s [#$@<] [$@<]", opname[opcode]);
1345 errprn(F88ERR, aline, token);
1346 }
1347 break;
1348 case JMP:
1349 case JMZ:
1350 case JMN:
1351 case DJN:
1352 case SPL:
1353 if (cell->A_mode == (FIELD_T) IMMEDIATE) {
1354 sprintf(token, "%s [$@<] [#$@<]", opname[opcode]);
1355 errprn(F88ERR, aline, token);
1356 }
1357 break;
1358 case MUL:
1359 case DIV:
1360 case MOD:
1361 #ifdef NEW_OPCODES
1362 case SEQ:
1363 case SNE:
1364 case NOP:
1365 #endif
1366 #ifdef PSPACE
1367 case LDP:
1368 case STP:
1369 #endif
1370 errprn(M88ERR, aline, opname[opcode]);
1371 }
1372
1373 if (modifier != MODNUM)
1374 errprn(M88ERR, aline, "."); /* These two should be declared in
1375 * label */
1376 if ((cell->A_mode == (FIELD_T) POSTINC) ||
1377 (cell->B_mode == (FIELD_T) POSTINC))
1378 errprn(M88ERR, aline, ">");
1379 }
1380 if (modifier == MODNUM) /* no modifier, pick default */
1381 switch (opcode) {
1382 case DAT:
1383 #ifdef NEW_OPCODES
1384 case NOP:
1385 #endif
1386 modifier = (FIELD_T) mF;
1387 break;
1388 case MOV:
1389 case CMP:
1390 #ifdef NEW_OPCODES
1391 case SEQ:
1392 case SNE:
1393 #endif
1394 if (cell->A_mode == (FIELD_T) IMMEDIATE)
1395 modifier = (FIELD_T) mAB;
1396 else if (cell->B_mode == (FIELD_T) IMMEDIATE)
1397 modifier = (FIELD_T) mB;
1398 else
1399 modifier = (FIELD_T) mI;
1400 break;
1401 case ADD:
1402 case SUB:
1403 case MUL:
1404 case DIV:
1405 case MOD:
1406 if (cell->A_mode == (FIELD_T) IMMEDIATE)
1407 modifier = (FIELD_T) mAB;
1408 else if (cell->B_mode == (FIELD_T) IMMEDIATE)
1409 modifier = (FIELD_T) mB;
1410 else
1411 modifier = (FIELD_T) mF;
1412 break;
1413 #ifdef PSPACE
1414 case LDP:
1415 case STP:
1416 #endif
1417 case SLT:
1418 if (cell->A_mode == (FIELD_T) IMMEDIATE)
1419 modifier = (FIELD_T) mAB;
1420 else
1421 modifier = (FIELD_T) mB;
1422 break;
1423 default:
1424 modifier = (FIELD_T) mB;
1425 }
1426 cell->opcode = (FIELD_T) (opcode << 3) + modifier;
1427 }
1428 }
1429
1430 /* ******************************************************************* */
1431
1432 static int
normalize(value)1433 normalize(value)
1434 long value;
1435 {
1436 while (value >= (long) coreSize)
1437 value -= (long) coreSize;
1438 while (value < 0)
1439 value += (long) coreSize;
1440 return ((int) value);
1441 }
1442
1443 /* ******************************************************************* */
1444 /* assemble into instBank */
1445
1446 static void
encode(sspnt)1447 encode(sspnt)
1448 uShrt sspnt;
1449 {
1450 int evalerrA, evalerrB;
1451 long resultA, resultB;
1452 mem_struct *base;
1453
1454 if (line <= MAXINSTR) {
1455
1456 if (line > (uShrt) instrLim) {
1457 sprintf(buf, "%d", (int) line - instrLim);
1458 errprn(LINERR, (line_st *) NULL, buf);
1459 }
1460 warrior[curWarrior].instLen = line;
1461
1462 if (line)
1463 if ((warrior[curWarrior].instBank = base = (mem_struct *)
1464 MALLOC((line + 1) * sizeof(mem_struct))) != NULL) {
1465 for (aline = sline[sspnt], line = 0; aline; aline = aline->nextline) {
1466 dfashell(aline->vline, (mem_struct *) base + line);
1467 if (errnum == 0) {
1468 if (*A_expr == '\0')
1469 strcpy(A_expr, "0");
1470 if (*B_expr == '\0')
1471 strcpy(B_expr, "0");
1472
1473 if ((opcode == ENDOP) || (opcode == ORGOP)
1474 #ifdef SHARED_PSPACE
1475 || (opcode == PINOP)
1476 #endif
1477 )
1478 if ((evalerrA = eval_expr(B_expr, &resultB)) < OK_EXPR) {
1479 if (evalerrA == DIV_ZERO)
1480 errprn(DIVERR, aline, "");
1481 else
1482 errprn(EVLERR, aline, "");
1483 } else { /* by absolute */
1484 if (evalerrA == OVERFLOW)
1485 errprn(OFLERR, aline, "");
1486
1487 if ((opcode == ORGOP || opcode == PINOP) && SWITCH_8)
1488 errprn(M88ERR, aline, opname[opcode]);
1489
1490 if (opcode == ORGOP)
1491 warrior[curWarrior].offset = normalize(resultB);
1492 #ifdef SHARED_PSPACE
1493 else if (opcode == PINOP) {
1494 warrior[curWarrior].pSpaceIDNumber = resultB; /* not an address, no
1495 * need to normalize */
1496 warrior[curWarrior].pSpaceIndex = PIN_APPEARED; /* to indicate PIN has
1497 * been set */
1498 }
1499 #endif
1500 else if (resultB)
1501 if (warrior[curWarrior].offset)
1502 errprn(DOEERR, aline, "");
1503 else
1504 warrior[curWarrior].offset = normalize(resultB);
1505 /* else ignore 'end' with parameter == 0L */
1506 }
1507 else if ((evalerrA = eval_expr(A_expr, &resultA)) < OK_EXPR) {
1508 if (evalerrA == DIV_ZERO)
1509 errprn(DIVERR, aline, "");
1510 else
1511 errprn(EVLERR, aline, "");
1512 } else if ((evalerrB = eval_expr(B_expr, &resultB)) < OK_EXPR) {
1513 if (evalerrB == DIV_ZERO)
1514 errprn(DIVERR, aline, "");
1515 else
1516 errprn(EVLERR, aline, "");
1517 } else {
1518 if (evalerrA == OVERFLOW || evalerrB == OVERFLOW)
1519 errprn(OFLERR, aline, "");
1520 base[line].A_value = (ADDR_T) normalize(resultA);
1521 base[line].B_value = (ADDR_T) normalize(resultB);
1522 if ((base[line++].debuginfo = (FIELD_T) aline->dbginfo) != 0)
1523 debugState = BREAK;
1524 }
1525 }
1526 }
1527 if ((warrior[curWarrior].offset < 0) ||
1528 (warrior[curWarrior].offset >= warrior[curWarrior].instLen))
1529 errprn(OFSERR, (line_st *) NULL, "");
1530 } else
1531 MEMORYERROR;
1532 else
1533 errprn(ZLNERR, (line_st *) NULL, "");
1534 } else
1535 errprn(EXXERR, (line_st *) NULL, "");
1536 }
1537
1538 /* ******************************************************************* */
1539
1540 #define SNIL 0
1541 #define SLBL 1
1542 #define SVAL 2
1543 #define SCOM 3
1544 #define SPSE 4
1545 #define SFOR 5
1546 #define SROF 6
1547 #define SERR -1
1548
1549 /* ******************************************************************* */
1550
1551 static int
blkfor(expr,dest)1552 blkfor(expr, dest)
1553 char *expr, *dest;
1554 {
1555 int evalerr;
1556 line_st *cline;
1557 long result;
1558 ref_st *atbl, *ptbl;
1559 grp_st *forSymGr;
1560
1561 if (symtbl) {
1562 forSymGr = addsym(symtbl->symn, NULL);
1563 if (symtbl->nextsym) {
1564 newtbl();
1565 reftbl->reftype = RLABEL;
1566 reftbl->grpsym = symtbl->nextsym;
1567 reftbl->value = line;
1568 }
1569 symtbl = NULL;
1570 symnum = 0;
1571 } else
1572 forSymGr = NULL;
1573
1574 *dest = '\0';
1575 trav2(expr, dest, SVAL);
1576
1577 if (SWITCH_V) {
1578 sprintf(outs, currentFORMsg, dest);
1579 textout(outs);
1580 }
1581 if ((evalerr = eval_expr(dest, &result)) < OK_EXPR) {
1582 if (evalerr == DIV_ZERO)
1583 errprn(DIVERR, aline, "");
1584 else
1585 errprn(EVLERR, aline, "");
1586 } else if (result <= 0L) {
1587 if (evalerr == OVERFLOW)
1588 errprn(OFLERR, aline, "");
1589 statefine++;
1590 } else {
1591 if (evalerr == OVERFLOW)
1592 errprn(OFLERR, aline, "");
1593
1594 newtbl();
1595 reftbl->reftype = RSTACK;
1596 reftbl->grpsym = forSymGr;
1597 reftbl->visit = 1;
1598 atbl = reftbl;
1599
1600 cline = aline;
1601 for (atbl->value = 1; vcont && atbl->value <= (uShrt) result && aline;
1602 atbl->value++)
1603 for (aline = cline; vcont;)
1604 if (aline->nextline) {
1605 int r;
1606
1607 aline = aline->nextline;
1608 *dest = '\0';
1609 if ((r = trav2(aline->vline, dest, SNIL)) == SROF)
1610 break;
1611 else if (r == SCOM) {
1612 addline(dest, aline->linesrc, dspnt);
1613 if (dbginfo == 3)
1614 dbginfo = 0;
1615 }
1616 } else {
1617 errprn(ROFERR, (line_st *) NULL, "");
1618 vcont = FALSE;
1619 }
1620
1621 for (ptbl = NULL, atbl = reftbl; atbl; ptbl = atbl, atbl = atbl->nextref)
1622 if (atbl->reftype == RSTACK)
1623 break;
1624
1625 if (ptbl)
1626 ptbl->nextref = atbl->nextref;
1627 else
1628 reftbl = atbl->nextref;
1629
1630 disposetbl(atbl, atbl->nextref);
1631 }
1632
1633 return SFOR;
1634 }
1635
1636 /* ******************************************************************* */
1637
1638 static int
equtbl(expr)1639 equtbl(expr)
1640 char *expr;
1641 {
1642 line_st *cline, *pline = NULL;
1643 uChar i;
1644
1645 if (symtbl) {
1646
1647 newtbl();
1648 reftbl->reftype = RTEXT;
1649 reftbl->grpsym = symtbl;
1650 symtbl = NULL;
1651 symnum = 0;
1652
1653 if (((cline = (line_st *) MALLOC(sizeof(line_st))) != NULL) &&
1654 ((cline->vline = pstrdup(expr)) != NULL)) {
1655 cline->linesrc = aline->linesrc;
1656 cline->nextline = NULL;
1657 pline = reftbl->sline = cline;
1658 } else
1659 MEMORYERROR;
1660
1661 while (aline->nextline) {
1662
1663 i = 0;
1664 get_token(aline->nextline->vline, &i, token);
1665 to_upper(token);
1666 if (strcmp(token, "EQU") == 0) {
1667 aline = aline->nextline;
1668
1669 if (((cline = (line_st *) MALLOC(sizeof(line_st))) != NULL) &&
1670 ((cline->vline = pstrdup((char *) aline->vline + i)) != NULL)) {
1671 cline->linesrc = aline->linesrc;
1672 cline->nextline = NULL;
1673 pline = pline->nextline = cline;
1674 } else
1675 MEMORYERROR;
1676 }
1677 #ifndef SERVER
1678 else if (*token == com_sym) {
1679 aline = aline->nextline;
1680 lineswitch(aline->vline, i, aline);
1681 }
1682 #endif
1683 else
1684 break;
1685 }
1686 } else
1687 errprn(ANNERR, aline, "");
1688
1689 return SVAL;
1690 }
1691
1692 /* ******************************************************************* */
1693
1694 static int
equsub(expr,dest,wdecl,tbl)1695 equsub(expr, dest, wdecl, tbl)
1696 char *expr, *dest;
1697 int wdecl;
1698 ref_st *tbl;
1699 {
1700 line_st *cline;
1701
1702 tbl->visit = 1;
1703 cline = aline;
1704 aline = tbl->sline;
1705 wdecl = trav2(aline->vline, dest, wdecl);
1706
1707 while (aline->nextline && vcont) {
1708 if (statefine == 0)
1709 if (wdecl == SCOM) {
1710 addline(dest, aline->linesrc, dspnt);
1711 if (dbginfo == 3)
1712 dbginfo = 0;
1713 }
1714 aline = aline->nextline;
1715 *dest = '\0';
1716 wdecl = trav2(aline->vline, dest, SNIL);
1717 }
1718
1719 aline = cline;
1720 if (isspace(*expr))
1721 concat(dest, " ");
1722
1723 tbl->visit = 0;
1724 return trav2(expr, dest, wdecl);
1725 }
1726
1727 /* ******************************************************************* */
1728
1729 /* recursively traverse the buffer */
1730 /* buf[] has to be "" */
1731 static int
trav2(buffer,dest,wdecl)1732 trav2(buffer, dest, wdecl)
1733 char *buffer, *dest;
1734 int wdecl;
1735 {
1736 int evalerr;
1737 uChar idxp = 0;
1738 ref_st *tbl;
1739
1740 switch (get_token(buffer, &idxp, token)) {
1741
1742 case NONE:
1743 return wdecl;
1744
1745 case COMMTOKEN:
1746 if ((wdecl == SNIL) && (statefine == 0)) {
1747
1748 uChar idx;
1749
1750 idx = idxp;
1751 get_token(buffer, &idx, token);
1752 to_upper(token);
1753 if (strcmp(token, "ASSERT") == 0) {
1754 long result;
1755
1756 trav2((char *) buffer + idx, dest, SVAL);
1757
1758 if (SWITCH_V) {
1759 sprintf(outs, currentAssertMsg, dest);
1760 textout(outs);
1761 }
1762 if ((evalerr = eval_expr(dest, &result)) < OK_EXPR)
1763 errprn(BASERR, aline, "");
1764 else {
1765 if (evalerr == OVERFLOW)
1766 errprn(OFLERR, aline, "");
1767 noassert = FALSE;
1768 if (result == 0L)
1769 errprn(CHKERR, aline, "");
1770 }
1771 }
1772 #ifndef SERVER
1773 else
1774 lineswitch(buffer, idxp, aline);
1775 #endif
1776 }
1777 return wdecl;
1778
1779 case CHARTOKEN:
1780
1781 strcpy(buf, token);
1782 to_upper(buf);
1783
1784 if (strcmp(buf, "ROF") == 0)
1785 if (statefine)
1786 statefine--;
1787 else if (wdecl <= SLBL)
1788 return SROF;
1789 else
1790 errprn(APPERR, aline, token);
1791
1792 else if (strcmp(buf, "FOR") == 0)
1793 if (statefine)
1794 statefine++;
1795 else if (wdecl <= SLBL)
1796 return blkfor((char *) buffer + idxp, dest);
1797 else
1798 errprn(APPERR, aline, token);
1799
1800 else if (strcmp(token, "CURLINE") == 0)
1801 if (statefine)
1802 return SNIL;
1803 else if (wdecl > SLBL) {
1804 sprintf(buf, "%d", line);
1805 if (isspace(buffer[idxp]))
1806 concat(buf, " ");
1807 if (concat(dest, buf))
1808 return (trav2((char *) buffer + idxp, dest, wdecl));
1809 else
1810 errprn(BUFERR, aline, "");
1811 } else
1812 errprn(MISC, aline, CURLINEErr);
1813
1814 else if (strcmp(buf, "EQU") == 0)
1815 if (statefine)
1816 return SNIL;
1817 else if (wdecl <= SLBL)
1818 return equtbl((char *) buffer + idxp);
1819 else
1820 errprn(APPERR, aline, token);
1821
1822 else if ((opcode = str_in_set(buf, opname)) < EQUOP)
1823 if (statefine)
1824 return SNIL;
1825
1826 else if (wdecl <= SLBL) {
1827
1828 uChar j, op;
1829
1830 for (j = 0; buf[j]; j++);
1831
1832 while (buffer[idxp] && !isspace(buffer[idxp]))
1833 buf[j++] = buffer[idxp++];
1834
1835 if (isspace(buffer[idxp])) {
1836 buf[j++] = ' ';
1837 buf[j] = '\0';
1838 }
1839 if (!concat(dest, buf))
1840 errprn(BUFERR, aline, "");
1841
1842 else {
1843 op = opcode;
1844 if ((wdecl = trav2((char *) buffer + idxp, dest,
1845 op < OPNUM ? SVAL : SPSE)) != SERR) {
1846
1847 if (symtbl) {
1848 newtbl();
1849 reftbl->reftype = RLABEL;
1850 reftbl->value = line;
1851 reftbl->grpsym = symtbl;
1852 symtbl = NULL;
1853 symnum = 0;
1854 }
1855 if (op < OPNUM) {
1856 line++;
1857 if (dbginfo == 2)
1858 dbginfo++;
1859 } else if (op == ENDOP)
1860 vcont = FALSE;
1861
1862 return SCOM;
1863 } else
1864 return SERR;
1865 }
1866 } else
1867 errprn(APPERR, aline, token);
1868
1869 else if (statefine == 0) {
1870
1871 char tmp = 1;
1872
1873 while ((buffer[idxp] == cat_sym) && (isalpha(buffer[idxp + 1])) &&
1874 (idxp++, get_token(buffer, &idxp, buf) == CHARTOKEN) && tmp)
1875 if (((tbl = lookup(buf)) != NULL) && (tbl->reftype == RSTACK)) {
1876 sprintf(buf, "%02u", (unsigned int) tbl->value);
1877 if (!concat(token, buf))
1878 errprn(BUFERR, aline, "");
1879 } else {
1880 errprn(CATERR, aline, buf);
1881 tmp = 0;
1882 }
1883
1884 if ((tbl = lookup(token)) != NULL)
1885 if (tbl->reftype == RTEXT)
1886 if (tbl->visit)
1887 errprn(RECERR, aline, token);
1888 else
1889 return equsub((char *) buffer + idxp, dest, wdecl, tbl);
1890
1891 else if (wdecl > SLBL) {
1892 if (tbl->reftype == RSTACK)
1893 sprintf(buf, "%02u", (unsigned int) tbl->value);
1894 else if (wdecl == SPSE)
1895 sprintf(buf, "%d", tbl->value); /* absolute value */
1896 else
1897 sprintf(buf, "%d", tbl->value - line); /* relative value */
1898
1899 if (isspace(buffer[idxp]))
1900 concat(buf, " ");
1901
1902 if (concat(dest, buf))
1903 return (trav2((char *) buffer + idxp, dest, wdecl));
1904 else
1905 errprn(BUFERR, aline, "");
1906 } else
1907 errprn(IDNERR, aline, token);
1908
1909 else if (wdecl <= SLBL) {
1910 if (symnum < GRPMAX) {
1911 symtbl = addsym(token, symtbl);
1912 symnum++;
1913 } else
1914 errprn(GRPERR, aline, token);
1915
1916 if (buffer[idxp] == cln_sym) /* ignore a colon after a line-label */
1917 idxp++;
1918
1919 /* traverse the rest of buffer */
1920 return trav2((char *) buffer + idxp, dest, SLBL);
1921 } else {
1922 if (isspace(buffer[idxp]))
1923 concat(token, " ");
1924 if (concat(dest, token))
1925 return (trav2((char *) buffer + idxp, dest, wdecl));
1926 else
1927 errprn(BUFERR, aline, "");
1928 }
1929 } else
1930 return trav2((char *) buffer + idxp, dest, SNIL);
1931 break;
1932 default:
1933 if (statefine)
1934 return SNIL;
1935 else if (wdecl <= SLBL)
1936 errprn(TOKERR, aline, token);
1937 else {
1938 if (concat(dest, token))
1939 return trav2((char *) buffer + idxp, dest, wdecl);
1940 else
1941 errprn(BUFERR, aline, "");
1942 }
1943 }
1944 return SERR;
1945 }
1946
1947 /* ******************************************************************* */
1948
1949 /* collect and expand equ */
1950 static void
expand(sspnt)1951 expand(sspnt)
1952 uShrt sspnt;
1953 {
1954 dspnt = 1 - sspnt;
1955 disposeline(sline[dspnt]);
1956 sline[dspnt] = NULL;
1957
1958 vcont = TRUE;
1959 statefine = 0;
1960 linemax = (uShrt) instrLim + LEXCMAX;
1961
1962 aline = sline[sspnt];
1963 while (aline && vcont) {
1964 buf2[0] = '\0';
1965 switch (trav2(aline->vline, buf2, SNIL)) {
1966 case SCOM:
1967 addline(buf2, aline->linesrc, dspnt);
1968 if (dbginfo == 3)
1969 dbginfo = 0;
1970 break;
1971 case SFOR:
1972 break;
1973 case SROF:
1974 errprn(FORERR, aline, "");
1975 }
1976 aline = aline->nextline;
1977 }
1978 }
1979
1980 /* ******************************************************************* */
1981
1982 int
parse(expr,cell,loc)1983 parse(expr, cell, loc)
1984 char *expr;
1985 mem_struct *cell;
1986 ADDR_T loc;
1987 {
1988 int evalerrA, evalerrB;
1989 long resultA, resultB;
1990 mem_struct tmp;
1991 ADDR_T dloc;
1992 uChar i = 0;
1993 uShrt sspnt = 0;
1994
1995 errnum = warnum = 0;
1996 ierr = 0;
1997 aline = NULL;
1998 dloc = loc;
1999 switch (get_token(expr, &i, token)) {
2000 case CHARTOKEN:
2001 nocmnt(expr);
2002 addline(expr, addlinesrc(expr, (uShrt) loc), sspnt);
2003 break;
2004 case COMMTOKEN:
2005 globalswitch(expr, (uShrt) i, (uShrt) loc, sspnt);
2006 break;
2007 default:
2008 errprn(TOKERR, aline, token);
2009 }
2010
2011 line = (uShrt) dloc;
2012 expand(sspnt);
2013 disposeline(sline[sspnt]);
2014 sline[sspnt] = NULL;
2015 sspnt = 1 - sspnt;
2016
2017 for (aline = sline[sspnt], line = (uShrt) loc; aline;
2018 aline = aline->nextline) {
2019 dfashell(aline->vline, &tmp);
2020 if (errnum == 0)
2021 if (opcode < OPNUM)
2022 if ((evalerrA = eval_expr(A_expr, &resultA)) < OK_EXPR) {
2023 if (evalerrA == DIV_ZERO)
2024 errprn(DIVERR, aline, "");
2025 else
2026 errprn(EVLERR, aline, "");
2027 } else if ((evalerrB = eval_expr(B_expr, &resultB)) < OK_EXPR) {
2028 if (evalerrB == DIV_ZERO)
2029 errprn(DIVERR, aline, "");
2030 else
2031 errprn(EVLERR, aline, "");
2032 } else {
2033 if (evalerrA == OVERFLOW || evalerrB == OVERFLOW)
2034 errprn(OFLERR, aline, "");
2035 cell->opcode = tmp.opcode;
2036 cell->A_mode = tmp.A_mode;
2037 cell->B_mode = tmp.B_mode;
2038 cell->A_value = (ADDR_T) normalize(resultA);
2039 cell->B_value = (ADDR_T) normalize(resultB);
2040 if ((cell->debuginfo = (dbginfo ? TRUE : FALSE)) != FALSE)
2041 debugState = BREAK;
2042 cell++, line++;
2043 if (++dloc >= coreSize) {
2044 dloc -= coreSize;
2045 cell -= coreSize;
2046 }
2047 }
2048 }
2049 disposeline(sline[0]);
2050 disposeline(sline[1]);
2051 sline[0] = sline[1] = NULL;
2052
2053 while (srctbl) {
2054 src_st *tmp;
2055
2056 tmp = srctbl;
2057 srctbl = srctbl->nextsrc;
2058 FREE(tmp->src);
2059 FREE(tmp);
2060 }
2061
2062 if (dloc < loc)
2063 dloc = coreSize - loc + dloc;
2064 else
2065 dloc -= loc;
2066
2067 if (errnum)
2068 return (-1);
2069 else
2070 return (dloc);
2071 }
2072
2073 /* ******************************************************************* */
2074
2075 static char stdinstart = 0;
2076
2077 int
assemble(fName,aWarrior)2078 assemble(fName, aWarrior)
2079 char *fName;
2080 int aWarrior;
2081 {
2082 FILE *infp;
2083 uChar cont = TRUE, conLine = FALSE, i;
2084 uShrt lines; /* logical and physical lines */
2085 uShrt spnt = 0; /* index/pointer to sline and lline */
2086
2087 #ifdef VMS
2088 char DIAfilename[256], *temp;
2089 #endif
2090
2091 #ifdef ASM_DEBUG
2092 printf("Entering assemble sub\n");
2093 #endif
2094
2095 errorlevel = WARNING;
2096 errorcode = SUCCESS;
2097 *errmsg = '\0';
2098 errnum = warnum = 0;
2099
2100 pass = 0;
2101
2102 srctbl = NULL;
2103 sline[0] = sline[1] = NULL;
2104 reftbl = NULL;
2105 symtbl = NULL;
2106 symnum = 0;
2107
2108 lines = 0;
2109 ierr = 0;
2110
2111 if ((errkeep = (err_st *) MALLOC(sizeof(err_st) * ERRMAX)) == NULL)
2112 MEMORYERROR;
2113
2114 curWarrior = aWarrior;
2115 warrior[curWarrior].name = pstrdup(unknown);
2116 warrior[curWarrior].authorName = pstrdup(anonymous);
2117 warrior[curWarrior].date = pstrdup("");
2118 warrior[curWarrior].version = pstrdup("");
2119 #ifdef PSPACE
2120 warrior[curWarrior].pSpaceIndex = UNSHARED; /* tag */
2121 #endif
2122 /* These two inits turn out to be neccessary */
2123 warrior[curWarrior].instBank = NULL;
2124 warrior[curWarrior].instLen = 0;
2125
2126 #ifdef VMS
2127 if (SWITCH_D) {
2128 temp = strstr(warrior[curWarrior].fileName, "]"); /* Look for dir spec */
2129 if (temp == NULL) {
2130 temp = strstr(warrior[curWarrior].fileName, ":");
2131 if (temp == NULL)
2132 temp = warrior[curWarrior].fileName;
2133 else
2134 temp++; /* Bypass ":" */
2135 } else
2136 temp++; /* bypass "]" */
2137 strcpy(DIAfilename, temp);
2138 temp = strstr(DIAfilename, ".");
2139 if (temp == NULL)
2140 strcat(DIAfilename, ".DIA");
2141 else
2142 strcpy(temp, ".DIA");
2143 printf("%s %s.", Opening, DIAfilename);
2144 dias = fopen(DIAfilename, "w");
2145 fprintf(dias, "%s", StartMod);
2146 }
2147 #endif
2148
2149 dbgproceed = TRUE;
2150 dbginfo = FALSE;
2151 noassert = TRUE;
2152
2153 addpredefs();
2154
2155 #ifdef ASM_DEBUG
2156 printf("Entering file reading module\n");
2157 #endif
2158
2159 if ((*fName == '\0') || (infp = fopen(fName, "r")) != NULL) {
2160
2161 char pstart;
2162
2163 if (*fName == '\0') {
2164 infp = stdin;
2165 pstart = stdinstart;
2166 } else
2167 pstart = 0;
2168
2169 lines = 0;
2170 aline = NULL;
2171
2172 while (cont) {
2173
2174 /*
2175 * Read characters until newline or EOF encountered. newline is
2176 * excluded. Need to be non-strict boolean evaluation
2177 */
2178 *buf = '\0';
2179 i = 0; /* pointer to line buffer start */
2180 do {
2181 if (fgets(buf + i, MAXALLCHAR - i, infp)) {
2182 for (; buf[i]; i++)
2183 if (buf[i] == '\n' || buf[i] == '\r')
2184 break;
2185 buf[i] = 0;
2186 if (buf[i - 1] == '\\') { /* line continued */
2187 conLine = TRUE;
2188 buf[--i] = 0; /* reset */
2189 } else
2190 conLine = FALSE;
2191 } else if (ferror(infp)) {
2192 errprn(DSKERR, (line_st *) NULL, fName);
2193 fclose(infp);
2194 return PARSEERR;
2195 } else
2196 cont = (feof(infp) == 0);
2197 } while (conLine == TRUE);
2198 lines++;
2199 i = 0;
2200
2201 switch (get_token(buf, &i, token)) {
2202 /*
2203 * COMMTOKEN before any non-whitespace chars may contains switches.
2204 * We treat them first and therefore we don't have to save it in
2205 * sline
2206 */
2207 case COMMTOKEN:
2208 if (globalswitch(buf, (uShrt) i, lines, spnt)) /* REDCODE? */
2209 switch (pstart) {
2210 case 0:
2211 disposeline(sline[spnt]);
2212 sline[spnt] = lline[spnt] = NULL;
2213 pstart++;
2214 break;
2215 case 1:
2216 pstart++;
2217 /* fallthru */
2218 case 2:
2219 cont = 0;
2220 break;
2221 }
2222 break;
2223 #if 0 /* no longer scanning for END, ;redcode req'd
2224 * between warriors in stdin */
2225 case CHARTOKEN:
2226 nocmnt(buf);
2227 do {
2228 to_upper(token);
2229 if (strcmp(token, "END") == 0) {
2230 cont = 0;
2231 break;
2232 }
2233 } while (get_token(buf, &i, token) != NONE);
2234 addline(buf, addlinesrc(buf, lines), spnt);
2235 break;
2236 #endif
2237 case NONE:
2238 break;
2239 default:
2240 nocmnt(buf); /* saving some space */
2241 addline(buf, addlinesrc(buf, lines), spnt);
2242 break;
2243 }
2244 }
2245
2246 if (pstart)
2247 pstart--;
2248
2249 if (*fName)
2250 fclose(infp);
2251 else
2252 stdinstart = pstart; /* save value for next stdin reference */
2253
2254 if (SWITCH_V) {
2255 show_info(spnt);
2256 textout(paramCheckMsg);
2257 }
2258 #ifdef ASM_DEBUG
2259 printf("Entering pass 1 (expand and shrink)\n");
2260 #endif
2261
2262 line = 0;
2263 expand(spnt);
2264
2265 if (symtbl) {
2266 grp_st *tmp;
2267
2268 *buf = '\0';
2269 for (tmp = symtbl; tmp; tmp = tmp->nextsym) {
2270 if (*buf)
2271 if (!concat(buf, " "))
2272 break;
2273 if (!concat(buf, tmp->symn))
2274 break;
2275 }
2276
2277 errprn(DLBERR, (line_st *) NULL, buf);
2278 disposegrp(symtbl); /* discount any symtbl with empty reference */
2279 symtbl = NULL;
2280 symnum = 0;
2281 }
2282 spnt = 1 - spnt;
2283 pass++;
2284
2285 if (noassert)
2286 errprn(NASERR, (line_st *) NULL, "");
2287
2288 if (SWITCH_V) {
2289 textout("\n");
2290 show_info(spnt);
2291 show_lbl();
2292 }
2293 #ifdef ASM_DEBUG
2294 printf("Entering pass 2 (parsing and loading)\n");
2295 #endif
2296 encode(spnt);
2297
2298 dbginfo = FALSE;
2299 dbgproceed = TRUE;
2300
2301 #ifdef ASM_DEBUG
2302 printf("Disclaiming all temporary storage\n");
2303 #endif
2304 /* release all allocated memory */
2305 cleanmem();
2306 while (srctbl) {
2307 src_st *tmp;
2308
2309 tmp = srctbl;
2310 srctbl = srctbl->nextsrc;
2311 FREE(tmp->src);
2312 FREE(tmp);
2313 }
2314
2315 /* leave it for cdb() */
2316 addpredefs();
2317
2318 if (errnum) {
2319 FREE(warrior[curWarrior].instBank);
2320 warrior[curWarrior].instBank = NULL;
2321 warrior[curWarrior].instLen = 0;
2322 }
2323 #ifndef SERVER
2324 if (errnum + warnum) {
2325 if (*warrior[curWarrior].fileName)
2326 sprintf(outs, "\nSource: filename '%s'\n", warrior[curWarrior].fileName);
2327 else
2328 sprintf(outs, "\nSource: standard input (%s by %s)\n",
2329 warrior[curWarrior].name, warrior[curWarrior].authorName);
2330 textout(outs);
2331 }
2332 #endif
2333 if (errnum) {
2334 sprintf(outs, errNumMsg, errnum);
2335 textout(outs);
2336 }
2337 if (warnum) {
2338 sprintf(outs, warNumMsg, warnum);
2339 textout(outs);
2340 }
2341 while (ierr)
2342 if (errkeep[--ierr].num > 1) {
2343 sprintf(outs, duplicateMsg, errkeep[ierr].loc, errkeep[ierr].num);
2344 textout(outs);
2345 }
2346 if (errnum + warnum) {
2347 sprintf(outs, "\n");
2348 textout(outs);
2349 }
2350 } else
2351 errprn(FNFERR, (line_st *) NULL, fName);
2352
2353 if (errnum)
2354 errorcode = PARSEERR;
2355 else
2356 errorcode = SUCCESS;
2357
2358 reset_regs();
2359 #ifdef VMS
2360 if (SWITCH_D) {
2361 fprintf(dias, "%s", EndMod);
2362 fclose(dias);
2363 }
2364 #endif
2365 return (errorcode);
2366 }
2367