5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
25 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
33 #pragma ident "%Z%%M% %I% %E% SMI"
43 static void getout
(int) __NORETURN
;
44 static int *bundle
(int, ...
);
45 static void usage
(void);
47 int cpeek
(char, int, char, int, char);
57 %type
<iptr
> stat
, def
, slist
, dlets
, e
58 %type
<iptr
> slist
, re
, fprefix
, cargs
, eora
, cons
, constant
, lora
66 %type
<cptr
> EQOP
, CRS
67 %token
<cc
> DIGIT
, SQRT
, LENGTH
, _IF
, FFF
, EQ
68 %token
<cc
> _WHILE _FOR NE LE GE INCR DECR
69 %token
<cc
> _RETURN _BREAK _DEFINE BASE OBASE SCALE
70 %token
<cc
> EQPL EQMI EQMUL EQDIV EQREM EQEXP
71 %token
<cptr
> _AUTO DOT
75 #define STRING_SIZE (BC_STRING_MAX + 3) /* string plus quotes */
79 char cary
[LINE_MAX
+1];
81 char *cpend
= &cary
[LINE_MAX
]; /* last address (not the null char) */
82 char string[STRING_SIZE
];
83 char *str
= { string };
85 int rcrs
= '0'; /* reset crs */
87 int lev
= 0; /* current scope level */
88 int ln
; /* line number of current file */
90 char *ss
; /* current input source */
91 int bstack
[10] = { 0 };
93 " 0", " 1", " 2", " 3", " 4", " 5",
94 " 6", " 7", " 8", " 9", " 10", " 11",
98 int interact
= 0; /* talking to a tty? */
106 | start def dargs
')' '{' dlist slist
'}'
108 ttp
= bundle
(6, pre
, $7, post
, "0", numb
[lev
], "Q");
109 conout
(ttp
, (char *)$2);
117 | dlist _AUTO dlets tail
121 = bundle
(2, $1, "ps.");
125 = bundle
(3, "[", $1, "]P");
127 = bundle
(3, $3, "s", $1);
128 | LETTER
'[' e
']' '=' e
129 = bundle
(4, $6, $3, ":", geta
($1));
131 = bundle
(6, "l", $1, $3, $2, "s", $1);
132 | LETTER
'[' e
']' EQOP e
133 = bundle
(8, $3, ";", geta
($1), $6, $5, $3, ":", geta
($1));
135 = bundle
(2, numb
[lev
-bstack
[bindx
-1]], "Q");
137 = bundle
(4, $3, post
, numb
[lev
], "Q");
139 = bundle
(4, "0", post
, numb
[lev
], "Q");
141 = bundle
(4, "0", post
, numb
[lev
], "Q");
143 = bundle
(2, $3, "k");
145 = bundle
(4, "K", $3, $2, "k");
147 = bundle
(2, $3, "i");
149 = bundle
(4, "I", $3, $2, "i");
151 = bundle
(2, $3, "o");
153 = bundle
(4, "O", $3, $2, "o");
162 | _IF CRS BLEV
'(' re
')' stat
165 bundle
(3, $5, $2, " ");
167 | _WHILE CRS
'(' re
')' stat BLEV
169 bundle
(3, $6, $4, $2);
171 bundle
(3, $4, $2, " ");
173 | fprefix CRS re
';' e
')' stat BLEV
175 bundle
(5, $7, $5, "s.", $3, $2);
177 bundle
(5, $1, "s.", $3, $2, " ");
180 = bundle
(3, $4, "S", $2);
209 fprefix
: _FOR
'(' e
';'
233 $$
= bundle
(3, $1, $3, "=");
236 = bundle
(3, $1, $3, ">");
238 = bundle
(3, $1, $3, "<");
240 = bundle
(3, $1, $3, "!=");
242 = bundle
(3, $1, $3, "!>");
244 = bundle
(3, $1, $3, "!<");
246 = bundle
(2, $1, " 0!=");
250 = bundle
(3, $1, $3, "+");
252 = bundle
(3, $1, $3, "-");
254 = bundle
(3, " 0", $2, "-");
256 = bundle
(3, $1, $3, "*");
258 = bundle
(3, $1, $3, "/");
260 = bundle
(3, $1, $3, "%%");
262 = bundle
(3, $1, $3, "^");
264 = bundle
(3, $3, ";", geta
($1));
266 = bundle
(4, "l", $1, "d1+s", $1);
268 = bundle
(4, "l", $2, "1+ds", $2);
270 = bundle
(4, "l", $2, "1-ds", $2);
272 = bundle
(4, "l", $1, "d1-s", $1);
273 | LETTER
'[' e
']' INCR
274 = bundle
(7, $3, ";", geta
($1), "d1+", $3, ":", geta
($1));
275 | INCR LETTER
'[' e
']'
276 = bundle
(7, $4, ";", geta
($2), "1+d", $4, ":", geta
($2));
277 | LETTER
'[' e
']' DECR
278 = bundle
(7, $3, ";", geta
($1), "d1-", $3, ":", geta
($1));
279 | DECR LETTER
'[' e
']'
280 = bundle
(7, $4, ";", geta
($2), "1-d", $4, ":", geta
($2));
282 = bundle
(1, "Kd1+k");
284 = bundle
(1, "K1+dk");
286 = bundle
(1, "Kd1-k");
288 = bundle
(1, "K1-dk");
290 = bundle
(1, "Id1+i");
292 = bundle
(1, "I1+di");
294 = bundle
(1, "Id1-i");
296 = bundle
(1, "I1-di");
298 = bundle
(1, "Od1+o");
300 = bundle
(1, "O1+do");
302 = bundle
(1, "Od1-o");
304 = bundle
(1, "O1-do");
305 | LETTER
'(' cargs
')'
306 = bundle
(4, $3, "l", getf
($1), "x");
308 = bundle
(3, "l", getf
($1), "x");
310 = bundle
(2, " ", $1);
312 = bundle
(2, " .", $2);
314 = bundle
(4, " ", $1, ".", $3);
316 = bundle
(3, " ", $1, ".");
322 = bundle
(2, "l", $1);
324 = bundle
(3, $3, "ds", $1);
325 | LETTER EQOP e %prec
'='
326 = bundle
(6, "l", $1, $3, $2, "ds", $1);
327 | LETTER
'[' e
']' '=' e
328 = bundle
(5, $6, "d", $3, ":", geta
($1));
329 | LETTER
'[' e
']' EQOP e
331 bundle
(9, $3, ";", geta
($1), $6, $5, "d", $3, ":",
335 = bundle
(2, $3, "Z");
337 = bundle
(2, $3, "X"); /* must be before '(' e ')' */
345 = bundle
(2, $3, "v");
347 = bundle
(2, "L", $2);
349 = bundle
(2, $3, "dk");
350 | SCALE EQOP e %prec
'='
351 = bundle
(4, "K", $3, $2, "dk");
353 = bundle
(2, $3, "di");
354 | BASE EQOP e %prec
'='
355 = bundle
(4, "I", $3, $2, "di");
357 = bundle
(2, $3, "do");
358 | OBASE EQOP e %prec
'='
359 = bundle
(4, "O", $3, $2, "do");
374 = bundle
(2, "l", geta
($1));
412 yyerror("program too big");
415 bstack
[bindx
++] = lev
++;
419 def
: _DEFINE LETTER
'('
425 bstack
[bindx
= 0] = 0;
460 int ifile
; /* current index into sargv */
461 int sargc
; /* size of sargv[] */
462 char **sargv
; /* saved arg list without options */
465 01, 0, 02, 0, 03, 0, 04, 0, 05, 0, 06, 0, 07, 0,
466 010, 0, 011, 0, 012, 0, 013, 0, 014, 0, 015, 0, 016, 0, 017, 0,
467 020, 0, 021, 0, 022, 0, 023, 0, 024, 0, 025, 0, 026, 0, 027, 0,
468 030, 0, 031, 0, 032, 0
471 unsigned char atab
[52] = {
472 0241, 0, 0242, 0, 0243, 0, 0244, 0, 0245, 0, 0246, 0, 0247, 0, 0250, 0,
473 0251, 0, 0252, 0, 0253, 0, 0254, 0, 0255, 0, 0256, 0, 0257, 0, 0260, 0,
474 0261, 0, 0262, 0, 0263, 0, 0264, 0, 0265, 0, 0266, 0, 0267, 0, 0270, 0,
479 "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
480 "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
481 "u", "v", "w", "x", "y", "z"
492 while
(c
== ' ' || c
== '\t')
498 if
(c
<= 'z' && c
>= 'a') {
499 /* look ahead to look for reserved words */
501 if
(peekc
>= 'a' && peekc
<= 'z') {
502 /* must be reserved word */
503 if
(c
== 'i' && peekc
== 'f') {
507 if
(c
== 'w' && peekc
== 'h') {
511 if
(c
== 'f' && peekc
== 'o') {
515 if
(c
== 's' && peekc
== 'q') {
519 if
(c
== 'r' && peekc
== 'e') {
523 if
(c
== 'b' && peekc
== 'r') {
527 if
(c
== 'd' && peekc
== 'e') {
531 if
(c
== 's' && peekc
== 'c') {
535 if
(c
== 'b' && peekc
== 'a') {
539 if
(c
== 'i' && peekc
== 'b') {
543 if
(c
== 'o' && peekc
== 'b') {
547 if
(c
== 'd' && peekc
== 'i') {
551 if
(c
== 'a' && peekc
== 'u') {
555 if
(c
== 'l' && peekc
== 'e') {
559 if
(c
== 'q' && peekc
== 'u') {
562 /* could not be found */
565 skip: /* skip over rest of word */
567 while
((ch
= getch
()) >= 'a' && ch
<= 'z')
573 /* usual case; just one single letter */
575 yylval.cptr
= letr
[c
-'a'];
579 if
(c
>= '0' && c
<= '9' || c
>= 'A' && c
<= 'F') {
589 switch
((peekc
= getch
())) {
626 return
(cpeek
('+', INCR
, '=', EQPL
, '+'));
629 return
(cpeek
('-', DECR
, '=', EQMI
, '-'));
632 return
(cpeek
('=', EQMUL
, '\0', 0, '*'));
635 return
(cpeek
('=', EQREM
, '\0', 0, '%'));
638 return
(cpeek
('=', EQEXP
, '\0', 0, '^'));
641 return
(cpeek
('=', LE
, '\0', 0, '<'));
644 return
(cpeek
('=', GE
, '\0', 0, '>'));
647 return
(cpeek
('=', NE
, '\0', 0, '!'));
650 if
((peekc
= getch
()) == '=') {
656 while
((getch
() != '*') ||
((peekc
= getch
()) != '/'))
666 while
((c
= getch
()) != '"') {
668 if
(str
>= &string[STRING_SIZE
-1]) {
669 yyerror("string space exceeded");
682 cpeek
(char c1
, int yes1
, char c2
, int yes2
, char none
)
689 else if
(peekc
== c2
)
705 ch
= (peekc
< 0) ? getc
(in
) : peekc
;
710 if
(++ifile
>= sargc
) {
711 if
(ifile
>= sargc
+1)
719 if
((in
= fopen
(sargv
[ifile
], "r")) != NULL
) {
724 (void) snprintf
(mbuf
, sizeof
(mbuf
), "can't open input file %s",
733 #define b_sp_max 5000
734 int b_space
[b_sp_max
];
735 int *b_sp_nxt
= { b_space
};
748 printf
("bundle %d elements at %o\n", i
, q
);
750 if
(b_sp_nxt
>= & b_space
[b_sp_max
])
751 yyerror("bundling space exceeded");
752 *b_sp_nxt
++ = va_arg
(ap
, int);
763 if
(bdebug
) printf
("routput(%o)\n", p
);
764 if
(p
>= &b_space
[0] && p
< &b_space
[b_sp_max
]) {
765 /* part of a bundle */
767 routput
((int *)*p
++);
770 printf
((char *)p
); /* character string */
777 b_sp_nxt
= & b_space
[0];
779 (void) fflush
(stdout
);
785 conout
(int *p
, char *s
)
790 (void) fflush
(stdout
);
800 if
(ss
== 0 ||
*ss
== 0)
801 (void) fprintf
(stderr
, gettext
("%s on line %d\n"), s
, ln
+1);
803 (void) fprintf
(stderr
, gettext
("%s on line %d, %s\n"),
805 (void) fflush
(stderr
);
811 b_sp_nxt
= &b_space
[0];
817 /* Do not exceed the last char in input line buffer */
819 yyerror("line too long\n");
827 /* puts the relevant stuff on pre and post for the letter s */
829 (void) bundle
(3, "S", s
, pre
);
831 (void) bundle
(4, post
, "L", s
, "s.");
837 { /* same as pp, but for temps */
838 bundle
(3, "0S", s
, pre
);
840 bundle
(4, post
, "L", s
, "s.");
845 yyinit
(int argc
, char **argv
)
849 (void) signal
(SIGINT
, SIG_IGN
); /* ignore all interrupts */
855 else if
((in
= fopen
(sargv
[0], "r")) == NULL
) {
856 (void) snprintf
(mbuf
, sizeof
(mbuf
), "can't open input file %s",
872 (void) fflush
(stdout
);
879 return
((int *) &funtab
[2*(*p
-0141)]);
885 return
((int *) &atab
[2*(*p
- 0141)]);
889 main
(int argc
, char **argv
)
898 (void) setlocale
(LC_ALL
, "");
899 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
900 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
902 (void) textdomain
(TEXT_DOMAIN
);
904 while
((flag
= getopt
(argc
, argv
, "dcl")) != EOF
) {
926 * argc is the count of arguments, which should be filenames,
927 * remaining in argv. av is a pointer to the first of the
928 * remaining arguments.
931 for
(filecounter
= 0; filecounter
< argc
; filecounter
++) {
932 if
((strlen
(av
[filecounter
])) >= PATH_MAX
) {
933 (void) fprintf
(stderr
,
934 gettext
("File argument too long\n"));
941 * if the user wants to include the math library, prepend
942 * the math library filename to the argument list by
943 * overwriting the last option (there must be at least one
944 * supplied option if this is being done).
946 av
= &argv
[optind
-1];
947 av
[0] = "/usr/lib/lib.b";
972 execl
("/usr/xpg6/bin/dc", "dc", "-", 0);
974 execl
("/usr/bin/dc", "dc", "-", 0);
983 (void) fprintf
(stderr
, gettext
(
984 "usage: bc [ -c ] [ -l ] [ file ... ]\n"));