/* ** 'renumber' renumbers the lines in the program starting at 'progstart'. ** It does this in three passes. On the first, it goes through and resolves ** all the line number references it can. It then renumbers the program. ** The last step is to go through all the line numbers again and replace ** the old line numbers with the new. As a bonus, all of the line number ** pointers in the program are left pointing at the right lines. */ void renumber_program(byte *progstart, int32 start, int32 step) { byte *bp; boolean ok; bp = progstart; while (!AT_PROGEND(bp) && start<=MAXLINENO) { resolve_linenums(bp); bp+=get_linelen(bp); } bp = progstart; while (!AT_PROGEND(bp) && start<=MAXLINENO) { save_lineno(bp, start); start+=step; bp+=get_linelen(bp); } ok = AT_PROGEND(bp); if (!ok) { /* Oops... Did not stop at end of program */ if (step!=1) { /* Try to fix line numbers */ start = 1; bp = progstart; while (!AT_PROGEND(bp) && start<=MAXLINENO) { save_lineno(bp, start); start++; bp+=get_linelen(bp); } } } bp = progstart; while (!AT_PROGEND(bp) && start<=MAXLINENO) { reset_linenums(bp); bp+=get_linelen(bp); } if(!ok) error(ERR_RENUMBER); }
/* ** 'clear_refs' is called to restore all the line number and case table tokens ** to their 'no address' versions. This is needed when a program is edited. ** The code also clears such tokens in installed libraries as any case tables ** built for statements in the libraries will have been put on the Basic heap. */ static void clear_refs(void) { byte *bp; library *lp; if (basicvars.runflags.has_variables) { clear_varlists(); clear_heap(); clear_strings(); } if (basicvars.runflags.has_offsets) { bp = basicvars.start; while (!AT_PROGEND(bp)) { clear_linerefs(bp); bp+=get_linelen(bp); } lp = basicvars.installist; /* Now clear the pointers in any installed libraries */ while (lp!=NIL) { bp = lp->libstart; while (!AT_PROGEND(bp)) { clear_linerefs(bp); bp = bp+GET_LINELEN(bp); } lp = lp->libflink; } } basicvars.liblist = NIL; basicvars.runflags.has_offsets = FALSE; basicvars.runflags.has_variables = FALSE; }
/* ** 'isvalidprog' checks the program in memory to make sure that it is okay. ** It returns 'true' if the program is okay, otherwise it returns 'false' */ static boolean isvalidprog(void) { int32 lastline; byte *p; boolean isnotfirst; lastline = 0; isnotfirst = FALSE; /* So that line number 0 is not flagged as an error */ p = basicvars.start; while (!AT_PROGEND(p)) { if (!isvalid(p) || (isnotfirst && get_lineno(p) <= lastline)) return FALSE; lastline = get_lineno(p); isnotfirst = TRUE; p+=get_linelen(p); } return AT_PROGEND(p); }
/* ** 'write_text' is called to save a program in text form */ void write_text(char *name) { FILE *savefile; byte *bp; int32 x; savefile = fopen(name, "w"); if (savefile==NIL) error(ERR_NOTCREATED, name); bp = basicvars.start; while (!AT_PROGEND(bp)) { expand(bp, basicvars.stringwork); x = fputs(basicvars.stringwork, savefile); if (x!=EOF) x = fputc('\n', savefile); if (x==EOF) { /* Error occured writing to file */ fclose(savefile); error(ERR_WRITEFAIL, name); } bp+=get_linelen(bp); } fclose(savefile); }
/* ** 'recover_program' is called to verify that the program at 'page' ** is legal. It resets the various program pointers if it is, or ** flags the program as invalid if not (after resetting the various ** pointer to 'safe' values) */ void recover_program(void) { byte *bp = NULL; if (basicvars.misc_flags.validsaved) { /* Only check if the command 'new' has been used */ reinstate(); /* Restore start of program */ bp = basicvars.start; basicvars.misc_flags.validsaved = isvalidprog(); } if (basicvars.misc_flags.validsaved) { /* Old program is okay */ while (!AT_PROGEND(bp)) bp+=get_linelen(bp); /* Find end */ basicvars.top = bp; adjust_heaplimits(); } else { /* Program is not valid - Ensure everything is set to safe values */ clear_varlists(); clear_strings(); clear_heap(); basicvars.misc_flags.badprogram = TRUE; save_lineno(basicvars.start, ENDLINENO); basicvars.current = basicvars.datacur = basicvars.top = basicvars.page+MARKERSIZE; adjust_heaplimits(); error(ERR_BADPROG); } }
/* ** 'list_if' deals with the 'LISTIF' command. It lists each line ** where there is at least one occurence of the string following ** the 'LISTIF' command. */ static void list_if(void) { byte *p, *tp; int32 targetlen, statelen; char first, *sp; boolean more; p = tp = get_srcaddr(basicvars.current); /* Get address of string to search for */ basicvars.current+=1+OFFSIZE; check_ateol(); while (*p != NUL) p++; /* Find the end of the string */ targetlen = p-tp; /* Number of characters in search string */ if (targetlen == 0) return; /* End if search string is empty */ p = basicvars.start; more = TRUE; first = *tp; while (more && !AT_PROGEND(p)) { reset_indent(); expand(p, basicvars.stringwork); sp = basicvars.stringwork; statelen = strlen(basicvars.stringwork); do { sp++; while (statelen>=targetlen && *sp != first) { statelen--; sp++; } } while(statelen>=targetlen && memcmp(sp, tp, targetlen) != 0); if (statelen>=targetlen) { /* Can only be true if the string was found */ if (basicvars.debug_flags.tokens) emulate_printf("%08p %s\r\n", p, basicvars.stringwork); else { emulate_printf("%s\r\n", basicvars.stringwork); } } p+=GET_LINELEN(p); } }