ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.7
Committed: Sat Jul 20 23:12:53 2019 UTC (4 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +19 -16 lines
Log Message:
Fixed issue with extra newline

File Contents

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