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