ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
Revision: 1.5
Committed: Tue Jul 16 15:59:49 2019 UTC (4 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +2 -1 lines
Log Message:
Made it so -t option sets newline if no character follows

File Contents

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