2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
3
Copyright (C) 2005- The University of Notre Dame
4
This software is distributed under the GNU General Public License.
5
See the file COPYING for details.
10
#include "ftsh_error.h"
12
#include "stringtools.h"
27
static struct vstack *head=0;
28
static int vstackdepth=0;
30
#define ISVALID(x) (isalpha(x) || isdigit(x) || (x=='_') || (x=='$') || (x=='#') || (x=='@') || (x=='*') )
32
static int isvalid( const char *n )
35
if(!ISVALID((int)(*n))) return 0;
41
int variable_frame_push( int line, int argc, char **argv )
46
if(vstackdepth>1000) {
47
ftsh_error(FTSH_ERROR_FAILURE,line,"aborting: you have recursed %d times",vstackdepth);
51
v = malloc(sizeof(*v));
53
ftsh_error(FTSH_ERROR_FAILURE,line,"out of memory");
62
for( i=0; i<argc; i++ ) {
63
ftsh_error(FTSH_ERROR_STRUCTURE,line,"${%d} = %s",i,argv[i]);
72
void variable_frame_pop()
79
ftsh_fatal(0,"stack underflow");
87
void variable_rval_set( char *rval )
92
char * variable_rval_get()
97
int variable_shift( int n, int line )
103
for(i=0;i<head->argc;i++) {
104
head->argv[i] = head->argv[i+n];
108
ftsh_error(FTSH_ERROR_SYNTAX,line,"cannot shift %d arguments; there are only %d",n,head->argc);
113
static char * variable_print_argv( int withquotes )
118
result = xstrdup("");
120
for(i=1;i<head->argc;i++) {
121
result = string_combine(result,xstrdup(head->argv[i]));
122
if(i!=(head->argc-1)) {
124
result = string_combine(result,xstrdup("\" \""));
126
result = string_combine(result,xstrdup(" "));
134
static char * variable_get( const char *name, int line, int withquotes )
139
if(!strcmp(name,"$")) {
140
sprintf(buffer,"%d",(int)getpid());
141
return xstrdup(buffer);
142
} else if(!strcmp(name,"#")) {
143
sprintf(buffer,"%d",head->argc-1);
144
return xstrdup(buffer);
145
} else if(!strcmp(name,"@")) {
146
return variable_print_argv(withquotes);
147
} else if(!strcmp(name,"*")) {
148
return variable_print_argv(0);
149
} else if( sscanf(name,"%d",&arg)==1 ) {
150
if(arg>=head->argc) {
153
return xstrdup(head->argv[arg]);
155
} else if( isvalid(name) ) {
156
char *result = getenv(name);
157
if(result) return xstrdup(result);
158
result = buffer_load(name);
159
if(result) string_chomp(result);
162
ftsh_fatal(line,"${%s} is an invalid variable name!",name);
167
char * variable_subst( char *value, int line )
169
char *subvalue, *newvalue;
170
char *dollar, *start, *end;
171
char terminator, oldend;
178
/* Find a non-escaped dollar */
180
for( dollar=value; *dollar; dollar++ ) {
186
} else if(*dollar=='$') {
192
/* If we didn't find it, stop. */
194
if(!*dollar) return value;
196
/* Is the variable name bracketed? */
198
if( *(dollar+1)=='{' ) {
201
} else if( *(dollar+1)=='(' ) {
210
end = strchr(start,terminator);
212
for(end=start;ISVALID(*end);end++) {
217
if(terminator && !end) {
218
ftsh_error(FTSH_ERROR_FAILURE,line,"variable reference began with %c but didn't end",*(dollar+1));
223
ftsh_error(FTSH_ERROR_FAILURE,line,"empty variable reference");
228
(dollar>value && *(dollar-1)=='\"') &&
238
subvalue = variable_get(start,line,withquotes);
242
subvalue = xstrdup("");
245
length = strlen(value) - (end-dollar) + strlen(subvalue) + 1;
247
newvalue = malloc(length);
256
strcpy(newvalue,value);
257
strcat(newvalue,subvalue);
258
if(terminator && *end) {
259
strcat(newvalue,end+1);
261
strcat(newvalue,end);