--- ray/src/common/header.c 2009/03/12 18:37:24 2.24 +++ ray/src/common/header.c 2022/03/14 22:57:24 2.47 @@ -1,22 +1,23 @@ #ifndef lint -static const char RCSid[] = "$Id: header.c,v 2.24 2009/03/12 18:37:24 greg Exp $"; +static const char RCSid[] = "$Id: header.c,v 2.47 2022/03/14 22:57:24 greg Exp $"; #endif /* * header.c - routines for reading and writing information headers. * - * Externals declared in resolu.h + * Externals declared in rtio.h * * newheader(t,fp) start new information header identified by string t - * isheadid(s) returns true if s is a header id line * headidval(r,s) copy header identifier value in s to r - * dateval(t,s) get capture date value - * isdate(s) returns true if s is a date line - * fputdate(t,fp) put out the given capture date and time + * dateval(t,s) get capture date value as UTC + * gmtval(t,s) get GMT as UTC + * fputdate(t,fp) put out the given UTC * fputnow(fp) put out the current date and time * printargs(ac,av,fp) print an argument list to fp, followed by '\n' - * isformat(s) returns true if s is of the form "FORMAT=*" * formatval(r,s) copy the format value in s to r * fputformat(s,fp) write "FORMAT=%s" to fp + * nativebigendian() are we native on big-endian machine? + * isbigendian(s) header line matches "BigEndian=1" (-1 if irrelevant) + * fputendian(fp) write native endianness in BigEndian= line * getheader(fp,f,p) read header from fp, calling f(s,p) on each line * globmatch(pat, str) check for glob match of str against pat * checkheader(i,p,o) check header format from i against p and copy to o @@ -28,39 +29,46 @@ static const char RCSid[] = "$Id: header.c,v 2.24 2009 #include +#include "tiff.h" /* for int32 */ #include "rtio.h" +#include "color.h" #include "resolu.h" #define MAXLINE 2048 -char HDRSTR[] = "#?"; /* information header magic number */ +extern time_t timegm(struct tm *tm); -char FMTSTR[] = "FORMAT="; /* format identifier */ +const char HDRSTR[] = "#?"; /* information header magic number */ -char TMSTR[] = "CAPDATE="; /* capture date identifier */ +const char FMTSTR[] = "FORMAT="; /* format identifier */ +const char TMSTR[] = "CAPDATE="; /* capture date identifier */ +const char GMTSTR[] = "GMT="; /* GMT identifier */ + +const char BIGEND[] = "BigEndian="; /* big-endian variable */ + static gethfunc mycheck; -extern void +void newheader( /* identifying line of information header */ - char *s, - register FILE *fp + const char *s, + FILE *fp ) { fputs(HDRSTR, fp); fputs(s, fp); - putc('\n', fp); + fputc('\n', fp); } -extern int +int headidval( /* get header id (return true if is id) */ - register char *r, - register char *s + char *r, + const char *s ) { - register char *cp = HDRSTR; + const char *cp = HDRSTR; while (*cp) if (*cp++ != *s++) return(0); if (r == NULL) return(1); @@ -70,23 +78,14 @@ headidval( /* get header id (return true if is id) * } -extern int -isheadid( /* check to see if line is header id */ - char *s -) -{ - return(headidval(NULL, s)); -} - - -extern int -dateval( /* get capture date value */ +int +dateval( /* convert capture date line to UTC */ time_t *tloc, - char *s + const char *s ) { struct tm tms; - register char *cp = TMSTR; + const char *cp = TMSTR; while (*cp) if (*cp++ != *s++) return(0); while (isspace(*s)) s++; @@ -105,31 +104,53 @@ dateval( /* get capture date value */ } -extern int -isdate( /* is the given line a capture date? */ - char *s +int +gmtval( /* convert GMT date line to UTC */ + time_t *tloc, + const char *s ) { - return(dateval(NULL, s)); + struct tm tms; + const char *cp = GMTSTR; + + while (*cp) if (*cp++ != *s++) return(0); + while (isspace(*s)) s++; + if (!*s) return(0); + if (sscanf(s, "%d:%d:%d %d:%d:%d", + &tms.tm_year, &tms.tm_mon, &tms.tm_mday, + &tms.tm_hour, &tms.tm_min, &tms.tm_sec) != 6) + return(0); + if (tloc == NULL) + return(1); + tms.tm_mon--; + tms.tm_year -= 1900; + *tloc = timegm(&tms); + return(1); } -extern void -fputdate( /* write out the given time value */ +void +fputdate( /* write out the given time value (local & GMT) */ time_t tv, FILE *fp ) { - struct tm *tm = localtime(&tv); - if (tm == NULL) - return; - fprintf(fp, "%s %04d:%02d:%02d %02d:%02d:%02d\n", TMSTR, - tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); + struct tm *tms; + + tms = localtime(&tv); + if (tms != NULL) + fprintf(fp, "%s %04d:%02d:%02d %02d:%02d:%02d\n", TMSTR, + tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday, + tms->tm_hour, tms->tm_min, tms->tm_sec); + tms = gmtime(&tv); + if (tms != NULL) + fprintf(fp, "%s %04d:%02d:%02d %02d:%02d:%02d\n", GMTSTR, + tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday, + tms->tm_hour, tms->tm_min, tms->tm_sec); } -extern void +void fputnow( /* write out the current time */ FILE *fp ) @@ -140,13 +161,21 @@ fputnow( /* write out the current time */ } -extern void +void printargs( /* print arguments to a file */ int ac, char **av, FILE *fp ) { +#if defined(_WIN32) || defined(_WIN64) + extern char *fixargv0(char *arg0); + char myav0[128]; + /* clean up Windows executable path */ + if (ac-- <= 0) return; + fputs(fixargv0(strcpy(myav0, *av++)), fp); + fputc(ac ? ' ' : '\n', fp); +#endif while (ac-- > 0) { fputword(*av++, fp); fputc(ac ? ' ' : '\n', fp); @@ -154,13 +183,14 @@ printargs( /* print arguments to a file */ } -extern int +int formatval( /* get format value (return true if format) */ - register char *r, - register char *s + char fmt[MAXFMTLEN], + const char *s ) { - register char *cp = FMTSTR; + const char *cp = FMTSTR; + char *r = fmt; while (*cp) if (*cp++ != *s++) return(0); while (isspace(*s)) s++; @@ -168,65 +198,130 @@ formatval( /* get format value (return true if forma if (r == NULL) return(1); do *r++ = *s++; - while(*s && !isspace(*s)); + while (*s && !isspace(*s) && r-fmt < MAXFMTLEN-1); *r = '\0'; return(1); } -extern int -isformat( /* is line a format line? */ - char *s +void +fputformat( /* put out a format value */ + const char *s, + FILE *fp ) { - return(formatval(NULL, s)); + int align = 0; + + fputs(FMTSTR, fp); + fputs(s, fp); + /* pad to align binary type for mmap() */ + if (globmatch(PICFMT, s)) + align = 0; /* not needed for picture data */ + else if (!strncmp("float", s, 5)) + align = sizeof(float); + else if (!strncmp("double", s, 6)) + align = sizeof(double); + else if (!strncmp("16-bit", s, 6)) + align = 2; + else if (!strncmp("32-bit", s, 6)) + align = 4; + else if (!strncmp("64-bit", s, 6)) + align = 8; + if (align) { + long pos = ftell(fp); + if (pos >= 0) { + pos = (pos + 2) % align; + if (pos) align -= pos; + else align = 0; + } else + align = 0; + } + while (align-- > 0) + putc(' ', fp); + fputc('\n', fp); } -extern void -fputformat( /* put out a format value */ - char *s, - FILE *fp +int +nativebigendian() /* are we native on a big-endian machine? */ +{ + union { int32 i; char c[4]; } u; + + u.i = 1; + + return(u.c[0] == 0); +} + + +int +isbigendian( /* header line says "BigEndian=1" (-1 if irrelevant) */ + const char *s ) { - fputs(FMTSTR, fp); - fputs(s, fp); - putc('\n', fp); + const char *be = BIGEND; + + while ((*s != '\0') & (*be != '=') && *s++ == *be) + ++be; + if (*be != '=') + return(-1); /* irrelevant */ + while (isspace(*s)) + s++; + if (*s++ != '=') + return(-1); + while (isspace(*s)) + s++; + return(*s == '1'); } -extern int +void +fputendian( /* write native endianness in BigEndian= line */ + FILE *fp +) +{ + fputs(BIGEND, fp); + if (nativebigendian()) + fputs("1\n", fp); + else + fputs("0\n", fp); +} + + +int getheader( /* get header from file */ FILE *fp, gethfunc *f, void *p ) { + int rtotal = 0; char buf[MAXLINE]; + int firstc = fgetc(fp); + if (!isprint(firstc)) + return(-1); /* messed up */ + ungetc(firstc, fp); for ( ; ; ) { + int rval = 0; buf[MAXLINE-2] = '\n'; if (fgets(buf, MAXLINE, fp) == NULL) return(-1); - if (buf[0] == '\n') - return(0); -#ifdef MSDOS - if (buf[0] == '\r' && buf[1] == '\n') - return(0); -#endif + if (buf[buf[0]=='\r'] == '\n') /* end of header? */ + return(rtotal); if (buf[MAXLINE-2] != '\n') { ungetc(buf[MAXLINE-2], fp); /* prevent false end */ buf[MAXLINE-2] = '\0'; } - if (f != NULL && (*f)(buf, p) < 0) + if (f != NULL && (rval = (*f)(buf, p)) < 0) return(-1); + rtotal += rval; } } struct check { FILE *fp; - char fs[64]; + char fs[MAXFMTLEN]; }; @@ -236,18 +331,19 @@ mycheck( /* check a header line for format info. */ void *cp ) { - if (!formatval(((struct check*)cp)->fs, s) - && ((struct check*)cp)->fp != NULL) { - fputs(s, ((struct check*)cp)->fp); - } + struct check *scp = (struct check *)cp; + + if (!formatval(scp->fs, s) && scp->fp != NULL) + return(fputs(s, scp->fp)); + return(0); } -extern int +int globmatch( /* check for match of s against pattern p */ - register char *p, - register char *s + const char *p, + const char *s ) { int setmatch; @@ -261,31 +357,32 @@ globmatch( /* check for match of s against pattern p case '*': /* match any string */ while (p[1] == '*') p++; do - if ( (p[1]=='?' || p[1]==*s) && + if ( (p[1]=='?') | (p[1]==*s) && globmatch(p+1,s) ) return(1); while (*s++); return(0); case '[': /* character set */ - setmatch = *s == *++p; + setmatch = (*s == *++p); if (!*p) return(0); while (*++p != ']') { if (!*p) return(0); if (*p == '-') { - setmatch += p[-1] <= *s && *s <= p[1]; + setmatch += (p[-1] <= *s) & (*s <= p[1]); if (!*++p) break; } else - setmatch += *p == *s; + setmatch += (*p == *s); } if (!setmatch) return(0); s++; break; case '\\': /* literal next */ - p++; + if (!*++p) + return(0); /* fall through */ default: /* normal character */ if (*p != *s) @@ -312,15 +409,15 @@ globmatch( /* check for match of s against pattern p * if fout is not NULL. */ -extern int +int checkheader( FILE *fin, - char *fmt, + char fmt[MAXFMTLEN], FILE *fout ) { struct check cdat; - register char *cp; + char *cp; cdat.fp = fout; cdat.fs[0] = '\0';