~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to ftsh/src/variable.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
6
*/
 
7
 
 
8
#include "xmalloc.h"
 
9
#include "buffer.h"
 
10
#include "ftsh_error.h"
 
11
#include "list.h"
 
12
#include "stringtools.h"
 
13
 
 
14
#include <stdio.h>
 
15
#include <stdlib.h>
 
16
#include <string.h>
 
17
#include <unistd.h>
 
18
#include <ctype.h>
 
19
 
 
20
struct vstack {
 
21
        int argc;
 
22
        char **argv;
 
23
        char *rval;
 
24
        struct vstack *next;
 
25
};
 
26
 
 
27
static struct vstack *head=0;
 
28
static int vstackdepth=0;
 
29
 
 
30
#define ISVALID(x) (isalpha(x) || isdigit(x) || (x=='_') || (x=='$') || (x=='#') || (x=='@')  || (x=='*') )
 
31
 
 
32
static int isvalid( const char *n )
 
33
{
 
34
        while(*n) {
 
35
                if(!ISVALID((int)(*n))) return 0;
 
36
                n++;
 
37
        }
 
38
        return 1;
 
39
}
 
40
 
 
41
int variable_frame_push( int line, int argc, char **argv )
 
42
{
 
43
        struct vstack *v;
 
44
        int i;
 
45
 
 
46
        if(vstackdepth>1000) {
 
47
                ftsh_error(FTSH_ERROR_FAILURE,line,"aborting: you have recursed %d times",vstackdepth);
 
48
                return 0;
 
49
        }
 
50
 
 
51
        v = malloc(sizeof(*v));
 
52
        if(!v) {
 
53
                ftsh_error(FTSH_ERROR_FAILURE,line,"out of memory");
 
54
                return 0;
 
55
        }
 
56
 
 
57
        v->argc = argc;
 
58
        v->argv = argv;
 
59
        v->rval = 0;
 
60
        v->next = head;
 
61
 
 
62
        for( i=0; i<argc; i++ ) {
 
63
                ftsh_error(FTSH_ERROR_STRUCTURE,line,"${%d} = %s",i,argv[i]);
 
64
        }
 
65
 
 
66
        head = v;
 
67
        vstackdepth++;
 
68
 
 
69
        return 1;
 
70
}
 
71
 
 
72
void variable_frame_pop()
 
73
{
 
74
        struct vstack *v;
 
75
 
 
76
        v = head;
 
77
 
 
78
        if(!v || !v->next ) {
 
79
                ftsh_fatal(0,"stack underflow");
 
80
        }
 
81
 
 
82
        head = v->next;
 
83
        free(v);
 
84
        vstackdepth--;
 
85
}
 
86
 
 
87
void   variable_rval_set( char *rval )
 
88
{
 
89
        head->rval = rval;
 
90
}
 
91
 
 
92
char * variable_rval_get()
 
93
{
 
94
        return head->rval;
 
95
}
 
96
 
 
97
int variable_shift( int n, int line )
 
98
{
 
99
        int i;
 
100
 
 
101
        if(head->argc>=n) {
 
102
                head->argc-=n;
 
103
                for(i=0;i<head->argc;i++) {
 
104
                        head->argv[i] = head->argv[i+n];
 
105
                }
 
106
                return 1;
 
107
        } else {
 
108
                ftsh_error(FTSH_ERROR_SYNTAX,line,"cannot shift %d arguments; there are only %d",n,head->argc);
 
109
                return 0;
 
110
        }
 
111
}
 
112
 
 
113
static char * variable_print_argv( int withquotes )
 
114
{
 
115
        char *result=0;
 
116
        int i;
 
117
 
 
118
        result = xstrdup("");
 
119
 
 
120
        for(i=1;i<head->argc;i++) {
 
121
                result = string_combine(result,xstrdup(head->argv[i]));
 
122
                if(i!=(head->argc-1)) {
 
123
                        if(withquotes) {
 
124
                                result = string_combine(result,xstrdup("\" \""));
 
125
                        } else {
 
126
                                result = string_combine(result,xstrdup(" "));
 
127
                        }
 
128
                }
 
129
        }
 
130
 
 
131
        return result;
 
132
}
 
133
 
 
134
static char * variable_get( const char *name, int line, int withquotes )
 
135
{
 
136
        char buffer[100];
 
137
        int arg;
 
138
 
 
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) {
 
151
                        return xstrdup("");
 
152
                } else {
 
153
                        return xstrdup(head->argv[arg]);
 
154
                }
 
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);
 
160
                return result;
 
161
        } else {
 
162
                ftsh_fatal(line,"${%s} is an invalid variable name!",name);
 
163
                return 0;
 
164
        }
 
165
}
 
166
 
 
167
char * variable_subst( char *value, int line )
 
168
{
 
169
        char *subvalue, *newvalue;
 
170
        char *dollar, *start, *end;
 
171
        char terminator, oldend;
 
172
        int length;
 
173
        int withquotes = 0;
 
174
        int escape = 0;
 
175
 
 
176
        while(1) {
 
177
 
 
178
                /* Find a non-escaped dollar */
 
179
 
 
180
                for( dollar=value; *dollar; dollar++ ) {
 
181
                        if(escape) {
 
182
                                escape = 0;
 
183
                        } else {
 
184
                                if(*dollar=='\\') {
 
185
                                        escape = 1;
 
186
                                } else if(*dollar=='$') {
 
187
                                        break;
 
188
                                }
 
189
                        }
 
190
                }
 
191
 
 
192
                /* If we didn't find it, stop. */
 
193
 
 
194
                if(!*dollar) return value;
 
195
 
 
196
                /* Is the variable name bracketed? */
 
197
 
 
198
                if( *(dollar+1)=='{' ) {
 
199
                        start = dollar+2;
 
200
                        terminator = '}';
 
201
                } else if( *(dollar+1)=='(' ) {
 
202
                        start = dollar+2;
 
203
                        terminator = ')';
 
204
                } else {
 
205
                        start = dollar+1;
 
206
                        terminator = 0;
 
207
                }
 
208
 
 
209
                if(terminator) {
 
210
                        end = strchr(start,terminator);
 
211
                } else {
 
212
                        for(end=start;ISVALID(*end);end++) {
 
213
                                /* nothing */
 
214
                        }
 
215
                }
 
216
 
 
217
                if(terminator && !end) {
 
218
                        ftsh_error(FTSH_ERROR_FAILURE,line,"variable reference began with %c but didn't end",*(dollar+1));
 
219
                        return 0;
 
220
                }
 
221
 
 
222
                if((end-start)<1) {
 
223
                        ftsh_error(FTSH_ERROR_FAILURE,line,"empty variable reference");
 
224
                        return 0;
 
225
                }
 
226
 
 
227
                withquotes =
 
228
                        (dollar>value && *(dollar-1)=='\"') &&
 
229
                        (*end) &&
 
230
                        (terminator
 
231
                                ? *(end+1)=='\"'
 
232
                                : *end=='\"'
 
233
                        );
 
234
 
 
235
                oldend = *end;
 
236
                *end = 0;
 
237
 
 
238
                subvalue = variable_get(start,line,withquotes);
 
239
                *end = oldend;
 
240
 
 
241
                if(!subvalue) {
 
242
                        subvalue = xstrdup("");
 
243
                }
 
244
 
 
245
                length = strlen(value) - (end-dollar) + strlen(subvalue) + 1;
 
246
 
 
247
                newvalue = malloc(length);
 
248
                if(!newvalue) {
 
249
                        free(subvalue);
 
250
                        free(value);
 
251
                        return 0;
 
252
                }
 
253
 
 
254
                *dollar = 0;
 
255
 
 
256
                strcpy(newvalue,value);
 
257
                strcat(newvalue,subvalue);
 
258
                if(terminator && *end) {
 
259
                        strcat(newvalue,end+1);
 
260
                } else {
 
261
                        strcat(newvalue,end);
 
262
                }
 
263
                free(subvalue);
 
264
                free(value);
 
265
 
 
266
                value = newvalue;
 
267
        }
 
268
}
 
269