/* * dobuf: * execute the contents of the buffer pointed to * by the passed BP * * Directives start with a "!" and include: * * !endm End a macro * !if (cond) conditional execution * !else * !endif * !return Return (terminating current macro) * !goto <label> Jump to a label in the current macro * !force Force macro to continue...even if command fails * !while (cond) Execute a loop if the condition is true * !endwhile * * Line Labels begin with a "*" as the first nonblank char, like: * * *LBL01 * * struct buffer *bp; buffer to execute */ int dobuf(struct buffer *bp) { int status; /* status return */ struct line *lp; /* pointer to line to execute */ struct line *hlp; /* pointer to line header */ struct line *glp; /* line to goto */ struct line *mp; /* Macro line storage temp */ int dirnum; /* directive index */ int linlen; /* length of line to execute */ int i; /* index */ int c; /* temp character */ int force; /* force TRUE result? */ struct window *wp; /* ptr to windows to scan */ struct while_block *whlist; /* ptr to !WHILE list */ struct while_block *scanner; /* ptr during scan */ struct while_block *whtemp; /* temporary ptr to a struct while_block */ char *einit; /* initial value of eline */ char *eline; /* text of line to execute */ char *tkn; /* buffer to evaluate an expresion in */ #if DEBUGM char *sp; /* temp for building debug string */ char *ep; /* ptr to end of outline */ #endif tkn = alloca(NSTRING * sizeof(char)); /* clear IF level flags/while ptr */ execlevel = 0; whlist = NULL; scanner = NULL; /* scan the buffer to execute, building WHILE header blocks */ hlp = bp->b_linep; lp = hlp->l_fp; while (lp != hlp) { /* scan the current line */ eline = lp->l_text; i = lp->l_used; /* trim leading whitespace */ while (i-- > 0 && (*eline == ' ' || *eline == '\t')) ++eline; /* if theres nothing here, don't bother */ if (i <= 0) goto nxtscan; /* if is a while directive, make a block... */ if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') { whtemp = (struct while_block *)malloc(sizeof(struct while_block)); if (whtemp == NULL) { noram:mlwrite ("%%Out of memory during while scan"); failexit:freewhile (scanner); freewhile(whlist); return FALSE; } whtemp->w_begin = lp; whtemp->w_type = BTWHILE; whtemp->w_next = scanner; scanner = whtemp; } /* if is a BREAK directive, make a block... */ if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') { if (scanner == NULL) { mlwrite ("%%!BREAK outside of any !WHILE loop"); goto failexit; } whtemp = (struct while_block *)malloc(sizeof(struct while_block)); if (whtemp == NULL) goto noram; whtemp->w_begin = lp; whtemp->w_type = BTBREAK; whtemp->w_next = scanner; scanner = whtemp; } /* if it is an endwhile directive, record the spot... */ if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) { if (scanner == NULL) { mlwrite ("%%!ENDWHILE with no preceding !WHILE in '%s'", bp->b_bname); goto failexit; } /* move top records from the scanner list to the whlist until we have moved all BREAK records and one WHILE record */ do { scanner->w_end = lp; whtemp = whlist; whlist = scanner; scanner = scanner->w_next; whlist->w_next = whtemp; } while (whlist->w_type == BTBREAK); } nxtscan: /* on to the next line */ lp = lp->l_fp; } /* while and endwhile should match! */ if (scanner != NULL) { mlwrite("%%!WHILE with no matching !ENDWHILE in '%s'", bp->b_bname); goto failexit; } /* let the first command inherit the flags from the last one.. */ thisflag = lastflag; /* starting at the beginning of the buffer */ hlp = bp->b_linep; lp = hlp->l_fp; while (lp != hlp) { /* allocate eline and copy macro line to it */ linlen = lp->l_used; if ((einit = eline = malloc(linlen + 1)) == NULL) { mlwrite("%%Out of Memory during macro execution"); freewhile(whlist); return FALSE; } strncpy(eline, lp->l_text, linlen); eline[linlen] = 0; /* make sure it ends */ /* trim leading whitespace */ while (*eline == ' ' || *eline == '\t') ++eline; /* dump comments and blank lines */ if (*eline == ';' || *eline == 0) goto onward; #if DEBUGM /* if $debug == TRUE, every line to execute gets echoed and a key needs to be pressed to continue ^G will abort the command */ if (macbug) { strcpy(outline, "<<<"); /* debug macro name */ strcat(outline, bp->b_bname); strcat(outline, ":"); /* debug if levels */ strcat(outline, itoa(execlevel)); strcat(outline, ":"); /* and lastly the line */ strcat(outline, eline); strcat(outline, ">>>"); /* change all '%' to ':' so mlwrite won't expect arguments */ sp = outline; while (*sp) if (*sp++ == '%') { /* advance to the end */ ep = --sp; while (*ep++); /* null terminate the string one out */ *(ep + 1) = 0; /* copy backwards */ while (ep-- > sp) *(ep + 1) = *ep; /* and advance sp past the new % */ sp += 2; } /* write out the debug line */ mlforce(outline); update(TRUE); /* and get the keystroke */ if ((c = get1key()) == abortc) { mlforce("(Macro aborted)"); freewhile(whlist); return FALSE; } if (c == metac) macbug = FALSE; } #endif /* Parse directives here.... */ dirnum = -1; if (*eline == '!') { /* Find out which directive this is */ ++eline; for (dirnum = 0; dirnum < NUMDIRS; dirnum++) if (strncmp(eline, dname[dirnum], strlen(dname[dirnum])) == 0) break; /* and bitch if it's illegal */ if (dirnum == NUMDIRS) { mlwrite("%%Unknown Directive"); freewhile(whlist); return FALSE; } /* service only the !ENDM macro here */ if (dirnum == DENDM) { mstore = FALSE; bstore = NULL; goto onward; } /* restore the original eline.... */ --eline; } /* if macro store is on, just salt this away */ if (mstore) { /* allocate the space for the line */ linlen = strlen(eline); if ((mp = lalloc(linlen)) == NULL) { mlwrite ("Out of memory while storing macro"); return FALSE; } /* copy the text into the new line */ for (i = 0; i < linlen; ++i) lputc(mp, i, eline[i]); /* attach the line to the end of the buffer */ bstore->b_linep->l_bp->l_fp = mp; mp->l_bp = bstore->b_linep->l_bp; bstore->b_linep->l_bp = mp; mp->l_fp = bstore->b_linep; goto onward; } force = FALSE; /* dump comments */ if (*eline == '*') goto onward; /* now, execute directives */ if (dirnum != -1) { /* skip past the directive */ while (*eline && *eline != ' ' && *eline != '\t') ++eline; execstr = eline; switch (dirnum) { case DIF: /* IF directive */ /* grab the value of the logical exp */ if (execlevel == 0) { if (macarg(tkn) != TRUE) goto eexec; if (stol(tkn) == FALSE) ++execlevel; } else ++execlevel; goto onward; case DWHILE: /* WHILE directive */ /* grab the value of the logical exp */ if (execlevel == 0) { if (macarg(tkn) != TRUE) goto eexec; if (stol(tkn) == TRUE) goto onward; } /* drop down and act just like !BREAK */ case DBREAK: /* BREAK directive */ if (dirnum == DBREAK && execlevel) goto onward; /* jump down to the endwhile */ /* find the right while loop */ whtemp = whlist; while (whtemp) { if (whtemp->w_begin == lp) break; whtemp = whtemp->w_next; } if (whtemp == NULL) { mlwrite ("%%Internal While loop error"); freewhile(whlist); return FALSE; } /* reset the line pointer back.. */ lp = whtemp->w_end; goto onward; case DELSE: /* ELSE directive */ if (execlevel == 1) --execlevel; else if (execlevel == 0) ++execlevel; goto onward; case DENDIF: /* ENDIF directive */ if (execlevel) --execlevel; goto onward; case DGOTO: /* GOTO directive */ /* .....only if we are currently executing */ if (execlevel == 0) { /* grab label to jump to */ eline = token(eline, golabel, NPAT); linlen = strlen(golabel); glp = hlp->l_fp; while (glp != hlp) { if (*glp->l_text == '*' && (strncmp (&glp->l_text[1], golabel, linlen) == 0)) { lp = glp; goto onward; } glp = glp->l_fp; } mlwrite("%%No such label"); freewhile(whlist); return FALSE; } goto onward; case DRETURN: /* RETURN directive */ if (execlevel == 0) goto eexec; goto onward; case DENDWHILE: /* ENDWHILE directive */ if (execlevel) { --execlevel; goto onward; } else { /* find the right while loop */ whtemp = whlist; while (whtemp) { if (whtemp->w_type == BTWHILE && whtemp->w_end == lp) break; whtemp = whtemp->w_next; } if (whtemp == NULL) { mlwrite ("%%Internal While loop error"); freewhile(whlist); return FALSE; } /* reset the line pointer back.. */ lp = whtemp->w_begin->l_bp; goto onward; } case DFORCE: /* FORCE directive */ force = TRUE; } } /* execute the statement */ status = docmd(eline); if (force) /* force the status */ status = TRUE; /* check for a command error */ if (status != TRUE) { /* look if buffer is showing */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { /* and point it */ wp->w_dotp = lp; wp->w_doto = 0; wp->w_flag |= WFHARD; } wp = wp->w_wndp; } /* in any case set the buffer . */ bp->b_dotp = lp; bp->b_doto = 0; free(einit); execlevel = 0; freewhile(whlist); return status; } onward: /* on to the next line */ free(einit); lp = lp->l_fp; } eexec: /* exit the current function */ execlevel = 0; freewhile(whlist); return TRUE; }
/* * set a variable * * int f; default flag * int n; numeric arg (can overide prompted value) */ int setvar(int f, int n) { int status; /* status return */ #if DEBUGM char *sp; /* temp string pointer */ char *ep; /* ptr to end of outline */ #endif struct variable_description vd; /* variable num/type */ char var[NVSIZE + 1]; /* name of variable to fetch */ char value[NSTRING]; /* value to set variable to */ /* first get the variable to set.. */ if (clexec == FALSE) { status = mlreply("Variable to set: ", &var[0], NVSIZE); if (status != TRUE) return status; } else { /* macro line argument */ /* grab token and skip it */ execstr = token(execstr, var, NVSIZE + 1); } /* check the legality and find the var */ findvar(var, &vd, NVSIZE + 1); /* if its not legal....bitch */ if (vd.v_type == -1) { mlwrite("%%No such variable as '%s'", var); return FALSE; } /* get the value for that variable */ if (f == TRUE) strcpy(value, itoa(n)); else { status = mlreply("Value: ", &value[0], NSTRING); if (status != TRUE) return status; } /* and set the appropriate value */ status = svar(&vd, value); #if DEBUGM /* if $debug == TRUE, every assignment will echo a statment to that effect here. */ if (macbug) { strcpy(outline, "((("); /* assignment status */ strcat(outline, ltos(status)); strcat(outline, ":"); /* variable name */ strcat(outline, var); strcat(outline, ":"); /* and lastly the value we tried to assign */ strcat(outline, value); strcat(outline, ")))"); /* expand '%' to "%%" so mlwrite wont bitch */ sp = outline; while (*sp) if (*sp++ == '%') { /* advance to the end */ ep = --sp; while (*ep++); /* null terminate the string one out */ *(ep + 1) = 0; /* copy backwards */ while (ep-- > sp) *(ep + 1) = *ep; /* and advance sp past the new % */ sp += 2; } /* write out the debug line */ mlforce(outline); update(TRUE); /* and get the keystroke to hold the output */ if (get1key() == abortc) { mlforce("(Macro aborted)"); status = FALSE; } } #endif /* and return it */ return status; }