Fix pdbox makefile to actually take part in dependency generation
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / m_binbuf.c
blob50ed03cd85bafbfeca5904efa1a8426b778cb810
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 #ifdef ROCKBOX
14 #include "plugin.h"
15 #include "../../pdbox.h"
16 #ifdef SIMULATOR
17 int printf(const char *fmt, ...);
18 void perror(const char*);
19 #endif
20 #else /* ROCKBOX */
21 #include <stdlib.h>
22 #include <stdio.h>
23 #ifdef UNIX
24 #include <unistd.h>
25 #endif
26 #ifdef MSW
27 #include <io.h>
28 #endif
29 #include <fcntl.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #endif /* ROCKBOX */
35 #include "m_pd.h"
36 #include "s_stuff.h"
38 struct _binbuf
40 int b_n;
41 t_atom *b_vec;
44 t_binbuf *binbuf_new(void)
46 t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
47 x->b_n = 0;
48 x->b_vec = t_getbytes(0);
49 return (x);
52 void binbuf_free(t_binbuf *x)
54 t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
55 t_freebytes(x, sizeof(*x));
58 t_binbuf *binbuf_duplicate(t_binbuf *y)
60 t_binbuf *x = (t_binbuf *)t_getbytes(sizeof(*x));
61 x->b_n = y->b_n;
62 x->b_vec = t_getbytes(x->b_n * sizeof(*x->b_vec));
63 memcpy(x->b_vec, y->b_vec, x->b_n * sizeof(*x->b_vec));
64 return (x);
67 void binbuf_clear(t_binbuf *x)
69 x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0);
70 x->b_n = 0;
73 /* convert text to a binbuf */
74 void binbuf_text(t_binbuf *x, char *text, size_t size)
76 char buf[MAXPDSTRING+1], *bufp, *ebuf = buf+MAXPDSTRING;
77 const char *textp = text, *etext = text+size;
78 t_atom *ap;
79 int nalloc = 16, natom = 0;
80 t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec));
81 x->b_vec = t_getbytes(nalloc * sizeof(*x->b_vec));
82 ap = x->b_vec;
83 x->b_n = 0;
84 while (1)
86 #ifndef ROCKBOX
87 int type;
88 #endif
89 /* skip leading space */
90 while ((textp != etext) && (*textp == ' ' || *textp == '\n'
91 || *textp == '\r' || *textp == '\t')) textp++;
92 if (textp == etext) break;
93 if (*textp == ';') SETSEMI(ap), textp++;
94 else if (*textp == ',') SETCOMMA(ap), textp++;
95 else
97 /* it's an atom other than a comma or semi */
98 char c;
99 int floatstate = 0, slash = 0, lastslash = 0,
100 firstslash = (*textp == '\\');
101 bufp = buf;
104 c = *bufp = *textp++;
105 lastslash = slash;
106 slash = (c == '\\');
108 if (floatstate >= 0)
110 int digit = (c >= '0' && c <= '9'),
111 dot = (c == '.'), minus = (c == '-'),
112 plusminus = (minus || (c == '+')),
113 expon = (c == 'e' || c == 'E');
114 if (floatstate == 0) /* beginning */
116 if (minus) floatstate = 1;
117 else if (digit) floatstate = 2;
118 else if (dot) floatstate = 3;
119 else floatstate = -1;
121 else if (floatstate == 1) /* got minus */
123 if (digit) floatstate = 2;
124 else if (dot) floatstate = 3;
125 else floatstate = -1;
127 else if (floatstate == 2) /* got digits */
129 if (dot) floatstate = 4;
130 else if (expon) floatstate = 6;
131 else if (!digit) floatstate = -1;
133 else if (floatstate == 3) /* got '.' without digits */
135 if (digit) floatstate = 5;
136 else floatstate = -1;
138 else if (floatstate == 4) /* got '.' after digits */
140 if (digit) floatstate = 5;
141 else if (expon) floatstate = 6;
142 else floatstate = -1;
144 else if (floatstate == 5) /* got digits after . */
146 if (expon) floatstate = 6;
147 else if (!digit) floatstate = -1;
149 else if (floatstate == 6) /* got 'e' */
151 if (plusminus) floatstate = 7;
152 else if (digit) floatstate = 8;
153 else floatstate = -1;
155 else if (floatstate == 7) /* got plus or minus */
157 if (digit) floatstate = 8;
158 else floatstate = -1;
160 else if (floatstate == 8) /* got digits */
162 if (!digit) floatstate = -1;
165 if (!slash) bufp++;
167 while (textp != etext && bufp != ebuf &&
168 (slash || (*textp != ' ' && *textp != '\n' && *textp != '\r'
169 && *textp != '\t' &&*textp != ',' && *textp != ';')));
170 *bufp = 0;
171 #if 0
172 post("buf %s", buf);
173 #endif
175 if (*buf == '$' && buf[1] >= '0' && buf[1] <= '9' && !firstslash)
177 for (bufp = buf+2; *bufp; bufp++)
178 if (*bufp < '0' || *bufp > '9')
180 SETDOLLSYM(ap, gensym(buf+1));
181 goto didit;
183 SETDOLLAR(ap, atoi(buf+1));
184 didit: ;
186 else
188 if (floatstate == 2 || floatstate == 4 || floatstate == 5 ||
189 floatstate == 8)
190 SETFLOAT(ap, atof(buf));
191 else SETSYMBOL(ap, gensym(buf));
194 ap++;
195 natom++;
196 if (natom == nalloc)
198 x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
199 nalloc * (2*sizeof(*x->b_vec)));
200 nalloc = nalloc * 2;
201 ap = x->b_vec + natom;
203 if (textp == etext) break;
205 /* reallocate the vector to exactly the right size */
206 x->b_vec = t_resizebytes(x->b_vec, nalloc * sizeof(*x->b_vec),
207 natom * sizeof(*x->b_vec));
208 x->b_n = natom;
211 /* convert a binbuf to text; no null termination. */
212 void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp)
214 char *buf = getbytes(0), *newbuf;
215 int length = 0;
216 char string[MAXPDSTRING];
217 t_atom *ap;
218 int indx;
220 for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
222 int newlength;
223 if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
224 length && buf[length-1] == ' ') length--;
225 atom_string(ap, string, MAXPDSTRING);
226 newlength = length + strlen(string) + 1;
227 if (!(newbuf = resizebytes(buf, length, newlength))) break;
228 buf = newbuf;
229 strcpy(buf + length, string);
230 length = newlength;
231 if (ap->a_type == A_SEMI) buf[length-1] = '\n';
232 else buf[length-1] = ' ';
234 if (length && buf[length-1] == ' ')
236 if((newbuf = t_resizebytes(buf, length, length-1)))
238 buf = newbuf;
239 length--;
242 *bufp = buf;
243 *lengthp = length;
246 /* LATER improve the out-of-space behavior below. Also fix this so that
247 writing to file doesn't buffer everything together. */
249 void binbuf_add(t_binbuf *x, int argc, t_atom *argv)
251 int newsize = x->b_n + argc, i;
252 t_atom *ap;
253 if((ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
254 newsize * sizeof(*x->b_vec))))
255 x->b_vec = ap;
256 else
258 error("binbuf_addmessage: out of space");
259 return;
261 #if 0
262 startpost("binbuf_add: ");
263 postatom(argc, argv);
264 endpost();
265 #endif
266 for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
267 *ap = *(argv++);
268 x->b_n = newsize;
271 #define MAXADDMESSV 100
272 void binbuf_addv(t_binbuf *x, char *fmt, ...)
274 va_list ap;
275 t_atom arg[MAXADDMESSV], *at =arg;
276 int nargs = 0;
277 char *fp = fmt;
279 va_start(ap, fmt);
280 while (1)
282 if (nargs >= MAXADDMESSV)
284 error("binbuf_addmessv: only %d allowed", MAXADDMESSV);
285 break;
287 switch(*fp++)
289 case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
290 case 'f': SETFLOAT(at, va_arg(ap, double)); break;
291 case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
292 case ';': SETSEMI(at); break;
293 case ',': SETCOMMA(at); break;
294 default: goto done;
296 at++;
297 nargs++;
299 done:
300 va_end(ap);
301 binbuf_add(x, nargs, arg);
304 /* add a binbuf to another one for saving. Semicolons and commas go to
305 symbols ";", "'",; the symbol ";" goes to "\;", etc. */
307 void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y)
309 t_binbuf *z = binbuf_new();
310 int i;
311 t_atom *ap;
312 binbuf_add(z, y->b_n, y->b_vec);
313 for (i = 0, ap = z->b_vec; i < z->b_n; i++, ap++)
315 char tbuf[MAXPDSTRING];
316 switch (ap->a_type)
318 case A_FLOAT:
319 break;
320 case A_SEMI:
321 SETSYMBOL(ap, gensym(";"));
322 break;
323 case A_COMMA:
324 SETSYMBOL(ap, gensym(","));
325 break;
326 case A_DOLLAR:
327 #ifdef ROCKBOX
328 snprintf(tbuf, sizeof(tbuf), "$%d", ap->a_w.w_index);
329 #else /* ROCKBOX */
330 sprintf(tbuf, "$%d", ap->a_w.w_index);
331 #endif /* ROCKBOX */
332 SETSYMBOL(ap, gensym(tbuf));
333 break;
334 case A_DOLLSYM:
335 #ifdef ROCKBOX
336 snprintf(tbuf, sizeof(tbuf), "$%s", ap->a_w.w_symbol->s_name);
337 #else /* ROCKBOX */
338 sprintf(tbuf, "$%s", ap->a_w.w_symbol->s_name);
339 #endif /* ROCKBOX */
340 SETSYMBOL(ap, gensym(tbuf));
341 break;
342 case A_SYMBOL:
343 /* FIXME make this general */
344 if (!strcmp(ap->a_w.w_symbol->s_name, ";"))
345 SETSYMBOL(ap, gensym(";"));
346 else if (!strcmp(ap->a_w.w_symbol->s_name, ","))
347 SETSYMBOL(ap, gensym(","));
348 break;
349 default:
350 bug("binbuf_addbinbuf");
354 binbuf_add(x, z->b_n, z->b_vec);
357 void binbuf_addsemi(t_binbuf *x)
359 t_atom a;
360 SETSEMI(&a);
361 binbuf_add(x, 1, &a);
364 /* Supply atoms to a binbuf from a message, making the opposite changes
365 from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
367 void binbuf_restore(t_binbuf *x, int argc, t_atom *argv)
369 int newsize = x->b_n + argc, i;
370 t_atom *ap;
371 if((ap = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec),
372 newsize * sizeof(*x->b_vec))))
373 x->b_vec = ap;
374 else
376 error("binbuf_addmessage: out of space");
377 return;
380 for (ap = x->b_vec + x->b_n, i = argc; i--; ap++)
382 if (argv->a_type == A_SYMBOL)
384 char *str = argv->a_w.w_symbol->s_name;
385 if (!strcmp(str, ";")) SETSEMI(ap);
386 else if (!strcmp(str, ",")) SETCOMMA(ap);
387 else if (str[0] == '$' && str[1] >= '0' && str[1] <= '9')
389 int dollsym = 0;
390 char *str2;
391 for (str2 = str + 2; *str2; str2++)
392 if (*str2 < '0' || *str2 > '9')
393 dollsym = 1;
394 if (dollsym)
395 SETDOLLSYM(ap, gensym(str + 1));
396 else
398 int dollar = 0;
399 #ifdef ROCKBOX
400 dollar = atoi(argv->a_w.w_symbol->s_name + 1);
401 #else
402 sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar);
403 #endif
404 SETDOLLAR(ap, dollar);
407 else *ap = *argv;
408 argv++;
410 else *ap = *(argv++);
412 x->b_n = newsize;
416 #define MSTACKSIZE 2048
418 void binbuf_print(t_binbuf *x)
420 int i, startedpost = 0, newline = 1;
421 for (i = 0; i < x->b_n; i++)
423 if (newline)
425 if (startedpost) endpost();
426 startpost("");
427 startedpost = 1;
429 postatom(1, x->b_vec + i);
430 if (x->b_vec[i].a_type == A_SEMI)
431 newline = 1;
432 else newline = 0;
434 if (startedpost) endpost();
437 int binbuf_getnatom(t_binbuf *x)
439 return (x->b_n);
442 t_atom *binbuf_getvec(t_binbuf *x)
444 return (x->b_vec);
447 int canvas_getdollarzero( void);
449 t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
451 int argno = atol(s->s_name), lastnum;
452 char buf[MAXPDSTRING], c, *sp;
453 for (lastnum = 0, sp = s->s_name; ((c = *sp) && c >= '0' && c <= '9');
454 sp++, lastnum++)
455 if (!c || argno < 0 || argno > ac)
457 if (!tonew)
458 return (0);
459 #ifdef ROCKBOX
460 else snprintf(buf, sizeof(buf), "$%d", argno);
461 #else /* ROCKBOX */
462 else sprintf(buf, "$%d", argno);
463 #endif /* ROCKBOX */
465 else if (argno == 0)
466 #ifdef ROCKBOX
467 snprintf(buf, sizeof(buf), "%d", canvas_getdollarzero());
468 #else /* ROCKBOX */
469 sprintf(buf, "%d", canvas_getdollarzero());
470 #endif /* ROCKBOX */
471 else
472 atom_string(av+(argno-1), buf, MAXPDSTRING/2-1);
473 strncat(buf, sp, MAXPDSTRING/2-1);
474 return (gensym(buf));
477 void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
479 static t_atom mstack[MSTACKSIZE], *msp = mstack, *ems = mstack+MSTACKSIZE;
480 t_atom *stackwas = msp;
481 t_atom *at = x->b_vec;
482 int ac = x->b_n;
483 int nargs;
484 while (1)
486 t_pd *nexttarget;
487 /* get a target. */
488 while (!target)
490 t_symbol *s;
491 while (ac && (at->a_type == A_SEMI || at->a_type == A_COMMA))
492 ac--, at++;
493 if (!ac) break;
494 if (at->a_type == A_DOLLAR)
496 if (at->a_w.w_index <= 0 || at->a_w.w_index > argc)
498 error("$%d: not enough arguments supplied",
499 at->a_w.w_index);
500 goto cleanup;
502 else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL)
504 error("$%d: symbol needed as message destination",
505 at->a_w.w_index);
506 goto cleanup;
508 else s = argv[at->a_w.w_index-1].a_w.w_symbol;
510 else if (at->a_type == A_DOLLSYM)
512 if (!(s = binbuf_realizedollsym(at->a_w.w_symbol,
513 argc, argv, 0)))
515 error("$%s: not enough arguments supplied",
516 at->a_w.w_symbol->s_name);
517 goto cleanup;
520 else s = atom_getsymbol(at);
521 if (!(target = s->s_thing))
523 error("%s: no such object", s->s_name);
524 cleanup:
525 do at++, ac--;
526 while (ac && at->a_type != A_SEMI);
527 /* LATER eat args until semicolon and continue */
528 continue;
530 else
532 at++, ac--;
533 break;
536 if (!ac) break;
537 nargs = 0;
538 nexttarget = target;
539 while (1)
541 t_symbol *s9;
542 if (!ac) goto gotmess;
543 if (msp >= ems)
545 error("message stack overflow");
546 goto broken;
548 switch (at->a_type)
550 case A_SEMI:
551 /* semis and commas in new message just get bashed to
552 a symbol. This is needed so you can pass them to "expr." */
553 if (target == &pd_objectmaker)
555 SETSYMBOL(msp, gensym(";"));
556 break;
558 else
560 nexttarget = 0;
561 goto gotmess;
563 case A_COMMA:
564 if (target == &pd_objectmaker)
566 SETSYMBOL(msp, gensym(","));
567 break;
569 else goto gotmess;
570 case A_FLOAT:
571 case A_SYMBOL:
572 *msp = *at;
573 break;
574 case A_DOLLAR:
575 if (at->a_w.w_index > 0 && at->a_w.w_index <= argc)
576 *msp = argv[at->a_w.w_index-1];
577 else if (at->a_w.w_index == 0)
578 SETFLOAT(msp, canvas_getdollarzero());
579 else
581 if (target == &pd_objectmaker)
582 SETFLOAT(msp, 0);
583 else
585 error("$%d: argument number out of range",
586 at->a_w.w_index);
587 SETFLOAT(msp, 0);
590 break;
591 case A_DOLLSYM:
592 s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv,
593 target == &pd_objectmaker);
594 if (!s9)
595 goto broken;
596 SETSYMBOL(msp, s9);
597 break;
598 default:
599 bug("bad item in binbuf");
600 goto broken;
602 msp++;
603 ac--;
604 at++;
605 nargs++;
607 gotmess:
608 if (nargs)
610 switch (stackwas->a_type)
612 case A_SYMBOL:
613 typedmess(target, stackwas->a_w.w_symbol, nargs-1, stackwas+1);
614 break;
615 case A_FLOAT:
616 if (nargs == 1) pd_float(target, stackwas->a_w.w_float);
617 else pd_list(target, 0, nargs, stackwas);
618 break;
619 #ifdef ROCKBOX
620 default:
621 break;
622 #endif
625 msp = stackwas;
626 if (!ac) break;
627 target = nexttarget;
628 at++;
629 ac--;
632 return;
633 broken:
634 msp = stackwas;
637 static int binbuf_doopen(char *s, int mode)
639 char namebuf[MAXPDSTRING];
640 #ifdef MSW
641 mode |= O_BINARY;
642 #endif
643 sys_bashfilename(s, namebuf);
644 return (open(namebuf, mode));
647 #ifndef ROCKBOX
648 static FILE *binbuf_dofopen(char *s, char *mode)
650 char namebuf[MAXPDSTRING];
651 sys_bashfilename(s, namebuf);
652 return (fopen(namebuf, mode));
654 #endif
656 int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag)
658 long length;
659 int fd;
660 int readret;
661 char *buf;
662 char namebuf[MAXPDSTRING];
664 namebuf[0] = 0;
665 if (*dirname)
666 strcat(namebuf, dirname), strcat(namebuf, "/");
667 strcat(namebuf, filename);
669 if ((fd = binbuf_doopen(namebuf, 0)) < 0)
671 #ifdef ROCKBOX
672 #ifdef SIMULATOR
673 printf("open: ");
674 perror(namebuf);
675 #endif /* SIMULATOR */
676 #else /* ROCKBOX */
677 fprintf(stderr, "open: ");
678 perror(namebuf);
679 #endif /* ROCKBOX */
680 return (1);
682 if ((length = lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0
683 || !(buf = t_getbytes(length)))
685 #ifdef ROCKBOX
686 #ifdef SIMULATOR
687 printf("lseek: ");
688 perror(namebuf);
689 #endif /* SIMULATOR */
690 #else /* ROCKBOX */
691 fprintf(stderr, "lseek: ");
692 perror(namebuf);
693 #endif /* ROCKBOX */
694 close(fd);
695 return(1);
697 if ((readret = read(fd, buf, length)) < length)
699 #ifdef ROCKBOX
700 #ifdef SIMULATOR
701 printf("read (%d %ld) -> %d\n", fd, length, readret);
702 perror(namebuf);
703 #endif /* SIMULATOR */
704 #else /* ROCKBOX */
705 fprintf(stderr, "read (%d %ld) -> %d\n", fd, length, readret);
706 perror(namebuf);
707 #endif /* ROCKBOX */
708 close(fd);
709 t_freebytes(buf, length);
710 return(1);
712 /* optionally map carriage return to semicolon */
713 if (crflag)
715 int i;
716 for (i = 0; i < length; i++)
717 if (buf[i] == '\n')
718 buf[i] = ';';
720 binbuf_text(b, buf, length);
722 #if 0
723 startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost();
724 #endif
726 t_freebytes(buf, length);
727 close(fd);
728 return (0);
731 int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
732 int crflag)
734 int filedesc;
735 char buf[MAXPDSTRING], *bufptr;
736 if ((filedesc = open_via_path(
737 dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0)
739 error("%s: can't open", filename);
740 return (1);
742 else close (filedesc);
743 if (binbuf_read(b, bufptr, buf, crflag))
744 return (1);
745 else return (0);
748 #define WBUFSIZE 4096
749 static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd);
751 /* write a binbuf to a text file. If "crflag" is set we suppress
752 semicolons. */
753 int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
755 #ifdef ROCKBOX
756 int f = 0;
757 #else /* ROCKBOX */
758 FILE *f = 0;
759 #endif /* ROCKBOX */
760 char sbuf[WBUFSIZE], fbuf[MAXPDSTRING], *bp = sbuf, *ep = sbuf + WBUFSIZE;
761 t_atom *ap;
762 int indx, deleteit = 0;
763 int ncolumn = 0;
765 fbuf[0] = 0;
766 if (*dir)
767 strcat(fbuf, dir), strcat(fbuf, "/");
768 strcat(fbuf, filename);
769 if (!strcmp(filename + strlen(filename) - 4, ".pat"))
771 x = binbuf_convert(x, 0);
772 deleteit = 1;
775 #ifdef ROCKBOX
776 if(!(f = binbuf_doopen(fbuf, O_WRONLY|O_CREAT|O_TRUNC)))
777 #else /* ROCKBOX */
778 if (!(f = binbuf_dofopen(fbuf, "w")))
779 #endif /* ROCKBOX */
781 #ifdef ROCKBOX
782 #ifdef SIMULATOR
783 printf("open: ");
784 #endif /* SIMULATOR */
785 #else /* ROCKBOX */
786 fprintf(stderr, "open: ");
787 #endif /* ROCKBOX */
788 sys_unixerror(fbuf);
789 goto fail;
791 for (ap = x->b_vec, indx = x->b_n; indx--; ap++)
793 int length;
794 /* estimate how many characters will be needed. Printing out
795 symbols may need extra characters for inserting backslashes. */
796 if (ap->a_type == A_SYMBOL || ap->a_type == A_DOLLSYM)
797 length = 80 + strlen(ap->a_w.w_symbol->s_name);
798 else length = 40;
799 if (ep - bp < length)
801 #ifdef ROCKBOX
802 if(write(f, sbuf, bp-sbuf) < 1)
803 #else /* ROCKBOX */
804 if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
805 #endif /* ROCKBOX */
807 sys_unixerror(fbuf);
808 goto fail;
810 bp = sbuf;
812 if ((ap->a_type == A_SEMI || ap->a_type == A_COMMA) &&
813 bp > sbuf && bp[-1] == ' ') bp--;
814 if (!crflag || ap->a_type != A_SEMI)
816 atom_string(ap, bp, (ep-bp)-2);
817 length = strlen(bp);
818 bp += length;
819 ncolumn += length;
821 if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65))
823 *bp++ = '\n';
824 ncolumn = 0;
826 else
828 *bp++ = ' ';
829 ncolumn++;
832 #ifdef ROCKBOX
833 if(write(f, sbuf, bp-sbuf) < 1)
834 #else /* ROCKBOX */
835 if (fwrite(sbuf, bp-sbuf, 1, f) < 1)
836 #endif /* ROCKBOX */
838 sys_unixerror(fbuf);
839 goto fail;
841 if (deleteit)
842 binbuf_free(x);
843 #ifdef ROCKBOX
844 close(f);
845 #else /* ROCKBOX */
846 fclose(f);
847 #endif /* ROCKBOX */
848 return (0);
849 fail:
850 if (deleteit)
851 binbuf_free(x);
852 if (f)
853 #ifdef ROCKBOX
854 close(f);
855 #else /* ROCKBOX */
856 fclose(f);
857 #endif /* ROCKBOX */
858 return (1);
861 /* The following routine attempts to convert from max to pd or back. The
862 max to pd direction is working OK but you will need to make lots of
863 abstractions for objects like "gate" which don't exist in Pd. conversion
864 from Pd to Max hasn't been tested for patches with subpatches yet! */
866 #define MAXSTACK 1000
868 #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \
869 !strcmp((a)->a_w.w_symbol->s_name, (b)))
871 static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
873 t_binbuf *newb = binbuf_new();
874 t_atom *vec = oldb->b_vec;
875 t_int n = oldb->b_n, nextindex, stackdepth = 0, stack[MAXSTACK],
876 nobj = 0, i;
877 t_atom outmess[MAXSTACK], *nextmess;
878 if (!maxtopd)
879 binbuf_addv(newb, "ss;", gensym("max"), gensym("v2"));
880 for (nextindex = 0; nextindex < n; )
882 int endmess, natom;
883 char *first, *second;
884 for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI;
885 endmess++)
887 if (endmess == n) break;
888 if (endmess == nextindex || endmess == nextindex + 1
889 || vec[nextindex].a_type != A_SYMBOL ||
890 vec[nextindex+1].a_type != A_SYMBOL)
892 nextindex = endmess + 1;
893 continue;
895 natom = endmess - nextindex;
896 if (natom > MAXSTACK-10) natom = MAXSTACK-10;
897 nextmess = vec + nextindex;
898 first = nextmess->a_w.w_symbol->s_name;
899 second = (nextmess+1)->a_w.w_symbol->s_name;
900 if (maxtopd)
902 /* case 1: importing a ".pat" file into Pd. */
904 /* dollar signs in file translate to symbols */
905 for (i = 0; i < natom; i++)
907 if (nextmess[i].a_type == A_DOLLAR)
909 char buf[100];
910 #ifdef ROCKBOX
911 snprintf(buf, sizeof(buf), "$%d", nextmess[i].a_w.w_index);
912 #else /* ROCKBOX */
913 sprintf(buf, "$%d", nextmess[i].a_w.w_index);
914 #endif /* ROCKBOX */
915 SETSYMBOL(nextmess+i, gensym(buf));
917 else if (nextmess[i].a_type == A_DOLLSYM)
919 char buf[100];
920 #ifdef ROCKBOX
921 snprintf(buf, sizeof(buf), "$%s", nextmess[i].a_w.w_symbol->s_name);
922 #else /* ROCKBOX */
923 sprintf(buf, "$%s", nextmess[i].a_w.w_symbol->s_name);
924 #endif /* ROCKBOX */
925 SETSYMBOL(nextmess+i, gensym(buf));
928 if (!strcmp(first, "#N"))
930 if (!strcmp(second, "vpatcher"))
932 if (stackdepth >= MAXSTACK)
934 post("too many embedded patches");
935 return (newb);
937 stack[stackdepth] = nobj;
938 stackdepth++;
939 nobj = 0;
940 binbuf_addv(newb, "ssfffff;",
941 gensym("#N"), gensym("canvas"),
942 atom_getfloatarg(2, natom, nextmess),
943 atom_getfloatarg(3, natom, nextmess),
944 atom_getfloatarg(4, natom, nextmess) -
945 atom_getfloatarg(2, natom, nextmess),
946 atom_getfloatarg(5, natom, nextmess) -
947 atom_getfloatarg(3, natom, nextmess),
948 #ifdef ROCKBOX
949 10.0);
950 #else
951 (float)sys_defaultfont);
952 #endif
955 if (!strcmp(first, "#P"))
957 /* drop initial "hidden" flag */
958 if (!strcmp(second, "hidden"))
960 nextmess++;
961 natom--;
962 second = (nextmess+1)->a_w.w_symbol->s_name;
964 if (natom >= 7 && !strcmp(second, "newobj")
965 && (ISSYMBOL(&nextmess[6], "patcher") ||
966 ISSYMBOL(&nextmess[6], "p")))
968 binbuf_addv(newb, "ssffss;",
969 gensym("#X"), gensym("restore"),
970 atom_getfloatarg(2, natom, nextmess),
971 atom_getfloatarg(3, natom, nextmess),
972 gensym("pd"), atom_getsymbolarg(7, natom, nextmess));
973 if (stackdepth) stackdepth--;
974 nobj = stack[stackdepth];
975 nobj++;
977 else if (!strcmp(second, "newex") || !strcmp(second, "newobj"))
979 t_symbol *classname =
980 atom_getsymbolarg(6, natom, nextmess);
981 if (classname == gensym("trigger") ||
982 classname == gensym("t"))
984 for (i = 7; i < natom; i++)
985 if (nextmess[i].a_type == A_SYMBOL &&
986 nextmess[i].a_w.w_symbol == gensym("i"))
987 nextmess[i].a_w.w_symbol = gensym("f");
989 if (classname == gensym("table"))
990 classname = gensym("TABLE");
991 SETSYMBOL(outmess, gensym("#X"));
992 SETSYMBOL(outmess + 1, gensym("obj"));
993 outmess[2] = nextmess[2];
994 outmess[3] = nextmess[3];
995 SETSYMBOL(outmess+4, classname);
996 for (i = 7; i < natom; i++)
997 outmess[i-2] = nextmess[i];
998 SETSEMI(outmess + natom - 2);
999 binbuf_add(newb, natom - 1, outmess);
1000 nobj++;
1002 else if (!strcmp(second, "message") ||
1003 !strcmp(second, "comment"))
1005 SETSYMBOL(outmess, gensym("#X"));
1006 SETSYMBOL(outmess + 1, gensym(
1007 (strcmp(second, "message") ? "text" : "msg")));
1008 outmess[2] = nextmess[2];
1009 outmess[3] = nextmess[3];
1010 for (i = 6; i < natom; i++)
1011 outmess[i-2] = nextmess[i];
1012 SETSEMI(outmess + natom - 2);
1013 binbuf_add(newb, natom - 1, outmess);
1014 nobj++;
1016 else if (!strcmp(second, "button"))
1018 binbuf_addv(newb, "ssffs;",
1019 gensym("#X"), gensym("obj"),
1020 atom_getfloatarg(2, natom, nextmess),
1021 atom_getfloatarg(3, natom, nextmess),
1022 gensym("bng"));
1023 nobj++;
1025 else if (!strcmp(second, "number") || !strcmp(second, "flonum"))
1027 binbuf_addv(newb, "ssff;",
1028 gensym("#X"), gensym("floatatom"),
1029 atom_getfloatarg(2, natom, nextmess),
1030 atom_getfloatarg(3, natom, nextmess));
1031 nobj++;
1033 else if (!strcmp(second, "slider"))
1035 float inc = atom_getfloatarg(7, natom, nextmess);
1036 if (inc <= 0)
1037 inc = 1;
1038 binbuf_addv(newb, "ssffsffffffsssfffffffff;",
1039 gensym("#X"), gensym("obj"),
1040 atom_getfloatarg(2, natom, nextmess),
1041 atom_getfloatarg(3, natom, nextmess),
1042 gensym("vsl"),
1043 atom_getfloatarg(4, natom, nextmess),
1044 atom_getfloatarg(5, natom, nextmess),
1045 atom_getfloatarg(6, natom, nextmess),
1046 atom_getfloatarg(6, natom, nextmess)
1047 + (atom_getfloatarg(5, natom, nextmess) - 1) * inc,
1048 0., 0.,
1049 gensym("empty"), gensym("empty"), gensym("empty"),
1050 0., -8., 0., 8., -262144., -1., -1., 0., 1.);
1051 nobj++;
1053 else if (!strcmp(second, "toggle"))
1055 binbuf_addv(newb, "ssffs;",
1056 gensym("#X"), gensym("obj"),
1057 atom_getfloatarg(2, natom, nextmess),
1058 atom_getfloatarg(3, natom, nextmess),
1059 gensym("tgl"));
1060 nobj++;
1062 else if (!strcmp(second, "inlet"))
1064 binbuf_addv(newb, "ssffs;",
1065 gensym("#X"), gensym("obj"),
1066 atom_getfloatarg(2, natom, nextmess),
1067 atom_getfloatarg(3, natom, nextmess),
1068 gensym((natom > 5 ? "inlet~" : "inlet")));
1069 nobj++;
1071 else if (!strcmp(second, "outlet"))
1073 binbuf_addv(newb, "ssffs;",
1074 gensym("#X"), gensym("obj"),
1075 atom_getfloatarg(2, natom, nextmess),
1076 atom_getfloatarg(3, natom, nextmess),
1077 gensym((natom > 5 ? "outlet~" : "outlet")));
1078 nobj++;
1080 else if (!strcmp(second, "user"))
1082 binbuf_addv(newb, "ssffs;",
1083 gensym("#X"), gensym("obj"),
1084 atom_getfloatarg(3, natom, nextmess),
1085 atom_getfloatarg(4, natom, nextmess),
1086 atom_getsymbolarg(2, natom, nextmess));
1087 nobj++;
1089 else if (!strcmp(second, "connect")||
1090 !strcmp(second, "fasten"))
1092 binbuf_addv(newb, "ssffff;",
1093 gensym("#X"), gensym("connect"),
1094 nobj - atom_getfloatarg(2, natom, nextmess) - 1,
1095 atom_getfloatarg(3, natom, nextmess),
1096 nobj - atom_getfloatarg(4, natom, nextmess) - 1,
1097 atom_getfloatarg(5, natom, nextmess));
1101 else /* Pd to Max */
1103 if (!strcmp(first, "#N"))
1105 if (!strcmp(second, "canvas"))
1107 if (stackdepth >= MAXSTACK)
1109 post("too many embedded patches");
1110 return (newb);
1112 stack[stackdepth] = nobj;
1113 stackdepth++;
1114 nobj = 0;
1115 binbuf_addv(newb, "ssffff;",
1116 gensym("#N"), gensym("vpatcher"),
1117 atom_getfloatarg(2, natom, nextmess),
1118 atom_getfloatarg(3, natom, nextmess),
1119 atom_getfloatarg(4, natom, nextmess),
1120 atom_getfloatarg(5, natom, nextmess));
1123 if (!strcmp(first, "#X"))
1125 if (natom >= 5 && !strcmp(second, "restore")
1126 && (ISSYMBOL (&nextmess[4], "pd")))
1128 binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
1129 binbuf_addv(newb, "ssffffss;",
1130 gensym("#P"), gensym("newobj"),
1131 atom_getfloatarg(2, natom, nextmess),
1132 atom_getfloatarg(3, natom, nextmess), 50., 1.,
1133 gensym("patcher"),
1134 atom_getsymbolarg(5, natom, nextmess));
1135 if (stackdepth) stackdepth--;
1136 nobj = stack[stackdepth];
1137 nobj++;
1139 else if (!strcmp(second, "obj"))
1141 t_symbol *classname =
1142 atom_getsymbolarg(4, natom, nextmess);
1143 if (classname == gensym("inlet"))
1144 binbuf_addv(newb, "ssfff;", gensym("#P"),
1145 gensym("inlet"),
1146 atom_getfloatarg(2, natom, nextmess),
1147 atom_getfloatarg(3, natom, nextmess),
1148 15.);
1149 else if (classname == gensym("inlet~"))
1150 binbuf_addv(newb, "ssffff;", gensym("#P"),
1151 gensym("inlet"),
1152 atom_getfloatarg(2, natom, nextmess),
1153 atom_getfloatarg(3, natom, nextmess),
1154 15., 1.);
1155 else if (classname == gensym("outlet"))
1156 binbuf_addv(newb, "ssfff;", gensym("#P"),
1157 gensym("outlet"),
1158 atom_getfloatarg(2, natom, nextmess),
1159 atom_getfloatarg(3, natom, nextmess),
1160 15.);
1161 else if (classname == gensym("outlet~"))
1162 binbuf_addv(newb, "ssffff;", gensym("#P"),
1163 gensym("outlet"),
1164 atom_getfloatarg(2, natom, nextmess),
1165 atom_getfloatarg(3, natom, nextmess),
1166 15., 1.);
1167 else if (classname == gensym("bng"))
1168 binbuf_addv(newb, "ssffff;", gensym("#P"),
1169 gensym("button"),
1170 atom_getfloatarg(2, natom, nextmess),
1171 atom_getfloatarg(3, natom, nextmess),
1172 atom_getfloatarg(5, natom, nextmess), 0.);
1173 else if (classname == gensym("tgl"))
1174 binbuf_addv(newb, "ssffff;", gensym("#P"),
1175 gensym("toggle"),
1176 atom_getfloatarg(2, natom, nextmess),
1177 atom_getfloatarg(3, natom, nextmess),
1178 atom_getfloatarg(5, natom, nextmess), 0.);
1179 else if (classname == gensym("vsl"))
1180 binbuf_addv(newb, "ssffffff;", gensym("#P"),
1181 gensym("slider"),
1182 atom_getfloatarg(2, natom, nextmess),
1183 atom_getfloatarg(3, natom, nextmess),
1184 atom_getfloatarg(5, natom, nextmess),
1185 atom_getfloatarg(6, natom, nextmess),
1186 (atom_getfloatarg(8, natom, nextmess) -
1187 atom_getfloatarg(7, natom, nextmess)) /
1188 (atom_getfloatarg(6, natom, nextmess) == 1? 1 :
1189 atom_getfloatarg(6, natom, nextmess) - 1),
1190 atom_getfloatarg(7, natom, nextmess));
1191 else
1193 SETSYMBOL(outmess, gensym("#P"));
1194 SETSYMBOL(outmess + 1, gensym("newex"));
1195 outmess[2] = nextmess[2];
1196 outmess[3] = nextmess[3];
1197 SETFLOAT(outmess + 4, 50);
1198 SETFLOAT(outmess + 5, 1);
1199 for (i = 4; i < natom; i++)
1200 outmess[i+2] = nextmess[i];
1201 SETSEMI(outmess + natom + 2);
1202 binbuf_add(newb, natom + 3, outmess);
1204 nobj++;
1207 else if (!strcmp(second, "msg") ||
1208 !strcmp(second, "text"))
1210 SETSYMBOL(outmess, gensym("#P"));
1211 SETSYMBOL(outmess + 1, gensym(
1212 (strcmp(second, "msg") ? "comment" : "message")));
1213 outmess[2] = nextmess[2];
1214 outmess[3] = nextmess[3];
1215 SETFLOAT(outmess + 4, 50);
1216 SETFLOAT(outmess + 5, 1);
1217 for (i = 4; i < natom; i++)
1218 outmess[i+2] = nextmess[i];
1219 SETSEMI(outmess + natom + 2);
1220 binbuf_add(newb, natom + 3, outmess);
1221 nobj++;
1223 else if (!strcmp(second, "floatatom"))
1225 binbuf_addv(newb, "ssfff;",
1226 gensym("#P"), gensym("flonum"),
1227 atom_getfloatarg(2, natom, nextmess),
1228 atom_getfloatarg(3, natom, nextmess), 35);
1229 nobj++;
1231 else if (!strcmp(second, "connect"))
1233 binbuf_addv(newb, "ssffff;",
1234 gensym("#P"), gensym("connect"),
1235 nobj - atom_getfloatarg(2, natom, nextmess) - 1,
1236 atom_getfloatarg(3, natom, nextmess),
1237 nobj - atom_getfloatarg(4, natom, nextmess) - 1,
1238 atom_getfloatarg(5, natom, nextmess));
1242 nextindex = endmess + 1;
1244 if (!maxtopd)
1245 binbuf_addv(newb, "ss;", gensym("#P"), gensym("pop"));
1246 #if 0
1247 binbuf_write(newb, "import-result.pd", "/tmp", 0);
1248 #endif
1249 return (newb);
1252 /* function to support searching */
1253 int binbuf_match(t_binbuf *inbuf, t_binbuf *searchbuf)
1255 int indexin, nmatched;
1256 for (indexin = 0; indexin <= inbuf->b_n - searchbuf->b_n; indexin++)
1258 for (nmatched = 0; nmatched < searchbuf->b_n; nmatched++)
1260 t_atom *a1 = &inbuf->b_vec[indexin + nmatched],
1261 *a2 = &searchbuf->b_vec[nmatched];
1262 if (a1->a_type != a2->a_type ||
1263 (a1->a_type == A_SYMBOL && a1->a_w.w_symbol != a2->a_w.w_symbol)
1265 (a1->a_type == A_FLOAT && a1->a_w.w_float != a2->a_w.w_float)
1267 (a1->a_type == A_DOLLAR && a1->a_w.w_index != a2->a_w.w_index)
1269 (a1->a_type == A_DOLLSYM && a1->a_w.w_symbol != a2->a_w.w_symbol))
1270 goto nomatch;
1272 return (1);
1273 nomatch: ;
1275 return (0);
1278 void pd_doloadbang(void);
1280 /* LATER make this evaluate the file on-the-fly. */
1281 /* LATER figure out how to log errors */
1282 void binbuf_evalfile(t_symbol *name, t_symbol *dir)
1284 t_binbuf *b = binbuf_new();
1285 int import = !strcmp(name->s_name + strlen(name->s_name) - 4, ".pat");
1286 /* set filename so that new canvases can pick them up */
1287 int dspstate = canvas_suspend_dsp();
1288 glob_setfilename(0, name, dir);
1290 if (binbuf_read(b, name->s_name, dir->s_name, 0))
1292 #if !defined(ROCKBOX) || (defined(ROCKBOX) && defined(SIMULATOR))
1293 perror(name->s_name);
1294 #endif
1296 else
1298 if (import)
1300 t_binbuf *newb = binbuf_convert(b, 1);
1301 binbuf_free(b);
1302 b = newb;
1304 binbuf_eval(b, 0, 0, 0);
1306 glob_setfilename(0, &s_, &s_); /* bug fix by Krzysztof Czaja */
1307 binbuf_free(b);
1308 canvas_resume_dsp(dspstate);
1311 void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
1313 t_pd *x = 0;
1315 #ifdef ROCKBOX
1316 (void) ignore;
1317 #endif
1318 /* even though binbuf_evalfile appears to take care of dspstate,
1319 we have to do it again here, because canvas_startdsp() assumes
1320 that all toplevel canvases are visible. LATER check if this
1321 is still necessary -- probably not. */
1323 int dspstate = canvas_suspend_dsp();
1324 binbuf_evalfile(name, dir);
1325 while ((x != s__X.s_thing) && (x = s__X.s_thing))
1326 vmess(x, gensym("pop"), "i", 1);
1327 pd_doloadbang();
1328 canvas_resume_dsp(dspstate);