1 /*
2 entity.c -- Miscellaneous routines for entities.
3
4 Copyright (C) 1994-2002 K. Scott Hunziker.
5 Copyright (C) 1990-1994 The Boeing Company.
6
7 See the file COPYING for license, warranty, and permission details.
8 */
9
10 static char rcsid[] =
11 "$Id: entity.c,v 1.5 2002/07/30 22:05:17 ksh Exp $";
12
13 #include "entity.h"
14 #include "scalar.h"
15 #include "vector.h"
16 #include "matrix.h"
17 #include "table.h"
18 #include "function.h"
19 #include "cast.h"
20
21 #define ENUM_STRNG_INIT 1
22 #include "enum_strng.h"
23
24 /*
25 * When debugging, a message is printed if the number of references
26 * to an entity exceeds DB_REF_THRESHOLD.
27 */
28
29 #ifndef DB_REF_THRESHOLD
30 #define DB_REF_THRESHOLD 1000
31 #endif
32
33 char NULL_string[1] = ""; /* Most NULL strings point here. */
34
35 void *
eat(p)36 eat (p)
37 void **p;
38 {
39 void *e;
40
41 e = *p;
42 *p = NULL;
43 return (e);
44 }
45
46 ENTITY *
DB_copy_entity(p,file,line)47 DB_copy_entity (p, file, line)
48 ENTITY *p;
49 char *file;
50 int line;
51 {
52 EASSERT (p, 0, 0);
53
54 if (++p->ref_count >= DB_REF_THRESHOLD || debug_level > 1)
55 inform ("%s \"ref_count\" increment: %x, %d, %s, %d.",
56 class_string[p->class], p, p->ref_count, file, line);
57
58 return (p);
59 }
60
61 void
DB_delete_entity(p,file,line)62 DB_delete_entity (p, file, line)
63 ENTITY *p;
64 char *file;
65 int line;
66 {
67 /*
68 * This is the DEBUG version of `delete_entity'. It decrements
69 * the entity's reference count, and frees it if it is unreferenced.
70 */
71
72 if (p)
73 {
74
75 if (--p->ref_count < 0)
76 {
77 wipeout ("A %s's \"ref_count\" went below zero: %s, %d.",
78 class_string[p->class], file, line);
79 }
80
81 if (p->ref_count >= DB_REF_THRESHOLD || debug_level > 1)
82 {
83 inform ("%s \"ref_count\" decrement: %x, %d, %s, %d.",
84 class_string[p->class], p, p->ref_count, file, line);
85 }
86
87 if (p->ref_count == 0)
88 free_entity (p);
89
90 }
91 }
92
93 void
free_entity(p)94 free_entity (p)
95 ENTITY *p;
96 {
97 assert (p != NULL);
98 assert (p->ref_count == 0);
99
100 switch (p->class)
101 {
102 case scalar:
103 free_scalar ((SCALAR *) p);
104 break;
105 case vector:
106 free_vector ((VECTOR *) p);
107 break;
108 case matrix:
109 free_matrix ((MATRIX *) p);
110 break;
111 case table:
112 free_table ((TABLE *) p);
113 break;
114 case function:
115 free_function ((FUNCTION *) p);
116 break;
117 default:
118 BAD_CLASS (p->class);
119 delete_entity (p);
120 raise_exception ();
121 }
122 }
123
124 ENTITY *
dup_entity(p)125 dup_entity (p)
126 ENTITY *p;
127 {
128 EASSERT (p, 0, 0);
129
130 switch (p->class)
131 {
132 case scalar:
133 return (dup_scalar ((SCALAR *) p));
134 case vector:
135 return (dup_vector ((VECTOR *) p));
136 case matrix:
137 return (dup_matrix ((MATRIX *) p));
138 case table:
139 return (dup_table ((TABLE *) p));
140 case function:
141 return (dup_function ((FUNCTION *) p));
142 default:
143 BAD_CLASS (p->class);
144 delete_entity (p);
145 raise_exception ();
146 }
147 }
148
149 char *
dup_char(p)150 dup_char (p)
151 char *p;
152 {
153 assert (p != NULL);
154
155 if (*p == '\0')
156 return (NULL_string);
157
158 return (strcpy (MALLOC (strlen (p) + 1), p));
159 }
160
161 char *
append_char(l,r)162 append_char (l, r)
163 char *l;
164 char *r;
165 {
166 char *p;
167
168 assert (l != NULL && r != NULL);
169 p = MALLOC (strlen (l) + strlen (r) + 1);
170 return (strcat (strcpy (p, l), r));
171 }
172
173 void *
dup_mem(p,len)174 dup_mem (p, len)
175 void *p;
176 int len;
177 {
178 assert (p != NULL);
179
180 return (memcpy (MALLOC (len), p, len));
181 }
182
183 ENTITY *
not_NULL(p)184 not_NULL (p)
185 ENTITY *p;
186 {
187 if (p == NULL)
188 raise_exception ();
189 return (p);
190 }
191
192 int
member_cmp(keyval,dat)193 member_cmp (keyval, dat)
194 const void *keyval;
195 const void *dat;
196 {
197 return (strcmp ((char *) keyval, ((MEMBER_ID *) dat)->name));
198 }
199
200 ENTITY *
bi_class(n,p)201 bi_class (n, p)
202 int n;
203 ENTITY *p;
204 {
205 char *c;
206
207 if (p)
208 {
209 c = class_string[p->class];
210 delete_entity (p);
211 }
212 else
213 {
214 c = "NULL";
215 }
216
217 return char_to_scalar (dup_char (c));
218 }
219
220 char *
th(i)221 th (i)
222 int i;
223 {
224 if (i < 0)
225 {
226 return ("");
227 }
228 else if (i > 3 && i < 21)
229 {
230 return ("th");
231 }
232 else
233 {
234 switch (i % 10)
235 {
236 case 1:
237 return ("st");
238 case 2:
239 return ("nd");
240 case 3:
241 return ("rd");
242 default:
243 return ("th");
244 }
245 }
246 }
247
248 int
entity_to_int(e)249 entity_to_int (e)
250 ENTITY *e;
251 {
252 /* Convert an entity to an integer */
253
254 int i;
255
256 e = cast_scalar ((SCALAR *) scalar_entity (e), integer);
257 i = ((SCALAR *) e)->v.integer;
258
259 delete_scalar ((SCALAR *) e);
260 return (i);
261 }
262
263 REAL
entity_to_real(e)264 entity_to_real (e)
265 ENTITY *e;
266 {
267 /* Convert an entity to a real. */
268
269 REAL r;
270
271 e = cast_scalar ((SCALAR *) scalar_entity (e), real);
272 r = ((SCALAR *) e)->v.real;
273
274 delete_scalar ((SCALAR *) e);
275 return r;
276 }
277
278 COMPLEX
entity_to_complex(e)279 entity_to_complex (e)
280 ENTITY *e;
281 {
282 /* Convert an entity to a complex. */
283
284 COMPLEX r;
285
286 e = cast_scalar ((SCALAR *) scalar_entity (e), complex);
287 r.real = ((SCALAR *) e)->v.complex.real;
288 r.imag = ((SCALAR *) e)->v.complex.imag;
289
290 delete_scalar ((SCALAR *) e);
291 return r;
292 }
293
294 char *
entity_to_string(e)295 entity_to_string (e)
296 ENTITY *e;
297 {
298 /* Convert an entity to a character string. */
299
300 char *s;
301
302 e = cast_scalar ((SCALAR *) scalar_entity (e), character);
303
304 /*
305 * We'll try to take a little shortcut here. If the ref_count
306 * is 1, we'll just steal the entity's copy of the string
307 * instead of malloc'ing another.
308 */
309
310 if (e->ref_count == 1)
311 {
312 s = ((SCALAR *) e)->v.character;
313 ((SCALAR *) e)->v.character = NULL_string;
314 }
315 else
316 {
317 s = dup_char (((SCALAR *) e)->v.character);
318 }
319
320 delete_scalar ((SCALAR *) e);
321 return (s);
322 }
323
324 void *
memmove_forward(s,t,n)325 memmove_forward (s, t, n)
326 void *s;
327 void *t;
328 size_t n;
329 {
330 /*
331 * Copy `n' characters from `t' to `s', and return `s'. This
332 * works if `t' and `s' overlap, provided that s>=t.
333 */
334
335 assert (s && t && n > 0);
336
337 while (n--)
338 ((char *) s)[n] = ((char *) t)[n];
339
340 return (s);
341 }
342