diff options
author | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-05-22 21:58:48 +0000 |
---|---|---|
committer | Peter D'Hoye <peter.dhoye@gmail.com> | 2009-05-22 21:58:48 +0000 |
commit | 513389b4c1bc8afe4b2dc9947c534bfeb105e3da (patch) | |
tree | 10e673b35651ac567fed2eda0c679c7ade64cbc6 /apps/plugins/pdbox/PDa/src/m_binbuf.c | |
parent | 95fa7f6a2ef466444fbe3fe87efc6d5db6b77b36 (diff) | |
download | rockbox-513389b4c1bc8afe4b2dc9947c534bfeb105e3da.tar.gz rockbox-513389b4c1bc8afe4b2dc9947c534bfeb105e3da.zip |
Add FS #10214. Initial commit of the original PDa code for the GSoC Pure Data plugin project of Wincent Balin. Stripped some non-sourcefiles and added a rockbox readme that needs a bit more info from Wincent. Is added to CATEGORIES and viewers, but not yet to SUBDIRS (ie doesn't build yet)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21044 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/m_binbuf.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/m_binbuf.c | 2438 |
1 files changed, 2438 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/m_binbuf.c b/apps/plugins/pdbox/PDa/src/m_binbuf.c new file mode 100644 index 0000000000..c215e399e6 --- /dev/null +++ b/apps/plugins/pdbox/PDa/src/m_binbuf.c | |||
@@ -0,0 +1,2438 @@ | |||
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. */ | ||
4 | |||
5 | |||
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 | ||
11 | */ | ||
12 | |||
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> | ||
26 | |||
27 | struct _binbuf | ||
28 | { | ||
29 | int b_n; | ||
30 | t_atom *b_vec; | ||
31 | }; | ||
32 | |||
33 | t_binbuf *binbuf_new(void) | ||
34 | { | ||
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); | ||
39 | } | ||
40 | |||
41 | void binbuf_free(t_binbuf *x) | ||
42 | { | ||
43 | t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec)); | ||
44 | t_freebytes(x, sizeof(*x)); | ||
45 | } | ||
46 | |||
47 | t_binbuf *binbuf_duplicate(t_binbuf *y) | ||
48 | { | ||
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); | ||
54 | } | ||
55 | |||
56 | void binbuf_clear(t_binbuf *x) | ||
57 | { | ||
58 | x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0); | ||
59 | x->b_n = 0; | ||
60 | } | ||
61 | |||
62 | /* convert text to a binbuf */ | ||
63 | void binbuf_text(t_binbuf *x, char *text, size_t size) | ||
64 | { | ||
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) | ||
74 | { | ||
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 | ||
83 | { | ||
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; | ||
89 | do | ||
90 | { | ||
91 | c = *bufp = *textp++; | ||
92 | lastslash = slash; | ||
93 | slash = (c == '\\'); | ||
94 | |||
95 | if (floatstate >= 0) | ||
96 | { | ||
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 */ | ||
102 | { | ||
103 | if (minus) floatstate = 1; | ||
104 | else if (digit) floatstate = 2; | ||
105 | else if (dot) floatstate = 3; | ||
106 | else floatstate = -1; | ||
107 | } | ||
108 | else if (floatstate == 1) /* got minus */ | ||
109 | { | ||
110 | if (digit) floatstate = 2; | ||
111 | else if (dot) floatstate = 3; | ||
112 | else floatstate = -1; | ||
113 | } | ||
114 | else if (floatstate == 2) /* got digits */ | ||
115 | { | ||
116 | if (dot) floatstate = 4; | ||
117 | else if (expon) floatstate = 6; | ||
118 | else if (!digit) floatstate = -1; | ||
119 | } | ||
120 | else if (floatstate == 3) /* got '.' without digits */ | ||
121 | { | ||
122 | if (digit) floatstate = 5; | ||
123 | else floatstate = -1; | ||
124 | } | ||
125 | else if (floatstate == 4) /* got '.' after digits */ | ||
126 | { | ||
127 | if (digit) floatstate = 5; | ||
128 | else if (expon) floatstate = 6; | ||
129 | else floatstate = -1; | ||
130 | } | ||
131 | else if (floatstate == 5) /* got digits after . */ | ||
132 | { | ||
133 | if (expon) floatstate = 6; | ||
134 | else if (!digit) floatstate = -1; | ||
135 | } | ||
136 | else if (floatstate == 6) /* got 'e' */ | ||
137 | { | ||
138 | if (plusminus) floatstate = 7; | ||
139 | else if (digit) floatstate = 8; | ||
140 | else floatstate = -1; | ||
141 | } | ||
142 | else if (floatstate == 7) /* got plus or minus */ | ||
143 | { | ||
144 | if (digit) floatstate = 8; | ||
145 | else floatstate = -1; | ||
146 | } | ||
147 | else if (floatstate == 8) /* got digits */ | ||
148 | { | ||
149 | if (!digit) floatstate = -1; | ||
150 | } | ||
151 | } | ||
152 | if (!slash) bufp++; | ||
153 | } | ||
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) | ||
162 | { | ||
163 | for (bufp = buf+2; *bufp; bufp++) | ||
164 | if (*bufp < '0' || *bufp > '9') | ||
165 | { | ||
166 | SETDOLLSYM(ap, gensym(buf+1)); | ||
167 | goto didit; | ||
168 | } | ||
169 | SETDOLLAR(ap, atoi(buf+1)); | ||
170 | didit: ; | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | if (floatstate == 2 || floatstate == 4 || floatstate == 5 || | ||
175 | floatstate == 8) | ||
176 | SETFLOAT(ap, atof(buf)); | ||
177 | else SETSYMBOL(ap, gensym(buf)); | ||
178 | } | ||
179 | } | ||
180 | ap++; | ||
181 | natom++; | ||
182 | if (natom == nalloc) | ||
183 | { | ||
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; | ||
188 | } | ||
189 | if (textp == etext) break; | ||
190 | } | ||
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; | ||
195 | } | ||
196 | |||
197 | /* convert a binbuf to text; no null termination. */ | ||
198 | void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp) | ||
199 | { | ||
200 | char *buf = getbytes(0), *newbuf; | ||
201 | int length = 0; | ||
202 | char string[MAXPDSTRING]; | ||
203 | t_atom *ap; | ||
204 | int indx; | ||
205 | |||
206 | for (ap = x->b_vec, indx = x->b_n; indx--; ap++) | ||
207 | { | ||
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] = ' '; | ||
219 | } | ||
220 | if (length && buf[length-1] == ' ') | ||
221 | { | ||
222 | if (newbuf = t_resizebytes(buf, length, length-1)) | ||
223 | { | ||
224 | buf = newbuf; | ||
225 | length--; | ||
226 | } | ||
227 | } | ||
228 | *bufp = buf; | ||
229 | *lengthp = length; | ||
230 | } | ||
231 | |||
232 | /* LATER improve the out-of-space behavior below. Also fix this so that | ||
233 | writing to file doesn't buffer everything together. */ | ||
234 | |||
235 | void binbuf_add(t_binbuf *x, int argc, t_atom *argv) | ||
236 | { | ||
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 | ||
243 | { | ||
244 | error("binbuf_addmessage: out of space"); | ||
245 | return; | ||
246 | } | ||
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; | ||
255 | } | ||
256 | |||
257 | #define MAXADDMESSV 100 | ||
258 | void binbuf_addv(t_binbuf *x, char *fmt, ...) | ||
259 | { | ||
260 | va_list ap; | ||
261 | t_atom arg[MAXADDMESSV], *at =arg; | ||
262 | int nargs = 0; | ||
263 | char *fp = fmt; | ||
264 | |||
265 | va_start(ap, fmt); | ||
266 | while (1) | ||
267 | { | ||
268 | if (nargs >= MAXADDMESSV) | ||
269 | { | ||
270 | error("binbuf_addmessv: only %d allowed", MAXADDMESSV); | ||
271 | break; | ||
272 | } | ||
273 | switch(*fp++) | ||
274 | { | ||
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; | ||
281 | } | ||
282 | at++; | ||
283 | nargs++; | ||
284 | } | ||
285 | done: | ||
286 | va_end(ap); | ||
287 | binbuf_add(x, nargs, arg); | ||
288 | } | ||
289 | |||
290 | /* add a binbuf to another one for saving. Semicolons and commas go to | ||
291 | symbols ";", "'",; the symbol ";" goes to "\;", etc. */ | ||
292 | |||
293 | void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y) | ||
294 | { | ||
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++) | ||
300 | { | ||
301 | char tbuf[MAXPDSTRING]; | ||
302 | switch (ap->a_type) | ||
303 | { | ||
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"); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | binbuf_add(x, z->b_n, z->b_vec); | ||
333 | } | ||
334 | |||
335 | void binbuf_addsemi(t_binbuf *x) | ||
336 | { | ||
337 | t_atom a; | ||
338 | SETSEMI(&a); | ||
339 | binbuf_add(x, 1, &a); | ||
340 | } | ||
341 | |||
342 | /* Supply atoms to a binbuf from a message, making the opposite changes | ||
343 | from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */ | ||
344 | |||
345 | void binbuf_restore(t_binbuf *x, int argc, t_atom *argv) | ||
346 | { | ||
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 | ||
353 | { | ||
354 | error("binbuf_addmessage: out of space"); | ||
355 | return; | ||
356 | } | ||
357 | |||
358 | for (ap = x->b_vec + x->b_n, i = argc; i--; ap++) | ||
359 | { | ||
360 | if (argv->a_type == A_SYMBOL) | ||
361 | { | ||
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') | ||
366 | { | ||
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 | ||
375 | { | ||
376 | int dollar = 0; | ||
377 | sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar); | ||
378 | SETDOLLAR(ap, dollar); | ||
379 | } | ||
380 | } | ||
381 | else *ap = *argv; | ||
382 | argv++; | ||
383 | } | ||
384 | else *ap = *(argv++); | ||
385 | } | ||
386 | x->b_n = newsize; | ||
387 | } | ||
388 | |||
389 | |||
390 | #define MSTACKSIZE 2048 | ||
391 | |||
392 | void binbuf_print(t_binbuf *x) | ||
393 | { | ||
394 | int i, startedpost = 0, newline = 1; | ||
395 | for (i = 0; i < x->b_n; i++) | ||
396 | { | ||
397 | if (newline) | ||
398 | { | ||
399 | if (startedpost) endpost(); | ||
400 | startpost(""); | ||
401 | startedpost = 1; | ||
402 | } | ||
403 | postatom(1, x->b_vec + i); | ||
404 | if (x->b_vec[i].a_type == A_SEMI) | ||
405 | newline = 1; | ||
406 | else newline = 0; | ||
407 | } | ||
408 | if (startedpost) endpost(); | ||
409 | } | ||
410 | |||
411 | int binbuf_getnatom(t_binbuf *x) | ||
412 | { | ||
413 | return (x->b_n); | ||
414 | } | ||
415 | |||
416 | t_atom *binbuf_getvec(t_binbuf *x) | ||
417 | { | ||
418 | return (x->b_vec); | ||
419 | } | ||
420 | |||
421 | int canvas_getdollarzero( void); | ||
422 | |||
423 | t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew) | ||
424 | { | ||
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) | ||
430 | { | ||
431 | if (!tonew) | ||
432 | return (0); | ||
433 | else sprintf(buf, "$%d", argno); | ||
434 | } | ||
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)); | ||
441 | } | ||
442 | |||
443 | void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) | ||
444 | { | ||
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) | ||
451 | { | ||
452 | t_pd *nexttarget; | ||
453 | /* get a target. */ | ||
454 | while (!target) | ||
455 | { | ||
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) | ||
461 | { | ||
462 | if (at->a_w.w_index <= 0 || at->a_w.w_index > argc) | ||
463 | { | ||
464 | error("$%d: not enough arguments supplied", | ||
465 | at->a_w.w_index); | ||
466 | goto cleanup; | ||
467 | } | ||
468 | else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL) | ||
469 | { | ||
470 | error("$%d: symbol needed as message destination", | ||
471 | at->a_w.w_index); | ||
472 | goto cleanup; | ||
473 | } | ||
474 | else s = argv[at->a_w.w_index-1].a_w.w_symbol; | ||
475 | } | ||
476 | else if (at->a_type == A_DOLLSYM) | ||
477 | { | ||
478 | if (!(s = binbuf_realizedollsym(at->a_w.w_symbol, | ||
479 | argc, argv, 0))) | ||
480 | { | ||
481 | error("$%s: not enough arguments supplied", | ||
482 | at->a_w.w_symbol->s_name); | ||
483 | goto cleanup; | ||
484 | } | ||
485 | } | ||
486 | else s = atom_getsymbol(at); | ||
487 | if (!(target = s->s_thing)) | ||
488 | { | ||
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; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | at++, ac--; | ||
499 | break; | ||
500 | } | ||
501 | } | ||
502 | if (!ac) break; | ||
503 | nargs = 0; | ||
504 | nexttarget = target; | ||
505 | while (1) | ||
506 | { | ||
507 | t_symbol *s9; | ||
508 | if (!ac) goto gotmess; | ||
509 | if (msp >= ems) | ||
510 | { | ||
511 | error("message stack overflow"); | ||
512 | goto broken; | ||
513 | } | ||
514 | switch (at->a_type) | ||
515 | { | ||
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) | ||
520 | { | ||
521 | SETSYMBOL(msp, gensym(";")); | ||
522 | break; | ||
523 | } | ||
524 | else | ||
525 | { | ||
526 | nexttarget = 0; | ||
527 | goto gotmess; | ||
528 | } | ||
529 | case A_COMMA: | ||
530 | if (target == &pd_objectmaker) | ||
531 | { | ||
532 | SETSYMBOL(msp, gensym(",")); | ||
533 | break; | ||
534 | } | ||
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 | ||
546 | { | ||
547 | if (target == &pd_objectmaker) | ||
548 | SETFLOAT(msp, 0); | ||
549 | else | ||
550 | { | ||
551 | error("$%d: argument number out of range", | ||
552 | at->a_w.w_index); | ||
553 | SETFLOAT(msp, 0); | ||
554 | } | ||
555 | } | ||
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; | ||
567 | } | ||
568 | msp++; | ||
569 | ac--; | ||
570 | at++; | ||
571 | nargs++; | ||
572 | } | ||
573 | gotmess: | ||
574 | if (nargs) | ||
575 | { | ||
576 | switch (stackwas->a_type) | ||
577 | { | ||
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; | ||
585 | } | ||
586 | } | ||
587 | msp = stackwas; | ||
588 | if (!ac) break; | ||
589 | target = nexttarget; | ||
590 | at++; | ||
591 | ac--; | ||
592 | } | ||
593 | |||
594 | return; | ||
595 | broken: | ||
596 | msp = stackwas; | ||
597 | } | ||
598 | |||
599 | static int binbuf_doopen(char *s, int mode) | ||
600 | { | ||
601 | char namebuf[MAXPDSTRING]; | ||
602 | #ifdef MSW | ||
603 | mode |= O_BINARY; | ||
604 | #endif | ||
605 | sys_bashfilename(s, namebuf); | ||
606 | return (open(namebuf, mode)); | ||
607 | } | ||
608 | |||
609 | static FILE *binbuf_dofopen(char *s, char *mode) | ||
610 | { | ||
611 | char namebuf[MAXPDSTRING]; | ||
612 | sys_bashfilename(s, namebuf); | ||
613 | return (fopen(namebuf, mode)); | ||
614 | } | ||
615 | |||
616 | int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag) | ||
617 | { | ||
618 | long length; | ||
619 | int fd; | ||
620 | int readret; | ||
621 | char *buf; | ||
622 | char namebuf[MAXPDSTRING]; | ||
623 | |||
624 | namebuf[0] = 0; | ||
625 | if (*dirname) | ||
626 | strcat(namebuf, dirname), strcat(namebuf, "/"); | ||
627 | strcat(namebuf, filename); | ||
628 | |||
629 | if ((fd = binbuf_doopen(namebuf, 0)) < 0) | ||
630 | { | ||
631 | fprintf(stderr, "open: "); | ||
632 | perror(namebuf); | ||
633 | return (1); | ||
634 | } | ||
635 | if ((length = lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0 | ||
636 | || !(buf = t_getbytes(length))) | ||
637 | { | ||
638 | fprintf(stderr, "lseek: "); | ||
639 | perror(namebuf); | ||
640 | close(fd); | ||
641 | return(1); | ||
642 | } | ||
643 | if ((readret = read(fd, buf, length)) < length) | ||
644 | { | ||
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); | ||
650 | } | ||
651 | /* optionally map carriage return to semicolon */ | ||
652 | if (crflag) | ||
653 | { | ||
654 | int i; | ||
655 | for (i = 0; i < length; i++) | ||
656 | if (buf[i] == '\n') | ||
657 | buf[i] = ';'; | ||
658 | } | ||
659 | binbuf_text(b, buf, length); | ||
660 | |||
661 | #if 0 | ||
662 | startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost(); | ||
663 | #endif | ||
664 | |||
665 | t_freebytes(buf, length); | ||
666 | close(fd); | ||
667 | return (0); | ||
668 | } | ||
669 | |||
670 | int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname, | ||
671 | int crflag) | ||
672 | { | ||
673 | int filedesc; | ||
674 | char buf[MAXPDSTRING], *bufptr; | ||
675 | if ((filedesc = open_via_path( | ||
676 | dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0) | ||
677 | { | ||
678 | error("%s: can't open", filename); | ||
679 | return (1); | ||
680 | } | ||
681 | else close (filedesc); | ||
682 | if (binbuf_read(b, bufptr, buf, crflag)) | ||
683 | return (1); | ||
684 | else return (0); | ||
685 | } | ||
686 | |||
687 | #define WBUFSIZE 4096 | ||
688 | static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd); | ||
689 | |||
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) | ||
693 | { | ||
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; | ||
699 | |||
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")) | ||
705 | { | ||
706 | x = binbuf_convert(x, 0); | ||
707 | deleteit = 1; | ||
708 | } | ||
709 | |||
710 | if (!(f = binbuf_dofopen(fbuf, "w"))) | ||
711 | { | ||
712 | fprintf(stderr, "open: "); | ||
713 | sys_unixerror(fbuf); | ||
714 | goto fail; | ||
715 | } | ||
716 | for (ap = x->b_vec, indx = x->b_n; indx--; ap++) | ||
717 | { | ||
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) | ||
725 | { | ||
726 | if (fwrite(sbuf, bp-sbuf, 1, f) < 1) | ||
727 | { | ||
728 | sys_unixerror(fbuf); | ||
729 | goto fail; | ||
730 | } | ||
731 | bp = sbuf; | ||
732 | } | ||
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) | ||
736 | { | ||
737 | atom_string(ap, bp, (ep-bp)-2); | ||
738 | length = strlen(bp); | ||
739 | bp += length; | ||
740 | ncolumn += length; | ||
741 | } | ||
742 | if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65)) | ||
743 | { | ||
744 | *bp++ = '\n'; | ||
745 | ncolumn = 0; | ||
746 | } | ||
747 | else | ||
748 | { | ||
749 | *bp++ = ' '; | ||
750 | ncolumn++; | ||
751 | } | ||
752 | } | ||
753 | if (fwrite(sbuf, bp-sbuf, 1, f) < 1) | ||
754 | { | ||
755 | sys_unixerror(fbuf); | ||
756 | goto fail; | ||
757 | } | ||
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); | ||
768 | } | ||
769 | |||
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! */ | ||
774 | |||
775 | #define MAXSTACK 1000 | ||
776 | |||
777 | #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \ | ||
778 | !strcmp((a)->a_w.w_symbol->s_name, (b))) | ||
779 | |||
780 | static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd) | ||
781 | { | ||
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; ) | ||
790 | { | ||
791 | int endmess, natom; | ||
792 | char *first, *second; | ||
793 | for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI; | ||
794 | endmess++) | ||
795 | ; | ||
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) | ||
800 | { | ||
801 | nextindex = endmess + 1; | ||
802 | continue; | ||
803 | } | ||
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) | ||
810 | { | ||
811 | /* case 1: importing a ".pat" file into Pd. */ | ||
812 | |||
813 | /* dollar signs in file translate to symbols */ | ||
814 | for (i = 0; i < natom; i++) | ||
815 | { | ||
816 | if (nextmess[i].a_type == A_DOLLAR) | ||
817 | { | ||
818 | char buf[100]; | ||
819 | sprintf(buf, "$%d", nextmess[i].a_w.w_index); | ||
820 | SETSYMBOL(nextmess+i, gensym(buf)); | ||
821 | } | ||
822 | else if (nextmess[i].a_type == A_DOLLSYM) | ||
823 | { | ||
824 | char buf[100]; | ||
825 | sprintf(buf, "$%s", nextmess[i].a_w.w_symbol->s_name); | ||
826 | SETSYMBOL(nextmess+i, gensym(buf)); | ||
827 | } | ||
828 | } | ||
829 | if (!strcmp(first, "#N")) | ||
830 | { | ||
831 | if (!strcmp(second, "vpatcher")) | ||
832 | { | ||
833 | if (stackdepth >= MAXSTACK) | ||
834 | { | ||
835 | post("too many embedded patches"); | ||
836 | return (newb); | ||
837 | } | ||
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); | ||
850 | } | ||
851 | } | ||
852 | if (!strcmp(first, "#P")) | ||
853 | { | ||
854 | /* drop initial "hidden" flag */ | ||
855 | if (!strcmp(second, "hidden")) | ||
856 | { | ||
857 | nextmess++; | ||
858 | natom--; | ||
859 | second = (nextmess+1)->a_w.w_symbol->s_name; | ||
860 | } | ||
861 | if (natom >= 7 && !strcmp(second, "newobj") | ||
862 | && (ISSYMBOL(&nextmess[6], "patcher") || | ||
863 | ISSYMBOL(&nextmess[6], "p"))) | ||
864 | { | ||
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++; | ||
873 | } | ||
874 | else if (!strcmp(second, "newex") || !strcmp(second, "newobj")) | ||
875 | { | ||
876 | t_symbol *classname = | ||
877 | atom_getsymbolarg(6, natom, nextmess); | ||
878 | if (classname == gensym("trigger") || | ||
879 | classname == gensym("t")) | ||
880 | { | ||
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"); | ||
885 | } | ||
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++; | ||
898 | } | ||
899 | else if (!strcmp(second, "message") || | ||
900 | !strcmp(second, "comment")) | ||
901 | { | ||
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++; | ||
912 | } | ||
913 | else if (!strcmp(second, "button")) | ||
914 | { | ||
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++; | ||
921 | } | ||
922 | else if (!strcmp(second, "number") || !strcmp(second, "flonum")) | ||
923 | { | ||
924 | binbuf_addv(newb, "ssff;", | ||
925 | gensym("#X"), gensym("floatatom"), | ||
926 | atom_getfloatarg(2, natom, nextmess), | ||
927 | atom_getfloatarg(3, natom, nextmess)); | ||
928 | nobj++; | ||
929 | } | ||
930 | else if (!strcmp(second, "slider")) | ||
931 | { | ||
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++; | ||
949 | } | ||
950 | else if (!strcmp(second, "toggle")) | ||
951 | { | ||
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++; | ||
958 | } | ||
959 | else if (!strcmp(second, "inlet")) | ||
960 | { | ||
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++; | ||
967 | } | ||
968 | else if (!strcmp(second, "outlet")) | ||
969 | { | ||
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++; | ||
976 | } | ||
977 | else if (!strcmp(second, "user")) | ||
978 | { | ||
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++; | ||
985 | } | ||
986 | else if (!strcmp(second, "connect")|| | ||
987 | !strcmp(second, "fasten")) | ||
988 | { | ||
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)); | ||
995 | } | ||
996 | } | ||
997 | } | ||
998 | else /* Pd to Max */ | ||
999 | { | ||
1000 | if (!strcmp(first, "#N")) | ||
1001 | { | ||
1002 | if (!strcmp(second, "canvas")) | ||
1003 | { | ||
1004 | if (stackdepth >= MAXSTACK) | ||
1005 | { | ||
1006 | post("too many embedded patches"); | ||
1007 | return (newb); | ||
1008 | } | ||
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)); | ||
1018 | } | ||
1019 | } | ||
1020 | if (!strcmp(first, "#X")) | ||
1021 | { | ||
1022 | if (natom >= 5 && !strcmp(second, "restore") | ||
1023 | && (ISSYMBOL (&nextmess[4], "pd"))) | ||
1024 | { | ||
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++; | ||
1035 | } | ||
1036 | else if (!strcmp(second, "obj")) | ||
1037 | { | ||
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 | ||
1089 | { | ||
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); | ||
1100 | } | ||
1101 | nobj++; | ||
1102 | |||
1103 | } | ||
1104 | else if (!strcmp(second, "msg") || | ||
1105 | !strcmp(second, "text")) | ||
1106 | { | ||
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++; | ||
1119 | } | ||
1120 | else if (!strcmp(second, "floatatom")) | ||
1121 | { | ||
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++; | ||
1127 | } | ||
1128 | else if (!strcmp(second, "connect")) | ||
1129 | { | ||
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)); | ||
1136 | } | ||
1137 | } | ||
1138 | } | ||
1139 | nextindex = endmess + 1; | ||
1140 | } | ||
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); | ||
1147 | } | ||
1148 | |||
1149 | /* function to support searching */ | ||
1150 | int binbuf_match(t_binbuf *inbuf, t_binbuf *searchbuf) | ||
1151 | { | ||
1152 | int indexin, nmatched; | ||
1153 | for (indexin = 0; indexin <= inbuf->b_n - searchbuf->b_n; indexin++) | ||
1154 | { | ||
1155 | for (nmatched = 0; nmatched < searchbuf->b_n; nmatched++) | ||
1156 | { | ||
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 | ||
1161 | || | ||
1162 | a1->a_type == A_FLOAT && a1->a_w.w_float != a2->a_w.w_float | ||
1163 | || | ||
1164 | a1->a_type == A_DOLLAR && a1->a_w.w_index != a2->a_w.w_index | ||
1165 | || | ||
1166 | a1->a_type == A_DOLLSYM && a1->a_w.w_symbol != a2->a_w.w_symbol) | ||
1167 | goto nomatch; | ||
1168 | } | ||
1169 | return (1); | ||
1170 | nomatch: ; | ||
1171 | } | ||
1172 | return (0); | ||
1173 | } | ||
1174 | |||
1175 | void pd_doloadbang(void); | ||
1176 | |||
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) | ||
1180 | { | ||
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)) | ||
1187 | { | ||
1188 | perror(name->s_name); | ||
1189 | } | ||
1190 | else | ||
1191 | { | ||
1192 | if (import) | ||
1193 | { | ||
1194 | t_binbuf *newb = binbuf_convert(b, 1); | ||
1195 | binbuf_free(b); | ||
1196 | b = newb; | ||
1197 | } | ||
1198 | binbuf_eval(b, 0, 0, 0); | ||
1199 | } | ||
1200 | glob_setfilename(0, &s_, &s_); /* bug fix by Krzysztof Czaja */ | ||
1201 | binbuf_free(b); | ||
1202 | canvas_resume_dsp(dspstate); | ||
1203 | } | ||
1204 | |||
1205 | void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir) | ||
1206 | { | ||
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. */ | ||
1212 | |||
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); | ||
1219 | } | ||
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. */ | ||
1223 | |||
1224 | |||
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 | ||
1230 | */ | ||
1231 | |||
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> | ||
1245 | |||
1246 | struct _binbuf | ||
1247 | { | ||
1248 | int b_n; | ||
1249 | t_atom *b_vec; | ||
1250 | }; | ||
1251 | |||
1252 | t_binbuf *binbuf_new(void) | ||
1253 | { | ||
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); | ||
1258 | } | ||
1259 | |||
1260 | void binbuf_free(t_binbuf *x) | ||
1261 | { | ||
1262 | t_freebytes(x->b_vec, x->b_n * sizeof(*x->b_vec)); | ||
1263 | t_freebytes(x, sizeof(*x)); | ||
1264 | } | ||
1265 | |||
1266 | t_binbuf *binbuf_duplicate(t_binbuf *y) | ||
1267 | { | ||
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); | ||
1273 | } | ||
1274 | |||
1275 | void binbuf_clear(t_binbuf *x) | ||
1276 | { | ||
1277 | x->b_vec = t_resizebytes(x->b_vec, x->b_n * sizeof(*x->b_vec), 0); | ||
1278 | x->b_n = 0; | ||
1279 | } | ||
1280 | |||
1281 | /* convert text to a binbuf */ | ||
1282 | void binbuf_text(t_binbuf *x, char *text, size_t size) | ||
1283 | { | ||
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) | ||
1293 | { | ||
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 | ||
1302 | { | ||
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; | ||
1308 | do | ||
1309 | { | ||
1310 | c = *bufp = *textp++; | ||
1311 | lastslash = slash; | ||
1312 | slash = (c == '\\'); | ||
1313 | |||
1314 | if (floatstate >= 0) | ||
1315 | { | ||
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 */ | ||
1321 | { | ||
1322 | if (minus) floatstate = 1; | ||
1323 | else if (digit) floatstate = 2; | ||
1324 | else if (dot) floatstate = 3; | ||
1325 | else floatstate = -1; | ||
1326 | } | ||
1327 | else if (floatstate == 1) /* got minus */ | ||
1328 | { | ||
1329 | if (digit) floatstate = 2; | ||
1330 | else if (dot) floatstate = 3; | ||
1331 | else floatstate = -1; | ||
1332 | } | ||
1333 | else if (floatstate == 2) /* got digits */ | ||
1334 | { | ||
1335 | if (dot) floatstate = 4; | ||
1336 | else if (expon) floatstate = 6; | ||
1337 | else if (!digit) floatstate = -1; | ||
1338 | } | ||
1339 | else if (floatstate == 3) /* got '.' without digits */ | ||
1340 | { | ||
1341 | if (digit) floatstate = 5; | ||
1342 | else floatstate = -1; | ||
1343 | } | ||
1344 | else if (floatstate == 4) /* got '.' after digits */ | ||
1345 | { | ||
1346 | if (digit) floatstate = 5; | ||
1347 | else if (expon) floatstate = 6; | ||
1348 | else floatstate = -1; | ||
1349 | } | ||
1350 | else if (floatstate == 5) /* got digits after . */ | ||
1351 | { | ||
1352 | if (expon) floatstate = 6; | ||
1353 | else if (!digit) floatstate = -1; | ||
1354 | } | ||
1355 | else if (floatstate == 6) /* got 'e' */ | ||
1356 | { | ||
1357 | if (plusminus) floatstate = 7; | ||
1358 | else if (digit) floatstate = 8; | ||
1359 | else floatstate = -1; | ||
1360 | } | ||
1361 | else if (floatstate == 7) /* got plus or minus */ | ||
1362 | { | ||
1363 | if (digit) floatstate = 8; | ||
1364 | else floatstate = -1; | ||
1365 | } | ||
1366 | else if (floatstate == 8) /* got digits */ | ||
1367 | { | ||
1368 | if (!digit) floatstate = -1; | ||
1369 | } | ||
1370 | } | ||
1371 | if (!slash) bufp++; | ||
1372 | } | ||
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) | ||
1381 | { | ||
1382 | for (bufp = buf+2; *bufp; bufp++) | ||
1383 | if (*bufp < '0' || *bufp > '9') | ||
1384 | { | ||
1385 | SETDOLLSYM(ap, gensym(buf+1)); | ||
1386 | goto didit; | ||
1387 | } | ||
1388 | SETDOLLAR(ap, atoi(buf+1)); | ||
1389 | didit: ; | ||
1390 | } | ||
1391 | else | ||
1392 | { | ||
1393 | if (floatstate == 2 || floatstate == 4 || floatstate == 5 || | ||
1394 | floatstate == 8) | ||
1395 | SETFLOAT(ap, atof(buf)); | ||
1396 | else SETSYMBOL(ap, gensym(buf)); | ||
1397 | } | ||
1398 | } | ||
1399 | ap++; | ||
1400 | natom++; | ||
1401 | if (natom == nalloc) | ||
1402 | { | ||
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; | ||
1407 | } | ||
1408 | if (textp == etext) break; | ||
1409 | } | ||
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; | ||
1414 | } | ||
1415 | |||
1416 | /* convert a binbuf to text; no null termination. */ | ||
1417 | void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp) | ||
1418 | { | ||
1419 | char *buf = getbytes(0), *newbuf; | ||
1420 | int length = 0; | ||
1421 | char string[MAXPDSTRING]; | ||
1422 | t_atom *ap; | ||
1423 | int indx; | ||
1424 | |||
1425 | for (ap = x->b_vec, indx = x->b_n; indx--; ap++) | ||
1426 | { | ||
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] = ' '; | ||
1438 | } | ||
1439 | if (length && buf[length-1] == ' ') | ||
1440 | { | ||
1441 | if (newbuf = t_resizebytes(buf, length, length-1)) | ||
1442 | { | ||
1443 | buf = newbuf; | ||
1444 | length--; | ||
1445 | } | ||
1446 | } | ||
1447 | *bufp = buf; | ||
1448 | *lengthp = length; | ||
1449 | } | ||
1450 | |||
1451 | /* LATER improve the out-of-space behavior below. Also fix this so that | ||
1452 | writing to file doesn't buffer everything together. */ | ||
1453 | |||
1454 | void binbuf_add(t_binbuf *x, int argc, t_atom *argv) | ||
1455 | { | ||
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 | ||
1462 | { | ||
1463 | error("binbuf_addmessage: out of space"); | ||
1464 | return; | ||
1465 | } | ||
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; | ||
1474 | } | ||
1475 | |||
1476 | #define MAXADDMESSV 100 | ||
1477 | void binbuf_addv(t_binbuf *x, char *fmt, ...) | ||
1478 | { | ||
1479 | va_list ap; | ||
1480 | t_atom arg[MAXADDMESSV], *at =arg; | ||
1481 | int nargs = 0; | ||
1482 | char *fp = fmt; | ||
1483 | |||
1484 | va_start(ap, fmt); | ||
1485 | while (1) | ||
1486 | { | ||
1487 | if (nargs >= MAXADDMESSV) | ||
1488 | { | ||
1489 | error("binbuf_addmessv: only %d allowed", MAXADDMESSV); | ||
1490 | break; | ||
1491 | } | ||
1492 | switch(*fp++) | ||
1493 | { | ||
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; | ||
1500 | } | ||
1501 | at++; | ||
1502 | nargs++; | ||
1503 | } | ||
1504 | done: | ||
1505 | va_end(ap); | ||
1506 | binbuf_add(x, nargs, arg); | ||
1507 | } | ||
1508 | |||
1509 | /* add a binbuf to another one for saving. Semicolons and commas go to | ||
1510 | symbols ";", "'",; the symbol ";" goes to "\;", etc. */ | ||
1511 | |||
1512 | void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y) | ||
1513 | { | ||
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++) | ||
1519 | { | ||
1520 | char tbuf[MAXPDSTRING]; | ||
1521 | switch (ap->a_type) | ||
1522 | { | ||
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"); | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | binbuf_add(x, z->b_n, z->b_vec); | ||
1552 | } | ||
1553 | |||
1554 | void binbuf_addsemi(t_binbuf *x) | ||
1555 | { | ||
1556 | t_atom a; | ||
1557 | SETSEMI(&a); | ||
1558 | binbuf_add(x, 1, &a); | ||
1559 | } | ||
1560 | |||
1561 | /* Supply atoms to a binbuf from a message, making the opposite changes | ||
1562 | from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */ | ||
1563 | |||
1564 | void binbuf_restore(t_binbuf *x, int argc, t_atom *argv) | ||
1565 | { | ||
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 | ||
1572 | { | ||
1573 | error("binbuf_addmessage: out of space"); | ||
1574 | return; | ||
1575 | } | ||
1576 | |||
1577 | for (ap = x->b_vec + x->b_n, i = argc; i--; ap++) | ||
1578 | { | ||
1579 | if (argv->a_type == A_SYMBOL) | ||
1580 | { | ||
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') | ||
1585 | { | ||
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 | ||
1594 | { | ||
1595 | int dollar = 0; | ||
1596 | sscanf(argv->a_w.w_symbol->s_name + 1, "%d", &dollar); | ||
1597 | SETDOLLAR(ap, dollar); | ||
1598 | } | ||
1599 | } | ||
1600 | else *ap = *argv; | ||
1601 | argv++; | ||
1602 | } | ||
1603 | else *ap = *(argv++); | ||
1604 | } | ||
1605 | x->b_n = newsize; | ||
1606 | } | ||
1607 | |||
1608 | |||
1609 | #define MSTACKSIZE 2048 | ||
1610 | |||
1611 | void binbuf_print(t_binbuf *x) | ||
1612 | { | ||
1613 | int i, startedpost = 0, newline = 1; | ||
1614 | for (i = 0; i < x->b_n; i++) | ||
1615 | { | ||
1616 | if (newline) | ||
1617 | { | ||
1618 | if (startedpost) endpost(); | ||
1619 | startpost(""); | ||
1620 | startedpost = 1; | ||
1621 | } | ||
1622 | postatom(1, x->b_vec + i); | ||
1623 | if (x->b_vec[i].a_type == A_SEMI) | ||
1624 | newline = 1; | ||
1625 | else newline = 0; | ||
1626 | } | ||
1627 | if (startedpost) endpost(); | ||
1628 | } | ||
1629 | |||
1630 | int binbuf_getnatom(t_binbuf *x) | ||
1631 | { | ||
1632 | return (x->b_n); | ||
1633 | } | ||
1634 | |||
1635 | t_atom *binbuf_getvec(t_binbuf *x) | ||
1636 | { | ||
1637 | return (x->b_vec); | ||
1638 | } | ||
1639 | |||
1640 | int canvas_getdollarzero( void); | ||
1641 | |||
1642 | t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew) | ||
1643 | { | ||
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) | ||
1649 | { | ||
1650 | if (!tonew) | ||
1651 | return (0); | ||
1652 | else sprintf(buf, "$%d", argno); | ||
1653 | } | ||
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)); | ||
1660 | } | ||
1661 | |||
1662 | void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) | ||
1663 | { | ||
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) | ||
1670 | { | ||
1671 | t_pd *nexttarget; | ||
1672 | /* get a target. */ | ||
1673 | while (!target) | ||
1674 | { | ||
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) | ||
1680 | { | ||
1681 | if (at->a_w.w_index <= 0 || at->a_w.w_index > argc) | ||
1682 | { | ||
1683 | error("$%d: not enough arguments supplied", | ||
1684 | at->a_w.w_index); | ||
1685 | goto cleanup; | ||
1686 | } | ||
1687 | else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL) | ||
1688 | { | ||
1689 | error("$%d: symbol needed as message destination", | ||
1690 | at->a_w.w_index); | ||
1691 | goto cleanup; | ||
1692 | } | ||
1693 | else s = argv[at->a_w.w_index-1].a_w.w_symbol; | ||
1694 | } | ||
1695 | else if (at->a_type == A_DOLLSYM) | ||
1696 | { | ||
1697 | if (!(s = binbuf_realizedollsym(at->a_w.w_symbol, | ||
1698 | argc, argv, 0))) | ||
1699 | { | ||
1700 | error("$%s: not enough arguments supplied", | ||
1701 | at->a_w.w_symbol->s_name); | ||
1702 | goto cleanup; | ||
1703 | } | ||
1704 | } | ||
1705 | else s = atom_getsymbol(at); | ||
1706 | if (!(target = s->s_thing)) | ||
1707 | { | ||
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; | ||
1714 | } | ||
1715 | else | ||
1716 | { | ||
1717 | at++, ac--; | ||
1718 | break; | ||
1719 | } | ||
1720 | } | ||
1721 | if (!ac) break; | ||
1722 | nargs = 0; | ||
1723 | nexttarget = target; | ||
1724 | while (1) | ||
1725 | { | ||
1726 | t_symbol *s9; | ||
1727 | if (!ac) goto gotmess; | ||
1728 | if (msp >= ems) | ||
1729 | { | ||
1730 | error("message stack overflow"); | ||
1731 | goto broken; | ||
1732 | } | ||
1733 | switch (at->a_type) | ||
1734 | { | ||
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) | ||
1739 | { | ||
1740 | SETSYMBOL(msp, gensym(";")); | ||
1741 | break; | ||
1742 | } | ||
1743 | else | ||
1744 | { | ||
1745 | nexttarget = 0; | ||
1746 | goto gotmess; | ||
1747 | } | ||
1748 | case A_COMMA: | ||
1749 | if (target == &pd_objectmaker) | ||
1750 | { | ||
1751 | SETSYMBOL(msp, gensym(",")); | ||
1752 | break; | ||
1753 | } | ||
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 | ||
1765 | { | ||
1766 | if (target == &pd_objectmaker) | ||
1767 | SETFLOAT(msp, 0); | ||
1768 | else | ||
1769 | { | ||
1770 | error("$%d: argument number out of range", | ||
1771 | at->a_w.w_index); | ||
1772 | SETFLOAT(msp, 0); | ||
1773 | } | ||
1774 | } | ||
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; | ||
1786 | } | ||
1787 | msp++; | ||
1788 | ac--; | ||
1789 | at++; | ||
1790 | nargs++; | ||
1791 | } | ||
1792 | gotmess: | ||
1793 | if (nargs) | ||
1794 | { | ||
1795 | switch (stackwas->a_type) | ||
1796 | { | ||
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; | ||
1804 | } | ||
1805 | } | ||
1806 | msp = stackwas; | ||
1807 | if (!ac) break; | ||
1808 | target = nexttarget; | ||
1809 | at++; | ||
1810 | ac--; | ||
1811 | } | ||
1812 | |||
1813 | return; | ||
1814 | broken: | ||
1815 | msp = stackwas; | ||
1816 | } | ||
1817 | |||
1818 | static int binbuf_doopen(char *s, int mode) | ||
1819 | { | ||
1820 | char namebuf[MAXPDSTRING]; | ||
1821 | #ifdef MSW | ||
1822 | mode |= O_BINARY; | ||
1823 | #endif | ||
1824 | sys_bashfilename(s, namebuf); | ||
1825 | return (open(namebuf, mode)); | ||
1826 | } | ||
1827 | |||
1828 | static FILE *binbuf_dofopen(char *s, char *mode) | ||
1829 | { | ||
1830 | char namebuf[MAXPDSTRING]; | ||
1831 | sys_bashfilename(s, namebuf); | ||
1832 | return (fopen(namebuf, mode)); | ||
1833 | } | ||
1834 | |||
1835 | int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag) | ||
1836 | { | ||
1837 | long length; | ||
1838 | int fd; | ||
1839 | int readret; | ||
1840 | char *buf; | ||
1841 | char namebuf[MAXPDSTRING]; | ||
1842 | |||
1843 | namebuf[0] = 0; | ||
1844 | if (*dirname) | ||
1845 | strcat(namebuf, dirname), strcat(namebuf, "/"); | ||
1846 | strcat(namebuf, filename); | ||
1847 | |||
1848 | if ((fd = binbuf_doopen(namebuf, 0)) < 0) | ||
1849 | { | ||
1850 | fprintf(stderr, "open: "); | ||
1851 | perror(namebuf); | ||
1852 | return (1); | ||
1853 | } | ||
1854 | if ((length = lseek(fd, 0, SEEK_END)) < 0 || lseek(fd, 0, SEEK_SET) < 0 | ||
1855 | || !(buf = t_getbytes(length))) | ||
1856 | { | ||
1857 | fprintf(stderr, "lseek: "); | ||
1858 | perror(namebuf); | ||
1859 | close(fd); | ||
1860 | return(1); | ||
1861 | } | ||
1862 | if ((readret = read(fd, buf, length)) < length) | ||
1863 | { | ||
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); | ||
1869 | } | ||
1870 | /* optionally map carriage return to semicolon */ | ||
1871 | if (crflag) | ||
1872 | { | ||
1873 | int i; | ||
1874 | for (i = 0; i < length; i++) | ||
1875 | if (buf[i] == '\n') | ||
1876 | buf[i] = ';'; | ||
1877 | } | ||
1878 | binbuf_text(b, buf, length); | ||
1879 | |||
1880 | #if 0 | ||
1881 | startpost("binbuf_read "); postatom(b->b_n, b->b_vec); endpost(); | ||
1882 | #endif | ||
1883 | |||
1884 | t_freebytes(buf, length); | ||
1885 | close(fd); | ||
1886 | return (0); | ||
1887 | } | ||
1888 | |||
1889 | int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname, | ||
1890 | int crflag) | ||
1891 | { | ||
1892 | int filedesc; | ||
1893 | char buf[MAXPDSTRING], *bufptr; | ||
1894 | if ((filedesc = open_via_path( | ||
1895 | dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0) | ||
1896 | { | ||
1897 | error("%s: can't open", filename); | ||
1898 | return (1); | ||
1899 | } | ||
1900 | else close (filedesc); | ||
1901 | if (binbuf_read(b, bufptr, buf, crflag)) | ||
1902 | return (1); | ||
1903 | else return (0); | ||
1904 | } | ||
1905 | |||
1906 | #define WBUFSIZE 4096 | ||
1907 | static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd); | ||
1908 | |||
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) | ||
1912 | { | ||
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; | ||
1918 | |||
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")) | ||
1924 | { | ||
1925 | x = binbuf_convert(x, 0); | ||
1926 | deleteit = 1; | ||
1927 | } | ||
1928 | |||
1929 | if (!(f = binbuf_dofopen(fbuf, "w"))) | ||
1930 | { | ||
1931 | fprintf(stderr, "open: "); | ||
1932 | sys_unixerror(fbuf); | ||
1933 | goto fail; | ||
1934 | } | ||
1935 | for (ap = x->b_vec, indx = x->b_n; indx--; ap++) | ||
1936 | { | ||
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) | ||
1944 | { | ||
1945 | if (fwrite(sbuf, bp-sbuf, 1, f) < 1) | ||
1946 | { | ||
1947 | sys_unixerror(fbuf); | ||
1948 | goto fail; | ||
1949 | } | ||
1950 | bp = sbuf; | ||
1951 | } | ||
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) | ||
1955 | { | ||
1956 | atom_string(ap, bp, (ep-bp)-2); | ||
1957 | length = strlen(bp); | ||
1958 | bp += length; | ||
1959 | ncolumn += length; | ||
1960 | } | ||
1961 | if (ap->a_type == A_SEMI || (!crflag && ncolumn > 65)) | ||
1962 | { | ||
1963 | *bp++ = '\n'; | ||
1964 | ncolumn = 0; | ||
1965 | } | ||
1966 | else | ||
1967 | { | ||
1968 | *bp++ = ' '; | ||
1969 | ncolumn++; | ||
1970 | } | ||
1971 | } | ||
1972 | if (fwrite(sbuf, bp-sbuf, 1, f) < 1) | ||
1973 | { | ||
1974 | sys_unixerror(fbuf); | ||
1975 | goto fail; | ||
1976 | } | ||
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); | ||
1987 | } | ||
1988 | |||
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! */ | ||
1993 | |||
1994 | #define MAXSTACK 1000 | ||
1995 | |||
1996 | #define ISSYMBOL(a, b) ((a)->a_type == A_SYMBOL && \ | ||
1997 | !strcmp((a)->a_w.w_symbol->s_name, (b))) | ||
1998 | |||
1999 | static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd) | ||
2000 | { | ||
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; ) | ||
2009 | { | ||
2010 | int endmess, natom; | ||
2011 | char *first, *second; | ||
2012 | for (endmess = nextindex; endmess < n && vec[endmess].a_type != A_SEMI; | ||
2013 | endmess++) | ||
2014 | ; | ||
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) | ||
2019 | { | ||
2020 | nextindex = endmess + 1; | ||
2021 | continue; | ||
2022 | } | ||
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) | ||
2029 | { | ||
2030 | /* case 1: importing a ".pat" file into Pd. */ | ||
2031 | |||
2032 | /* dollar signs in file translate to symbols */ | ||
2033 | for (i = 0; i < natom; i++) | ||
2034 | { | ||
2035 | if (nextmess[i].a_type == A_DOLLAR) | ||
2036 | { | ||
2037 | char buf[100]; | ||
2038 | sprintf(buf, "$%d", nextmess[i].a_w.w_index); | ||
2039 | SETSYMBOL(nextmess+i, gensym(buf)); | ||
2040 | } | ||
2041 | else if (nextmess[i].a_type == A_DOLLSYM) | ||
2042 | { | ||
2043 | char buf[100]; | ||
2044 | sprintf(buf, "$%s", nextmess[i].a_w.w_symbol->s_name); | ||
2045 | SETSYMBOL(nextmess+i, gensym(buf)); | ||
2046 | } | ||
2047 | } | ||
2048 | if (!strcmp(first, "#N")) | ||
2049 | { | ||
2050 | if (!strcmp(second, "vpatcher")) | ||
2051 | { | ||
2052 | if (stackdepth >= MAXSTACK) | ||
2053 | { | ||
2054 | post("too many embedded patches"); | ||
2055 | return (newb); | ||
2056 | } | ||
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); | ||
2069 | } | ||
2070 | } | ||
2071 | if (!strcmp(first, "#P")) | ||
2072 | { | ||
2073 | /* drop initial "hidden" flag */ | ||
2074 | if (!strcmp(second, "hidden")) | ||
2075 | { | ||
2076 | nextmess++; | ||
2077 | natom--; | ||
2078 | second = (nextmess+1)->a_w.w_symbol->s_name; | ||
2079 | } | ||
2080 | if (natom >= 7 && !strcmp(second, "newobj") | ||
2081 | && (ISSYMBOL(&nextmess[6], "patcher") || | ||
2082 | ISSYMBOL(&nextmess[6], "p"))) | ||
2083 | { | ||
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++; | ||
2092 | } | ||
2093 | else if (!strcmp(second, "newex") || !strcmp(second, "newobj")) | ||
2094 | { | ||
2095 | t_symbol *classname = | ||
2096 | atom_getsymbolarg(6, natom, nextmess); | ||
2097 | if (classname == gensym("trigger") || | ||
2098 | classname == gensym("t")) | ||
2099 | { | ||
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"); | ||
2104 | } | ||
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++; | ||
2117 | } | ||
2118 | else if (!strcmp(second, "message") || | ||
2119 | !strcmp(second, "comment")) | ||
2120 | { | ||
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++; | ||
2131 | } | ||
2132 | else if (!strcmp(second, "button")) | ||
2133 | { | ||
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++; | ||
2140 | } | ||
2141 | else if (!strcmp(second, "number") || !strcmp(second, "flonum")) | ||
2142 | { | ||
2143 | binbuf_addv(newb, "ssff;", | ||
2144 | gensym("#X"), gensym("floatatom"), | ||
2145 | atom_getfloatarg(2, natom, nextmess), | ||
2146 | atom_getfloatarg(3, natom, nextmess)); | ||
2147 | nobj++; | ||
2148 | } | ||
2149 | else if (!strcmp(second, "slider")) | ||
2150 | { | ||
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++; | ||
2168 | } | ||
2169 | else if (!strcmp(second, "toggle")) | ||
2170 | { | ||
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++; | ||
2177 | } | ||
2178 | else if (!strcmp(second, "inlet")) | ||
2179 | { | ||
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++; | ||
2186 | } | ||
2187 | else if (!strcmp(second, "outlet")) | ||
2188 | { | ||
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++; | ||
2195 | } | ||
2196 | else if (!strcmp(second, "user")) | ||
2197 | { | ||
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++; | ||
2204 | } | ||
2205 | else if (!strcmp(second, "connect")|| | ||
2206 | !strcmp(second, "fasten")) | ||
2207 | { | ||
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)); | ||
2214 | } | ||
2215 | } | ||
2216 | } | ||
2217 | else /* Pd to Max */ | ||
2218 | { | ||
2219 | if (!strcmp(first, "#N")) | ||
2220 | { | ||
2221 | if (!strcmp(second, "canvas")) | ||
2222 | { | ||
2223 | if (stackdepth >= MAXSTACK) | ||
2224 | { | ||
2225 | post("too many embedded patches"); | ||
2226 | return (newb); | ||
2227 | } | ||
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)); | ||
2237 | } | ||
2238 | } | ||
2239 | if (!strcmp(first, "#X")) | ||
2240 | { | ||
2241 | if (natom >= 5 && !strcmp(second, "restore") | ||
2242 | && (ISSYMBOL (&nextmess[4], "pd"))) | ||
2243 | { | ||
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++; | ||
2254 | } | ||
2255 | else if (!strcmp(second, "obj")) | ||
2256 | { | ||
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 | ||
2308 | { | ||
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); | ||
2319 | } | ||
2320 | nobj++; | ||
2321 | |||
2322 | } | ||
2323 | else if (!strcmp(second, "msg") || | ||
2324 | !strcmp(second, "text")) | ||
2325 | { | ||
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++; | ||
2338 | } | ||
2339 | else if (!strcmp(second, "floatatom")) | ||
2340 | { | ||
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++; | ||
2346 | } | ||
2347 | else if (!strcmp(second, "connect")) | ||
2348 | { | ||
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)); | ||
2355 | } | ||
2356 | } | ||
2357 | } | ||
2358 | nextindex = endmess + 1; | ||
2359 | } | ||
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); | ||
2366 | } | ||
2367 | |||
2368 | /* function to support searching */ | ||
2369 | int binbuf_match(t_binbuf *inbuf, t_binbuf *searchbuf) | ||
2370 | { | ||
2371 | int indexin, nmatched; | ||
2372 | for (indexin = 0; indexin <= inbuf->b_n - searchbuf->b_n; indexin++) | ||
2373 | { | ||
2374 | for (nmatched = 0; nmatched < searchbuf->b_n; nmatched++) | ||
2375 | { | ||
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 | ||
2380 | || | ||
2381 | a1->a_type == A_FLOAT && a1->a_w.w_float != a2->a_w.w_float | ||
2382 | || | ||
2383 | a1->a_type == A_DOLLAR && a1->a_w.w_index != a2->a_w.w_index | ||
2384 | || | ||
2385 | a1->a_type == A_DOLLSYM && a1->a_w.w_symbol != a2->a_w.w_symbol) | ||
2386 | goto nomatch; | ||
2387 | } | ||
2388 | return (1); | ||
2389 | nomatch: ; | ||
2390 | } | ||
2391 | return (0); | ||
2392 | } | ||
2393 | |||
2394 | void pd_doloadbang(void); | ||
2395 | |||
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) | ||
2399 | { | ||
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)) | ||
2406 | { | ||
2407 | perror(name->s_name); | ||
2408 | } | ||
2409 | else | ||
2410 | { | ||
2411 | if (import) | ||
2412 | { | ||
2413 | t_binbuf *newb = binbuf_convert(b, 1); | ||
2414 | binbuf_free(b); | ||
2415 | b = newb; | ||
2416 | } | ||
2417 | binbuf_eval(b, 0, 0, 0); | ||
2418 | } | ||
2419 | glob_setfilename(0, &s_, &s_); /* bug fix by Krzysztof Czaja */ | ||
2420 | binbuf_free(b); | ||
2421 | canvas_resume_dsp(dspstate); | ||
2422 | } | ||
2423 | |||
2424 | void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir) | ||
2425 | { | ||
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. */ | ||
2431 | |||
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); | ||
2438 | } | ||