Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / snmp / eval.c
CommitLineData
9e8e5516
C
1/* eval.c - MIB realization of the EVAL group */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/snmp/RCS/eval.c,v 7.7 91/02/22 09:43:13 mrose Interim $";
5#endif
6
7/*
8 * $Header: /f/osi/snmp/RCS/eval.c,v 7.7 91/02/22 09:43:13 mrose Interim $
9 *
10 *
11 * $Log: eval.c,v $
12 * Revision 7.7 91/02/22 09:43:13 mrose
13 * Interim 6.8
14 *
15 * Revision 7.6 91/01/13 11:05:42 mrose
16 * update
17 *
18 * Revision 7.5 91/01/12 21:38:32 mrose
19 * typo
20 *
21 * Revision 7.4 91/01/12 21:25:41 mrose
22 * again
23 *
24 * Revision 7.3 91/01/12 21:22:49 mrose
25 * update
26 *
27 * Revision 7.2 90/12/18 10:13:19 mrose
28 * update
29 *
30 * Revision 7.1 90/11/20 15:31:59 mrose
31 * update
32 *
33 * Revision 7.0 90/11/18 09:30:47 mrose
34 * *** empty log message ***
35 *
36 */
37
38/*
39 * NOTICE
40 *
41 * Acquisition, use, and distribution of this module and related
42 * materials are subject to the restrictions of a license agreement.
43 * Consult the Preface in the User's Manual for the full terms of
44 * this agreement.
45 *
46 */
47
48
49#include <ctype.h>
50#include <stdio.h>
51#include "mib.h"
52
53/* \f FUNCTION MIB */
54
55#define NSTACK 10
56
57static integer *tos;
58static integer *roof;
59static integer fstack[NSTACK + 1];
60
61
62#define NEXPR 10
63
64struct expr {
65 PStream e_ps;
66
67 int e_eval; /* exprEval */
68
69 char *e_expr; /* exprExpr */
70 int e_size;
71
72 int e_status; /* exprStatus */
73#define E_noError 0
74#define E_divide 1
75#define E_overflow 2
76#define E_underflow 3
77#define E_noSuchName 4
78#define E_notAnInteger 5
79#define E_other 6
80
81 /* exprHints */
82 char e_hints[255 + 1];
83
84 struct {
85 char *expr;
86
87 int size;
88 } e_save;
89};
90
91static integer exprNumber = 0;
92
93static struct expr exprs[NEXPR];
94static struct expr *curexpr = NULL;
95static struct expr *roofexpr;
96
97/* \f */
98
99#define functAdd 0
100#define functSub 1
101#define functMul 2
102#define functDiv 3
103#define functMod 4
104#define functNeg 5
105#define functXch 6
106#define functClr 7
107#define functDup 8
108#define functPop 9
109#define functAbs 10
110#define functSgn 11
111#define functMin 12
112#define functAnd 13
113#define functOr 14
114#define functNot 15
115
116
117static int o_funct (oi, v, offset)
118OI oi;
119register struct type_SNMP_VarBind *v;
120int offset;
121{
122 int ifvar;
123 integer arg1,
124 arg2;
125 register OT ot = oi -> oi_type;
126
127 ifvar = (int) ot -> ot_info;
128 switch (offset) {
129 case type_SNMP_PDUs_get__request:
130 if (curexpr == NULL)
131 return int_SNMP_error__status_noSuchName;
132 break;
133
134 case type_SNMP_PDUs_get__next__request:
135 if (curexpr == NULL)
136 return NOTOK;
137 break;
138
139 default:
140 return int_SNMP_error__status_genErr;
141 }
142
143#define get_arg(a) \
144 if (tos <= fstack + 1) { \
145 curexpr -> e_status = E_underflow; \
146 (void) strcpy (curexpr -> e_hints, "stack underflow"); \
147 return NOTOK; \
148 } \
149 (a) = *--tos;
150
151 switch (ifvar) {
152 case functAdd:
153 case functSub:
154 case functMul:
155 case functDiv:
156 case functMod:
157 case functXch:
158 case functDup:
159 case functMin:
160 case functAnd:
161 case functOr:
162 get_arg (arg2);
163 get_arg (arg1);
164 break;
165
166 case functNeg:
167 case functPop:
168 case functAbs:
169 case functSgn:
170 case functNot:
171 get_arg (arg1);
172 break;
173
174 case functClr:
175 arg1 = 0;
176 break;
177
178 default:
179 return int_SNMP_error__status_genErr;
180 }
181#undef get_arg
182
183 switch (ifvar) {
184 case functAdd:
185 arg1 += arg2;
186 break;
187
188 case functSub:
189 arg1 -= arg2;
190 break;
191
192 case functMul:
193 arg1 *= arg2;
194 break;
195
196 case functDiv:
197 if (arg2 == 0) {
198 curexpr -> e_status = E_divide;
199 (void) strcpy (curexpr -> e_hints, "division by zero");
200 return NOTOK;
201 }
202 arg1 /= arg2;
203 break;
204
205 case functMod:
206 if (arg2 == 0) {
207 curexpr -> e_status = E_divide;
208 (void) strcpy (curexpr -> e_hints, "modulus by zero");
209 return NOTOK;
210 }
211 arg1 %= arg2;
212 break;
213
214 case functNeg:
215 arg1 = -arg1;
216 break;
217
218 case functXch:
219 *tos++ = arg2;
220 break;
221
222 case functClr:
223 tos = fstack;
224 return NOTOK;
225
226 case functDup:
227 *tos++ = arg1;
228 break;
229
230 case functPop:
231 arg1 = tos <= fstack ? 0 : *--tos;
232 return NOTOK;
233
234 case functAbs:
235 if (arg1 < 0)
236 arg1 = -arg1;
237 break;
238
239 case functSgn:
240 arg1 = arg1 > 0 ? 1 : arg1 < 0 ? -1 : 0;
241 break;
242
243 case functMin:
244 if (arg2 < arg1)
245 arg1 = arg2;
246 break;
247
248 case functAnd:
249 arg1 &= arg2;
250 break;
251
252 case functOr:
253 arg1 |= arg2;
254 break;
255
256 case functNot:
257 arg1 = !arg1;
258 break;
259
260 default:
261 return int_SNMP_error__status_noSuchName;
262 }
263
264 return o_integer (oi, v, arg1);
265}
266
267/* \f */
268
269/* assumes that exprEval occurs first in variable-bindings of get... */
270
271#define exprIndex 0
272#define exprEval 1
273#define exprExpr 2
274#define exprStatus 3
275#define exprHints 4
276
277
278static int o_expressions (oi, v, offset)
279OI oi;
280register struct type_SNMP_VarBind *v;
281int offset;
282{
283 int ifnum,
284 ifvar;
285 register OID oid = oi -> oi_name;
286 register OT ot = oi -> oi_type;
287 register struct expr *e;
288
289 ifvar = (int) ot -> ot_info;
290 switch (offset) {
291 case type_SNMP_PDUs_get__request:
292 if (oid -> oid_nelem != ot -> ot_name -> oid_nelem + 1)
293 return int_SNMP_error__status_noSuchName;
294 if ((ifnum = oid -> oid_elements[oid -> oid_nelem - 1]) == 0
295 || ifnum > exprNumber)
296 return int_SNMP_error__status_noSuchName;
297 if ((e = exprs + ifnum - 1) -> e_expr == NULL)
298 return int_SNMP_error__status_noSuchName;
299 break;
300
301 case type_SNMP_PDUs_get__next__request:
302 if (oid -> oid_nelem == ot -> ot_name -> oid_nelem) {
303 OID new;
304
305 for (e = exprs; e < roofexpr; e++)
306 if (e -> e_expr)
307 break;
308 if (e >= roofexpr)
309 return NOTOK;
310 ifnum = (e - exprs) + 1;
311
312 if ((new = oid_extend (oid, 1)) == NULLOID)
313 return NOTOK;
314 new -> oid_elements[new -> oid_nelem - 1] = ifnum;
315
316 if (v -> name)
317 free_SNMP_ObjectName (v -> name);
318 v -> name = new;
319 }
320 else {
321 int i = ot -> ot_name -> oid_nelem;
322
323 if ((ifnum = oid -> oid_elements[i]) >= NEXPR)
324 return NOTOK;
325 for (e = exprs + ifnum; e < roofexpr; e++)
326 if (e -> e_expr)
327 break;
328 if (e >= roofexpr)
329 return NOTOK;
330 ifnum = (e - exprs) + 1;
331
332 oid -> oid_elements[i] = ifnum;
333 oid -> oid_nelem = i + 1;
334 }
335 break;
336
337 default:
338 return int_SNMP_error__status_genErr;
339 }
340
341 switch (ifvar) {
342 case exprIndex:
343 return o_integer (oi, v, ifnum);
344
345 case exprEval:
346 e -> e_eval = 0, e -> e_status = E_noError, e -> e_hints[0] = NULL;
347 (void) eval_expr (curexpr = e);
348 curexpr = NULL;
349 return o_integer (oi, v, e -> e_eval);
350
351 case exprExpr:
352 return o_string (oi, v, e -> e_expr, e -> e_size);
353
354 case exprStatus:
355 return o_integer (oi, v, e -> e_status);
356
357 case exprHints:
358 return o_string (oi, v, e -> e_hints, strlen (e -> e_hints));
359
360 default:
361 return int_SNMP_error__status_noSuchName;
362 }
363}
364
365/* \f */
366
367static int eval_expr (e)
368register struct expr *e;
369{
370 PElementClass class;
371 PElementForm form;
372 PElementID id;
373 PElementLen len;
374 PS ps = &e -> e_ps;
375
376 roof = (tos = fstack) + (sizeof fstack / sizeof fstack[0]);
377 tos++;
378
379 bzero ((char *) ps, sizeof *ps);
380 if (str_open (ps) == NOTOK) {
381 e -> e_status = E_other;
382 (void) strcpy (e -> e_hints, "str_open failed");
383 return NOTOK;
384 }
385 if (str_setup (ps, e -> e_expr, e -> e_size, 1) == NOTOK) {
386 e -> e_status = E_other;
387 (void) sprintf (e -> e_hints, "str_setup failed: %s",
388 ps_error (ps -> ps_errno));
389 return NOTOK;
390 }
391
392 if (read_tl (e, &class, &form, &id, &len) == NOTOK)
393 return NOTOK;
394 if (PE_ID (class, id) != PE_ID (PE_CLASS_UNIV, PE_CONS_SEQ)) {
395 e -> e_status = E_other;
396 (void) sprintf (e -> e_hints, "unexpected TAG: %d/%d", class, id);
397 return NOTOK;
398 }
399
400 while (ps -> ps_cnt > 0) {
401 integer i;
402 OID oid;
403
404 if (read_tl (e, &class, &form, &id, &len) == NOTOK)
405 return NOTOK;
406 switch (PE_ID (class, id)) {
407 case PE_ID (PE_CLASS_UNIV, PE_PRIM_INT):
408 if (read_long (e, ps -> ps_ptr, len, form, &i) == NOTOK)
409 return NOTOK;
410 break;
411
412 case PE_ID (PE_CLASS_UNIV, PE_PRIM_OID):
413 if (read_oid (e, ps -> ps_ptr, len, form, &oid) == NOTOK)
414 return NOTOK;
415 if (get_var_value (e, oid, &i) == NOTOK)
416 return NOTOK;
417 break;
418
419 default:
420 e -> e_status = E_other;
421 (void) sprintf (e -> e_hints, "unexpected TAG: %d/%d",
422 class, id);
423 return NOTOK;
424 }
425 ps -> ps_ptr += len, ps -> ps_cnt -= len;
426
427 if (tos < roof)
428 *tos++ = i;
429 else {
430 e -> e_status = E_overflow;
431 (void) strcpy (e -> e_hints, "stack overflow");
432 return NOTOK;
433 }
434 }
435
436 if (tos <= fstack) {
437 e -> e_status = E_underflow;
438 (void) strcpy (e -> e_hints, "stack underflow");
439 return NOTOK;
440 }
441 e -> e_eval = *--tos;
442
443 if (tos > fstack + 1 && e -> e_hints[0] == NULL)
444 (void) sprintf (e -> e_hints,
445 "%d items left on stack after evaluating expression",
446 tos - fstack - 1);
447
448 return OK;
449}
450
451/* \f */
452
453static int read_tl (e, class, form, id, len)
454struct expr *e;
455PElementClass *class;
456PElementForm *form;
457PElementID *id;
458PElementLen *len;
459{
460 PS ps = &e -> e_ps;
461
462 if (ps_read_id (ps, 0, class, form, id) == NOTOK) {
463 e -> e_status = E_other;
464 (void) sprintf (e -> e_hints, "error reading TAG info: %s",
465 ps_error (ps -> ps_errno));
466 return NOTOK;
467 }
468 if (ps_read_len (ps, len) == NOTOK) {
469 e -> e_status = E_other;
470 (void) sprintf (e -> e_hints, "error reading LEN info: %s",
471 ps_error (ps -> ps_errno));
472 return NOTOK;
473 }
474
475 return OK;
476}
477
478/* \f */
479
480static int read_long (e, base, len, form, result)
481struct expr *e;
482char *base;
483int len;
484PElementForm form;
485integer *result;
486{
487 register integer i;
488 register PElementData dp,
489 ep;
490
491 if (form != PE_FORM_PRIM) {
492 e -> e_status = E_other;
493 (void) sprintf (e -> e_hints, "integer: %s", pe_error (PE_ERR_PRIM));
494 return NOTOK;
495 }
496 if (len > sizeof (i)) {
497 e -> e_status = E_other;
498 (void) sprintf (e -> e_hints, "integer: %s", pe_error (PE_ERR_OVER));
499 return NOTOK;
500 }
501
502 i = (*(dp = (PElementData) base) & 0x80) ? (-1) : 0;
503 for (ep = dp + len; dp < ep;)
504 i = (i << 8) | (*dp++ & 0xff);
505
506 *result = i;
507
508 return OK;
509}
510
511/* \f */
512
513static int read_oid (e, base, len, form, ox)
514struct expr *e;
515char *base;
516int len;
517PElementForm form;
518OID *ox;
519{
520 register unsigned int i,
521 *ip;
522 register PElementData dp,
523 ep;
524 static OIDentifier oid;
525 register OID o = &oid;
526
527 if (form != PE_FORM_PRIM
528 || (dp = (PElementData) base) == NULLPED
529 || len == 0) {
530 e -> e_status = E_other;
531 (void) sprintf (e -> e_hints, "oid: %s", pe_error (PE_ERR_PRIM));
532 return NOTOK;
533 }
534 ep = dp + len;
535
536 if (o -> oid_elements)
537 free ((char *) o -> oid_elements);
538
539 for (i = 1; dp < ep; i++) { /* another whacko OSI encoding... */
540 if (*dp == 0x80) {
541 e -> e_status = E_other;
542 (void) sprintf (e -> e_hints, "oid: %s", pe_error (PE_ERR_OID));
543 return NOTOK;
544 }
545
546 while (*dp++ & 0x80)
547 if (dp > ep) {
548 e -> e_status = E_other;
549 (void) sprintf (e -> e_hints, "oid: %s",
550 pe_error (PE_ERR_OID));
551 return NOTOK;
552 }
553 }
554
555 if ((ip = (unsigned int *) malloc ((i + 1) * sizeof *ip)) == NULL) {
556 e -> e_status = E_other;
557 (void) sprintf (e -> e_hints, "oid: %s", pe_error (PE_ERR_NMEM));
558 return NOTOK;
559 }
560 o -> oid_elements = ip, o -> oid_nelem = i;
561
562 for (dp = (PElementData) base; dp < ep; ) {
563 i = 0;
564 do {
565 i <<= 7;
566 i |= *dp & 0x7f;
567 } while (*dp++ & 0x80);
568
569 if (ip != o -> oid_elements)
570 *ip++ = i;
571 else
572 if (i < 40)
573 *ip++ = 0, *ip++ = i;
574 else
575 if (i < 80)
576 *ip++ = 1, *ip++ = i - 40;
577 else
578 *ip++ = 2, *ip++ = i - 80;
579 }
580
581 *ox = o;
582
583 return OK;
584}
585
586/* \f */
587
588static int get_var_value (e, oid, i)
589struct expr *e;
590OID oid;
591integer *i;
592{
593 int status;
594 integer *result;
595 OI oi;
596 OS os;
597 OT ot;
598 struct type_SNMP_VarBind *v;
599
600 if ((oi = name2inst (oid)) == NULL) {
601 e -> e_status = E_noSuchName;
602 (void) sprintf (e -> e_hints, "variable %s unknown", oid2ode (oid));
603 return NOTOK;
604 }
605 if ((ot = oi -> oi_type) == NULL) {
606 e -> e_status = E_noSuchName;
607 (void) sprintf (e -> e_hints, "no object type for variable %s",
608 oid2ode (oid));
609 return NOTOK;
610 }
611 if ((os = ot -> ot_syntax) == NULL) {
612 e -> e_status = E_noSuchName;
613 (void) sprintf (e -> e_hints, "no object syntax for variable %s",
614 oid2ode (oid));
615 return NOTOK;
616 }
617
618 if (!os -> os_data2) {
619 e -> e_status = E_notAnInteger;
620 (void) sprintf (e -> e_hints, "variable %s is not integer-valued",
621 oid2ode (oid));
622 return NOTOK;
623 }
624
625 if (ot -> ot_getfnx == NULL) {
626 e -> e_status = E_noSuchName;
627 (void) sprintf (e -> e_hints, "no get method for variable %s",
628 oid2ode (oid));
629 return NOTOK;
630 }
631
632 if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL
633 || (v -> name = oid_cpy (oid)) == NULL
634 || (v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM,
635 PE_PRIM_NULL)) == NULL) {
636 if (v)
637 free_SNMP_VarBind (v);
638 e -> e_status = E_other;
639 (void) sprintf (e -> e_hints, "out of memory");
640 return NOTOK;
641 }
642
643 if ((status = (*ot -> ot_getfnx) (oi, v, type_SNMP_PDUs_get__request))
644 != int_SNMP_error__status_noError) {
645 if (e -> e_hints[0] == NULL)
646 (void) sprintf (e -> e_hints, "%s: %d", oid2ode (oid), status);
647losing: ;
648 free_SNMP_VarBind (v);
649 return NOTOK;
650 }
651
652 if ((*os -> os_decode) (&result, v -> value) == NOTOK) {
653 e -> e_status = E_other;
654 (void) sprintf (e -> e_hints, "%s: decoding error!", oid2ode (oid));
655 goto losing;
656 }
657 *i = *result;
658 free ((char *) result);
659 free_SNMP_VarBind (v);
660
661 return OK;
662}
663
664/* \f */
665
666static int s_expressions (oi, v, offset)
667OI oi;
668register struct type_SNMP_VarBind *v;
669int offset;
670{
671 int ifnum
672#ifndef lint
673 ,
674 ifvar
675#endif
676 ;
677 register OID oid = oi -> oi_name;
678 register OT ot = oi -> oi_type;
679 register OS os = ot -> ot_syntax;
680 register struct expr *e;
681 struct qbuf *qb;
682
683#ifndef lint
684 ifvar = (int) ot -> ot_info;
685#endif
686 switch (offset) {
687 case type_SNMP_PDUs_set__request:
688 case type_SNMP_PDUs_commit:
689 case type_SNMP_PDUs_rollback:
690 if (oid -> oid_nelem != ot -> ot_name -> oid_nelem + 1)
691 return int_SNMP_error__status_noSuchName;
692 if ((ifnum = oid -> oid_elements[oid -> oid_nelem - 1]) == 0
693 || ifnum > exprNumber + 1)
694 return int_SNMP_error__status_noSuchName;
695 e = exprs + ifnum - 1;
696 break;
697
698 default:
699 return int_SNMP_error__status_genErr;
700 }
701
702 if (os == NULLOS) {
703 advise (LLOG_EXCEPTIONS, NULLCP,
704 "no syntax defined for object \"%s\"", ot -> ot_text);
705
706 return int_SNMP_error__status_genErr;
707 }
708
709 switch (offset) {
710 case type_SNMP_PDUs_set__request:
711 if (e -> e_save.expr)
712 free (e -> e_save.expr), e -> e_save.expr = NULL;
713 if ((*os -> os_decode) ((caddr_t *) &qb, v -> value) == NOTOK)
714 return int_SNMP_error__status_badValue;
715 e -> e_save.expr = qb2str (qb);
716 e -> e_save.size = qb -> qb_len;
717 (*os -> os_free) (qb);
718 if (e -> e_save.expr == NULL)
719 return int_SNMP_error__status_genErr;
720 if (e -> e_save.size == 0)
721 free (e -> e_save.expr), e -> e_save.expr = NULL;
722 break;
723
724 case type_SNMP_PDUs_commit:
725 if (e -> e_expr)
726 free (e -> e_expr);
727 e -> e_expr = e -> e_save.expr, e -> e_save.expr = NULL;
728 e -> e_size = e -> e_save.size;
729 for (e = exprs + NEXPR - 1; e >= exprs; e--)
730 if (e -> e_expr)
731 break;
732 exprNumber = (e - exprs) + 1;
733 break;
734
735 case type_SNMP_PDUs_rollback:
736 if (e -> e_save.expr)
737 free (e -> e_save.expr), e -> e_save.expr = NULL;
738 break;
739 }
740
741 return int_SNMP_error__status_noError;
742}
743
744/* \f */
745
746init_eval () {
747 register OT ot;
748
749 roof = (tos = fstack) + (sizeof fstack / sizeof fstack[0]);
750 roofexpr = exprs + NEXPR;
751
752 bzero ((char *) exprs, sizeof exprs);
753
754 {
755 OS os;
756
757 if (os = text2syn ("INTEGER"))
758 os -> os_data2 = 1;
759
760 if (os = text2syn ("Counter"))
761 os -> os_data2 = 1;
762
763 if (os = text2syn ("Gauge"))
764 os -> os_data2 = 1;
765
766 if (os = text2syn ("TimeTicks"))
767 os -> os_data2 = 1;
768 }
769
770 if (ot = text2obj ("functAdd"))
771 ot -> ot_getfnx = o_funct,
772 ot -> ot_info = (caddr_t) functAdd;
773 if (ot = text2obj ("functSub"))
774 ot -> ot_getfnx = o_funct,
775 ot -> ot_info = (caddr_t) functSub;
776 if (ot = text2obj ("functMul"))
777 ot -> ot_getfnx = o_funct,
778 ot -> ot_info = (caddr_t) functMul;
779 if (ot = text2obj ("functDiv"))
780 ot -> ot_getfnx = o_funct,
781 ot -> ot_info = (caddr_t) functDiv;
782 if (ot = text2obj ("functMod"))
783 ot -> ot_getfnx = o_funct,
784 ot -> ot_info = (caddr_t) functMod;
785 if (ot = text2obj ("functNeg"))
786 ot -> ot_getfnx = o_funct,
787 ot -> ot_info = (caddr_t) functNeg;
788 if (ot = text2obj ("functXch"))
789 ot -> ot_getfnx = o_funct,
790 ot -> ot_info = (caddr_t) functXch;
791 if (ot = text2obj ("functClr"))
792 ot -> ot_getfnx = o_funct,
793 ot -> ot_info = (caddr_t) functClr;
794 if (ot = text2obj ("functDup"))
795 ot -> ot_getfnx = o_funct,
796 ot -> ot_info = (caddr_t) functDup;
797 if (ot = text2obj ("functPop"))
798 ot -> ot_getfnx = o_funct,
799 ot -> ot_info = (caddr_t) functPop;
800 if (ot = text2obj ("functAbs"))
801 ot -> ot_getfnx = o_funct,
802 ot -> ot_info = (caddr_t) functAbs;
803 if (ot = text2obj ("functSgn"))
804 ot -> ot_getfnx = o_funct,
805 ot -> ot_info = (caddr_t) functSgn;
806 if (ot = text2obj ("functMin"))
807 ot -> ot_getfnx = o_funct,
808 ot -> ot_info = (caddr_t) functMin;
809 if (ot = text2obj ("functAnd"))
810 ot -> ot_getfnx = o_funct,
811 ot -> ot_info = (caddr_t) functAnd;
812 if (ot = text2obj ("functOr"))
813 ot -> ot_getfnx = o_funct,
814 ot -> ot_info = (caddr_t) functOr;
815 if (ot = text2obj ("functNot"))
816 ot -> ot_getfnx = o_funct,
817 ot -> ot_info = (caddr_t) functNot;
818
819 if (ot = text2obj ("exprNumber"))
820 ot -> ot_getfnx = o_generic,
821 ot -> ot_info = (caddr_t) &exprNumber;
822 if (ot = text2obj ("exprIndex"))
823 ot -> ot_getfnx = o_expressions,
824 ot -> ot_info = (caddr_t) exprIndex;
825 if (ot = text2obj ("exprEval"))
826 ot -> ot_getfnx = o_expressions,
827 ot -> ot_info = (caddr_t) exprEval;
828 if (ot = text2obj ("exprExpr"))
829 ot -> ot_getfnx = o_expressions,
830 ot -> ot_setfnx = s_expressions,
831 ot -> ot_info = (caddr_t) exprExpr;
832 if (ot = text2obj ("exprStatus"))
833 ot -> ot_getfnx = o_expressions,
834 ot -> ot_info = (caddr_t) exprStatus;
835 if (ot = text2obj ("exprHints"))
836 ot -> ot_getfnx = o_expressions,
837 ot -> ot_info = (caddr_t) exprHints;
838}
839
840/* \f */
841
842int f_expression (vec)
843char **vec;
844{
845 int i;
846 register char *cp;
847 register struct expr *e;
848 PE pe;
849 PS ps;
850
851 vec++;
852
853 if (sscanf (*vec, "%d", &i) != 1) {
854invalid: ;
855 advise (LLOG_EXCEPTIONS, NULLCP, "invalid expression index: %s", *vec);
856 return NOTOK;
857 }
858 if (i <= 0 || i > NEXPR)
859 goto invalid;
860 vec++;
861
862 e = exprs + i - 1;
863 if (e -> e_expr)
864 free (e -> e_expr), e -> e_expr = NULL;
865
866 if ((pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SEQ)) == NULL)
867 adios (NULLCP, "pe_alloc: out of memory");
868 while (cp = *vec++) {
869 OID oid;
870 PE p;
871
872 if (isdigit (*cp)) {
873 if (sscanf (cp, "%ld", &i) != 1) {
874 advise (LLOG_EXCEPTIONS, NULLCP, "bad integer-value: %s", cp);
875 return NOTOK;
876 }
877 p = num2prim ((integer) i, PE_CLASS_UNIV, PE_PRIM_INT);
878 }
879 else {
880 if ((oid = text2oid (cp)) == NULL) {
881 advise (LLOG_EXCEPTIONS, NULLCP, "unknown variable: %s", cp);
882 return NOTOK;
883 }
884 p = obj2prim (oid, PE_CLASS_UNIV, PE_PRIM_OID);
885 oid_free (oid);
886 }
887
888 if (seq_add (pe, p, NOTOK) == NOTOK)
889 adios (NULLCP, "seq_add: out of memory");
890 }
891
892 if ((ps = ps_alloc (str_open)) == NULLPS)
893 adios (NULLCP, "ps_alloc: failed");
894 if (str_setup (ps, NULLCP, BUFSIZ, 0) == NOTOK)
895 adios (NULLCP, "std_setup: %s", ps_error (ps -> ps_errno));
896 if (pe2ps (ps, pe) == NOTOK)
897 adios (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
898
899 e -> e_size = ps -> ps_ptr - (e -> e_expr = ps -> ps_base);
900
901 ps -> ps_base = NULL, ps -> ps_cnt = 0;
902 ps -> ps_ptr = NULL, ps -> ps_bufsiz = 0;
903
904 ps_free (ps);
905
906 if (debug)
907 vunknown (pe);
908 pe_free (pe);
909
910 if (i > exprNumber)
911 exprNumber = i;
912
913 return OK;
914}