Back to index

radiance  4R0+20100331
readobj.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: readobj.c,v 2.20 2010/03/30 12:42:33 greg Exp $";
00003 #endif
00004 /*
00005  *  readobj.c - routines for reading in object descriptions.
00006  *
00007  *  External symbols declared in object.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include  <ctype.h>
00013 #include  <string.h>
00014 #include  <stdio.h>
00015 
00016 #include  "platform.h"
00017 #include  "rtprocess.h"
00018 #include  "standard.h"
00019 #include  "object.h"
00020 #include  "otypes.h"
00021 
00022 
00023 OBJREC  *objblock[MAXOBJBLK];             /* our objects */
00024 OBJECT  nobjects = 0;                     /* # of objects */
00025 
00026 
00027 void
00028 readobj(inpspec)            /* read in an object file or stream */
00029 char  *inpspec;
00030 {
00031        OBJECT  lastobj;
00032        FILE  *infp;
00033        char  buf[2048];
00034        register int  c;
00035 
00036        lastobj = nobjects;
00037        if (inpspec == NULL) {
00038               infp = stdin;
00039               inpspec = "standard input";
00040        } else if (inpspec[0] == '!') {
00041               if ((infp = popen(inpspec+1, "r")) == NULL) {
00042                      sprintf(errmsg, "cannot execute \"%s\"", inpspec);
00043                      error(SYSTEM, errmsg);
00044               }
00045        } else if ((infp = fopen(inpspec, "r")) == NULL) {
00046               sprintf(errmsg, "cannot open scene file \"%s\"", inpspec);
00047               error(SYSTEM, errmsg);
00048        }
00049        while ((c = getc(infp)) != EOF) {
00050               if (isspace(c))
00051                      continue;
00052               if (c == '#') {                           /* comment */
00053                      fgets(buf, sizeof(buf), infp);
00054               } else if (c == '!') {                    /* command */
00055                      ungetc(c, infp);
00056                      fgetline(buf, sizeof(buf), infp);
00057                      readobj(buf);
00058               } else {                           /* object */
00059                      ungetc(c, infp);
00060                      getobject(inpspec, infp);
00061               }
00062        }
00063        if (inpspec[0] == '!')
00064               pclose(infp);
00065        else
00066               fclose(infp);
00067        if (nobjects == lastobj) {
00068               sprintf(errmsg, "(%s): empty file", inpspec);
00069               error(WARNING, errmsg);
00070        }
00071 }
00072 
00073 
00074 void
00075 getobject(name, fp)                /* read the next object */
00076 char  *name;
00077 FILE  *fp;
00078 {
00079 #define       OALIAS -2
00080        OBJECT  obj;
00081        char  sbuf[MAXSTR];
00082        int  rval;
00083        register OBJREC  *objp;
00084 
00085        if ((obj = newobject()) == OVOID)
00086               error(SYSTEM, "out of object space");
00087        objp = objptr(obj);
00088                                    /* get modifier */
00089        strcpy(sbuf, "EOF");
00090        fgetword(sbuf, MAXSTR, fp);
00091        if (strchr(sbuf, '\t')) {
00092               sprintf(errmsg, "(%s): illegal tab in modifier \"%s\"",
00093                                    name, sbuf);
00094               error(USER, errmsg);
00095        }
00096        if (!strcmp(sbuf, VOIDID))
00097               objp->omod = OVOID;
00098        else if (!strcmp(sbuf, ALIASMOD))
00099               objp->omod = OALIAS;
00100        else if ((objp->omod = modifier(sbuf)) == OVOID) {
00101               sprintf(errmsg, "(%s): undefined modifier \"%s\"", name, sbuf);
00102               error(USER, errmsg);
00103        }
00104                                    /* get type */
00105        strcpy(sbuf, "EOF");
00106        fgetword(sbuf, MAXSTR, fp);
00107        if ((objp->otype = otype(sbuf)) < 0) {
00108               sprintf(errmsg, "(%s): unknown type \"%s\"", name, sbuf);
00109               error(USER, errmsg);
00110        }
00111                                    /* get identifier */
00112        sbuf[0] = '\0';
00113        fgetword(sbuf, MAXSTR, fp);
00114        if (strchr(sbuf, '\t')) {
00115               sprintf(errmsg, "(%s): illegal tab in identifier \"%s\"",
00116                                    name, sbuf);
00117               error(USER, errmsg);
00118        }
00119        objp->oname = savqstr(sbuf);
00120                                    /* get arguments */
00121        if (objp->otype == MOD_ALIAS) {
00122               register OBJECT  alias;
00123               strcpy(sbuf, "EOF");
00124               fgetword(sbuf, MAXSTR, fp);
00125               if ((alias = modifier(sbuf)) == OVOID) {
00126                      sprintf(errmsg, "(%s): bad reference \"%s\"",
00127                                    name, sbuf);
00128                      objerror(objp, USER, errmsg);
00129               }
00130               if (objp->omod == OALIAS || 
00131                             objp->omod == objptr(alias)->omod) {
00132                      objp->omod = alias;
00133               } else {
00134                      objp->oargs.sarg = (char **)malloc(sizeof(char *));
00135                      if (objp->oargs.sarg == NULL)
00136                             error(SYSTEM, "out of memory in getobject");
00137                      objp->oargs.nsargs = 1;
00138                      objp->oargs.sarg[0] = savestr(sbuf);
00139               }
00140        } else if ((rval = readfargs(&objp->oargs, fp)) == 0) {
00141               sprintf(errmsg, "(%s): bad arguments", name);
00142               objerror(objp, USER, errmsg);
00143        } else if (rval < 0) {
00144               sprintf(errmsg, "(%s): error reading scene", name);
00145               error(SYSTEM, errmsg);
00146        }
00147        if (objp->omod == OALIAS) {
00148               sprintf(errmsg, "(%s): inappropriate use of '%s' modifier",
00149                             name, ALIASMOD);
00150               objerror(objp, USER, errmsg);
00151        }
00152                                    /* initialize */
00153        objp->os = NULL;
00154 
00155        insertobject(obj);          /* add to global structure */
00156 #undef OALIAS
00157 }
00158 
00159 
00160 OBJECT
00161 newobject()                        /* get a new object */
00162 {
00163        register int  i;
00164 
00165        if ((nobjects & (OBJBLKSIZ-1)) == 0) {    /* new block */
00166               errno = 0;
00167               i = nobjects >> OBJBLKSHFT;
00168               if (i >= MAXOBJBLK)
00169                      return(OVOID);
00170               objblock[i] = (OBJREC *)calloc(OBJBLKSIZ, sizeof(OBJREC));
00171               if (objblock[i] == NULL)
00172                      return(OVOID);
00173        }
00174        return(nobjects++);
00175 }
00176 
00177 void
00178 freeobjects(firstobj, nobjs)              /* free a range of objects */
00179 int  firstobj, nobjs;
00180 {
00181        register int  obj;
00182                                    /* check bounds */
00183        if (firstobj < 0)
00184               return;
00185        if (nobjs <= 0)
00186               return;
00187        if (firstobj + nobjs > nobjects)
00188               return;
00189                                    /* clear objects */
00190        for (obj = firstobj+nobjs; obj-- > firstobj; ) {
00191               register OBJREC  *o = objptr(obj);
00192               free_os(o);          /* free client memory */
00193               freeqstr(o->oname);
00194               freefargs(&o->oargs);
00195               memset((void *)o, '\0', sizeof(OBJREC));
00196        }
00197        clearobjndx();
00198                                    /* free objects off end */
00199        for (obj = nobjects; obj-- > 0; )
00200               if (objptr(obj)->oname != NULL)
00201                      break;
00202        ++obj;
00203        while (nobjects > obj)             /* free empty end blocks */
00204               if ((--nobjects & (OBJBLKSIZ-1)) == 0) {
00205                      int    i = nobjects >> OBJBLKSHFT;
00206                      free((void *)objblock[i]);
00207                      objblock[i] = NULL;
00208               }
00209 }