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

« back to all changes in this revision

Viewing changes to ftsh/src/expr.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 "expr.h"
 
9
#include "ftsh_error.h"
 
10
#include "ast_execute.h"
 
11
#include "ast_print.h"
 
12
 
 
13
#include "xmalloc.h"
 
14
#include "macros.h"
 
15
 
 
16
#include <stdio.h>
 
17
#include <stdlib.h>
 
18
#include <string.h>
 
19
#include <unistd.h>
 
20
#include <sys/types.h>
 
21
#include <sys/stat.h>
 
22
#include <errno.h>
 
23
#include <limits.h>
 
24
 
 
25
static void expr_print_list( FILE *file, struct expr *e, int with_commas );
 
26
 
 
27
struct expr_table {
 
28
        const char *string;
 
29
        enum expr_type_t type;
 
30
};
 
31
 
 
32
static struct expr_table table[] = {
 
33
        {".add.",EXPR_ADD},
 
34
        {".sub.",EXPR_SUB},
 
35
        {".mul.",EXPR_MUL},
 
36
        {".div.",EXPR_DIV},
 
37
        {".mod.",EXPR_MOD},
 
38
        {".pow.",EXPR_POW},
 
39
        {".eq.",EXPR_EQ},
 
40
        {".ne.",EXPR_NE},
 
41
        {".eql.",EXPR_EQL},
 
42
        {".neql.",EXPR_NEQL},
 
43
        {".lt.",EXPR_LT},
 
44
        {".le.",EXPR_LE},
 
45
        {".gt.",EXPR_GT},
 
46
        {".ge.",EXPR_GE},
 
47
        {".and.",EXPR_AND},
 
48
        {".or.",EXPR_OR},
 
49
        {".not.",EXPR_NOT},
 
50
        {".exists.",EXPR_EXISTS},
 
51
        {".isr.",EXPR_ISR},
 
52
        {".isw.",EXPR_ISW},
 
53
        {".isx.",EXPR_ISX},
 
54
        {".isblock.",EXPR_ISBLOCK},
 
55
        {".ischar.",EXPR_ISCHAR},
 
56
        {".isdir.",EXPR_ISDIR},
 
57
        {".isfile.",EXPR_ISFILE},
 
58
        {".islink.",EXPR_ISLINK},
 
59
        {".ispipe.",EXPR_ISPIPE},
 
60
        {".issock.",EXPR_ISSOCK},
 
61
        {0,0}
 
62
};
 
63
 
 
64
const char *expr_type_to_string( enum expr_type_t type )
 
65
{
 
66
        struct expr_table *t;
 
67
 
 
68
        for(t=table;t->string;t++) {
 
69
                if(t->type==type) return t->string;
 
70
        }
 
71
 
 
72
        return 0;
 
73
}
 
74
 
 
75
static int digits_in_int( int i )
 
76
{
 
77
        int digits=0;
 
78
        do {
 
79
                digits++;
 
80
                i/=10;
 
81
        } while(i>0);
 
82
        return digits;
 
83
}
 
84
 
 
85
struct expr * expr_create( int line, enum expr_type_t type, struct ast_word *literal, struct expr *a, struct expr *b, struct expr *c )
 
86
{
 
87
        struct expr *e = xxmalloc(sizeof(*e));
 
88
        e->line = line;
 
89
        e->literal = literal;
 
90
        e->type = type;
 
91
        e->a = a;
 
92
        e->b = b;
 
93
        e->c = c;
 
94
        e->next = 0;
 
95
        return e;
 
96
}
 
97
 
 
98
int expr_to_integer( struct expr *e, ftsh_integer_t *ival, time_t stoptime )
 
99
{
 
100
        char *value;
 
101
        char *end;
 
102
 
 
103
        value = expr_eval(e,stoptime);
 
104
        if(!value) return 0;
 
105
 
 
106
        *ival = strtol(value,&end,10);
 
107
        if(!*end) {
 
108
                /* good conversion */
 
109
                free(value);
 
110
                return 1;
 
111
        } else {
 
112
                ftsh_error(FTSH_ERROR_FAILURE,e->line,"expected integer but got '%s' instead",value);
 
113
                free(value);
 
114
                return 0;
 
115
        }
 
116
}
 
117
 
 
118
int expr_to_boolean( struct expr *e, ftsh_boolean_t *bval, time_t stoptime )
 
119
{
 
120
        char *value;
 
121
 
 
122
        value = expr_eval(e,stoptime);
 
123
        if(!value) return 0;
 
124
 
 
125
        if(!strcmp(value,"true")) {
 
126
                free(value);
 
127
                *bval = 1;
 
128
                return 1;
 
129
        } else if(!strcmp(value,"false")) {
 
130
                free(value);
 
131
                *bval = 0;
 
132
                return 1;
 
133
        } else {
 
134
                ftsh_error(FTSH_ERROR_FAILURE,e->line,"expected 'true' or 'false' but got %s instead",value);
 
135
                free(value);
 
136
                return 0;
 
137
        }
 
138
}
 
139
 
 
140
static char * integer_to_string( int line, ftsh_integer_t i )
 
141
{
 
142
        char istr[256];
 
143
        char *s;
 
144
 
 
145
        sprintf(istr,"%ld",i);
 
146
        s = strdup(istr);
 
147
 
 
148
        if(!s) {
 
149
                ftsh_error(FTSH_ERROR_FAILURE,line,"out of memory");
 
150
        }
 
151
 
 
152
        return s;
 
153
}
 
154
 
 
155
static char * boolean_to_string( int line, ftsh_boolean_t b )
 
156
{
 
157
        char *s;
 
158
 
 
159
        if(b) {
 
160
                s = strdup("true");
 
161
        } else {
 
162
                s = strdup("false");
 
163
        }
 
164
 
 
165
        if(!s) {
 
166
                ftsh_error(FTSH_ERROR_FAILURE,line,"out of memory");
 
167
        }
 
168
 
 
169
        return s;
 
170
}
 
171
 
 
172
static char * expr_eval_access( struct expr *e, time_t stoptime )
 
173
{
 
174
        char *path;
 
175
        char *result;
 
176
        int ival;
 
177
        int mode;
 
178
 
 
179
        path = expr_eval(e->a,stoptime);
 
180
        if(!path) return 0;
 
181
 
 
182
        switch(e->type) {
 
183
                case EXPR_EXISTS:
 
184
                        mode = F_OK;
 
185
                        break;
 
186
                case EXPR_ISR:
 
187
                        mode = R_OK;
 
188
                        break;
 
189
                case EXPR_ISW:
 
190
                        mode = W_OK;
 
191
                        break;
 
192
                case EXPR_ISX:
 
193
                        mode = X_OK;
 
194
                        break;
 
195
                default:
 
196
                        ftsh_fatal(e->line,"unexpected expression type %d",e->type);
 
197
                        break;
 
198
        }
 
199
 
 
200
        ival = access(path,mode);
 
201
        if(ival!=0) {
 
202
                switch(errno) {
 
203
                        #ifdef EACCES
 
204
                        case EACCES:
 
205
                        #endif
 
206
 
 
207
                        #ifdef EROFS
 
208
                        case EROFS:
 
209
                        #endif
 
210
 
 
211
                        #ifdef ENOENT
 
212
                        case ENOENT:
 
213
                        #endif
 
214
 
 
215
                        #ifdef ENOTDIR
 
216
                        case ENOTDIR:
 
217
                        #endif
 
218
 
 
219
                        #ifdef ELOOP
 
220
                        case ELOOP:
 
221
                        #endif
 
222
                                result = xstrdup("false");
 
223
                                break;
 
224
                        default:
 
225
                                result = 0;
 
226
                                break;
 
227
                }
 
228
        } else {
 
229
                result = xstrdup("true");
 
230
        }
 
231
 
 
232
        if(result) {
 
233
                ftsh_error(FTSH_ERROR_COMMAND,e->line,"%s %s is %s",expr_type_to_string(e->type),path,result);
 
234
        } else {
 
235
                ftsh_error(FTSH_ERROR_FAILURE,e->line,"%s %s failed: %s",expr_type_to_string(e->type),path,strerror(errno));
 
236
        }
 
237
        free(path);
 
238
        return result;
 
239
}
 
240
 
 
241
static char * expr_eval_islink( struct expr *e, time_t stoptime )
 
242
{
 
243
        char buf[PATH_MAX];
 
244
        char *path;
 
245
        char *r;
 
246
        int result;
 
247
 
 
248
        path = expr_eval(e->a,stoptime);
 
249
        if(!path) return 0;
 
250
 
 
251
        result = readlink(path,buf,sizeof(buf));
 
252
        if(result>=0) {
 
253
                r = xstrdup("true");
 
254
        } else switch(errno) {
 
255
                case EINVAL:
 
256
                case ENOENT:
 
257
                case ENOTDIR:
 
258
                case EISDIR:
 
259
                case EACCES:
 
260
                case ENAMETOOLONG:
 
261
                        r = xstrdup("false");
 
262
                        break;
 
263
                default:
 
264
                        r = 0;
 
265
                        break;
 
266
        }
 
267
 
 
268
        free(path);
 
269
        return r;
 
270
}
 
271
 
 
272
static char * expr_eval_filetype( struct expr *e, time_t stoptime )
 
273
{
 
274
        char *path;
 
275
        char *result;
 
276
        struct stat buf;
 
277
        int ival;
 
278
 
 
279
        path = expr_eval(e->a,stoptime);
 
280
        if(!path) return 0;
 
281
 
 
282
        ival = stat(path,&buf);
 
283
        if(ival!=0) {
 
284
                switch(errno) {
 
285
                        #ifdef ENOENT
 
286
                        case ENOENT:
 
287
                        #endif
 
288
 
 
289
                        #ifdef ENOTDIR
 
290
                        case ENOTDIR:
 
291
                        #endif
 
292
 
 
293
                        #ifdef ELOOP
 
294
                        case ELOOP:
 
295
                        #endif
 
296
 
 
297
                        #ifdef EACCES
 
298
                        case EACCES:
 
299
                        #endif
 
300
                                result = xstrdup("false");
 
301
                                break;
 
302
 
 
303
                        default:
 
304
                                result = 0;
 
305
                                break;
 
306
                }
 
307
        } else {
 
308
                switch(e->type) {
 
309
                        case EXPR_ISBLOCK:
 
310
                                ival = S_ISBLK(buf.st_mode);
 
311
                                break;
 
312
                        case EXPR_ISCHAR:
 
313
                                ival = S_ISCHR(buf.st_mode);
 
314
                                break;
 
315
                        case EXPR_ISDIR:
 
316
                                ival = S_ISDIR(buf.st_mode);
 
317
                                break;
 
318
                        case EXPR_ISFILE:
 
319
                                ival = S_ISREG(buf.st_mode);
 
320
                                break;
 
321
                        case EXPR_ISLINK:
 
322
                                /* We should not get here because of shortcut earlier to avoid the broken S_ISLNK macro. */
 
323
                                abort();
 
324
                                ival = S_ISLNK(buf.st_mode);
 
325
                                break;
 
326
                        case EXPR_ISPIPE:
 
327
                                ival = S_ISFIFO(buf.st_mode);
 
328
                                break;
 
329
                        case EXPR_ISSOCK:
 
330
                                ival = S_ISSOCK(buf.st_mode);
 
331
                                break;
 
332
                        default:
 
333
                                ftsh_fatal(e->line,"unexpected expression type %d",e->type);
 
334
                                break;
 
335
                }
 
336
 
 
337
                if(ival) {
 
338
                        result = xstrdup("true");
 
339
                } else {
 
340
                        result = xstrdup("false");
 
341
                }
 
342
        }
 
343
 
 
344
        if(result) {
 
345
                ftsh_error(FTSH_ERROR_COMMAND,e->line,"%s %s is %s",expr_type_to_string(e->type),path,result);
 
346
        } else {
 
347
                ftsh_error(FTSH_ERROR_FAILURE,e->line,"%s %s failed: %s",expr_type_to_string(e->type),path,strerror(errno));
 
348
        }
 
349
        free(path);
 
350
        return result;
 
351
}
 
352
 
 
353
static char * expr_eval_range( struct expr *e, time_t stoptime )
 
354
{
 
355
        ftsh_integer_t i, ia, ib;
 
356
        char *r=0;
 
357
 
 
358
        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ) {
 
359
 
 
360
                ftsh_integer_t step;
 
361
                int digits;
 
362
 
 
363
                /* use the step if we have it */
 
364
 
 
365
                if(e->c) {
 
366
                        if(!expr_to_integer(e->c,&step,stoptime)) return 0;
 
367
                } else {
 
368
                        step = 1;
 
369
                }
 
370
 
 
371
                digits = MAX(digits_in_int(ia),digits_in_int(ib));
 
372
                /* add one for a unary - and for a space */
 
373
                digits+=2;
 
374
 
 
375
                /* allocate enough space for the set */
 
376
                r = xxmalloc((ABS((ib-ia)/step)+1)*digits+4);
 
377
 
 
378
                strcpy(r,"\"");
 
379
 
 
380
                /* fill up the text */
 
381
                if(ia<=ib) {
 
382
                        for( i=ia; i<=ib; i+=ABS(step) ) {
 
383
                                sprintf(&r[strlen(r)],"%ld ",i);
 
384
                        }
 
385
                } else {
 
386
                        for( i=ib; i<=ia; i+=ABS(step) ) {
 
387
                                sprintf(&r[strlen(r)],"%ld ",i);
 
388
                        }
 
389
                }
 
390
                strcat(r,"\"");
 
391
        }
 
392
 
 
393
        return r;
 
394
}
 
395
 
 
396
static char * expr_eval_fcall( struct expr *e, time_t stoptime )
 
397
{
 
398
        struct expr *f;
 
399
        char *name;
 
400
        char *rval=0;
 
401
        int i, argc=0;
 
402
        char **argv;
 
403
 
 
404
        name = ast_word_execute(e->line,e->literal);
 
405
        if(name) {
 
406
                argc = 1;
 
407
                for(f=e->a;f;f=f->next) argc++;
 
408
                argv = xxmalloc( sizeof(char*)*argc );
 
409
                for(i=0;i<argc;i++) argv[0] = 0;
 
410
                argv[0] = xstrdup(name);
 
411
                f = e->a;
 
412
                for(i=1;i<argc;i++) {
 
413
                        argv[i] = expr_eval(f,stoptime);
 
414
                        if(!argv[i]) break;
 
415
                        f = f->next;
 
416
                }
 
417
                if(i==argc) {
 
418
                        rval = ast_function_execute(e->line,argc,argv,stoptime);
 
419
                }
 
420
                for(i=i-1;i>=0;i--) free(argv[i]);
 
421
                free(argv);
 
422
                free(name);
 
423
        }
 
424
 
 
425
        return rval;
 
426
}
 
427
 
 
428
char * expr_eval( struct expr *e, time_t stoptime )
 
429
{
 
430
        ftsh_integer_t i, ia, ib;
 
431
        ftsh_boolean_t b, ba, bb;
 
432
        char *r=0, *ra, *rb;
 
433
 
 
434
        switch(e->type) {
 
435
                case EXPR_ADD:
 
436
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
437
                                i = ia + ib;
 
438
                                r = integer_to_string(e->line,i);
 
439
                        }
 
440
                        break;
 
441
                case EXPR_SUB:
 
442
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
443
                                i = ia - ib;
 
444
                                r = integer_to_string(e->line,i);
 
445
                        }
 
446
                        break;
 
447
                case EXPR_MUL:
 
448
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
449
                                i = ia * ib;
 
450
                                r = integer_to_string(e->line,i);
 
451
                        }
 
452
                        break;
 
453
                case EXPR_DIV:
 
454
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
455
                                i = ia / ib;
 
456
                                r = integer_to_string(e->line,i);
 
457
                        }
 
458
                        break;
 
459
                case EXPR_MOD:
 
460
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
461
                                i = ia % ib;
 
462
                                r = integer_to_string(e->line,i);
 
463
                        }
 
464
                        break;
 
465
                case EXPR_POW:
 
466
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
467
                                i=1;
 
468
                                while( ib>0 ) {
 
469
                                        i = i*ia;
 
470
                                        ib--;
 
471
                                }
 
472
                                r = integer_to_string(e->line,i);
 
473
                        }
 
474
                        break;
 
475
                case EXPR_EQ:
 
476
                        ra = expr_eval(e->a,stoptime);
 
477
                        rb = expr_eval(e->b,stoptime);
 
478
                        b = !strcmp(ra,rb);
 
479
                        free(ra);
 
480
                        free(rb);
 
481
                        r = boolean_to_string(e->line,b);
 
482
                        break;
 
483
                case EXPR_NE:
 
484
                        ra = expr_eval(e->a,stoptime);
 
485
                        rb = expr_eval(e->b,stoptime);
 
486
                        b = strcmp(ra,rb);
 
487
                        free(ra);
 
488
                        free(rb);
 
489
                        r = boolean_to_string(e->line,b);
 
490
                        break;
 
491
                case EXPR_EQL:
 
492
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
493
                                b = (ia==ib);
 
494
                                r = boolean_to_string(e->line,b);
 
495
                        }
 
496
                        break;
 
497
                case EXPR_NEQL:
 
498
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
499
                                b = (ia!=ib);
 
500
                                r = boolean_to_string(e->line,b);
 
501
                        }
 
502
                        break;
 
503
                case EXPR_LT:
 
504
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
505
                                b = ia < ib;
 
506
                                r = boolean_to_string(e->line,b);
 
507
                        }
 
508
                        break;
 
509
                case EXPR_LE:
 
510
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
511
                                b = ia <= ib;
 
512
                                r = boolean_to_string(e->line,b);
 
513
                        }
 
514
                        break;
 
515
                case EXPR_GT:
 
516
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
517
                                b = ia > ib;
 
518
                                r = boolean_to_string(e->line,b);
 
519
                        }
 
520
                        break;
 
521
                case EXPR_GE:
 
522
                        if( expr_to_integer(e->a,&ia,stoptime) && expr_to_integer(e->b,&ib,stoptime) ){
 
523
                                b = ia >= ib;
 
524
                                r = boolean_to_string(e->line,b);
 
525
                        }
 
526
                        break;
 
527
                case EXPR_AND:
 
528
                        if( expr_to_boolean(e->a,&ba,stoptime) && expr_to_boolean(e->b,&bb,stoptime) ){
 
529
                                b = ba && bb;
 
530
                                r = boolean_to_string(e->line,b);
 
531
                        }
 
532
                        break;
 
533
                case EXPR_OR:
 
534
                        if( expr_to_boolean(e->a,&ba,stoptime) && expr_to_boolean(e->b,&bb,stoptime) ){
 
535
                                b = ba || bb;
 
536
                                r = boolean_to_string(e->line,b);
 
537
                        }
 
538
                        break;
 
539
                case EXPR_NOT:
 
540
                        if(expr_to_boolean(e->a,&b,stoptime)) {
 
541
                                r = boolean_to_string(e->line,!b);
 
542
                        }
 
543
                        break;
 
544
                case EXPR_EXISTS:
 
545
                case EXPR_ISR:
 
546
                case EXPR_ISW:
 
547
                case EXPR_ISX:
 
548
                        r = expr_eval_access(e,stoptime);
 
549
                        break;
 
550
                case EXPR_ISBLOCK:
 
551
                case EXPR_ISCHAR:
 
552
                case EXPR_ISDIR:
 
553
                case EXPR_ISFILE:
 
554
                case EXPR_ISPIPE:
 
555
                case EXPR_ISSOCK:
 
556
                        r = expr_eval_filetype(e,stoptime);
 
557
                        break;
 
558
                case EXPR_ISLINK:
 
559
                        r = expr_eval_islink(e,stoptime);
 
560
                        break;
 
561
                case EXPR_EXPR:
 
562
                        r = expr_eval(e->a,stoptime);
 
563
                        break;
 
564
                case EXPR_TO:
 
565
                        r = expr_eval_range(e,stoptime);
 
566
                        break;
 
567
                case EXPR_FCALL:
 
568
                        r = expr_eval_fcall(e,stoptime);
 
569
                        break;
 
570
                case EXPR_LITERAL:
 
571
                        return ast_word_list_execute(e->line,e->literal);
 
572
                        break;
 
573
        }
 
574
 
 
575
        return r;
 
576
}
 
577
 
 
578
void expr_print( FILE *file, struct expr *e )
 
579
{
 
580
        expr_print_list(file,e,0);
 
581
}
 
582
 
 
583
static void expr_print_list( FILE *file, struct expr *e, int with_commas )
 
584
{
 
585
        if(!e) return;
 
586
 
 
587
        switch(e->type) {
 
588
                case EXPR_ADD:
 
589
                case EXPR_SUB:
 
590
                case EXPR_MUL:
 
591
                case EXPR_DIV:
 
592
                case EXPR_MOD:
 
593
                case EXPR_POW:
 
594
                case EXPR_EQ:
 
595
                case EXPR_NE:
 
596
                case EXPR_EQL:
 
597
                case EXPR_NEQL:
 
598
                case EXPR_LT:
 
599
                case EXPR_LE:
 
600
                case EXPR_GT:
 
601
                case EXPR_GE:
 
602
                case EXPR_AND:
 
603
                case EXPR_OR:
 
604
                        expr_print(file,e->a);
 
605
                        fprintf(file," %s ",expr_type_to_string(e->type));
 
606
                        expr_print(file,e->b);
 
607
                        break;
 
608
                case EXPR_NOT:
 
609
                case EXPR_EXISTS:
 
610
                case EXPR_ISR:
 
611
                case EXPR_ISW:
 
612
                case EXPR_ISX:
 
613
                case EXPR_ISBLOCK:
 
614
                case EXPR_ISCHAR:
 
615
                case EXPR_ISDIR:
 
616
                case EXPR_ISFILE:
 
617
                case EXPR_ISLINK:
 
618
                case EXPR_ISPIPE:
 
619
                case EXPR_ISSOCK:
 
620
                        fprintf(file,"%s ",expr_type_to_string(e->type));
 
621
                        expr_print(file,e->a);
 
622
                        break;
 
623
                case EXPR_TO:
 
624
                        expr_print(file,e->a);
 
625
                        fprintf(file," .to. ");
 
626
                        expr_print(file,e->b);
 
627
                        if(e->c) {
 
628
                                fprintf(file," .step. ");
 
629
                                expr_print(file,e->c);
 
630
                        }
 
631
                        fprintf(file," ");
 
632
                        break;
 
633
                case EXPR_EXPR:
 
634
                        fprintf(file,"(");
 
635
                        expr_print(file,e->a);
 
636
                        fprintf(file,")");
 
637
                        break;
 
638
                case EXPR_FCALL:
 
639
                        ast_word_print(file,e->literal);
 
640
                        fprintf(file,"(");
 
641
                        expr_print_list(file,e->a,1);
 
642
                        fprintf(file,")");
 
643
                        break;                  
 
644
                case EXPR_LITERAL:
 
645
                        ast_word_print(file,e->literal);
 
646
                        break;
 
647
                default:
 
648
                        ftsh_fatal(e->line,"unknown expression type %d",e->type);
 
649
                        break;
 
650
        }
 
651
 
 
652
        if(e->next) {
 
653
                if(with_commas) {
 
654
                        fprintf(file,",");
 
655
                } else {
 
656
                        fprintf(file," ");
 
657
                }
 
658
                expr_print(file,e->next);
 
659
        }
 
660
}
 
661
 
 
662
int expr_is_list( struct expr *e )
 
663
{
 
664
        if(e->type==EXPR_TO) {
 
665
                return 1;
 
666
        } else if(e->type==EXPR_EXPR) {
 
667
                return expr_is_list(e->a);
 
668
        } else {
 
669
                return 0;
 
670
        }
 
671
}