| 19 | 
  | 
 | 
| 20 | 
  | 
#define MAXFILE         512             /* maximum number of files */ | 
| 21 | 
  | 
 | 
| 22 | 
< | 
static int              swapped = 0;    /* input is byte-swapped */ | 
| 22 | 
> | 
int                     swapped = 0;    /* input is byte-swapped */ | 
| 23 | 
  | 
 | 
| 24 | 
< | 
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; | 
| 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 | 
< | 
static RESOLU   ourres = {PIXSTANDARD, 0, 0}; | 
| 34 | 
> | 
int             nfiles = 0;     /* output file count */ | 
| 35 | 
  | 
 | 
| 36 | 
< | 
static char     buf[16384];             /* input buffer used in scanOK() */ | 
| 36 | 
> | 
RESOLU          ourres = {PIXSTANDARD, 0, 0}; | 
| 37 | 
  | 
 | 
| 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[]; | 
| 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 | 
  | 
                } | 
| 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]) { | 
| 178 | 
  | 
                                        break; | 
| 179 | 
  | 
                                case 'a': | 
| 180 | 
  | 
                                        curfmt = "ascii"; | 
| 181 | 
< | 
                                        curbytes = -1; | 
| 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); | 
| 170 | 
< | 
                                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 | 
  | 
                                bininp += (curbytes > 0); | 
| 194 | 
  | 
                                break; | 
| 195 | 
< | 
                        case '\0': | 
| 196 | 
< | 
                                needres |= (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: | 
| 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 | 
  | 
                        needres |= (curflags & DORESOLU); | 
| 225 | 
< | 
                        termc[nfiles] = curterm; | 
| 226 | 
< | 
                        hdrflags[nfiles] = curflags; | 
| 227 | 
< | 
                        if ((output[nfiles] = popen(argv[i]+1, "w")) == NULL) { | 
| 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 | 
+ | 
                        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", | 
| 252 | 
  | 
                                return(1); | 
| 253 | 
  | 
                        } | 
| 254 | 
  | 
                        needres |= (curflags & DORESOLU); | 
| 255 | 
< | 
                        termc[nfiles] = curterm; | 
| 256 | 
< | 
                        hdrflags[nfiles] = curflags; | 
| 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 | 
  | 
                } | 
| 233 | 
– | 
                if (nfiles >= MAXFILE) { | 
| 234 | 
– | 
                        fputs(argv[0], stderr); | 
| 235 | 
– | 
                        fputs(": too many output streams\n", stderr); | 
| 236 | 
– | 
                        return(1); | 
| 237 | 
– | 
                } | 
| 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 (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 (inpflags & DORESOLU && !fgetsresolu(&ourres, stdin)) { | 
| 305 | 
  | 
                fputs(argv[0], stderr); | 
| 306 | 
< | 
                fputs(": cannot get resolution string from standard input\n", | 
| 262 | 
< | 
                                stderr); | 
| 306 | 
> | 
                fputs(": bad resolution string on standard input\n", stderr); | 
| 307 | 
  | 
                return(1); | 
| 308 | 
  | 
        } | 
| 309 | 
  | 
        if (needres && (ourres.xr <= 0) | (ourres.yr <= 0)) { | 
| 321 | 
  | 
                } | 
| 322 | 
  | 
        } | 
| 323 | 
  | 
        for (i = 0; i < nfiles; i++) {          /* complete headers */ | 
| 324 | 
< | 
                if (hdrflags[i] & DOHEADER) { | 
| 324 | 
> | 
                if (rofile[i].hdrflags & DOHEADER) { | 
| 325 | 
  | 
                        if (!(inpflags & DOHEADER)) | 
| 326 | 
< | 
                                newheader("RADIANCE", output[i]); | 
| 327 | 
< | 
                        printargs(argc, argv, output[i]); | 
| 328 | 
< | 
                        if (format[i] != NULL) { | 
| 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 ((format[i][0] == 'f') | | 
| 333 | 
< | 
                                                (format[i][0] == 'd')) { | 
| 288 | 
< | 
                                        fputs(BIGEND, output[i]); | 
| 332 | 
> | 
                                if (rofile[i].bytsiz > 1) { | 
| 333 | 
> | 
                                        fputs(BIGEND, rofile[i].output); | 
| 334 | 
  | 
                                        fputs(nativebigendian() ^ swapped ? | 
| 335 | 
< | 
                                                "1\n" : "0\n", output[i]); | 
| 335 | 
> | 
                                                "1\n" : "0\n", rofile[i].output); | 
| 336 | 
  | 
                                } | 
| 337 | 
< | 
                                fputformat(format[i], output[i]); | 
| 337 | 
> | 
                                fputformat(rofile[i].format, rofile[i].output); | 
| 338 | 
  | 
                        } | 
| 339 | 
< | 
                        fputc('\n', output[i]); | 
| 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 && termc[nfiles-1] != '\n') { | 
| 379 | 
> | 
                        if (!bininp && rofile[nfiles-1].termc != '\n') { | 
| 380 | 
  | 
                                int     c = getchar(); | 
| 381 | 
  | 
                                if ((c != '\n') & (c != EOF)) | 
| 382 | 
  | 
                                        ungetc(c, stdin); |