Back to index

radiance  4R0+20100331
segment.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: segment.c,v 1.2 2003/11/15 02:13:37 schorsch Exp $";
00003 #endif
00004 /*
00005  *   Routines for segment storage and inclusion for meta-files
00006  *
00007  *   12/18/84
00008  */
00009 
00010 #include <string.h>
00011 
00012 #include  "rtio.h"
00013 #include  "meta.h"
00014 
00015 
00016 #define  NODEC  0           /* null declaration (must be 0) */
00017 
00018 #define  MAXDEC  2048              /* maximum number of declarations */
00019 
00020 #define  NHASH  101         /* hash size (prime) */
00021 
00022 
00023 static struct declaration {
00024                   char      *sname;              /* segment name */
00025                   PLIST     sprims;              /* segment primitives */
00026                   int              context;      /* declaration containing us */
00027                   int              nexthash;     /* next in hash list */
00028               } dectabl[MAXDEC];
00029 
00030 static int    hashtabl[NHASH];
00031 
00032 static int    dectop = 0;          /* top of declaration table */
00033 
00034 static int    curdec = NODEC;             /* current declaration */
00035 
00036 
00037 static int hash(register char      *s);
00038 static int lookup(register char    *name);
00039 
00040 
00041 
00042 static int
00043 hash(                /* hash a string */
00044        register char *s
00045 )
00046 
00047 {
00048     register int     hval = 0;
00049 
00050     while (*s)
00051        hval += *s++;
00052 
00053     return(hval % NHASH);
00054 }
00055 
00056 
00057 
00058 
00059 
00060 static int
00061 lookup(              /* find name in declaration table */
00062        register char *name
00063 )
00064 
00065 {
00066     register int     curd;
00067 
00068     if (name == NULL)
00069        error(USER, "illegal null segment name in lookup");
00070 
00071     for (curd = hashtabl[hash(name)]; curd != NODEC; curd = dectabl[curd].nexthash)
00072        if (strcmp(name, dectabl[curd].sname) == 0)
00073            break;
00074 
00075     return(curd);
00076 }
00077 
00078 
00079 
00080 int
00081 inseg(void)                 /* return TRUE if currently in a segment */
00082 
00083 {
00084 
00085     return(curdec != NODEC);
00086 }
00087 
00088 
00089 
00090 void
00091 openseg(                    /* open a new segment */
00092        char   *name
00093 )
00094 
00095 {
00096     register int  olddec;
00097 
00098     if ((olddec = lookup(name)) != NODEC &&
00099               dectabl[olddec].context == curdec) /* redefined segment */
00100         plfree(&dectabl[olddec].sprims);
00101 
00102     if (++dectop >= MAXDEC)
00103        error(SYSTEM, "too many segments in openseg");
00104 
00105     dectabl[dectop].sname = savestr(name);
00106                             /* save previous context */
00107     dectabl[dectop].context = curdec;
00108     curdec = dectop;
00109     
00110 }
00111 
00112 
00113 
00114 
00115 void
00116 segprim(             /* store primitive in current segment */
00117        register PRIMITIVE  *p
00118 )
00119 
00120 {
00121     register PRIMITIVE  *newp;
00122 
00123     if (!inseg())
00124         error(SYSTEM, "illegal call to segprim");
00125 
00126     switch (p->com) {
00127 
00128        case POPEN:
00129            openseg(p->args);
00130            break;
00131            
00132        case PSEG:
00133            segment(p, segprim);
00134            break;
00135 
00136        case PCLOSE:
00137            closeseg();
00138            break;
00139 
00140        default:
00141            if ((newp = palloc()) == NULL)
00142               error(SYSTEM, "memory limit exceeded in segprim");
00143            mcopy((char *)newp, (char *)p, sizeof(PRIMITIVE));
00144            newp->args = savestr(p->args);
00145            add(newp, &dectabl[curdec].sprims);
00146            break;
00147     }
00148 
00149 }
00150 
00151 
00152 void
00153 closeseg(void)              /* close the current segment */
00154 
00155 {
00156     register int  i;
00157     
00158     if (!inseg())
00159         error(SYSTEM, "illegal call to closeseg");
00160         
00161                             /* undefine internal declarations */
00162     for (i = dectop; i > curdec; i--) {
00163        hashtabl[hash(dectabl[i].sname)] = dectabl[i].nexthash;
00164        freestr(dectabl[i].sname);
00165        plfree(&dectabl[i].sprims);
00166     }
00167     dectop = curdec;
00168                             /* define this declaration */
00169     i = hash(dectabl[curdec].sname);
00170     dectabl[curdec].nexthash = hashtabl[i];
00171     hashtabl[i] = curdec;
00172                             /* return context */
00173     curdec = dectabl[curdec].context;
00174 }
00175 
00176 
00177 
00178 void
00179 segment(                    /* expand segment p */
00180        PRIMITIVE     *p,
00181        void   (*funcp)(PRIMITIVE *p)
00182 )
00183 
00184 {
00185     int              decln;
00186     PRIMITIVE curp;
00187     register PRIMITIVE      *sp;
00188 
00189     if ((decln = lookup(p->args)) == NODEC)  {
00190        sprintf(errmsg, "reference to undefined segment \"%s\" in segment",
00191                                           p->args);
00192        error(USER, errmsg);
00193     }
00194 
00195     for (sp = dectabl[decln].sprims.ptop; sp != NULL; sp = sp->pnext)
00196 
00197        if (isglob(sp->com))
00198 
00199            (*funcp)(sp);
00200 
00201        else {
00202 
00203            switch (curp.com = sp->com) {
00204 
00205               case PSEG:
00206               case PVSTR:
00207               case PTFILL:
00208               case PPFILL:
00209                   curp.arg0 = (sp->arg0 & 0100) |
00210                             (((sp->arg0 & 060) + p->arg0) & 060);
00211                   break;
00212 
00213               case PLSEG:
00214                   if (p->arg0 & 020)
00215                      curp.arg0 = (~sp->arg0 & 0100) | (sp->arg0 & 060);
00216                   else
00217                      curp.arg0 = sp->arg0 & 0160;
00218                   break;
00219 
00220               default:
00221                   curp.arg0 = sp->arg0 & 0160;
00222                   break;
00223            }
00224            if (p->arg0 & 014)
00225               curp.arg0 |= p->arg0 & 014;
00226            else
00227               curp.arg0 |= sp->arg0 & 014;
00228            if (p->arg0 & 03)
00229               curp.arg0 |= p->arg0 & 03;
00230            else
00231               curp.arg0 |= sp->arg0 & 03;
00232 
00233            curp.xy[XMN] = xlate(XMN, sp, p);
00234            curp.xy[YMN] = xlate(YMN, sp, p);
00235            curp.xy[XMX] = xlate(XMX, sp, p);
00236            curp.xy[YMX] = xlate(YMX, sp, p);
00237            curp.args = sp->args;
00238 
00239             (*funcp)(&curp);
00240        }
00241 
00242 }
00243 
00244 
00245 
00246 
00247 
00248 int
00249 xlate(        /* return extrema from p through px */
00250        short                extrema,
00251        PRIMITIVE            *p,
00252        register PRIMITIVE   *px
00253 )
00254 
00255 {
00256     short     oldex;
00257     int              val;
00258 
00259     if (((oldex = (extrema + 4 - ((px->arg0 >> 4) & 03))%4) ^ extrema) & 02)
00260        val = (XYSIZE-1) - p->xy[oldex];
00261     else
00262        val = p->xy[oldex];
00263     
00264     if (extrema & 01)
00265        return(CONV(val, px->xy[YMX] - px->xy[YMN]) + px->xy[YMN]);
00266     else
00267        return(CONV(val, px->xy[XMX] - px->xy[XMN]) + px->xy[XMN]);
00268 }