static void relocateX86_64(struct elf_obj *elfobj, void *(*find_sym)(void *context, char const *name), void *context, struct elf_sec *reltab, unsigned char *text) { int idx, i, reltab_size; struct elf_sym *symtab, *sym_entry; ELF_RELOC *rel_tablep, *rel_entry; int32_t *inst, P, A, S; idx = -1; get_idxorname(elfobj, ".symtab", &idx); if (idx < 0) { HSA_DEBUG_LOG(".symtab can't find.\n"); isfailed = 1; return; } symtab = (struct elf_sym *)(elfobj->sec_tablep[idx].buf); reltab_size = (int)(unsigned long)reltab->extra; rel_tablep = (ELF_RELOC *)reltab->buf; for (i = 0; i < reltab_size; i++) { rel_entry = &rel_tablep[i]; sym_entry = &symtab[ELF_R_SYM(rel_entry->r_info)]; inst = (int32_t *)&(text[rel_entry->r_offset]); P = (int32_t)(int64_t)inst; A = (int32_t)(int64_t)rel_entry->r_addend; S = (int32_t)(int64_t)get_symety_addr(elfobj, sym_entry, 1); if (0 == S) { S = (int64_t)find_sym(context, get_symname(elfobj, sym_entry)); /* zdguo: set the S to the symbol entry struct for optimization */ } switch (ELF_R_TYPE(rel_entry->r_info)) { case R_X86_64_64: *inst = (S+A); break; case R_X86_64_PC32: *inst = (S+A-P); break; case R_X86_64_32: case R_X86_64_32S: *inst = (S+A); break; default: HSA_DEBUG_LOG("Not implemented relocation type.\n"); isfailed = 1; break; } } return; }
void list_for(char *var, statement *stmt) { char *tmp1 = 0, *tmp2 = 0, *tmp3 = 0; mysprintf(var, "%s=", get_symname(stmt->metalist[1].shortarg)); simplifylist(var, stmt, 2, stmt->metapos); if (outcount == 3) { tmp3 = listpop(); tmp2 = listpop(); tmp1 = listpop(); } else { tmp2 = listpop(); tmp1 = listpop(); } mysprintf(var, "%s TO %s", tmp1, tmp2); if (tmp3) mysprintf(var, " STEP %s", tmp3); }
struct token * lr_token (struct linereader *lr, const struct charmap_t *charmap, struct localedef_t *locale, const struct repertoire_t *repertoire, int verbose) { int ch; while (1) { do { ch = lr_getc (lr); if (ch == EOF) { lr->token.tok = tok_eof; return &lr->token; }; if (ch == '\n') { lr->token.tok = tok_eol; return &lr->token; } } while (isspace (ch)); if (ch != lr->comment_char) break; /* Is there an newline at the end of the buffer? */ if (lr->buf[lr->bufact - 1] != '\n') { /* No. Some people want this to mean that only the line in the file not the logical, concatenated line is ignored. Let's try this. */ lr->idx = lr->bufact; continue; } /* Ignore rest of line. */ lr_ignore_rest (lr, 0); lr->token.tok = tok_eol; return &lr->token; } /* Match escape sequences. */ if (ch == lr->escape_char) return get_toplvl_escape (lr); /* Match ellipsis. */ if (ch == '.') { if (strncmp (&lr->buf[lr->idx], "...(2)....", 10) == 0) { int cnt; for (cnt = 0; cnt < 10; ++cnt) lr_getc (lr); lr->token.tok = tok_ellipsis4_2; return &lr->token; } if (strncmp (&lr->buf[lr->idx], "...", 3) == 0) { lr_getc (lr); lr_getc (lr); lr_getc (lr); lr->token.tok = tok_ellipsis4; return &lr->token; } if (strncmp (&lr->buf[lr->idx], "..", 2) == 0) { lr_getc (lr); lr_getc (lr); lr->token.tok = tok_ellipsis3; return &lr->token; } if (strncmp (&lr->buf[lr->idx], ".(2)..", 6) == 0) { int cnt; for (cnt = 0; cnt < 6; ++cnt) lr_getc (lr); lr->token.tok = tok_ellipsis2_2; return &lr->token; } if (lr->buf[lr->idx] == '.') { lr_getc (lr); lr->token.tok = tok_ellipsis2; return &lr->token; } } switch (ch) { case '<': return get_symname (lr); case '0' ... '9': lr->token.tok = tok_number; lr->token.val.num = ch - '0'; while (isdigit (ch = lr_getc (lr))) { lr->token.val.num *= 10; lr->token.val.num += ch - '0'; } if (isalpha (ch)) lr_error (lr, _("garbage at end of number")); lr_ungetn (lr, 1); return &lr->token; case ';': lr->token.tok = tok_semicolon; return &lr->token; case ',': lr->token.tok = tok_comma; return &lr->token; case '(': lr->token.tok = tok_open_brace; return &lr->token; case ')': lr->token.tok = tok_close_brace; return &lr->token; case '"': return get_string (lr, charmap, locale, repertoire, verbose); case '-': ch = lr_getc (lr); if (ch == '1') { lr->token.tok = tok_minus1; return &lr->token; } lr_ungetn (lr, 2); break; } return get_ident (lr); }
/** * @brief Match a function in a symbol table. * @param sect Section pointer for symbol table. * @param num Element number. * @param preg Reguler expression to use. * @param func_list Function table. * @param count Counter pointer (from the table). * @param get_symname Function ptr to get symbol name. * @return Success (0) or Error (-1). */ static int trace_match_symtab(elfshsect_t *sect, int num, regex_t *preg, char ***func_list, u_int *count, char *(*get_symname)(elfshobj_t *f, elfsh_Sym *s)) { u_int index; elfsh_Sym *table; char *name; char **f_list; u_int cnum; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Check argument before anything */ if (!sect || !preg || !func_list || !count || !get_symname) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid parameters", -1); f_list = *func_list; cnum = *count; table = (elfsh_Sym *) (sect->shdr->sh_addr ? elfsh_readmem(sect) : sect->data); /* Parse every function */ for (index = 0; index < num; index++) { /* Only functions */ if (elfsh_get_symbol_type(table + index) != STT_FUNC || table[index].st_value == 0) continue; name = get_symname(sect->parent, table + index); /* Check if this name is valid */ if (name == NULL || *name == 0) continue; /* We match a function */ if (regexec(preg, name, 0, 0, 0) == 0) { /* Do we need to realloc ? */ if (((cnum+1) % TRACE_MATCH_ALLOCSTEP) == 0) { XREALLOC(__FILE__, __FUNCTION__, __LINE__, f_list, f_list, sizeof(char*) * (cnum + 1 + TRACE_MATCH_ALLOCSTEP), -1); /* Blank new elements */ memset(&f_list[cnum], 0x00, TRACE_MATCH_ALLOCSTEP*sizeof(char*)); /* Update the pointer, data can move during a reallocation */ *func_list = f_list; } /* Add the function in the table */ f_list[cnum] = name; *count = ++cnum; } } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
void listline(char *var, statement *stmt, byte showline) { int x; outcount = 0; if (stmt->errorflag) { mysprintf(var, "*ERR "); for (x=0; x<tokenpos; x++) mysprintf(var, " "); mysprintf(var, "V\n"); } if (showline) mysprintf(var, "%.5d ", stmt->linenum); if (stmt->errorflag) { mysprintf(var, "%s", stmt->metalist[1].stringarg); return; } if (stmt->numlabels) { for (x=0; x<stmt->numlabels; x++) mysprintf(var, "%s: ", get_labelname(stmt->labelset[x]->labelnum)); } mysprintf(var, "%s ", get_opname(stmt->opcode)); switch(stmt->opcode) { case CMD_DEFFN: list_deffn(var, stmt); break; case CMD_REM: mysprintf(var, "%s", stmt->metalist[1].stringarg); break; case CMD_IF: list_if(var, stmt); break; case CMD_LET: list_let(var, stmt); break; case CMD_SETESC: case CMD_SETERR: case CMD_GOTO: case CMD_GOSUB: if (stmt->metalist[1].operation == LABELREF) mysprintf(var, "%s", get_labelname(stmt->metalist[1].shortarg)); else mysprintf(var, "%.5d", stmt->metalist[1].shortarg); break; case CMD_FOR: list_for(var, stmt); break; case CMD_NEXT: mysprintf(var, "%s", get_symname(stmt->metalist[1].shortarg)); break; case CMD_LIST: case CMD_DELETE: if (stmt->metapos == 1) mysprintf(var, "00001, 65534"); else if (stmt->metapos == 2) mysprintf(var, "%.5d", flt2int(stmt->metalist[1].floatarg)); else mysprintf(var, "%.5d, %.5d", flt2int(stmt->metalist[1].floatarg), flt2int(stmt->metalist[3].floatarg)); break; case CMD_RETURN: case CMD_WEND: case CMD_RETRY: case CMD_SETERRON: case CMD_SETERROFF: break; case CMD_ON: list_on(var, stmt); break; default: if (stmt->metapos == 1) break; simplifylist(var, stmt, 0, stmt->metapos); mysprintf(var, "%s", listpop()); break; } }
void simplifylist(char *var, statement *stmt, int start, int end) { int y = 0, channels = 0; char tmp[MAX_STRING_LENGTH], *hex; char *tmp1, *tmp2, *tmp3; char *reorder[32]; int ctr = 0; for (y=start; y<=end; y++) { oppush(0); if (get_sysvarname(stmt->metalist[y].operation)) { sprintf(tmp, "%s", get_sysvarname(stmt->metalist[y].operation)); listpush(tmp); } else if (get_fncname(stmt->metalist[y].operation)) { if ((stmt->metalist[y].operation == OP_AND) || (stmt->metalist[y].operation == OP_OR) || (stmt->metalist[y].operation == OP_XOR)) goto blah; sprintf(tmp, "%s(", get_fncname(stmt->metalist[y].operation)); if (stmt->metalist[y].intarg) { for (ctr=0; ctr<stmt->metalist[y].intarg; ctr++) { reorder[ctr] = SafeMalloc(MAX_STRING_LENGTH); reorder[ctr] = listpop(); } } else { for (ctr=0; ctr<fnctable[get_fnc(get_fncname(stmt->metalist[y]. operation))].numparms; ctr++) { reorder[ctr] = SafeMalloc(MAX_STRING_LENGTH); reorder[ctr] = listpop(); } } for (ctr=ctr-1; ctr>=0; ctr--) { strcat(tmp, reorder[ctr]); if (ctr) strcat(tmp, ","); } strcat(tmp, ")"); listpush(tmp); } else blah: switch(stmt->metalist[y].operation) { case HEXSTRING: hex = SafeMalloc(2+(stmt->metalist[y].intarg*2)); *hex = 0; sprintf(tmp, "$"); for (ctr = 0; ctr < stmt->metalist[y].intarg; ctr++) { sprintf(hex, "%X", stmt->metalist[y].stringarg[ctr]); sprintf(hex, "%c%c", hex[strlen(hex)-2], hex[strlen(hex)-1]); strcat(tmp, hex); } strcat(tmp, "$"); GC_free(hex); listpush(tmp); break; case 0xF5: if (stmt->opcode != CMD_DEFFN) listpush("<BEGINLIST>"); break; case 0xF8: if (stmt->opcode != CMD_DEFFN) { ctr = 0; do { reorder[ctr] = SafeMalloc(MAX_STRING_LENGTH); reorder[ctr] = listpop(); if (!strcmp(reorder[ctr], "<BEGINLIST>")) break; ctr++; } while(1); sprintf(tmp, "%s(", listpop()); for (ctr = ctr-1; ctr >= 0; ctr--) { strcat(tmp, reorder[ctr]); if (ctr) strcat(tmp, ","); } strcat(tmp, ")"); listpush(tmp); } break; case 0x8DC9: listpush(gprog->userfunctions[stmt->metalist[y].shortarg].name); break; case 0xF1: case 0xEC: // workaround, LET handles its own commas if (stmt->opcode != CMD_LET) { sprintf(tmp, "%s,", listpop()); listpush(tmp); for (ctr = 0; ctr < outcount; ctr++) mysprintf(var, "%s", listpop()); } break; case 0xF4F1: if (channels) mysprintf(var, ") "); break; case 0xE1: channels = 1; mysprintf(var, "(%s", listpop()); break; case OP_OPT: case OP_SEP: case OP_SRT: case OP_BNK: case OP_DOM: case OP_END: case OP_IND: case OP_IOL: case OP_ISZ: case OP_KEY: case OP_SIZ: case OP_TBL: case OP_TIM: case OP_ERR: case OP_LEN: case OP_PWD: case OP_ATR: if (channels) mysprintf(var, ", %s=%s", get_symbol(stmt->metalist[y].operation), listpop()); else { sprintf(tmp, "%s, %s=%s", listpop(), get_symbol(stmt->metalist[y].operation), listpop()); listpush(tmp); } break; case LABELREF: sprintf(tmp, "%s", get_labelname(stmt->metalist[y].shortarg)); listpush(tmp); break; case LINEREF: sprintf(tmp, "%.5d", stmt->metalist[y].shortarg); listpush(tmp); break; case MNEMONICREF: sprintf(tmp, "\'%s\'", stmt->metalist[y].stringarg); listpush(tmp); break; case 0xF7: tmp2 = listpop(); sprintf(tmp, "@(%s,%s)", listpop(), tmp2); listpush(tmp); break; case 0xF6: sprintf(tmp, "@(%s)", listpop()); listpush(tmp); break; case FLOAT: sprintf(tmp, "%s", flt2asc(stmt->metalist[y].floatarg)); listpush(tmp); break; case GETVAL_STRINGARRAY: case SETVAL_STRINGARRAY: case GETVAL_STRING: case SETVAL_STRING: ctr = stmt->metalist[y].shortarg; tmp3 = SafeMalloc(MAX_STRING_LENGTH); if (stmt->metalist[y].shortarg & 0x2000) { ctr -= 0x2000; sprintf(tmp3, "(%s)", listpop()); } else if (stmt->metalist[y].shortarg & 0x4000) { ctr -= 0x4000; tmp2 = listpop(); sprintf(tmp3, "(%s,%s)", listpop(), tmp2); } else tmp3 = 0; if (stmt->metalist[y].shortarg & 0x8000) { ctr -= 0x8000; if (stmt->metalist[y].operation == GETVAL_STRINGARRAY || stmt->metalist[y].operation == SETVAL_STRINGARRAY) { tmp1 = listpop(); tmp2 = listpop(); sprintf(tmp, "[%s,%s,%s]", listpop(), tmp2, tmp1); listpush(tmp); } else { sprintf(tmp, "[%s]", listpop()); listpush(tmp); } } else if (stmt->metalist[y].operation == GETVAL_STRINGARRAY || stmt->metalist[y].operation == SETVAL_STRINGARRAY) { tmp1 = listpop(); sprintf(tmp, "[%s,%s]", listpop(), tmp1); listpush(tmp); } else listpush(""); // noarrayref if (tmp3) sprintf(tmp, "%s%s%s", get_symname(ctr), listpop(), tmp3); else sprintf(tmp, "%s%s", get_symname(ctr), listpop()); GC_free(tmp3); if ((stmt->metalist[y].operation == SETVAL_STRING) || (stmt->metalist[y].operation == SETVAL_STRINGARRAY)) { if ((stmt->opcode == CMD_LET) || (stmt->opcode == CMD_FOR)) strcat(tmp, "="); } listpush(tmp); break; case GETVAL_NUMERIC: case SETVAL_NUMERIC: case GETVAL_NUMERICARRAY: case SETVAL_NUMERICARRAY: ctr = stmt->metalist[y].shortarg; if (stmt->metalist[y].shortarg & 0x8000) { ctr -= 0x8000; if (stmt->metalist[y].operation == GETVAL_NUMERICARRAY || stmt->metalist[y].operation == SETVAL_NUMERICARRAY) { tmp1 = listpop(); tmp2 = listpop(); sprintf(tmp, "[%s,%s,%s]", listpop(), tmp2, tmp1); listpush(tmp); } else { sprintf(tmp, "[%s]", listpop()); listpush(tmp); } } else if (stmt->metalist[y].operation == GETVAL_NUMERICARRAY || stmt->metalist[y].operation == SETVAL_NUMERICARRAY) { tmp1 = listpop(); sprintf(tmp, "[%s,%s]", listpop(), tmp1); listpush(tmp); } else listpush(""); // noarrayref sprintf(tmp, "%s%s", get_symname(ctr), listpop()); if (stmt->metalist[y].operation == SETVAL_NUMERIC || stmt->metalist[y].operation == SETVAL_NUMERICARRAY) if ((stmt->opcode == CMD_LET) || (stmt->opcode == CMD_FOR)) strcat(tmp, "="); listpush(tmp); break; case SHORTLITERAL: sprintf(tmp, "\"%s\"", stmt->metalist[y].stringarg); listpush(tmp); break; case OP_NEGATE: sprintf(tmp, "(-%s)", listpop()); listpush(tmp); break; case OP_STRCAT: tmp2 = listpop(); sprintf(tmp, "%s+%s", listpop(), tmp2); listpush(tmp); break; case OP_AND: case OP_XOR: case OP_OR: case OP_LESSTHAN: case OP_GREATTHAN: case OP_NOTEQUAL: case OP_EQUALSCMP: case OP_LTEQ: case OP_GTEQ: case OP_ADD: case OP_SUBTRACT: case OP_MULTIPLY: case OP_DIVIDE: case OP_EXPONENT: oppop(); if (oppop() >= getprec(get_symbol(stmt->metalist[y].operation))) { tmp3 = listpop(); tmp1 = SafeMalloc(strlen(tmp3)+2); sprintf(tmp1, "(%s)", tmp3); } else tmp1 = listpop(); if (oppop() >= getprec(get_symbol(stmt->metalist[y].operation))) { tmp3 = listpop(); tmp2 = SafeMalloc(strlen(tmp3)+2); sprintf(tmp2, "(%s)", tmp3); } else tmp2 = listpop(); oppush(getprec(get_symbol(stmt->metalist[y].operation))); sprintf(tmp, "%s%s%s", tmp2, get_symbol(stmt->metalist[y].operation), tmp1); listpush(tmp); break; } } }
/** * Print the chosen symbol table * @param file * @param sect * @param tab * @param num * @param regx * @param get_symname * @return */ int ds(elfshobj_t *file, elfshsect_t *sect, u_int num, regex_t *regx, char *(*get_symname)(elfshobj_t *f, elfsh_Sym *s)) { elfsh_Sym *table; char *name; char *type; char *bind; u_int typenum; u_int bindnum; u_int foff; u_int index; char *sect_name; char buff[512]; char off[50]; char type_unk[ERESI_MEANING + 1]; char bind_unk[ERESI_MEANING + 1]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sort the table if necessary */ if (world.state.sort != NULL) switch (*world.state.sort) { case ELFSH_SORT_BY_ADDR: table = sect->altdata; break; case ELFSH_SORT_BY_SIZE: table = sect->terdata; break; default: PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unknown sort mode", -1); } /* Avoid reading inexistant memory in the process for .symtab */ else table = (elfsh_Sym *) (sect->shdr->sh_addr ? elfsh_readmem(sect) : sect->data); /* Browse symtab */ for (index = 0; index < num; index++) { /* Retreive names */ typenum = elfsh_get_symbol_type(table + index); bindnum = elfsh_get_symbol_bind(table + index); type = (char *) (typenum > ELFSH_SYMTYPE_MAX ? revm_build_unknown(type_unk, "type", typenum) : elfsh_sym_type[typenum].desc); bind = (char *) (bindnum >= ELFSH_SYMBIND_MAX ? revm_build_unknown(bind_unk, "type", bindnum) : elfsh_sym_bind[bindnum].desc); name = get_symname(world.curjob->curfile, table + index); sect_name = NULL; sect = elfsh_get_parent_section(world.curjob->curfile, table[index].st_value, NULL); if (sect == NULL && table[index].st_shndx) sect = elfsh_get_section_by_index(world.curjob->curfile, table[index].st_shndx, NULL, NULL); if (sect != NULL) sect_name = elfsh_get_section_name(world.curjob->curfile, sect); /* Fixup names */ if (name == NULL || *name == 0) name = ELFSH_NULL_STRING; if (type == NULL || *type == 0) type = ELFSH_NULL_STRING; if (bind == NULL || *bind == 0) bind = ELFSH_NULL_STRING; if (sect_name == NULL) sect_name = ELFSH_NULL_STRING; foff = (!table[index].st_value ? 0 : elfsh_get_foffset_from_vaddr(world.curjob->curfile, table[index].st_value)); if (sect && sect->shdr->sh_addr != table[index].st_value) snprintf(off, sizeof(off), " + %s", revm_colornumber("%u", (u_int) (table[index].st_value - sect->shdr->sh_addr))); else *off = '\0'; /* Different output depending on the quiet flag */ if (!world.state.revm_quiet) { snprintf(buff, sizeof(buff), " %s %s %s %s %s%s " "%s%s %s%s %s%s => %s%s\n", revm_colornumber("[%03u]", index), revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base), revm_colortypestr_fmt("%-8s", type), revm_colorstr_fmt("%-40s", name), revm_colorfieldstr("size:"), revm_colornumber("%010u", elfsh_get_symbol_size(table + index)), revm_colorfieldstr("foffset:"), revm_colornumber("%06u", foff), revm_colorfieldstr("scope:"), revm_colortypestr_fmt("%-6s", bind), revm_colorfieldstr("sctndx:"), revm_colornumber("%02u", elfsh_get_symbol_link(table + index)), revm_colorstr(sect_name), off); } else { snprintf(buff, sizeof(buff), " %s %s %s %s %s%s %s%s %s%-6s\n", revm_colornumber("[%03u]", index), revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base), revm_colortypestr_fmt("%-8s", type), revm_colorstr_fmt("%-15s", name), revm_colorfieldstr("sz:"), revm_colornumber("%06u", elfsh_get_symbol_size(table + index)), revm_colorfieldstr("foff:"), revm_colornumber("%06u", foff), revm_colorfieldstr("scop:"), revm_colortypestr_fmt("%-6s", bind)); } if (regx == NULL || (regx != NULL && regexec(regx, buff, 0, 0, 0) == 0)) { /* If the user ask quit, we just break */ if (revm_output(buff) == -1) break; } revm_endline(); } revm_endline(); revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
// 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); }