ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/rsplit.c
(Generate patch)

Comparing ray/src/cal/rsplit.c (file contents):
Revision 1.5 by greg, Tue Jul 16 15:59:49 2019 UTC vs.
Revision 1.16 by greg, Fri Jun 7 18:19:22 2024 UTC

# Line 7 | Line 7 | static const char      RCSid[] = "$Id$";
7   *      7/4/19          Greg Ward
8   */
9  
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
10   #include <ctype.h>
11  
12 + #include "rtio.h"
13   #include "platform.h"
14 + #include "paths.h"
15   #include "resolu.h"
17 #include "rtio.h"
16  
17   #define DOHEADER        1
18   #define DORESOLU        2
19  
20   #define MAXFILE         512             /* maximum number of files */
21  
22 < FILE            *output[MAXFILE];
25 < int             bytsiz[MAXFILE];
26 < short           hdrflags[MAXFILE];
27 < const char      *format[MAXFILE];
28 < int             termc[MAXFILE];
29 < int             nfiles = 0;
22 > int                     swapped = 0;    /* input is byte-swapped */
23  
24 < int             outheader = 0;          /* output header to each stream? */
24 > struct outstream {              /* structure to hold output stream info */
25 >        const char      *outspec;       /* output specification */
26 >        FILE            *output;        /* output stream */
27 >        int             ncomp;          /* component count */
28 >        int             bytsiz;         /* bytes/component if binary */
29 >        int             hdrflags;       /* header output flags */
30 >        const char      *format;        /* data format */
31 >        int             termc;          /* data separation character */
32 > }       *rofile = NULL;
33  
34 + int             nfiles = 0;     /* output file count */
35 +
36   RESOLU          ourres = {PIXSTANDARD, 0, 0};
37  
38 < char            buf[16384];
38 > char            buf[16384];             /* input buffer used in scanOK() */
39  
40  
41   /* process header line */
42 < static int
42 > int
43   headline(char *s, void *p)
44   {
45          extern const char       FMTSTR[];
46 <        int                     i = nfiles;
46 >        int                     i;
47  
48          if (strstr(s, FMTSTR) == s)
49                  return(0);              /* don't copy format */
# Line 50 | Line 53 | headline(char *s, void *p)
53                  return(0);
54          if (!strncmp(s, "NCOMP=", 6))
55                  return(0);
56 +        if ((i = isbigendian(s)) >= 0) {
57 +                swapped = (nativebigendian() != i);
58 +                return(0);
59 +        }
60 +        i = nfiles;
61          while (i--)                     /* else copy line to output streams */
62 <                if (hdrflags[i] & DOHEADER)
63 <                        fputs(s, output[i]);
62 >                if (rofile[i].hdrflags & DOHEADER)
63 >                        fputs(s, rofile[i].output);
64          return(1);
65   }
66  
67  
68   /* scan field into buffer up to and including terminating byte */
69 < static int
69 > int
70   scanOK(int termc)
71   {
72 +        int     skip_white = (termc == ' ');
73          char    *cp = buf;
74          int     c;
75  
76          while ((c = getchar()) != EOF) {
77 +                if (skip_white && isspace(c))
78 +                        continue;
79 +                skip_white = 0;
80 +                if (c == '\n' && isspace(termc))
81 +                        c = termc;      /* forgiving assumption */
82                  *cp++ = c;
83                  if (cp-buf >= sizeof(buf))
84                          break;
85 <                if (c == termc) {
85 >                if ((termc == ' ') ? isspace(c) : (c == termc)) {
86                          *cp = '\0';
87                          return(cp-buf);
88                  }
# Line 80 | Line 94 | scanOK(int termc)
94   int
95   main(int argc, char *argv[])
96   {
97 <        int             inpheader = 0;
98 <        int             inpres = 0;
85 <        int             outres = 0;
97 >        int             inpflags = 0;
98 >        int             needres = 0;
99          int             force = 0;
100          int             append = 0;
101          long            outcnt = 0;
102          int             bininp = 0;
103 +        int             nstdoutcomp = 0;
104          int             curterm = '\n';
105 +        int             curncomp = 1;
106          int             curbytes = 0;
107          int             curflags = 0;
108          const char      *curfmt = "ascii";
109 <        int     i;
109 >        int             i;
110  
111 +        rofile = (struct outstream *)calloc(argc-1, sizeof(struct outstream));
112 +        if (!rofile) {
113 +                fputs(argv[0], stderr);
114 +                fputs(": not enough memory\n", stderr);
115 +                return(1);
116 +        }
117          for (i = 1; i < argc; i++) {
118                  if (argv[i][0] == '-') {
119                          switch (argv[i][1]) {
# Line 103 | Line 124 | main(int argc, char *argv[])
124                          case 'i':
125                                  switch (argv[i][2]) {
126                                  case 'h':
127 <                                        inpheader = !inpheader;
127 >                                        inpflags ^= DOHEADER;
128                                          break;
129                                  case 'H':
130 <                                        inpres = !inpres;
130 >                                        inpflags ^= DORESOLU;
131                                          break;
132                                  default:
133                                          goto badopt;
134                                  }
135                                  break;
136                          case 'f':
137 <                                ++force;
117 <                                append = 0;
137 >                                force = !force;
138                                  break;
139                          case 'a':
140 <                                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;
140 >                                append = !append;
141                                  break;
142                          case 'x':
143                                  ourres.xr = atoi(argv[++i]);
130                                outres = 1;
144                                  break;
145                          case 'y':
146                                  ourres.yr = atoi(argv[++i]);
134                                outres = 1;
147                                  break;
148                          case 'o':
149                                  switch (argv[i][2]) {
# Line 166 | Line 178 | main(int argc, char *argv[])
178                                          break;
179                                  case 'a':
180                                          curfmt = "ascii";
181 <                                        curbytes = argv[i][3] ? -1 : 0;
181 >                                        curbytes = 0;
182                                          break;
183                                  default:
184                                          goto badopt;
185                                  }
186 <                                if (isdigit(argv[i][3]))
187 <                                        curbytes *= atoi(argv[i]+3);
188 <                                curbytes += (curbytes == -1);
177 <                                if (curbytes > (int)sizeof(buf)) {
186 >                                curncomp = isdigit(argv[i][3]) ?
187 >                                                        atoi(argv[i]+3) : 1 ;
188 >                                if (curbytes*curncomp > (int)sizeof(buf)) {
189                                          fputs(argv[0], stderr);
190                                          fputs(": output size too big\n", stderr);
191                                          return(1);
192                                  }
193 <                                if (curbytes > 0) {
183 <                                        curterm = '\0';
184 <                                        ++bininp;
185 <                                }
193 >                                bininp += (curbytes > 0);
194                                  break;
195 <                        case '\0':
196 <                                outres |= (curflags & DORESOLU);
197 <                                termc[nfiles] = curterm;
198 <                                hdrflags[nfiles] = curflags;
199 <                                output[nfiles] = stdout;
195 >                        case '\0':                      /* stdout */
196 >                                if (!nstdoutcomp) {     /* first use? */
197 >                                        needres |= (curflags & DORESOLU);
198 >                                        rofile[nfiles].hdrflags = curflags;
199 >                                }
200 >                                rofile[nfiles].output = stdout;
201                                  if (curbytes > 0)
202 <                                        SET_FILE_BINARY(output[nfiles]);
203 <                                format[nfiles] = curfmt;
204 <                                bytsiz[nfiles++] = curbytes;
202 >                                        SET_FILE_BINARY(rofile[nfiles].output);
203 >                                rofile[nfiles].termc = curterm;
204 >                                rofile[nfiles].format = curfmt;
205 >                                nstdoutcomp +=
206 >                                        rofile[nfiles].ncomp = curncomp;
207 >                                rofile[nfiles].bytsiz = curbytes;
208 >                                rofile[nfiles++].outspec = argv[i];
209                                  break;
210                          badopt:;
211                          default:
# Line 200 | Line 213 | main(int argc, char *argv[])
213                                  fputs(": bad option\n", stderr);
214                                  return(1);
215                          }
216 +                } else if (argv[i][0] == '.' && !argv[i][1]) {
217 +                        rofile[nfiles].output = NULL;           /* discard data */
218 +                        rofile[nfiles].termc = curterm;
219 +                        rofile[nfiles].format = curfmt;
220 +                        rofile[nfiles].ncomp = curncomp;
221 +                        rofile[nfiles].bytsiz = curbytes;
222 +                        rofile[nfiles++].outspec = argv[i];
223                  } else if (argv[i][0] == '!') {
224 <                        outres |= (curflags & DORESOLU);
225 <                        termc[nfiles] = curterm;
226 <                        hdrflags[nfiles] = curflags;
227 <                        if ((output[nfiles] = popen(argv[i]+1, "w")) == NULL) {
224 >                        needres |= (curflags & DORESOLU);
225 >                        rofile[nfiles].hdrflags = curflags;
226 >                        rofile[nfiles].termc = curterm;
227 >                        if ((rofile[nfiles].output = popen(argv[i]+1, "w")) == NULL) {
228                                  fputs(argv[i], stderr);
229                                  fputs(": cannot start command\n", stderr);
230                                  return(1);
231                          }
232                          if (curbytes > 0)
233 <                                SET_FILE_BINARY(output[nfiles]);
234 <                        format[nfiles] = curfmt;
235 <                        bytsiz[nfiles++] = curbytes;
233 >                                SET_FILE_BINARY(rofile[nfiles].output);
234 >                        rofile[nfiles].format = curfmt;
235 >                        rofile[nfiles].ncomp = curncomp;
236 >                        rofile[nfiles].bytsiz = curbytes;
237 >                        rofile[nfiles++].outspec = argv[i];
238                  } else {
239 <                        outres |= (curflags & DORESOLU);
240 <                        termc[nfiles] = curterm;
241 <                        hdrflags[nfiles] = curflags;
239 >                        int     j = nfiles;
240 >                        while (j--)                     /* check duplicates */
241 >                                if (!strcmp(argv[i], rofile[j].outspec)) {
242 >                                        fputs(argv[0], stderr);
243 >                                        fputs(": duplicate output: ", stderr);
244 >                                        fputs(argv[i], stderr);
245 >                                        fputc('\n', stderr);
246 >                                        return(1);
247 >                                }
248 >                        if (append & (curflags != 0)) {
249 >                                fputs(argv[0], stderr);
250 >                                fputs(": -a option incompatible with -oh and -oH\n",
251 >                                                stderr);
252 >                                return(1);
253 >                        }
254 >                        needres |= (curflags & DORESOLU);
255 >                        rofile[nfiles].hdrflags = curflags;
256 >                        rofile[nfiles].termc = curterm;
257                          if (!append & !force && access(argv[i], F_OK) == 0) {
258                                  fputs(argv[i], stderr);
259                                  fputs(": file exists -- use -f to overwrite\n",
260                                                  stderr);
261                                  return(1);
262                          }
263 <                        output[nfiles] = fopen(argv[i], append ? "a" : "w");
264 <                        if (output[nfiles] == NULL) {
263 >                        rofile[nfiles].output = fopen(argv[i], append ? "a" : "w");
264 >                        if (!rofile[nfiles].output) {
265                                  fputs(argv[i], stderr);
266                                  fputs(": cannot open for output\n", stderr);
267                                  return(1);
268                          }
269                          if (curbytes > 0)
270 <                                SET_FILE_BINARY(output[nfiles]);
271 <                        format[nfiles] = curfmt;
272 <                        bytsiz[nfiles++] = curbytes;
270 >                                SET_FILE_BINARY(rofile[nfiles].output);
271 >                        rofile[nfiles].format = curfmt;
272 >                        rofile[nfiles].ncomp = curncomp;
273 >                        rofile[nfiles].bytsiz = curbytes;
274 >                        rofile[nfiles++].outspec = argv[i];
275                  }
237                if (nfiles >= MAXFILE) {
238                        fputs(argv[0], stderr);
239                        fputs(": too many output streams\n", stderr);
240                        return(1);
241                }
276          }
277          if (!nfiles) {
278                  fputs(argv[0], stderr);
279                  fputs(": no output streams\n", stderr);
280                  return(1);
281 +        }                                       /* reduce array to size we need */
282 +        rofile = (struct outstream *)realloc(rofile, nfiles*sizeof(struct outstream));
283 +        if (!rofile) {
284 +                fputs(argv[0], stderr);
285 +                fputs(": realloc() failed!\n", stderr);
286 +                return(1);
287          }
288          if (bininp)                             /* binary input? */
289                  SET_FILE_BINARY(stdin);
290   #ifdef getc_unlocked                            /* avoid lock/unlock overhead */
291          flockfile(stdin);
292          for (i = nfiles; i--; )
293 <                flockfile(output[i]);
293 >                if (rofile[i].output != NULL)
294 >                        ftrylockfile(rofile[i].output);
295   #endif
296                                                  /* load/copy header */
297 <        if (inpheader && getheader(stdin, headline, NULL) < 0) {
297 >        if (inpflags & DOHEADER && getheader(stdin, headline, NULL) < 0) {
298                  fputs(argv[0], stderr);
299 <                fputs(": cannot get header from standard input\n",
299 >                fputs(": cannot read header from standard input\n",
300                                  stderr);
301                  return(1);
302          }
303                                                  /* handle resolution string */
304 <        if (inpres && !fgetsresolu(&ourres, stdin)) {
304 >        if (inpflags & DORESOLU && !fgetsresolu(&ourres, stdin)) {
305                  fputs(argv[0], stderr);
306 <                fputs(": cannot get resolution string from standard input\n",
266 <                                stderr);
306 >                fputs(": bad resolution string on standard input\n", stderr);
307                  return(1);
308          }
309 <        if (outres && (ourres.xr <= 0) | (ourres.yr <= 0)) {
309 >        if (needres && (ourres.xr <= 0) | (ourres.yr <= 0)) {
310                  fputs(argv[0], stderr);
311                  fputs(": -oH option requires -iH or -x and -y options\n", stderr);
312                  return(1);
# Line 281 | Line 321 | main(int argc, char *argv[])
321                  }
322          }
323          for (i = 0; i < nfiles; i++) {          /* complete headers */
324 <                if (hdrflags[i] & DOHEADER) {
325 <                        if (!inpheader)
326 <                                newheader("RADIANCE", output[i]);
327 <                        printargs(argc, argv, output[i]);
328 <                        if (format[i] != NULL)
329 <                                fputformat(format[i], output[i]);
330 <                        fputc('\n', output[i]);
324 >                if (rofile[i].hdrflags & DOHEADER) {
325 >                        if (!(inpflags & DOHEADER))
326 >                                newheader("RADIANCE", rofile[i].output);
327 >                        printargs(argc, argv, rofile[i].output);
328 >                        fprintf(rofile[i].output, "NCOMP=%d\n", rofile[i].output==stdout ?
329 >                                                nstdoutcomp : rofile[i].ncomp);
330 >                        if (rofile[i].format != NULL) {
331 >                                extern const char  BIGEND[];
332 >                                if (rofile[i].bytsiz > 1) {
333 >                                        fputs(BIGEND, rofile[i].output);
334 >                                        fputs(nativebigendian() ^ swapped ?
335 >                                                "1\n" : "0\n", rofile[i].output);
336 >                                }
337 >                                fputformat(rofile[i].format, rofile[i].output);
338 >                        }
339 >                        fputc('\n', rofile[i].output);
340                  }
341 <                if (hdrflags[i] & DORESOLU)
342 <                        fputsresolu(&ourres, output[i]);
341 >                if (rofile[i].hdrflags & DORESOLU)
342 >                        fputsresolu(&ourres, rofile[i].output);
343          }
344          do {                                    /* main loop */
345                  for (i = 0; i < nfiles; i++) {
346 <                        if (bytsiz[i] > 0) {            /* binary output */
347 <                                if (getbinary(buf, bytsiz[i], 1, stdin) < 1)
346 >                        if (rofile[i].bytsiz > 0) {             /* binary output */
347 >                                if (getbinary(buf, rofile[i].bytsiz, rofile[i].ncomp,
348 >                                                        stdin) != rofile[i].ncomp)
349                                          break;
350 <                                if (putbinary(buf, bytsiz[i], 1, output[i]) != 1)
350 >                                if (rofile[i].output != NULL &&
351 >                                            putbinary(buf, rofile[i].bytsiz, rofile[i].ncomp,
352 >                                                        rofile[i].output) != rofile[i].ncomp)
353                                          break;
354 <                        } else if (bytsiz[i] < 0) {     /* N-field output */
355 <                                int     n = -bytsiz[i];
354 >                        } else if (rofile[i].ncomp > 1) {       /* N-field output */
355 >                                int     n = rofile[i].ncomp;
356                                  while (n--) {
357 <                                        if (!scanOK(termc[i]))
357 >                                        if (!scanOK(rofile[i].termc))
358                                                  break;
359 <                                        if (fputs(buf, output[i]) == EOF)
359 >                                        if (rofile[i].output != NULL &&
360 >                                                    fputs(buf, rofile[i].output) == EOF)
361                                                  break;
362                                  }
363                                  if (n >= 0)             /* fell short? */
364                                          break;
365 <                                if (termc[i] != '\n')   /* add EOL if none */
366 <                                        fputc('\n', output[i]);
365 >                                if ((rofile[i].output != NULL) &  /* add EOL if none */
366 >                                                (rofile[i].termc != '\n'))
367 >                                        fputc('\n', rofile[i].output);
368                          } else {                        /* 1-field output */
369 <                                if (!scanOK(termc[i]))
369 >                                if (!scanOK(rofile[i].termc))
370                                          break;
371 <                                if (fputs(buf, output[i]) == EOF)
372 <                                        break;
373 <                                if (termc[i] != '\n')   /* add EOL if none */
374 <                                        fputc('\n', output[i]);
371 >                                if (rofile[i].output != NULL) {
372 >                                        if (fputs(buf, rofile[i].output) == EOF)
373 >                                                break;
374 >                                        if (rofile[i].termc != '\n')    /* add EOL? */
375 >                                                fputc('\n', rofile[i].output);
376 >                                }
377 >                        }
378 >                                                        /* skip input EOL? */
379 >                        if (!bininp && rofile[nfiles-1].termc != '\n') {
380 >                                int     c = getchar();
381 >                                if ((c != '\n') & (c != EOF))
382 >                                        ungetc(c, stdin);
383                          }
384                  }
385                  if (i < nfiles)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines