home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / clrread.c < prev    next >
C/C++ Source or Header  |  1990-04-28  |  9KB  |  314 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    clrread.c (Color Read)
  6.  * Purpose:    Read and Write file and internally stored color tables
  7.  * Subroutine:    parse_color_file()        returns: int
  8.  * Xlib calls:    none
  9.  * Copyright:    1989 Smithsonian Astrophysical Observatory
  10.  *        You may do anything you like with this file except remove
  11.  *        this copyright.  The Smithsonian Astrophysical Observatory
  12.  *        makes no representations about the suitability of this
  13.  *        software for any purpose.  It is provided "as is" without
  14.  *        express or implied warranty.
  15.  * Modified:    {0} Michael VanHilst    initial version          21 Nov 1989
  16.  *        {n} <who> -- <does what> -- <when>
  17.  */
  18.  
  19. #include <stdio.h>        /* stderr, NULL, etc. */
  20. #include <ctype.h>        /* toupper, isalpha, etc. */
  21. #include "hfiles/colormap.h"    /* color table storage structs */
  22. #include "hfiles/define.h"    /* define SZ_LINE, etc. */
  23.  
  24. /*
  25.  * Subroutine:    parse_color_file
  26.  * Purpose:    Parse values after color identifier
  27.  */
  28. int parse_color_file ( fp, ctable, max_entries )
  29.      ColorTable *ctable;
  30.      int max_entries;
  31.      FILE *fp;
  32. {
  33.   int len, i;
  34.   int line_num;
  35.   char line[SZ_LINE];
  36.   char cbuf[SZ_LINE];
  37.   struct SubTable *table;
  38.   static int parse_color_table(), advance_to_ascii();
  39.  
  40.   line_num = 0;
  41.   /* advance to first non-comment line */
  42.   len = advance_to_ascii(fp, line, cbuf, SZ_LINE, &line_num, 1);
  43.   if( len == 0 )
  44.     return( 0 );
  45.   if( (len < 0) || (len != 11) ||
  46.       (strncmp(cbuf, "PSEUDOCOLOR", 11) != 0) ) {
  47.     (void)fprintf(stderr,
  48.           "ERROR: pseudocolor keyword not found at head of file\n");
  49.     return( 0 );
  50.   }
  51.   /* advance to next non-comment line */
  52.   len = advance_to_ascii(fp, line, cbuf, SZ_LINE, &line_num, 1);
  53.   for( i=0; i<3; i++ ) {
  54.     switch( len ) {
  55.     case 0:
  56.       return( 0 );
  57.     case 3:
  58.       if( strncmp(cbuf, "RED", 3) != 0 )
  59.     table = NULL;
  60.       else
  61.     table = &ctable->red;
  62.       break;
  63.     case 4:
  64.       if( strncmp(cbuf, "BLUE", 4) != 0 )
  65.     table = NULL;
  66.       else
  67.     table = &ctable->blue;
  68.       break;
  69.     case 5:
  70.       if( strncmp(cbuf, "GREEN", 5) != 0 )
  71.     table = NULL;
  72.       else
  73.     table = &ctable->green;
  74.       break;
  75.     default:
  76.       table = NULL;
  77.     }
  78.     if( table == NULL ) {
  79.       (void)fprintf(stderr,
  80.             "ERROR: unrecognized keyword %s in line %d\n  %s\n",
  81.             cbuf, line_num, line);
  82.       return( 0 );
  83.     } else {
  84.       if( (len = parse_color_table(fp, line, cbuf, len + 1, SZ_LINE,
  85.                    &line_num, table, max_entries, i))
  86.      < 0 )
  87.     return( 0 );
  88.     }
  89.   }
  90.   return( 1 );
  91. }
  92.  
  93. /*
  94.  * Subroutine:    parse_color_table
  95.  * Purpose:    Read color table entries for one color
  96.  * Note:    Values may start with word "gamma" and its value
  97.  */
  98. static int parse_color_table ( fp, line, cbuf, i, len, line_num,
  99.                    farb, max_entries, color_cnt )
  100.      FILE *fp;
  101.      char *line;        /* i/l: line as read from file */
  102.      char *cbuf;        /* i/l: buffer for processing string */
  103.      int i;            /* i/l: index in working buffer of token */
  104.      int len;            /* i: length of character buffers */
  105.      int *line_num;        /* i/o: line number in file */
  106.      struct SubTable *farb;    /* i/o: structure to get color table info */
  107.      int max_entries;        /* i: maximum number of entries in table */
  108.      int color_cnt;        /* i: number of colors done so far */
  109. {
  110.   float level, intensity;
  111.   char *level_token, *intensity_token;
  112.   int status, entry;
  113.   static int advance_to_ascii(), prep_alpha();
  114.   int check_parens();
  115.   char *next_token();
  116.  
  117.   status = 0;
  118.   intensity_token = NULL;
  119.   /* first check rest of this line */
  120.   if( (cbuf[i] != '\0') && (cbuf[i] != '#') && (cbuf[i] != '\n') ) {
  121.     /* strip of parens and other non-space spacers */
  122.     if( check_parens(line, cbuf + i) < 0 )
  123.       return( -1 );
  124.     /* are there any tokens? */
  125.     intensity_token = next_token(cbuf + i, 1);
  126.   }
  127.   /* else look for a later line */
  128.   if( intensity_token == NULL ) {
  129.     i = 0;
  130.     status = advance_to_ascii(fp, line, cbuf, len, line_num, 1);
  131.     if( status == 0 )
  132.       return( -1 );
  133.     /* prepare for scanf parsing, even though it starts with alpha */
  134.     if( status > 0 ) {
  135.       if( check_parens(line, cbuf) < 0 )
  136.     return( -1 );
  137.     }
  138.     if( (intensity_token = next_token(cbuf + i, 1)) == NULL) {
  139.       (void)fprintf(stderr, "ERROR: parse error at line %d or %d\n  %s\n",
  140.             *line_num - 1, *line_num, line);
  141.       return( -1 );
  142.     }
  143.   }
  144.   /* first look for gamma */
  145.   /* don't do this prep if we know line starts with alpha */
  146.   if( status <= 0 ) {
  147.     /* this will be a check-paren'd spaced out line */
  148.     while( cbuf[i] == ' ' ) i++;
  149.     if( isalpha(cbuf[i]) )
  150.       /* aha! */
  151.       status = prep_alpha(cbuf + i, 10);
  152.   }
  153.   /* do we have alpha? */
  154.   if( status > 0 ) {
  155.     if( (status == 5) && (strncmp(cbuf+i, "GAMMA", 5) == 0) &&
  156.         (sscanf(intensity_token, "%f", &intensity) == 1) ) {
  157.       farb->gamma = intensity;
  158.       if( intensity != 1.0 )
  159.     farb->do_gamma = 1;
  160.       level_token = next_token(intensity_token, 1);
  161.     } else {
  162.       (void)fprintf(stderr, "ERROR: parse error in line %d\n  %s\n",
  163.             *line_num, line);
  164.       return( -1 );
  165.     }
  166.   } else
  167.     level_token = cbuf + i;
  168.  
  169.   i = 0;
  170.   while( i < max_entries ) {
  171.     while( level_token != NULL ) {
  172.       if( (intensity_token = next_token(level_token, 1)) == NULL ) {
  173.     (void)fprintf(stderr,"ERROR: odd number of tokens\n");
  174.     return( -1 );
  175.       }
  176.       if( sscanf(level_token, "%f %f", &level, &intensity) != 2 ) {
  177.     (void)fprintf(stderr,"ERROR: could not parse floating values\n  %s\n",
  178.               line);
  179.     return( -1 );
  180.       }
  181.       if( (i > 0) && (level < farb->cell_level[i-1]) ) {
  182.     (void)fprintf
  183.       (stderr,"ERROR: levels not consecutive and assending (%.2f)\n  %s\n",
  184.        level, line);
  185.     return( -1 );
  186.       } else if( (intensity < 0.0) || (intensity > 1.0) ) {
  187.     (void)fprintf(stderr,
  188.               "ERROR: intensity not between 0 and 1 (%.2f)\n  %s\n",
  189.               intensity, line);
  190.     return( -1 );
  191.       }
  192.       farb->cell_level[i] = level;
  193.       farb->intensity[i] = intensity;
  194.       /* too many entries for table size? */
  195.       if( ++i >= max_entries ) {
  196.     (void)fprintf(stderr, "ERROR: too many entries defined\n");
  197.     return( -1 );
  198.       }
  199.       level_token = next_token(intensity_token, 1);
  200.     }
  201.     /* advance to next non-comment line */
  202.     status = advance_to_ascii(fp, line, cbuf, len, line_num, 0);
  203.     /* check for termination conditions (text token or end of file) */
  204.     if( status >= 0 ) {
  205.       if( i < 2 )
  206.     return( -1 );
  207.       else {
  208.     /* error if real parsing error, or not last color */
  209.     if( (status == 0) && ((*line_num != 0) || (color_cnt < 2)) )
  210.       return( -1 );
  211.     else {
  212.       /* this is the good return */
  213.       farb->vertex_cnt = i;
  214.       return( status );
  215.     }
  216.       }
  217.     } else
  218.       level_token = cbuf;
  219.   }
  220.   return( -1 );
  221. }
  222.  
  223. /*
  224.  * Subroutine:    advance_to_ascii
  225.  * Purpose:    Get next processable line, and prepare a copy for processing
  226.  * Returns:    Positive character count if string starts with a name
  227.  *        Negative val if string starts with a number or paren
  228.  *        0 if file ended, or first character was neither char nor num
  229.  */
  230. static int advance_to_ascii ( fp, line, scratch, len, line_num, dont_end )
  231.      FILE *fp;        /* i: file descriptor */
  232.      char *line;    /* i: buffer to get entire line */
  233.      char *scratch;    /* i/o: buffer to get string ready for processing */
  234.      int len;        /* i: length of buffers */
  235.      int *line_num;    /* i/o: current line number */
  236.      int dont_end;    /* flag that more is definitely expected */
  237. {
  238.   int i;
  239.   static int find_token(), prep_alpha();
  240.   int check_parens();
  241.  
  242.   /* advance to first non-comment line */
  243.   do {
  244.     if( fgets(line, len, fp) == NULL ) {
  245.       if( dont_end )
  246.     (void)fprintf(stderr, "ERROR: premature end of file at line %d\n",
  247.               *line_num);
  248.       else
  249.     *line_num = 0;
  250.       return( 0 );
  251.     }
  252.     ++(*line_num);
  253.     if( (i = find_token(line, len)) >= 0 ) {
  254.       line[len-1] = '\0';
  255.       (void)strcpy(scratch, &line[i]);
  256.       if( isalpha(line[i]) )
  257.     return( prep_alpha(scratch, len - i) );
  258.       else if( (line[i] == '(') || (line[i] == '.') || isdigit(line[i]) ) {
  259.     if( (i = check_parens(line, scratch)) < 0 )
  260.       return( 0 );
  261.     else
  262.       return( -i );
  263.       } else {
  264.     (void)fprintf(stderr, "ERROR: could not parse line %d:\n  %s\n",
  265.               *line_num, line);
  266.     return( 0 );
  267.       }
  268.     }
  269.   } while( *line_num < 1000 );
  270.   (void)fprintf(stderr, "ERROR: file has too many lines to be reasonable\n");
  271.   return( 0 );
  272. }
  273.  
  274. /*
  275.  * Subroutine:    find_token
  276.  * Purpose:    Point at first non-space character if it might be parsable
  277.  * Returns:    index of character, or -1 if line ends or is comment
  278.  */
  279. static int find_token ( line, len )
  280.      char *line;
  281.      int len;
  282.   int i = 0;
  283.   /* advance to next first non-space character */
  284.   while( (line[i] == ' ') || (line[i] == '\t') ) {
  285.     if( ++i >= len )
  286.       return( -1 );
  287.   }
  288.   if( (line[i] == '\0') || (line[i] == '#') || (line[i] == '\n') )
  289.     return( -1 );
  290.   else
  291.     return( i );
  292. }
  293.  
  294. /*
  295.  * Subroutine:    prep_alpha
  296.  * Purpose:    Convert all characters to upper case and null terminate word
  297.  * Returns:    Number of characters in the word
  298.  */
  299. static int prep_alpha ( line, len )
  300.      char *line;
  301.   int i = 0;
  302.   /* advance to next first non-space character */
  303.   while( (i < len) && (isalpha(line[i])) ) {
  304.     if( islower(line[i]) )
  305.       line[i] = toupper(line[i]);
  306.     i++;
  307.   }
  308.   if( line[i] != '\0' )
  309.     line[i] = ' ';
  310.   return( i );
  311. }
  312.