ngspice/src/frontend/com_alias.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;
}