home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / formats / off / code / readobj.c < prev    next >
C/C++ Source or Header  |  1994-06-20  |  12KB  |  459 lines

  1.  
  2. /*
  3.  *
  4.  * Description
  5.  *    Read an OFF object data file.
  6.  *
  7.  * Output
  8.  *
  9.  * Input
  10.  *    Obj        Pointer to object structure in which to store data.
  11.  *    FileName    Name of file to be read.
  12.  *
  13.  * Diagnostics
  14.  *    Returns 0 if successful, -1 if unsuccessful for any reason.
  15.  *
  16.  * Author
  17.  *    Randi J. Rost
  18.  *    Digital Equipment Corp.
  19.  *    Workstation Systems Engineering
  20.  *    Palo Alto, CA
  21.  *
  22.  * History
  23.  *    17-Nov-86    Created
  24.  *
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include "off.h"
  29.  
  30. #define    MAX_OBJ_DIRS        10
  31. #define DEFAULT_DATA_BLK    100
  32.  
  33. static    char        ObjDir[MAX_OBJ_DIRS][OFF_BIGSTR];
  34. static    int        NumObjDirs = 0;
  35. static    int        firsttime = 1;
  36. static    OFFProperty    **pProp;
  37.  
  38. OFFReadObj(Obj, FileName)
  39.     OFFObjDesc     *Obj;            /* Object data structure to fill out */
  40.     char     *FileName;        /* File to be opened and read */
  41.  
  42.     {
  43.     FILE    *ObjFile;
  44.     char    Line[OFF_BIGSTR];
  45.     char    Key[OFF_BIGSTR];
  46.     char    Remainder[OFF_BIGSTR];
  47.     char    Directory[OFF_BIGSTR];
  48.     char    Path[OFF_BIGSTR];
  49.     char    TmpString[OFF_BIGSTR];
  50.     char    *index(), *getenv();
  51.     int        i;
  52.     int        status = 0;
  53.     char    *comment = "comment";
  54.     char    *nl = "nl";
  55.  
  56.  
  57. /*  If this is the first time, parse the object search path  */
  58.     if (firsttime)
  59.     status = ParseObjPath();
  60.  
  61. /*  Punt if too many directories in OBJ_PATH  */
  62.     if (status < 0)
  63.     {
  64.     fprintf(stderr,"OFFReadObj: too many (> %d) directories in OBJ_PATH\n",
  65.         MAX_OBJ_DIRS);
  66.     return(-1);
  67.     }
  68.  
  69. /*  See if filename has a leading pathname component  */
  70.     Directory[0] = '\0';
  71.     for (i = strlen(FileName) - 1; i >= 0; i--)
  72.     if (FileName[i] == '/') break;
  73.     if (i >= 0)
  74.     {
  75.     strncpy(Directory, FileName, i + 1);
  76.     Directory[i+1] = '\0';
  77.     }
  78.  
  79. /*  First try opening the file as passed to us  */
  80.     ObjFile = fopen(FileName,"r");
  81.  
  82. /*  If that doesn't work, try each directory in search path  */
  83.     if (ObjFile == NULL)
  84.     { 
  85.     for (i = 0; i < NumObjDirs; i++)
  86.         {
  87.         strcpy(Path, ObjDir[i]);
  88.         strcat(Path, FileName);
  89.         ObjFile = fopen(Path, "r");
  90.         if (ObjFile != NULL)
  91.         {
  92.         strcpy(TmpString, ObjDir[i]);
  93.         strcat(TmpString, Directory);
  94.         strcpy(Directory, TmpString);
  95.         break;
  96.         }
  97.         }
  98.     }
  99.  
  100. /*  If the file isn't found in any of the search directories, punt  */
  101.     if (ObjFile == NULL)
  102.     {
  103.     fprintf(stderr, "OFFReadObj:  %s not found\n", FileName);
  104.     return(-1);
  105.     }
  106.  
  107. /*  Initialize fields in object structure  */
  108.     pProp = &(Obj->FirstProp);
  109.     Obj->FirstProp = NULL;
  110.  
  111. /*  Read lines from the header file  */
  112.     while((fgets(Line, OFF_BIGSTR - 1, ObjFile)) != NULL) 
  113.     {
  114.     /*  Get the first token  */
  115.     if (Line[0] == '\n')
  116.         status = AddProperty(nl, NULL, NULL);
  117.     else if (Line[0] == '#')
  118.         status = AddProperty(comment, Line, NULL);
  119.     else
  120.         {
  121.         SplitLine(Line, Key, Remainder);
  122.         status = AddProperty(Key, Remainder, Directory);
  123.         }
  124.     if (status != 0)
  125.         {
  126.         fprintf(stderr, "OFFReadObj: problem parsing line\n");
  127.         fprintf(stderr, "\t>>>%s\n", Line);
  128.         return(-1);
  129.         }
  130.     }
  131.  
  132.     fclose(ObjFile);
  133.     return(0);
  134.     }
  135.  
  136.  
  137.  
  138. static SplitLine(str, part1, remainder)
  139.     char *str, *part1, *remainder;
  140.  
  141.     {
  142.     int    i, p1, p2;
  143.  
  144. /*  If first character is '#' for a comment, we're done  */
  145.     if (str[0] == '#')
  146.     {
  147.     strcpy(part1, "#");
  148.     strcpy(remainder, &(str[1]));
  149.     return;
  150.     }
  151.  
  152. /*  Position p1 to first non-separator character  */
  153. /*  Blanks, tabs, commas are separators */
  154.     p1 = 0;    
  155.     while ((str[p1] == ' ' ) || (str[p1] == '\t') || (str[p1] == ',')) p1++;
  156.  
  157. /*  Position p2 to first separator character after p1  */
  158.     p2 = p1;
  159.     while ((str[p2] != ' ') && (str[p2] != '\t') && (str[p2] != '\0') &&
  160.        (str[p2] != ',') && (str[p2] != '\n')) p2++;
  161.  
  162. /*  Copy what's between p1 and p2 to part1  */
  163.     for (i = p1; i < p2; i++)
  164.     part1[i - p1] = str[i];
  165.     part1[i - p1] = '\0';
  166.  
  167. /*  Position p2 to next non-separator character  */
  168.     while ((str[p2] == ' ' ) || (str[p2] == '\t') || (str[p2] == ',')) p2++;
  169.     i = 0;
  170.     while ((str[p2] != '\0') && (str[p2] != '\n') && (str[p2] != '\0'))
  171.     remainder[i++] = str[p2++];
  172.     remainder[i] = '\0';
  173.     }
  174.  
  175. #ifdef caca
  176. OFFPrintObjPath()
  177.  
  178.     {
  179.     int        i;
  180.  
  181. /*  If this is the first time, parse the object search path  */
  182.     if (firsttime)
  183.     i = ParseObjPath();
  184.  
  185. /*  Punt if too many directories in OBJ_PATH  */
  186.     if (i < 0)
  187.     {
  188.     fprintf(stderr,
  189.         "PrintObjPath: too many (> %d) directories in OBJ_PATH\n",
  190.         MAX_OBJ_DIRS);
  191.     return(-1);
  192.     }
  193.  
  194. /*  Print out all directories in the object search path  */
  195.     for (i = 0; i < NumObjDirs; i++)
  196.     printf("%s ", ObjDir[i]);
  197.     printf("\n");
  198.  
  199.     return(0);
  200.     }
  201. #endif
  202.  
  203. static ParseObjPath()
  204.  
  205.     {
  206.     char    *str;
  207.     int        i, j, len;
  208.  
  209.     firsttime = 0;
  210.     str = getenv("OBJ_PATH");
  211.     len = (str == NULL) ? 0 : strlen(str);
  212.     for (i = 0; i < len; i++)
  213.     {
  214.     while ((str[i] == ' ') || (str[i] == '\t')) i++;
  215.     j = i;
  216.     while ((str[j] != ' ') && (str[j] != '\t') && (j < strlen(str)))
  217.         j++;
  218.     strncpy(ObjDir[NumObjDirs], &(str[i]), j - i);
  219.     ObjDir[NumObjDirs][j - i] = '/';
  220.     ObjDir[NumObjDirs][j - i + 1] = '\0';
  221.     if (strcmp(ObjDir[NumObjDirs], "./") != 0)
  222.         glob(ObjDir[NumObjDirs++]);  /* ignore directory "." in path */
  223.     i = j;
  224.     if (NumObjDirs > MAX_OBJ_DIRS)
  225.         return(-1);
  226.     }
  227.  
  228.     return(0);
  229.     }
  230.  
  231.  
  232. #include <pwd.h>
  233. #include <ctype.h>
  234.  
  235. static glob(string)
  236.     char    *string;
  237.  
  238.     {
  239.     struct    passwd    *p, *getpwname();
  240.     char    str1[160], str2[160];
  241.     char    *pstr;
  242.     char    *getenv();
  243.  
  244.    
  245. /*  If first character is '~', expand it  */
  246.     if (string[0] == '~')
  247.  
  248.     {
  249.  
  250.     strcpy(str1, string);
  251.  
  252.     /*  ~/... means use home directory  */
  253.     if (string[1] == '/')
  254.         {
  255.         strcpy(string, getenv("HOME"));
  256.         strcat(string, &(str1[1]));
  257.         }
  258.  
  259.     /*  ~whatever/... means use whatever's home directory  */
  260.     else
  261.         {
  262.         pstr = index(str1, '/');
  263.         strncpy(str2, &(string[1]), pstr - str1 - 1);
  264.         str2[pstr - str1 - 1] = 0;
  265.         p = getpwnam(str2);
  266.         strcpy(string, p->pw_dir);
  267.         strcat(string, pstr);
  268.         }
  269.  
  270.     }
  271.  
  272.     }
  273.  
  274.  
  275. static int AddProperty(PropName, String, Directory)
  276.     char    *PropName;
  277.     char    *String;
  278.     char    *Directory;
  279.  
  280.     {
  281.     OFFProperty    *newprop;
  282.     char    str[OFF_BIGSTR], junk[OFF_BIGSTR], remainder[OFF_BIGSTR];
  283.     char    datatype[OFF_BIGSTR];
  284.     char    filename[OFF_BIGSTR];
  285.     long    *iptr;
  286.     short    *hptr;
  287.     float    *fptr;
  288.     double    *dptr;
  289.     char    *ptr;
  290.     int        i, j, k;
  291.     char    *comment = "comment";
  292.  
  293.     newprop = (OFFProperty *) malloc(sizeof(OFFProperty));
  294.     *pProp = newprop;
  295.     pProp = &(newprop->NextProp);
  296.     newprop->NextProp = NULL;
  297.     newprop->PropData = NULL;
  298.     newprop->PropFileName[0] = '\0';
  299.     newprop->DataFormat[0] = '\0';
  300.     newprop->PropCount = 0;
  301.     PropName[OFF_SMSTR] = '\0';
  302.     strcpy(newprop->PropName, PropName);
  303.  
  304. /* The following strcmp apparently caused some problems with the MIPS
  305.    compiler...don't know what the problem was, but have altered the code
  306.    some and it seems to work now.  Somehow the value for PropName was
  307.    getting trashed.  Don't ask me.  */
  308. /* fprintf(stderr, "PropName = >%s<\n", PropName); */
  309.     if (strncmp(PropName, comment, strlen(comment) - 1) == 0)
  310.     {
  311. /* fprintf(stderr, "Got a comment!!!\n"); */
  312.     String[strlen(String) - 1] = '\0';
  313.     newprop->PropData = (char *) malloc(strlen(String));
  314.     strcpy(newprop->PropData, String);
  315.     newprop->PropType = OFF_COMMENT_DATA;
  316.     return(0);
  317.     }
  318. /* fprintf(stderr, "PropName = >%s<\n", PropName); */
  319.  
  320.     if (strcmp(PropName, "nl") == 0)
  321.     {
  322.     newprop->PropData = (char *) malloc(OFF_BIGSTR);
  323.     newprop->PropType = OFF_COMMENT_DATA;
  324.     return(0);
  325.     }
  326.  
  327.     if (strcmp(PropName, "name") == 0 || strcmp(PropName, "author") == 0 ||
  328.     strcmp(PropName, "type") == 0 || strcmp(PropName, "description") == 0
  329.     || strcmp(PropName, "copyright") == 0)
  330.     {
  331.     newprop->PropData = (char *) malloc(OFF_BIGSTR);
  332.     strcpy(newprop->PropData, String);
  333.     newprop->PropType = OFF_STANDARD_DATA;
  334.     return(0);
  335.     }
  336.  
  337.     else
  338.     {
  339.     SplitLine(String, datatype, remainder);
  340.     if (strcmp(datatype, "default") == 0)
  341.         newprop->PropType = OFF_DEFAULT_DATA;
  342.     else if (strcmp(datatype, "generic") == 0)
  343.         newprop->PropType = OFF_GENERIC_DATA;
  344.     else if (strcmp(datatype, "indexed") == 0)
  345.         newprop->PropType = OFF_INDEXED_DATA;
  346.     else if (strcmp(datatype, "indexed_poly") == 0)
  347.         newprop->PropType = OFF_INDEXED_POLY_DATA;
  348.     else
  349.         newprop->PropType = OFF_UNKNOWN_TYPE_DATA;
  350.     strcpy(str, remainder);
  351.     SplitLine(str, newprop->DataFormat, remainder);
  352.  
  353.     remainder[OFF_SMSTR] = '\0';
  354.     if (newprop->PropType != OFF_DEFAULT_DATA)
  355.         strcpy(newprop->PropFileName, remainder);
  356.  
  357.     switch(newprop->PropType)
  358.         {
  359.         case OFF_DEFAULT_DATA:
  360.         newprop->PropCount = 1;
  361.         newprop->PropData = (char *) malloc(DEFAULT_DATA_BLK);
  362.         ptr = newprop->PropData;
  363.         for (i = 0; i < strlen(newprop->DataFormat); i++)
  364.             {
  365.             switch (newprop->DataFormat[i])
  366.             {
  367.             case 'i':
  368.                  /* Make sure we're aligned on word boundary */
  369.                  ptr += (((int) ptr % 4) == 0) ?
  370.                 0 : 4 - (int) ptr % 4;
  371.                  iptr = (long *) ptr;
  372.                  sscanf(remainder, "%d", iptr);
  373.                  ptr += sizeof(long);
  374.                  strcpy(str, remainder);
  375.                  SplitLine(str, junk, remainder);
  376.                  break;
  377.             case 'b':
  378.                  sscanf(remainder, "%d", &j);
  379.                  *ptr++ = (unsigned char) j;
  380.                  strcpy(str, remainder);
  381.                  SplitLine(str, junk, remainder);
  382.                  break;
  383.             case 'd':
  384.                  /* Make sure we're aligned on word boundary */
  385.                  ptr += (((int) ptr % 4) == 0) ?
  386.                 0 : 4 - (int) ptr % 4;
  387.                  dptr = (double *) ptr;
  388.                  sscanf(remainder, "%F", dptr);
  389.                  ptr += sizeof(double);
  390.                  strcpy(str, remainder);
  391.                  SplitLine(str, junk, remainder);
  392.                  break;
  393.             case 'h':
  394.                  /* Make sure we're aligned on halfword boundary */
  395.                  ptr += (((int) ptr % 2) == 0) ? 0 : 1;
  396.                  hptr = (short *) ptr;
  397.                  sscanf(remainder, "%hd", hptr);
  398.                  ptr += sizeof(short);
  399.                  strcpy(str, remainder);
  400.                  SplitLine(str, junk, remainder);
  401.                  break;
  402.             case 'f':
  403.                  /* Make sure we're aligned on word boundary */
  404.                  ptr += (((int) ptr % 4) == 0) ?
  405.                 0 : 4 - (int) ptr % 4;
  406.                  fptr = (float *) ptr;
  407.                  sscanf(remainder, "%f", fptr);
  408.                  ptr += sizeof(float);
  409.                  strcpy(str, remainder);
  410.                  SplitLine(str, junk, remainder);
  411.                  break;
  412.             case 's':
  413.                  j = 0; k = 0;
  414.                  while (remainder[j] != ' ' && remainder[j] != '\t'
  415.                     && j < strlen(remainder))
  416.                  junk[k++] = remainder[j++];
  417.                  junk[k] = '\0';
  418.                  *((char **) ptr) = (char *) malloc(k + 1);
  419.                  strcpy(*((char **) ptr), junk);
  420.                  ptr += sizeof(char *);
  421.                  strcpy(junk, &(remainder[j]));
  422.                  strcpy(remainder, junk);
  423.                  break;
  424.             default:
  425.                  return(-1);
  426.             } /* switch */
  427.             } /* for */
  428.         break;
  429.  
  430.         case OFF_GENERIC_DATA:
  431.         strcpy(filename, Directory);
  432.         strcat(filename, newprop->PropFileName);
  433.         if ((i = OFFReadGeneric(newprop, filename)) != 0)
  434.             return(-1);
  435.         break;
  436.  
  437.         case OFF_INDEXED_DATA:
  438.         strcpy(filename, Directory);
  439.         strcat(filename, newprop->PropFileName);
  440.         if ((i = OFFReadIndexed(newprop, filename)) != 0)
  441.             return(-1);
  442.         break;
  443.  
  444.         case OFF_INDEXED_POLY_DATA:
  445.         strcpy(filename, Directory);
  446.         strcat(filename, newprop->PropFileName);
  447.         if (OFFReadIndexedPoly(newprop, filename) != 0)
  448.             return(-1);
  449.         break;
  450.  
  451.         default:
  452.         return(-1);
  453.         break;
  454.         } /* switch */
  455.     }
  456.  
  457.     return(0);
  458.     }
  459.