1 /* Low-level support for variables and properties in Xconq GDL.
2    Copyright (C) 1991-1996, 1998-2000 Stanley T. Shebs.
3 
4 Xconq is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.  See the file COPYING.  */
8 
9 #include "config.h"
10 #include "misc.h"
11 #include "lisp.h"
12 #include "game.h"
13 
14 /* The total number of unit/material/terrain/advance types. */
15 
16 short numutypes;
17 short nummtypes;
18 short numttypes;
19 short numatypes;
20 
21 /* These variables indicate whether new types can still be defined.
22    Once a table or list of types is manipulated, these are turned off. */
23 
24 short canaddutype = TRUE;
25 short canaddmtype = TRUE;
26 short canaddttype = TRUE;
27 short canaddatype = TRUE;
28 
29 /* This is the number of terrain types that can fill a cell. */
30 
31 int numcelltypes = 0;
32 
33 /* This is the number of terrain types that can be aux terrain. */
34 
35 int numauxttypes = 0;
36 
37 /* This is the number of terrain types that can be border terrain. */
38 
39 int numbordtypes = 0;
40 
41 /* This is the number of types that can be connections. */
42 
43 int numconntypes = 0;
44 
45 /* This is the number of types that can be coatings. */
46 
47 int numcoattypes = 0;
48 
49 /* This is an array listing all the aux types in order, typically used
50    to construct menus in interfaces. */
51 
52 short *aux_terrain_type_index;
53 
54 /* This is true if any terrain type has nonzero thickness. */
55 
56 int any_thickness;
57 
58 short first_auxt_type;
59 short *next_auxt_type = NULL;
60 short first_bord_type;
61 short *next_bord_type = NULL;
62 short first_conn_type;
63 short *next_conn_type = NULL;
64 
65 int *tmp_u_array;
66 int *tmp_u2_array;
67 int *tmp_t_array;
68 int *tmp_m_array;
69 int *tmp_a_array;
70 
71 int **tmp_uu_array;
72 
73 /* It would be useful for these to mention the slot or table access that
74    resulted in the error, but we don't want to have to pass a bunch of
75    parameters to these routines, since they're referenced a lot. */
76 
77 void
utype_error(int u)78 utype_error(int u)
79 {
80     run_warning("Bad utype %d", u);
81 }
82 
83 void
mtype_error(int m)84 mtype_error(int m)
85 {
86     run_warning("Bad mtype %d", m);
87 }
88 
89 void
ttype_error(int t)90 ttype_error(int t)
91 {
92     run_warning("Bad ttype %d", t);
93 }
94 
95 void
atype_error(int a)96 atype_error(int a)
97 {
98     run_warning("Bad atype %d", a);
99 }
100 
101 /* Declarations of the type definitions themselves. */
102 
103 Utype *utypes;
104 
105 Mtype *mtypes;
106 
107 Ttype *ttypes;
108 
109 Atype *atypes;
110 
111 Globals globals;
112 
113 /* These variables contain the current size of the type property
114    arrays.  The values are arbitrary, since create_unit_type and
115    friend will increase these if necessary; so we pick values that
116    are large enough for most game designs. */
117 
118 int curmaxutypes = 100;
119 
120 int curmaxmtypes = 20;
121 
122 int curmaxttypes = 40;
123 
124 int curmaxatypes = 200;
125 
126 /* This prepares the type definitions to be filled in, doing initial
127    allocations, etc. */
128 
129 void
init_types(void)130 init_types(void)
131 {
132     numutypes = nummtypes = numttypes = numatypes = 0;
133 
134     utypes = (Utype *) xmalloc(sizeof(Utype) * curmaxutypes);
135     mtypes = (Mtype *) xmalloc(sizeof(Mtype) * curmaxmtypes);
136     ttypes = (Ttype *) xmalloc(sizeof(Ttype) * curmaxttypes);
137     atypes = (Atype *) xmalloc(sizeof(Atype) * curmaxatypes);
138 }
139 
140 VarDefn vardefns[] = {
141 
142 #undef  DEF_VAR_I
143 #define DEF_VAR_I(NAME,FNAME,SETFNAME,DOC,var,LO,DFLT,HI)  \
144     { NAME, FNAME, NULL, NULL, SETFNAME, NULL, NULL, DOC, DFLT, NULL, NULL, LO, HI },
145 #undef  DEF_VAR_S
146 #define DEF_VAR_S(NAME,FNAME,SETFNAME,DOC,var,DFLT)  \
147     { NAME, NULL, FNAME, NULL, NULL, SETFNAME, NULL, DOC,    0, DFLT, NULL,  0,  0 },
148 #undef  DEF_VAR_L
149 #define DEF_VAR_L(NAME,FNAME,SETFNAME,DOC,var,DFLT)  \
150     { NAME, NULL, NULL, FNAME, NULL, NULL, SETFNAME, DOC,    0, NULL, DFLT,  0,  0 },
151 
152 #include "gvar.def"
153 
154     { NULL }
155 };
156 
157 /* Define all the global-getting and -setting functions. */
158 
159 #undef  DEF_VAR_I
160 #define DEF_VAR_I(str,FNAME,SETFNAME,doc,VAR,lo,dflt,hi)  \
161   int FNAME(void) { return globals.VAR; }  \
162   void SETFNAME(int v) { globals.VAR = v; }
163 #undef  DEF_VAR_S
164 #define DEF_VAR_S(str,FNAME,SETFNAME,doc,VAR,dflt)  \
165   char *FNAME(void) { return globals.VAR; }  \
166   void SETFNAME(char *v) { globals.VAR = v; }
167 #undef  DEF_VAR_L
168 #define DEF_VAR_L(str,FNAME,SETFNAME,doc,VAR,DFLT)  \
169   Obj *FNAME(void) { return globals.VAR; }  \
170   void SETFNAME(Obj *v) { globals.VAR = v; }
171 
172 #include "gvar.def"
173 
174 /* Set the globals to their default values.  For Lisp values, the default
175    is an initialization function rather than a value. */
176 
177 void
init_globals(void)178 init_globals(void)
179 {
180 #undef  DEF_VAR_I
181 #define DEF_VAR_I(str,fname,SETFNAME,doc,var,lo,DFLT,hi)  \
182     SETFNAME(DFLT);
183 #undef  DEF_VAR_S
184 #define DEF_VAR_S(str,fname,SETFNAME,doc,var,DFLT)  \
185     SETFNAME(DFLT);
186   /* The 0 had been NULL but this was changed along with calls in gvar.def
187   after compile warnings from g++ */
188 #undef  DEF_VAR_L
189 #define DEF_VAR_L(str,fname,SETFNAME,doc,var,DFLT)  \
190     if ((DFLT) != 0) {  \
191 	Obj *(*fn)(void) = (DFLT);  \
192 	if (fn != NULL) SETFNAME((*fn)());  \
193     } else { \
194 	SETFNAME(lispnil);  \
195     }
196 
197 #include "gvar.def"
198 
199 }
200 
201 /* Return the number of a new unit type, being careful to allocate
202    more space for unit properties if needed. */
203 
204 int
create_unit_type(void)205 create_unit_type(void)
206 {
207     int u, newmax;
208     Utype *newutypes;
209 
210     if (numutypes >= curmaxutypes) {
211 	/* Double in size.  This is reasonable because the type
212 	   structures are smallish, and don't need to grow very
213 	   often. */
214 	newmax = curmaxutypes * 2;
215 	/* This is similar to realloc, except that we need to be sure
216 	   that the new space is all zeros. */
217 	newutypes = (Utype *) xmalloc(newmax * sizeof(Utype));
218 	memcpy(newutypes, utypes, curmaxutypes * sizeof(Utype));
219 	free(utypes);
220 	utypes = newutypes;
221 	curmaxutypes = newmax;
222     }
223     u = numutypes++;
224     return u;
225 }
226 
227 /* Return the number of a new material type. */
228 
229 int
create_material_type(void)230 create_material_type(void)
231 {
232     int m, newmax;
233     Mtype *newmtypes;
234 
235     if (nummtypes >= curmaxmtypes) {
236 	newmax = curmaxmtypes * 2;
237 	newmtypes = (Mtype *) xmalloc(newmax * sizeof(Mtype));
238 	memcpy(newmtypes, mtypes, curmaxmtypes * sizeof(Mtype));
239 	free(mtypes);
240 	mtypes = newmtypes;
241 	curmaxmtypes = newmax;
242     }
243     m = nummtypes++;
244     return m;
245 }
246 
247 /* Return the number of a new terrain type. */
248 
249 int
create_terrain_type(void)250 create_terrain_type(void)
251 {
252     int t, newmax;
253     Ttype *newttypes;
254 
255     if (numttypes >= curmaxttypes) {
256 	newmax = curmaxttypes * 2;
257 	newttypes = (Ttype *) xmalloc(newmax * sizeof(Ttype));
258 	memcpy(newttypes, ttypes, curmaxttypes * sizeof(Ttype));
259 	free(ttypes);
260 	ttypes = newttypes;
261 	curmaxttypes = newmax;
262     }
263     t = numttypes++;
264     return t;
265 }
266 
267 /* Return the number of a new advance type. */
268 
269 int
create_advance_type(void)270 create_advance_type(void)
271 {
272     int a, newmax;
273     Atype *newatypes;
274 
275     if (numatypes >= curmaxatypes) {
276 	newmax = curmaxatypes * 2;
277 	newatypes = (Atype *) xmalloc(newmax * sizeof(Atype));
278 	memcpy(newatypes, atypes, curmaxatypes * sizeof(Atype));
279 	free(atypes);
280 	atypes = newatypes;
281 	curmaxatypes = newmax;
282     }
283     a = numatypes++;
284     return a;
285 }
286 
287 #define TYPEPROP(TYPES, N, DEFNS, I, TYPE)  \
288   ((TYPE *) &(((char *) (&(TYPES[N])))[DEFNS[I].offset]))[0]
289 
290 /* This sets all the defaults in a unit type definition.  Note that all
291    type structures get blasted with zeros initially, so we really only
292    need to do default settings of nonzero values, thus the test.  (It
293    helps if the compiler is smart enough to remove dead code.) */
294 
295 void
default_unit_type(int u)296 default_unit_type(int u)
297 {
298     int i;
299 
300     for (i = 0; utypedefns[i].name != NULL; ++i) {
301 	if (utypedefns[i].intgetter) {
302 	    if (utypedefns[i].dflt != 0)
303 	      TYPEPROP(utypes, u, utypedefns, i, short) = utypedefns[i].dflt;
304 	} else if (utypedefns[i].strgetter) {
305 	    if (utypedefns[i].dfltstr != NULL)
306 	      TYPEPROP(utypes, u, utypedefns, i, char *) =
307 		(char *) utypedefns[i].dfltstr;
308 	} else {
309 	    TYPEPROP(utypes, u, utypedefns, i, Obj *) = lispnil;
310 	}
311     }
312 }
313 
314 /* This sets all the defaults in a material type definition. */
315 
316 void
default_material_type(int m)317 default_material_type(int m)
318 {
319     int i;
320 
321     for (i = 0; mtypedefns[i].name != NULL; ++i) {
322 	if (mtypedefns[i].intgetter) {
323 	    if (mtypedefns[i].dflt != 0)
324 	      TYPEPROP(mtypes, m, mtypedefns, i, short) = mtypedefns[i].dflt;
325 	} else if (mtypedefns[i].strgetter) {
326 	    if (mtypedefns[i].dfltstr != NULL)
327 	      TYPEPROP(mtypes, m, mtypedefns, i, char *) = (char *) mtypedefns[i].dfltstr;
328 	} else {
329 	    TYPEPROP(mtypes, m, mtypedefns, i, Obj *) = lispnil;
330 	}
331     }
332 }
333 
334 /* This sets all the defaults in a terrain type definition. */
335 
336 void
default_terrain_type(int t)337 default_terrain_type(int t)
338 {
339     int i;
340 
341     for (i = 0; ttypedefns[i].name != NULL; ++i) {
342 	if (ttypedefns[i].intgetter) {
343 	    if (ttypedefns[i].dflt != 0)
344 	      TYPEPROP(ttypes, t, ttypedefns, i, short) = ttypedefns[i].dflt;
345 	} else if (ttypedefns[i].strgetter) {
346 	    if (ttypedefns[i].dfltstr != 0)
347 	      TYPEPROP(ttypes, t, ttypedefns, i, char *) = (char *) ttypedefns[i].dfltstr;
348 	} else {
349 	    TYPEPROP(ttypes, t, ttypedefns, i, Obj *) = lispnil;
350 	}
351     }
352 }
353 
354 /* This sets all the defaults in an advance type definition. */
355 
356 void
default_advance_type(int a)357 default_advance_type(int a)
358 {
359     int i;
360 
361     for (i = 0; atypedefns[i].name != NULL; ++i) {
362 	if (atypedefns[i].intgetter) {
363 	    if (atypedefns[i].dflt != 0)
364 	      TYPEPROP(atypes, a, atypedefns, i, short) = atypedefns[i].dflt;
365 	} else if (atypedefns[i].strgetter) {
366 	    if (atypedefns[i].dfltstr != 0)
367 	      TYPEPROP(atypes, a, atypedefns, i, char *) = (char *) atypedefns[i].dfltstr;
368 	} else {
369 	    TYPEPROP(atypes, a, atypedefns, i, Obj *) = lispnil;
370 	}
371     }
372 }
373 
374 char *
index_type_name(int x)375 index_type_name(int x)
376 {
377     return (char *)((x) == UTYP ? "unit"
378 	    : ((x) == MTYP ? "material"
379 	       : ((x) == TTYP ? "terrain"
380 		  : "advance")));
381 }
382 
383 /* This function allocates a parameter table and fills it with a default. */
384 
385 void
allocate_table(int tbl,int reset)386 allocate_table(int tbl, int reset)
387 {
388     int i, lim1, lim2, dflt = tabledefns[tbl].dflt;
389     short *rslt;
390 
391     if (reset) *(tabledefns[tbl].table) = NULL;
392     if (*tabledefns[tbl].table == NULL) {
393 	lim1 = numtypes_from_index_type(tabledefns[tbl].index1);
394 	lim2 = numtypes_from_index_type(tabledefns[tbl].index2);
395 	if (lim1 == 0) {
396 	    run_warning("Can't allocate the %s table, no %s types defined",
397 			tabledefns[tbl].name,
398 			index_type_name(tabledefns[tbl].index1));
399 	    return;
400 	}
401 	if (lim2 == 0) {
402 	    run_warning("Can't allocate the %s table, no %s types defined",
403 			tabledefns[tbl].name,
404 			index_type_name(tabledefns[tbl].index2));
405 	    return;
406 	}
407 	/* Allocate the table itself. */
408 	rslt = (short *) xmalloc(lim1 * lim2 * sizeof(short));
409 	/* Put the table's default everywhere in the table. */
410 	for (i = 0; i < lim1 * lim2; ++i) rslt[i] = dflt;
411 	*(tabledefns[tbl].table) = rslt;
412 	/* For each index, flag that no more types of that sort allowed. */
413 	switch (tabledefns[tbl].index1) {
414 	  case UTYP: disallow_more_unit_types();  break;
415 	  case MTYP: disallow_more_material_types();  break;
416 	  case TTYP: disallow_more_terrain_types();  break;
417 	  case ATYP: disallow_more_advance_types();  break;
418 	}
419 	switch (tabledefns[tbl].index2) {
420 	  case UTYP: disallow_more_unit_types();  break;
421 	  case MTYP: disallow_more_material_types();  break;
422 	  case TTYP: disallow_more_terrain_types();  break;
423 	  case ATYP: disallow_more_advance_types();  break;
424 	}
425     }
426 }
427 
428 int
numtypes_from_index_type(int x)429 numtypes_from_index_type(int x)
430 {
431     return ((x) == UTYP ? numutypes
432 	    : ((x) == MTYP ? nummtypes
433 	       : ((x) == TTYP ? numttypes
434 		  : numatypes)));
435 }
436 
437 void
disallow_more_unit_types(void)438 disallow_more_unit_types(void)
439 {
440     int u = NONUTYPE;
441 
442     canaddutype = FALSE;
443     if (tmp_u_array == NULL)
444       tmp_u_array = (int *) xmalloc(numutypes * sizeof(int));
445     if (!tmp_u2_array)
446       tmp_u2_array = (int *) xmalloc(numutypes * sizeof(int));
447     if (!tmp_uu_array) {
448 	tmp_uu_array = (int **) xmalloc(numutypes * sizeof(int *));
449 	for_all_unit_types(u)
450 	  tmp_uu_array[u] = (int *) xmalloc(numutypes * sizeof(int));
451     }
452 }
453 
454 void
disallow_more_terrain_types(void)455 disallow_more_terrain_types(void)
456 {
457     canaddttype = FALSE;
458     if (tmp_t_array == NULL)
459       tmp_t_array = (int *) xmalloc(numttypes * sizeof(int));
460     if (next_auxt_type == NULL)
461       next_auxt_type = (short *) xmalloc(numttypes * sizeof(short));
462     if (next_bord_type == NULL)
463       next_bord_type = (short *) xmalloc(numttypes * sizeof(short));
464     if (next_conn_type == NULL)
465       next_conn_type = (short *) xmalloc(numttypes * sizeof(short));
466     if (aux_terrain_type_index == NULL)
467       aux_terrain_type_index = (short *) xmalloc(numttypes * sizeof(short));
468     count_terrain_subtypes();
469 }
470 
471 /* Prevent more material types from being added, and prepare some integer
472    scratch space for doing math with materials types. */
473 
474 void
disallow_more_material_types(void)475 disallow_more_material_types(void)
476 {
477     canaddmtype = FALSE;
478     if (tmp_m_array == NULL)
479       tmp_m_array = (int *) xmalloc(nummtypes * sizeof(int));
480 }
481 
482 /* Prevent more advance types from being added, and prepare some integer
483    scratch space for doing math with advances types. */
484 
485 void
disallow_more_advance_types(void)486 disallow_more_advance_types(void)
487 {
488     canaddatype = FALSE;
489     if (tmp_a_array == NULL)
490       tmp_a_array = (int *) xmalloc(numatypes * sizeof(int));
491 }
492 
493 /* Calculate and cache some info about terrain types. */
494 
495 void
count_terrain_subtypes(void)496 count_terrain_subtypes(void)
497 {
498     int t, i = 0, preva = -1, prevb = -1, prevc = -1;
499 
500     /* Note that this function may be called several times. */
501     first_auxt_type = first_bord_type = first_conn_type = -1;
502 
503     numcelltypes = numbordtypes = numconntypes = numcoattypes = 0;
504     numauxttypes = 0;
505     any_thickness = FALSE;
506     for_all_terrain_types(t) {
507         switch (t_subtype(t)) {
508           case bordersubtype: case connectionsubtype: case coatingsubtype:
509             ++numauxttypes;
510             if (preva < 0) {
511                 first_auxt_type = t;
512             } else {
513                 next_auxt_type[preva] = t;
514             }
515             preva = t;
516 	    aux_terrain_type_index[i++] = t;
517             break;
518         }
519 	switch (t_subtype(t)) {
520 	  case cellsubtype:
521 	    ++numcelltypes;
522 	    break;
523 	  case bordersubtype:
524 	    ++numbordtypes;
525 	    if (prevb < 0) {
526 		first_bord_type = t;
527 	    } else {
528 		next_bord_type[prevb] = t;
529 	    }
530 	    prevb = t;
531 	    break;
532 	  case connectionsubtype:
533 	    ++numconntypes;
534 	    if (prevc < 0) {
535 		first_conn_type = t;
536 	    } else {
537 		next_conn_type[prevc] = t;
538 	    }
539 	    prevc = t;
540 	    break;
541 	  case coatingsubtype:
542 	    ++numcoattypes;
543 	    break;
544 	}
545 	if (t_thickness(t) > 0)
546 	  any_thickness = TRUE;
547     }
548     /* Mark the end of the links. */
549     if (preva >= 0)
550       next_auxt_type[preva] = -1;
551     if (prevb >= 0)
552       next_bord_type[prevb] = -1;
553     if (prevc >= 0)
554       next_conn_type[prevc] = -1;
555 }
556 
557 //! Default value for table.
558 
559 int
table_default(int (* getter)(int,int))560 table_default(int (*getter)(int, int))
561 {
562     int i = 0;
563 
564     for (i = 0; tabledefns[i].name != NULL; ++i) {
565         if (tabledefns[i].getter == getter)
566           return tabledefns[i].dflt;
567     }
568     assert_error((tabledefns[i].name != NULL),
569                  "Invalid table lookup attempted!");
570     return 0;
571 }
572 
573 //! Default value for integer uprop.
574 
575 short
uprop_i_default(int (* intgetter)(int))576 uprop_i_default(int (*intgetter)(int))
577 {
578     int i = 0;
579 
580     for (i = 0; utypedefns[i].name != NULL; ++i) {
581         if (utypedefns[i].intgetter == intgetter)
582           return utypedefns[i].dflt;
583     }
584     assert_error((utypedefns[i].name != NULL),
585                  "Invalid unit property lookup attempted!");
586     return 0;
587 }
588 
589 //! Default value for string uprop.
590 
591 char *
uprop_s_default(char * (* strgetter)(int))592 uprop_s_default(char *(*strgetter)(int))
593 {
594     int i = 0;
595 
596     for (i = 0; utypedefns[i].name != NULL; ++i) {
597         if (utypedefns[i].strgetter == strgetter)
598           return utypedefns[i].dfltstr;
599     }
600     assert_error((utypedefns[i].name != NULL),
601                  "Invalid unit property lookup attempted!");
602     return NULL;
603 }
604 
605 //! Default value for Lisp uprop.
606 
607 Obj *
uprop_l_default(Obj * (* objgetter)(int))608 uprop_l_default(Obj *(*objgetter)(int))
609 {
610     return lispnil;
611 }
612 
613 //! Default value for integer tprop.
614 
615 short
tprop_i_default(int (* intgetter)(int))616 tprop_i_default(int (*intgetter)(int))
617 {
618     int i = 0;
619 
620     for (i = 0; ttypedefns[i].name != NULL; ++i) {
621         if (ttypedefns[i].intgetter == intgetter)
622           return ttypedefns[i].dflt;
623     }
624     assert_error((ttypedefns[i].name != NULL),
625                  "Invalid terrain property lookup attempted!");
626     return 0;
627 }
628 
629 //! Default value for string tprop.
630 
631 char *
tprop_s_default(char * (* strgetter)(int))632 tprop_s_default(char *(*strgetter)(int))
633 {
634     int i = 0;
635 
636     for (i = 0; ttypedefns[i].name != NULL; ++i) {
637         if (ttypedefns[i].strgetter == strgetter)
638           return ttypedefns[i].dfltstr;
639     }
640     assert_error((ttypedefns[i].name != NULL),
641                  "Invalid terrain property lookup attempted!");
642     return 0;
643 }
644 
645 //! Default value for Lisp tprop.
646 
647 Obj *
tprop_l_default(Obj * (* objgetter)(int))648 tprop_l_default(Obj *(*objgetter)(int))
649 {
650     return lispnil;
651 }
652 
653 //! Default value for integer mprop.
654 
655 short
mprop_i_default(int (* intgetter)(int))656 mprop_i_default(int (*intgetter)(int))
657 {
658     int i = 0;
659 
660     for (i = 0; mtypedefns[i].name != NULL; ++i) {
661         if (mtypedefns[i].intgetter == intgetter)
662           return mtypedefns[i].dflt;
663     }
664     assert_error((mtypedefns[i].name != NULL),
665                  "Invalid material property lookup attempted!");
666     return 0;
667 }
668 
669 //! Default value for string mprop.
670 
671 char *
mprop_s_default(char * (* strgetter)(int))672 mprop_s_default(char *(*strgetter)(int))
673 {
674     int i = 0;
675 
676     for (i = 0; mtypedefns[i].name != NULL; ++i) {
677         if (mtypedefns[i].strgetter == strgetter)
678           return mtypedefns[i].dfltstr;
679     }
680     assert_error((mtypedefns[i].name != NULL),
681                  "Invalid material property lookup attempted!");
682     return 0;
683 }
684 
685 //! Default value for Lisp mprop.
686 
687 Obj *
mprop_l_default(Obj * (* objgetter)(int))688 mprop_l_default(Obj *(*objgetter)(int))
689 {
690     return lispnil;
691 }
692 
693 //! Default value for integer aprop.
694 
695 short
aprop_i_default(int (* intgetter)(int))696 aprop_i_default(int (*intgetter)(int))
697 {
698     int i = 0;
699 
700     for (i = 0; atypedefns[i].name != NULL; ++i) {
701         if (atypedefns[i].intgetter == intgetter)
702           return atypedefns[i].dflt;
703     }
704     assert_error((atypedefns[i].name != NULL),
705                  "Invalid advance property lookup attempted!");
706     return 0;
707 }
708 
709 //! Default value for string aprop.
710 
711 char *
aprop_s_default(char * (* strgetter)(int))712 aprop_s_default(char *(*strgetter)(int))
713 {
714     int i = 0;
715 
716     for (i = 0; atypedefns[i].name != NULL; ++i) {
717         if (atypedefns[i].strgetter == strgetter)
718           return atypedefns[i].dfltstr;
719     }
720     assert_error((atypedefns[i].name != NULL),
721                  "Invalid advance property lookup attempted!");
722     return 0;
723 }
724 
725 //! Default value for Lisp aprop.
726 
727 Obj *
aprop_l_default(Obj * (* objgetter)(int))728 aprop_l_default(Obj *(*objgetter)(int))
729 {
730     return lispnil;
731 }
732 
733 //! Default value for integer gvar.
734 
735 int
gvar_i_default(int (* intgetter)(void))736 gvar_i_default(int (*intgetter)(void))
737 {
738     int i = 0;
739 
740     for (i = 0; vardefns[i].name != NULL; ++i) {
741         if (vardefns[i].intgetter == intgetter)
742           return vardefns[i].dflt;
743     }
744     assert_error((vardefns[i].name != NULL),
745                  "Invalid global variable lookup attempted!");
746     return 0;
747 }
748 
749 //! Default value for string gvar.
750 
751 char *
gvar_s_default(char * (* strgetter)(void))752 gvar_s_default(char *(*strgetter)(void))
753 {
754     int i = 0;
755 
756     for (i = 0; vardefns[i].name != NULL; ++i) {
757         if (vardefns[i].strgetter == strgetter)
758           return vardefns[i].dfltstr;
759     }
760     assert_error((vardefns[i].name != NULL),
761                  "Invalid global variable lookup attempted!");
762     return NULL;
763 }
764 
765 //! Default value for Lisp gvar.
766 
767 Obj *
gvar_l_default(Obj * (* objgetter)(void))768 gvar_l_default(Obj *(*objgetter)(void))
769 {
770     int i = 0;
771 
772     for (i = 0; vardefns[i].name != NULL; ++i) {
773         if (vardefns[i].objgetter == objgetter)
774           return (*(vardefns[i].dfltfn))();
775     }
776     assert_error((vardefns[i].name != NULL),
777                  "Invalid global variable lookup attempted!");
778     return NULL;
779 }
780