summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/m_binbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/m_binbuf.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/m_binbuf.c1218
1 files changed, 0 insertions, 1218 deletions
diff --git a/apps/plugins/pdbox/PDa/src/m_binbuf.c b/apps/plugins/pdbox/PDa/src/m_binbuf.c
index c215e399e6..03a560db7b 100644
--- a/apps/plugins/pdbox/PDa/src/m_binbuf.c
+++ b/apps/plugins/pdbox/PDa/src/m_binbuf.c
@@ -1217,1222 +1217,4 @@ void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
1217 pd_doloadbang(); 1217 pd_doloadbang();
1218 canvas_resume_dsp(dspstate); 1218 canvas_resume_dsp(dspstate);
1219} 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
1246struct _binbuf
1247{
1248 int b_n;
1249 t_atom *b_vec;
1250};
1251
1252t_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
1260void 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
1266t_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
1275void 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 */
1282void 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. */
1417void 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
1452writing to file doesn't buffer everything together. */
1453
1454void 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
1477void 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 }
1504done:
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
1510symbols ";", "'",; the symbol ";" goes to "\;", etc. */
1511
1512void 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
1554void 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
1562from binbuf_addbinbuf. The symbol ";" goes to a semicolon, etc. */
1563
1564void 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
1611void 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
1630int binbuf_getnatom(t_binbuf *x)
1631{
1632 return (x->b_n);
1633}
1634
1635t_atom *binbuf_getvec(t_binbuf *x)
1636{
1637 return (x->b_vec);
1638}
1639
1640int canvas_getdollarzero( void);
1641
1642t_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
1662void 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;
1814broken:
1815 msp = stackwas;
1816}
1817
1818static 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
1828static FILE *binbuf_dofopen(char *s, char *mode)
1829{
1830 char namebuf[MAXPDSTRING];
1831 sys_bashfilename(s, namebuf);
1832 return (fopen(namebuf, mode));
1833}
1834 1220
1835int 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
1889int 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
1907static 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. */
1911int 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);
1981fail:
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
1990max to pd direction is working OK but you will need to make lots of
1991abstractions for objects like "gate" which don't exist in Pd. conversion
1992from 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
1999static 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 */
2369int 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
2394void pd_doloadbang(void);
2395
2396/* LATER make this evaluate the file on-the-fly. */
2397/* LATER figure out how to log errors */
2398void 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
2424void 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}