void read_input(char *str, int str_size) { char ch; if (NULL == str) { run_error ("Buffer is null in read_string"); return; } if (str_size < 0) { run_error ("Buffer size is null in read_string"); return; } // We assume that get_console_char will "do the right thing" wrt the msg // pump, etc. while ((1 < str_size) && (!force_break)) { ch = get_console_char(); *str = ch; ++str; --str_size; put_console_char(ch); // Read just one line. if (ch == '\n') break; } if (0 < str_size) *str = '\0'; }
PRIVATE void seg_proccheck(struct comal_line *mline, struct comal_line *sline) { struct proc_func_rec *mpf = &mline->lc.pfrec; struct proc_func_rec *spf = &sline->lc.pfrec; struct parm_list *mwalk = mpf->parmroot; struct parm_list *swalk = spf->parmroot; if (mline->cmd != sline->cmd) run_error(EXT_ERR, "PROC/FUNC mismatch in external segment"); if (mpf->id != spf->id) run_error(EXT_ERR, "EXTERNAL PROC/FUNC not in external segment"); if (mpf->closed && !spf->closed) run_error(EXT_ERR, "CLOSED mismatch with PROC/FUNC in external segment"); /* * If the PROC/FUNC definition in the main program does not contain * a parameter list, the the parm check is OK. The external definition * is the correct one. */ if (!mwalk) return; /* * Compare the paremeter lists of the definitions in the main program * and in the external segment. */ while (mwalk && swalk) { if (mwalk->ref != swalk->ref || mwalk->array != swalk->array || mwalk->id->type != swalk->id->type) run_error(EXT_ERR, "Specified parameter list mismatch with external PROC/FUNC definition"); mwalk = mwalk->next; swalk = swalk->next; } /* * If at this point both mwalk and swalk are NULL, the parameter lists in the main * program and the external segment are identical. If not, give an error... */ if ( (mwalk && !swalk) || (swalk && !mwalk) ) run_error(EXT_ERR, "Number of parameters differ in external PROC/FUNC definition"); }
PRIVATE int cmd_cont(struct comal_line *line) { if (curenv->running != HALTED) run_error(CMD_ERR, "CONtinuation not possible"); return contSYM; }
PRIVATE int cmd_load(struct comal_line *line) { char *fn; if (!line->lc.str && !curenv->name) run_error(CMD_ERR, "Missing program name (to LOAD)"); else if (check_changed()) { if (line->lc.str) fn = line->lc.str->s; else { fn = curenv->name; my_printf(MSG_DIALOG, 1, fn); } fn = my_strdup(MISC_POOL, fn); prog_load(fn); curenv->name = fn; prog_structure_scan(); mem_freepool(PARSE_POOL); longjmp(RESTART, JUST_RESTART); } return 0; }
void expand_k_data (int addl_bytes) { int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ int old_size = k_data_top - K_DATA_BOT; int new_size = old_size + delta; BYTE_TYPE *p; if ((addl_bytes < 0) || (new_size > k_data_size_limit)) { error ("Can't expand kernel data segment by %d bytes to %d bytes\n", addl_bytes, new_size); run_error ("Use -lkdata # with # > %d\n", new_size); } k_data_seg = (mem_word *) realloc (k_data_seg, new_size); if (k_data_seg == NULL) fatal_error ("realloc failed in expand_k_data\n"); k_data_seg_b = (BYTE_TYPE *) k_data_seg; k_data_seg_h = (short *) k_data_seg; k_data_top += delta; /* Zero new memory */ for (p = k_data_seg_b + old_size / BYTES_PER_WORD; p < k_data_seg_b + new_size / BYTES_PER_WORD; ) *p ++ = 0; }
void expand_stack (int addl_bytes) { int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ int old_size = STACK_TOP - stack_bot; int new_size = old_size + MAX (delta, old_size); mem_word *new_seg; mem_word *po, *pn; if ((addl_bytes < 0) || (new_size > stack_size_limit)) { error ("Can't expand stack segment by %d bytes to %d bytes\n", addl_bytes, new_size); run_error ("Use -lstack # with # > %d\n", new_size); } new_seg = (mem_word *) xmalloc (new_size); po = stack_seg + (old_size / BYTES_PER_WORD - 1); pn = new_seg + (new_size / BYTES_PER_WORD - 1); for ( ; po >= stack_seg ; ) *pn -- = *po --; for ( ; pn >= new_seg ; ) *pn -- = 0; free (stack_seg); stack_seg = new_seg; stack_seg_b = (BYTE_TYPE *) stack_seg; stack_seg_h = (short *) stack_seg; stack_bot -= (new_size - old_size); }
PRIVATE int cmd_enter(struct comal_line *line) { FILE *yyenter; char tline[MAX_LINELEN]; int stoppen = 0; struct comal_line *aline; yyenter = fopen(line->lc.str->s, "rt"); if (!yyenter) run_error(OPEN_ERR, "File open error: %s", sys_errlist[errno]); setvbuf(yyenter, NULL, _IOFBF, TEXT_BUFSIZE); ++entering; while (!stoppen) { stoppen = (fgets(tline, MAX_LINELEN - 1, yyenter) == NULL); if (stoppen) { if (!feof(yyenter)) run_error(CMD_ERR, "Error when reading ENTER file: %s", sys_errlist[errno]); } else { aline = crunch_line(tline); if (!aline) { my_nl(MSG_DIALOG); my_printf(MSG_DIALOG, 1, "Ignored line: %s", tline); mem_freepool(PARSE_POOL); } else process_comal_line(aline); } } fclose(yyenter); --entering; prog_structure_scan(); return 0; }
PUBLIC void seg_total_scan(struct seg_des *seg) { char errtxt[MAX_LINELEN]; struct comal_line *errline = NULL; if (comal_debug) my_printf(MSG_DEBUG, 1, "External Total scanning..."); if (!scan_scan(seg, errtxt, &errline)) run_error(SCAN_ERR, "SCAN error: %s", errtxt); }
PRIVATE void expand_read() { sqash_hwm = read(sqash_file, sqash_buf, SQASH_BUFSIZE); if (sqash_hwm < 0) { close(sqash_file); run_error(SQASH_ERR, "Error when reading from file: %s", sys_errlist[errno]); } sqash_i = 0; }
PRIVATE void sqash_flush() { if (sqash_i > 0) { if (write(sqash_file, sqash_buf, sqash_i) <= 0) { close(sqash_file); run_error(SQASH_ERR, "Error when writing to file: %s", sys_errlist[errno]); } sqash_i = 0; } }
PRIVATE int cmd_save(struct comal_line *line) { if (!line->lc.str && !curenv->name) run_error(CMD_ERR, "Missing program name (to SAVE)"); else if (!curenv->progroot) run_error(CMD_ERR, "No program (to SAVE)"); else { if (line->lc.str) { if (curenv->name) mem_free(curenv->name); curenv->name = my_strdup(MISC_POOL, line->lc.str->s); } else my_printf(MSG_DIALOG, 1, curenv->name); sqash_2file(curenv->name); curenv->changed = 0; } return 0; }
PUBLIC void sqash_2file(char *fname) { struct comal_line *work = curenv->progroot; char *s; sqash_file = open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE); if (sqash_file < 0) run_error(OPEN_ERR, "File open error: %s", sys_errlist[errno]); sqash_buf = mem_alloc(MISC_POOL, SQASH_BUFSIZE); sqash_i = 0; for (s=SQ_MARKER; *s; s++) sqash_putc(*s); sqash_putc(HOST_OS_CODE); sqash_putstr2(SQ_CONTROL, HOST_OS); sqash_putint(0, SQ_VERSION); sqash_putstr2(SQ_CONTROL, SQ_COPYRIGHT_MSG); while (work) { sqash_horse(work); work = work->ld->next; } sqash_putstr2(SQ_CONTROL, SQ_COPYRIGHT_MSG); sqash_flush(); mem_free(sqash_buf); if (close(sqash_file) < 0) run_error(CLOSE_ERR, "Error closing file: %s", sys_errlist[errno]); }
PRIVATE int cmd_del(struct comal_line *line) { long from = line->lc.twonum.num1; long to = line->lc.twonum.num2; if (from == 0 && to == MAXINT) run_error(CMD_ERR, "Please mention a line number range with DEL"); if (prog_del(&curenv->progroot, from, to, 1)) prog_structure_scan(); return 0; }
PRIVATE void cmd_list_horse(struct string *filename, long from, long to) { char buf[MAX_LINELEN]; char *buf2; FILE *listfile; struct comal_line *work = curenv->progroot; if (filename) { listfile = fopen(filename->s, "wt"); if (!listfile) run_error(OPEN_ERR, "File open error %s", sys_errlist[errno]); setvbuf(listfile, NULL, _IOFBF, TEXT_BUFSIZE); } else { listfile = NULL; sys_setpaged(1); } while (work && work->ld->lineno < from) work = work->ld->next; while (work && work->ld->lineno <= to) { if (sys_escape()) { my_printf(MSG_DIALOG, 1, "Escape"); break; } buf2 = buf; line_list(&buf2, work); if (listfile) fprintf(listfile, "%s\n", buf); else my_printf(MSG_DIALOG, 1, "%s", buf); work = work->ld->next; } if (listfile) fclose(listfile); else sys_setpaged(0); }
void* mem_reference(mem_addr addr) { if ((addr >= TEXT_BOT) && (addr < text_top)) return addr - TEXT_BOT + (char*) text_seg; else if ((addr >= DATA_BOT) && (addr < data_top)) return addr - DATA_BOT + (char*) data_seg; else if ((addr >= stack_bot) && (addr < STACK_TOP)) return addr - stack_bot + (char*) stack_seg; else if ((addr >= K_TEXT_BOT) && (addr < k_text_top)) return addr - K_TEXT_BOT + (char*) k_text_seg; else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) return addr - K_DATA_BOT + (char*) k_data_seg; else { run_error ("Memory address out of bounds\n"); return NULL; } }
PRIVATE int cmd_list(struct comal_line *line) { long from, to; int indent; struct comal_line *curline; if (!line->lc.listrec.id) cmd_list_horse(line->lc.listrec.str, line->lc.listrec.twonum.num1, line->lc.listrec.twonum.num2); else { curline = curenv->progroot; while (curline && !((curline->cmd == procSYM || curline->cmd == funcSYM) && curline->lc.pfrec.id == line->lc.listrec.id)) curline = curline->ld->next; if (!curline) run_error(CMD_ERR, "PROC/FUNC %s not found", line->lc.listrec.id->name); from = curline->ld->lineno; indent = curline->ld->indent; curline = curline->ld->next; while (curline && curline->ld->indent > indent) curline = curline->ld->next; if (curline) to = curline->ld->lineno; else to = MAXINT; cmd_list_horse(line->lc.listrec.str, from, to); } return 0; }
PUBLIC struct comal_line *expand_fromfile(char *fname) { struct comal_line *root; struct comal_line *line; struct comal_line *last = NULL; char *checkstr; char *s; extern int eof(int file); sqash_file = open(fname, O_RDONLY | O_BINARY); if (sqash_file < 0) run_error(OPEN_ERR, "File open error: %s", sys_errlist[errno]); sqash_buf = mem_alloc(MISC_POOL, SQASH_BUFSIZE); sqash_i = MAXUNSIGNED; for (s=SQ_MARKER; *s; s++) if (expand_getc()!=*s) run_error(SQASH_ERR, "Not an OpenComal SAVE file"); if (expand_getc()!=HOST_OS_CODE) run_error(SQASH_ERR, "File not an OpenComal file saved under this OS"); checkstr = expand_getstr2(SQ_CONTROL); if (strcmp(checkstr, HOST_OS) != 0) run_error(SQASH_ERR, "File not an OpenComal file saved under this OS"); mem_free(checkstr); if (expand_getint() != SQ_VERSION) run_error(SQASH_ERR, "File has been saved under a different version of the Sqasher"); checkstr = expand_getstr2(SQ_CONTROL); if (strcmp(checkstr, SQ_COPYRIGHT_MSG) != 0) fatal("Internal sqash/expand error #6"); mem_free(checkstr); while (expand_peekc() == SQ_LINE) { line = expand_horse(); if (last) last->ld->next = line; else root = line; last = line; } checkstr = expand_getstr2(SQ_CONTROL); if (strcmp(checkstr, SQ_COPYRIGHT_MSG) != 0) fatal("Internal sqash/expand error #7"); if (!eof(sqash_file) || sqash_i < sqash_hwm) fatal("Internal sqash/expand error #8"); mem_free(checkstr); mem_free(sqash_buf); if (close(sqash_file) < 0) run_error(CLOSE_ERR, "Error closing file: %s", sys_errlist[errno]); return root; }
int do_syscall () { /* Syscalls for the source-language version of SPIM. These are easier to use than the real syscall and are portable to non-MIPS operating systems. */ switch (R[REG_V0]) { case PRINT_INT_SYSCALL: write_output (console_out, "%d", R[REG_A0]); break; case PRINT_FLOAT_SYSCALL: { float val = FPR_S (REG_FA0); write_output (console_out, "%.8f", val); break; } case PRINT_DOUBLE_SYSCALL: write_output (console_out, "%.18g", FPR[REG_FA0 / 2]); break; case PRINT_STRING_SYSCALL: write_output (console_out, "%s", mem_reference (R[REG_A0])); break; case READ_INT_SYSCALL: { static char str [256]; read_input (str, 256); R[REG_RES] = atol (str); break; } case READ_FLOAT_SYSCALL: { static char str [256]; read_input (str, 256); FPR_S (REG_FRES) = (float) atof (str); break; } case READ_DOUBLE_SYSCALL: { static char str [256]; read_input (str, 256); FPR [REG_FRES] = atof (str); break; } case READ_STRING_SYSCALL: { read_input ( (char *) mem_reference (R[REG_A0]), R[REG_A1]); data_modified = 1; break; } case SBRK_SYSCALL: { mem_addr x = data_top; expand_data (R[REG_A0]); R[REG_RES] = x; data_modified = 1; break; } case PRINT_CHARACTER_SYSCALL: write_output (console_out, "%c", R[REG_A0]); break; case READ_CHARACTER_SYSCALL: { static char str [2]; read_input (str, 2); if (*str == '\0') *str = '\n'; /* makes xspim = spim */ R[REG_RES] = (long) str[0]; break; } case EXIT_SYSCALL: spim_return_value = 0; return (0); case EXIT2_SYSCALL: spim_return_value = R[REG_A0]; /* value passed to spim's exit() call */ return (0); case OPEN_SYSCALL: { #ifdef WIN32 R[REG_RES] = _open(mem_reference (R[REG_A0]), R[REG_A1], R[REG_A2]); #else R[REG_RES] = open(mem_reference (R[REG_A0]), R[REG_A1], R[REG_A2]); #endif break; } case READ_SYSCALL: { /* Test if address is valid */ (void)mem_reference (R[REG_A1] + R[REG_A2] - 1); #ifdef WIN32 R[REG_RES] = _read(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); #else R[REG_RES] = read(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); #endif data_modified = 1; break; } case WRITE_SYSCALL: { /* Test if address is valid */ (void)mem_reference (R[REG_A1] + R[REG_A2] - 1); #ifdef WIN32 R[REG_RES] = _write(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); #else R[REG_RES] = write(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); #endif break; } case CLOSE_SYSCALL: { #ifdef WIN32 R[REG_RES] = _close(R[REG_A0]); #else R[REG_RES] = close(R[REG_A0]); #endif break; } default: run_error ("Unknown system call: %d\n", R[REG_V0]); break; } return (1); }