Modified the UGetCursor() routine to return a valid response if the
[xcircuit.git] / asg / var.c
blob2c14542f07549f61bed3ae6b7f48839ff78494e5
1 /************************************************************
2 **
3 ** COPYRIGHT (C) 1993 UNIVERSITY OF PITTSBURGH
4 ** COPYRIGHT (C) 1996 GANNON UNIVERSITY
5 ** ALL RIGHTS RESERVED
6 **
7 ** This software is distributed on an as-is basis
8 ** with no warranty implied or intended. No author
9 ** or distributor takes responsibility to anyone
10 ** regarding its use of or suitability.
12 ** The software may be distributed and modified
13 ** freely for academic and other non-commercial
14 ** use but may NOT be utilized or included in whole
15 ** or part within any commercial product.
17 ** This copyright notice must remain on all copies
18 ** and modified versions of this software.
20 ************************************************************/
22 /*
23 * file var.c
24 * As part of MS Thesis Work, S T Frezza, UPitt Engineering
25 * June, 1990
27 * This file contains the structure and union manipulation functions that
28 * operate on VAR types and the underlying structures. These are based on the
29 * following definitions:
31 * typedef union var_item_union varItem;
32 * typedef struct var_item_struct varStruct;
33 * typedef struct var_struct var;
34 * typedef struct var_list_struct varlist;
36 * struct var_struct
37 * {
38 * int action;
39 * varStruct *item1;
40 * varStruct *item2;
41 * };
43 * struct var_item_struct
44 * {
45 * varItem *this;
46 * int type;
47 * };
49 * union var_union_type
50 * {
51 * int *i;
52 * srange *r;
53 * var *v;
54 * };
56 * struct var_struct_list
57 * {
58 * var *this;
59 * varlist *next;
60 * };
64 * These structures essentially create an evaluation tree for operations on ranges; It
65 * also implements a delayed evaluation mechanism. This means
66 * that there is an entire algebra being implemented (at least partially) within the following
67 * code. What is here is not that smart, and only has for operations { +, -, /, * }.
69 * For example, the sum of two ranges (caused by the evaluation of a _var_ structure with
70 * the operation ADD, and having two _varStruct_s which are both ranges yeilds a single
71 * range, which is the first range having both it's min and max fields augmented by the
72 * (integer) result of evaluating the second range. Note that the second range is altered
73 * (reduced) during this operation.
76 #include "externs.h"
79 /* ---- Local Variables ---------------------------------------------------------------*/
81 /*-------------------------------------------------------------------------------------*/
82 /* NEW STUFF - */
83 /*-------------------------------------------------------------------------------------*/
84 varStruct *create_int_varStruct(i)
85 int *i;
87 varStruct *vs;
88 vs = (varStruct *)calloc(1, sizeof(varStruct));
89 vs->type = INT;
90 vs->this = (varItem *)i;
91 return(vs);
93 /*-------------------------------------------------------------------------------------*/
94 varStruct *create_rng_varStruct(sr)
95 srange *sr;
97 varStruct *vs;
98 vs = (varStruct *)calloc(1, sizeof(varStruct));
99 vs->type = RNG;
100 vs->this = (varItem *)sr;
101 return(vs);
103 /*-------------------------------------------------------------------------------------*/
104 varStruct *create_var_varStruct(v)
105 var *v;
107 varStruct *vs;
108 vs = (varStruct *)calloc(1, sizeof(varStruct));
109 vs->type = VAR;
110 vs->this = (varItem *)v;
111 return(vs);
114 /*-------------------------------------------------------------------------------------*/
115 var *create_var_struct(a, i1, i2)
116 int a;
117 varStruct *i1, *i2;
119 /* Creates a var structure, with the given action and the two item pointers set. */
120 var *v;
121 v = (var *)calloc(1, sizeof(var));
122 v->action = a;
123 v->item1 = i1;
124 v->item2 = i2;
125 return(v);
127 /*-------------------------------------------------------------------------------------*/
128 /*-------------------------------------------------------------------------------------*/
129 srange *create_srange(q1, q2, or)
130 int q1, q2, or;
132 srange *r = (srange *)calloc(1, sizeof(srange));
133 r->q1 = MIN(q1, q2);
134 r->q2 = MAX(q1, q2);
135 r->orient = or;
136 return(r);
140 /*-------------------------------------------------------------------------------------*/
141 varStruct *reduce_var_struct(vs)
142 varStruct *vs;
144 /* NOTE: - this does not change <vs>, but if it is made up of vars, then it will
145 evaluate all of the lower var structures. */
146 int temp;
147 var *v;
150 switch (vs->type)
152 case INT:
153 case RNG: return(vs);
154 break;
156 case VAR: v = (var *)vs->this;
157 temp = eval_var_struct(v->item2);
158 return(eval_action(v->action,
159 v->item1, v->item2));
160 break;
161 default: fprintf(stderr, "screwy varStruct passed to REDUCE_VAR_STRUCT\n");
164 /*-------------------------------------------------------------------------------------*/
165 int eval_srange(r)
166 srange *r;
168 /* This returns an integer equivalent to the center of the given range: */
169 int sum;
170 if (r->q1 != r->q2)
172 sum = r->q1 + r->q2;
173 r->q1 = r->q2 = sum/2;
175 return(r->q1);
178 /*-------------------------------------------------------------------------------------*/
179 int eval_var_struct(vs)
180 varStruct *vs;
182 /* NOTE: - this changes <vs> */
183 int temp = 0;
185 switch (vs->type)
187 case INT: temp = (vs->this == NULL) ? 0 : *(int *)vs->this;
188 break;
189 case RNG: temp = eval_srange((srange *)vs->this);
190 break;
191 case VAR: temp = eval_var((var *)vs->this);
192 break;
193 default: fprintf(stderr, "screwy varStruct passed to EVAL_VAR_struct\n");
195 vs->this = (varItem *)&temp;
196 vs->type = INT;
197 return(temp);
199 /*-------------------------------------------------------------------------------------*/
200 varStruct *add_var_structs(i1,i2)
201 varStruct *i1, *i2;
203 /* adds <i1> to <i2>. <i2> MUST (or will be coerced)resolve to an integer.
204 * This modifies the internal values within <i1> and <i2>. <i1>'s union remains
205 * of the same type as it starts; i2 is reduced to an integer, if it is not one
206 * already. */
208 int addend = eval_var_struct(i2), t, *temp;
209 srange *sr;
210 var *v;
212 switch (i1->type)
214 case INT: t = *(int *)i1->this + addend;
215 temp = &t;
216 i1->this = (varItem *)&temp;
217 break;
218 case RNG: sr = (srange *)i1->this;
219 sr->q1 = sr->q1 + addend;
220 sr->q2 = sr->q2 + addend;
221 break;
222 case VAR: v = (var *)i1->this;
223 /* Recursively distribute the denom throughout the entire
224 nested var structure */
225 v->item1 = add_var_structs(v->item1, i2);
226 v->item2 = add_var_structs(v->item2, i2);
227 break;
228 default: fprintf(stderr, "screwy varStruct passed to ADD_VAR_structS\n");
230 return(i1);
233 /*-------------------------------------------------------------------------------------*/
234 varStruct *subtract_var_structs(i1,i2)
235 varStruct *i1, *i2;
237 /* subtracts <i2> from <i1>. <i2> MUST resolve (or will be coerced) to an integer.
238 * This modifies the internal values within <i1> and <i2>. <i1>'s union remains
239 * of the same type as it starts; i2 is reduced to an integer, if it is not one
240 * already. */
242 int subtrahend = eval_var_struct(i2), t, *temp;
243 srange *sr;
244 var *v;
246 switch (i1->type)
248 case INT: t = *(int *)i1->this - subtrahend;
249 i1->this = (varItem *)&t;
250 break;
251 case RNG: sr = (srange *)i1->this;
252 sr->q1 = sr->q1 - subtrahend;
253 sr->q2 = sr->q2 - subtrahend;
254 break;
255 case VAR: v = (var *)i1->this;
256 /* Recursively distribute the denom throughout the entire
257 nested var structure */
258 v->item1 = subtract_var_structs(v->item1, i2);
259 v->item2 = subtract_var_structs(v->item2, i2);
260 break;
261 default: fprintf(stderr, "screwy varStruct passed to SUBTRACT_VAR_structS\n");
263 return(i1);
266 /*-------------------------------------------------------------------------------------*/
267 varStruct *multiply_var_structs(i1,i2)
268 varStruct *i1, *i2;
270 /* multiply <i1> by <i2>. <i2> MUST resolve (or will be coerced) to an integer.
271 * This modifies the internal values within <i1> and <i2>. <i1>'s union remains
272 * of the same type as it starts; i2 is reduced to an integer, if it is not one
273 * already. */
275 int multiplicand = eval_var_struct(i2), t, *temp;
276 srange *sr;
277 var *v;
279 switch (i1->type)
281 case INT: t = *(int *)i1->this * multiplicand;
282 i1->this = (varItem *)&t;
283 break;
284 case RNG: sr = (srange *)i1->this;
285 sr->q1 = sr->q1 * multiplicand;
286 sr->q2 = sr->q2 * multiplicand;
287 break;
288 case VAR: v = (var *)i1->this;
289 /* Recursively distribute the denom throughout the entire
290 nested var structure */
291 v->item1 = multiply_var_structs(v->item1, i2);
292 v->item2 = multiply_var_structs(v->item2, i2);
293 break;
294 default: fprintf(stderr, "screwy varStruct passed to MULTIPLY_VAR_structS\n");
296 return(i1);
299 /*-------------------------------------------------------------------------------------*/
300 varStruct *divide_var_structs(i1,i2)
301 varStruct *i1, *i2;
303 /* divide <i1> by <i2>. <i2> MUST resolve (or will be coerced) to an integer.
304 * This modifies the internal values within <i1> and <i2>. <i1>'s union remains
305 * of the same type as it starts; i2 is reduced to an integer, if it is not one
306 * already. */
308 int denom = eval_var_struct(i2), t, *temp;
309 srange *sr;
310 var *v;
312 switch (i1->type)
314 case INT: t = *(int *)i1->this / denom;
315 i1->this = (varItem *)&t;
316 break;
317 case RNG: sr = (srange *)i1->this;
318 sr->q1 = sr->q1 / denom;
319 sr->q2 = sr->q2 / denom;
320 break;
321 case VAR: v = (var *)i1->this;
322 /* Recursively distribute the denom throughout the entire
323 nested var structure */
324 v->item1 = divide_var_structs(v->item1, i2);
325 v->item2 = divide_var_structs(v->item2, i2);
326 break;
327 default: fprintf(stderr, "screwy varStruct passed to DIVIDE_VAR_STRUCTS\n");
329 return(i1);
332 /*-------------------------------------------------------------------------------------*/
333 varStruct *eval_action(a,i1,i2)
334 int a;
335 varStruct *i1, *i2;
337 /* This takes an action and a pair of items and performs the intended action */
338 switch (a)
340 case ADD: return(add_var_structs(i1, i2));
341 break;
342 case SUBTRACT: return(subtract_var_structs(i1, i2));
343 break;
344 case MULTIPLY: return(multiply_var_structs(i1, i2));
345 break;
346 case DIVIDE: return(divide_var_structs(i1, i2));
347 break;
348 default : fprintf(stderr, "screwed up call to EVAL_ACTION\n");
349 return(NULL);
352 /*-------------------------------------------------------------------------------------*/
353 var *reduce_var(v)
354 var *v;
356 /* This reduces a complex var structure to a simplified one, that is where only
357 ->item1 is active, and the action is ADD. */
358 varStruct *vt = reduce_var_struct(v->item1);
359 switch (v->action)
361 case ADD: vt = add_var_structs(vt, v->item2);
362 break;
363 case SUBTRACT: vt = subtract_var_structs(vt, v->item2);
364 break;
365 case MULTIPLY: vt = multiply_var_structs(vt, v->item2);
366 break;
367 case DIVIDE: vt = divide_var_structs(vt, v->item2);
368 break;
369 default : fprintf(stderr, "screwed up call to REDUCE_VAR\n");
370 vt = NULL;
371 break;
373 v->item1 = vt;
374 v->item2 = NULL;
375 v->action = ADD;
377 return(v);
379 /*-------------------------------------------------------------------------------------*/
380 int eval_var(v)
381 var *v;
383 /* This reduces a complex var structure to a simplified one, and then performs the
384 * operation. All open range structures are replaced by fixed, arbitrary, legal
385 * values.
388 varStruct *vt = eval_action(v->action, v->item1, v->item2);
389 int *temp = (int *)vt->this;
391 return(*temp);
394 /*-------------------------------------------------------------------------------------*/
395 /*-------------------------------------------------------------------------------------*/
396 /*-------------------------------------------------------------------------------------*/
397 /* end of file "var.c" */