From cade2c07eeadbd230b9c64607750813415b8231e Mon Sep 17 00:00:00 2001 From: Massimiliano Ghilardi Date: Thu, 12 Jan 2023 21:06:31 +0100 Subject: implement command #substitute [string[=[text]]] diff --git a/src/cmd.c b/src/cmd.c index f11dd53..847fbdc 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -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); } - - diff --git a/src/cmd2.c b/src/cmd2.c index dbd264a..1503f88 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -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); } } - diff --git a/src/cmd2.h b/src/cmd2.h index 96cb067..7e9e1fe 100644 --- a/src/cmd2.h +++ b/src/cmd2.h @@ -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_ */ - diff --git a/src/edit.c b/src/edit.c index bcfab21..d42d8bb 100644 --- a/src/edit.c +++ b/src/edit.c @@ -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(); } - diff --git a/src/list.c b/src/list.c index 2652bda..3e7471b 100644 --- a/src/list.c +++ b/src/list.c @@ -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 || inext, 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); } diff --git a/src/list.h b/src/list.h index c336049..c57167e 100644 --- a/src/list.h +++ b/src/list.h @@ -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_ */ - diff --git a/src/main.c b/src/main.c index 3c7fe9b..fb81415 100644 --- a/src/main.c +++ b/src/main.c @@ -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 @@ -158,7 +158,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 */ diff --git a/src/main.h b/src/main.h index e76f7cb..3daafc3 100644 --- a/src/main.h +++ b/src/main.h @@ -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 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_ */ - -- cgit v0.10.2