~ubuntu-branches/debian/sid/bc/sid

« back to all changes in this revision

Viewing changes to dc/eval.c

  • Committer: Bazaar Package Importer
  • Author(s): John Hasler
  • Date: 2007-12-02 14:46:56 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071202144656-7x7aoc9833wgbmas
Tags: 1.06.94-3
Added "-pbc" to dh_installdirs line for bc in debian/rules.
Fixes build failure with "-j3".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
 
1
/*
2
2
 * evaluate the dc language, from a FILE* or a string
3
3
 *
4
 
 * Copyright (C) 1994, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
 
4
 * Copyright (C) 1994, 1997, 1998, 2000, 2003, 2005, 2006 Free Software
 
5
 * Foundation, Inc.
5
6
 *
6
7
 * This program is free software; you can redistribute it and/or modify
7
8
 * it under the terms of the GNU General Public License as published by
17
18
 * along with this program; if not, you can either send email to this
18
19
 * program's author (see below) or write to:
19
20
 *   The Free Software Foundation, Inc.
20
 
 *   59 Temple Place, Suite 330
21
 
 *   Boston, MA 02111 USA
 
21
 *   51 Franklin Street, Fifth Floor
 
22
 *   Boston, MA 02110-1301  USA
22
23
 */
23
24
 
24
25
/* This is the only module which knows about the dc input language */
37
38
#  endif
38
39
#endif
39
40
#endif
 
41
#include <signal.h>
40
42
#include "dc.h"
41
43
#include "dc-proto.h"
42
44
 
45
47
typedef enum {
46
48
        DC_OKAY = DC_SUCCESS, /* no further intervention needed for this command */
47
49
        DC_EATONE,              /* caller needs to eat the lookahead char */
 
50
        DC_EVALREG,             /* caller needs to eval the string named by `peekc' */
 
51
        DC_EVALTOS,             /* caller needs to eval the string on top of the stack */
48
52
        DC_QUIT,                /* quit out of unwind_depth levels of evaluation */
49
 
 
50
 
        /* with the following return values, the caller does not have to 
51
 
         * fret about stdin_lookahead's value
52
 
         */
53
53
        DC_INT,                 /* caller needs to parse a dc_num from input stream */
54
54
        DC_STR,                 /* caller needs to parse a dc_str from input stream */
55
55
        DC_SYSTEM,              /* caller needs to run a system() on next input line */
56
56
        DC_COMMENT,             /* caller needs to skip to the next input line */
57
57
        DC_NEGCMP,              /* caller needs to re-call dc_func() with `negcmp' set */
58
 
        DC_EVALREG,             /* caller needs to eval the string named by `peekc' */
59
58
 
60
59
        DC_EOF_ERROR    /* unexpected end of input; abort current eval */
61
60
} dc_status;
67
66
/* for Quitting evaluations */
68
67
static int unwind_depth=0;
69
68
 
 
69
/* for handling SIGINT properly */
 
70
static volatile sig_atomic_t interrupt_seen=0;
 
71
 
70
72
/* if true, active Quit will not exit program */
71
73
static dc_boolean unwind_noexit=DC_FALSE;
72
74
 
104
106
static int
105
107
input_str DC_DECLVOID()
106
108
{
107
 
        if (!*input_str_string)
 
109
        if (*input_str_string == '\0')
108
110
                return EOF;
109
111
        return *input_str_string++;
110
112
}
128
130
}
129
131
 
130
132
 
 
133
/* notice when an interrupt event happens */
 
134
static void
 
135
dc_trap_interrupt DC_DECLARG((signo))
 
136
        int signo DC_DECLEND
 
137
{
 
138
        signal(signo, dc_trap_interrupt);
 
139
        interrupt_seen = 1;
 
140
}
 
141
 
 
142
 
 
143
/* step pointer past next end-of-line (or to end-of-string) */
 
144
static const char *
 
145
skip_past_eol DC_DECLARG((strptr, strend))
 
146
        const char *strptr DC_DECLSEP
 
147
        const char *strend DC_DECLEND
 
148
{
 
149
        const char *p = memchr(strptr, '\n', (size_t)(strend-strptr));
 
150
        if (p != NULL)
 
151
                return p+1;
 
152
        return strend;
 
153
}
 
154
 
 
155
 
131
156
/* dc_func does the grunt work of figuring out what each input
132
157
 * character means; used by both dc_evalstr and dc_evalfile
133
158
 *
141
166
        int peekc DC_DECLSEP
142
167
        int negcmp DC_DECLEND
143
168
{
144
 
        /* we occasionally need these for temporary data */
145
 
        /* Despite the GNU coding standards, it is much easier
146
 
         * to have these declared once here, since this function
147
 
         * is just one big switch statement.
148
 
         */
149
169
        dc_data datum;
150
170
        int tmpint;
151
171
 
207
227
                 */
208
228
                if (peekc == EOF)
209
229
                        return DC_EOF_ERROR;
210
 
                if ( (dc_cmpop() <  0) == !negcmp )
 
230
                if ( (dc_cmpop() <  0) == (negcmp==0) )
211
231
                        return DC_EVALREG;
212
232
                return DC_EATONE;
213
233
        case '=':
216
236
                 */
217
237
                if (peekc == EOF)
218
238
                        return DC_EOF_ERROR;
219
 
                if ( (dc_cmpop() == 0) == !negcmp )
 
239
                if ( (dc_cmpop() == 0) == (negcmp==0) )
220
240
                        return DC_EVALREG;
221
241
                return DC_EATONE;
222
242
        case '>':
225
245
                 */
226
246
                if (peekc == EOF)
227
247
                        return DC_EOF_ERROR;
228
 
                if ( (dc_cmpop() >  0) == !negcmp )
 
248
                if ( (dc_cmpop() >  0) == (negcmp==0) )
229
249
                        return DC_EVALREG;
230
250
                return DC_EATONE;
231
251
        case '?':       /* read a line from standard-input and eval it */
234
254
                        stdin_lookahead = EOF;
235
255
                }
236
256
                datum = dc_readstring(stdin, '\n', '\n');
237
 
                if (dc_eval_and_free_str(&datum) == DC_QUIT)
238
 
                        return DC_QUIT;
239
 
                return DC_OKAY;
 
257
                if (ferror(stdin))
 
258
                        return DC_EOF_ERROR;
 
259
                dc_push(datum);
 
260
                return DC_EVALTOS;
240
261
        case '[':       /* read to balancing ']' into a dc_str */
241
262
                return DC_STR;
242
263
        case '!':       /* read to newline and call system() on resulting string */
275
296
                        tmpint = 0;
276
297
                        if (datum.dc_type == DC_NUMBER)
277
298
                                tmpint = dc_num2int(datum.v.number, DC_TOSS);
278
 
                        if ( ! (2 <= tmpint  &&  tmpint <= DC_IBASE_MAX) )
 
299
                        if (2 <= tmpint  &&  tmpint <= DC_IBASE_MAX)
 
300
                                dc_ibase = tmpint;
 
301
                        else
279
302
                                fprintf(stderr,
280
303
                                                "%s: input base must be a number \
281
304
between 2 and %d (inclusive)\n",
282
305
                                                progname, DC_IBASE_MAX);
283
 
                        else
284
 
                                dc_ibase = tmpint;
285
306
                }
286
307
                break;
287
308
        case 'k':       /* set scale to value on top of stack */
370
391
                }
371
392
                break;
372
393
        case 'x':       /* eval the datum popped from top of stack */
373
 
                if (dc_pop(&datum) == DC_SUCCESS){
374
 
                        if (datum.dc_type == DC_STRING){
375
 
                                if (dc_eval_and_free_str(&datum) == DC_QUIT)
376
 
                                        return DC_QUIT;
377
 
                        }else if (datum.dc_type == DC_NUMBER){
378
 
                                dc_push(datum);
379
 
                        }else{
380
 
                                dc_garbage("at top of stack", -1);
381
 
                        }
382
 
                }
383
 
                break;
 
394
                return DC_EVALTOS;
384
395
        case 'z':       /* push the current stack depth onto the top of stack */
385
396
                dc_push(dc_int2data(dc_tell_stackdepth()));
386
397
                break;
437
448
                break;
438
449
#if 0
439
450
        case 'R':       /* pop a value off of the evaluation stack,;
440
 
                                 * rotate the top
441
 
                                 remaining stack elements that many
 
451
                                 * rotate the top remaining stack elements that many
442
452
                                 * places forward (negative numbers mean rotate
443
453
                                 * backward).
444
454
                                 */
528
538
        int negcmp;
529
539
        int next_negcmp = 0;
530
540
        int tail_depth = 1; /* how much tail recursion is active */
 
541
        dc_data evalstr;
531
542
 
532
543
        if (string->dc_type != DC_STRING){
533
544
                fprintf(stderr,
535
546
                                progname);
536
547
                return DC_OKAY;
537
548
        }
 
549
        interrupt_seen = 0;
538
550
        s = dc_str2charp(string->v.string);
539
551
        end = s + dc_strlen(string->v.string);
540
 
        while (s < end){
 
552
        while (s < end && interrupt_seen==0){
541
553
                c = *(const unsigned char *)s++;
542
554
                peekc = EOF;
543
555
                if (s < end)
551
563
                        if (peekc != EOF)
552
564
                                ++s;
553
565
                        break;
 
566
                case DC_EVALREG:
 
567
                        /*commands which return this guarantee that peekc!=EOF*/
 
568
                        ++s;
 
569
                        if (dc_register_get(peekc, &evalstr) != DC_SUCCESS)
 
570
                                break;
 
571
                        dc_push(evalstr);
 
572
                        /*@fallthrough@*/
 
573
                case DC_EVALTOS:
 
574
                        /*skip trailing whitespace to assist tail-recursion detection*/
 
575
                        while (s<end && (*s==' '||*s=='\t'||*s=='\n'||*s=='#')){
 
576
                                if (*s++ == '#')
 
577
                                        s = skip_past_eol(s, end);
 
578
                        }
 
579
                        if (dc_pop(&evalstr) == DC_SUCCESS){
 
580
                                if (evalstr.dc_type == DC_NUMBER){
 
581
                                        dc_push(evalstr);
 
582
                                        return DC_OKAY;
 
583
                                }else if (evalstr.dc_type != DC_STRING){
 
584
                                        dc_garbage("at top of stack", -1);
 
585
                                }else if (s == end){
 
586
                                        /*handle tail recursion*/
 
587
                                        dc_free_str(&string->v.string);
 
588
                                        *string = evalstr;
 
589
                                        s = dc_str2charp(string->v.string);
 
590
                                        end = s + dc_strlen(string->v.string);
 
591
                                        ++tail_depth;
 
592
                                }else if (dc_eval_and_free_str(&evalstr) == DC_QUIT){
 
593
                                        if (unwind_depth > 0){
 
594
                                                --unwind_depth;
 
595
                                                return DC_QUIT;
 
596
                                        }
 
597
                                        return DC_OKAY;
 
598
                                }
 
599
                        }
 
600
                        break;
554
601
                case DC_QUIT:
555
602
                        if (unwind_depth >= tail_depth){
556
603
                                unwind_depth -= tail_depth;
572
619
                                        --count;
573
620
                                else if (*p == '[')
574
621
                                        ++count;
575
 
                        len = p - s;
 
622
                        len = (size_t) (p - s);
576
623
                        dc_push(dc_makestring(s, len-1));
577
624
                        s = p;
578
625
                        break;
579
626
                case DC_SYSTEM:
580
627
                        s = dc_system(s);
 
628
                        /*@fallthrough@*/
581
629
                case DC_COMMENT:
582
 
                        s = memchr(s, '\n', (size_t)(end-s));
583
 
                        if (!s)
584
 
                                s = end;
585
 
                        else
586
 
                                ++s;
 
630
                        s = skip_past_eol(s, end);
587
631
                        break;
588
632
                case DC_NEGCMP:
589
633
                        next_negcmp = 1;
590
634
                        break;
591
 
                case DC_EVALREG:
592
 
                        if (peekc == EOF){
593
 
                                fprintf(stderr, "%s: unexpected EOS\n", progname);
594
 
                                return DC_OKAY;
595
 
                        }else{
596
 
                                dc_data evalstr;
597
 
                                ++s;
598
 
                                if (dc_register_get(peekc, &evalstr) == DC_SUCCESS){
599
 
                                        if (s == end){
600
 
                                                if (evalstr.dc_type != DC_STRING){
601
 
                                                        fprintf(stderr,
602
 
                                                                "%s: eval called with non-string argument\n",
603
 
                                                                progname);
604
 
                                                        return DC_OKAY;
605
 
                                                }
606
 
                                                dc_free_str(&string->v.string);
607
 
                                                *string = evalstr;
608
 
                                                s = dc_str2charp(string->v.string);
609
 
                                                end = s + dc_strlen(string->v.string);
610
 
                                                ++tail_depth;
611
 
                                        }else if (dc_eval_and_free_str(&evalstr) == DC_QUIT){
612
 
                                                if (unwind_depth > 0){
613
 
                                                        --unwind_depth;
614
 
                                                        return DC_QUIT;
615
 
                                                }
616
 
                                                return DC_OKAY;
617
 
                                        }
618
 
                                }
619
 
                        }
620
 
                        break;
621
635
 
622
636
                case DC_EOF_ERROR:
 
637
                        if (ferror(stdin)) {
 
638
                                fprintf(stderr, "%s: ", progname);
 
639
                                perror("error reading stdin");
 
640
                                return DC_FAIL;
 
641
                        }
623
642
                        fprintf(stderr, "%s: unexpected EOS\n", progname);
624
643
                        return DC_OKAY;
625
644
                }
642
661
        int next_negcmp = 0;
643
662
        dc_data datum;
644
663
 
 
664
        signal(SIGINT, dc_trap_interrupt);
645
665
        stdin_lookahead = EOF;
646
666
        for (c=getc(fp); c!=EOF; c=peekc){
647
667
                peekc = getc(fp);
651
671
                 */
652
672
                if (fp == stdin)
653
673
                        stdin_lookahead = peekc;
 
674
                /*
 
675
                 * In the switch(), cases which naturally update peekc
 
676
                 * (unconditionally) do not have to update or reference
 
677
                 * stdin_lookahead; other functions use the predicate:
 
678
                 *    stdin_lookahead != peekc  &&  fp == stdin
 
679
                 * to recognize the case where:
 
680
                 *   a) stdin_lookahead == EOF (stdin and peekc are not in sync)
 
681
                 *   b) peekc != EOF (resync is possible)
 
682
                 *   c) fp == stdin (resync is relevant)
 
683
                 * The whole stdin_lookahead complication arises because the
 
684
                 * '?' command may be invoked from an arbritrarily deeply
 
685
                 * nested dc_evalstr(), '?' reads exclusively from stdin,
 
686
                 * and this winds up making peekc invalid when fp==stdin.
 
687
                 */
654
688
                negcmp = next_negcmp;
655
689
                next_negcmp = 0;
656
690
                switch (dc_func(c, peekc, negcmp)){
661
695
                case DC_EATONE:
662
696
                        peekc = getc(fp);
663
697
                        break;
 
698
                case DC_EVALREG:
 
699
                        /*commands which send us here shall guarantee that peekc!=EOF*/
 
700
                        c = peekc;
 
701
                        peekc = getc(fp);
 
702
                        stdin_lookahead = peekc;
 
703
                        if (dc_register_get(c, &datum) != DC_SUCCESS)
 
704
                                break;
 
705
                        dc_push(datum);
 
706
                        /*@fallthrough@*/
 
707
                case DC_EVALTOS:
 
708
                        if (stdin_lookahead != peekc  &&  fp == stdin)
 
709
                                peekc = getc(fp);
 
710
                        if (dc_pop(&datum) == DC_SUCCESS){
 
711
                                if (datum.dc_type == DC_NUMBER){
 
712
                                        dc_push(datum);
 
713
                                }else if (datum.dc_type == DC_STRING){
 
714
                                        if (dc_eval_and_free_str(&datum) == DC_QUIT){
 
715
                                                if (unwind_noexit != DC_TRUE)
 
716
                                                        return DC_SUCCESS;
 
717
                                                fprintf(stderr, "%s: Q command argument exceeded \
 
718
string execution depth\n", progname);
 
719
                                        }
 
720
                                }else{
 
721
                                        dc_garbage("at top of stack", -1);
 
722
                                }
 
723
                        }
 
724
                        break;
664
725
                case DC_QUIT:
665
726
                        if (unwind_noexit != DC_TRUE)
666
727
                                return DC_SUCCESS;
676
737
                        input_pushback = c;
677
738
                        ungetc(peekc, fp);
678
739
                        dc_push(dc_getnum(input_fil, dc_ibase, &peekc));
 
740
                        if (ferror(fp))
 
741
                                goto error_fail;
679
742
                        break;
680
743
                case DC_STR:
681
744
                        ungetc(peekc, fp);
682
745
                        datum = dc_readstring(fp, '[', ']');
 
746
                        if (ferror(fp))
 
747
                                goto error_fail;
683
748
                        dc_push(datum);
684
749
                        peekc = getc(fp);
685
750
                        break;
686
751
                case DC_SYSTEM:
687
752
                        ungetc(peekc, fp);
688
753
                        datum = dc_readstring(stdin, '\n', '\n');
 
754
                        if (ferror(stdin))
 
755
                                goto error_fail;
689
756
                        (void)dc_system(dc_str2charp(datum.v.string));
690
757
                        dc_free_str(&datum.v.string);
691
758
                        peekc = getc(fp);
699
766
                case DC_NEGCMP:
700
767
                        next_negcmp = 1;
701
768
                        break;
702
 
                case DC_EVALREG:
703
 
                        {
704
 
                                dc_data evalstr;
705
 
                                c = peekc;
706
 
                                peekc = getc(fp);
707
 
                                if (dc_register_get(c, &evalstr) == DC_SUCCESS &&
708
 
                                                        dc_eval_and_free_str(&evalstr) == DC_QUIT){
709
 
                                        if (unwind_noexit != DC_TRUE)
710
 
                                                return DC_SUCCESS;
711
 
                                        fprintf(stderr, "%s: Q command argument exceeded string execution depth\n", progname);
712
 
                                }
713
 
                        }
714
 
                        break;
715
769
 
716
770
                case DC_EOF_ERROR:
 
771
                        if (ferror(fp))
 
772
                                goto error_fail;
717
773
                        fprintf(stderr, "%s: unexpected EOF\n", progname);
718
774
                        return DC_FAIL;
719
775
                }
720
776
        }
721
 
        return DC_SUCCESS;
 
777
        if (!ferror(fp))
 
778
                return DC_SUCCESS;
 
779
 
 
780
error_fail:
 
781
        fprintf(stderr, "%s: ", progname);
 
782
        perror("error reading input");
 
783
        return DC_FAIL;
722
784
}
723
785
 
724
786
 
725
787
/*
726
 
  ! Local Variables: !
727
 
  ! mode: C !
728
 
  ! tab-width: 4 !
729
 
  ! End: !
730
 
  vi: ts=4 sw=4
731
 
*/
 
788
 * Local Variables:
 
789
 * mode: C
 
790
 * tab-width: 4
 
791
 * End:
 
792
 * vi: set ts=4 :
 
793
 */