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.10 by greg, Wed Aug 14 21:00:14 2019 UTC vs.
Revision 1.17 by greg, Fri Jun 7 20:26:53 2024 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines