diff options
| author | Steve Slaven <bpk@hoopajoo.net> | 2023-01-24 06:10:06 (GMT) | 
|---|---|---|
| committer | Steve Slaven <bpk@hoopajoo.net> | 2023-01-24 06:10:06 (GMT) | 
| commit | 8f3f779bb96e1b8ee6a87ca13915eaa16ad754c8 (patch) | |
| tree | ffdd226b9c8b7caf14e905ff2f130a687c0510a7 | |
| parent | 76f433d408da25e3291c4f4d47f8e60428a3e2e6 (diff) | |
| parent | cade2c07eeadbd230b9c64607750813415b8231e (diff) | |
| download | powwow-8f3f779bb96e1b8ee6a87ca13915eaa16ad754c8.zip powwow-8f3f779bb96e1b8ee6a87ca13915eaa16ad754c8.tar.gz powwow-8f3f779bb96e1b8ee6a87ca13915eaa16ad754c8.tar.bz2 | |
merge #substitute and --prove
| -rw-r--r-- | src/cmd.c | 20 | ||||
| -rw-r--r-- | src/cmd2.c | 120 | ||||
| -rw-r--r-- | src/cmd2.h | 4 | ||||
| -rw-r--r-- | src/defines.h | 19 | ||||
| -rw-r--r-- | src/edit.c | 3 | ||||
| -rw-r--r-- | src/list.c | 76 | ||||
| -rw-r--r-- | src/list.h | 6 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/main.h | 1 | ||||
| -rw-r--r-- | src/utils.c | 157 | ||||
| -rw-r--r-- | src/utils.h | 5 | 
11 files changed, 349 insertions, 67 deletions
| @@ -62,7 +62,7 @@ static void F(help), F(shell), F(action), F(add),    F(rawsend), F(rawprint), F(rebind), F(rebindall), F(rebindALL),    F(record), F(request), F(reset), F(retrace),    F(save), F(send), F(setvar), F(snoop), F(spawn), F(stop), -  F(time), F(var), F(ver), F(while), F(write), +  F(substitute), F(time), F(var), F(ver), F(while), F(write),    F(eval), F(zap), F(module), F(group), F(speedwalk), F(groupdelim);  #ifdef BUG_TELNET @@ -227,6 +227,8 @@ cmdstruct default_commands[] =        "connect-id command\ttalk with a shell command"),      C("speedwalk",  cmd_speedwalk,        "[speedwalk sequence]\texecute a speedwalk sequence explicitly"), +    C("substitute",       cmd_substitute, +      "[string[=[text]]]\tdelete/list/define substitutions"),      C("stop",       cmd_stop,        "\t\t\t\tremove all delayed commands from active list"),      C("time",       cmd_time, @@ -1281,6 +1283,12 @@ static void cmd_reset(char *arg)  	if (!all)  	    return;      } +    if (all || !strcmp(arg, "substitute")) { +        while (substitutions) +	    delete_substnode(&substitutions); +	if (!all) +	    return; +    }      if (all || !strcmp(arg, "var")) {          int n;  	varnode **first; @@ -1335,6 +1343,14 @@ static void cmd_stop(char *arg)      }  } +static void cmd_substitute(char *arg) +{ +    if (!*arg) +	show_substitutions(); +    else +	parse_substitute(arg); +} +  static void cmd_time(char *arg)  {      struct tm *s; @@ -2709,5 +2725,3 @@ static void cmd_put(char *arg)  	put_history(arg);      ptrdel(pbuf);  } - - @@ -879,8 +879,8 @@ void show_marks(void)  	       (markers && !markers->next) ? " is" : "s are",  	       markers ? ':' : '.');      for (p = markers; p; p = p->next) -	tty_printf("#mark %s%s=%s\n", p->mbeg ? "^" : "", -		   p->pattern, attr_name(p->attrcode)); +	tty_printf("#mark %s%s=%s\n", p->b.mbeg ? "^" : "", +		   p->b.pattern, attr_name(p->attrcode));  } @@ -894,7 +894,7 @@ void parse_mark(char *str)      char mbeg = 0;      if (*str == '=') { -	PRINTF("#marker must be non-null.\n"); +	PRINTF("#marker must be non-empty.\n");  	return;      }      p = first_regular(str, '='); @@ -906,10 +906,10 @@ void parse_mark(char *str)          if ((n = *np)) {  	    ptr pbuf = (ptr)0;  	    char *name; -	    pbuf = ptrmescape(pbuf, n->pattern, strlen(n->pattern), 0); +	    pbuf = ptrmescape(pbuf, n->b.pattern, strlen(n->b.pattern), 0);  	    if (MEM_ERROR) { ptrdel(pbuf); return; }              name = attr_name(n->attrcode); -            sprintf(inserted_next, "#mark %s%.*s=%.*s", n->mbeg ? "^" : "", +            sprintf(inserted_next, "#mark %s%.*s=%.*s", n->b.mbeg ? "^" : "",  		    BUFSIZE-(int)strlen(name)-9, pbuf ? ptrdata(pbuf) : "",  		    BUFSIZE-9, name);  	    ptrdel(pbuf); @@ -949,8 +949,8 @@ void parse_mark(char *str)          } else if (!*p)  	    if ((n = *np)) {  		if (opt_info) { -		    PRINTF("#deleting mark: %s%s=%s\n", n->mbeg ? "^" : "", -			   n->pattern, attr_name(n->attrcode)); +		    PRINTF("#deleting mark: %s%s=%s\n", n->b.mbeg ? "^" : "", +			   n->b.pattern, attr_name(n->attrcode));  		}  		delete_marknode(np);  	    } else { @@ -976,6 +976,111 @@ void parse_mark(char *str)      }  } + +/* + * show defined substitutions + */ +void show_substitutions(void) +{ +    substnode *p; +    PRINTF("#%s substitution%s defined%c\n", substitutions ? "the following" : "no", +	       (substitutions && !substitutions->next) ? " is" : "s are", +	       substitutions ? ':' : '.'); +    for (p = substitutions; p; p = p->next) +	tty_printf("#substitute %s%s=%s\n", p->b.mbeg ? "^" : "", +		   p->b.pattern, p->replacement); +} + + +/* + * parse arguments to the #mark command + */ +void parse_substitute(char *str) +{ +    char *p; +    substnode **np, *n; +    char mbeg = 0; + +    if (*str == '=') { +	PRINTF("#substitute must be non-empty.\n"); +	return; +    } +    p = first_regular(str, '='); +    if (!*p) { +	if (*str ==  '^') +	    mbeg = 1, str++; +        unescape(str); +        np = lookup_subst(str, mbeg); +        if ((n = *np)) { +	    char *replacement = n->replacement; +	    ptr pbuf = ptrmescape(pbuf, n->b.pattern, strlen(n->b.pattern), 0); +	    if (MEM_ERROR) { ptrdel(pbuf); return; } +            sprintf(inserted_next, "#substitute %s%.*s=%.*s", n->b.mbeg ? "^" : "", +		    BUFSIZE-(int)strlen(replacement)-14, pbuf ? ptrdata(pbuf) : "", +		    BUFSIZE-14, replacement); +	    ptrdel(pbuf); +        } else { +            PRINTF("#unknown substitution, cannot show: \"%s\"\n", str); +        } + +    } else { +	char pattern[BUFSIZE], *p2, *replacement; +        int  wild = 0; + +        *(p++) = '\0'; +	if (*str ==  '^') +	    mbeg = 1, str++; +	my_strncpy(pattern, str, BUFSIZE-1); +        unescape(pattern); +	p2 = pattern; +	while (*p2) { +	    if (ISMARKWILDCARD(*p2)) { +		wild = 1; +		if (ISMARKWILDCARD(*(p2 + 1))) { +		    error = SYNTAX_ERROR; +		    PRINTF("#error: two wildcards (& or $) may not be next to eachother\n"); +		    return; +		} +	    } +	    p2++; +	} + +        np = lookup_subst(pattern, mbeg); +        replacement = p; +        if (!*p) +	    if ((n = *np)) { +		if (opt_info) { +		    PRINTF("#deleting substitution: %s%s=%s\n", n->b.mbeg ? "^" : "", +			   n->b.pattern, n->replacement); +		} +		delete_substnode(np); +	    } else { +		PRINTF("#unknown substitution, cannot delete: \"%s%s\"\n", +		       mbeg ? "^" : "", pattern); +	    } +        else { +            if ((n = *np)) { +                if (!(replacement = my_strdup(replacement))) { +                        return; +                } +                if (n->replacement) { free(n->replacement); } +                n->replacement = replacement; +                if (opt_info) { +                    PRINTF("#changed"); +                } +            } else { +                add_substnode(pattern, replacement, mbeg, wild); +                if (opt_info) { +                    PRINTF("#new"); +                } +            } +            if (opt_info) +		tty_printf(" substitution: %s%s=%s\n", mbeg ? "^" : "", +			   pattern, replacement); +        } +    } +} +  /*   * turn ASCII description of a sequence   * into raw escape sequence @@ -1673,4 +1778,3 @@ void exe_history(int count)  	parse_user_input(buf, 0);      }  } - @@ -14,6 +14,9 @@ char *attr_name(int attrcode);  void show_marks(void);  void parse_mark(char *str); +void show_substitutions(void); +void parse_substitute(char *str); +  char *seq_name(char *seq, int len);  void show_binds(char edit);  void parse_bind(char *arg); @@ -29,4 +32,3 @@ void new_delaynode(char *name, char *command, long millisec);  void show_history(int count);  void exe_history(int count); - diff --git a/src/defines.h b/src/defines.h index 1e273e1..87687ef 100644 --- a/src/defines.h +++ b/src/defines.h @@ -215,15 +215,25 @@ typedef struct aliasnode {      int active;  } aliasnode; -typedef struct marknode { -    struct marknode *next; +typedef struct basenode {      char *pattern; -    int attrcode; -    char *start, *end; +    char *start, *end; // temporary data: start/end of current line match      char mbeg;      char wild; +} basenode; + +typedef struct marknode { +    struct marknode *next; +    basenode b; +    int attrcode;  } marknode; +typedef struct substnode { +    struct substnode *next; +    basenode b; +    char *replacement; +} substnode; +  typedef struct triggernode {      struct triggernode *next;      char *command, *label; @@ -303,4 +313,3 @@ typedef struct editsess {  } editsess;  #endif /* _DEFINES_H_ */ - @@ -133,7 +133,7 @@ void draw_prompt(void)          char *esc, *pstr;  	int e = error;  	error = 0; -	marked_prompt = ptraddmarks(marked_prompt, prompt->str); +	marked_prompt = ptraddsubst_and_marks(marked_prompt, prompt->str);  	if (MEM_ERROR) { promptzero(); errmsg("malloc(prompt)"); return; }          /* if prompt ends in unterminated escape code, do not print @@ -958,4 +958,3 @@ void edit_bootstrap(void)  {      default_completions();  } - @@ -23,6 +23,7 @@  #include "feature/regex.h"  #include "utils.h"  #include "cmd2.h" +#include "list.h"  #include "tty.h"  #include "eval.h" @@ -206,12 +207,13 @@ void add_marknode(char *pattern, int attrcode, char mbeg, char wild)  	errmsg("malloc");  	return;      } -    new->pattern = my_strdup(pattern); +    new->next = NULL; +    new->b.pattern = my_strdup(pattern); +    new->b.start = new->b.end = NULL; +    new->b.mbeg = mbeg; +    new->b.wild = wild;      new->attrcode = attrcode; -    new->start = new->end = NULL; -    new->mbeg = mbeg; -    new->wild = wild; -    if (!new->pattern) { +    if (!new->b.pattern) {  	errmsg("malloc");  	free(new);  	return; @@ -226,6 +228,39 @@ void add_marknode(char *pattern, int attrcode, char mbeg, char wild)  #endif  } + +/* + * add a node to the substitution list + */ +void add_substnode(char *pattern, char *replacement, char mbeg, char wild) +{ +    substnode **p, *new = (substnode*)malloc(sizeof(substnode)); +    int i; +    if (!new) { +        errmsg("malloc"); +        return; +    } +    new->next = NULL; +    new->b.pattern = my_strdup(pattern); +    new->b.start = new->b.end = NULL; +    new->b.mbeg = mbeg; +    new->b.wild = wild; +    new->replacement = my_strdup(replacement); +    if (!new->b.pattern || (replacement && !new->replacement)) { +        errmsg("malloc"); +        delete_substnode(&new); +        return; +    } +#ifdef DO_SORT +    add_node((defnode*)new, (defnode**)&substitutions, ascii_sort); +#else +    for (p=&substitutions, i=1; *p && (a_nice==0 || i<a_nice); p = &(*p)->next, i++) +        ; +    new->next = *p; +    *p = new; +#endif +} +  /*   * add a node to the action list   */ @@ -487,13 +522,25 @@ actionnode **lookup_prompt(char *label)  }  /* - * look up an marker node by pattern: + * look up a marker node by pattern:   * return pointer to pointer to node or a pointer to NULL if nothing found   */  marknode **lookup_marker(char *pattern, char mbeg)  {      marknode **p = &markers; -    while (*p && (mbeg != (*p)->mbeg || strcmp(pattern, (*p)->pattern))) +    while (*p && (mbeg != (*p)->b.mbeg || strcmp(pattern, (*p)->b.pattern))) +	p = &(*p)->next; +    return p; +} + +/* + * look up a substitution node by pattern: + * return pointer to pointer to node or a pointer to NULL if nothing found + */ +substnode **lookup_subst(char *pattern, char mbeg) +{ +    substnode **p = &substitutions; +    while (*p && (mbeg != (*p)->b.mbeg || strcmp(pattern, (*p)->b.pattern)))  	p = &(*p)->next;      return p;  } @@ -505,7 +552,6 @@ marknode **lookup_marker(char *pattern, char mbeg)  keynode **lookup_key(char *name)  {      keynode **p = &keydefs; -      while (*p && strcmp(name, (*p)->name))  	p = &(*p)->next;      return p; @@ -596,7 +642,19 @@ void delete_promptnode(promptnode **base)  void delete_marknode(marknode **base)  {      marknode *p = *base; -    if (p->pattern) free(p->pattern); +    if (p->b.pattern) free(p->b.pattern); +    *base = p->next; +    free((void*)p); +} + +/* + * delete a substnode, given a pointer to its precessor's pointer + */ +void delete_substnode(substnode **base) +{ +    substnode *p = *base; +    if (p->b.pattern) free(p->b.pattern); +    if (p->replacement) free(p->replacement);      *base = p->next;      free((void*)p);  } @@ -13,7 +13,7 @@ int rev_ascii_sort(defnode *node1, defnode *node2);  int time_sort(defnode *node1, defnode *node2);  int rev_time_sort(defnode *node1, defnode *node2); -int hash(char *name); +int hash(char *name, int optlen);  void add_node(defnode *newnode, defnode **base, function_sort sort);  void reverse_sortedlist(sortednode **base); @@ -23,6 +23,7 @@ void add_actionnode(char *pattern, char *command, char *label, int active, int t  void add_promptnode(char *pattern, char *command, char *label, int active, int type, void *qregexp);  void add_marknode(char *pattern, int attrcode, char mbeg, char wild);  void add_keynode(char *name, char *sequence, int seqlen, function_str funct, char *call_data); +void add_substnode(char *pattern, char *replacement, char mbeg, char wild);  delaynode *add_delaynode(char *name, char *command, vtime *when, int is_dead);  varnode *add_varnode(char *name, int type); @@ -31,6 +32,7 @@ actionnode **lookup_action(char *label);  actionnode **lookup_prompt(char *label);  actionnode **lookup_action_pattern(char *pattern);  marknode   **lookup_marker(char *pattern, char mbeg); +substnode  **lookup_subst(char *pattern, char mbeg);  keynode    **lookup_key(char *name);  delaynode  **lookup_delay(char *name, int is_dead);  varnode    **lookup_varnode(char *name, int type); @@ -41,7 +43,7 @@ void delete_promptnode(promptnode **base);  void delete_marknode(marknode **base);  void delete_keynode(keynode **base);  void delete_delaynode(delaynode **base); +void delete_substnode(substnode **base);  void delete_varnode(varnode **base, int type);  #endif /* _LIST_H_ */ - @@ -13,7 +13,7 @@   *   * Initially inspired to the Tintin client by Peter Unold,   * Powwow contains no Tintin code. - * The original program Cancan, written by Mattias Engdegård (Yorick) + * The original program Cancan, written by Mattias Engdeg�rd (Yorick)   * (f91-men@nada.kth.se) 1992-94,   * was greatly improved upon by Vivriel, Thuzzle and Ilie and then   * transformed from Cancan into Powwow by Cosmos who worked @@ -159,7 +159,8 @@ aliasnode *sortedaliases;          /* head of (ASCII) sorted alias list */  actionnode *actions;               /* head of action list */  promptnode *prompts;               /* head of prompt list */  marknode *markers;                 /* head of mark list */ -int a_nice = 0;                    /* default priority of new actions/marks */ +substnode *substitutions;          /* head of substitution list */ +int a_nice = 0;                    /* default priority of new actions/marks/substitutions */  keynode *keydefs;                  /* head of key binding list */  delaynode *delays;                 /* head of delayed commands list */  delaynode *dead_delays;            /* head of dead-delayed commands list */ @@ -63,6 +63,7 @@ extern aliasnode *sortedaliases;  extern actionnode *actions;  extern promptnode *prompts;  extern marknode *markers; +extern substnode *substitutions;  extern int a_nice;  extern keynode *keydefs;  extern delaynode *delays; diff --git a/src/utils.c b/src/utils.c index f6582ef..0c3be5d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -334,24 +334,24 @@ void escape_specials(char *dst, char *src)   * if 1, start and end contain the match bounds   * if 0, start and end are undefined on return   */ -static int match_mark(marknode *mp, char *src) +static int match_mark_or_subst(basenode *bp, char *src)  { -    char *pat = mp->pattern; +    char *pat = bp->pattern;      char *npat=0, *npat2=0, *nsrc=0, *prm=0, *endprm=0, *tmp, c;      static char mpat[BUFSIZE]; -    int mbeg = mp->mbeg, mword = 0, p; +    int mbeg = bp->mbeg, mword = 0, p;      /* shortcut for #marks without wildcards */ -    if (!mp->wild) { +    if (!bp->wild) {  	if ((nsrc = strstr(src, pat))) { -	    mp->start = nsrc; -	    mp->end = nsrc + strlen(pat); +	    bp->start = nsrc; +	    bp->end = nsrc + strlen(pat);  	    return 1;  	}  	return 0;      } -    mp->start = NULL; +    bp->start = NULL;      if (ISMARKWILDCARD(*pat))  	mbeg = - mbeg - 1;  /* pattern starts with '&' or '$' */ @@ -363,8 +363,8 @@ static int match_mark(marknode *mp, char *src)  	    prm = src;  	    if (c == '$')  		mword = 1; -	    else if (!mp->start) -		mp->start = src; +	    else if (!bp->start) +		bp->start = src;  	    ++pat;  	} @@ -389,17 +389,17 @@ static int match_mark(marknode *mp, char *src)  		mbeg = 0;  /* reset mbeg to stop further start match */  	    }  	    endprm = nsrc; -	    if (!mp->start) { +	    if (!bp->start) {  		if (prm) -		    mp->start = src; +		    bp->start = src;  		else -		    mp->start = nsrc; +		    bp->start = nsrc;  	    } -	    mp->end = nsrc + strlen(mpat); +	    bp->end = nsrc + strlen(mpat);  	} else if (prm)           /* end of pattern space */ -	    mp->end = endprm = prm + strlen(prm); +	    bp->end = endprm = prm + strlen(prm);  	else -	    mp->end = src; +	    bp->end = src;  	/* post-processing of param */ @@ -417,11 +417,11 @@ static int match_mark(marknode *mp, char *src)  			else  			    p = -1;  		    } -		    mp->start = prm += p + 1; +		    bp->start = prm += p + 1;  		} else if (!*pat) {  		    /* '$' at end of pattern, take first word */  		    if ((tmp = memchrs(prm, strlen(prm), DELIM, DELIM_LEN))) -			mp->end = endprm = tmp; +			bp->end = endprm = tmp;  		} else {  			/* match only if param is single-worded */  		    if (memchrs(prm, endprm - prm, DELIM, DELIM_LEN)) @@ -441,7 +441,7 @@ static int match_mark(marknode *mp, char *src)  /*   * add marks to line. write in dst.   */ -ptr ptrmaddmarks(ptr dst, char *line, int len) +static ptr ptrmaddmarks(ptr dst, char *line, int len)  {      marknode *mp, *mfirst;      char begin[CAPLEN], end[CAPLEN], *lineend = line + len; @@ -453,19 +453,19 @@ ptr ptrmaddmarks(ptr dst, char *line, int len)  	return dst;      for (mp = markers; mp; mp = mp->next) -	mp->start = NULL; +	mp->b.start = NULL;      do {  	mfirst = NULL;  	for (mp = markers; mp; mp = mp->next) { -	    if (mp->start && mp->start >= line) +	    if (mp->b.start && mp->b.start >= line)  		matched = 1;  	    else { -		if (!(matched = (!mp->mbeg || start) && match_mark(mp, line))) -		    mp->start = lineend; +		if (!(matched = (!mp->b.mbeg || start) && match_mark_or_subst(&mp->b, line))) +		    mp->b.start = lineend;  	    } -	    if (matched && mp->start < lineend && -		(!mfirst || mp->start < mfirst->start)) +	    if (matched && mp->b.start < lineend && +		(!mfirst || mp->b.start < mfirst->b.start))  		mfirst = mp;  	} @@ -473,7 +473,7 @@ ptr ptrmaddmarks(ptr dst, char *line, int len)  	    start = 0;  	    attr_string(mfirst->attrcode, begin, end); -	    dst = ptrmcat(dst, line, matchlen = mfirst->start - line); +	    dst = ptrmcat(dst, line, matchlen = mfirst->b.start - line);  	    if (MEM_ERROR) break;  	    line += matchlen;  	    len -= matchlen; @@ -481,7 +481,7 @@ ptr ptrmaddmarks(ptr dst, char *line, int len)  	    dst = ptrmcat(dst, begin, strlen(begin));  	    if (MEM_ERROR) break; -	    dst = ptrmcat(dst, line, matchlen = mfirst->end - mfirst->start); +	    dst = ptrmcat(dst, line, matchlen = mfirst->b.end - mfirst->b.start);  	    if (MEM_ERROR) break;  	    line += matchlen;  	    len -= matchlen; @@ -497,10 +497,93 @@ ptr ptrmaddmarks(ptr dst, char *line, int len)      return dst;  } -ptr ptraddmarks(ptr dst, ptr line) +/* + * add substitutions to line. write in dst. + */ +static ptr ptrmaddsubst(ptr dst, char *line, int len) +{ +    substnode *sp, *sfirst; +    char *lineend = line + len; +    int start = 1, matchlen, matched = 0; + +    ptrzero(dst); + +    if (!line || len <= 0) +	return dst; + +    for (sp = substitutions; sp; sp = sp->next) +	sp->b.start = NULL; + +    do { +	sfirst = NULL; +	for (sp = substitutions; sp; sp = sp->next) { +	    if (sp->b.start && sp->b.start >= line) +		matched = 1; +	    else { +		if (!(matched = (!sp->b.mbeg || start) && match_mark_or_subst(&sp->b, line))) +		    sp->b.start = lineend; +	    } +	    if (matched && sp->b.start < lineend && +		(!sfirst || sp->b.start < sfirst->b.start)) +		sfirst = sp; +	} + +	if (sfirst) { +	    start = 0; + +	    dst = ptrmcat(dst, line, matchlen = sfirst->b.start - line); +	    if (MEM_ERROR) break; +	    line += matchlen; +	    len -= matchlen; + +	    dst = ptrmcat(dst, sfirst->replacement, strlen(sfirst->replacement)); +	    if (MEM_ERROR) break; +            matchlen = sfirst->b.end - sfirst->b.start; +            line += matchlen; +	    len -= matchlen; +	} +    } while (sfirst); + +    if (!MEM_ERROR) +	dst = ptrmcat(dst, line, len); + +    return dst; +} + + +/* + * add substitutions and markers to line. write in dst. + */ +ptr ptrmaddsubst_and_marks(ptr dst, char *line, int len) +{ +    static ptr ptrbuf = NULL; +    if (!substitutions) { +        return ptrmaddmarks(dst, line, len); +    } else if (!markers) { +        return ptrmaddsubst(dst, line, len); +    } +    if (!ptrbuf) { +        ptrbuf = ptrnew(PARAMLEN); +        if (!ptrbuf) { +            goto fail; +        } +    } +    ptrbuf = ptrmaddsubst(ptrbuf, line, len); +    if (ptrbuf) { +        dst = ptrmaddmarks(dst, ptrdata(ptrbuf), ptrlen(ptrbuf)); +    } +fail: +    if (MEM_ERROR) { +        print_error(error); +        ptrzero(dst); +    } +    return dst; +} + +ptr ptraddsubst_and_marks(ptr dst, ptr line)  {      if (line) -	return ptrmaddmarks(dst, ptrdata(line), ptrlen(line)); +	return ptrmaddsubst_and_marks(dst, ptrdata(line), ptrlen(line));      ptrzero(dst);      return dst;  } @@ -594,7 +677,7 @@ static void wrap_print(char *s)  }  /* - * add marks to line and print. + * add substitutions and marks to line and print.   * if newline, also print a final \n   */  void smart_print(char *line, char newline) @@ -607,7 +690,7 @@ void smart_print(char *line, char newline)  	    ptrbuf = ptrnew(PARAMLEN);  	    if (MEM_ERROR) break;  	} -	ptrbuf = ptrmaddmarks(ptrbuf, line, strlen(line)); +	ptrbuf = ptrmaddsubst_and_marks(ptrbuf, line, strlen(line));  	if (MEM_ERROR || !ptrbuf) break;  	buf = ptrdata(ptrbuf); @@ -943,6 +1026,8 @@ int read_settings(void)  	delete_marknode(&markers);      while (keydefs)  	delete_keynode(&keydefs); +    while (substitutions) +	delete_substnode(&substitutions);      for (n = 0; n < MAX_HASH; n++) {  	while (named_vars[0][n])  	    delete_varnode(&named_vars[0][n], 0); @@ -1059,6 +1144,7 @@ int save_settings(void)      actionnode *acp;      promptnode *ptp;      marknode *mp; +    substnode *sp;      keynode *kp;      varnode *vp;      ptr pp = (ptr)0; @@ -1150,11 +1236,18 @@ int save_settings(void)      }      for (mp = markers; mp && failed > 0; mp = mp->next) { -	pp = ptrmescape(pp, mp->pattern, strlen(mp->pattern), 0); +	pp = ptrmescape(pp, mp->b.pattern, strlen(mp->b.pattern), 0);  	if (MEM_ERROR) { failed = -1; break; } -	failed = fprintf(f, "#mark %s%s=%s\n", mp->mbeg ? "^" : "", +	failed = fprintf(f, "#mark %s%s=%s\n", mp->b.mbeg ? "^" : "",  			     ptrdata(pp), attr_name(mp->attrcode));      } + +    for (sp = substitutions; sp && failed > 0; sp = sp->next) { +	pp = ptrmescape(pp, sp->b.pattern, strlen(sp->b.pattern), 0); +	if (MEM_ERROR) { failed = -1; break; } +	failed = fprintf(f, "#substitute %s%s=%s\n", sp->b.mbeg ? "^" : "", +			     ptrdata(pp), sp->replacement); +    }      /* save value of global variables */      for (flag = 0, i=0; i<NUMVAR && failed > 0; i++) { diff --git a/src/utils.h b/src/utils.h index f5b8704..833b0ba 100644 --- a/src/utils.h +++ b/src/utils.h @@ -13,8 +13,8 @@ int  memunescape(char *p, int lenp);  ptr  ptrescape(ptr dst, ptr src, int append);  ptr  ptrmescape(ptr dst, char *src, int srclen, int append); -ptr  ptraddmarks(ptr dst, ptr line); -ptr  ptrmaddmarks(ptr dst, char *line, int len); +ptr  ptraddsubst_and_marks(ptr dst, ptr line); +ptr  ptrmaddsubst_and_marks(ptr dst, char *line, int len);  void put_marks(char *dst, char *line);  void smart_print(char *line, char newline); @@ -45,4 +45,3 @@ void movie_write(char *str, int newline);  void update_now(void);  #endif /* _UTILS_H_ */ - | 
