1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/* alias.c
*
* Alias expansion and maintenance for lafe.
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lafe.h"
static int aliases=0;
static char **key=NULL; /* alias names */
static char **value=NULL; /* alias definitions */
static int width=0; /* size of largest alias key */
static void print_aliases() {
int i;
for (i=0;i<aliases;i++) {
printf("%-*s %s\n",width,key[i],value[i]);
}
printf(" %d aliases\n",aliases);
return;
}
/* look up name in alias database and return index. Should do a
* binary search. Returns -1 if name is not found. */
static int find_alias(char *name) {
int i;
for (i=0;i<aliases;i++) {
if (!strcmp(name,key[i])) return i;
}
return -1;
}
static void remove_alias(char *name) {
int i;
i = find_alias(name);
if (i>=0) {
free(key[i]);
free(value[i]);
aliases--;
key[i]=key[aliases];
value[i]=value[aliases];
} else {
printf("%s not defined\n",name);
}
}
static void define_alias(char *name,char *definition) {
int i;
int w;
w=strlen(name);
if (w>width) width=w;
i=find_alias(name);
if (i>=0) {
free(value[i]);
value[i]=strdup(definition);
} else {
key=realloc(key,(aliases+1) * sizeof(*key));
value=realloc(value,(aliases+1) * sizeof(*value));
key[aliases]=strdup(name);
value[aliases]=strdup(definition);
aliases++;
}
}
/* alias expansion. Tokenizes arg and adds tokens to environment $1 $2 .... */
/* not finished */
static void tokenize(char *arg) {
int start,end;
char c,buffer[8];
int i;
putvar("*",arg);
/* put each fragment of arg into environment variables */
i=0;
for (start=0;arg[start];start++) {
if (!isspace(arg[start])) {
for (end=start+1;arg[end] && !isspace(arg[end]);end++) ;
c=arg[end];
arg[end]=0;
sprintf(buffer,"%d",++i);
putvar(buffer,arg+start);
arg[end]=c;
start=end;
}
}
sprintf(buffer,"%d",++i);
clearvar(buffer);
}
/* line must be individually malloced. If the alias is expanded, line will
be freed by expand_alias, and a new line returned */
char *expand_alias(char *line) {
int i,j,k;
char *alias,*semi;
for (i=0;line[i] && isspace(line[i]);i++) ;
for (j=i;line[j] && !isspace(line[j]);j++) ;
/* attempt to locate the alias index for this line */
{
char c;
c=line[j]; line[j]=0;
k=find_alias(line+i);
line[j]=c;
}
/* no alias found, so return line */
if (k<0) return line;
/* expand ;'s in alias */
alias=strdup(value[k]);
semi=strchr(alias,';');
while (semi) {
*semi='\n';
semi=strchr(semi+1,';');
}
/* advance j to next character */
for (;line[j] && isspace(line[j]);j++) ;
/* if there are $'s in the alias, fill variables and return alias value */
if (strchr(alias,'$') || strchr(alias,'\n')) {
tokenize(line+j);
free(line);
return alias;
/* otherwise, replace the first word and append arguments */
} else {
int len;
char *newline;
len=strlen(alias);
newline=malloc(len+strlen(line+j)+2);
strcpy(newline,alias);
newline[len]=' ';
strcpy(newline+len+1,line+j);
free(line);
free(alias);
return newline;
}
}
/* no arguments prints the alias database.
* one argument delete the alias for that argument.
* two arguments defines a new alias.
*/
void alias(char *line) {
int i,j,k;
i=0;
/* print alias database */
if (!line || !*line) {
print_aliases();
return;
}
/* alias name starts at i, ends at j. Def starts at k. */
/* get name of new or old alias */
for (j=i;line[j] && !isspace(line[j]);j++) ;
/* skip whitespace */
for (k=j;line[k] && isspace(line[k]);k++) ;
/* delete definition of name */
if (!line[k]) {
line[j]=0;
remove_alias(line+i);
return;
}
line[j]=0;
define_alias(line+i,line+k);
}
|