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