1 /* xlstruct.c - the defstruct facility */
2 /* Copyright (c) 1989, by David Michael Betz. */
3 /* You may give out copies of this software; for conditions see the file */
4 /* COPYING included with this distribution. */
8 /* forward declarations */
9 LOCAL VOID addslot
P5H(LVAL
, LVAL
, int, LVAL
*, LVAL
*);
10 LOCAL VOID updateslot
P3H(LVAL
, LVAL
, LVAL
);
13 static char prefix
[STRMAX
+1];
14 static char makestr
[] = "MAKE-%s";
16 /* xmkstruct - the '%make-struct' function */
22 /* get the structure type */
25 /* make the structure */
26 val
= newstruct(type
,xlargc
);
28 /* store each argument */
29 for (i
= 1; moreargs(); ++i
)
30 setelement(val
,i
,nextarg());
33 /* return the structure */
37 /* xcpystruct - the '%copy-struct' function */
45 val
= newstruct(getelement(str
,0),size
-1);
46 for (i
= 1; i
< size
; ++i
)
47 setelement(val
,i
,getelement(str
,i
));
51 /* xstrref - the '%struct-ref' function */
57 val
= xlgafixnum(); i
= (int)getfixnum(val
);
59 if (i
>= getsize(str
)) /* wrong structure TAA MOD fix*/
60 xlerror("bad structure reference",str
);
61 return (getelement(str
,i
));
64 /* xstrset - the '%struct-set' function */
70 val
= xlgafixnum(); i
= (int)getfixnum(val
);
73 if (i
>= getsize(str
)) /* wrong structure TAA MOD fix*/
74 xlerror("bad structure reference",str
);
75 setelement(str
,i
,val
);
79 /* xstrtypep - the '%struct-type-p' function */
87 for (val
= getelement(val
,0);
89 val
= xlgetprop(val
,s_strinclude
))
90 if (val
== type
) return(s_true
);
96 /* xdefstruct - the 'defstruct' special form */
99 LVAL structname
,slotname
,defexpr
,sym
,tmp
,args
,body
;
100 LVAL options
,oargs
,slots
,constrsym
,predsym
;
102 int slotn
, has_include
;
104 /* protect some pointers */
120 /* get the structure name */
124 pname
= getstring(getpname(structname
));
125 sprintf(prefix
, "%s-", pname
);
128 /* get the structure name and options */
129 else if (consp(tmp
) && symbolp(car(tmp
))) {
130 structname
= car(tmp
);
131 pname
= getstring(getpname(structname
));
132 sprintf(prefix
, "%s-", pname
);
134 /* handle the list of options */
135 for (options
= cdr(tmp
); consp(options
); options
= cdr(options
)) {
137 /* get the next argument */
140 /* handle options that don't take arguments */
142 xlerror("unknown option",tmp
);
145 /* handle options that take arguments */
146 else if (consp(tmp
) && symbolp(car(tmp
))) {
149 /* check for the :CONC-NAME keyword */
150 if (car(tmp
) == k_concname
) {
152 /* get the name of the structure to include */
153 if (!consp(oargs
) || !symbolp(car(oargs
)))
154 xlerror("expecting a symbol",oargs
);
156 /* save the prefix */
157 if (null(car(oargs
)))
160 STRCPY(prefix
,getstring(getpname(car(oargs
))));
163 /* check for the :INCLUDE keyword */
164 else if (car(tmp
) == k_include
) {
168 xlfail("only one :INCLUDE option allowed");
172 /* get the name of the structure to include */
173 if (!consp(oargs
) || !symbolp(car(oargs
)))
174 xlerror("expecting a structure name",oargs
);
175 parent
= tmp
= car(oargs
);
178 /* add each slot from the included structure */
179 slots
= xlgetprop(tmp
,s_sslots
);
180 for (; consp(slots
); slots
= cdr(slots
)) {
181 if (consp(car(slots
)) && consp(cdr(car(slots
)))) {
183 /* get the next slot description */
186 /* create the slot access functions */
187 addslot(car(tmp
),car(cdr(tmp
)),++slotn
,&args
,&body
);
191 /* handle slot initialization overrides */
192 for (; consp(oargs
); oargs
= cdr(oargs
)) {
198 else if (consp(tmp
) && symbolp(car(tmp
))) {
200 defexpr
= (consp(cdr(tmp
)) ? car(cdr(tmp
)) : NIL
);
203 xlerror("bad slot description",tmp
);
204 updateslot(args
,slotname
,defexpr
);
206 xlputprop(structname
,parent
,s_strinclude
);
208 /* check for :PRINT-FUNCTION option (Ken Whedbee) */
209 else if (car(tmp
) == k_prntfunc
) {
210 if (!consp(oargs
) || !symbolp(car(oargs
)))
211 xlerror("expecting a print function name",oargs
);
212 xlputprop(structname
,car(oargs
),s_prntfunc
);
214 else if (car(tmp
) == k_construct
) {
215 if (!consp(oargs
) || !symbolp(car(oargs
)))
216 xlerror("expecting a constructor function name",oargs
);
217 if (consp(cdr(oargs
)))
218 xlfail("BOA constructors not supported");
219 constrsym
= car(oargs
);
220 if (! symbolp(constrsym
)) xlbadtype(constrsym
);
221 xlputprop(structname
,constrsym
, s_strconstruct
);
223 else if (car(tmp
) == k_predicate
) {
224 if (!consp(oargs
) || !symbolp(car(oargs
)))
225 xlerror("expecting a predicate function name",oargs
);
226 predsym
= car(oargs
);
227 if (! symbolp(predsym
)) xlbadtype(predsym
);
230 xlerror("unknown option",tmp
);
233 xlerror("bad option syntax",tmp
);
237 /**** need to add documentation string */
238 /* flush documentation string */
239 if (moreargs() && stringp(*xlargv
)) (void)(nextarg());
241 /* get each of the structure members */
244 /* get the slot name and default value expression */
250 else if (consp(tmp
) && symbolp(car(tmp
))) {
252 defexpr
= (consp(cdr(tmp
)) ? car(cdr(tmp
)) : NIL
);
255 xlerror("bad slot description",tmp
);
257 /* create a closure for non-trivial default expressions */
258 if (defexpr
!= NIL
) {
259 tmp
= newclosure(NIL
,s_lambda
,xlenv
,xlfenv
);
260 setbody(tmp
,cons(defexpr
,NIL
));
265 /* create the slot access functions */
266 addslot(slotname
,defexpr
,++slotn
,&args
,&body
);
269 /* store the slotnames and default expressions */
270 xlputprop(structname
,args
,s_sslots
);
272 /* enter the MAKE-xxx symbol */
273 if (constrsym
== NULL
) {
274 sprintf(buf
, makestr
, pname
);
276 constrsym
= xlintern(buf
, getvalue(s_package
));
278 constrsym
= xlenter(buf
);
279 #endif /* PACKAGES */
280 xlputprop(structname
,constrsym
, s_strconstruct
);
283 /* make the MAKE-xxx function */
284 if (! null(constrsym
)) {
285 args
= cons(lk_key
,args
);
286 tmp
= cons(structname
,NIL
);
287 tmp
= cons(s_quote
,tmp
);
288 body
= cons(tmp
,body
);
289 body
= cons(s_mkstruct
,body
);
290 body
= cons(body
,NIL
);
291 setfunction(constrsym
,
292 xlclose(constrsym
,s_lambda
,args
,body
,xlenv
,xlfenv
));
295 /* enter the xxx-P symbol */
296 if (predsym
== NULL
) {
297 sprintf(buf
,"%s-P", pname
);
299 predsym
= xlintern(buf
, getvalue(s_package
));
301 predsym
= xlenter(buf
);
302 #endif /* PACKAGES */
305 /* make the xxx-P function */
306 if (! null(predsym
)) {
307 args
= cons(s_x
,NIL
);
308 body
= cons(s_x
,NIL
);
309 tmp
= cons(structname
,NIL
);
310 tmp
= cons(s_quote
,tmp
);
311 body
= cons(tmp
,body
);
312 body
= cons(s_strtypep
,body
);
313 body
= cons(body
,NIL
);
315 xlclose(predsym
,s_lambda
,args
,body
,NIL
,NIL
));
318 /* enter the COPY-xxx symbol */
319 sprintf(buf
,"COPY-%s", pname
);
321 sym
= xlintern(buf
, getvalue(s_package
));
324 #endif /* PACKAGES */
326 /* make the COPY-xxx function */
327 args
= cons(s_x
,NIL
);
328 body
= cons(s_x
,NIL
);
329 body
= cons(s_cpystruct
,body
);
330 body
= cons(body
,NIL
);
332 xlclose(sym
,s_lambda
,args
,body
,NIL
,NIL
));
334 /* restore the stack */
337 /* return the structure name */
341 /* xlrdstruct - convert a list to a structure (used by the reader) */
342 /* Modified by TAA to quote arguments and accept leading colons on keys */
343 LVAL xlrdstruct
P1C(LVAL
, list
)
345 LVAL structname
,slotname
,expr
,last
,val
;
347 /* protect the new structure */
350 /* get the structure name */
351 if (!consp(list
) || !symbolp(car(list
)))
352 xlerror("bad structure initialization list",list
);
353 structname
= car(list
);
356 /* initialize the constructor function call expression */
357 expr
= consa(xlgetprop(structname
, s_strconstruct
));
360 /* turn the rest of the initialization list into keyword arguments */
361 while (consp(list
) && consp(cdr(list
))) {
363 /* get the slot keyword name */
364 slotname
= car(list
);
365 if (!symbolp(slotname
))
366 xlerror("expecting a slot name",slotname
);
368 /* add the slot keyword */
370 rplacd(last
,consa(xlintern(getstring(getpname(slotname
)), xlkeypack
)));
372 if (*(getstring(getpname(slotname
))) != ':') { /* add colon */
373 sprintf(buf
,":%s",getstring(getpname(slotname
)));
374 rplacd(last
,cons(xlenter(buf
),NIL
));
377 rplacd(last
,cons(slotname
,NIL
));
379 #endif /* PACKAGES */
383 /* add the value expression -- QUOTED (TAA MOD) */
384 rplacd(last
,cons(NIL
,NIL
));
386 rplaca(last
, (slotname
= cons(s_quote
,NIL
)));
387 rplacd(slotname
, cons(car(list
), NIL
));
391 /* make sure all of the initializers were used */
393 xlerror("bad structure initialization list",list
);
395 /* invoke the creation function */
398 /* restore the stack */
401 /* return the new structure */
405 /* xlprstruct - print a structure (used by printer) */
406 VOID xlprstruct
P4C(LVAL
, fptr
, LVAL
, vptr
, FIXTYPE
, plevel
, int, flag
)
413 LVAL type
= getelement(vptr
,0);
414 next
= xlgetprop(type
, s_prntfunc
);
415 while (null(next
) && ! null(type
)) {
416 type
= xlgetprop(type
,s_strinclude
);
417 next
= xlgetprop(type
, s_prntfunc
);
420 if (!null(next
)) { /* Ken Whedbee addition */
422 pusharg(cvfixnum((FIXTYPE
)(newfp
- xlfp
)));
423 pusharg(symbolp(next
) ? xlgetfunction(next
) : next
);
424 pusharg(cvfixnum((FIXTYPE
) 3));
427 pusharg(cvfixnum(plevel
));
432 xlputstr(fptr
,"#S("); /* TAA MOD */
433 xlprint(fptr
,getelement(vptr
,0),flag
);
434 next
= xlgetprop(getelement(vptr
,0), s_sslots
);
435 for (i
= 1, n
= getsize(vptr
) - 1; i
<= n
&& consp(next
); ++i
) {
436 if (consp(car(next
))) { /* should always succeed */
437 xlputc(fptr
,' '); /* Alternate, could print " :" */
438 xlprint(fptr
,car(car(next
)),flag
);
440 xlprint(fptr
,getelement(vptr
,i
),flag
);
448 /* addslot - make the slot access functions */
449 LOCAL VOID addslot
P5C(LVAL
, slotname
, LVAL
, defexpr
, int, slotn
, LVAL
*, pargs
, LVAL
*, pbody
)
451 LVAL sym
,args
,body
,tmp
;
453 /* protect some pointers */
460 /* construct the update function name */
461 sprintf(buf
,"%s%s",prefix
,getstring(getpname(slotname
)));
463 sym
= xlintern(buf
, getvalue(s_package
));
466 #endif /* PACKAGES */
468 /* make the access function */
469 args
= cons(s_s
,NIL
);
470 body
= cons(cvfixnum((FIXTYPE
)slotn
),NIL
);
471 body
= cons(s_s
,body
);
472 body
= cons(s_strref
,body
);
473 body
= cons(body
,NIL
);
475 xlclose(sym
,s_lambda
,args
,body
,NIL
,NIL
));
477 /* make the update function */
478 args
= cons(s_x
,NIL
);
479 args
= cons(s_s
,args
);
480 body
= cons(s_x
,NIL
);
481 body
= cons(cvfixnum((FIXTYPE
)slotn
),body
);
482 body
= cons(s_s
,body
);
483 body
= cons(s_strset
,body
);
484 body
= cons(body
,NIL
);
486 xlclose(NIL
,s_lambda
,args
,body
,NIL
,NIL
),
489 /* add the slotname to the make-xxx keyword list */
490 tmp
= cons(defexpr
,NIL
);
491 tmp
= cons(slotname
,tmp
);
493 if ((args
= *pargs
) == NIL
)
496 while (consp(cdr(args
)))
501 /* add the slotname to the %make-xxx argument list */
502 tmp
= cons(slotname
,NIL
);
503 if ((body
= *pbody
) == NIL
)
506 while (consp(cdr(body
)))
511 /* restore the stack */
515 /* updateslot - update a slot definition */
516 LOCAL VOID updateslot
P3C(LVAL
, args
, LVAL
, slotname
, LVAL
, defexpr
)
519 for (; consp(args
); args
= cdr(args
))
520 if (slotname
== car(car(args
))) {
521 if (defexpr
!= NIL
) {
523 tmp
= newclosure(NIL
,s_lambda
,xlenv
,xlfenv
);
524 setbody(tmp
,cons(defexpr
,NIL
));
529 rplaca(cdr(car(args
)),defexpr
);
533 xlerror("unknown slot name",slotname
);