diff options
Diffstat (limited to 'shared/common')
-rw-r--r-- | shared/common/binport.c | 566 | ||||
-rw-r--r-- | shared/common/binport.h | 6 | ||||
-rw-r--r-- | shared/common/port.c | 295 |
3 files changed, 663 insertions, 204 deletions
diff --git a/shared/common/binport.c b/shared/common/binport.c index c886955..72e89c7 100644 --- a/shared/common/binport.c +++ b/shared/common/binport.c @@ -1,17 +1,20 @@ -/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. +/* Copyright (c) 1997-2004 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +/* LATER verify endianness transparency */ + #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <string.h> +#include <math.h> #define BINPORT_MAXSTRING 256 #define BINPORT_SYMGROW 64 #ifndef BINPORT_STANDALONE -/* load max binary file to a binbuf */ +/* load a max binary file into a Pd binbuf */ #include "m_pd.h" @@ -24,7 +27,6 @@ #define BINPORT_VERBOSE //#define BINPORT_DEBUG - #endif #include "binport.h" @@ -41,12 +43,14 @@ static void binport_error(char *fmt, ...) static void binport_warning(char *fmt, ...) { +#if defined (BINPORT_STANDALONE) || defined(BINPORT_VERBOSE) va_list ap; va_start(ap, fmt); fprintf(stderr, "warning (binport): "); vfprintf(stderr, fmt, ap); putc('\n', stderr); va_end(ap); +#endif } static void binport_bug(char *fmt, ...) @@ -59,6 +63,17 @@ static void binport_bug(char *fmt, ...) va_end(ap); } +static void binport_failure(char *filename) +{ + binport_error("\"%s\" doesn't look like a patch file", filename); +} + +static void binpold_failure(char *filename) +{ + binport_error("tried reading \"%s\" as an old format file, but failed", + filename); +} + #ifdef BINPORT_STANDALONE typedef int t_int; @@ -171,62 +186,90 @@ t_symbol *gensym(char *s) #endif /* end of Pd API */ -/* clumsy... LATER find a better way */ -#ifdef BINPORT_STANDALONE -#define A_INT (A_CANT + 1) -#endif +enum { + BINPORT_NULLTYPE, + BINPORT_INTTYPE = 1, BINPORT_FLOATTYPE, BINPORT_SYMTYPE, + BINPORT_DEFINTTYPE = 5, BINPORT_DEFFLOATTYPE, BINPORT_DEFSYMTYPE, + BINPORT_SEMITYPE = 10, BINPORT_COMMATYPE, + BINPORT_DOLLARTYPE, BINPORT_DOLLSYMTYPE +}; -static int binport_getint(t_atom *ap) -{ -#ifdef A_INT - return (*(int *)&ap->a_w); -#else - return (ap->a_w.w_float); -#endif -} +/* We use A_INT atom type not only for listing, but for import too -- + the parser passes ints to individual token handlers, so that any + required conversion has to be done during Pd message generation. */ +#define A_INT A_DEFFLOAT -static void binport_setint(t_atom *ap, int i) +static int binport_readbuf(FILE *fp, char *buf, size_t sz) { -#ifdef A_INT - ap->a_type = A_INT; - *(int *)&ap->a_w = i; -#else - SETFLOAT(ap, (float)i); -#endif + return (fread(buf, 1, sz, fp) == sz ? sz : 0); } -static void binport_setfloat(t_atom *ap, float f) +static int binport_readbyte(FILE *fp, unsigned char *buf) { - ap->a_type = A_FLOAT; - ap->a_w.w_float = f; + int c; + if ((c = fgetc(fp)) == EOF) + return (0); + *buf = (unsigned char)c; + return (1); } -typedef struct _binport +static int binport_readint(FILE *fp, int *iptr) { - FILE *b_fp; - int b_nsymbols; - int b_symsize; - t_symbol **b_symtable; -} t_binport; - -static int binport_getbuf(t_binport *bp, char *buf, size_t sz) -{ - return (fread(buf, 1, sz, bp->b_fp) == sz); + unsigned char word[4]; + if (fread(word, 1, 4, fp) == 4) + { + *iptr = ((word[0] << 24) | (word[1] << 16) | (word[2] << 8) | word[3]); + return (4); + } + else return (0); } -static int binport_getbyte(t_binport *bp, unsigned char *buf) +/* LATER more testing */ +/* make it binpold_readfloat() */ +static int binport_readfloat(FILE *fp, float *fptr) { - int c; - if ((c = fgetc(bp->b_fp)) == EOF) - return (0); - *buf = (unsigned char)c; - return (1); + unsigned char word[10]; + if (fread(word, 1, 10, fp) == 10) + { + int ex; + unsigned hi, lo; + ex = ((word[0] & 0x7F) << 8) | word[1]; + hi = ((unsigned)word[2] << 24) | ((unsigned)word[3] << 16) | + ((unsigned)word[4] << 8) | (unsigned)word[5]; + lo = ((unsigned)word[6] << 24) | ((unsigned)word[7] << 16) | + ((unsigned)word[8] << 8) | (unsigned)word[9]; + if (ex == 0x7FFF) + { + binport_warning("NaN atom bashed to zero"); + *fptr = 0.; + } + else if (ex || hi || lo) + { + double d; + ex -= 0x401e; + hi = ((hi - 0x7fffffff) - 1) + ((float)0x7fffffff + 1.); + lo = ((lo - 0x7fffffff) - 1) + ((float)0x7fffffff + 1.); + d = ldexp(hi, ex) + ldexp(lo, ex - 32); + *fptr = ((word[0] & 0x80) ? -(float)d : (float)d); + } + else *fptr = 0.; +#ifdef BINPORT_DEBUG + fprintf(stderr, "%02x%02x", (int)word[0], (int)word[1]); + fprintf(stderr, " %02x%02x%02x%02x", + (int)word[2], (int)word[3], (int)word[4], (int)word[5]); + fprintf(stderr, " %02x%02x%02x%02x", + (int)word[6], (int)word[7], (int)word[8], (int)word[9]); + fprintf(stderr, " == %g\n", *fptr); +#endif + return (10); + } + else return (0); } -static int binport_getstring(t_binport *bp, char *buf) +static int binport_readstring(FILE *fp, char *buf) { - int c, i = 0; - while (c = fgetc(bp->b_fp)) + int c, i = 1; + while (c = fgetc(fp)) { if (c == EOF) return (0); @@ -236,9 +279,229 @@ static int binport_getstring(t_binport *bp, char *buf) *buf = '\0'; if (i >= BINPORT_MAXSTRING) binport_warning("symbol string too long, skipped"); + return (i); +} + +typedef struct _binpold +{ + FILE *o_fp; + int o_natoms; + int o_bodysize; + int o_nsymbols; + int o_symbolid; + int o_ndx; + t_atom *o_atombuf; +} t_binpold; + +#define BINPOLD_NATOMTYPES 16 +#define BINPOLD_MAXATOMS 1000000 /* LATER rethink */ + +static t_atomtype binpold_atomtypes[BINPOLD_NATOMTYPES] = { + A_NULL, A_INT, A_FLOAT, A_SYMBOL, + A_CANT, A_CANT, A_CANT, A_CANT, A_CANT, A_CANT, + A_SEMI, A_COMMA, A_DOLLAR, A_CANT, A_CANT, A_CANT +}; + +static int binpold_gettype(t_binpold *old, t_atom *ap) +{ + int typecode; + if ((typecode = fgetc(old->o_fp)) != EOF) + { + if (typecode > 0 && typecode < BINPOLD_NATOMTYPES) + { + ap->a_type = binpold_atomtypes[typecode]; + if (ap->a_type != A_CANT) + return (1); + else binport_warning("unsupported type of atom %d: %d", + old->o_ndx, typecode); + } + else binport_warning("bad type of atom %d: %d", old->o_ndx, typecode); + } + else binport_warning("failed reading type of atom %d", old->o_ndx); + return (0); +} + +static int binpold_getvalue(t_binpold *old, t_atom *ap, int *countp) +{ + int ival; + float fval; + *countp = 0; + switch (ap->a_type) + { + case A_INT: + case A_SYMBOL: + if (*countp = binport_readint(old->o_fp, &ival)) + ap->a_w.w_index = ival; + else + goto valuefailed; + if (ap->a_type == A_SYMBOL) + { + if (ival >= old->o_nsymbols) + old->o_nsymbols = ival + 1; + ap->a_type = A_DEFSYM; /* invalidate, until w_symbol is known */ + } + break; + case A_FLOAT: + if (*countp = binport_readfloat(old->o_fp, &fval)) + ap->a_w.w_float = fval; + else + goto valuefailed; + break; + case A_SEMI: + case A_COMMA: + break; + case A_DOLLAR: + if (*countp = binport_readint(old->o_fp, &ival)) + ap->a_w.w_index = ival; + else + goto valuefailed; + break; + default: + goto valuefailed; + } + return (1); +valuefailed: + binport_warning("failed reading value of atom %d (type %d)", + old->o_ndx, ap->a_type); + return (0); +} + +static int binpold_load(t_binpold *old) +{ + char buf[BINPORT_MAXSTRING]; + t_atom *ap; + int total; +#ifdef BINPORT_DEBUG + fprintf(stderr, "old format: %d atoms, %d-byte chunk of atom values\n", + old->o_natoms, old->o_bodysize); +#endif + for (old->o_ndx = 0, ap = old->o_atombuf; + old->o_ndx < old->o_natoms; old->o_ndx++, ap++) + if (!binpold_gettype(old, ap)) + return (0); + old->o_nsymbols = 0; + total = 0; + for (old->o_ndx = 0, ap = old->o_atombuf; + old->o_ndx < old->o_natoms; old->o_ndx++, ap++) + { + int count; + if (!binpold_getvalue(old, ap, &count)) + return (0); + total += count; + } + if (total != old->o_bodysize) + { + binport_warning("actual chunk size %d inconsistent with declared %d", + total, old->o_bodysize); + return (0); + } + for (old->o_symbolid = 0; + old->o_symbolid < old->o_nsymbols; old->o_symbolid++) + { + if (binport_readstring(old->o_fp, buf)) + { + t_symbol *s = gensym(buf); + for (old->o_ndx = 0, ap = old->o_atombuf; + old->o_ndx < old->o_natoms; old->o_ndx++, ap++) + { + if (ap->a_type == A_DEFSYM && + ap->a_w.w_index == old->o_symbolid) + { + ap->a_type = A_SYMBOL; + ap->a_w.w_symbol = s; + } + } + } + else + { + binport_warning("failed reading string for symbol %d", + old->o_symbolid); + return (0); + } + } + for (old->o_ndx = 0, ap = old->o_atombuf; + old->o_ndx < old->o_natoms; old->o_ndx++, ap++) + { + if (ap->a_type == A_DEFSYM) + { + binport_warning("unknown string for symbol %d", ap->a_w.w_index); + return (0); + } + else if (ap->a_type == A_DOLLAR) + { + sprintf(buf, "#%d", ap->a_w.w_index); + ap->a_type = A_SYMBOL; + ap->a_w.w_symbol = gensym(buf); + } + /* CHECKME A_DOLLSYM */ + } return (1); } +static void binpold_free(t_binpold *old) +{ + if (old->o_fp) + fclose(old->o_fp); + if (old->o_atombuf) + freebytes(old->o_atombuf, old->o_natoms * sizeof(*old->o_atombuf)); + freebytes(old, sizeof(*old)); +} + +static t_binpold *binpold_new(FILE *fp) +{ + int natoms, bodysize; + if (binport_readint(fp, &natoms)) + { + if (natoms < 0 || natoms > BINPOLD_MAXATOMS) + binport_warning("bad number of atoms: %d", natoms); + else if (binport_readint(fp, &bodysize)) + { + if (bodysize < 0) + binport_warning("negative chunk size: %d", bodysize); + else + { + t_binpold *old = getbytes(sizeof(*old)); + old->o_fp = fp; + old->o_natoms = natoms; + old->o_bodysize = bodysize; + if (!(old->o_atombuf = + getbytes(old->o_natoms * sizeof(*old->o_atombuf)))) + { + binport_error("could not allocate %d atoms", old->o_natoms); + freebytes(old, sizeof(*old)); + fclose(fp); + return (0); + } + return (old); + } + } + } + else binport_warning("file too short"); + fclose(fp); + return (0); +} + +typedef struct _binport +{ + FILE *b_fp; + int b_nsymbols; + int b_symsize; + t_symbol **b_symtable; + t_binpold *b_old; +} t_binport; + +static void binport_setint(t_atom *ap, int i) +{ + ap->a_type = A_INT; + ap->a_w.w_index = i; +} + +static void binport_setfloat(t_atom *ap, float f) +{ + ap->a_type = A_FLOAT; + ap->a_w.w_float = f; +} + static t_symbol *binport_makesymbol(t_binport *bp, int id) { char s[BINPORT_MAXSTRING]; @@ -246,7 +509,7 @@ static t_symbol *binport_makesymbol(t_binport *bp, int id) binport_bug("symbol id mismatch"); else if (id > bp->b_nsymbols) binport_error("unexpected symbol id"); - else if (binport_getstring(bp, s)) + else if (binport_readstring(bp->b_fp, s)) { int reqsize = ++bp->b_nsymbols; if (reqsize > bp->b_symsize) @@ -295,14 +558,24 @@ static int binport_nextatom(t_binport *bp, t_atom *ap) unsigned char opcode; int opval; char buf[64]; - if (!binport_getbyte(bp, &opcode)) + t_binpold *old = bp->b_old; + if (old) + { + if (old->o_ndx < old->o_natoms) + { + *ap = old->o_atombuf[old->o_ndx++]; + return (1); + } + else return (0); + } + if (!binport_readbyte(bp->b_fp, &opcode)) goto bad; opval = opcode & 0x0f; switch (opcode >> 4) { - case 1: /* variable length int, - opval: length (number of bytes that follow) */ - if (!binport_getbuf(bp, buf, opval)) + case BINPORT_INTTYPE: /* variable length int, + opval: length (number of bytes that follow) */ + if (!binport_readbuf(bp->b_fp, buf, opval)) goto bad; else { @@ -314,9 +587,9 @@ static int binport_nextatom(t_binport *bp, t_atom *ap) binport_setint(ap, i); } break; - case 2: /* variable length float, - opval: length (number of bytes that follow) */ - if (!binport_getbuf(bp, buf, opval)) + case BINPORT_FLOATTYPE: /* variable length float, + opval: length (number of bytes that follow) */ + if (!binport_readbuf(bp->b_fp, buf, opval)) goto bad; else { @@ -326,9 +599,9 @@ static int binport_nextatom(t_binport *bp, t_atom *ap) binport_setfloat(ap, *(t_float *)&i); } break; - case 3: /* variable length symbol id, - opval: length (number of bytes that follow) */ - if (!binport_getbuf(bp, buf, opval)) + case BINPORT_SYMTYPE: /* variable length symbol id, + opval: length (number of bytes that follow) */ + if (!binport_readbuf(bp->b_fp, buf, opval)) goto bad; else { @@ -339,21 +612,31 @@ static int binport_nextatom(t_binport *bp, t_atom *ap) goto bad; } break; - case 5: /* half-byte int */ + case BINPORT_DEFINTTYPE: /* half-byte int */ binport_setint(ap, opval); break; - case 7: /* half-byte symbol id */ + case BINPORT_DEFSYMTYPE: /* half-byte symbol id */ if (!binport_setsymbol(bp, ap, opval)) goto bad; break; - case 12: /* #number */ + case BINPORT_SEMITYPE: + /* LATER warn about nonzero opval */ + ap->a_type = A_SEMI; + break; + case BINPORT_COMMATYPE: + /* CHECKME apparently never used? */ + binport_warning("found the comma type in max binary..."); + /* LATER warn about nonzero opval */ + ap->a_type = A_COMMA; + break; + case BINPORT_DOLLARTYPE: /* #number */ sprintf(buf, "#%d", opval); ap->a_type = A_SYMBOL; ap->a_w.w_symbol = gensym(buf); break; - case 13: /* #symbol id, - opval: length (number of bytes that follow) */ - if (!binport_getbuf(bp, buf, opval)) + case BINPORT_DOLLSYMTYPE: /* #symbol id, + opval: length (number of bytes that follow) */ + if (!binport_readbuf(bp->b_fp, buf, opval)) goto bad; else { @@ -370,70 +653,96 @@ static int binport_nextatom(t_binport *bp, t_atom *ap) ap->a_w.w_symbol = gensym(buf); break; default: - switch (opcode) - { - case 0xa0: - ap->a_type = A_SEMI; - break; - default: - goto unknown; - } + binport_error("unknown opcode %x", (int)opcode); + goto bad; } return (1); -unknown: - binport_error("unknown opcode %x", (int)opcode); bad: return (0); } +static int binport_binalike(char *header) +{ + static char binport_header[4] = { 2, 0, 0, 0 }; /* CHECKME any others? */ + return (memcmp(header, binport_header, 4) == 0); +} + +static int binport_oldalike(char *header) +{ + static char binpold_header[4] = { 0, 0, 0, 1 }; /* CHECKME any others? */ + return (memcmp(header, binpold_header, 4) == 0); +} + static void binport_free(t_binport *bp) { fclose(bp->b_fp); - freebytes(bp->b_symtable, bp->b_symsize * sizeof(*bp->b_symtable)); + if (bp->b_symtable) + freebytes(bp->b_symtable, bp->b_symsize * sizeof(*bp->b_symtable)); + if (bp->b_old) + { + bp->b_old->o_fp = 0; + binpold_free(bp->b_old); + } freebytes(bp, sizeof(*bp)); } static t_binport *binport_new(FILE *fp, int *ftypep) { - static char binport_header[4] = { 2, 0, 0, 0 }; char header[4]; *ftypep = BINPORT_INVALID; if (fread(header, 1, 4, fp) == 4) { - if (memcmp(header, binport_header, 4)) - { - if (memcmp(header, "max", 3)) - { - if (header[0] == '#') /* LATER rethink */ - *ftypep = BINPORT_PDFILE; -#ifdef BINPORT_VERBOSE - else binport_warning("unknown header: %x %x %x %x", - (int)header[0], (int)header[1], - (int)header[2], (int)header[3]); -#endif - } - else *ftypep = BINPORT_MAXTEXT; - } - else + if (binport_binalike(header)) { t_binport *bp = getbytes(sizeof(*bp)); bp->b_fp = fp; bp->b_nsymbols = 0; bp->b_symsize = BINPORT_SYMGROW; bp->b_symtable = getbytes(bp->b_symsize * sizeof(*bp->b_symtable)); + bp->b_old = 0; *ftypep = BINPORT_OK; return (bp); } + else if (memcmp(header, "max", 3) == 0) + *ftypep = BINPORT_MAXTEXT; + else if (binport_oldalike(header)) + { + t_binport *bp = getbytes(sizeof(*bp)); + bp->b_fp = fp; + bp->b_nsymbols = 0; + bp->b_symsize = 0; + bp->b_symtable = 0; + bp->b_old = 0; + *ftypep = BINPORT_MAXOLD; + return (bp); + } + else + { + if (header[0] == '#') /* LATER rethink */ + *ftypep = BINPORT_PDFILE; + else binport_warning("unknown header: %x %x %x %x", + (int)header[0], (int)header[1], + (int)header[2], (int)header[3]); + } } -#ifdef BINPORT_VERBOSE else binport_warning("file too short"); -#endif fclose(fp); return (0); } #ifndef BINPORT_STANDALONE +static int binport_tobinbuf(t_binport *bp, t_binbuf *bb) +{ + t_atom at; + if (bp->b_old) + bp->b_old->o_ndx = 0; + while (binport_nextatom(bp, &at)) + if (at.a_type != A_NULL) + binbuf_add(bb, 1, &at); + return (1); +} + /* LATER deal with corrupt binary files? */ int binport_read(t_binbuf *bb, char *filename, char *dirname) { @@ -450,17 +759,30 @@ int binport_read(t_binbuf *bb, char *filename, char *dirname) t_binport *bp = binport_new(fp, &ftype); if (bp) { - t_atom at; - while (binport_nextatom(bp, &at)) - if (at.a_type != A_NULL) - binbuf_add(bb, 1, &at); + int result; + if (ftype == BINPORT_OK) + result = (binport_tobinbuf(bp, bb) + ? BINPORT_OK : BINPORT_CORRUPT); + else if (ftype == BINPORT_MAXOLD) + { + t_binpold *old = binpold_new(fp); + result = BINPORT_FAILED; + if (old) + { + bp->b_old = old; + if (binpold_load(old) && binport_tobinbuf(bp, bb)) + result = BINPORT_OK; + } + else binpold_failure(filename); + } + else result = BINPORT_FAILED; binport_free(bp); - return (BINPORT_OK); + return (result); } else if (ftype == BINPORT_MAXTEXT || ftype == BINPORT_PDFILE) return (ftype); else - binport_error("\"%s\" doesn't look like a patch file", filename); + binport_failure(filename); } else binport_bug("cannot open file"); return (BINPORT_INVALID); @@ -478,7 +800,7 @@ static void binport_atomstring(t_atom *ap, char *buf, int bufsize) case A_COMMA: strcpy(buf, ","); break; case A_INT: - sprintf(buf, "%d", binport_getint(ap)); break; + sprintf(buf, "%d", ap->a_w.w_index); break; case A_FLOAT: sprintf(buf, "%#f", ap->a_w.w_float); ep = buf + strlen(buf) - 1; @@ -514,6 +836,29 @@ static void binport_atomstring(t_atom *ap, char *buf, int bufsize) } } +static void binport_print(t_binport *bp) +{ + char buf[BINPORT_MAXSTRING]; + t_atom at; + int ac = 0; + if (bp->b_old) + bp->b_old->o_ndx = 0; + while (binport_nextatom(bp, &at)) + { + if (at.a_type == A_SEMI) + { + fputs(";\n", stdout); + ac = 0; + } + else if (at.a_type != A_NULL) + { + if (ac++) fputc(' ', stdout); + binport_atomstring(&at, buf, BINPORT_MAXSTRING); + fputs(buf, stdout); + } + } +} + int main(int ac, char **av) { if (ac > 1) @@ -525,22 +870,21 @@ int main(int ac, char **av) t_binport *bp = binport_new(fp, &ftype); if (bp) { - char buf[BINPORT_MAXSTRING]; - t_atom at; - int ac = 0; - while (binport_nextatom(bp, &at)) + if (ftype == BINPORT_OK) + binport_print(bp); + else if (ftype == BINPORT_MAXOLD) { - if (at.a_type == A_SEMI) - { - fputs(";\n", stdout); - ac = 0; - } - else if (at.a_type != A_NULL) + t_binpold *old = binpold_new(fp); + if (old) { - if (ac++) fputc(' ', stdout); - binport_atomstring(&at, buf, BINPORT_MAXSTRING); - fputs(buf, stdout); + bp->b_old = old; + if (binpold_load(old)) + binport_print(bp); + else + ftype = BINPORT_FAILED; } + else ftype = BINPORT_FAILED; + if (ftype == BINPORT_FAILED) binpold_failure(av[1]); } binport_free(bp); } @@ -549,7 +893,7 @@ int main(int ac, char **av) else if (ftype == BINPORT_PDFILE) binport_warning("\"%s\" looks like a Pd patch file", av[1]); else - binport_error("\"%s\" doesn't look like a patch file", av[1]); + binport_failure(av[1]); } else binport_error("cannot open file \"%s\"", av[1]); } diff --git a/shared/common/binport.h b/shared/common/binport.h index 0b6b607..bdf1ca1 100644 --- a/shared/common/binport.h +++ b/shared/common/binport.h @@ -1,12 +1,12 @@ -/* Copyright (c) 2003 krzYszcz and others. +/* Copyright (c) 2003-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __BINPORT_H__ #define __BINPORT_H__ -enum { BINPORT_OK, BINPORT_MAXTEXT, BINPORT_PDFILE, - BINPORT_INVALID, BINPORT_CORRUPT }; +enum { BINPORT_OK, BINPORT_MAXTEXT, BINPORT_MAXOLD, BINPORT_PDFILE, + BINPORT_INVALID, BINPORT_CORRUPT, BINPORT_FAILED }; #ifndef BINPORT_STANDALONE int binport_read(t_binbuf *bb, char *filename, char *dirname); diff --git a/shared/common/port.c b/shared/common/port.c index 26f24ca..95ccc7f 100644 --- a/shared/common/port.c +++ b/shared/common/port.c @@ -1,4 +1,4 @@ -/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. +/* Copyright (c) 1997-2004 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -35,6 +35,9 @@ enum { PORT_OK, PORT_NEXT, /* next line, please */ PORT_UNKNOWN, PORT_CORRUPT, PORT_FATAL }; +/* cf binport.c */ +#define A_INT A_DEFFLOAT + /* without access to sys_defaultfont, we just mimic defs from s_main.c */ #ifdef MSW #define PORT_DEFFONTSIZE 12. @@ -48,8 +51,8 @@ enum { PORT_OK, typedef struct _port { - t_binbuf *x_oldbb; - t_binbuf *x_newbb; + t_binbuf *x_inbb; + t_binbuf *x_outbb; int x_nobj; int x_withbogus; int x_inatoms; @@ -79,6 +82,25 @@ static t_float port_floatarg(t_port *x, int ndx) else return (0); } +static t_int port_intarg(t_port *x, int ndx) +{ + if (ndx < x->x_inatoms) + { + t_atom *av = &x->x_inmess[ndx]; +#ifdef FIXME + return (av->a_type == A_INT ? av->a_w.w_index : 0); +#else + if (av->a_type == A_INT) + return (av->a_w.w_index); + else if (av->a_type == A_FLOAT) + return ((t_int)av->a_w.w_float); + else + return (0); +#endif + } + else return (0); +} + static t_symbol *port_symbolarg(t_port *x, int ndx) { if (ndx < x->x_inatoms) @@ -106,17 +128,17 @@ static int port_wstretch(float f) static t_float port_xarg(t_port *x, int ndx) { - return ((t_float)port_xstretch(port_floatarg(x, ndx))); + return ((t_float)port_xstretch(port_intarg(x, ndx))); } static t_float port_yarg(t_port *x, int ndx) { - return ((t_float)port_ystretch(port_floatarg(x, ndx))); + return ((t_float)port_ystretch(port_intarg(x, ndx))); } static t_float port_widtharg(t_port *x, int ndx) { - return ((t_float)port_wstretch(port_floatarg(x, ndx))); + return ((t_float)port_wstretch(port_intarg(x, ndx))); } static void port_setxy(t_port *x, int ndx, t_atom *ap) @@ -128,6 +150,20 @@ static void port_setxy(t_port *x, int ndx, t_atom *ap) SETFLOAT(ap, f); } +static t_atom *import_copyatoms(t_atom *out, t_atom *in, int ac) +{ + while (ac-- > 0) + { + if (in->a_type == A_INT) + { + out->a_type = A_FLOAT; + out++->a_w.w_float = (float)in++->a_w.w_index; + } + else *out++ = *in++; + } + return (out); +} + static void import_addclassname(t_port *x, char *outname, t_atom *inatom) { t_atom at; @@ -145,22 +181,22 @@ static void import_addclassname(t_port *x, char *outname, t_atom *inatom) { x->x_withbogus = 1; SETSYMBOL(&at, portps_bogus); - binbuf_add(x->x_newbb, 1, &at); + binbuf_add(x->x_outbb, 1, &at); } SETSYMBOL(&at, insym); } else at = *inatom; - binbuf_add(x->x_newbb, 1, &at); + binbuf_add(x->x_outbb, 1, &at); } static int import_obj(t_port *x, char *name) { int ndx = (x->x_inmess[1].a_w.w_symbol == gensym("user") ? 3 : 2); - binbuf_addv(x->x_newbb, "ssff", + binbuf_addv(x->x_outbb, "ssff", gensym("#X"), gensym("obj"), port_xarg(x, ndx), port_yarg(x, ndx + 1)); import_addclassname(x, name, &x->x_inmess[ndx == 2 ? 6 : 2]); - binbuf_addsemi(x->x_newbb); + binbuf_addsemi(x->x_outbb); x->x_nobj++; return (PORT_NEXT); } @@ -171,26 +207,22 @@ static int import_objarg(t_port *x, char *name) if (x->x_inatoms > 6 || (ndx == 3 && x->x_inatoms > 4)) { - int nextra; - t_atom *in, *out = x->x_outmess; + t_atom *out = x->x_outmess; SETSYMBOL(out, gensym("#X")); out++; SETSYMBOL(out, gensym("obj")); out++; port_setxy(x, ndx, out); - binbuf_add(x->x_newbb, 4, x->x_outmess); + binbuf_add(x->x_outbb, 4, x->x_outmess); import_addclassname(x, name, &x->x_inmess[ndx == 2 ? 6 : 2]); - out = x->x_outmess; - for (ndx = 7, nextra = 1, in = x->x_inmess + 7; - ndx < x->x_inatoms; ndx++, nextra++) - *out++ = *in++; + out = import_copyatoms(x->x_outmess, x->x_inmess + 7, x->x_inatoms - 7); SETSEMI(out); - binbuf_add(x->x_newbb, nextra, x->x_outmess); + binbuf_add(x->x_outbb, x->x_inatoms - 6, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } else return (PORT_CORRUPT); } -static int imaction_vpatcher(t_port *x, char *arg) +static int imaction_N1_vpatcher(t_port *x, char *arg) { if (x->x_stackdepth >= x->x_stacksize) { @@ -208,20 +240,43 @@ static int imaction_vpatcher(t_port *x, char *arg) } x->x_stack[x->x_stackdepth++] = x->x_nobj; x->x_nobj = 0; - binbuf_addv(x->x_newbb, "ssfffff;", + binbuf_addv(x->x_outbb, "ssfffff;", gensym("#N"), gensym("canvas"), port_xarg(x, 2), port_yarg(x, 3), - (float)port_xstretch(port_floatarg(x, 4) - port_floatarg(x, 2)), - (float)port_ystretch(port_floatarg(x, 5) - port_floatarg(x, 3)), + (float)port_xstretch(port_intarg(x, 4) - port_intarg(x, 2)), + (float)port_ystretch(port_intarg(x, 5) - port_intarg(x, 3)), PORT_DEFFONTSIZE); return (PORT_NEXT); } -static int imaction_patcher(t_port *x, char *arg) +/* FIXME */ +static int imaction_N1_vtable(t_port *x, char *arg) +{ +#if 1 + post("vtable \"%s\": size %d, range %d, coords %d %d %d %d, flags %d", + port_symbolarg(x, 9)->s_name, + port_intarg(x, 2), port_intarg(x, 8), + port_intarg(x, 3), port_intarg(x, 4), + port_intarg(x, 5), port_intarg(x, 6), + port_intarg(x, 7)); +#endif + return (PORT_NEXT); +} + +/* FIXME */ +static int imaction_N1_picture(t_port *x, char *arg) { - binbuf_addv(x->x_newbb, "ss;", portps_cleanup, portps_cleanup); +#if 1 + post("picture"); +#endif + return (PORT_NEXT); +} + +static int imaction_P6_patcher(t_port *x, char *arg) +{ + binbuf_addv(x->x_outbb, "ss;", portps_cleanup, portps_cleanup); x->x_withbogus = 0; - binbuf_addv(x->x_newbb, "ssffss;", + binbuf_addv(x->x_outbb, "ssffss;", gensym("#X"), gensym("restore"), port_xarg(x, 2), port_yarg(x, 3), gensym("pd"), port_symbolarg(x, 7)); @@ -232,7 +287,7 @@ static int imaction_patcher(t_port *x, char *arg) return (PORT_NEXT); } -static int imaction_trigger(t_port *x, char *arg) +static int imaction_P6_trigger(t_port *x, char *arg) { int i; for (i = 7; i < x->x_inatoms; i++) @@ -242,11 +297,10 @@ static int imaction_trigger(t_port *x, char *arg) return (PORT_OK); } -static int imaction_scope(t_port *x, char *name) +static int imaction_P2_scope(t_port *x, char *name) { if (x->x_inatoms > 6) { - t_atom *in = x->x_inmess + 7; t_atom *out = x->x_outmess; int i, xpix, ypix; SETSYMBOL(out, gensym("#X")); out++; @@ -254,16 +308,15 @@ static int imaction_scope(t_port *x, char *name) port_setxy(x, 3, out); xpix = (int)out++->a_w.w_float; ypix = (int)out->a_w.w_float; - binbuf_add(x->x_newbb, 4, x->x_outmess); + binbuf_add(x->x_outbb, 4, x->x_outmess); import_addclassname(x, name, &x->x_inmess[2]); out = x->x_outmess; port_setxy(x, 5, out); out++->a_w.w_float -= xpix; out++->a_w.w_float -= ypix; - for (i = 7; i < x->x_inatoms; i++) - *out++ = *in++; + out = import_copyatoms(out, x->x_inmess + 7, x->x_inatoms - 7); SETSEMI(out); - binbuf_add(x->x_newbb, x->x_inatoms - 4, x->x_outmess); + binbuf_add(x->x_outbb, x->x_inatoms - 4, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } @@ -271,7 +324,7 @@ static int imaction_scope(t_port *x, char *name) } /* width fontsize fontfamily encoding fontprops red green blue text... */ -static int imaction_comment(t_port *x, char *arg) +static int imaction_P1_comment(t_port *x, char *arg) { int outatoms; SETSYMBOL(x->x_outmess, gensym("#X")); @@ -284,7 +337,12 @@ static int imaction_comment(t_port *x, char *arg) float width = port_widtharg(x, 4); t_atom *ap = x->x_inmess + 5; SETFLOAT(x->x_outmess + 5, width); - if (ap->a_type == A_FLOAT) + if (ap->a_type == A_INT) + { + fontsize = ap->a_w.w_index & 0x0ff; + fontprops = ap->a_w.w_index >> 8; + } + else if (ap->a_type == A_FLOAT) /* FIXME */ { fontsize = ((int)ap->a_w.w_float) & 0x0ff; fontprops = ((int)ap->a_w.w_float) >> 8; @@ -298,33 +356,32 @@ static int imaction_comment(t_port *x, char *arg) SETFLOAT(x->x_outmess + 11, 0); SETFLOAT(x->x_outmess + 12, 0); outatoms = x->x_inatoms + 7; - for (i = 13; i < outatoms ; i++) - x->x_outmess[i] = x->x_inmess[i - 7]; + import_copyatoms(x->x_outmess + 13, x->x_inmess + 6, x->x_inatoms - 6); } else outatoms = 5; SETSEMI(x->x_outmess + outatoms); - binbuf_add(x->x_newbb, outatoms + 1, x->x_outmess); + binbuf_add(x->x_outbb, outatoms + 1, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } -static int imaction_message(t_port *x, char *arg) +static int imaction_P1_message(t_port *x, char *arg) { int i; + t_atom *out; SETSYMBOL(x->x_outmess, gensym("#X")); SETSYMBOL(x->x_outmess + 1, gensym("msg")); port_setxy(x, 2, x->x_outmess + 2); - for (i = 6; i < x->x_inatoms; i++) - x->x_outmess[i-2] = x->x_inmess[i]; - SETSEMI(x->x_outmess + x->x_inatoms - 2); - binbuf_add(x->x_newbb, x->x_inatoms - 1, x->x_outmess); + out = import_copyatoms(x->x_outmess + 4, x->x_inmess + 6, x->x_inatoms - 6); + SETSEMI(out); + binbuf_add(x->x_outbb, x->x_inatoms - 1, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } -static int imaction_io(t_port *x, char *arg) +static int imaction_P1_io(t_port *x, char *arg) { - binbuf_addv(x->x_newbb, "ssff", + binbuf_addv(x->x_outbb, "ssff", gensym("#X"), gensym("obj"), port_xarg(x, 2), port_yarg(x, 3)); if (x->x_inmess[1].a_w.w_symbol == portps_inlet || @@ -332,31 +389,62 @@ static int imaction_io(t_port *x, char *arg) { t_atom at; SETSYMBOL(&at, portps_bogus); - binbuf_add(x->x_newbb, 1, &at); + binbuf_add(x->x_outbb, 1, &at); } - binbuf_add(x->x_newbb, 1, &x->x_inmess[1]); - binbuf_addsemi(x->x_newbb); + binbuf_add(x->x_outbb, 1, &x->x_inmess[1]); + binbuf_addsemi(x->x_outbb); x->x_nobj++; return (PORT_NEXT); } -static int imaction_number(t_port *x, char *arg) +static int imaction_P1_number(t_port *x, char *arg) { - binbuf_addv(x->x_newbb, "ssff;", + binbuf_addv(x->x_outbb, "ssff;", gensym("#X"), gensym("floatatom"), port_xarg(x, 2), port_yarg(x, 3)); x->x_nobj++; return (PORT_NEXT); } -static int imaction_connect(t_port *x, char *arg) +static int imaction_P1_connect(t_port *x, char *arg) { - binbuf_addv(x->x_newbb, "ssffff;", + binbuf_addv(x->x_outbb, "ssiiii;", gensym("#X"), gensym("connect"), - x->x_nobj - port_floatarg(x, 2) - 1, - port_floatarg(x, 3), - x->x_nobj - port_floatarg(x, 4) - 1, - port_floatarg(x, 5)); + x->x_nobj - port_intarg(x, 2) - 1, + port_intarg(x, 3), + x->x_nobj - port_intarg(x, 4) - 1, + port_intarg(x, 5)); + return (PORT_NEXT); +} + +/* FIXME */ +static int imaction_T1_set(t_port *x, char *arg) +{ +#if 1 + post("set (%d atoms from %d): %d ... %d", + x->x_inatoms - 3, port_intarg(x, 2), + port_intarg(x, 3), port_intarg(x, x->x_inatoms - 1)); +#endif + return (PORT_NEXT); +} + +/* FIXME */ +static int imaction_K1_replace(t_port *x, char *arg) +{ +#if 1 + post("replace %d", port_intarg(x, 2)); +#endif + return (PORT_NEXT); +} + +/* FIXME */ +static int imaction_K1_set(t_port *x, char *arg) +{ +#if 1 + post("set (%d atoms from %d): %d ... %d", + x->x_inatoms - 3, port_intarg(x, 2), + port_intarg(x, 3), port_intarg(x, x->x_inatoms - 1)); +#endif return (PORT_NEXT); } @@ -382,14 +470,16 @@ typedef struct _portnode /* a parser's symbol definition, sort of... */ static t_portslot imslots__N[] = { - { "vpatcher", imaction_vpatcher, 0, 0, 0 } + { "vpatcher", imaction_N1_vpatcher, 0, 0, 0 }, + { "vtable", imaction_N1_vtable, 0, 0, 0 }, + { "picture", imaction_N1_picture, 0, 0, 0 } }; static t_portnode imnode__N = { imslots__N, PORT_NSLOTS(imslots__N), 1 }; static t_portslot imslots_newobj[] = { - { "patcher", imaction_patcher, 0, 0, 0 }, - { "p", imaction_patcher, 0, 0, 0 }, + { "patcher", imaction_P6_patcher, 0, 0, 0 }, + { "p", imaction_P6_patcher, 0, 0, 0 }, /* state is embedded in #N vtable...; #T set...; */ { "table", import_obj, "Table", 0, 0 } }; @@ -410,8 +500,8 @@ static t_portslot imslots_newex[] = { "line~", import_objarg, "Line~", 0, 0 }, { "poly", import_objarg, "Poly", 0, 0 }, { "snapshot~", import_objarg, "Snapshot~", 0, 0 }, - { "trigger", imaction_trigger, 0, 0, 0 }, - { "t", imaction_trigger, 0, 0, 0 }, + { "trigger", imaction_P6_trigger, 0, 0, 0 }, + { "t", imaction_P6_trigger, 0, 0, 0 }, /* LATER rethink */ { "Borax", import_objarg, "Borax", 0, 0 }, @@ -432,7 +522,7 @@ static t_portslot imslots_user[] = { "GSwitch", import_objarg, "Gswitch", 0, 0 }, { "GSwitch2", import_objarg, "Ggate", 0, 0 }, { "number~", import_obj, 0, 0, 0 }, - { "scope~", imaction_scope, "Scope~", 0, 0 }, + { "scope~", imaction_P2_scope, "Scope~", 0, 0 }, { "uslider", import_obj, "vsl", 0, 0 } /* LATER range and offset */ }; static t_portnode imnode_user = { imslots_user, @@ -440,16 +530,16 @@ static t_portnode imnode_user = { imslots_user, static t_portslot imslots__P[] = { - { "comment", imaction_comment, 0, 0, 0 }, - { "message", imaction_message, 0, 0, 0 }, + { "comment", imaction_P1_comment, 0, 0, 0 }, + { "message", imaction_P1_message, 0, 0, 0 }, { "newobj", import_objarg, 0, &imnode_newobj, 0 }, { "newex", import_objarg, 0, &imnode_newex, 0 }, - { "inlet", imaction_io, 0, 0, 0 }, - { "inlet~", imaction_io, 0, 0, 0 }, - { "outlet", imaction_io, 0, 0, 0 }, - { "outlet~", imaction_io, 0, 0, 0 }, - { "number", imaction_number, 0, 0, 0 }, - { "flonum", imaction_number, 0, 0, 0 }, + { "inlet", imaction_P1_io, 0, 0, 0 }, + { "inlet~", imaction_P1_io, 0, 0, 0 }, + { "outlet", imaction_P1_io, 0, 0, 0 }, + { "outlet~", imaction_P1_io, 0, 0, 0 }, + { "number", imaction_P1_number, 0, 0, 0 }, + { "flonum", imaction_P1_number, 0, 0, 0 }, { "button", import_obj, "bng", 0, 0 }, { "slider" , import_obj, "vsl", 0, 0 }, /* LATER range and offset */ { "hslider", import_obj, "hsl", 0, 0 }, /* LATER range and offset */ @@ -460,19 +550,34 @@ static t_portslot imslots__P[] = /* an object created from the "Paste Picture" menu, state is embedded in #N picture; #K...; */ { "vpicture", import_obj, "vpicture", 0, 0 }, - { "connect", imaction_connect, 0, 0, 0 }, - { "fasten", imaction_connect, 0, 0, 0 } + { "connect", imaction_P1_connect, 0, 0, 0 }, + { "fasten", imaction_P1_connect, 0, 0, 0 } }; static t_portnode imnode__P = { imslots__P, PORT_NSLOTS(imslots__P), 1 }; +static t_portslot imslots__T[] = +{ + { "set", imaction_T1_set, 0, 0, 0 } +}; +static t_portnode imnode__T = { imslots__T, PORT_NSLOTS(imslots__T), 1 }; + +static t_portslot imslots__K[] = +{ + { "replace", imaction_K1_replace, 0, 0, 0 }, + { "set", imaction_K1_set, 0, 0, 0 } +}; +static t_portnode imnode__K = { imslots__K, PORT_NSLOTS(imslots__K), 1 }; + static t_portslot imslots_[] = { { "#N", 0, 0, &imnode__N, 0 }, - { "#P", 0, 0, &imnode__P, 0 } + { "#P", 0, 0, &imnode__P, 0 }, + { "#T", 0, 0, &imnode__T, 0 }, + { "#K", 0, 0, &imnode__K, 0 } }; static t_portnode imnode_ = { imslots_, PORT_NSLOTS(imslots_), 0 }; -static int port_doit(t_port *x, t_portnode *node) +static int port_doline(t_port *x, t_portnode *node) { int nslots = node->n_nslots; if (nslots > 0) @@ -489,7 +594,7 @@ secondpass: if (slot->s_subtree) { int nobj = x->x_nobj; - int result = port_doit(x, slot->s_subtree); + int result = port_doline(x, slot->s_subtree); if (result == PORT_FATAL || result == PORT_CORRUPT || result == PORT_NEXT) return (result); @@ -509,7 +614,7 @@ secondpass: goto secondpass; } } - else bug("port_doit"); + else bug("port_doline"); return (PORT_UNKNOWN); } @@ -755,7 +860,8 @@ static void port_checksetup(void) static t_port *port_new(void) { t_port *x = (t_port *)getbytes(sizeof(*x)); - x->x_oldbb = binbuf_new(); + x->x_inbb = binbuf_new(); + x->x_outbb = 0; x->x_withbogus = 0; x->x_outsize = PORT_INISIZE; x->x_outatoms = 0; @@ -787,10 +893,9 @@ static void port_free(t_port *x) static int import_binbuf(t_port *x) { - t_atom *av = binbuf_getvec(x->x_oldbb); - int ac = binbuf_getnatom(x->x_oldbb); + t_atom *av = binbuf_getvec(x->x_inbb); + int ac = binbuf_getnatom(x->x_inbb); int startmess, endmess; - x->x_newbb = binbuf_new(); for (startmess = 0; startmess < ac; startmess = endmess + 1) { t_atom *mess = av + startmess, *ap; @@ -849,7 +954,7 @@ static int import_binbuf(t_port *x) SETSYMBOL(ap, gensym(buf)); } } - if (port_doit(x, &imnode_) == PORT_FATAL) + if (port_doline(x, &imnode_) == PORT_FATAL) return (PORT_FATAL); } return (PORT_OK); @@ -872,32 +977,42 @@ void import_max(char *fn, char *dir) x = port_new(); glob_setfilename(0, gensym(bufp), gensym(buf)); - ftype = binport_read(x->x_oldbb, bufp, buf); + ftype = binport_read(x->x_inbb, bufp, buf); + /* FIXME for BINPORT_MAXTEXT use an int-preserving version of binbuf_read */ if (ftype == BINPORT_MAXTEXT || ftype == BINPORT_PDFILE) - failure = binbuf_read(x->x_oldbb, bufp, buf, 0); + failure = binbuf_read(x->x_inbb, bufp, buf, 0); else failure = (ftype != BINPORT_OK); /* LATER rethink */ if (failure) { perror(fn); /* FIXME */ - binbuf_free(x->x_oldbb); + binbuf_free(x->x_inbb); } else { - if (ftype == BINPORT_PDFILE) x->x_newbb = x->x_oldbb; + if (ftype == BINPORT_PDFILE) x->x_outbb = x->x_inbb; else { #ifdef PORT_DEBUG - binbuf_write(x->x_oldbb, "import-debug.pd", "", 0); + /* save as .pd (bypass export translation) */ + binbuf_write(x->x_inbb, "import-debug.pd", "", 0); #endif - import_binbuf(x); - binbuf_free(x->x_oldbb); + x->x_outbb = binbuf_new(); + if (import_binbuf(x) != PORT_OK) + { + loud_error(0, "%s: import failed", fn); + x->x_outbb = 0; + } + binbuf_free(x->x_inbb); #ifdef PORT_LOG - binbuf_write(x->x_newbb, "import-result.pd", "", 0); + if (x->x_outbb) binbuf_write(x->x_outbb, "import-result.pd", "", 0); #endif } - binbuf_eval(x->x_newbb, 0, 0, 0); - binbuf_free(x->x_newbb); + if (x->x_outbb) + { + binbuf_eval(x->x_outbb, 0, 0, 0); + binbuf_free(x->x_outbb); + } } port_free(x); |