hexpand.c revision 3e14f97f673e8a630f076077de35afdd43dc1587
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie/***********************************************************************
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* This software is part of the ast package *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* Copyright (c) 1982-2010 AT&T Intellectual Property *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* and is licensed under the *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* Common Public License, Version 1.0 *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* by AT&T Intellectual Property *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* A copy of the License is available at *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* http://www.opensource.org/licenses/cpl1.0.txt *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* Information and Software Systems Research *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* AT&T Research *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* Florham Park NJ *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* David Korn <dgk@research.att.com> *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie* *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie***********************************************************************/
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie#pragma prototyped
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie/*
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * bash style history expansion
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * Author:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * Karsten Fleischer
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf * Omnium Software Engineering
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * An der Luisenburg 7
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * D-51379 Leverkusen
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * Germany
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * <K.Fleischer@omnium.de>
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie#include "defs.h"
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie#include "edit.h"
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie#if ! SHOPT_HISTEXPAND
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arieNoN(hexpand)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie#else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661ariestatic char *modifiers = "htrepqxs&";
10a4fa49f51ed9ae1c857a626de6ce9ebf41661ariestatic int mod_flags[] = { 0, 0, 0, 0, HIST_PRINT, HIST_QUOTE, HIST_QUOTE|HIST_QUOTE_BR, 0, 0 };
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie#define DONE() {flag |= HIST_ERROR; cp = 0; stakseek(0); goto done;}
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661ariestruct subst
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie{
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie char *str[2]; /* [0] is "old", [1] is "new" string */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie};
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie/*
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * parse an /old/new/ string, delimiter expected as first char.
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * if "old" not specified, keep sb->str[0]
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * if "new" not specified, set sb->str[1] to empty string
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * read up to third delimeter char, \n or \0, whichever comes first.
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * return adress is one past the last valid char in s:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * - the address containing \n or \0 or
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * - one char beyond the third delimiter
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661ariestatic char *parse_subst(const char *s, struct subst *sb)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie{
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie char *cp,del;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie int off,n = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* build the strings on the stack, mainly for '&' substition in "new" */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie off = staktell();
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* init "new" with empty string */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(sb->str[1])
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie free(sb->str[1]);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sb->str[1] = strdup("");
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* get delimiter */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie del = *s;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp = (char*) s + 1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while(n < 2)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*cp == del || *cp == '\n' || *cp == '\0')
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* delimiter or EOL */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(staktell() != off)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* dupe string on stack and rewind stack */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc('\0');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(sb->str[n])
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie free(sb->str[n]);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sb->str[n] = strdup(stakptr(off));
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakseek(off);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* if not delimiter, we've reached EOL. Get outta here. */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*cp != del)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else if(*cp == '\\')
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*(cp+1) == del) /* quote delimiter */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(del);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else if(*(cp+1) == '&' && n == 1)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie { /* quote '&' only in "new" */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc('&');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc('\\');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else if(*cp == '&' && n == 1 && sb->str[0])
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* substitute '&' with "old" in "new" */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputs(sb->str[0]);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(*cp);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* rewind stack */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakseek(off);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie return cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie}
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie/*
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie * history expansion main routine
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arieint hist_expand(const char *ln, char **xp)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie{
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie int off, /* stack offset */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie q, /* quotation flags */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie p, /* flag */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie c, /* current char */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag=0; /* HIST_* flags */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie Sfoff_t n, /* history line number, counter, etc. */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie i, /* counter */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[2]; /* word range */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie char *sp, /* stack pointer */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp, /* current char in ln */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *str, /* search string */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *evp, /* event/word designator string, for error msgs */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cc=0, /* copy of current line up to cp; temp ptr */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie hc[3], /* default histchars */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *qc="\'\"`"; /* quote characters */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie Sfio_t *ref=0, /* line referenced by event designator */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *tmp=0, /* temporary line buffer */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *tmp2=0;/* temporary line buffer */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie Histloc_t hl; /* history location */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie static Namval_t *np = 0; /* histchars variable */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie static struct subst sb = {0,0}; /* substition strings */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie static Sfio_t *wm=0; /* word match from !?string? event designator */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(!wm)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie wm = sfopen(NULL, NULL, "swr");
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie hc[0] = '!';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie hc[1] = '^';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie hc[2] = 0;
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if((np = nv_open("histchars",sh.var_tree,0)) && (cp = nv_getval(np)))
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(cp[0])
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf hc[0] = cp[0];
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(cp[1])
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf hc[1] = cp[1];
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(cp[2])
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf hc[2] = cp[2];
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* save shell stack */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(off = staktell())
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sp = stakfreeze(0);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp = (char*)ln;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf while(cp && *cp)
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf {
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf /* read until event/quick substitution/comment designator */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if((*cp != hc[0] && *cp != hc[1] && *cp != hc[2])
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie || (*cp == hc[1] && cp != ln))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*cp == '\\') /* skip escaped designators */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(*cp++);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else if(*cp == '\'') /* skip quoted designators */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie do
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(*cp);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while(*++cp && *cp != '\'');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(*cp++);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie continue;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(hc[2] && *cp == hc[2]) /* history comment designator, skip rest of line */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(*cp++);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputs(cp);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie DONE();
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = -1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie str = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag &= HIST_EVENT; /* save event flag for returning later */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie evp = cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie ref = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*cp == hc[1]) /* shortcut substitution */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_QUICKSUBST;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto getline;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*cp == hc[0] && *(cp+1) == hc[0]) /* refer to line -1 */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp += 2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto getline;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie switch(c = *++cp) {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case ' ':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '\t':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '\n':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '\0':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '=':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '(':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc(hc[0]);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie continue;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '#': /* the line up to current position */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_HASH;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = staktell(); /* terminate string and dup */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakputc('\0');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cc = strdup(stakptr(0));
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie stakseek(n); /* remove null byte again */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie ref = sfopen(ref, cc, "s"); /* open as file */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 0; /* skip history file referencing */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '-': /* back reference by number */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(!isdigit(*(cp+1)))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto string_event;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '0': /* reference by number */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '1':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '2':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '3':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '4':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '5':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '6':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '7':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '8':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '9':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while(isdigit(*cp))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = n * 10 + (*cp++) - '0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(c == '-')
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = -n;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '$':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = -1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case ':':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '?':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_QUESTION;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie string_event:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie default:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* read until end of string or word designator/modifier */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie str = cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while(*cp)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if((!(flag&HIST_QUESTION) &&
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie (*cp == ':' || isspace(*cp)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie || *cp == '^' || *cp == '$'
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie || *cp == '*' || *cp == '-'
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie || *cp == '%')
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie )
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie || ((flag&HIST_QUESTION) && (*cp == '?' || *cp == '\n')))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie c = *cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp = '\0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcrafgetline:
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf flag |= HIST_EVENT;
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf if(str) /* !string or !?string? event designator */
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf {
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf /* search history for string */
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf hl = hist_find(sh.hist_ptr, str,
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sh.hist_ptr->histind,
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag&HIST_QUESTION, -1);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if((n = hl.hist_command) == -1)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 0; /* not found */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n < 0) /* determine index for backref */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = sh.hist_ptr->histind + n;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* search and use history file if found */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n > 0 && hist_seek(sh.hist_ptr, n) != -1)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie ref = sh.hist_ptr->histfp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(!ref)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* string not found or command # out of range */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie c = *cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp = '\0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie errormsg(SH_DICT, ERROR_ERROR, "%s: event not found", evp);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp = c;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie DONE();
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(str) /* string search: restore orig. line */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(flag&HIST_QUESTION)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp++ = c; /* skip second question mark */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp = c;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* colon introduces either word designators or modifiers */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(*(evp = cp) == ':')
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[0] = 0; /* -1 means last word, -2 means match from !?string? */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[1] = -1; /* -1 means last word, -2 means suppress last word */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(flag & HIST_QUICKSUBST) /* shortcut substitution */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto getsel;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while(n < 2)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie switch(c = *cp++) {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '^': /* first word */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n == 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[0] = w[1] = 1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto skip;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto skip2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '$': /* last word */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[n] = -1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto skip;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '%': /* match from !?string? event designator */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n == 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(!str)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[0] = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[1] = -1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie ref = wm;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[0] = -2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[1] = sftell(ref) + hl.hist_char;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfseek(wm, 0, SEEK_SET);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie goto skip;
cce0e03bb2d07f0fe27cabb93acae9c23655859fab }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie default:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie skip2:
cce0e03bb2d07f0fe27cabb93acae9c23655859fab cp--;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '*': /* until last word */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n == 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[0] = 1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[1] = -1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie skip:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_WORDDSGN;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '-': /* until last word or specified index */
d326b23bcecd3c0d693a54003343ec3de73e58d0rie w[1] = -2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_WORDDSGN;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '0':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '1':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '2':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '3':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '4':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '5':
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf case '6':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '7':
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie case '8':
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf case '9': /* specify index */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if((*evp == ':') || w[1] == -2)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf w[n] = c - '0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while(isdigit(c=*cp++))
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf w[n] = w[n] * 10 + c - '0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_WORDDSGN;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n == 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie w[1] = w[0];
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = 2;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp--;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf if(w[0] != -2 && w[1] > 0 && w[0] > w[1])
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie c = *cp;
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf *cp = '\0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie errormsg(SH_DICT, ERROR_ERROR, "%s: bad word specifier", evp);
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf *cp = c;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie DONE();
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* no valid word designator after colon, rewind */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(!(flag & HIST_WORDDSGN) && (*evp == ':'))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cp = evp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661ariegetsel:
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* open temp buffer, let sfio do the (re)allocation */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie tmp = sfopen(NULL, NULL, "swr");
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* push selected words into buffer, squash
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie whitespace into single blank or a newline */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n = i = q = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while((c = sfgetc(ref)) > 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(isspace(c))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= (c == '\n' ? HIST_NEWLINE : 0);
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf continue;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
8cd45542f2a452ca0dab13d8b2d5cfa876ccbebcraf
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(n >= w[0] && ((w[0] != -2) ? (w[1] < 0 || n <= w[1]) : 1))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(w[0] < 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfseek(tmp, 0, SEEK_SET);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie i = sftell(tmp);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(i > 0)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfputc(tmp, flag & HIST_NEWLINE ? '\n' : ' ');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag &= ~HIST_NEWLINE;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie p = 1;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie p = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie do
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cc = strchr(qc, c);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie q ^= cc ? 1<<(int)(cc - qc) : 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(p)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfputc(tmp, c);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie while((c = sfgetc(ref)) > 0 && (!isspace(c) || q));
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(w[0] == -2 && sftell(ref) > w[1])
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie break;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= (c == '\n' ? HIST_NEWLINE : 0);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie n++;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(w[0] != -2 && w[1] >= 0 && w[1] >= n)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie c = *cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp = '\0';
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie errormsg(SH_DICT, ERROR_ERROR, "%s: bad word specifier", evp);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cp = c;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie DONE();
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else if(w[1] == -2) /* skip last word */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfseek(tmp, i, SEEK_SET);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* remove trailing newline */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(sftell(tmp))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfseek(tmp, -1, SEEK_CUR);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(sfgetc(tmp) == '\n')
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfungetc(tmp, '\n');
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfputc(tmp, '\0');
7257d1b4d25bfac0c802847390e98a464fd787acraf
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(str)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
7257d1b4d25bfac0c802847390e98a464fd787acraf if(wm)
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfclose(wm);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie wm = tmp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
7257d1b4d25bfac0c802847390e98a464fd787acraf if(cc && (flag&HIST_HASH))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie /* close !# temp file */
7257d1b4d25bfac0c802847390e98a464fd787acraf sfclose(ref);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag &= ~HIST_HASH;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie free(cc);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie cc = 0;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf evp = cp;
7257d1b4d25bfac0c802847390e98a464fd787acraf
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf /* selected line/words are now in buffer, now go for the modifiers */
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf while(*cp == ':' || (flag & HIST_QUICKSUBST))
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf {
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf if(flag & HIST_QUICKSUBST)
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf {
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf flag &= ~HIST_QUICKSUBST;
7257d1b4d25bfac0c802847390e98a464fd787acraf c = 's';
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf cp--;
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf }
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf else
494a4c5197688884a8a9a926ffc8d6627ba3bc1braf c = *++cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie sfseek(tmp, 0, SEEK_SET);
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie tmp2 = sfopen(tmp2, NULL, "swr");
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
7257d1b4d25bfac0c802847390e98a464fd787acraf if(c == 'g') /* global substitution */
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie {
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= HIST_GLOBALSUBST;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie c = *++cp;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie }
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie if(cc = strchr(modifiers, c))
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie flag |= mod_flags[cc - modifiers];
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie else
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf errormsg(SH_DICT, ERROR_ERROR, "%c: unrecognized history modifier", c);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf DONE();
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(c == 'h' || c == 'r') /* head or base */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf n = -1;
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf while((c = sfgetc(tmp)) > 0)
7257d1b4d25bfac0c802847390e98a464fd787acraf { /* remember position of / or . */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if((c == '/' && *cp == 'h') || (c == '.' && *cp == 'r'))
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf n = sftell(tmp2);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf sfputc(tmp2, c);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(n > 0)
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf { /* rewind to last / or . */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf sfseek(tmp2, n, SEEK_SET);
7257d1b4d25bfac0c802847390e98a464fd787acraf /* end string there */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf sfputc(tmp2, '\0');
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf else if(c == 't' || c == 'e') /* tail or suffix */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf n = 0;
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf while((c = sfgetc(tmp)) > 0)
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf { /* remember position of / or . */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if((c == '/' && *cp == 't') || (c == '.' && *cp == 'e'))
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf n = sftell(tmp);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf /* rewind to last / or . */
7257d1b4d25bfac0c802847390e98a464fd787acraf sfseek(tmp, n, SEEK_SET);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf /* copy from there on */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf while((c = sfgetc(tmp)) > 0)
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf sfputc(tmp2, c);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf else if(c == 's' || c == '&')
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf cp++;
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(c == 's')
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf /* preset old with match from !?string? */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(!sb.str[0] && wm)
7257d1b4d25bfac0c802847390e98a464fd787acraf sb.str[0] = strdup(sfsetbuf(wm, (Void_t*)1, 0));
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf cp = parse_subst(cp, &sb);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(!sb.str[0] || !sb.str[1])
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf c = *cp;
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf *cp = '\0';
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf errormsg(SH_DICT, ERROR_ERROR,
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf "%s%s: no previous substitution",
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf (flag & HIST_QUICKSUBST) ? ":s" : "",
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf evp);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf *cp = c;
7257d1b4d25bfac0c802847390e98a464fd787acraf DONE();
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf }
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf /* need pointer for strstr() */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf str = sfsetbuf(tmp, (Void_t*)1, 0);
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf flag |= HIST_SUBSTITUTE;
7257d1b4d25bfac0c802847390e98a464fd787acraf while(flag & HIST_SUBSTITUTE)
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf {
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf /* find string */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf if(cc = strstr(str, sb.str[0]))
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf { /* replace it */
a574db851cdc636fc3939b68e80d79fe7fbd57f2raf c = *cc;
10a4fa49f51ed9ae1c857a626de6ce9ebf41661arie *cc = '\0';
sfputr(tmp2, str, -1);
sfputr(tmp2, sb.str[1], -1);
*cc = c;
str = cc + strlen(sb.str[0]);
}
else if(!sftell(tmp2))
{ /* not successfull */
c = *cp;
*cp = '\0';
errormsg(SH_DICT, ERROR_ERROR,
"%s%s: substitution failed",
(flag & HIST_QUICKSUBST) ? ":s" : "",
evp);
*cp = c;
DONE();
}
/* loop if g modifier specified */
if(!cc || !(flag & HIST_GLOBALSUBST))
flag &= ~HIST_SUBSTITUTE;
}
/* output rest of line */
sfputr(tmp2, str, -1);
if(*cp)
cp--;
}
if(sftell(tmp2))
{ /* if any substitions done, swap buffers */
if(wm != tmp)
sfclose(tmp);
tmp = tmp2;
tmp2 = 0;
}
cc = 0;
if(*cp)
cp++;
}
/* flush temporary buffer to stack */
if(tmp)
{
sfseek(tmp, 0, SEEK_SET);
if(flag & HIST_QUOTE)
stakputc('\'');
while((c = sfgetc(tmp)) > 0)
{
if(isspace(c))
{
flag = flag & ~HIST_NEWLINE;
/* squash white space to either a
blank or a newline */
do
flag |= (c == '\n' ? HIST_NEWLINE : 0);
while((c = sfgetc(tmp)) > 0 && isspace(c));
sfungetc(tmp, c);
c = (flag & HIST_NEWLINE) ? '\n' : ' ';
if(flag & HIST_QUOTE_BR)
{
stakputc('\'');
stakputc(c);
stakputc('\'');
}
else
stakputc(c);
}
else if((c == '\'') && (flag & HIST_QUOTE))
{
stakputc('\'');
stakputc('\\');
stakputc(c);
stakputc('\'');
}
else
stakputc(c);
}
if(flag & HIST_QUOTE)
stakputc('\'');
}
}
stakputc('\0');
done:
if(cc && (flag&HIST_HASH))
{
/* close !# temp file */
sfclose(ref);
free(cc);
cc = 0;
}
/* error? */
if(staktell() && !(flag & HIST_ERROR))
*xp = strdup(stakfreeze(1));
/* restore shell stack */
if(off)
stakset(sp,off);
else
stakseek(0);
/* drop temporary files */
if(tmp && tmp != wm)
sfclose(tmp);
if(tmp2)
sfclose(tmp2);
return (flag & HIST_ERROR ? HIST_ERROR : flag & HIST_FLAG_RETURN_MASK);
}
#endif