ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.11
Committed: Thu Nov 7 23:13:12 2019 UTC (5 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +8 -2 lines
Log Message:
Made it so a space separator matches all white space

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.11 static const char RCSid[] = "$Id: rsplit.c,v 1.10 2019/08/14 21:00:14 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * rsplit.c - split input into multiple output streams
6     *
7     * 7/4/19 Greg Ward
8     */
9    
10     #include <ctype.h>
11    
12 greg 1.6 #include "rtio.h"
13 greg 1.1 #include "platform.h"
14 greg 1.9 #include "paths.h"
15 greg 1.1 #include "resolu.h"
16    
17     #define DOHEADER 1
18     #define DORESOLU 2
19    
20     #define MAXFILE 512 /* maximum number of files */
21    
22 greg 1.10 static int swapped = 0; /* input is byte-swapped */
23    
24 greg 1.7 static FILE *output[MAXFILE];
25     static int bytsiz[MAXFILE];
26     static short hdrflags[MAXFILE];
27     static const char *format[MAXFILE];
28     static int termc[MAXFILE];
29     static int nfiles = 0;
30 greg 1.1
31 greg 1.7 static RESOLU ourres = {PIXSTANDARD, 0, 0};
32 greg 1.1
33 greg 1.7 static char buf[16384]; /* input buffer used in scanOK() */
34 greg 1.1
35    
36     /* process header line */
37     static int
38     headline(char *s, void *p)
39     {
40     extern const char FMTSTR[];
41 greg 1.10 int i;
42 greg 1.1
43     if (strstr(s, FMTSTR) == s)
44     return(0); /* don't copy format */
45     if (!strncmp(s, "NROWS=", 6))
46     return(0);
47     if (!strncmp(s, "NCOLS=", 6))
48     return(0);
49     if (!strncmp(s, "NCOMP=", 6))
50     return(0);
51 greg 1.10 if ((i = isbigendian(s)) >= 0) {
52     swapped = (nativebigendian() != i);
53     return(0);
54     }
55     i = nfiles;
56 greg 1.1 while (i--) /* else copy line to output streams */
57     if (hdrflags[i] & DOHEADER)
58     fputs(s, output[i]);
59     return(1);
60     }
61    
62    
63     /* scan field into buffer up to and including terminating byte */
64     static int
65     scanOK(int termc)
66     {
67 greg 1.11 int skip_white = (termc == ' ');
68 greg 1.1 char *cp = buf;
69     int c;
70    
71     while ((c = getchar()) != EOF) {
72 greg 1.11 if (skip_white && isspace(c))
73     continue;
74     skip_white = 0;
75     if (c == '\n' && isspace(termc))
76     c = termc; /* forgiving assumption */
77 greg 1.1 *cp++ = c;
78     if (cp-buf >= sizeof(buf))
79     break;
80 greg 1.11 if ((termc == ' ') ? isspace(c) : (c == termc)) {
81 greg 1.1 *cp = '\0';
82     return(cp-buf);
83     }
84     }
85     return(0);
86     }
87    
88    
89     int
90     main(int argc, char *argv[])
91     {
92 greg 1.8 int inpflags = 0;
93     int needres = 0;
94 greg 1.1 int force = 0;
95     int append = 0;
96     long outcnt = 0;
97     int bininp = 0;
98     int curterm = '\n';
99     int curbytes = 0;
100     int curflags = 0;
101     const char *curfmt = "ascii";
102     int i;
103    
104     for (i = 1; i < argc; i++) {
105     if (argv[i][0] == '-') {
106     switch (argv[i][1]) {
107     case 't':
108     curterm = argv[i][2];
109 greg 1.5 if (!curterm) curterm = '\n';
110 greg 1.1 break;
111     case 'i':
112     switch (argv[i][2]) {
113     case 'h':
114 greg 1.8 inpflags ^= DOHEADER;
115 greg 1.1 break;
116     case 'H':
117 greg 1.8 inpflags ^= DORESOLU;
118 greg 1.1 break;
119     default:
120     goto badopt;
121     }
122     break;
123     case 'f':
124 greg 1.8 force = !force;
125 greg 1.1 break;
126     case 'a':
127 greg 1.8 append = !append;
128 greg 1.1 break;
129     case 'x':
130     ourres.xr = atoi(argv[++i]);
131     break;
132     case 'y':
133     ourres.yr = atoi(argv[++i]);
134     break;
135     case 'o':
136     switch (argv[i][2]) {
137     case 'n':
138     outcnt = atol(argv[++i]);
139     continue;
140     case 'h':
141     curflags ^= DOHEADER;
142     continue;
143     case 'H':
144     curflags ^= DORESOLU;
145     continue;
146     case 'f':
147     curfmt = "float";
148     curbytes = sizeof(float);
149     break;
150     case 'd':
151     curfmt = "double";
152     curbytes = sizeof(double);
153     break;
154     case 'i':
155     curfmt = "int";
156     curbytes = sizeof(int);
157     break;
158     case 'w':
159     curfmt = "16-bit";
160     curbytes = 2;
161     break;
162     case 'b':
163     curfmt = "byte";
164     curbytes = 1;
165     break;
166     case 'a':
167     curfmt = "ascii";
168 greg 1.7 curbytes = -1;
169 greg 1.1 break;
170     default:
171     goto badopt;
172     }
173     if (isdigit(argv[i][3]))
174     curbytes *= atoi(argv[i]+3);
175     curbytes += (curbytes == -1);
176     if (curbytes > (int)sizeof(buf)) {
177     fputs(argv[0], stderr);
178     fputs(": output size too big\n", stderr);
179     return(1);
180     }
181 greg 1.7 bininp += (curbytes > 0);
182 greg 1.1 break;
183     case '\0':
184 greg 1.8 needres |= (curflags & DORESOLU);
185 greg 1.1 termc[nfiles] = curterm;
186     hdrflags[nfiles] = curflags;
187     output[nfiles] = stdout;
188     if (curbytes > 0)
189     SET_FILE_BINARY(output[nfiles]);
190     format[nfiles] = curfmt;
191     bytsiz[nfiles++] = curbytes;
192     break;
193     badopt:;
194     default:
195     fputs(argv[0], stderr);
196     fputs(": bad option\n", stderr);
197     return(1);
198     }
199     } else if (argv[i][0] == '!') {
200 greg 1.8 needres |= (curflags & DORESOLU);
201 greg 1.1 termc[nfiles] = curterm;
202     hdrflags[nfiles] = curflags;
203     if ((output[nfiles] = popen(argv[i]+1, "w")) == NULL) {
204     fputs(argv[i], stderr);
205     fputs(": cannot start command\n", stderr);
206     return(1);
207     }
208     if (curbytes > 0)
209     SET_FILE_BINARY(output[nfiles]);
210     format[nfiles] = curfmt;
211     bytsiz[nfiles++] = curbytes;
212     } else {
213 greg 1.8 if (append & (curflags != 0)) {
214     fputs(argv[0], stderr);
215     fputs(": -a option incompatible with -oh and -oH\n",
216     stderr);
217     return(1);
218     }
219     needres |= (curflags & DORESOLU);
220 greg 1.1 termc[nfiles] = curterm;
221     hdrflags[nfiles] = curflags;
222     if (!append & !force && access(argv[i], F_OK) == 0) {
223     fputs(argv[i], stderr);
224     fputs(": file exists -- use -f to overwrite\n",
225     stderr);
226     return(1);
227     }
228     output[nfiles] = fopen(argv[i], append ? "a" : "w");
229     if (output[nfiles] == NULL) {
230     fputs(argv[i], stderr);
231     fputs(": cannot open for output\n", stderr);
232     return(1);
233     }
234     if (curbytes > 0)
235     SET_FILE_BINARY(output[nfiles]);
236     format[nfiles] = curfmt;
237     bytsiz[nfiles++] = curbytes;
238     }
239     if (nfiles >= MAXFILE) {
240     fputs(argv[0], stderr);
241     fputs(": too many output streams\n", stderr);
242     return(1);
243     }
244     }
245     if (!nfiles) {
246     fputs(argv[0], stderr);
247     fputs(": no output streams\n", stderr);
248     return(1);
249     }
250     if (bininp) /* binary input? */
251     SET_FILE_BINARY(stdin);
252     #ifdef getc_unlocked /* avoid lock/unlock overhead */
253     flockfile(stdin);
254     for (i = nfiles; i--; )
255     flockfile(output[i]);
256     #endif
257     /* load/copy header */
258 greg 1.8 if (inpflags & DOHEADER && getheader(stdin, headline, NULL) < 0) {
259 greg 1.1 fputs(argv[0], stderr);
260     fputs(": cannot get header from standard input\n",
261     stderr);
262     return(1);
263     }
264     /* handle resolution string */
265 greg 1.8 if (inpflags & DORESOLU && !fgetsresolu(&ourres, stdin)) {
266 greg 1.1 fputs(argv[0], stderr);
267     fputs(": cannot get resolution string from standard input\n",
268     stderr);
269     return(1);
270     }
271 greg 1.8 if (needres && (ourres.xr <= 0) | (ourres.yr <= 0)) {
272 greg 1.1 fputs(argv[0], stderr);
273     fputs(": -oH option requires -iH or -x and -y options\n", stderr);
274     return(1);
275     }
276     if ((ourres.xr > 0) & (ourres.yr > 0)) {
277     if (outcnt <= 0) {
278     outcnt = ourres.xr * ourres.yr;
279     } else if (outcnt != ourres.xr*ourres.yr) {
280     fputs(argv[0], stderr);
281     fputs(": warning: -on option does not agree with resolution\n",
282     stderr);
283     }
284     }
285     for (i = 0; i < nfiles; i++) { /* complete headers */
286     if (hdrflags[i] & DOHEADER) {
287 greg 1.8 if (!(inpflags & DOHEADER))
288 greg 1.1 newheader("RADIANCE", output[i]);
289     printargs(argc, argv, output[i]);
290 greg 1.10 if (format[i] != NULL) {
291     extern const char BIGEND[];
292     if ((format[i][0] == 'f') |
293     (format[i][0] == 'd')) {
294     fputs(BIGEND, output[i]);
295     fputs(nativebigendian() ^ swapped ?
296     "1\n" : "0\n", output[i]);
297     }
298 greg 1.1 fputformat(format[i], output[i]);
299 greg 1.10 }
300 greg 1.1 fputc('\n', output[i]);
301     }
302     if (hdrflags[i] & DORESOLU)
303     fputsresolu(&ourres, output[i]);
304     }
305     do { /* main loop */
306     for (i = 0; i < nfiles; i++) {
307     if (bytsiz[i] > 0) { /* binary output */
308     if (getbinary(buf, bytsiz[i], 1, stdin) < 1)
309     break;
310 greg 1.7 if (putbinary(buf, bytsiz[i], 1, output[i]) < 1)
311 greg 1.4 break;
312 greg 1.1 } else if (bytsiz[i] < 0) { /* N-field output */
313     int n = -bytsiz[i];
314     while (n--) {
315     if (!scanOK(termc[i]))
316     break;
317 greg 1.4 if (fputs(buf, output[i]) == EOF)
318     break;
319 greg 1.1 }
320     if (n >= 0) /* fell short? */
321     break;
322 greg 1.4 if (termc[i] != '\n') /* add EOL if none */
323     fputc('\n', output[i]);
324 greg 1.1 } else { /* 1-field output */
325     if (!scanOK(termc[i]))
326     break;
327 greg 1.4 if (fputs(buf, output[i]) == EOF)
328     break;
329     if (termc[i] != '\n') /* add EOL if none */
330     fputc('\n', output[i]);
331 greg 1.1 }
332 greg 1.7 /* skip input EOL? */
333     if (!bininp && termc[nfiles-1] != '\n') {
334     int c = getchar();
335     if ((c != '\n') & (c != EOF))
336     ungetc(c, stdin);
337     }
338 greg 1.1 }
339     if (i < nfiles)
340     break;
341     } while (--outcnt);
342 greg 1.2 /* check ending */
343 greg 1.3 if (fflush(NULL) == EOF) {
344     fputs(argv[0], stderr);
345     fputs(": write error on one or more outputs\n", stderr);
346     return(1);
347     }
348 greg 1.4 if (outcnt > 0) {
349     fputs(argv[0], stderr);
350     fputs(": warning: premature EOD\n", stderr);
351     }
352 greg 1.1 return(0);
353     }