Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin...
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / m_binbuf.c
blobc215e399e66f94d1326e3e2633bdd68e1904d858
1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
6 /* IOhannes :
7 * changed the canvas_restore in "g_canvas.c", so that it might accept $args as well (like "pd $0_test")
8 * so you can make multiple & distinguishable templates
9 * 1511:forum::für::umläute:2001
10 * change marked with IOhannes
13 #include <stdlib.h>
14 #include "m_pd.h"
15 #include "s_stuff.h"
16 #include <stdio.h>
17 #ifdef UNIX
18 #include <unistd.h>
19 #endif
20 #ifdef MSW
21 #include <io.h>
22 #endif
23 #include <fcntl.h>
24 #include <string.h>
25 #include <stdarg.h>
27 struct _binbuf
29 int b_n;
30 t_atom *b_vec;
33 t_binbuf *binbuf_new(void)
35 t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
36 x->b_n = 0;
37 x->b_vec = t_getbytes(0);
38 return (x);
41 void binbuf_free(t_binbuf *x)
43 t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
44 t_freebytes(x, sizeof(*x));
47 t_binbuf *binbuf_duplicate(t_binbuf *y)
49 t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
50 x->b_n = y->b_n;
51 x->b_vec = t_getbytes(x->b_n * sizeof(*x->b_vec));
52 memcpy(x->b_vec, y->b_vec, x->b_n * sizeof(*x->b_vec));
53 return (x);
56 void binbuf_clear(t_binbuf *x)
58 x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0);
59 x->b_n = 0;
62 /* convert text to a binbuf */
63 void binbuf_text(t_binbuf *x, char *text, size_t size)
65 char buf[MAXPDSTRING+1], *bufp, *ebuf = buf+MAXPDSTRING;
66 const char *textp = text, *etext = text+size;
67 t_atom *ap;
68 int nalloc = 16, natom = 0;
69 t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
70 x->b_vec = t_getbytes(nalloc * sizeof(*x->b_vec));
71 ap = x->b_vec;
72 x->b_n = 0;
73 while (1)
75 int type;
76 /* skip leading space */
77 while ((textp != etext) && (*textp == ' ' || *textp == '\n'
78 || *textp == '\r' || *textp == '\t')) textp++;
79 if (textp == etext) break;
80 if (*textp == ';') SETSEMI(ap), textp++;
81 else if (*textp == ',') SETCOMMA(ap), textp++;
82 else
84 /* it's an atom other than a comma or semi */
85 char c;
86 int floatstate = 0, slash = 0, lastslash = 0,
87 firstslash = (*textp == '\\');
88 bufp = buf;
91 c = *bufp = *textp++;
92 lastslash = slash;
93 slash = (c == '\\');
95 if (floatstate >= 0)
97 int digit = (c >= '0' && c <= '9'),
98 dot = (c == '.'), minus = (c == '-'),
99 plusminus = (minus || (c == '+')),
100 expon = (c == 'e' || c == 'E');
101 if (floatstate == 0) /* beginning */
103 if (minus) floatstate = 1;
104 else if (digit) floatstate = 2;
105 else if (dot) floatstate = 3;
106 else floatstate = -1;
108 else if (floatstate == 1) /* got minus */
110 if (digit) floatstate = 2;
111 else if (dot) floatstate = 3;
112 else floatstate = -1;
114 else if (floatstate == 2) /* got digits */
116 if (dot) floatstate = 4;
117 else if (expon) floatstate = 6;
118 else if (!digit) floatstate = -1;
120 else if (floatstate == 3) /* got '.' without digits */
122 if (digit) floatstate = 5;
123 else floatstate = -1;
125 else if (floatstate == 4) /* got '.' after digits */
127 if (digit) floatstate = 5;
128 else if (expon) floatstate = 6;
129 else floatstate = -1;
131 else if (floatstate == 5) /* got digits after . */
133 if (expon) floatstate = 6;
134 else if (!digit) floatstate = -1;
136 else if (floatstate == 6) /* got 'e' */
138 if (plusminus) floatstate = 7;
139 else if (digit) floatstate = 8;
140 else floatstate = -1;
142 else if (floatstate == 7) /* got plus or minus */
144 if (digit) floatstate = 8;
145 else floatstate = -1;
147 else if (floatstate == 8) /* got digits */
149 if (!digit) floatstate = -1;
152 if (!slash) bufp++;
154 while (textp != etext && bufp != ebuf &&
155 (slash || (*textp != ' ' && *textp != '\n' && *textp != '\r'
156 && *textp != '\t' &&*textp != ',' && *textp != ';')));
157 *bufp = 0;
158 #if 0
159 post("buf %s", buf);
160 #endif
161 if (*buf == '$' && buf[1] >= '0' && buf[1] <= '9' && !firstslash)
163 for (bufp = buf+2; *bufp; bufp++)
164 if (*bufp < '0' || *bufp > '9')
166 SETDOLLSYM(ap, gensym(buf+1));
167 goto didit;
169 SETDOLLAR(ap, atoi(buf+1));
170 didit: ;
172 else
174 if (floatstate == 2 || floatstate == 4 || floatstate == 5 ||
175 floatstate == 8)
176 SETFLOAT(ap, atof(buf));
177 else SETSYMBOL(ap, gensym(buf));
180 ap++;
181 natom++;
182 if (natom == nalloc)
184 x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
185 nalloc * (2*sizeof(*x->b_vec)));
186 nalloc = nalloc * 2;
187 ap = x->b_vec + natom;
189 if (textp == etext) break;
191 /* reallocate the vector to exactly the right size */
192 x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
193 natom * sizeof(*x->b_vec));
194 x->b_n = natom;
197 /* convert a binbuf to text; no null termination. */
198 void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp)
200 char *buf = getbytes(0), *newbuf;
201 int length = 0;
202 char string[MAXPDSTRING];
203 t_atom *ap;
204 int indx;
206 for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
208 int newlength;
209 if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
210 length && buf[length-1] == ' ') length--;
211 atom_string(ap, string, MAXPDSTRING);
212 newlength = length + strlen(string) + 1;
213 if (!(newbuf = resizebytes(buf, length, newlength))) break;
214 buf = newbuf;
215 strcpy(buf + length, string);
216 length = newlength;
217 if (ap->a_type == A_SEMI) buf[length-1] = '\n';
218 else buf[length-1] = ' ';
220 if (length && buf[length-1] == ' ')
222 if (newbuf = t_resizebytes(buf, length, length-1))
224 buf = newbuf;
225 length--;
228 *bufp = buf;
229 *lengthp = length;
232 /* LATER improve the out-of-space behavior below. Also fix this so that
233 writing to file doesn't buffer everything together. */
235 void binbuf_add(t_binbuf *x, int argc, t_atom *argv)
237 int newsize = x->b_n + argc, i;
238 t_atom *ap;
239 if (ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
240 newsize * sizeof(*x->b_vec)))
241 x->b_vec = ap;
242 else
244 error("binbuf_addmessage: out of space");
245 return;
247 #if 0
248 startpost("binbuf_add: ");
249 postatom(argc, argv);
250 endpost();
251 #endif
252 for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
253 *ap = *(argv++);
254 x->b_n = newsize;
257 #define MAXADDMESSV 100
258 void binbuf_addv(t_binbuf *x, char *fmt, ...)
260 va_list ap;
261 t_atom arg[MAXADDMESSV], *at =arg;
262 int nargs = 0;
263 char *fp = fmt;
265 va_start(ap, fmt);
266 while (1)
268 if (nargs >= MAXADDMESSV)
270 error("binbuf_addmessv: only %d allowed", MAXADDMESSV);
271 break;
273 switch(*fp++)
275 case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
276 case 'f': SETFLOAT(at, va_arg(ap, double)); break;
277 case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
278 case ';': SETSEMI(at); break;
279 case ',': SETCOMMA(at); break;
280 default: goto done;
282 at++;
283 nargs++;
285 done:
286 va_end(ap);
287 binbuf_add(x, nargs, arg);
290 /* add a binbuf to another one for saving. Semicolons and commas go to
291 symbols ";", "'",; the symbol ";" goes to "\;", etc. */
293 void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y)
295 t_binbuf *z = binbuf_new();
296 int i;
297 t_atom *ap;
298 binbuf_add(z, y->b_n, y->b_vec);
299 for (i = 0, ap = z->b_vec; i < z->b_n; i++, ap++)
301 char tbuf[MAXPDSTRING];
302 switch (ap->a_type)
304 case A_FLOAT:
305 break;
306 case A_SEMI:
307 SETSYMBOL(ap, gensym(";"));
308 break;
309 case A_COMMA:
310 SETSYMBOL(ap, gensym(","));
311 break;
312 case A_DOLLAR:
313 sprintf(tbuf, "$%d", ap->a_w.w_index);
314 SETSYMBOL(ap, gensym(tbuf));
315 break;
316 case A_DOLLSYM:
317 sprintf(tbuf, "$%s", ap->a_w.w_symbol->s_name);
318 SETSYMBOL(ap, gensym(tbuf));
319 break;
320 case A_SYMBOL:
321 /* FIXME make this general */
322 if (!strcmp(ap->a_w.w_symbol->s_name, ";"))
323 SETSYMBOL(ap, gensym(";"));
324 else if (!strcmp(ap->a_w.w_symbol->s_name, ","))
325 SETSYMBOL(ap, gensym(","));
326 break;
327 default:
328 bug("binbuf_addbinbuf");
332 binbuf_add(x, z->b_n, z->b_vec);
335 void binbuf_addsemi(t_binbuf *x)
337 t_atom a;
338 SETSEMI(&a);
339 binbuf_add(x, 1, &a);
342 /* Supply atoms to a binbuf from a message, making the opposite changes
343 from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
345 void binbuf_restore(t_binbuf *x, int argc, t_atom *argv)
347 int newsize = x->b_n + argc, i;
348 t_atom *ap;
349 if (ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
350 newsize * sizeof(*x->b_vec)))
351 x->b_vec = ap;
352 else
354 error("binbuf_addmessage: out of space");
355 return;
358 for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
360 if (argv->a_type == A_SYMBOL)
362 char *str = argv->a_w.w_symbol->s_name;
363 if (!strcmp(str, ";")) SETSEMI(ap);
364 else if (!strcmp(str, ",")) SETCOMMA(ap);
365 else if (str[0] == '$' && str[1] >= '0' && str[1] <= '9')
367 int dollsym = 0;
368 char *str2;
369 for (str2 = str + 2; *str2; str2++)
370 if (*str2 < '0' || *str2 > '9')
371 dollsym = 1;
372 if (dollsym)
373 SETDOLLSYM(ap, gensym(str + 1));
374 else
376 int dollar = 0;
377 sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar);
378 SETDOLLAR(ap, dollar);
381 else *ap = *argv;
382 argv++;
384 else *ap = *(argv++);
386 x->b_n = newsize;
390 #define MSTACKSIZE 2048
392 void binbuf_print(t_binbuf *x)
394 int i, startedpost = 0, newline = 1;
395 for (i = 0; i < x->b_n; i++)
397 if (newline)
399 if (startedpost) endpost();
400 startpost("");
401 startedpost = 1;
403 postatom(1, x->b_vec + i);
404 if (x->b_vec[i].a_type == A_SEMI)
405 newline = 1;
406 else newline = 0;
408 if (startedpost) endpost();
411 int binbuf_getnatom(t_binbuf *x)
413 return (x->b_n);
416 t_atom *binbuf_getvec(t_binbuf *x)
418 return (x->b_vec);
421 int canvas_getdollarzero( void);
423 t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
425 int argno = atol(s->s_name), lastnum;
426 char buf[MAXPDSTRING], c, *sp;
427 for (lastnum = 0, sp = s->s_name; ((c = *sp) && c >= '0' && c <= '9');
428 sp++, lastnum++)
429 if (!c || argno < 0 || argno > ac)
431 if (!tonew)
432 return (0);
433 else sprintf(buf, "$%d", argno);
435 else if (argno == 0)
436 sprintf(buf, "%d", canvas_getdollarzero());
437 else
438 atom_string(av+(argno-1), buf, MAXPDSTRING/2-1);
439 strncat(buf, sp, MAXPDSTRING/2-1);
440 return (gensym(buf));
443 void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
445 static t_atom mstack[MSTACKSIZE], *msp = mstack, *ems = mstack+MSTACKSIZE;
446 t_atom *stackwas = msp;
447 t_atom *at = x->b_vec;
448 int ac = x->b_n;
449 int nargs;
450 while (1)
452 t_pd *nexttarget;
453 /* get a target. */
454 while (!target)
456 t_symbol *s;
457 while (ac && (at->a_type == A_SEMI || at->a_type == A_COMMA))
458 ac--, at++;
459 if (!ac) break;
460 if (at->a_type == A_DOLLAR)
462 if (at->a_w.w_index <= 0 || at->a_w.w_index > argc)
464 error("$%d: not enough arguments supplied",
465 at->a_w.w_index);
466 goto cleanup;
468 else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL)
470 error("$%d: symbol needed as message destination",
471 at->a_w.w_index);
472 goto cleanup;
474 else s = argv[at->a_w.w_index-1].a_w.w_symbol;
476 else if (at->a_type == A_DOLLSYM)
478 if (!(s = binbuf_realizedollsym(at->a_w.w_symbol,
479 argc, argv, 0)))
481 error("$%s: not enough arguments supplied",
482 at->a_w.w_symbol->s_name);
483 goto cleanup;
486 else s = atom_getsymbol(at);
487 if (!(target = s->s_thing))
489 error("%s: no such object", s->s_name);
490 cleanup:
491 do at++, ac--;
492 while (ac && at->a_type != A_SEMI);
493 /* LATER eat args until semicolon and continue */
494 continue;
496 else
498 at++, ac--;
499 break;
502 if (!ac) break;
503 nargs = 0;
504 nexttarget = target;
505 while (1)
507 t_symbol *s9;
508 if (!ac) goto gotmess;
509 if (msp >= ems)
511 error("message stack overflow");
512 goto broken;
514 switch (at->a_type)
516 case A_SEMI:
517 /* semis and commas in new message just get bashed to
518 a symbol. This is needed so you can pass them to "expr." */
519 if (target == &pd_objectmaker)
521 SETSYMBOL(msp, gensym(";"));
522 break;
524 else
526 nexttarget = 0;
527 goto gotmess;
529 case A_COMMA:
530 if (target == &pd_objectmaker)
532 SETSYMBOL(msp, gensym(","));
533 break;
535 else goto gotmess;
536 case A_FLOAT:
537 case A_SYMBOL:
538 *msp = *at;
539 break;
540 case A_DOLLAR:
541 if (at->a_w.w_index > 0 && at->a_w.w_index <= argc)
542 *msp = argv[at->a_w.w_index-1];
543 else if (at->a_w.w_index == 0)
544 SETFLOAT(msp, canvas_getdollarzero());
545 else
547 if (target == &pd_objectmaker)
548 SETFLOAT(msp, 0);
549 else
551 error("$%d: argument number out of range",
552 at->a_w.w_index);
553 SETFLOAT(msp, 0);
556 break;
557 case A_DOLLSYM:
558 s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv,
559 target == &pd_objectmaker);
560 if (!s9)
561 goto broken;
562 SETSYMBOL(msp, s9);
563 break;
564 default:
565 bug("bad item in binbuf");
566 goto broken;
568 msp++;
569 ac--;
570 at++;
571 nargs++;
573 gotmess:
574 if (nargs)
576 switch (stackwas->a_type)
578 case A_SYMBOL:
579 typedmess(target, stackwas->a_w.w_symbol, nargs-1, stackwas+1);
580 break;
581 case A_FLOAT:
582 if (nargs == 1) pd_float(target, stackwas->a_w.w_float);
583 else pd_list(target, 0, nargs, stackwas);
584 break;
587 msp = stackwas;
588 if (!ac) break;
589 target = nexttarget;
590 at++;
591 ac--;
594 return;
595 broken:
596 msp = stackwas;
599 static int binbuf_doopen(char *s, int mode)
601 char namebuf[MAXPDSTRING];
602 #ifdef MSW
603 mode |= O_BINARY;
604 #endif
605 sys_bashfilename(s, namebuf);
606 return (open(namebuf, mode));
609 static FILE *binbuf_dofopen(char *s, char *mode)
611 char namebuf[MAXPDSTRING];
612 sys_bashfilename(s, namebuf);
613 return (fopen(namebuf, mode));
616 int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag)
618 long length;
619 int fd;
620 int readret;
621 char *buf;
622 char namebuf[MAXPDSTRING];
624 namebuf[0] = 0;
625 if (*dirname)
626 strcat(namebuf, dirname), strcat(namebuf, "/");
627 strcat(namebuf, filename);
629 if ((fd = binbuf_doopen(namebuf, 0)) < 0)
631 fprintf(stderr, "open: ");
632 perror(namebuf);
633 return (1);
635 if ((length = lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0
636 || !(buf = t_getbytes(length)))
638 fprintf(stderr, "lseek: ");
639 perror(namebuf);
640 close(fd);
641 return(1);
643 if ((readret = read(fd, buf, length)) < length)
645 fprintf(stderr, "read (%d %ld) -> %d\n", fd, length, readret);
646 perror(namebuf);
647 close(fd);
648 t_freebytes(buf, length);
649 return(1);
651 /* optionally map carriage return to semicolon */
652 if (crflag)
654 int i;
655 for (i = 0; i < length; i++)
656 if (buf[i] == '\n')
657 buf[i] = ';';
659 binbuf_text(b, buf, length);
661 #if 0
662 startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost();
663 #endif
665 t_freebytes(buf, length);
666 close(fd);
667 return (0);
670 int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
671 int crflag)
673 int filedesc;
674 char buf[MAXPDSTRING], *bufptr;
675 if ((filedesc = open_via_path(
676 dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0)
678 error("%s: can't open", filename);
679 return (1);
681 else close (filedesc);
682 if (binbuf_read(b, bufptr, buf, crflag))
683 return (1);
684 else return (0);
687 #define WBUFSIZE 4096
688 static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd);
690 /* write a binbuf to a text file. If "crflag" is set we suppress
691 semicolons. */
692 int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
694 FILE *f = 0;
695 char sbuf[WBUFSIZE], fbuf[MAXPDSTRING], *bp = sbuf, *ep = sbuf + WBUFSIZE;
696 t_atom *ap;
697 int indx, deleteit = 0;
698 int ncolumn = 0;
700 fbuf[0] = 0;
701 if (*dir)
702 strcat(fbuf, dir), strcat(fbuf, "/");
703 strcat(fbuf, filename);
704 if (!strcmp(filename + strlen(filename) - 4, ".pat"))
706 x = binbuf_convert(x, 0);
707 deleteit = 1;
710 if (!(f = binbuf_dofopen(fbuf, "w")))
712 fprintf(stderr, "open: ");
713 sys_unixerror(fbuf);
714 goto fail;
716 for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
718 int length;
719 /* estimate how many characters will be needed. Printing out
720 symbols may need extra characters for inserting backslashes. */
721 if (ap->a_type == A_SYMBOL || ap->a_type == A_DOLLSYM)
722 length = 80 + strlen(ap->a_w.w_symbol->s_name);
723 else length = 40;
724 if (ep - bp < length)
726 if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
728 sys_unixerror(fbuf);
729 goto fail;
731 bp = sbuf;
733 if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
734 bp > sbuf && bp[-1] == ' ') bp--;
735 if (!crflag || ap->a_type != A_SEMI)
737 atom_string(ap, bp, (ep-bp)-2);
738 length = strlen(bp);
739 bp += length;
740 ncolumn += length;
742 if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65))
744 *bp++ = '\n';
745 ncolumn = 0;
747 else
749 *bp++ = ' ';
750 ncolumn++;
753 if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
755 sys_unixerror(fbuf);
756 goto fail;
758 if (deleteit)
759 binbuf_free(x);
760 fclose(f);
761 return (0);
762 fail:
763 if (deleteit)
764 binbuf_free(x);
765 if (f)
766 fclose(f);
767 return (1);
770 /* The following routine attempts to convert from max to pd or back. The
771 max to pd direction is working OK but you will need to make lots of
772 abstractions for objects like "gate" which don't exist in Pd. conversion
773 from Pd to Max hasn't been tested for patches with subpatches yet! */
775 #define MAXSTACK 1000
777 #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \
778 !strcmp((a)->a_w.w_symbol->s_name, (b)))
780 static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
782 t_binbuf *newb = binbuf_new();
783 t_atom *vec = oldb->b_vec;
784 t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK],
785 nobj = 0, i;
786 t_atom outmess[MAXSTACK], *nextmess;
787 if (!maxtopd)
788 binbuf_addv(newb, "ss;", gensym("max"), gensym("v2"));
789 for (nextindex = 0; nextindex < n; )
791 int endmess, natom;
792 char *first, *second;
793 for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI;
794 endmess++)
796 if (endmess == n) break;
797 if (endmess == nextindex || endmess == nextindex + 1
798 || vec[nextindex].a_type != A_SYMBOL ||
799 vec[nextindex+1].a_type != A_SYMBOL)
801 nextindex = endmess + 1;
802 continue;
804 natom = endmess - nextindex;
805 if (natom > MAXSTACK-10) natom = MAXSTACK-10;
806 nextmess = vec + nextindex;
807 first = nextmess->a_w.w_symbol->s_name;
808 second = (nextmess+1)->a_w.w_symbol->s_name;
809 if (maxtopd)
811 /* case 1: importing a ".pat" file into Pd. */
813 /* dollar signs in file translate to symbols */
814 for (i = 0; i < natom; i++)
816 if (nextmess[i].a_type == A_DOLLAR)
818 char buf[100];
819 sprintf(buf, "$%d", nextmess[i].a_w.w_index);
820 SETSYMBOL(nextmess+i, gensym(buf));
822 else if (nextmess[i].a_type == A_DOLLSYM)
824 char buf[100];
825 sprintf(buf, "$%s", nextmess[i].a_w.w_symbol->s_name);
826 SETSYMBOL(nextmess+i, gensym(buf));
829 if (!strcmp(first, "#N"))
831 if (!strcmp(second, "vpatcher"))
833 if (stackdepth >= MAXSTACK)
835 post("too many embedded patches");
836 return (newb);
838 stack[stackdepth] = nobj;
839 stackdepth++;
840 nobj = 0;
841 binbuf_addv(newb, "ssfffff;",
842 gensym("#N"), gensym("canvas"),
843 atom_getfloatarg(2, natom, nextmess),
844 atom_getfloatarg(3, natom, nextmess),
845 atom_getfloatarg(4, natom, nextmess) -
846 atom_getfloatarg(2, natom, nextmess),
847 atom_getfloatarg(5, natom, nextmess) -
848 atom_getfloatarg(3, natom, nextmess),
849 (float)sys_defaultfont);
852 if (!strcmp(first, "#P"))
854 /* drop initial "hidden" flag */
855 if (!strcmp(second, "hidden"))
857 nextmess++;
858 natom--;
859 second = (nextmess+1)->a_w.w_symbol->s_name;
861 if (natom >= 7 && !strcmp(second, "newobj")
862 && (ISSYMBOL(&nextmess[6], "patcher") ||
863 ISSYMBOL(&nextmess[6], "p")))
865 binbuf_addv(newb, "ssffss;",
866 gensym("#X"), gensym("restore"),
867 atom_getfloatarg(2, natom, nextmess),
868 atom_getfloatarg(3, natom, nextmess),
869 gensym("pd"), atom_getsymbolarg(7, natom, nextmess));
870 if (stackdepth) stackdepth--;
871 nobj = stack[stackdepth];
872 nobj++;
874 else if (!strcmp(second, "newex") || !strcmp(second, "newobj"))
876 t_symbol *classname =
877 atom_getsymbolarg(6, natom, nextmess);
878 if (classname == gensym("trigger") ||
879 classname == gensym("t"))
881 for (i = 7; i < natom; i++)
882 if (nextmess[i].a_type == A_SYMBOL &&
883 nextmess[i].a_w.w_symbol == gensym("i"))
884 nextmess[i].a_w.w_symbol = gensym("f");
886 if (classname == gensym("table"))
887 classname = gensym("TABLE");
888 SETSYMBOL(outmess, gensym("#X"));
889 SETSYMBOL(outmess + 1, gensym("obj"));
890 outmess[2] = nextmess[2];
891 outmess[3] = nextmess[3];
892 SETSYMBOL(outmess+4, classname);
893 for (i = 7; i < natom; i++)
894 outmess[i-2] = nextmess[i];
895 SETSEMI(outmess + natom - 2);
896 binbuf_add(newb, natom - 1, outmess);
897 nobj++;
899 else if (!strcmp(second, "message") ||
900 !strcmp(second, "comment"))
902 SETSYMBOL(outmess, gensym("#X"));
903 SETSYMBOL(outmess + 1, gensym(
904 (strcmp(second, "message") ? "text" : "msg")));
905 outmess[2] = nextmess[2];
906 outmess[3] = nextmess[3];
907 for (i = 6; i < natom; i++)
908 outmess[i-2] = nextmess[i];
909 SETSEMI(outmess + natom - 2);
910 binbuf_add(newb, natom - 1, outmess);
911 nobj++;
913 else if (!strcmp(second, "button"))
915 binbuf_addv(newb, "ssffs;",
916 gensym("#X"), gensym("obj"),
917 atom_getfloatarg(2, natom, nextmess),
918 atom_getfloatarg(3, natom, nextmess),
919 gensym("bng"));
920 nobj++;
922 else if (!strcmp(second, "number") || !strcmp(second, "flonum"))
924 binbuf_addv(newb, "ssff;",
925 gensym("#X"), gensym("floatatom"),
926 atom_getfloatarg(2, natom, nextmess),
927 atom_getfloatarg(3, natom, nextmess));
928 nobj++;
930 else if (!strcmp(second, "slider"))
932 float inc = atom_getfloatarg(7, natom, nextmess);
933 if (inc <= 0)
934 inc = 1;
935 binbuf_addv(newb, "ssffsffffffsssfffffffff;",
936 gensym("#X"), gensym("obj"),
937 atom_getfloatarg(2, natom, nextmess),
938 atom_getfloatarg(3, natom, nextmess),
939 gensym("vsl"),
940 atom_getfloatarg(4, natom, nextmess),
941 atom_getfloatarg(5, natom, nextmess),
942 atom_getfloatarg(6, natom, nextmess),
943 atom_getfloatarg(6, natom, nextmess)
944 + (atom_getfloatarg(5, natom, nextmess) - 1) * inc,
945 0., 0.,
946 gensym("empty"), gensym("empty"), gensym("empty"),
947 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
948 nobj++;
950 else if (!strcmp(second, "toggle"))
952 binbuf_addv(newb, "ssffs;",
953 gensym("#X"), gensym("obj"),
954 atom_getfloatarg(2, natom, nextmess),
955 atom_getfloatarg(3, natom, nextmess),
956 gensym("tgl"));
957 nobj++;
959 else if (!strcmp(second, "inlet"))
961 binbuf_addv(newb, "ssffs;",
962 gensym("#X"), gensym("obj"),
963 atom_getfloatarg(2, natom, nextmess),
964 atom_getfloatarg(3, natom, nextmess),
965 gensym((natom > 5 ? "inlet~" : "inlet")));
966 nobj++;
968 else if (!strcmp(second, "outlet"))
970 binbuf_addv(newb, "ssffs;",
971 gensym("#X"), gensym("obj"),
972 atom_getfloatarg(2, natom, nextmess),
973 atom_getfloatarg(3, natom, nextmess),
974 gensym((natom > 5 ? "outlet~" : "outlet")));
975 nobj++;
977 else if (!strcmp(second, "user"))
979 binbuf_addv(newb, "ssffs;",
980 gensym("#X"), gensym("obj"),
981 atom_getfloatarg(3, natom, nextmess),
982 atom_getfloatarg(4, natom, nextmess),
983 atom_getsymbolarg(2, natom, nextmess));
984 nobj++;
986 else if (!strcmp(second, "connect")||
987 !strcmp(second, "fasten"))
989 binbuf_addv(newb, "ssffff;",
990 gensym("#X"), gensym("connect"),
991 nobj - atom_getfloatarg(2, natom, nextmess) - 1,
992 atom_getfloatarg(3, natom, nextmess),
993 nobj - atom_getfloatarg(4, natom, nextmess) - 1,
994 atom_getfloatarg(5, natom, nextmess));
998 else /* Pd to Max */
1000 if (!strcmp(first, "#N"))
1002 if (!strcmp(second, "canvas"))
1004 if (stackdepth >= MAXSTACK)
1006 post("too many embedded patches");
1007 return (newb);
1009 stack[stackdepth] = nobj;
1010 stackdepth++;
1011 nobj = 0;
1012 binbuf_addv(newb, "ssffff;",
1013 gensym("#N"), gensym("vpatcher"),
1014 atom_getfloatarg(2, natom, nextmess),
1015 atom_getfloatarg(3, natom, nextmess),
1016 atom_getfloatarg(4, natom, nextmess),
1017 atom_getfloatarg(5, natom, nextmess));
1020 if (!strcmp(first, "#X"))
1022 if (natom >= 5 && !strcmp(second, "restore")
1023 && (ISSYMBOL (&nextmess[4], "pd")))
1025 binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
1026 binbuf_addv(newb, "ssffffss;",
1027 gensym("#P"), gensym("newobj"),
1028 atom_getfloatarg(2, natom, nextmess),
1029 atom_getfloatarg(3, natom, nextmess), 50., 1.,
1030 gensym("patcher"),
1031 atom_getsymbolarg(5, natom, nextmess));
1032 if (stackdepth) stackdepth--;
1033 nobj = stack[stackdepth];
1034 nobj++;
1036 else if (!strcmp(second, "obj"))
1038 t_symbol *classname =
1039 atom_getsymbolarg(4, natom, nextmess);
1040 if (classname == gensym("inlet"))
1041 binbuf_addv(newb, "ssfff;", gensym("#P"),
1042 gensym("inlet"),
1043 atom_getfloatarg(2, natom, nextmess),
1044 atom_getfloatarg(3, natom, nextmess),
1045 15.);
1046 else if (classname == gensym("inlet~"))
1047 binbuf_addv(newb, "ssffff;", gensym("#P"),
1048 gensym("inlet"),
1049 atom_getfloatarg(2, natom, nextmess),
1050 atom_getfloatarg(3, natom, nextmess),
1051 15., 1.);
1052 else if (classname == gensym("outlet"))
1053 binbuf_addv(newb, "ssfff;", gensym("#P"),
1054 gensym("outlet"),
1055 atom_getfloatarg(2, natom, nextmess),
1056 atom_getfloatarg(3, natom, nextmess),
1057 15.);
1058 else if (classname == gensym("outlet~"))
1059 binbuf_addv(newb, "ssffff;", gensym("#P"),
1060 gensym("outlet"),
1061 atom_getfloatarg(2, natom, nextmess),
1062 atom_getfloatarg(3, natom, nextmess),
1063 15., 1.);
1064 else if (classname == gensym("bng"))
1065 binbuf_addv(newb, "ssffff;", gensym("#P"),
1066 gensym("button"),
1067 atom_getfloatarg(2, natom, nextmess),
1068 atom_getfloatarg(3, natom, nextmess),
1069 atom_getfloatarg(5, natom, nextmess), 0.);
1070 else if (classname == gensym("tgl"))
1071 binbuf_addv(newb, "ssffff;", gensym("#P"),
1072 gensym("toggle"),
1073 atom_getfloatarg(2, natom, nextmess),
1074 atom_getfloatarg(3, natom, nextmess),
1075 atom_getfloatarg(5, natom, nextmess), 0.);
1076 else if (classname == gensym("vsl"))
1077 binbuf_addv(newb, "ssffffff;", gensym("#P"),
1078 gensym("slider"),
1079 atom_getfloatarg(2, natom, nextmess),
1080 atom_getfloatarg(3, natom, nextmess),
1081 atom_getfloatarg(5, natom, nextmess),
1082 atom_getfloatarg(6, natom, nextmess),
1083 (atom_getfloatarg(8, natom, nextmess) -
1084 atom_getfloatarg(7, natom, nextmess)) /
1085 (atom_getfloatarg(6, natom, nextmess) == 1? 1 :
1086 atom_getfloatarg(6, natom, nextmess) - 1),
1087 atom_getfloatarg(7, natom, nextmess));
1088 else
1090 SETSYMBOL(outmess, gensym("#P"));
1091 SETSYMBOL(outmess + 1, gensym("newex"));
1092 outmess[2] = nextmess[2];
1093 outmess[3] = nextmess[3];
1094 SETFLOAT(outmess + 4, 50);
1095 SETFLOAT(outmess + 5, 1);
1096 for (i = 4; i < natom; i++)
1097 outmess[i+2] = nextmess[i];
1098 SETSEMI(outmess + natom + 2);
1099 binbuf_add(newb, natom + 3, outmess);
1101 nobj++;
1104 else if (!strcmp(second, "msg") ||
1105 !strcmp(second, "text"))
1107 SETSYMBOL(outmess, gensym("#P"));
1108 SETSYMBOL(outmess + 1, gensym(
1109 (strcmp(second, "msg") ? "comment" : "message")));
1110 outmess[2] = nextmess[2];
1111 outmess[3] = nextmess[3];
1112 SETFLOAT(outmess + 4, 50);
1113 SETFLOAT(outmess + 5, 1);
1114 for (i = 4; i < natom; i++)
1115 outmess[i+2] = nextmess[i];
1116 SETSEMI(outmess + natom + 2);
1117 binbuf_add(newb, natom + 3, outmess);
1118 nobj++;
1120 else if (!strcmp(second, "floatatom"))
1122 binbuf_addv(newb, "ssfff;",
1123 gensym("#P"), gensym("flonum"),
1124 atom_getfloatarg(2, natom, nextmess),
1125 atom_getfloatarg(3, natom, nextmess), 35);
1126 nobj++;
1128 else if (!strcmp(second, "connect"))
1130 binbuf_addv(newb, "ssffff;",
1131 gensym("#P"), gensym("connect"),
1132 nobj - atom_getfloatarg(2, natom, nextmess) - 1,
1133 atom_getfloatarg(3, natom, nextmess),
1134 nobj - atom_getfloatarg(4, natom, nextmess) - 1,
1135 atom_getfloatarg(5, natom, nextmess));
1139 nextindex = endmess + 1;
1141 if (!maxtopd)
1142 binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
1143 #if 0
1144 binbuf_write(newb, "import-result.pd", "/tmp", 0);
1145 #endif
1146 return (newb);
1149 /* function to support searching */
1150 int binbuf_match(t_binbuf *inbuf, t_binbuf *searchbuf)
1152 int indexin, nmatched;
1153 for (indexin = 0; indexin <= inbuf->b_n - searchbuf->b_n; indexin++)
1155 for (nmatched = 0; nmatched < searchbuf->b_n; nmatched++)
1157 t_atom *a1 = &inbuf->b_vec[indexin + nmatched],
1158 *a2 = &searchbuf->b_vec[nmatched];
1159 if (a1->a_type != a2->a_type ||
1160 a1->a_type == A_SYMBOL && a1->a_w.w_symbol != a2->a_w.w_symbol
1162 a1->a_type == A_FLOAT && a1->a_w.w_float != a2->a_w.w_float
1164 a1->a_type == A_DOLLAR && a1->a_w.w_index != a2->a_w.w_index
1166 a1->a_type == A_DOLLSYM && a1->a_w.w_symbol != a2->a_w.w_symbol)
1167 goto nomatch;
1169 return (1);
1170 nomatch: ;
1172 return (0);
1175 void pd_doloadbang(void);
1177 /* LATER make this evaluate the file on-the-fly. */
1178 /* LATER figure out how to log errors */
1179 void binbuf_evalfile(t_symbol *name, t_symbol *dir)
1181 t_binbuf *b = binbuf_new();
1182 int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat");
1183 /* set filename so that new canvases can pick them up */
1184 int dspstate = canvas_suspend_dsp();
1185 glob_setfilename(0, name, dir);
1186 if (binbuf_read(b, name->s_name, dir->s_name, 0))
1188 perror(name->s_name);
1190 else
1192 if (import)
1194 t_binbuf *newb = binbuf_convert(b, 1);
1195 binbuf_free(b);
1196 b = newb;
1198 binbuf_eval(b, 0, 0, 0);
1200 glob_setfilename(0, &s_, &s_); /* bug fix by Krzysztof Czaja */
1201 binbuf_free(b);
1202 canvas_resume_dsp(dspstate);
1205 void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
1207 t_pd *x = 0;
1208 /* even though binbuf_evalfile appears to take care of dspstate,
1209 we have to do it again here, because canvas_startdsp() assumes
1210 that all toplevel canvases are visible. LATER check if this
1211 is still necessary -- probably not. */
1213 int dspstate = canvas_suspend_dsp();
1214 binbuf_evalfile(name, dir);
1215 while ((x != s__X.s_thing) && (x = s__X.s_thing))
1216 vmess(x, gensym("pop"), "i", 1);
1217 pd_doloadbang();
1218 canvas_resume_dsp(dspstate);
1220 /* Copyright (c) 1997-1999 Miller Puckette.
1221 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
1222 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
1225 /* IOhannes :
1226 * changed the canvas_restore in "g_canvas.c", so that it might accept $args as well (like "pd $0_test")
1227 * so you can make multiple & distinguishable templates
1228 * 1511:forum::für::umläute:2001
1229 * change marked with IOhannes
1232 #include <stdlib.h>
1233 #include "m_pd.h"
1234 #include "s_stuff.h"
1235 #include <stdio.h>
1236 #ifdef UNIX
1237 #include <unistd.h>
1238 #endif
1239 #ifdef MSW
1240 #include <io.h>
1241 #endif
1242 #include <fcntl.h>
1243 #include <string.h>
1244 #include <stdarg.h>
1246 struct _binbuf
1248 int b_n;
1249 t_atom *b_vec;
1252 t_binbuf *binbuf_new(void)
1254 t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
1255 x->b_n = 0;
1256 x->b_vec = t_getbytes(0);
1257 return (x);
1260 void binbuf_free(t_binbuf *x)
1262 t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
1263 t_freebytes(x, sizeof(*x));
1266 t_binbuf *binbuf_duplicate(t_binbuf *y)
1268 t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
1269 x->b_n = y->b_n;
1270 x->b_vec = t_getbytes(x->b_n * sizeof(*x->b_vec));
1271 memcpy(x->b_vec, y->b_vec, x->b_n * sizeof(*x->b_vec));
1272 return (x);
1275 void binbuf_clear(t_binbuf *x)
1277 x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0);
1278 x->b_n = 0;
1281 /* convert text to a binbuf */
1282 void binbuf_text(t_binbuf *x, char *text, size_t size)
1284 char buf[MAXPDSTRING+1], *bufp, *ebuf = buf+MAXPDSTRING;
1285 const char *textp = text, *etext = text+size;
1286 t_atom *ap;
1287 int nalloc = 16, natom = 0;
1288 t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
1289 x->b_vec = t_getbytes(nalloc * sizeof(*x->b_vec));
1290 ap = x->b_vec;
1291 x->b_n = 0;
1292 while (1)
1294 int type;
1295 /* skip leading space */
1296 while ((textp != etext) && (*textp == ' ' || *textp == '\n'
1297 || *textp == '\r' || *textp == '\t')) textp++;
1298 if (textp == etext) break;
1299 if (*textp == ';') SETSEMI(ap), textp++;
1300 else if (*textp == ',') SETCOMMA(ap), textp++;
1301 else
1303 /* it's an atom other than a comma or semi */
1304 char c;
1305 int floatstate = 0, slash = 0, lastslash = 0,
1306 firstslash = (*textp == '\\');
1307 bufp = buf;
1310 c = *bufp = *textp++;
1311 lastslash = slash;
1312 slash = (c == '\\');
1314 if (floatstate >= 0)
1316 int digit = (c >= '0' && c <= '9'),
1317 dot = (c == '.'), minus = (c == '-'),
1318 plusminus = (minus || (c == '+')),
1319 expon = (c == 'e' || c == 'E');
1320 if (floatstate == 0) /* beginning */
1322 if (minus) floatstate = 1;
1323 else if (digit) floatstate = 2;
1324 else if (dot) floatstate = 3;
1325 else floatstate = -1;
1327 else if (floatstate == 1) /* got minus */
1329 if (digit) floatstate = 2;
1330 else if (dot) floatstate = 3;
1331 else floatstate = -1;
1333 else if (floatstate == 2) /* got digits */
1335 if (dot) floatstate = 4;
1336 else if (expon) floatstate = 6;
1337 else if (!digit) floatstate = -1;
1339 else if (floatstate == 3) /* got '.' without digits */
1341 if (digit) floatstate = 5;
1342 else floatstate = -1;
1344 else if (floatstate == 4) /* got '.' after digits */
1346 if (digit) floatstate = 5;
1347 else if (expon) floatstate = 6;
1348 else floatstate = -1;
1350 else if (floatstate == 5) /* got digits after . */
1352 if (expon) floatstate = 6;
1353 else if (!digit) floatstate = -1;
1355 else if (floatstate == 6) /* got 'e' */
1357 if (plusminus) floatstate = 7;
1358 else if (digit) floatstate = 8;
1359 else floatstate = -1;
1361 else if (floatstate == 7) /* got plus or minus */
1363 if (digit) floatstate = 8;
1364 else floatstate = -1;
1366 else if (floatstate == 8) /* got digits */
1368 if (!digit) floatstate = -1;
1371 if (!slash) bufp++;
1373 while (textp != etext && bufp != ebuf &&
1374 (slash || (*textp != ' ' && *textp != '\n' && *textp != '\r'
1375 && *textp != '\t' &&*textp != ',' && *textp != ';')));
1376 *bufp = 0;
1377 #if 0
1378 post("buf %s", buf);
1379 #endif
1380 if (*buf == '$' && buf[1] >= '0' && buf[1] <= '9' && !firstslash)
1382 for (bufp = buf+2; *bufp; bufp++)
1383 if (*bufp < '0' || *bufp > '9')
1385 SETDOLLSYM(ap, gensym(buf+1));
1386 goto didit;
1388 SETDOLLAR(ap, atoi(buf+1));
1389 didit: ;
1391 else
1393 if (floatstate == 2 || floatstate == 4 || floatstate == 5 ||
1394 floatstate == 8)
1395 SETFLOAT(ap, atof(buf));
1396 else SETSYMBOL(ap, gensym(buf));
1399 ap++;
1400 natom++;
1401 if (natom == nalloc)
1403 x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
1404 nalloc * (2*sizeof(*x->b_vec)));
1405 nalloc = nalloc * 2;
1406 ap = x->b_vec + natom;
1408 if (textp == etext) break;
1410 /* reallocate the vector to exactly the right size */
1411 x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
1412 natom * sizeof(*x->b_vec));
1413 x->b_n = natom;
1416 /* convert a binbuf to text; no null termination. */
1417 void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp)
1419 char *buf = getbytes(0), *newbuf;
1420 int length = 0;
1421 char string[MAXPDSTRING];
1422 t_atom *ap;
1423 int indx;
1425 for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
1427 int newlength;
1428 if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
1429 length && buf[length-1] == ' ') length--;
1430 atom_string(ap, string, MAXPDSTRING);
1431 newlength = length + strlen(string) + 1;
1432 if (!(newbuf = resizebytes(buf, length, newlength))) break;
1433 buf = newbuf;
1434 strcpy(buf + length, string);
1435 length = newlength;
1436 if (ap->a_type == A_SEMI) buf[length-1] = '\n';
1437 else buf[length-1] = ' ';
1439 if (length && buf[length-1] == ' ')
1441 if (newbuf = t_resizebytes(buf, length, length-1))
1443 buf = newbuf;
1444 length--;
1447 *bufp = buf;
1448 *lengthp = length;
1451 /* LATER improve the out-of-space behavior below. Also fix this so that
1452 writing to file doesn't buffer everything together. */
1454 void binbuf_add(t_binbuf *x, int argc, t_atom *argv)
1456 int newsize = x->b_n + argc, i;
1457 t_atom *ap;
1458 if (ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
1459 newsize * sizeof(*x->b_vec)))
1460 x->b_vec = ap;
1461 else
1463 error("binbuf_addmessage: out of space");
1464 return;
1466 #if 0
1467 startpost("binbuf_add: ");
1468 postatom(argc, argv);
1469 endpost();
1470 #endif
1471 for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
1472 *ap = *(argv++);
1473 x->b_n = newsize;
1476 #define MAXADDMESSV 100
1477 void binbuf_addv(t_binbuf *x, char *fmt, ...)
1479 va_list ap;
1480 t_atom arg[MAXADDMESSV], *at =arg;
1481 int nargs = 0;
1482 char *fp = fmt;
1484 va_start(ap, fmt);
1485 while (1)
1487 if (nargs >= MAXADDMESSV)
1489 error("binbuf_addmessv: only %d allowed", MAXADDMESSV);
1490 break;
1492 switch(*fp++)
1494 case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
1495 case 'f': SETFLOAT(at, va_arg(ap, double)); break;
1496 case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
1497 case ';': SETSEMI(at); break;
1498 case ',': SETCOMMA(at); break;
1499 default: goto done;
1501 at++;
1502 nargs++;
1504 done:
1505 va_end(ap);
1506 binbuf_add(x, nargs, arg);
1509 /* add a binbuf to another one for saving. Semicolons and commas go to
1510 symbols ";", "'",; the symbol ";" goes to "\;", etc. */
1512 void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y)
1514 t_binbuf *z = binbuf_new();
1515 int i;
1516 t_atom *ap;
1517 binbuf_add(z, y->b_n, y->b_vec);
1518 for (i = 0, ap = z->b_vec; i < z->b_n; i++, ap++)
1520 char tbuf[MAXPDSTRING];
1521 switch (ap->a_type)
1523 case A_FLOAT:
1524 break;
1525 case A_SEMI:
1526 SETSYMBOL(ap, gensym(";"));
1527 break;
1528 case A_COMMA:
1529 SETSYMBOL(ap, gensym(","));
1530 break;
1531 case A_DOLLAR:
1532 sprintf(tbuf, "$%d", ap->a_w.w_index);
1533 SETSYMBOL(ap, gensym(tbuf));
1534 break;
1535 case A_DOLLSYM:
1536 sprintf(tbuf, "$%s", ap->a_w.w_symbol->s_name);
1537 SETSYMBOL(ap, gensym(tbuf));
1538 break;
1539 case A_SYMBOL:
1540 /* FIXME make this general */
1541 if (!strcmp(ap->a_w.w_symbol->s_name, ";"))
1542 SETSYMBOL(ap, gensym(";"));
1543 else if (!strcmp(ap->a_w.w_symbol->s_name, ","))
1544 SETSYMBOL(ap, gensym(","));
1545 break;
1546 default:
1547 bug("binbuf_addbinbuf");
1551 binbuf_add(x, z->b_n, z->b_vec);
1554 void binbuf_addsemi(t_binbuf *x)
1556 t_atom a;
1557 SETSEMI(&a);
1558 binbuf_add(x, 1, &a);
1561 /* Supply atoms to a binbuf from a message, making the opposite changes
1562 from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
1564 void binbuf_restore(t_binbuf *x, int argc, t_atom *argv)
1566 int newsize = x->b_n + argc, i;
1567 t_atom *ap;
1568 if (ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
1569 newsize * sizeof(*x->b_vec)))
1570 x->b_vec = ap;
1571 else
1573 error("binbuf_addmessage: out of space");
1574 return;
1577 for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
1579 if (argv->a_type == A_SYMBOL)
1581 char *str = argv->a_w.w_symbol->s_name;
1582 if (!strcmp(str, ";")) SETSEMI(ap);
1583 else if (!strcmp(str, ",")) SETCOMMA(ap);
1584 else if (str[0] == '$' && str[1] >= '0' && str[1] <= '9')
1586 int dollsym = 0;
1587 char *str2;
1588 for (str2 = str + 2; *str2; str2++)
1589 if (*str2 < '0' || *str2 > '9')
1590 dollsym = 1;
1591 if (dollsym)
1592 SETDOLLSYM(ap, gensym(str + 1));
1593 else
1595 int dollar = 0;
1596 sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar);
1597 SETDOLLAR(ap, dollar);
1600 else *ap = *argv;
1601 argv++;
1603 else *ap = *(argv++);
1605 x->b_n = newsize;
1609 #define MSTACKSIZE 2048
1611 void binbuf_print(t_binbuf *x)
1613 int i, startedpost = 0, newline = 1;
1614 for (i = 0; i < x->b_n; i++)
1616 if (newline)
1618 if (startedpost) endpost();
1619 startpost("");
1620 startedpost = 1;
1622 postatom(1, x->b_vec + i);
1623 if (x->b_vec[i].a_type == A_SEMI)
1624 newline = 1;
1625 else newline = 0;
1627 if (startedpost) endpost();
1630 int binbuf_getnatom(t_binbuf *x)
1632 return (x->b_n);
1635 t_atom *binbuf_getvec(t_binbuf *x)
1637 return (x->b_vec);
1640 int canvas_getdollarzero( void);
1642 t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
1644 int argno = atol(s->s_name), lastnum;
1645 char buf[MAXPDSTRING], c, *sp;
1646 for (lastnum = 0, sp = s->s_name; ((c = *sp) && c >= '0' && c <= '9');
1647 sp++, lastnum++)
1648 if (!c || argno < 0 || argno > ac)
1650 if (!tonew)
1651 return (0);
1652 else sprintf(buf, "$%d", argno);
1654 else if (argno == 0)
1655 sprintf(buf, "%d", canvas_getdollarzero());
1656 else
1657 atom_string(av+(argno-1), buf, MAXPDSTRING/2-1);
1658 strncat(buf, sp, MAXPDSTRING/2-1);
1659 return (gensym(buf));
1662 void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
1664 static t_atom mstack[MSTACKSIZE], *msp = mstack, *ems = mstack+MSTACKSIZE;
1665 t_atom *stackwas = msp;
1666 t_atom *at = x->b_vec;
1667 int ac = x->b_n;
1668 int nargs;
1669 while (1)
1671 t_pd *nexttarget;
1672 /* get a target. */
1673 while (!target)
1675 t_symbol *s;
1676 while (ac && (at->a_type == A_SEMI || at->a_type == A_COMMA))
1677 ac--, at++;
1678 if (!ac) break;
1679 if (at->a_type == A_DOLLAR)
1681 if (at->a_w.w_index <= 0 || at->a_w.w_index > argc)
1683 error("$%d: not enough arguments supplied",
1684 at->a_w.w_index);
1685 goto cleanup;
1687 else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL)
1689 error("$%d: symbol needed as message destination",
1690 at->a_w.w_index);
1691 goto cleanup;
1693 else s = argv[at->a_w.w_index-1].a_w.w_symbol;
1695 else if (at->a_type == A_DOLLSYM)
1697 if (!(s = binbuf_realizedollsym(at->a_w.w_symbol,
1698 argc, argv, 0)))
1700 error("$%s: not enough arguments supplied",
1701 at->a_w.w_symbol->s_name);
1702 goto cleanup;
1705 else s = atom_getsymbol(at);
1706 if (!(target = s->s_thing))
1708 error("%s: no such object", s->s_name);
1709 cleanup:
1710 do at++, ac--;
1711 while (ac && at->a_type != A_SEMI);
1712 /* LATER eat args until semicolon and continue */
1713 continue;
1715 else
1717 at++, ac--;
1718 break;
1721 if (!ac) break;
1722 nargs = 0;
1723 nexttarget = target;
1724 while (1)
1726 t_symbol *s9;
1727 if (!ac) goto gotmess;
1728 if (msp >= ems)
1730 error("message stack overflow");
1731 goto broken;
1733 switch (at->a_type)
1735 case A_SEMI:
1736 /* semis and commas in new message just get bashed to
1737 a symbol. This is needed so you can pass them to "expr." */
1738 if (target == &pd_objectmaker)
1740 SETSYMBOL(msp, gensym(";"));
1741 break;
1743 else
1745 nexttarget = 0;
1746 goto gotmess;
1748 case A_COMMA:
1749 if (target == &pd_objectmaker)
1751 SETSYMBOL(msp, gensym(","));
1752 break;
1754 else goto gotmess;
1755 case A_FLOAT:
1756 case A_SYMBOL:
1757 *msp = *at;
1758 break;
1759 case A_DOLLAR:
1760 if (at->a_w.w_index > 0 && at->a_w.w_index <= argc)
1761 *msp = argv[at->a_w.w_index-1];
1762 else if (at->a_w.w_index == 0)
1763 SETFLOAT(msp, canvas_getdollarzero());
1764 else
1766 if (target == &pd_objectmaker)
1767 SETFLOAT(msp, 0);
1768 else
1770 error("$%d: argument number out of range",
1771 at->a_w.w_index);
1772 SETFLOAT(msp, 0);
1775 break;
1776 case A_DOLLSYM:
1777 s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv,
1778 target == &pd_objectmaker);
1779 if (!s9)
1780 goto broken;
1781 SETSYMBOL(msp, s9);
1782 break;
1783 default:
1784 bug("bad item in binbuf");
1785 goto broken;
1787 msp++;
1788 ac--;
1789 at++;
1790 nargs++;
1792 gotmess:
1793 if (nargs)
1795 switch (stackwas->a_type)
1797 case A_SYMBOL:
1798 typedmess(target, stackwas->a_w.w_symbol, nargs-1, stackwas+1);
1799 break;
1800 case A_FLOAT:
1801 if (nargs == 1) pd_float(target, stackwas->a_w.w_float);
1802 else pd_list(target, 0, nargs, stackwas);
1803 break;
1806 msp = stackwas;
1807 if (!ac) break;
1808 target = nexttarget;
1809 at++;
1810 ac--;
1813 return;
1814 broken:
1815 msp = stackwas;
1818 static int binbuf_doopen(char *s, int mode)
1820 char namebuf[MAXPDSTRING];
1821 #ifdef MSW
1822 mode |= O_BINARY;
1823 #endif
1824 sys_bashfilename(s, namebuf);
1825 return (open(namebuf, mode));
1828 static FILE *binbuf_dofopen(char *s, char *mode)
1830 char namebuf[MAXPDSTRING];
1831 sys_bashfilename(s, namebuf);
1832 return (fopen(namebuf, mode));
1835 int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag)
1837 long length;
1838 int fd;
1839 int readret;
1840 char *buf;
1841 char namebuf[MAXPDSTRING];
1843 namebuf[0] = 0;
1844 if (*dirname)
1845 strcat(namebuf, dirname), strcat(namebuf, "/");
1846 strcat(namebuf, filename);
1848 if ((fd = binbuf_doopen(namebuf, 0)) < 0)
1850 fprintf(stderr, "open: ");
1851 perror(namebuf);
1852 return (1);
1854 if ((length = lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0
1855 || !(buf = t_getbytes(length)))
1857 fprintf(stderr, "lseek: ");
1858 perror(namebuf);
1859 close(fd);
1860 return(1);
1862 if ((readret = read(fd, buf, length)) < length)
1864 fprintf(stderr, "read (%d %ld) -> %d\n", fd, length, readret);
1865 perror(namebuf);
1866 close(fd);
1867 t_freebytes(buf, length);
1868 return(1);
1870 /* optionally map carriage return to semicolon */
1871 if (crflag)
1873 int i;
1874 for (i = 0; i < length; i++)
1875 if (buf[i] == '\n')
1876 buf[i] = ';';
1878 binbuf_text(b, buf, length);
1880 #if 0
1881 startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost();
1882 #endif
1884 t_freebytes(buf, length);
1885 close(fd);
1886 return (0);
1889 int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
1890 int crflag)
1892 int filedesc;
1893 char buf[MAXPDSTRING], *bufptr;
1894 if ((filedesc = open_via_path(
1895 dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0)
1897 error("%s: can't open", filename);
1898 return (1);
1900 else close (filedesc);
1901 if (binbuf_read(b, bufptr, buf, crflag))
1902 return (1);
1903 else return (0);
1906 #define WBUFSIZE 4096
1907 static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd);
1909 /* write a binbuf to a text file. If "crflag" is set we suppress
1910 semicolons. */
1911 int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
1913 FILE *f = 0;
1914 char sbuf[WBUFSIZE], fbuf[MAXPDSTRING], *bp = sbuf, *ep = sbuf + WBUFSIZE;
1915 t_atom *ap;
1916 int indx, deleteit = 0;
1917 int ncolumn = 0;
1919 fbuf[0] = 0;
1920 if (*dir)
1921 strcat(fbuf, dir), strcat(fbuf, "/");
1922 strcat(fbuf, filename);
1923 if (!strcmp(filename + strlen(filename) - 4, ".pat"))
1925 x = binbuf_convert(x, 0);
1926 deleteit = 1;
1929 if (!(f = binbuf_dofopen(fbuf, "w")))
1931 fprintf(stderr, "open: ");
1932 sys_unixerror(fbuf);
1933 goto fail;
1935 for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
1937 int length;
1938 /* estimate how many characters will be needed. Printing out
1939 symbols may need extra characters for inserting backslashes. */
1940 if (ap->a_type == A_SYMBOL || ap->a_type == A_DOLLSYM)
1941 length = 80 + strlen(ap->a_w.w_symbol->s_name);
1942 else length = 40;
1943 if (ep - bp < length)
1945 if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
1947 sys_unixerror(fbuf);
1948 goto fail;
1950 bp = sbuf;
1952 if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
1953 bp > sbuf && bp[-1] == ' ') bp--;
1954 if (!crflag || ap->a_type != A_SEMI)
1956 atom_string(ap, bp, (ep-bp)-2);
1957 length = strlen(bp);
1958 bp += length;
1959 ncolumn += length;
1961 if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65))
1963 *bp++ = '\n';
1964 ncolumn = 0;
1966 else
1968 *bp++ = ' ';
1969 ncolumn++;
1972 if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
1974 sys_unixerror(fbuf);
1975 goto fail;
1977 if (deleteit)
1978 binbuf_free(x);
1979 fclose(f);
1980 return (0);
1981 fail:
1982 if (deleteit)
1983 binbuf_free(x);
1984 if (f)
1985 fclose(f);
1986 return (1);
1989 /* The following routine attempts to convert from max to pd or back. The
1990 max to pd direction is working OK but you will need to make lots of
1991 abstractions for objects like "gate" which don't exist in Pd. conversion
1992 from Pd to Max hasn't been tested for patches with subpatches yet! */
1994 #define MAXSTACK 1000
1996 #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \
1997 !strcmp((a)->a_w.w_symbol->s_name, (b)))
1999 static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
2001 t_binbuf *newb = binbuf_new();
2002 t_atom *vec = oldb->b_vec;
2003 t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK],
2004 nobj = 0, i;
2005 t_atom outmess[MAXSTACK], *nextmess;
2006 if (!maxtopd)
2007 binbuf_addv(newb, "ss;", gensym("max"), gensym("v2"));
2008 for (nextindex = 0; nextindex < n; )
2010 int endmess, natom;
2011 char *first, *second;
2012 for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI;
2013 endmess++)
2015 if (endmess == n) break;
2016 if (endmess == nextindex || endmess == nextindex + 1
2017 || vec[nextindex].a_type != A_SYMBOL ||
2018 vec[nextindex+1].a_type != A_SYMBOL)
2020 nextindex = endmess + 1;
2021 continue;
2023 natom = endmess - nextindex;
2024 if (natom > MAXSTACK-10) natom = MAXSTACK-10;
2025 nextmess = vec + nextindex;
2026 first = nextmess->a_w.w_symbol->s_name;
2027 second = (nextmess+1)->a_w.w_symbol->s_name;
2028 if (maxtopd)
2030 /* case 1: importing a ".pat" file into Pd. */
2032 /* dollar signs in file translate to symbols */
2033 for (i = 0; i < natom; i++)
2035 if (nextmess[i].a_type == A_DOLLAR)
2037 char buf[100];
2038 sprintf(buf, "$%d", nextmess[i].a_w.w_index);
2039 SETSYMBOL(nextmess+i, gensym(buf));
2041 else if (nextmess[i].a_type == A_DOLLSYM)
2043 char buf[100];
2044 sprintf(buf, "$%s", nextmess[i].a_w.w_symbol->s_name);
2045 SETSYMBOL(nextmess+i, gensym(buf));
2048 if (!strcmp(first, "#N"))
2050 if (!strcmp(second, "vpatcher"))
2052 if (stackdepth >= MAXSTACK)
2054 post("too many embedded patches");
2055 return (newb);
2057 stack[stackdepth] = nobj;
2058 stackdepth++;
2059 nobj = 0;
2060 binbuf_addv(newb, "ssfffff;",
2061 gensym("#N"), gensym("canvas"),
2062 atom_getfloatarg(2, natom, nextmess),
2063 atom_getfloatarg(3, natom, nextmess),
2064 atom_getfloatarg(4, natom, nextmess) -
2065 atom_getfloatarg(2, natom, nextmess),
2066 atom_getfloatarg(5, natom, nextmess) -
2067 atom_getfloatarg(3, natom, nextmess),
2068 (float)sys_defaultfont);
2071 if (!strcmp(first, "#P"))
2073 /* drop initial "hidden" flag */
2074 if (!strcmp(second, "hidden"))
2076 nextmess++;
2077 natom--;
2078 second = (nextmess+1)->a_w.w_symbol->s_name;
2080 if (natom >= 7 && !strcmp(second, "newobj")
2081 && (ISSYMBOL(&nextmess[6], "patcher") ||
2082 ISSYMBOL(&nextmess[6], "p")))
2084 binbuf_addv(newb, "ssffss;",
2085 gensym("#X"), gensym("restore"),
2086 atom_getfloatarg(2, natom, nextmess),
2087 atom_getfloatarg(3, natom, nextmess),
2088 gensym("pd"), atom_getsymbolarg(7, natom, nextmess));
2089 if (stackdepth) stackdepth--;
2090 nobj = stack[stackdepth];
2091 nobj++;
2093 else if (!strcmp(second, "newex") || !strcmp(second, "newobj"))
2095 t_symbol *classname =
2096 atom_getsymbolarg(6, natom, nextmess);
2097 if (classname == gensym("trigger") ||
2098 classname == gensym("t"))
2100 for (i = 7; i < natom; i++)
2101 if (nextmess[i].a_type == A_SYMBOL &&
2102 nextmess[i].a_w.w_symbol == gensym("i"))
2103 nextmess[i].a_w.w_symbol = gensym("f");
2105 if (classname == gensym("table"))
2106 classname = gensym("TABLE");
2107 SETSYMBOL(outmess, gensym("#X"));
2108 SETSYMBOL(outmess + 1, gensym("obj"));
2109 outmess[2] = nextmess[2];
2110 outmess[3] = nextmess[3];
2111 SETSYMBOL(outmess+4, classname);
2112 for (i = 7; i < natom; i++)
2113 outmess[i-2] = nextmess[i];
2114 SETSEMI(outmess + natom - 2);
2115 binbuf_add(newb, natom - 1, outmess);
2116 nobj++;
2118 else if (!strcmp(second, "message") ||
2119 !strcmp(second, "comment"))
2121 SETSYMBOL(outmess, gensym("#X"));
2122 SETSYMBOL(outmess + 1, gensym(
2123 (strcmp(second, "message") ? "text" : "msg")));
2124 outmess[2] = nextmess[2];
2125 outmess[3] = nextmess[3];
2126 for (i = 6; i < natom; i++)
2127 outmess[i-2] = nextmess[i];
2128 SETSEMI(outmess + natom - 2);
2129 binbuf_add(newb, natom - 1, outmess);
2130 nobj++;
2132 else if (!strcmp(second, "button"))
2134 binbuf_addv(newb, "ssffs;",
2135 gensym("#X"), gensym("obj"),
2136 atom_getfloatarg(2, natom, nextmess),
2137 atom_getfloatarg(3, natom, nextmess),
2138 gensym("bng"));
2139 nobj++;
2141 else if (!strcmp(second, "number") || !strcmp(second, "flonum"))
2143 binbuf_addv(newb, "ssff;",
2144 gensym("#X"), gensym("floatatom"),
2145 atom_getfloatarg(2, natom, nextmess),
2146 atom_getfloatarg(3, natom, nextmess));
2147 nobj++;
2149 else if (!strcmp(second, "slider"))
2151 float inc = atom_getfloatarg(7, natom, nextmess);
2152 if (inc <= 0)
2153 inc = 1;
2154 binbuf_addv(newb, "ssffsffffffsssfffffffff;",
2155 gensym("#X"), gensym("obj"),
2156 atom_getfloatarg(2, natom, nextmess),
2157 atom_getfloatarg(3, natom, nextmess),
2158 gensym("vsl"),
2159 atom_getfloatarg(4, natom, nextmess),
2160 atom_getfloatarg(5, natom, nextmess),
2161 atom_getfloatarg(6, natom, nextmess),
2162 atom_getfloatarg(6, natom, nextmess)
2163 + (atom_getfloatarg(5, natom, nextmess) - 1) * inc,
2164 0., 0.,
2165 gensym("empty"), gensym("empty"), gensym("empty"),
2166 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
2167 nobj++;
2169 else if (!strcmp(second, "toggle"))
2171 binbuf_addv(newb, "ssffs;",
2172 gensym("#X"), gensym("obj"),
2173 atom_getfloatarg(2, natom, nextmess),
2174 atom_getfloatarg(3, natom, nextmess),
2175 gensym("tgl"));
2176 nobj++;
2178 else if (!strcmp(second, "inlet"))
2180 binbuf_addv(newb, "ssffs;",
2181 gensym("#X"), gensym("obj"),
2182 atom_getfloatarg(2, natom, nextmess),
2183 atom_getfloatarg(3, natom, nextmess),
2184 gensym((natom > 5 ? "inlet~" : "inlet")));
2185 nobj++;
2187 else if (!strcmp(second, "outlet"))
2189 binbuf_addv(newb, "ssffs;",
2190 gensym("#X"), gensym("obj"),
2191 atom_getfloatarg(2, natom, nextmess),
2192 atom_getfloatarg(3, natom, nextmess),
2193 gensym((natom > 5 ? "outlet~" : "outlet")));
2194 nobj++;
2196 else if (!strcmp(second, "user"))
2198 binbuf_addv(newb, "ssffs;",
2199 gensym("#X"), gensym("obj"),
2200 atom_getfloatarg(3, natom, nextmess),
2201 atom_getfloatarg(4, natom, nextmess),
2202 atom_getsymbolarg(2, natom, nextmess));
2203 nobj++;
2205 else if (!strcmp(second, "connect")||
2206 !strcmp(second, "fasten"))
2208 binbuf_addv(newb, "ssffff;",
2209 gensym("#X"), gensym("connect"),
2210 nobj - atom_getfloatarg(2, natom, nextmess) - 1,
2211 atom_getfloatarg(3, natom, nextmess),
2212 nobj - atom_getfloatarg(4, natom, nextmess) - 1,
2213 atom_getfloatarg(5, natom, nextmess));
2217 else /* Pd to Max */
2219 if (!strcmp(first, "#N"))
2221 if (!strcmp(second, "canvas"))
2223 if (stackdepth >= MAXSTACK)
2225 post("too many embedded patches");
2226 return (newb);
2228 stack[stackdepth] = nobj;
2229 stackdepth++;
2230 nobj = 0;
2231 binbuf_addv(newb, "ssffff;",
2232 gensym("#N"), gensym("vpatcher"),
2233 atom_getfloatarg(2, natom, nextmess),
2234 atom_getfloatarg(3, natom, nextmess),
2235 atom_getfloatarg(4, natom, nextmess),
2236 atom_getfloatarg(5, natom, nextmess));
2239 if (!strcmp(first, "#X"))
2241 if (natom >= 5 && !strcmp(second, "restore")
2242 && (ISSYMBOL (&nextmess[4], "pd")))
2244 binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
2245 binbuf_addv(newb, "ssffffss;",
2246 gensym("#P"), gensym("newobj"),
2247 atom_getfloatarg(2, natom, nextmess),
2248 atom_getfloatarg(3, natom, nextmess), 50., 1.,
2249 gensym("patcher"),
2250 atom_getsymbolarg(5, natom, nextmess));
2251 if (stackdepth) stackdepth--;
2252 nobj = stack[stackdepth];
2253 nobj++;
2255 else if (!strcmp(second, "obj"))
2257 t_symbol *classname =
2258 atom_getsymbolarg(4, natom, nextmess);
2259 if (classname == gensym("inlet"))
2260 binbuf_addv(newb, "ssfff;", gensym("#P"),
2261 gensym("inlet"),
2262 atom_getfloatarg(2, natom, nextmess),
2263 atom_getfloatarg(3, natom, nextmess),
2264 15.);
2265 else if (classname == gensym("inlet~"))
2266 binbuf_addv(newb, "ssffff;", gensym("#P"),
2267 gensym("inlet"),
2268 atom_getfloatarg(2, natom, nextmess),
2269 atom_getfloatarg(3, natom, nextmess),
2270 15., 1.);
2271 else if (classname == gensym("outlet"))
2272 binbuf_addv(newb, "ssfff;", gensym("#P"),
2273 gensym("outlet"),
2274 atom_getfloatarg(2, natom, nextmess),
2275 atom_getfloatarg(3, natom, nextmess),
2276 15.);
2277 else if (classname == gensym("outlet~"))
2278 binbuf_addv(newb, "ssffff;", gensym("#P"),
2279 gensym("outlet"),
2280 atom_getfloatarg(2, natom, nextmess),
2281 atom_getfloatarg(3, natom, nextmess),
2282 15., 1.);
2283 else if (classname == gensym("bng"))
2284 binbuf_addv(newb, "ssffff;", gensym("#P"),
2285 gensym("button"),
2286 atom_getfloatarg(2, natom, nextmess),
2287 atom_getfloatarg(3, natom, nextmess),
2288 atom_getfloatarg(5, natom, nextmess), 0.);
2289 else if (classname == gensym("tgl"))
2290 binbuf_addv(newb, "ssffff;", gensym("#P"),
2291 gensym("toggle"),
2292 atom_getfloatarg(2, natom, nextmess),
2293 atom_getfloatarg(3, natom, nextmess),
2294 atom_getfloatarg(5, natom, nextmess), 0.);
2295 else if (classname == gensym("vsl"))
2296 binbuf_addv(newb, "ssffffff;", gensym("#P"),
2297 gensym("slider"),
2298 atom_getfloatarg(2, natom, nextmess),
2299 atom_getfloatarg(3, natom, nextmess),
2300 atom_getfloatarg(5, natom, nextmess),
2301 atom_getfloatarg(6, natom, nextmess),
2302 (atom_getfloatarg(8, natom, nextmess) -
2303 atom_getfloatarg(7, natom, nextmess)) /
2304 (atom_getfloatarg(6, natom, nextmess) == 1? 1 :
2305 atom_getfloatarg(6, natom, nextmess) - 1),
2306 atom_getfloatarg(7, natom, nextmess));
2307 else
2309 SETSYMBOL(outmess, gensym("#P"));
2310 SETSYMBOL(outmess + 1, gensym("newex"));
2311 outmess[2] = nextmess[2];
2312 outmess[3] = nextmess[3];
2313 SETFLOAT(outmess + 4, 50);
2314 SETFLOAT(outmess + 5, 1);
2315 for (i = 4; i < natom; i++)
2316 outmess[i+2] = nextmess[i];
2317 SETSEMI(outmess + natom + 2);
2318 binbuf_add(newb, natom + 3, outmess);
2320 nobj++;
2323 else if (!strcmp(second, "msg") ||
2324 !strcmp(second, "text"))
2326 SETSYMBOL(outmess, gensym("#P"));
2327 SETSYMBOL(outmess + 1, gensym(
2328 (strcmp(second, "msg") ? "comment" : "message")));
2329 outmess[2] = nextmess[2];
2330 outmess[3] = nextmess[3];
2331 SETFLOAT(outmess + 4, 50);
2332 SETFLOAT(outmess + 5, 1);
2333 for (i = 4; i < natom; i++)
2334 outmess[i+2] = nextmess[i];
2335 SETSEMI(outmess + natom + 2);
2336 binbuf_add(newb, natom + 3, outmess);
2337 nobj++;
2339 else if (!strcmp(second, "floatatom"))
2341 binbuf_addv(newb, "ssfff;",
2342 gensym("#P"), gensym("flonum"),
2343 atom_getfloatarg(2, natom, nextmess),
2344 atom_getfloatarg(3, natom, nextmess), 35);
2345 nobj++;
2347 else if (!strcmp(second, "connect"))
2349 binbuf_addv(newb, "ssffff;",
2350 gensym("#P"), gensym("connect"),
2351 nobj - atom_getfloatarg(2, natom, nextmess) - 1,
2352 atom_getfloatarg(3, natom, nextmess),
2353 nobj - atom_getfloatarg(4, natom, nextmess) - 1,
2354 atom_getfloatarg(5, natom, nextmess));
2358 nextindex = endmess + 1;
2360 if (!maxtopd)
2361 binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
2362 #if 0
2363 binbuf_write(newb, "import-result.pd", "/tmp", 0);
2364 #endif
2365 return (newb);
2368 /* function to support searching */
2369 int binbuf_match(t_binbuf *inbuf, t_binbuf *searchbuf)
2371 int indexin, nmatched;
2372 for (indexin = 0; indexin <= inbuf->b_n - searchbuf->b_n; indexin++)
2374 for (nmatched = 0; nmatched < searchbuf->b_n; nmatched++)
2376 t_atom *a1 = &inbuf->b_vec[indexin + nmatched],
2377 *a2 = &searchbuf->b_vec[nmatched];
2378 if (a1->a_type != a2->a_type ||
2379 a1->a_type == A_SYMBOL && a1->a_w.w_symbol != a2->a_w.w_symbol
2381 a1->a_type == A_FLOAT && a1->a_w.w_float != a2->a_w.w_float
2383 a1->a_type == A_DOLLAR && a1->a_w.w_index != a2->a_w.w_index
2385 a1->a_type == A_DOLLSYM && a1->a_w.w_symbol != a2->a_w.w_symbol)
2386 goto nomatch;
2388 return (1);
2389 nomatch: ;
2391 return (0);
2394 void pd_doloadbang(void);
2396 /* LATER make this evaluate the file on-the-fly. */
2397 /* LATER figure out how to log errors */
2398 void binbuf_evalfile(t_symbol *name, t_symbol *dir)
2400 t_binbuf *b = binbuf_new();
2401 int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat");
2402 /* set filename so that new canvases can pick them up */
2403 int dspstate = canvas_suspend_dsp();
2404 glob_setfilename(0, name, dir);
2405 if (binbuf_read(b, name->s_name, dir->s_name, 0))
2407 perror(name->s_name);
2409 else
2411 if (import)
2413 t_binbuf *newb = binbuf_convert(b, 1);
2414 binbuf_free(b);
2415 b = newb;
2417 binbuf_eval(b, 0, 0, 0);
2419 glob_setfilename(0, &s_, &s_); /* bug fix by Krzysztof Czaja */
2420 binbuf_free(b);
2421 canvas_resume_dsp(dspstate);
2424 void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
2426 t_pd *x = 0;
2427 /* even though binbuf_evalfile appears to take care of dspstate,
2428 we have to do it again here, because canvas_startdsp() assumes
2429 that all toplevel canvases are visible. LATER check if this
2430 is still necessary -- probably not. */
2432 int dspstate = canvas_suspend_dsp();
2433 binbuf_evalfile(name, dir);
2434 while ((x != s__X.s_thing) && (x = s__X.s_thing))
2435 vmess(x, gensym("pop"), "i", 1);
2436 pd_doloadbang();
2437 canvas_resume_dsp(dspstate);