[SCM] calf/master: + Big Bull: rewrite TTL scanner in a proper programming language ; ) to improve compatibility (now depends on flex instead of python.yappy)

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:37:32 UTC 2013


The following commit has been merged in the master branch:
commit 6a5e6b9ce67357e8ff9b491a7e58b4e837d9ac69
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Sun Aug 31 19:47:45 2008 +0000

    + Big Bull: rewrite TTL scanner in a proper programming language ;) to improve compatibility (now depends on flex instead of python.yappy)
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@273 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/bigbull/Makefile b/bigbull/Makefile
new file mode 100644
index 0000000..8187b50
--- /dev/null
+++ b/bigbull/Makefile
@@ -0,0 +1,8 @@
+all: calfpytools.cpp ttl.cpp Makefile setup.py ttldata.h
+	python setup.py build
+
+ttl.cpp: ttl.l Makefile ttldata.h
+	flex --batch --nodefault --c++ -o ttl.cpp --header-file=ttl.h ttl.l
+
+install:
+	python setup.py install
diff --git a/bigbull/calfpytools.cpp b/bigbull/calfpytools.cpp
index bde0f72..b13ecb3 100644
--- a/bigbull/calfpytools.cpp
+++ b/bigbull/calfpytools.cpp
@@ -1,12 +1,22 @@
 #include "Python.h"
+#include "ttl.h"
+#include "ttldata.h"
+#include <map>
+#include <iostream>
+#include <fstream>
 #include <jack/jack.h>
 
 //////////////////////////////////////////////////// PyJackClient
 
+struct PyJackPort;
+
+typedef std::map<jack_port_t *, PyJackPort *> PortHandleMap;
+
 struct PyJackClient
 {
     PyObject_HEAD
     jack_client_t *client;
+    PortHandleMap *port_handle_map;
 };
 
 static PyTypeObject jackclient_type = {
@@ -40,10 +50,22 @@ static PyObject *jackclient_open(PyJackClient *self, PyObject *args)
         return NULL;
     
     self->client = jack_client_open(name, (jack_options_t)options, &status);
+    self->port_handle_map = new PortHandleMap;
     
     return Py_BuildValue("i", status);
 }
 
+static int jackclient_dealloc(PyJackPort *self)
+{
+    if (self->client)
+    {
+        PyObject_CallMethod((PyObject *)self, strdup("close"), NULL);
+        assert(!self->client);
+    }
+    
+    return 0;
+}
+
 #define CHECK_CLIENT if (!self->client) { PyErr_SetString(PyExc_ValueError, "Client not opened"); return NULL; }
 
 
@@ -59,12 +81,19 @@ static PyObject *jackclient_get_name(PyJackClient *self, PyObject *args)
 
 static PyObject *create_jack_port(PyJackClient *client, jack_port_t *port)
 {
+    PortHandleMap::iterator it = client->port_handle_map->find(port);
+    if (it != client->port_handle_map->end())
+    {
+        Py_INCREF(it->second);
+        return Py_BuildValue("O", it->second);
+    }
     if (port)
     {
         PyObject *cobj = PyCObject_FromVoidPtr(port, NULL);
         PyObject *args = Py_BuildValue("OO", client, cobj);
         PyObject *newobj = _PyObject_New(&jackport_type);
         jackport_type.tp_init(newobj, args, NULL);
+        (*client->port_handle_map)[port] = (PyJackPort *)newobj;
         Py_DECREF(args);
         return newobj; 
     }
@@ -97,6 +126,16 @@ static PyObject *jackclient_get_port(PyJackClient *self, PyObject *args)
     return create_jack_port(self, port);
 }
 
+static PyObject *jackclient_get_cobj(PyJackClient *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, ":get_cobj"))
+        return NULL;
+    
+    CHECK_CLIENT
+    
+    return PyCObject_FromVoidPtr((void *)self->client, NULL);
+}
+
 static PyObject *jackclient_close(PyJackClient *self, PyObject *args)
 {
     if (!PyArg_ParseTuple(args, ":close"))
@@ -117,6 +156,7 @@ static PyMethodDef jackclient_methods[] = {
     {"get_name", (PyCFunction)jackclient_get_name, METH_VARARGS, "Retrieve client name"},
     {"get_port", (PyCFunction)jackclient_get_port, METH_VARARGS, "Create port object from name of existing JACK port"},
     {"register_port", (PyCFunction)jackclient_register_port, METH_VARARGS, "Register a new port and return an object that represents it"},
+    {"get_cobj", (PyCFunction)jackclient_get_cobj, METH_VARARGS, "Retrieve jack_client_t pointer for the client"},
     {NULL, NULL, 0, NULL}
 };
 
@@ -142,6 +182,17 @@ static int jackport_init(PyJackPort *self, PyObject *args, PyObject *kwds)
     return 0;
 }
 
+static int jackport_dealloc(PyJackPort *self)
+{
+    // if not unregistered, decref (unregister decrefs automatically)
+    if (self->client) {
+        self->client->port_handle_map->erase(self->port);
+        Py_DECREF(self->client);
+    }
+    
+    return 0;
+}
+
 #define CHECK_PORT_CLIENT if (!self->client || !self->client->client) { PyErr_SetString(PyExc_ValueError, "Client not opened"); return NULL; }
 #define CHECK_PORT if (!self->port) { PyErr_SetString(PyExc_ValueError, "The port is not valid"); return NULL; }
 
@@ -186,6 +237,17 @@ static PyObject *jackport_get_name(PyJackPort *self, PyObject *args)
     return Py_BuildValue("s", jack_port_short_name(self->port));
 }
 
+static PyObject *jackport_get_cobj(PyJackPort *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, ":get_cobj"))
+        return NULL;
+    
+    CHECK_PORT_CLIENT
+    CHECK_PORT
+    
+    return PyCObject_FromVoidPtr((void *)self->port, NULL);
+}
+
 static PyObject *jackport_get_aliases(PyJackPort *self, PyObject *args)
 {
     if (!PyArg_ParseTuple(args, ":get_aliases"))
@@ -205,6 +267,26 @@ static PyObject *jackport_get_aliases(PyJackPort *self, PyObject *args)
     return Py_BuildValue("[ss]", aliases[0], aliases[1]);
 }
 
+static PyObject *jackport_get_connections(PyJackPort *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, ":get_aliases"))
+        return NULL;
+
+    CHECK_PORT_CLIENT
+    CHECK_PORT
+    
+    const char **conns = jack_port_get_all_connections(self->client->client, self->port);
+    
+    PyObject *res = PyList_New(0);
+    if (conns)
+    {
+        for (const char **p = conns; *p; p++)
+            PyList_Append(res, PyString_FromString(*p));
+    }
+    
+    return res;
+}
+
 static PyObject *jackport_set_name(PyJackPort *self, PyObject *args)
 {
     const char *name;
@@ -227,11 +309,13 @@ static PyObject *jackport_unregister(PyJackPort *self, PyObject *args)
     
     PyJackClient *client = self->client;
     
+    client->port_handle_map->erase(self->port);
     jack_port_unregister(self->client->client, self->port);
     self->port = NULL;
     self->client = NULL;
     
     Py_DECREF(client);
+    client = NULL;
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -243,22 +327,45 @@ static PyMethodDef jackport_methods[] = {
     {"get_full_name", (PyCFunction)jackport_get_full_name, METH_VARARGS, "Retrieve full port name (including client name)"},
     {"get_name", (PyCFunction)jackport_get_name, METH_VARARGS, "Retrieve short port name (without client name)"},
     {"set_name", (PyCFunction)jackport_set_name, METH_VARARGS, "Set short port name"},
-    {"get_aliases", (PyCFunction)jackport_get_aliases, METH_VARARGS, "Retrieve two port aliases"},
+    {"get_aliases", (PyCFunction)jackport_get_aliases, METH_VARARGS, "Retrieve a list of port aliases"},
+    {"get_connections", (PyCFunction)jackport_get_connections, METH_VARARGS, "Retrieve a list of ports the port is connected to"},
+    {"get_cobj", (PyCFunction)jackport_get_cobj, METH_VARARGS, "Retrieve jack_port_t pointer for the port"},
     {NULL, NULL, 0, NULL}
 };
 
 
 //////////////////////////////////////////////////// calfpytools
 
-/*
-static PyObject *calfpytools_test(PyObject *self, PyObject *args)
+static PyObject *calfpytools_scan_ttl_file(PyObject *self, PyObject *args)
 {
-    return Py_BuildValue("i", 42);
+    char *ttl_name = NULL;
+    if (!PyArg_ParseTuple(args, "s:scan_ttl_file", &ttl_name))
+        return NULL;
+    
+    std::filebuf fb;
+    fb.open(ttl_name, std::ios::in);
+    std::istream istr(&fb);
+    TTLLexer lexer(&istr);
+    lexer.yylex();
+    return lexer.grab();
+}
+
+static PyObject *calfpytools_scan_ttl_string(PyObject *self, PyObject *args)
+{
+    char *data = NULL;
+    if (!PyArg_ParseTuple(args, "s:scan_ttl_string", &data))
+        return NULL;
+    
+    std::string data_str = data;
+    std::stringstream str(data_str);
+    TTLLexer lexer(&str);
+    lexer.yylex();
+    return lexer.grab();
 }
-*/
 
 static PyMethodDef module_methods[] = {
-//    {"test", calfpytools_test, METH_VARARGS, "Do nothing, return 42"},
+    {"scan_ttl_file", calfpytools_scan_ttl_file, METH_VARARGS, "Scan a TTL file, return a list of token tuples"},
+    {"scan_ttl_string", calfpytools_scan_ttl_string, METH_VARARGS, "Scan a TTL string, return a list of token tuples"},
     {NULL, NULL, 0, NULL}
 };
 
@@ -268,6 +375,7 @@ PyMODINIT_FUNC initcalfpytools()
     jackclient_type.tp_flags = Py_TPFLAGS_DEFAULT;
     jackclient_type.tp_doc = "JACK client object";
     jackclient_type.tp_methods = jackclient_methods;
+    jackclient_type.tp_dealloc = (destructor)jackclient_dealloc;
     if (PyType_Ready(&jackclient_type) < 0)
         return;
 
@@ -276,6 +384,7 @@ PyMODINIT_FUNC initcalfpytools()
     jackport_type.tp_doc = "JACK port object (created by client)";
     jackport_type.tp_methods = jackport_methods;
     jackport_type.tp_init = (initproc)jackport_init;
+    jackport_type.tp_dealloc = (destructor)jackport_dealloc;
     if (PyType_Ready(&jackport_type) < 0)
         return;
     
diff --git a/bigbull/fakeserv.py b/bigbull/fakeserv.py
index f6e9d7f..04c807d 100644
--- a/bigbull/fakeserv.py
+++ b/bigbull/fakeserv.py
@@ -2,7 +2,6 @@ import re
 import os
 import sys
 import glob
-import yappy.parser
 
 lv2 = "http://lv2plug.in/ns/lv2core#"
 lv2evt = "http://lv2plug.in/ns/ext/event#"
@@ -95,87 +94,6 @@ class SimpleRDFModel:
             for p in self.bySubject[s].keys():
                 print "%s %s %s" % (s, p, self.bySubject[s][p])
 
-def parseTTL(uri, content, model):
-    # Missing stuff: translated literals, blank nodes
-    print "Parsing: %s" % uri
-    prefixes = {}
-    lexer = yappy.parser.Lexer([
-        (r"(?m)^\s*#[^\n]*", ""),
-        ('"""(\n|\r|.)*?"""', lambda x : ("string", x[3:-3])),
-        (r'"([^"\\]|\\.)+"', lambda x : ("string", x[1:-1])),
-        (r"<>", lambda x : ("URI", uri)),
-        (r"<[^>]*>", lambda x : ("URI", x[1:-1])),
-        ("[-a-zA-Z0-9_]*:[-a-zA-Z0-9_]*", lambda x : ("prnot", x)),
-        ("@prefix", lambda x : ("prefix", x)),
-        (r"-?[0-9]+\.[0-9]+", lambda x : ("number", float(x))),
-        (r"-?[0-9]+", lambda x : ("number", int(x))),
-        ("[a-zA-Z0-9_]+", lambda x : ("symbol", x)),
-        (r"[()\[\];.,]", lambda x : (x, x)),
-        ("\s+", ""),
-    ])
-    spo_stack = []
-    spo = ["", "", ""]
-    item = 0
-    anoncnt = 1
-    for x in lexer.scan(content):
-        if x[0] == '':
-            continue
-        if x[0] == 'prefix':
-            spo[0] = "@prefix"
-            item = 1
-            continue
-        elif (x[0] == '.' and spo_stack == []) or x[0] == ';' or x[0] == ',':
-            if item == 3:
-                if spo[0] == "@prefix":
-                    prefixes[spo[1][:-1]] = spo[2]
-                else:
-                    model.addTriple(spo[0], spo[1], spo[2])
-                if x[0] == '.': item = 0
-                elif x[0] == ';': item = 1
-                elif x[0] == ',': item = 2
-            else:
-                raise Exception, uri+": Unexpected " + x[0]
-        elif x[0] == "prnot" and item < 3:
-            prnot = x[1].split(":")
-            if item != 0 and spo[0] == "@prefix":
-                spo[item] = x[1]
-            else:
-                spo[item] = prefixes[prnot[0]] + prnot[1]
-            item += 1
-        elif (x[0] == 'URI' or x[0] == "string" or x[0] == "number" or (x[0] == "symbol" and x[1] == "a" and item == 1)) and (item < 3):
-            if x[0] == "URI" and x[1].find(":") == -1 and x[1][0] != "/":
-                # This is quite silly
-                x = ("URI", os.path.dirname(uri) + "/" + x[1])
-            spo[item] = x[1]
-            item += 1
-        elif x[0] == '[':
-            if item != 2:
-                raise Exception, "Incorrect use of ["
-            uri2 = uri + "$anon$" + str(anoncnt)
-            spo[2] = uri2
-            spo_stack.append(spo)
-            spo = [uri2, "", ""]
-            item = 1
-            anoncnt += 1
-        elif x[0] == ']' or x[0] == ')':
-            if item == 3:
-                model.addTriple(spo[0], spo[1], spo[2])
-                item = 0
-            spo = spo_stack[-1]
-            spo_stack = spo_stack[:-1]
-            item = 3
-        elif x[0] == '(':
-            if item != 2:
-                raise Exception, "Incorrect use of ("
-            uri2 = uri + "$anon$" + str(anoncnt)
-            spo[2] = uri2
-            spo_stack.append(spo)
-            spo = [uri2, "", ""]
-            item = 2
-            anoncnt += 1
-        else:
-            print uri + ": Unexpected: " + repr(x)
-
 class FakeServer(object):
     def __init__(self):
         pass
diff --git a/bigbull/lv2.py b/bigbull/lv2.py
index b8b1733..34d4bb6 100644
--- a/bigbull/lv2.py
+++ b/bigbull/lv2.py
@@ -2,7 +2,7 @@ import re
 import os
 import sys
 import glob
-import yappy.parser
+import calfpytools
 
 lv2 = "http://lv2plug.in/ns/lv2core#"
 lv2evt = "http://lv2plug.in/ns/ext/event#"
@@ -100,25 +100,11 @@ def parseTTL(uri, content, model, debug):
     if debug:
         print "Parsing: %s" % uri
     prefixes = {}
-    lexer = yappy.parser.Lexer([
-        (r"(?m)^\s*#[^\n]*", ""),
-        ('"""(\n|\r|.)*?"""', lambda x : ("string", x[3:-3])),
-        (r'"([^"\\]|\\.)+"', lambda x : ("string", x[1:-1])),
-        (r"<>", lambda x : ("URI", uri)),
-        (r"<[^>]*>", lambda x : ("URI", x[1:-1])),
-        ("[-a-zA-Z0-9_]*:[-a-zA-Z0-9_]*", lambda x : ("prnot", x)),
-        ("@prefix", lambda x : ("prefix", x)),
-        (r"-?[0-9]+\.[0-9]+", lambda x : ("number", float(x))),
-        (r"-?[0-9]+", lambda x : ("number", int(x))),
-        ("[a-zA-Z0-9_]+", lambda x : ("symbol", x)),
-        (r"[()\[\];.,]", lambda x : (x, x)),
-        ("\s+", ""),
-    ])
     spo_stack = []
     spo = ["", "", ""]
     item = 0
     anoncnt = 1
-    for x in lexer.scan(content):
+    for x in calfpytools.scan_ttl_string(content):
         if x[0] == '':
             continue
         if x[0] == 'prefix':
@@ -135,10 +121,10 @@ def parseTTL(uri, content, model, debug):
                 elif x[0] == ';': item = 1
                 elif x[0] == ',': item = 2
             else:
-                # Kludge for swh's plugins
-                if x[0] != '.' and x[0] != ',':
+                if x[0] == '.':
+                    item = 0
+                elif item != 0:
                     raise Exception, uri+": Unexpected " + x[0]
-                item = 0
         elif x[0] == "prnot" and item < 3:
             prnot = x[1].split(":")
             if item != 0 and spo[0] == "@prefix":
@@ -149,7 +135,9 @@ def parseTTL(uri, content, model, debug):
                 spo[item] = prefixes[prnot[0]] + prnot[1]
             item += 1
         elif (x[0] == 'URI' or x[0] == "string" or x[0] == "number" or (x[0] == "symbol" and x[1] == "a" and item == 1)) and (item < 3):
-            if x[0] == "URI" and x[1].find(":") == -1 and x[1][0] != "/":
+            if x[0] == "URI" and x[1] == "":
+                x = ("URI", uri)
+            elif x[0] == "URI" and x[1].find(":") == -1 and x[1] != "" and x[1][0] != "/":
                 # This is quite silly
                 x = ("URI", os.path.dirname(uri) + "/" + x[1])
             spo[item] = x[1]
@@ -230,7 +218,7 @@ class LV2DB:
             world.copyFrom(self.manifests)
             seeAlso = self.manifests.bySubject[uri]["http://www.w3.org/2000/01/rdf-schema#seeAlso"]
             for doc in seeAlso:
-                # print "Loading " + doc
+                # print "Loading " + doc + " for plugin " + uri
                 parseTTL(doc, file(doc).read(), world, self.debug)
             self.plugin_info[uri] = world                
         info = self.plugin_info[uri]
diff --git a/bigbull/setup.py b/bigbull/setup.py
index 23286cb..3cc0c5b 100644
--- a/bigbull/setup.py
+++ b/bigbull/setup.py
@@ -3,7 +3,9 @@ from distutils.core import setup, Extension
 
 module1 = Extension('calfpytools',
                     libraries = ['jack'],
-                    sources = ['calfpytools.cpp']
+                    sources = ['calfpytools.cpp', 'ttl.cpp'],
+                    extra_compile_args = ["-g"],
+                    extra_link_args = ["-g"]
                     )
 
 setup (name = 'CalfPyTools',
diff --git a/bigbull/test.py b/bigbull/test.py
index c9e358a..37d65dd 100755
--- a/bigbull/test.py
+++ b/bigbull/test.py
@@ -1,20 +1,33 @@
 #!/usr/bin/env python
 import calfpytools
+import time
+
+print calfpytools.scan_ttl_file("/usr/local/lib/lv2/allpass-swh.lv2/plugin.ttl")
 
 client = calfpytools.JackClient()
 client.open("calf")
+print client.get_cobj()
 port = client.register_port("port")
 print port
+print port.get_cobj()
 assert port.get_name() == "port"
 assert port.get_full_name() == "calf:port"
 assert port.set_name("port2") == "port2"
 assert port.get_name() == "port2"
 assert port.get_full_name() == "calf:port2"
 assert port.is_valid()
+
+# This doesn't work: assert client.get_port("calf:port2") == port (because JACK C API doesn't reuse the jack_port_t structs)
+
 port2 = client.get_port("system:playback_1")
 assert port2.get_name() == "playback_1"
 print port2.get_full_name()
 print port2.get_aliases()
+# prevent Patchage from crashing
+time.sleep(1)
 port.unregister()
+assert port2 == client.get_port("system:playback_1")
 assert not port.is_valid()
-client.close()
+print port2.get_connections()
+#client.close()
+
diff --git a/bigbull/ttl.h b/bigbull/ttl.h
new file mode 100644
index 0000000..208c600
--- /dev/null
+++ b/bigbull/ttl.h
@@ -0,0 +1,281 @@
+#ifndef yyHEADER_H
+#define yyHEADER_H 1
+#define yyIN_HEADER 1
+
+#line 6 "ttl.h"
+
+#line 8 "ttl.h"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 34
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+    /* The c++ scanner is a mess. The FlexLexer.h header file relies on the
+     * following macro. This is required in order to pass the c++-multiple-scanners
+     * test in the regression suite. We get reports that it breaks inheritance.
+     * We will address this in a future release of flex, or omit the C++ scanner
+     * altogether.
+     */
+    #define yyFlexLexer yyFlexLexer
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+#include <iostream> 
+#include <errno.h>
+#include <cstdlib>
+#include <cstring>
+/* end standard C++ headers. */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ * Given that the standard has decreed that size_t exists since 1989,
+ * I guess we can afford to depend on it. Manoj.
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+
+	std::istream* yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+/* Begin user sect3 */
+
+#define yytext_ptr yytext
+
+#include <FlexLexer.h>
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define C_COMMENT 1
+#define C_LONGSTRING 2
+#define C_STRING 3
+
+#endif
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+#define YY_DECL int yyFlexLexer::yylex()
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 46 "ttl.l"
+
+
+#line 280 "ttl.h"
+#undef yyIN_HEADER
+#endif /* yyHEADER_H */
diff --git a/bigbull/ttl.l b/bigbull/ttl.l
new file mode 100644
index 0000000..138f747
--- /dev/null
+++ b/bigbull/ttl.l
@@ -0,0 +1,46 @@
+%{
+#include <Python.h>
+#include "ttldata.h"
+
+int yyFlexLexer::yywrap() { return 1; }
+
+void yyerror(const char *str)
+{
+    PyErr_SetString(PyExc_SyntaxError, str);
+}
+
+%}
+
+%x C_COMMENT C_LONGSTRING C_STRING
+
+SYMBOL [A-Za-z_-][a-zA-Z0-9_-]*
+TRIPLEQUOTE \"\"\"
+
+%%
+
+ at prefix { LEXER_DATA->add("prefix", "@prefix"); }
+# BEGIN(C_COMMENT);
+{TRIPLEQUOTE} { LEXER_DATA->strctx.clear(); BEGIN(C_LONGSTRING); }
+\" { LEXER_DATA->strctx.clear(); BEGIN(C_STRING); }
+\<[^>]*\> { LEXER_DATA->add("URI", std::string(yytext + 1, strlen(yytext) - 2)); }
+[+-]?[0-9]+\.[0-9]*([eE][-+]?[0-9]+)? { std::stringstream ss(yytext); double value; ss >> value; LEXER_DATA->add("number", PyFloat_FromDouble(value)); }
+[+-]?[0-9]+ { LEXER_DATA->add("number", PyInt_FromLong(atol(yytext))); }
+{SYMBOL}?:{SYMBOL}? { LEXER_DATA->add("prnot", yytext); } 
+{SYMBOL} { LEXER_DATA->add("symbol", yytext); } 
+[.,;\[\]\(\)] { LEXER_DATA->add(yytext, yytext); } 
+[ \t\n] ;
+
+. { printf("Unexpected characters: '%s'\n", yytext); yyerror("Syntax error"); }
+
+<C_LONGSTRING>{TRIPLEQUOTE} { LEXER_DATA->add("string", LEXER_DATA->strctx); BEGIN(INITIAL); }
+<C_LONGSTRING>[^"]+ LEXER_DATA->strctx += yytext;
+<C_LONGSTRING>\" LEXER_DATA->strctx += yytext;
+
+<C_STRING>\" { LEXER_DATA->add("string", LEXER_DATA->strctx); BEGIN(INITIAL); }
+<C_STRING>\\\" LEXER_DATA->strctx += "\""; 
+<C_STRING>[^\\\"\n]+ LEXER_DATA->strctx += yytext;
+
+<C_COMMENT>\n { BEGIN(INITIAL); }
+<C_COMMENT>. ;
+
+%%
diff --git a/bigbull/ttldata.h b/bigbull/ttldata.h
new file mode 100644
index 0000000..cc73920
--- /dev/null
+++ b/bigbull/ttldata.h
@@ -0,0 +1,38 @@
+#ifndef _TTLDATA_H
+#define _TTLDATA_H
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <Python.h>
+
+class TTLLexer: public yyFlexLexer
+{
+public:
+    std::string strctx;
+    PyObject *pylist;
+
+    TTLLexer(std::istream *istr) : yyFlexLexer(istr), pylist(PyList_New(0)) {}
+    void add(const std::string &type, const std::string &value) { 
+        PyList_Append(pylist, Py_BuildValue("(ss)", type.c_str(), value.c_str()));
+        // printf("Type %s, Value %s\n", type.c_str(), value.c_str());
+    }
+    void add(const std::string &type, PyObject *value) { 
+        PyList_Append(pylist, Py_BuildValue("(sO)", type.c_str(), value));
+        PyObject *str = PyObject_Str(value);
+        // printf("Type %s, Repr Value %s\n", type.c_str(), PyString_AsString(str));
+        Py_DECREF(str);
+    }
+    PyObject *grab() {
+        PyObject *tmp = pylist;
+        pylist = NULL;
+        return tmp;
+    }
+    ~TTLLexer() {
+        Py_XDECREF(pylist);
+    }
+};
+
+#define LEXER_DATA (dynamic_cast<TTLLexer *>(this))
+
+#endif

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list