Back to index

radiance  4R0+20100331
trans.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: trans.c,v 2.5 2003/11/15 17:54:06 schorsch Exp $";
00003 #endif
00004 /*
00005  * Translator utilities
00006  *
00007  *     Greg Ward
00008  */
00009 
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 
00014 #include "rterror.h"
00015 #include "trans.h"
00016 
00017 static int idcmp(ID *id1, ID *id2);
00018 static void fputidlist(IDLIST *qp, FILE *fp);
00019 static int qtype(char *qnm, register QLIST *qlp);
00020 
00021 extern int
00022 fgetid(              /* read an id up to char in dls from fp */
00023        ID     *idp,
00024        char   *dls,
00025        register FILE *fp
00026 )
00027 {
00028        char   dset[256/8];
00029        char   buf[MAXSTR];
00030        register int  c;
00031        register char *cp;
00032                                    /* create delimiter set */
00033        for (cp = dset+sizeof(dset); cp-- > dset; )
00034               *cp = 0;
00035        for (cp = dls; *cp; cp++)
00036               dset[*cp>>3] |= 1<<(*cp&7);
00037                                    /* get characters up to delimiter */
00038        cp = buf;
00039        while ((c = getc(fp)) != EOF && !(dset[c>>3] & 1<<(c&7)))
00040               *cp++ = c;
00041                                    /* check for empty */
00042        if (cp == buf) {
00043               if (c == EOF)
00044                      return(EOF);
00045               idp->number = 0;
00046               idp->name = NULL;
00047               return(0);
00048        }
00049                                    /* truncate space at end */
00050        while (cp[-1] == ' ' || cp[-1] == '\t')
00051               cp--;
00052        *cp = '\0';
00053                                    /* skip white space at beginning */
00054        for (cp = buf; *cp && (*cp == ' ' || *cp == '\t'); cp++)
00055               ;
00056                                    /* assign value */
00057        idp->number = atoi(cp);
00058        idp->name = NULL;
00059                                    /* check for ghost string */
00060        if (!*cp)
00061               return(0);
00062                                    /* check for name */
00063        if (idp->number == 0 && *cp != '0')
00064               idp->name = savestr(cp);
00065        return(0);
00066 }
00067 
00068 
00069 extern int
00070 findid(              /* find (or insert) id in list */
00071        register IDLIST      *idl,
00072        ID     *idp,
00073        int    insert
00074 )
00075 {
00076        int  upper, lower;
00077        register int  cm, i;
00078                                    /* binary search */
00079        lower = 0;
00080        upper = cm = idl->nids;
00081        while ((i = (lower + upper) >> 1) != cm) {
00082               cm = idcmp(idp, &idl->id[i]);
00083               if (cm > 0)
00084                      lower = i;
00085               else if (cm < 0)
00086                      upper = i;
00087               else
00088                      return(i);
00089               cm = i;
00090        }
00091        if (!insert)
00092               return(-1);
00093        if (idl->nids == 0) {                     /* create new list */
00094               idl->id = (ID *)malloc(sizeof(ID));
00095               if (idl->id == NULL)
00096                      goto memerr;
00097        } else {                           /* grow old list */
00098               idl->id = (ID *)realloc((void *)idl->id,(idl->nids+1)*sizeof(ID));
00099               if (idl->id == NULL)
00100                      goto memerr;
00101               for (i = idl->nids; i > upper; i--) {
00102                      idl->id[i].number = idl->id[i-1].number;
00103                      idl->id[i].name = idl->id[i-1].name;
00104               }
00105        }
00106        idl->nids++;                       /* insert new element */
00107        idl->id[i].number = idp->number;
00108        if (idp->name == NULL)
00109               idl->id[i].name = NULL;
00110        else
00111               idl->id[i].name = savestr(idp->name);
00112        return(i);
00113 memerr:
00114        eputs("Out of memory in findid\n");
00115        quit(1);
00116        return -1; /* pro forma return */
00117 }
00118 
00119 
00120 static int
00121 idcmp(                      /* compare two identifiers */
00122        register ID   *id1,
00123        register ID *id2
00124 )
00125 {
00126                                    /* names are greater than numbers */
00127        if (id1->name == NULL)
00128               if (id2->name == NULL)
00129                      return(id1->number - id2->number);
00130               else
00131                      return(-1);
00132        else
00133               if (id2->name == NULL)
00134                      return(1);
00135               else
00136                      return(strcmp(id1->name, id2->name));
00137 }
00138 
00139 
00140 extern void
00141 write_quals(  /* write out qualifier lists */
00142        QLIST  *qlp,
00143        IDLIST idl[],
00144        FILE   *fp
00145 )
00146 {
00147        int    i;
00148        
00149        for (i = 0; i < qlp->nquals; i++)
00150               if (idl[i].nids > 0) {
00151                      fprintf(fp, "qualifier %s begin\n", qlp->qual[i]);
00152                      fputidlist(&idl[i], fp);
00153                      fprintf(fp, "end\n");
00154               }
00155 }
00156 
00157 
00158 static void
00159 fputidlist(          /* put id list out to fp */
00160        IDLIST *qp,
00161        FILE   *fp
00162 )
00163 {
00164        int    fi;
00165        register int  i;
00166                                    /* print numbers/ranges */
00167        fi = 0;
00168        for (i = 0; i < qp->nids && qp->id[i].name == NULL; i++)
00169               if (i > 0 && qp->id[i].number > qp->id[i-1].number+1) {
00170                      if (i > fi+1)
00171                             fprintf(fp, "[%d:%d]\n", qp->id[fi].number,
00172                                           qp->id[i-1].number);
00173                      else
00174                             fprintf(fp, "%d\n", qp->id[fi].number);
00175                      fi = i;
00176               }
00177        if (i-1 > fi)
00178               fprintf(fp, "[%d:%d]\n", qp->id[fi].number,
00179                             qp->id[i-1].number);
00180        else if (i > 0)
00181               fprintf(fp, "%d\n", qp->id[fi].number);
00182        for ( ; i < qp->nids; i++)
00183               fprintf(fp, "\"%s\"\n", qp->id[i].name);
00184 }
00185 
00186 
00187 RULEHD *
00188 getmapping(          /* read in mapping file */
00189        char   *file,
00190        QLIST  *qlp
00191 )
00192 {
00193        char   *err;
00194        register int  c;
00195        RULEHD *mp = NULL;
00196        int    nrules = 0;
00197        register RULEHD      *rp;
00198        register int  qt;
00199        char   buf[MAXSTR];
00200        FILE   *fp;
00201        
00202        if ((fp = fopen(file, "r")) == NULL) {
00203               eputs(file);
00204               eputs(": cannot open\n");
00205               quit(1);
00206        }
00207                                                  /* get each rule */
00208        while (fscanf(fp, " %[^     ;\n]", buf) == 1) {
00209               if (buf[0] == '#') {               /* comment */
00210                      while ((c = getc(fp)) != EOF && c != '\n')
00211                             ;
00212                      continue;
00213               }
00214               rp = (RULEHD *)calloc(1, rulsiz(qlp->nquals));
00215               if (rp == NULL)
00216                      goto memerr;
00217               rp->mnam = savestr(buf);
00218               for ( ; ; ) {                      /* get conditions */
00219                      while ((c = getc(fp)) != '(')
00220                             if (c == ';' || c == EOF)
00221                                    goto endloop;
00222                      if (fscanf(fp, " %s ", buf) != 1) {
00223                             err = "missing variable";
00224                             goto fmterr;
00225                      }
00226                      if ((qt = qtype(buf, qlp)) == -1) {
00227                             err = "unknown variable";
00228                             goto fmterr;
00229                      }
00230                      if (rp->qflg & FL(qt)) {
00231                             err = "variable repeated";
00232                             goto fmterr;
00233                      }
00234                      rp->qflg |= FL(qt);
00235                      c = getc(fp);
00236                      switch (c) {
00237                      case '"':                   /* id name */
00238                             if (fscanf(fp, "%[^\"]\" )", buf) != 1) {
00239                                    err = "bad string value";
00240                                    goto fmterr;
00241                             }
00242                             idm(rp)[qt].nam = savestr(buf);
00243                             break;
00244                      case '[':                   /* id range */
00245                             if (fscanf(fp, "%d : %d ] )", &idm(rp)[qt].min,
00246                                           &idm(rp)[qt].max) != 2) {
00247                                    err = "bad range value";
00248                                    goto fmterr;
00249                             }
00250                             if (idm(rp)[qt].min > idm(rp)[qt].max) {
00251                                    err = "reverse range value";
00252                                    goto fmterr;
00253                             }
00254                             break;
00255                      default:                    /* id number? */
00256                             if ((c < '0' || c > '9') && c != '-') {
00257                                    err = "unrecognizable value";
00258                                    goto fmterr;
00259                             }
00260                             ungetc(c, fp);
00261                             if (fscanf(fp, "%d )", &idm(rp)[qt].min) != 1) {
00262                                    err = "bad number id";
00263                                    goto fmterr;
00264                             }
00265                             idm(rp)[qt].max = idm(rp)[qt].min;
00266                             break;
00267                      }
00268               }
00269        endloop:
00270               rp->next = mp;
00271               mp = rp;
00272               nrules++;
00273        }
00274        fclose(fp);
00275        return(mp);
00276 fmterr:
00277        sprintf(buf, "%s: %s for rule %d\n", file, err, nrules+1);
00278        eputs(buf);
00279        quit(1);
00280 memerr:
00281        eputs("Out of memory in getmapping\n");
00282        quit(1);
00283        return NULL; /* pro forma return */
00284 }
00285 
00286 
00287 static int
00288 qtype(               /* return number for qualifier name */
00289        char   *qnm,
00290        register QLIST       *qlp
00291 )
00292 {
00293        register int  i;
00294        
00295        for (i = 0; i < qlp->nquals; i++)
00296               if (!strcmp(qnm, qlp->qual[i]))
00297                      return(i);
00298        return(-1);
00299 }
00300 
00301 
00302 extern int
00303 matchid(                    /* see if we match an id */
00304        register ID   *it,
00305        register IDMATCH     *im
00306 )
00307 {
00308        if (it->name == NULL) {
00309               if (im->nam != NULL)
00310                      return(0);
00311               return(it->number >= im->min && it->number <= im->max);
00312        }
00313        if (im->nam == NULL)
00314               return(0);
00315        return(!strcmp(it->name, im->nam));
00316 }