ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rcode_ident.c
Revision: 2.7
Committed: Wed Jul 24 17:50:32 2019 UTC (4 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +7 -4 lines
Log Message:
Use separation character for ID table output

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rcode_ident.c,v 2.6 2019/07/24 00:25:51 greg Exp $";
3 #endif
4 /*
5 * Create or read identifier index map
6 *
7 */
8
9 #include <stdlib.h>
10 #include <ctype.h>
11 #include "rtio.h"
12 #include "platform.h"
13 #include "lookup.h"
14 #include "idmap.h"
15
16 #ifndef MAXIDLEN
17 #define MAXIDLEN 256 /* longest ID length supported */
18 #endif
19
20 #define HF_TABLOUT 0x100 /* output ID table after header */
21
22 char *progname; /* global argv[0] */
23
24 static int unbuffered = 0;
25 static int numeric = 0;
26 static int sepc = '\n';
27
28
29 /* Report usage error and exit */
30 static void
31 usage_exit(int code)
32 {
33 fputs("Usage: ", stderr);
34 fputs(progname, stderr);
35 fputs(" [-8|-16|-24][-h][-tS][-x xr -y yr] [input.txt [output.idx]]\n",
36 stderr);
37 fputs(" Or: ", stderr);
38 fputs(progname, stderr);
39 fputs(" -r [-i][-u][-h][-H][-l][-n][-tS] input.idx [output.txt]\n",
40 stderr);
41 exit(code);
42 }
43
44
45 /* read identifier from input, trimming white space on either end */
46 static int
47 scan_ident(char ident[MAXIDLEN], FILE *fp)
48 {
49 char *cp = ident;
50 int c;
51
52 while ((c = getc(fp)) != EOF) {
53 if (cp == ident && isspace(c))
54 continue;
55 if (c == sepc) {
56 while (cp > ident && isspace(cp[-1]))
57 cp--;
58 *cp = '\0';
59 return cp - ident; /* return string length */
60 }
61 if (cp - ident >= MAXIDLEN-1) {
62 fputs(progname, stderr);
63 fputs(": identifier too long in scan_ident()\n", stderr);
64 return -1;
65 }
66 *cp++ = c;
67 }
68 return -1;
69 }
70
71
72 /* elide format from header lines */
73 static int
74 headline(char *s, void *p)
75 {
76 extern const char FMTSTR[];
77
78 if (strstr(s, FMTSTR) == s)
79 return 0;
80
81 fputs(s, stdout);
82 return 1;
83 }
84
85
86 /* Create an identifier index from the given input file (stdin if NULL) */
87 int
88 create_index(const char *fname, int hdrflags, int ndxbytes, int xres, int yres)
89 {
90 FILE *fp = stdin;
91 char **idmap;
92 int idmlen;
93 int nextID = 0;
94 LUTAB hashtab;
95 RESOLU rs;
96 long n;
97 int ndx;
98 /* open file if not stdin */
99 if (!fname)
100 fname = "<stdin>";
101 else if (!(fp = fopen(fname, "r"))) {
102 fputs(fname, stderr);
103 fputs(": cannot open for input\n", stderr);
104 return 0;
105 }
106 #ifdef getc_unlocked /* avoid stupid semaphores */
107 flockfile(fp);
108 #endif
109 /* load/copy header */
110 if (hdrflags & HF_HEADOUT && getheader(fp, headline, NULL) < 0) {
111 fputs(fname, stderr);
112 fputs(": bad header or wrong input format\n", stderr);
113 fclose(fp);
114 return 0;
115 }
116 if (!(hdrflags & HF_HEADOUT))
117 newheader("RADIANCE", stdout);
118 /* finish & allocate ID table */
119 switch (ndxbytes) {
120 case 1:
121 fputformat(IDMAP8FMT, stdout);
122 idmap = (char **)malloc((idmlen=256)*sizeof(char *));
123 break;
124 case 2:
125 fputformat(IDMAP16FMT, stdout);
126 idmap = (char **)malloc((idmlen=4096)*sizeof(char *));
127 break;
128 case 3:
129 fputformat(IDMAP24FMT, stdout);
130 idmap = (char **)malloc((idmlen=1L<<17)*sizeof(char *));
131 break;
132 default:
133 fputs(progname, stderr);
134 fputs(": unsupported bits/pixel\n", stderr);
135 return 0;
136 }
137 memset(&hashtab, 0, sizeof(hashtab));
138 hashtab.hashf = lu_shash;
139 hashtab.keycmp = strcmp;
140 hashtab.freek = free;
141 if (!idmap || !lu_init(&hashtab, idmlen))
142 goto memerr;
143 fputc('\n', stdout); /* end of info header */
144
145 rs.rt = PIXSTANDARD; /* get/write map resolution */
146 if (hdrflags & HF_RESOUT) {
147 if (!fgetsresolu(&rs, fp)) {
148 fputs(fname, stderr);
149 fputs(": bad resolution string\n", stderr);
150 return 0;
151 }
152 } else if (((rs.xr = xres) <= 0) | ((rs.yr = yres) <= 0)) {
153 fputs(fname, stderr);
154 fputs(": missing/illegal resolution\n", stderr);
155 return 0;
156 }
157 fputsresolu(&rs, stdout);
158 /* read/assign/write each ID */
159 for (n = (long)rs.xr*rs.yr; n-- > 0; ) {
160 LUENT *lep;
161 char ident[MAXIDLEN];
162 int len = scan_ident(ident, fp);
163 if (len < 0) {
164 if (feof(fp)) {
165 fputs(fname, stderr);
166 fputs(": unexpected EOF\n", stderr);
167 }
168 return 0;
169 }
170 lep = lu_find(&hashtab, ident);
171 if (!lep->key) { /* new entry */
172 if (nextID >= 1<<(ndxbytes<<3)) {
173 fputs(progname, stderr);
174 fputs(
175 ": too many unique identifiers for index size\n",
176 stderr);
177 return 0;
178 }
179 if (nextID >= idmlen) { /* reallocate? */
180 idmlen += idmlen>>2; /* +25% growth */
181 idmap = (char **)realloc(idmap, idmlen);
182 if (!idmap)
183 goto memerr;
184 }
185 lep->key = (char *)malloc(len+1);
186 if (!lep->key)
187 goto memerr;
188 idmap[nextID] = strcpy(lep->key, ident);
189 lep->data = (char *)nextID++;
190 }
191 /* write this id index */
192 putint((int)lep->data, ndxbytes, stdout);
193 }
194 while ((ndx = getc(fp)) != EOF) /* verify we got them all */
195 if (!isspace(ndx)) {
196 fputs(fname, stderr);
197 fputs(": warning - non-white characters past end\n",
198 stderr);
199 break;
200 }
201 if (fp != stdin) /* done with input */
202 fclose(fp);
203 for (ndx = 0; ndx < nextID; ndx++) { /* append string table */
204 fputs(idmap[ndx], stdout);
205 putchar('\0'); /* nul-terminated IDs */
206 }
207 free(idmap); /* clean up */
208 lu_done(&hashtab);
209 return 1;
210 memerr:
211 fputs(progname, stderr);
212 fputs(": out of memory!\n", stderr);
213 return 0;
214 }
215
216
217 /* print out ID table */
218 void
219 print_IDs(IDMAP *idmp)
220 {
221 int i;
222
223 printf("============ %d IDs ============\n", idmp->nids);
224
225 for (i = 0; i < idmp->nids; i++) {
226 fputs(mapID(idmp, i), stdout);
227 putchar(sepc);
228 }
229 if (sepc != '\n')
230 fputc('\n', stdout);
231 puts("============= END =============");
232 }
233
234
235 /* Load selected pixels from identifier index file */
236 int
237 decode_select(const char *fname, int hdrflags)
238 {
239 IDMAP *idmp = idmap_ropen(fname, hdrflags);
240 int i, j;
241
242 if (!idmp)
243 return 0;
244
245 if (hdrflags & HF_TABLOUT)
246 print_IDs(idmp);
247
248 if (idmp->res.rt != PIXSTANDARD) {
249 fputs(progname, stderr);
250 fputs(": can only handle standard pixel ordering\n", stderr);
251 idmap_close(idmp);
252 return 0;
253 }
254 while (scanf("%d %d", &i, &j) == 2) {
255 i = idmap_seek(idmp, i, idmp->res.yr-1 - j);
256 if (!i) {
257 fputs(progname, stderr);
258 fputs(": warning - pixel index is off map\n", stderr);
259 continue;
260 }
261 if (i > 0)
262 i = idmap_next_i(idmp);
263 if (i < 0) {
264 fputs(fname, stderr);
265 fputs(": read/seek error in decode_select()\n", stderr);
266 idmap_close(idmp);
267 return 0;
268 }
269 if (numeric) {
270 printf("%d", i);
271 } else {
272 const char *id = mapID(idmp, i);
273 if (!id) {
274 fputs(fname, stderr);
275 fputs(": bad ID index in file\n", stderr);
276 idmap_close(idmp);
277 return 0;
278 }
279 fputs(id, stdout);
280 }
281 putchar(sepc);
282 if (unbuffered && fflush(stdout) == EOF) {
283 fputs(progname, stderr);
284 fputs(": write error on output\n", stderr);
285 idmap_close(idmp);
286 return 0;
287 }
288 }
289 idmap_close(idmp);
290
291 if (!feof(stdin)) {
292 fputs(progname, stderr);
293 fputs(": non-numeric input for pixel index\n", stderr);
294 return 0;
295 }
296 return 1;
297 }
298
299
300 /* Load and convert identifier index file to ASCII */
301 int
302 decode_all(const char *fname, int hdrflags)
303 {
304 IDMAP *idmp = idmap_ropen(fname, hdrflags);
305 long n;
306
307 if (!idmp)
308 return 0;
309
310 if (hdrflags & HF_TABLOUT)
311 print_IDs(idmp);
312
313 for (n = idmp->res.xr*idmp->res.yr; n-- > 0; ) {
314 const int ndx = idmap_next_i(idmp);
315 if (ndx < 0) {
316 fputs(fname, stderr);
317 fputs(": unexpected EOF\n", stderr);
318 idmap_close(idmp);
319 return 0;
320 }
321 if (numeric) {
322 printf("%d", ndx);
323 } else {
324 const char *id = mapID(idmp, ndx);
325 if (!id) {
326 fputs(fname, stderr);
327 fputs(": bad ID index in file\n", stderr);
328 idmap_close(idmp);
329 return 0;
330 }
331 fputs(id, stdout);
332 }
333 putchar(sepc);
334 }
335 idmap_close(idmp);
336 return 1;
337 }
338
339
340 int
341 main(int argc, char *argv[])
342 {
343 char *inpfname = NULL;
344 int reverse = 0;
345 int bypixel = 0;
346 int hdrflags = HF_HEADOUT|HF_RESOUT;
347 int xres=0, yres=0;
348 int ndxbytes = 2;
349 int a;
350
351 progname = argv[0];
352 for (a = 1; a < argc && argv[a][0] == '-'; a++)
353 switch (argv[a][1]) {
354 case 'r':
355 reverse++;
356 break;
357 case 'i':
358 bypixel++;
359 break;
360 case 'u':
361 unbuffered++;
362 break;
363 case 'n':
364 numeric++;
365 break;
366 case 'l':
367 hdrflags |= HF_TABLOUT;
368 break;
369 case 'h':
370 hdrflags &= ~HF_HEADOUT;
371 break;
372 case 'H':
373 hdrflags &= ~HF_RESOUT;
374 break;
375 case 't':
376 if (!(sepc = argv[a][2]))
377 sepc = '\n';
378 break;
379 case 'x':
380 xres = atoi(argv[++a]);
381 break;
382 case 'y':
383 yres = atoi(argv[++a]);
384 break;
385 case '8':
386 case '1':
387 case '2':
388 switch (atoi(argv[a]+1)) {
389 case 8:
390 ndxbytes = 1;
391 break;
392 case 16:
393 ndxbytes = 2;
394 break;
395 case 24:
396 ndxbytes = 3;
397 break;
398 default:
399 usage_exit(1);
400 }
401 break;
402 default:
403 usage_exit(1);
404 }
405 if ((xres > 0) & (yres > 0)) /* user specified resolution? */
406 hdrflags &= ~HF_RESOUT;
407 if (reverse && a >= argc) {
408 fputs(progname, stderr);
409 fputs(": -r option requires named input file\n", stderr);
410 return 1;
411 }
412 if (a < argc-2) {
413 fputs(progname, stderr);
414 fputs(": too many file arguments\n", stderr);
415 return 1;
416 }
417 if (a < argc)
418 inpfname = argv[a];
419 if (a+1 < argc && !freopen(argv[a+1], "w", stdout)) {
420 fputs(argv[a+1], stderr);
421 fputs(": cannot open output\n", stderr);
422 return 1;
423 }
424 if (!reverse)
425 SET_FILE_BINARY(stdout);
426 #ifdef getc_unlocked /* avoid stupid semaphores */
427 flockfile(stdout);
428 #endif
429 if (reverse) {
430 if (!(bypixel ? decode_select(inpfname, hdrflags) :
431 decode_all(inpfname, hdrflags)))
432 return 1;
433 } else if (!create_index(inpfname, hdrflags, ndxbytes, xres, yres))
434 return 1;
435
436 if (fflush(stdout) == EOF) {
437 fputs(progname, stderr);
438 fputs(": error writing output\n", stderr);
439 return 1;
440 }
441 return 0;
442 }