w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

strexpr.c
Go to the documentation of this file.
1 /*
2  * File: strexpr.c
3  * Purpose: calculate value from algebraic string expression
4  * (Stripped down from expr.c from J.T. Conklin <jtc@netbsd.org>.)
5  * Version: 1.0 (Nov 1995)
6  * Author: Piet Tutelaers
7  */
8 
9 #include <stdio.h> /* sprintf() */
10 #include <stdlib.h> /* free(), malloc() */
11 #include <string.h> /* strchr(), strcpy() */
12 #include <ctype.h> /* isdigit(), isspace() */
13 #include "basics.h" /* fatal() */
14 
15 const char *OPERATORS = "+-*/%()";
16 
17 enum token {
19 };
20 
21 struct val {
22  enum {
24  string
25  } type;
26 
27  union {
28  char *s;
29  int i;
30  } u;
31 };
32 
33 enum token token;
34 struct val *tokval;
35 char *pexpr;
36 
37 struct val *
38 make_int(int i)
39 {
40  struct val *vp;
41 
42  vp = (struct val *) malloc(sizeof(*vp));
43  if (vp == NULL) fatal("expression error\n");
44  vp->type = integer;
45  vp->u.i = i;
46  return vp;
47 }
48 
49 
50 struct val *
51 make_str(char *s)
52 {
53  char operand[32]; int i;
54 
55  struct val *vp;
56 
57  vp = (struct val *) malloc(sizeof(*vp));
58  if (vp == NULL) fatal("expression error\n");
59 
60  pexpr = s; i = 0;
61  while (1) {
62  if (isspace(*pexpr) || *pexpr == '\0') break;
63  if (strchr(OPERATORS, *pexpr) != NULL) break;
64  if (i == 30) fatal("operand too large\n");
65  operand[i++] = *pexpr++;
66  }
67  if (i == 0) fatal("invalid operand\n");
68  operand[i] = '\0';
69  vp->u.s = malloc(i+1);
70  if (vp->u.s == NULL) fatal("Out of memory\n");
71  strcpy(vp->u.s, operand);
72  vp->type = string;
73  return vp;
74 }
75 
76 
77 void
78 free_value(struct val *vp)
79 {
80  if (vp->type == string)
81  free(vp->u.s);
82  free(vp);
83 }
84 
85 
86 /* determine if vp is an integer; if so, return it's value in *r */
87 int
88 is_integer(struct val *vp, int *r)
89 {
90  char *s;
91  int neg;
92  int i;
93 
94  if (vp->type == integer) {
95  *r = vp->u.i;
96  return 1;
97  }
98 
99  /*
100  * POSIX.2 defines an "integer" as an optional unary minus
101  * followed by digits.
102  */
103  s = vp->u.s;
104  i = 0;
105 
106  neg = (*s == '-');
107  if (neg)
108  s++;
109 
110  while (*s) {
111  if (!isdigit(*s))
112  return 0;
113 
114  i *= 10;
115  i += *s - '0';
116 
117  s++;
118  }
119 
120  if (neg)
121  i *= -1;
122 
123  *r = i;
124  return 1;
125 }
126 
127 
128 /* coerce to vp to an integer */
129 int
130 to_integer(struct val *vp)
131 {
132  int r;
133 
134  if (vp->type == integer)
135  return 1;
136 
137  if (is_integer(vp, &r)) {
138  free(vp->u.s);
139  vp->u.i = r;
140  vp->type = integer;
141  return 1;
142  }
143 
144  return 0;
145 }
146 
147 
148 /* coerce to vp to an string */
149 void
150 to_string(struct val *vp)
151 {
152  char *tmp;
153 
154  if (vp->type == string)
155  return;
156 
157  tmp = malloc(25);
158  if (tmp == NULL) fatal("Out of memory\n");
159  sprintf(tmp, "%d", vp->u.i);
160  vp->type = string;
161  vp->u.s = tmp;
162 }
163 
164 void
166 {
167  char *i; /* index */
168 
169  while (isspace(*pexpr)) pexpr++;
170 
171  if (*pexpr == '\0') {
172  token = EOI;
173  return;
174  }
175 
176  if ((i = strchr(OPERATORS, *pexpr)) != NULL) {
177  pexpr++;
178  token = i - OPERATORS;
179  return;
180  }
181  tokval = make_str(pexpr);
182  token = OPERAND;
183  return;
184 }
185 
186 struct val *
188 {
189  struct val *eval3(void);
190  struct val *v;
191 
192  if (token == OPERAND) {
193  nexttoken();
194  return tokval;
195 
196  } else if (token == LP) {
197  nexttoken();
198  v = eval3();
199 
200  if (token != RP)
201  fatal("missing parenthesis in expression\n");
202  nexttoken();
203  return v;
204  } else fatal("expression error\n");
205  /* NOTREACHED */
206 }
207 
208 /* Parse and evaluate multiplication and division expressions */
209 struct val *
211 {
212  struct val *l, *r;
213  enum token op;
214 
215  l = eval6();
216  while ((op = token) == MUL || op == DIV || op == MOD) {
217  nexttoken();
218  r = eval6();
219 
220  if (!to_integer(l) || !to_integer(r)) {
221  fatal("non-numeric argument\n");
222  }
223 
224  if (op == MUL) {
225  l->u.i *= r->u.i;
226  } else {
227  if (r->u.i == 0) {
228  fatal("division by zero\n");
229  }
230  if (op == DIV) {
231  l->u.i /= r->u.i;
232  } else {
233  l->u.i %= r->u.i;
234  }
235  }
236 
237  free_value(r);
238  }
239 
240  return l;
241 }
242 
243 /* Parse and evaluate addition and subtraction expressions */
244 struct val *
246 {
247  struct val *l, *r;
248  enum token op;
249 
250  l = eval4();
251  while ((op = token) == ADD || op == SUB) {
252  nexttoken();
253  r = eval4();
254 
255  if (!to_integer(l) || !to_integer(r)) {
256  fatal("non-numeric argument\n");
257  }
258 
259  if (op == ADD) {
260  l->u.i += r->u.i;
261  } else {
262  l->u.i -= r->u.i;
263  }
264 
265  free_value(r);
266  }
267 
268  return l;
269 }
270 
271 /*
272  * Evaluate the algebraic expression contained in <expression>. The
273  * value will be assigned to <result>. When errors are encountered
274  * non-zero is returned (if program is not aborted) otherwise zero.
275  */
276 int strexpr(int *result, char *expression) {
277  struct val *vp;
278 
279  pexpr = expression;
280 
281  nexttoken();
282  vp = eval3();
283 
284  if (token != EOI) return 1;
285 
286  if (vp->type == integer || to_integer(vp)) {
287  *result = vp->u.i;
288  return 0;
289  }
290 
291  return 1;
292 }
#define free(a)
Definition: decNumber.cpp:310
int v
Definition: dviconv.c:10
char * strcpy()
#define s
Definition: afcover.h:80
#define strchr
Definition: gsftopk.c:59
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
#define string
Definition: ctangleboot.c:111
#define malloc
Definition: alloca.c:91
#define fatal
Definition: tie.c:14
#define sprintf
Definition: snprintf.c:44
#define isdigit(c)
Definition: snprintf.c:177
int integer
Definition: pbmtopk.c:38
int r
Definition: ppmqvga.c:68
#define isspace(ch)
Definition: utype.h:87
struct val * eval6()
Definition: strexpr.c:187
char * pexpr
Definition: strexpr.c:35
struct val * eval4()
Definition: strexpr.c:210
struct val * tokval
Definition: strexpr.c:34
token
Definition: strexpr.c:17
@ MUL
Definition: strexpr.c:18
@ RP
Definition: strexpr.c:18
@ SUB
Definition: strexpr.c:18
@ MOD
Definition: strexpr.c:18
@ LP
Definition: strexpr.c:18
@ DIV
Definition: strexpr.c:18
@ EOI
Definition: strexpr.c:18
@ OPERAND
Definition: strexpr.c:18
@ ADD
Definition: strexpr.c:18
void to_string(struct val *vp)
Definition: strexpr.c:150
struct val * eval3()
Definition: strexpr.c:245
struct val * make_str(char *s)
Definition: strexpr.c:51
int strexpr(int *result, char *expression)
Definition: strexpr.c:276
void free_value(struct val *vp)
Definition: strexpr.c:78
const char * OPERATORS
Definition: strexpr.c:15
struct val * make_int(int i)
Definition: strexpr.c:38
int is_integer(struct val *vp, int *r)
Definition: strexpr.c:88
int to_integer(struct val *vp)
Definition: strexpr.c:130
void nexttoken()
Definition: strexpr.c:165
Definition: sh.h:1226
Definition: parser.c:43
Definition: strexpr.c:21
int i
Definition: strexpr.c:29
union val::@185 u
@ integer
Definition: strexpr.c:23
enum val::@184 type
char * s
Definition: strexpr.c:28
op
Definition: tex4ht.c:3129