Commit | Line | Data |
---|---|---|
ec15bdbc LM |
1 | /* depend: */ |
2 | /* cflags: */ | |
f2927108 | 3 | /* linker: atoi.o debug.o fdprintf.o parser.o -lm */ |
ec15bdbc | 4 | |
01f02c41 LM |
5 | //#include <malloc.h> |
6 | #include <stddef.h> | |
ec15bdbc | 7 | #include <stdio.h> |
ec15bdbc LM |
8 | #include <unistd.h> |
9 | ||
01f02c41 | 10 | #include "atoi.h" |
bc97a989 | 11 | #include "debug.h" |
01f02c41 | 12 | #include "fdprintf.h" |
bc97a989 | 13 | #include "parser.h" |
01f02c41 | 14 | |
ec15bdbc LM |
15 | /* constants */ |
16 | ||
17 | //#define BUFFER_SIZE 4096 | |
18 | #define BUFFER_SIZE 256 | |
19 | ||
20 | /* macros */ | |
21 | ||
22 | #define CEIL(x, y) (((x) + (y) - 1) / (y)) | |
23 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | |
24 | #define MAX(x, y) (((x) > (y)) ? (x) : (y)) | |
25 | ||
ec15bdbc LM |
26 | /* gobal variables */ |
27 | ||
28 | char *progname = NULL; | |
ec15bdbc LM |
29 | |
30 | /* help function */ | |
31 | ||
01f02c41 | 32 | int usage (int ret) |
ec15bdbc | 33 | { |
01f02c41 LM |
34 | int fd = ret ? stdfderr : stdfdout; |
35 | fdprintf (fd, "usage: %s\n", progname); | |
36 | fdprintf (fd, " -h : help message\n"); | |
37 | fdprintf (fd, " -v : verbose level (%d)\n", verbose); | |
ec15bdbc | 38 | |
01f02c41 | 39 | return ret; |
ec15bdbc LM |
40 | } |
41 | ||
42 | /* main function */ | |
43 | ||
44 | int main (int argc, char *argv[]) | |
45 | { | |
46 | char buffer[BUFFER_SIZE + 1] = {0}; | |
47 | char *pt = buffer; | |
01f02c41 | 48 | int i = 0, j = 0, n; |
efdfb543 | 49 | int ret = 0; |
01f02c41 LM |
50 | |
51 | /* program name */ | |
ec15bdbc LM |
52 | |
53 | progname = argv[0]; | |
01f02c41 LM |
54 | while (progname[i] != '\0') { |
55 | if ((progname[i] == '/') || (progname[i] == '\\')) { | |
56 | progname += i + 1; | |
57 | i = 0; | |
58 | } else { | |
59 | i++; | |
60 | } | |
61 | } | |
62 | ||
63 | /* argument processing */ | |
ec15bdbc | 64 | |
01f02c41 LM |
65 | while (argc-- > 1) { |
66 | char *arg = *(++argv); | |
67 | if (arg[0] != '-') { | |
68 | PRINTERR ("%s: invalid option -- %s\n", progname, arg); | |
69 | return usage (1); | |
70 | } | |
71 | char c = arg[1]; | |
ec15bdbc LM |
72 | switch (c) { |
73 | case 'v': | |
01f02c41 LM |
74 | arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL; |
75 | if (arg == NULL) { | |
76 | PRINTERR ("%s: missing verbose level\n", progname); | |
77 | return usage (1); | |
78 | } | |
79 | verbose = atoi (arg); | |
ec15bdbc LM |
80 | break; |
81 | case 'h': | |
ec15bdbc | 82 | default: |
01f02c41 | 83 | return usage (c != 'h'); |
ec15bdbc LM |
84 | } |
85 | } | |
ec15bdbc LM |
86 | |
87 | /* read from input stream */ | |
01f02c41 LM |
88 | |
89 | while ((n = read (stdfdin, pt, BUFFER_SIZE - (pt - buffer))) != 0) { | |
49223129 | 90 | VERBOSE (INFO, PRINTOUT ("read %d bytes\n", n)); |
ec15bdbc | 91 | n += (pt - buffer); |
bc97a989 LM |
92 | if ((n == 2) && (buffer[0] == '.')) { |
93 | return 0; | |
94 | } | |
ec15bdbc LM |
95 | |
96 | /* look for end of line */ | |
97 | for (i = 0, j = 0; i < n; i++) { | |
98 | if (buffer[i] == '\n') { | |
99 | buffer[i] = 0; | |
49223129 | 100 | VERBOSE (INFO, PRINTOUT ("line(%d): %s\n", j, buffer + j)); |
031d7bba LM |
101 | element_t *element = parser (buffer + j, NULL, 0); |
102 | if (element == ERROR_OP) { | |
bc97a989 | 103 | VERBOSE (WARNING, PRINTOUT ("error while parsing: %s\n", buffer)); |
efdfb543 | 104 | ret = 1; |
031d7bba | 105 | } else { |
f2927108 | 106 | VERBOSE (INFO, print_element (element, 0)); |
3b4b0bbe | 107 | PRINTOUT ("=> %f\n", evaluate_element (element, 0)); |
031d7bba | 108 | delelement (element); |
efdfb543 | 109 | ret = 0; |
bc97a989 | 110 | } |
01f02c41 | 111 | //fsync (stdfdout); |
ec15bdbc LM |
112 | j = i + 1; |
113 | } | |
114 | } | |
115 | ||
116 | /* keep remainding */ | |
117 | if (j < n) { | |
118 | for (i = 0; i < n - j; i++) { | |
119 | buffer[i] = buffer[i + j]; | |
120 | } | |
121 | pt = buffer + n - j; | |
122 | for (i = n - j; i < BUFFER_SIZE; i++) { | |
123 | buffer[i] = 0; | |
124 | } | |
125 | } | |
126 | } | |
127 | ||
efdfb543 | 128 | return ret; |
ec15bdbc LM |
129 | } |
130 | ||
131 | // test: calc.exe -h | |
132 | // test: calc.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }' | |
b449884c | 133 | // test: echo 1 | calc.exe -v3 | grep -q value |
ec15bdbc LM |
134 | // test: calc.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }' |
135 | // test: calc.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }' | |
f2927108 LM |
136 | // test: echo "1 + 2" | calc.exe | grep -q '=> 3' |
137 | // test: echo "1 - 2" | calc.exe | grep -q '=> -1' | |
138 | // test: echo "2 * 3" | calc.exe | grep -q '=> 6' | |
139 | // test: echo "1 / 2" | calc.exe | grep -q '=> 5e-1' | |
c47a9298 LM |
140 | // test: echo "8 % 3" | calc.exe | grep -q '=> 2' |
141 | // test: echo "-9 % 3.1" | calc.exe | grep -q '=> -2.8' | |
f2927108 LM |
142 | // test: echo "2 ^ 3" | calc.exe | grep -q '=> 8' |
143 | // test: echo "1e-1 + 2.34e3" | calc.exe | grep -q '=> 2.3401' | |
144 | // test: echo "sqrt (2)" | calc.exe | grep -q '=> 1.414213' | |
145 | // test: echo "pow (2, 3)" | calc.exe | grep -q '=> 8' | |
146 | // test: echo "cos (2)" | calc.exe | grep -q '=> -4.161468e-1' | |
147 | // test: echo "sin (2)" | calc.exe | grep -q '=> 9.092974e-1' | |
148 | // test: echo "atan (2)" | calc.exe | grep -q '=> 1.107148' | |
149 | // test: echo "exp (2)" | calc.exe | grep -q '=> 7.389056' | |
150 | // test: echo "log (2)" | calc.exe | grep -q '=> 6.931471e-1' | |
151 | // test: echo "2 + 3 - 4" | calc.exe | grep -q '=> 1' | |
152 | // test: echo "1 + cos (2 - 3)" | calc.exe | grep -q '=> 1.54030' | |
153 | // test: echo "cos (1 / 2) * 3" | calc.exe | grep -q '=> 2.63274' | |
154 | // test: echo "1 + 4 * (2 - 3)" | calc.exe | grep -q '=> -3' | |
155 | // test: echo "(2 - 3) / 4" | calc.exe | grep -q '=> -2.5e-1' | |
156 | // test: echo "pow (8 - 3, 4 / 3)" | calc.exe | grep -q '=> 8.549879' | |
157 | // test: echo "1 + -2" | calc.exe | grep -q '=> -1' | |
158 | // test: echo "1 - +2" | calc.exe | grep -q '=> -1' | |
159 | // test: echo "-1 + +2" | calc.exe | grep -q '=> 1' | |
160 | // test: echo "-1+2" | calc.exe | grep -q '=> 1' | |
161 | // test: echo "1-2" | calc.exe | grep -q '=> -1' | |
162 | // test: echo "1 * 2 / 3 + 4" | calc.exe | grep -q '=> 4.666666' | |
163 | // test: echo "2 ^ 3 * 4 + 5" | calc.exe | grep -q '=> 3.7e1' | |
164 | // test: echo "2 + 3 * 4 ^ 5" | calc.exe | grep -q '=> 3.074e3' | |
165 | // test: echo "2 ^ 3 * 4 + cos(5/6)" | calc.exe | grep -q '=> 3.267241e1' | |
b449884c | 166 | // test: echo "95-6.3*15-1" | calc.exe | grep -q '=> -5.000028e-1' |
3b4b0bbe | 167 | // test: echo "95 - 6.3 * 15 - 1" | calc.exe | grep -q '=> -5.000028e-1' |
b449884c | 168 | // test: echo "95-6.3+15" | calc.exe | grep -q '=> 1.037e2' |
3b4b0bbe | 169 | // test: echo "-cos (0) + 1" | calc.exe | grep -q '=> 0' |
89cf0955 LM |
170 | // test: echo "quit" | calc.exe | grep -q 'bye' |
171 | // test: echo "help" | calc.exe | grep -q 'miscellaneous' | |
031d7bba LM |
172 | // test: echo "1 + 2 *" | calc.exe | grep -q 'error' |
173 | // test: echo "* 1 - 2" | calc.exe | grep -q 'error' | |
174 | // test: echo "2 + * 3" | calc.exe | grep -q 'error' | |
175 | // test: echo "sqrt 2" | calc.exe | grep -q 'error' | |
176 | // test: echo "pow (2)" | calc.exe | grep -q 'error' | |
ec15bdbc LM |
177 | |
178 | /* vim: set ts=4 sw=4 et: */ |