//The function of decoding the L-command, //if the symbol is already in the symboltable, get the address of it; //if not, adds it into the symboltable void decodeL(char str1[],char code[]) { int i; int address=-1; char number2[17]="0000000000000000"; char *str2=(char*)malloc(strlen(str1)*sizeof(char)); for(i=0;i<(strlen(str1)-1);i++) { str2[i]=str1[i+1]; } str2[i]='\0'; for(i=0;i<symbolsid;i++) { if (strcmp(str2,symbols[i].name)==0) { address=symbols[i].address; } } if(address==-1) { address=symbolsrom; addsymbol(str2,symbolsrom++); } for(i=15;address>0;i--) { if((address%2)==1) number2[i]='1'; address=address/2; } free(str2); strcpy(code,number2); }
//First pass of the str[], change the whole L-command to the symbols' names //then call the addsymbol function void firstpass(char command[], int address) { int i; char *symbol=(char*)malloc(strlen(command)*sizeof(char)); for(i=0;i<(strlen(command)-2);i++) { symbol[i]=command[i+1]; } symbol[i]='\0'; addsymbol(symbol,address); free(symbol); }
/* * Add all exported symbols to the object */ void addexports(void) { int i; for (i = 0; i < HASHSIZE; i += 1) { struct sSymbol *pSym; pSym = tHashedSymbols[i]; while (pSym) { if (pSym->nType & SYMF_EXPORT) addsymbol(pSym); pSym = pSym->pNext; } } }
static void vobj_read(struct GlobalVars *gv,struct LinkFile *lf,uint8_t *data) { struct ObjectUnit *u; int bpb,bpt,nsecs,nsyms,i; struct vobj_symbol *vsymbols = NULL; if (lf->type == ID_LIBARCH) { /* check ar-member for correct format */ vobj_check_ar_type(fff[lf->format],lf->pathname,data); } p = data + 5; /* skip ID and endianess */ bpb = (int)read_number(); /* bits per byte */ if (bpb != 8) { /* bits per byte are not supported */ error(113,lf->pathname,fff[lf->format]->tname,bpb); } bpt = (int)read_number(); /* bytes per taddr */ if (bpt > sizeof(taddr)) { /* n bytes per target-address are not supported */ error(114,lf->pathname,fff[lf->format]->tname,bpt); } skip_string(); /* skip cpu-string */ u = create_objunit(gv,lf,lf->objname); nsecs = (int)read_number(); /* number of sections */ nsyms = (int)read_number(); /* number of symbols */ if (nsyms) { vsymbols = alloc(nsyms * sizeof(struct vobj_symbol)); for (i=0; i<nsyms; i++) read_symbol(&vsymbols[i]); } for (i=1; i<=nsecs; i++) read_section(gv,u,(uint32_t)i,vsymbols,nsyms); /* add relocatable and absolute symbols, ignore unknown symbol-refs */ for (i=0; i<nsyms; i++) { struct vobj_symbol *vs = &vsymbols[i]; struct Section *s = NULL; uint8_t type,bind,info; if (vs->flags & WEAK) bind = SYMB_WEAK; else if (vs->flags & EXPORT) bind = SYMB_GLOBAL; else bind = SYMB_LOCAL; if (vs->flags & COMMON) { type = SYM_COMMON; s = common_section(gv,u); } else if (vs->type == EXPRESSION) { type = SYM_ABS; s = abs_section(u); } else if (vs->type == LABSYM) { type = SYM_RELOC; if (!(s = find_sect_id(u,vs->sec))) { /* a section with this index doesn't exist! */ error(53,lf->pathname,vs->name,lf->objname,vs->sec); } } else if (vs->type == IMPORT) { type = 0; /* ignore unknown symbols */ } else { /* illegal symbol type */ error(116,getobjname(u),fff[lf->format]->tname, vs->type,vs->name,lf->objname); type = 0; } switch (TYPE(vs)) { case TYPE_UNKNOWN: info = SYMI_NOTYPE; break; case TYPE_OBJECT: info = SYMI_OBJECT; break; case TYPE_FUNCTION: info = SYMI_FUNC; break; case TYPE_SECTION: type = 0; break; /* ignore SECTION symbols */ case TYPE_FILE: info = SYMI_FILE; break; default: error(54,lf->pathname,TYPE(vs),vs->name,lf->objname); type = 0; break; } if (type) { if (bind == SYMB_LOCAL) addlocsymbol(gv,s,vs->name,NULL,(lword)vs->val,type,0,info,vs->size); else addsymbol(gv,s,vs->name,NULL,(lword)vs->val, type,0,info,bind,vs->size,TRUE); } } if (nsyms) free(vsymbols); add_objunit(gv,u,TRUE); /* add object unit and fix relocations */ }
/* * Create a new patch (includes the rpn expr) */ void createpatch(ULONG type, struct Expression * expr) { struct Patch *pPatch; UWORD rpndata; UBYTE rpnexpr[2048]; char tzSym[512]; ULONG rpnptr = 0, symptr; pPatch = allocpatch(); pPatch->nType = type; strcpy(pPatch->tzFilename, tzCurrentFileName); pPatch->nLine = nLineNo; pPatch->nOffset = nPC; while ((rpndata = rpn_PopByte(expr)) != 0xDEAD) { switch (rpndata) { case RPN_CONST: rpnexpr[rpnptr++] = RPN_CONST; rpnexpr[rpnptr++] = rpn_PopByte(expr); rpnexpr[rpnptr++] = rpn_PopByte(expr); rpnexpr[rpnptr++] = rpn_PopByte(expr); rpnexpr[rpnptr++] = rpn_PopByte(expr); break; case RPN_SYM: symptr = 0; while ((tzSym[symptr++] = rpn_PopByte(expr)) != 0); if (sym_isConstant(tzSym)) { ULONG value; value = sym_GetConstantValue(tzSym); rpnexpr[rpnptr++] = RPN_CONST; rpnexpr[rpnptr++] = value & 0xFF; rpnexpr[rpnptr++] = value >> 8; rpnexpr[rpnptr++] = value >> 16; rpnexpr[rpnptr++] = value >> 24; } else { struct sSymbol *sym; if ((sym = sym_FindSymbol(tzSym)) == NULL) break; symptr = addsymbol(sym); rpnexpr[rpnptr++] = RPN_SYM; rpnexpr[rpnptr++] = symptr & 0xFF; rpnexpr[rpnptr++] = symptr >> 8; rpnexpr[rpnptr++] = symptr >> 16; rpnexpr[rpnptr++] = symptr >> 24; } break; case RPN_BANK: { struct sSymbol *sym; symptr = 0; while ((tzSym[symptr++] = rpn_PopByte(expr)) != 0); if ((sym = sym_FindSymbol(tzSym)) == NULL) break; symptr = addsymbol(sym); rpnexpr[rpnptr++] = RPN_BANK; rpnexpr[rpnptr++] = symptr & 0xFF; rpnexpr[rpnptr++] = symptr >> 8; rpnexpr[rpnptr++] = symptr >> 16; rpnexpr[rpnptr++] = symptr >> 24; } break; default: rpnexpr[rpnptr++] = rpndata; break; } }
// main entry into parser void encode_rpn() { statement *stmt, *tempstmt = gprog->firststmt; struct labelset *label; unsigned int x = 0, y = 0; int channum = 0, lastfnc = 0, lastvar = 0, ifcount = 0; byte display = 0, watchchannel = 0, special = 0; char *cont; symbol *sym; begin: stmt = SafeMalloc(sizeof(statement)); stmtinit(stmt); for (x=0; x<MAX_STMT_METAS; x++) { stmt->metalist[x].operation = 0; stmt->metalist[x].floatarg.mantisa.i = 0; stmt->metalist[x].floatarg.exp = 0; stmt->metalist[x].shortarg = 0; for (y=0; y<MAX_STRING_LENGTH; y++) stmt->metalist[x].stringarg[y] = 0; } special = 0; foundequals = 0; firstvar = 1; numlabels = 0; envinfo.stmttype = 0; tokenpos = 0; token_type = 1; lastopcode = 0; for (x=0; x<32; x++) { numargs[x] = 0; parenstack[x] = 0; } do { get_token(); tokenpos += strlen(token); if(!checkoption(get_cmdindex(get_opname(stmt->opcode)), token, token_type)) lineerror(stmt, __FILE__, __LINE__); // hack to avoid using runtime system // using runtime system would change the last executed line info. // if ((!strcmp(token, "PBSTEP")) && (token_type == TOK_COMMAND)) // dbg_step(); switch (token_type) { case TOK_ERROR: lineerror(stmt, __FILE__, __LINE__); break; case TOK_COMMAND: lastopcode = get_opcode(token); if (cmdtable[get_cmdindex(token)].options & IO_CHANNEL) watchchannel = 1; else watchchannel = 0; stmt->opcode = get_opcode(token); if (stmt->opcode == CMD_LET) goto loop2; else goto loop; case TOK_NUMBER: stmt->opcode = 0; stmt->linenum = atoi(token); break; default: buffermeta(stmt, token_type, token); goto loop2; } buffermeta(stmt, token_type, token); loop: get_token(); if (checkerr == 2) checkerr = 1; else if (checkerr == 1) { if (token[0] == '=') { if (stmt->metalist[stmt->metapos-2].operation == 0xEC) stmt->metapos-=2; else stmt->metapos--; push("ERR", TOK_OPERATOR); } else if (token[0] == '(') { prog--; stmt->metapos--; strcpy(token, "ERR"); token_type = TOK_FUNCTION; } checkerr = 0; } if (lastopcode == CMD_SETERR) { if (!strcmp(token, "ON")) lastopcode = CMD_SETERRON; if (!strcmp(token, "OFF")) lastopcode = CMD_SETERROFF; } if (!strcmp(token, "RECORD")) { if (stmt->opcode == CMD_READ) lastopcode = CMD_READRECORD; if (stmt->opcode == CMD_WRITE) lastopcode = CMD_WRITERECORD; if (stmt->opcode == CMD_EXTRACT) lastopcode = CMD_EXTRACTRECORD; if (stmt->opcode == CMD_FIND) lastopcode = CMD_FINDRECORD; if (stmt->opcode == CMD_PRINT) lastopcode = CMD_PRINTRECORD; token_type = lasttype; goto loop; } if (lastopcode == CMD_REM) { stmt->metalist[1].operation = 0xF5; tokenpos -= 2; if (input[tokenpos] == '\"') x = tokenpos; else x = tokenpos+2; stmt->metalist[1].shortarg = strlen(input) - x; y = 0; for (x=x; x<strlen(input); x++) { stmt->metalist[1].stringarg[y] = input[x]; y++; } stmt->metalist[1].stringarg[y] = '\0'; stmt->metapos++; if (stmt->linenum) insertstmt(gprog, stmt); return; } tokenpos += strlen(token); if(!checkoption(get_cmdindex(get_opname(lastopcode)), token, token_type)) lineerror(stmt, __FILE__, __LINE__); loop2: switch (token_type) { case TOK_SEMICOLON: popstack(stmt, -1); if (!stmt->linenum) { execline(gprog, stmt); stmtinit(stmt); } break; case TOK_COLON: if ((stmt->metalist[stmt->metapos-1].operation == SETVAL_NUMERIC) || (stmt->metalist[stmt->metapos-1].operation == GETVAL_NUMERIC) || (stmt->metalist[stmt->metapos-1].operation == LABELREF)) { label = SafeMalloc(sizeof(struct labelset)); sym = idx2sym(gprog, stmt->metalist[stmt->metapos-1].shortarg); label->labelnum = addlabel(gprog, sym->name, stmt->linenum); for (x=0; x<MAX_STRING_LENGTH; x++) sym->name[x] = '\0'; x = 0; stmt->metapos--; stmt->metalist[stmt->metapos].shortarg = 0; stmt->opcode = 0; stmt->labelset[stmt->numlabels] = label; stmt->numlabels++; firstvar = 1; } else { do { if (stmt->linenum == tempstmt->linenum) { for (x=0; x<strlen(input); x++) if (input[x] == ':') break; y = x; for (x=0; x<=y; x++) input[x] = ' '; cont = SafeMalloc(1024*64); *cont = 0; listline(cont, tempstmt, 1); strcat(cont, input); *prog = 0; prog = cont; display = 1; goto begin; } tempstmt = tempstmt->nextstmt; } while (tempstmt != NULL); numlabels++; } goto loop; case TOK_COMMA: if (parencount > 0) { // comma being delimiter for system functions popstack(stmt, -2); push("(", TOK_OPERATOR); if (chaninfo == 1) { if (!channum) { channum = 1; stmt->metalist[stmt->metapos].operation = 0xE1; stmt->metapos++; } } else { if (special == 1) numargs[parencount-1]+=10; else numargs[parencount-1]++; envinfo.stmttype = 0; } } else { // comma being delimiter for verbs popstack(stmt, -1); buffermeta(stmt, TOK_COMMA, token); for (x=0; x<32; x++) numargs[x] = 0; envinfo.stmttype = 0; foundequals = 0; firstvar = 1; } goto loop; case TOK_ERROR: lineerror(stmt, __FILE__, __LINE__); return; case TOK_COMMAND: lastopcode = get_opcode(token); if (cmdtable[get_cmdindex(token)].options & IO_CHANNEL) watchchannel = 1; else watchchannel = 0; if (!strcmp(token, "IF")) ifcount++; if (!stmt->opcode) { stmt->opcode = get_opcode(token); envinfo.stmttype = 0; goto loop; } else { popstack(stmt, -1); envinfo.stmttype = 0; if (ifcount > 0) { stmt->metalist[stmt->metapos].operation = 0xE7; stmt->metalist[stmt->metapos].shortarg = 0; stmt->metalist[stmt->metapos].intarg = 0; stmt->metapos++; stmt->length++; // watchchannel = 0; chaninfo = 0; channum = 0; ifcount--; } if (lastopcode == CMD_ON) { special = 1; if (!strcmp(token, "GOTO")) stmt->metalist[stmt->metapos].operation = 0x00F4; else stmt->metalist[stmt->metapos].operation = 0x01F4; stmt->length += 2; stmt->metapos++; } else buffermeta(stmt, TOK_COMMAND, token); goto loop; } break; case TOK_RESERVED: popstack(stmt, -1); envinfo.stmttype = 0; lineref = 0; if (!strcmp(token, "ELSE")) { stmt->metalist[stmt->metapos].operation = 0xE7; stmt->metalist[stmt->metapos].intarg = 0; stmt->metalist[stmt->metapos].shortarg = 0; stmt->metapos++; stmt->metalist[stmt->metapos].operation = 0xE2; stmt->metalist[stmt->metapos].intarg = 0; stmt->metalist[stmt->metapos].shortarg = 0; stmt->metapos++; stmt->length+=2; envinfo.stmttype = 0; chaninfo = 0; channum = 0; } goto loop; case TOK_DONE: if ((stmt->linenum) && (!stmt->opcode)) deletestmt(gprog,stmt->linenum); else { popstack(stmt, -1); if (stmt->opcode == CMD_LET && foundequals == 0) lineerror(stmt, __FILE__, __LINE__); if (parencount > 0 || numlabels < 0) lineerror(stmt, __FILE__, __LINE__); if (stmt->linenum) { if (!stmt->errorflag) insertstmt(gprog, stmt); } else if (stmt->opcode) { if (!stmt->errorflag) { execline(gprog, stmt); } } } if (display) { GC_realloc(cont, strlen(cont)); listprog(gprog, stmt->linenum, stmt->linenum); } return; case TOK_USERFUNCTION: if (lastopcode == CMD_DEFFN) addfunction(gprog, token, stmt->linenum, 1); else addfunction(gprog, token, stmt->linenum, 0); if (token[strlen(token)-1] == '$') parenstack[parencount] = 8; else parenstack[parencount] = 7; buffermeta(stmt, TOK_USERFUNCTION, token); break; case TOK_FUNCTION: lastfnc = get_fnc(token); numlabels++; case TOK_OPERATOR: if (token[0] == '[') { special = 1; cont = get_symname(lastvar); if (cont[strlen(cont)-1] == '$') parenstack[parencount] = 2; else parenstack[parencount] = 1; numlabels++; goto openparen; } else if (token[0] == ']') { numargs[parencount-1] += 9; popstack(stmt, -2); envinfo.stmttype = parenstack[parencount]; token_type = TOK_ARRAY; special = 0; goto loop; } else if (token[0] == '-') { // placeholder if ((lasttype == TOK_OPERATOR) || (lasttype == TOK_RESERVED)) token[0] = '_'; evalstack(stmt); goto loop; } else if (token[0] == '(') { openparen: if (lasttype == TOK_COMMAND) { if (watchchannel == 1) chaninfo = 1; } else if (lasttype == TOK_ARRAY) { envinfo.stmttype = 0; numargs[parencount]++; push(token, token_type); goto loop; } else if (lasttype == TOK_SETVAL) { push(get_symname(lastvar), TOK_SETVAL); stmt->metapos--; stmt->metalist[stmt->metapos].shortarg = 0; numlabels++; cont = get_symname(lastvar); if (cont[strlen(cont)-1] == '$') parenstack[parencount] = 2; else parenstack[parencount] = 1; } else if (lasttype == TOK_VARIABLE) { push(get_symname(lastvar), TOK_VARIABLE); numlabels++; stmt->metapos--; stmt->metalist[stmt->metapos].shortarg = 0; cont = get_symname(lastvar); if (cont[strlen(cont)-1] == '$') parenstack[parencount] = 2; else parenstack[parencount] = 1; } else if (lasttype == TOK_USERFUNCTION) { stmt->metapos--; stmt->metalist[stmt->metapos].operation = 0xF5; stmt->metapos++; stmt->length++; } else if (lasttype == TOK_FUNCTION) { if ((envinfo.stmttype != fnctable[lastfnc].returntype) && (envinfo.stmttype != 0)) lineerror(stmt, __FILE__, __LINE__); else parenstack[parencount] = fnctable[lastfnc].returntype; } else parenstack[parencount] = 1; envinfo.stmttype = 0; numargs[parencount] = 1; push(token, token_type); goto loop; } else if (token[0] == ')') { if (parencount == 0) lineerror(stmt, __FILE__, __LINE__); popstack(stmt, -2); if (parenstack[parencount] == 7) { stmt->metalist[stmt->metapos].operation = 0xF8; stmt->metapos++; stmt->length++; envinfo.stmttype = 1; } else if (parenstack[parencount] == 8) { stmt->metalist[stmt->metapos].operation = 0xF8; stmt->metapos++; stmt->length++; envinfo.stmttype = 2; } else envinfo.stmttype = parenstack[parencount]; if (lastopcode == CMD_DEFFN && foundequals == 0) { stmt->metapos--; stmt->metalist[stmt->metapos].operation = 0xF8; stmt->metapos++; } if (chaninfo == 1) { chaninfo = 0; if (!channum) { stmt->metalist[stmt->metapos].operation = 0xE1; stmt->metapos++; } stmt->metalist[stmt->metapos].operation = 0xF4F1; stmt->metapos++; numargs[parencount] = 0; } goto loop; } else { evalstack(stmt); goto loop; } break; case TOK_VARIABLE: if (get_sysvar(token)) { buffermeta(stmt, TOK_SYSVAR, token); numlabels++; goto loop; } else { addsymbol(gprog, token); lastvar = get_symref(token); } case TOK_NUMBER: default: if(!stmt->opcode) { envinfo.stmttype = 0; lastopcode = stmt->opcode = CMD_LET; } if ((firstvar == 1) && (token_type == TOK_VARIABLE) && (lastopcode == CMD_LET || lastopcode == CMD_FOR || lastopcode == CMD_FOR || lastopcode == CMD_NEXT || lastopcode == CMD_DIM || lastopcode == CMD_INPUT)) { buffermeta(stmt, TOK_SETVAL, token); firstvar = 0; token_type = TOK_SETVAL; } else { numlabels++; buffermeta(stmt, token_type, token); } goto loop; } } while (1); }