236 lines
5.6 KiB
C
236 lines
5.6 KiB
C
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
|
**********/
|
|
|
|
/* Do alias substitution. */
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/cpdefs.h"
|
|
#include "com_alias.h"
|
|
|
|
struct alias *cp_aliases = NULL;
|
|
|
|
|
|
|
|
/* Return NULL if no alias was found. We can get away with just
|
|
* calling cp_histsubst now because the line will have gone onto the
|
|
* history list by now and cp_histsubst will look in the right place. */
|
|
static wordlist *
|
|
asubst(wordlist *wlist)
|
|
{
|
|
struct alias *al;
|
|
wordlist *wl;
|
|
char *word;
|
|
|
|
word = wlist->wl_word;
|
|
if (*word == '\\') {
|
|
wlist->wl_word++; /* FIXME !!!, free() will fail !!! */
|
|
return (NULL);
|
|
}
|
|
for (al = cp_aliases; al; al = al->al_next)
|
|
if (eq(word, al->al_name))
|
|
break;
|
|
if (!al)
|
|
return (NULL);
|
|
wl = cp_histsubst(wl_copy(al->al_text));
|
|
|
|
if (cp_didhsubst) {
|
|
/* Make sure that we have an up-to-date last history entry. */
|
|
wl_free(cp_lastone->hi_wlist);
|
|
cp_lastone->hi_wlist = wl_copy(wl);
|
|
} else {
|
|
/* If it had no history args, then append the rest of the wl */
|
|
wl_append(wl, wl_copy(wlist->wl_next));
|
|
}
|
|
return (wl);
|
|
}
|
|
|
|
|
|
|
|
/* MW. This function should not use cp_lastone, see cp_parse in cpshar.c
|
|
* Many things are deleted here and memory leak closed */
|
|
wordlist *
|
|
cp_doalias(wordlist *wlist)
|
|
{
|
|
wordlist *comm;
|
|
|
|
/* The alias process is going to modify the "last" line typed, so
|
|
* save a copy of what it really is and restore it after aliasing
|
|
* is done. We have to do tricky things do get around the problems
|
|
* with ; ... */
|
|
comm = wlist;
|
|
|
|
while (comm) {
|
|
|
|
int ntries;
|
|
wordlist *end, *nextc;
|
|
|
|
nextc = wl_find(cp_csep, comm);
|
|
|
|
if(nextc == comm) { /* skip leading `;' */
|
|
comm = comm->wl_next;
|
|
continue;
|
|
}
|
|
|
|
/* Temporarily hide the rest of the command... */
|
|
end = comm->wl_prev;
|
|
wl_chop(comm);
|
|
wl_chop(nextc);
|
|
|
|
for (ntries = 21; ntries; ntries--) {
|
|
wordlist *nwl = asubst(comm);
|
|
if (nwl == NULL)
|
|
break;
|
|
if (eq(nwl->wl_word, comm->wl_word)) {
|
|
/* Just once through... */
|
|
wl_free(comm);
|
|
comm = nwl;
|
|
break;
|
|
} else {
|
|
wl_free(comm);
|
|
comm = nwl;
|
|
}
|
|
}
|
|
|
|
if (!ntries) {
|
|
fprintf(cp_err, "Error: alias loop.\n");
|
|
wlist->wl_word = NULL;
|
|
return (wlist);
|
|
}
|
|
|
|
wl_append(end, comm);
|
|
wl_append(comm, nextc);
|
|
|
|
if (!end)
|
|
wlist = comm;
|
|
|
|
comm = nextc;
|
|
}
|
|
|
|
return (wlist);
|
|
}
|
|
|
|
|
|
/* If we use this, aliases will be in alphabetical order. */
|
|
void
|
|
cp_setalias(char *word, wordlist *wlist)
|
|
{
|
|
struct alias *al, *ta;
|
|
|
|
cp_unalias(word);
|
|
cp_addkword(CT_ALIASES, word);
|
|
if (cp_aliases == NULL) {
|
|
al = cp_aliases = alloc(struct alias);
|
|
al->al_next = NULL;
|
|
al->al_prev = NULL;
|
|
} else {
|
|
for (al = cp_aliases; al->al_next; al = al->al_next) {
|
|
if (strcmp(al->al_name, word) > 0)
|
|
break;
|
|
}
|
|
/* The new one goes before al */
|
|
if (al->al_prev) {
|
|
al = al->al_prev;
|
|
ta = al->al_next;
|
|
al->al_next = alloc(struct alias);
|
|
al->al_next->al_prev = al;
|
|
al = al->al_next;
|
|
al->al_next = ta;
|
|
ta->al_prev = al;
|
|
} else {
|
|
cp_aliases = alloc(struct alias);
|
|
cp_aliases->al_next = al;
|
|
cp_aliases->al_prev = NULL;
|
|
al->al_prev = cp_aliases;
|
|
al = cp_aliases;
|
|
}
|
|
}
|
|
al->al_name = copy(word);
|
|
al->al_text = wl_copy(wlist);
|
|
cp_striplist(al->al_text);
|
|
/* We can afford to not worry about the bits, because before the
|
|
* keyword lookup is done the alias is evaluated. Make everything
|
|
* file completion, just in case... */
|
|
cp_addcomm(word, (long) 1, (long) 1, (long) 1, (long) 1);
|
|
return;
|
|
}
|
|
|
|
void
|
|
cp_unalias(char *word)
|
|
{
|
|
struct alias *al;
|
|
|
|
cp_remkword(CT_ALIASES, word);
|
|
for (al = cp_aliases; al; al = al->al_next)
|
|
if (eq(word, al->al_name))
|
|
break;
|
|
if (al == NULL)
|
|
return;
|
|
if (al->al_next)
|
|
al->al_next->al_prev = al->al_prev;
|
|
if (al->al_prev)
|
|
al->al_prev->al_next = al->al_next;
|
|
else {
|
|
al->al_next->al_prev = NULL;
|
|
cp_aliases = al->al_next;
|
|
}
|
|
wl_free(al->al_text);
|
|
tfree(al->al_name);
|
|
tfree(al);
|
|
cp_remcomm(word);
|
|
return;
|
|
}
|
|
|
|
void
|
|
cp_paliases(char *word)
|
|
{
|
|
struct alias *al;
|
|
|
|
for (al = cp_aliases; al; al = al->al_next)
|
|
if ((word == NULL) || eq(al->al_name, word)) {
|
|
if (!word)
|
|
fprintf(cp_out, "%s\t", al->al_name);
|
|
wl_print(al->al_text, cp_out);
|
|
(void) putc('\n', cp_out);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* The routine for the "alias" command. */
|
|
|
|
void
|
|
com_alias(wordlist *wl)
|
|
{
|
|
if (wl == NULL)
|
|
cp_paliases(NULL);
|
|
else if (wl->wl_next == NULL)
|
|
cp_paliases(wl->wl_word);
|
|
else
|
|
cp_setalias(wl->wl_word, wl->wl_next);
|
|
return;
|
|
}
|
|
|
|
void
|
|
com_unalias(wordlist *wl)
|
|
{
|
|
struct alias *al, *na;
|
|
|
|
if (eq(wl->wl_word, "*")) {
|
|
for (al = cp_aliases; al; al = na) {
|
|
na = al->al_next;
|
|
wl_free(al->al_text);
|
|
tfree(al->al_name);
|
|
tfree(al);
|
|
}
|
|
cp_aliases = NULL;
|
|
wl = wl->wl_next;
|
|
}
|
|
while (wl != NULL) {
|
|
cp_unalias(wl->wl_word);
|
|
wl = wl->wl_next;
|
|
}
|
|
return;
|
|
}
|
|
|