--- ray/src/common/readobj.c 2003/02/22 02:07:22 2.8
+++ ray/src/common/readobj.c 2025/06/24 21:04:16 2.31
@@ -1,5 +1,5 @@
#ifndef lint
-static const char RCSid[] = "$Id: readobj.c,v 2.8 2003/02/22 02:07:22 greg Exp $";
+static const char RCSid[] = "$Id: readobj.c,v 2.31 2025/06/24 21:04:16 greg Exp $";
#endif
/*
* readobj.c - routines for reading in object descriptions.
@@ -7,83 +7,32 @@ static const char RCSid[] = "$Id: readobj.c,v 2.8 2003
* External symbols declared in object.h
*/
-/* ====================================================================
- * The Radiance Software License, Version 1.0
- *
- * Copyright (c) 1990 - 2002 The Regents of the University of California,
- * through Lawrence Berkeley National Laboratory. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes Radiance software
- * (http://radsite.lbl.gov/)
- * developed by the Lawrence Berkeley National Laboratory
- * (http://www.lbl.gov/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
- * and "The Regents of the University of California" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact radiance@radsite.lbl.gov.
- *
- * 5. Products derived from this software may not be called "Radiance",
- * nor may "Radiance" appear in their name, without prior written
- * permission of Lawrence Berkeley National Laboratory.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of Lawrence Berkeley National Laboratory. For more
- * information on Lawrence Berkeley National Laboratory, please see
- * .
- */
+#include "copyright.h"
-#include "standard.h"
+#include
+#include "platform.h"
+#include "standard.h"
#include "object.h"
-
#include "otypes.h"
-#include
+#ifndef OBJMEMOPT
+#define OBJMEMOPT 0 /* optimize object block memory? */
+#endif
OBJREC *objblock[MAXOBJBLK]; /* our objects */
OBJECT nobjects = 0; /* # of objects */
void
-readobj(inpspec) /* read in an object file or stream */
-char *inpspec;
+readobj( /* read in an object file or stream */
+ char *inpspec
+)
{
OBJECT lastobj;
FILE *infp;
- char buf[1024];
- register int c;
+ char buf[2048];
+ int c;
lastobj = nobjects;
if (inpspec == NULL) {
@@ -98,6 +47,9 @@ char *inpspec;
sprintf(errmsg, "cannot open scene file \"%s\"", inpspec);
error(SYSTEM, errmsg);
}
+#ifdef getc_unlocked /* avoid stupid semaphores */
+ flockfile(infp);
+#endif
while ((c = getc(infp)) != EOF) {
if (isspace(c))
continue;
@@ -112,10 +64,17 @@ char *inpspec;
getobject(inpspec, infp);
}
}
- if (inpspec[0] == '!')
- pclose(infp);
- else
+ if (inpspec[0] == '!') {
+ if (pclose(infp) != 0) {
+ sprintf(errmsg, "bad status from \"%s\"", inpspec);
+ error(WARNING, errmsg);
+ }
+ } else if (infp != stdin)
fclose(infp);
+#ifdef getc_unlocked
+ else
+ funlockfile(infp);
+#endif
if (nobjects == lastobj) {
sprintf(errmsg, "(%s): empty file", inpspec);
error(WARNING, errmsg);
@@ -124,14 +83,16 @@ char *inpspec;
void
-getobject(name, fp) /* read the next object */
-char *name;
-FILE *fp;
+getobject( /* read the next object */
+ char *name,
+ FILE *fp
+)
{
+#define OALIAS -2
OBJECT obj;
char sbuf[MAXSTR];
int rval;
- register OBJREC *objp;
+ OBJREC *objp;
if ((obj = newobject()) == OVOID)
error(SYSTEM, "out of object space");
@@ -139,8 +100,15 @@ FILE *fp;
/* get modifier */
strcpy(sbuf, "EOF");
fgetword(sbuf, MAXSTR, fp);
+ if (strchr(sbuf, '\t')) {
+ sprintf(errmsg, "(%s): illegal tab in modifier \"%s\"",
+ name, sbuf);
+ error(USER, errmsg);
+ }
if (!strcmp(sbuf, VOIDID))
objp->omod = OVOID;
+ else if (!strcmp(sbuf, ALIASMOD))
+ objp->omod = OALIAS;
else if ((objp->omod = modifier(sbuf)) == OVOID) {
sprintf(errmsg, "(%s): undefined modifier \"%s\"", name, sbuf);
error(USER, errmsg);
@@ -148,29 +116,43 @@ FILE *fp;
/* get type */
strcpy(sbuf, "EOF");
fgetword(sbuf, MAXSTR, fp);
- if (!strcmp(sbuf, ALIASID))
- objp->otype = -1;
- else if ((objp->otype = otype(sbuf)) < 0) {
+ if ((objp->otype = otype(sbuf)) < 0) {
sprintf(errmsg, "(%s): unknown type \"%s\"", name, sbuf);
error(USER, errmsg);
}
/* get identifier */
sbuf[0] = '\0';
fgetword(sbuf, MAXSTR, fp);
+ if (strchr(sbuf, '\t')) {
+ sprintf(errmsg, "(%s): illegal tab in identifier \"%s\"",
+ name, sbuf);
+ error(USER, errmsg);
+ }
objp->oname = savqstr(sbuf);
/* get arguments */
- if (objp->otype == -1) {
- register OBJECT alias;
+ if (objp->otype == MOD_ALIAS) {
+ OBJECT ref;
+ OBJREC *rfp;
strcpy(sbuf, "EOF");
fgetword(sbuf, MAXSTR, fp);
- if ((alias = modifier(sbuf)) == OVOID) {
- sprintf(errmsg,
- "(%s): bad reference \"%s\" for %s \"%s\"",
- name, sbuf, ALIASID, objp->oname);
- error(USER, errmsg);
+ if ((ref = modifier(sbuf)) == OVOID) {
+ sprintf(errmsg, "(%s): bad reference \"%s\"",
+ name, sbuf);
+ objerror(objp, USER, errmsg);
+ } /* skip pass-thru aliases */
+ while ((rfp=objptr(ref))->otype == MOD_ALIAS &&
+ !rfp->oargs.nsargs & (rfp->omod != OVOID))
+ ref = rfp->omod;
+
+ if ((objp->omod == OALIAS) | (objp->omod == rfp->omod)) {
+ objp->omod = ref;
+ } else {
+ objp->oargs.sarg = (char **)malloc(sizeof(char *));
+ if (objp->oargs.sarg == NULL)
+ error(SYSTEM, "out of memory in getobject");
+ objp->oargs.nsargs = 1;
+ objp->oargs.sarg[0] = savestr(sbuf);
}
- objp->otype = objptr(alias)->otype;
- copystruct(&objp->oargs, &objptr(alias)->oargs);
} else if ((rval = readfargs(&objp->oargs, fp)) == 0) {
sprintf(errmsg, "(%s): bad arguments", name);
objerror(objp, USER, errmsg);
@@ -178,24 +160,122 @@ FILE *fp;
sprintf(errmsg, "(%s): error reading scene", name);
error(SYSTEM, errmsg);
}
+ if (objp->omod == OALIAS) {
+ sprintf(errmsg, "(%s): inappropriate use of '%s' modifier",
+ name, ALIASMOD);
+ objerror(objp, USER, errmsg);
+ }
/* initialize */
objp->os = NULL;
insertobject(obj); /* add to global structure */
+#undef OALIAS
}
-int
-newobject() /* get a new object */
+static void
+optimize_objblock(int i) /* consolidate memory in object block */
{
- register int i;
+#if OBJMEMOPT
+ OBJREC *o, *co;
+ int n = 0;
+ unsigned long sargcnt = 0, iargcnt = 0, fargcnt = 0, namecnt = 0;
+ if (i < 0 || objblock[i] == NULL || objblock[i][OBJBLKSIZ].otype < 0)
+ return; /* invalid or already done */
+
+ for (o = objblock[i]+OBJBLKSIZ; o-- > objblock[i]; ) {
+ if (o->oname == NULL) /* too early to optimize? */
+ return;
+ if (o->os != NULL) /* too late to optimize? */
+ return;
+ n += (o->oargs.nsargs > 0) | (o->oargs.nfargs > 0);
+ sargcnt += o->oargs.nsargs;
+ fargcnt += o->oargs.nfargs;
+#ifdef IARGS
+ iargcnt += o->oargs.niargs;
+#endif
+ namecnt += strlen(o->oname)+1;
+ }
+ if (n < OBJBLKSIZ/10) /* never happens? */
+ return;
+ /* prep consolidation object */
+ co = objblock[i]+OBJBLKSIZ;
+ co->oargs.nsargs = sargcnt;
+ co->oargs.nfargs = fargcnt;
+ if ((co->oargs.nsargs != sargcnt) | (co->oargs.nfargs != fargcnt))
+ return; /* overrun condition */
+
+ co->oname = (char *)malloc(sizeof(char)*namecnt);
+ co->oargs.sarg = (char **)malloc(sizeof(char *)*sargcnt);
+ co->oargs.farg = (RREAL *)malloc(sizeof(RREAL)*fargcnt);
+ if ((co->oname == NULL) | (co->oargs.sarg == NULL) |
+ (co->oargs.farg == NULL)) {
+ free(co->oname);
+ free(co->oargs.sarg); free(co->oargs.farg);
+ memset(co, 0, sizeof(OBJREC));
+ return; /* insufficient memory */
+ }
+#ifdef IARGS
+ co->oargs.niargs = iargcnt;
+ co->oargs.iarg = (long *)malloc(sizeof(long)*iargcnt);
+ if (co->oargs.iarg == NULL) {
+ free(co->oname);
+ free(co->oargs.sarg); free(co->oargs.farg);
+ memset(co, 0, sizeof(OBJREC));
+ return; /* insufficient memory */
+ }
+ iargcnt = 0;
+#endif
+ namecnt = sargcnt = fargcnt = 0;
+ for (o = objblock[i]+OBJBLKSIZ; o-- > objblock[i]; ) {
+ n = strlen(o->oname)+1;
+ memcpy(co->oname + namecnt, o->oname, n);
+ freeqstr(o->oname);
+ o->oname = co->oname + namecnt;
+ namecnt += n;
+ if (o->oargs.nsargs) {
+ memcpy(co->oargs.sarg+sargcnt, o->oargs.sarg,
+ sizeof(char *)*o->oargs.nsargs);
+ free(o->oargs.sarg);
+ o->oargs.sarg = co->oargs.sarg + sargcnt;
+ sargcnt += o->oargs.nsargs;
+ }
+ if (o->oargs.nfargs) {
+ memcpy(co->oargs.farg+fargcnt, o->oargs.farg,
+ sizeof(RREAL)*o->oargs.nfargs);
+ free(o->oargs.farg);
+ o->oargs.farg = co->oargs.farg + fargcnt;
+ fargcnt += o->oargs.nfargs;
+ }
+#ifdef IARGS
+ if (o->oargs.niargs) {
+ memcpy(co->oargs.iarg+iargcnt, o->oargs.iarg,
+ sizeof(long)*o->oargs.niargs);
+ free(o->oargs.iarg);
+ o->oargs.iarg = co->oargs.iarg + iargcnt;
+ iargcnt += o->oargs.niargs;
+ }
+#endif
+ }
+ co->otype = -1; /* flag for optimized block */
+#endif
+}
+
+
+OBJECT
+newobject(void) /* get a new object */
+{
+ int i;
+
if ((nobjects & (OBJBLKSIZ-1)) == 0) { /* new block */
- errno = 0;
i = nobjects >> OBJBLKSHFT;
+ optimize_objblock(i-1); /* optimize previous block */
+ errno = 0;
if (i >= MAXOBJBLK)
return(OVOID);
- objblock[i] = (OBJREC *)calloc(OBJBLKSIZ, sizeof(OBJREC));
+ objblock[i] = (OBJREC *)calloc(OBJBLKSIZ+OBJMEMOPT,
+ sizeof(OBJREC));
if (objblock[i] == NULL)
return(OVOID);
}
@@ -203,10 +283,12 @@ newobject() /* get a new object */
}
void
-freeobjects(firstobj, nobjs) /* free a range of objects */
-OBJECT firstobj, nobjs;
+freeobjects( /* free a range of objects */
+ int firstobj,
+ int nobjs
+)
{
- register int obj;
+ int obj;
/* check bounds */
if (firstobj < 0)
return;
@@ -216,22 +298,30 @@ OBJECT firstobj, nobjs;
return;
/* clear objects */
for (obj = firstobj+nobjs; obj-- > firstobj; ) {
- register OBJREC *o = objptr(obj);
+ OBJREC *o = objptr(obj);
free_os(o); /* free client memory */
- freeqstr(o->oname);
- freefargs(&o->oargs);
- bzero(o, sizeof(OBJREC));
+ if (!OBJMEMOPT || !objblock[obj>>OBJBLKSHFT][OBJBLKSIZ].otype) {
+ freeqstr(o->oname);
+ freefargs(&o->oargs);
+ }
+ memset(o, 0, sizeof(OBJREC));
}
- clearobjndx();
/* free objects off end */
for (obj = nobjects; obj-- > 0; )
if (objptr(obj)->oname != NULL)
break;
- ++obj;
+ if (++obj >= nobjects)
+ return;
while (nobjects > obj) /* free empty end blocks */
if ((--nobjects & (OBJBLKSIZ-1)) == 0) {
int i = nobjects >> OBJBLKSHFT;
- free((void *)objblock[i]);
+ /* consolidated block? */
+ if (OBJMEMOPT && objblock[i][OBJBLKSIZ].otype < 0) {
+ free(objblock[i][OBJBLKSIZ].oname);
+ freefargs(&objblock[i][OBJBLKSIZ].oargs);
+ }
+ free(objblock[i]);
objblock[i] = NULL;
}
+ truncobjndx(); /* truncate modifier look-up */
}