summaryrefslogtreecommitdiff
path: root/pmt
diff options
context:
space:
mode:
authoreb2007-05-02 04:08:47 +0000
committereb2007-05-02 04:08:47 +0000
commit0bf2128a621ae84099f43744e1b81800f2b9d2d7 (patch)
tree1345b44ae9060e99ff236f983dd272c6d35a012e /pmt
parent28259329a829f157fd877a1c14139eaf0117dabd (diff)
downloadgnuradio-0bf2128a621ae84099f43744e1b81800f2b9d2d7.tar.gz
gnuradio-0bf2128a621ae84099f43744e1b81800f2b9d2d7.tar.bz2
gnuradio-0bf2128a621ae84099f43744e1b81800f2b9d2d7.zip
Merged features/inband -r4812:5218 into trunk. This group of changes
includes: * working stand-alone mblock code * work-in-progress on usrp inband signaling usrp now depends on mblock, and guile is a dependency. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5221 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'pmt')
-rw-r--r--pmt/src/Makefile.am4
-rw-r--r--pmt/src/lib/Makefile.am17
-rw-r--r--pmt/src/lib/pmt.cc170
-rw-r--r--pmt/src/lib/pmt.h45
-rw-r--r--pmt/src/lib/pmt_int.h21
-rw-r--r--pmt/src/lib/pmt_pool.cc96
-rw-r--r--pmt/src/lib/pmt_pool.h61
-rw-r--r--pmt/src/lib/pmt_serialize.cc353
-rw-r--r--pmt/src/lib/qa_pmt_prims.cc132
-rw-r--r--pmt/src/lib/qa_pmt_prims.h4
-rw-r--r--pmt/src/scheme/Makefile.am21
-rw-r--r--pmt/src/scheme/gnuradio/Makefile.am32
-rwxr-xr-xpmt/src/scheme/gnuradio/gen-serial-tags.scm118
-rw-r--r--pmt/src/scheme/gnuradio/macros-etc.scm50
-rw-r--r--pmt/src/scheme/gnuradio/pmt-serial-tags.scm75
-rw-r--r--pmt/src/scheme/gnuradio/pmt-serialize.scm48
16 files changed, 1198 insertions, 49 deletions
diff --git a/pmt/src/Makefile.am b/pmt/src/Makefile.am
index bcbab2455..df73ba515 100644
--- a/pmt/src/Makefile.am
+++ b/pmt/src/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2004,2006 Free Software Foundation, Inc.
+# Copyright 2006,2007 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -19,4 +19,4 @@
# Boston, MA 02110-1301, USA.
#
-SUBDIRS = lib
+SUBDIRS = lib scheme
diff --git a/pmt/src/lib/Makefile.am b/pmt/src/lib/Makefile.am
index a738a1692..b77f6201b 100644
--- a/pmt/src/lib/Makefile.am
+++ b/pmt/src/lib/Makefile.am
@@ -21,7 +21,7 @@
include $(top_srcdir)/Makefile.common
-INCLUDES = $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+INCLUDES = $(DEFINES) $(OMNITHREAD_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
TESTS = test_pmt
@@ -48,18 +48,22 @@ GENERATED_CC = \
$(GENERATED_H) $(GENERATED_I) $(GENERATED_CC): $(CODE_GENERATOR)
PYTHONPATH=$(top_srcdir)/pmt/src/lib srcdir=$(srcdir) $(PYTHON) $(srcdir)/generate_unv.py
-BUILT_SOURCES = $(GENERATED_H) $(GENERATED_CC)
+pmt_serial_tags.h: $(srcdir)/../scheme/gnuradio/gen-serial-tags.scm $(srcdir)/../scheme/gnuradio/pmt-serial-tags.scm
+ $(RUN_GUILE) $(srcdir)/../scheme/gnuradio/gen-serial-tags.scm $(srcdir)/../scheme/gnuradio/pmt-serial-tags.scm pmt_serial_tags.h
+
+BUILT_SOURCES = $(GENERATED_H) $(GENERATED_CC) pmt_serial_tags.h
# ----------------------------------------------------------------
EXTRA_DIST = \
- $(CODE_GENERATOR)
-
+ $(CODE_GENERATOR)
# These are the source files that go into the pmt shared library
libpmt_la_SOURCES = \
pmt.cc \
pmt_io.cc \
+ pmt_pool.cc \
+ pmt_serialize.cc \
pmt_unv.cc
# magic flags
@@ -67,10 +71,13 @@ libpmt_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
# link the library against the c++ standard library
libpmt_la_LIBADD = \
+ $(OMNITHREAD_LA) \
-lstdc++
include_HEADERS = \
- pmt.h
+ pmt.h \
+ pmt_pool.h \
+ pmt_serial_tags.h
noinst_HEADERS = \
$(GENERATED_H) \
diff --git a/pmt/src/lib/pmt.cc b/pmt/src/lib/pmt.cc
index cf6547b57..9378953c1 100644
--- a/pmt/src/lib/pmt.cc
+++ b/pmt/src/lib/pmt.cc
@@ -26,6 +26,33 @@
#include <vector>
#include <pmt.h>
#include "pmt_int.h"
+#include <stdio.h>
+#include <pmt_pool.h>
+
+static const int CACHE_LINE_SIZE = 64; // good guess
+
+# if (PMT_LOCAL_ALLOCATOR)
+
+static pmt_pool global_pmt_pool(sizeof(pmt_pair), CACHE_LINE_SIZE);
+
+void *
+pmt_base::operator new(size_t size)
+{
+ void *p = global_pmt_pool.malloc();
+
+ // fprintf(stderr, "pmt_base::new p = %p\n", p);
+ assert((reinterpret_cast<intptr_t>(p) & (CACHE_LINE_SIZE - 1)) == 0);
+ return p;
+}
+
+void
+pmt_base::operator delete(void *p, size_t size)
+{
+ global_pmt_pool.free(p);
+}
+
+#endif
+
pmt_base::~pmt_base()
{
@@ -108,25 +135,37 @@ _dict(pmt_t x)
return dynamic_cast<pmt_dict*>(x.get());
}
+static pmt_any *
+_any(pmt_t x)
+{
+ return dynamic_cast<pmt_any*>(x.get());
+}
+
////////////////////////////////////////////////////////////////////////////
-// Booleans
+// Globals
////////////////////////////////////////////////////////////////////////////
-const pmt_t PMT_BOOL_T = pmt_t(new pmt_bool()); // singleton
-const pmt_t PMT_BOOL_F = pmt_t(new pmt_bool()); // singleton
+const pmt_t PMT_T = pmt_t(new pmt_bool()); // singleton
+const pmt_t PMT_F = pmt_t(new pmt_bool()); // singleton
+const pmt_t PMT_NIL = pmt_t(new pmt_null()); // singleton
+const pmt_t PMT_EOF = pmt_cons(PMT_NIL, PMT_NIL); // singleton
+
+////////////////////////////////////////////////////////////////////////////
+// Booleans
+////////////////////////////////////////////////////////////////////////////
pmt_bool::pmt_bool(){}
bool
pmt_is_true(pmt_t obj)
{
- return obj != PMT_BOOL_F;
+ return obj != PMT_F;
}
bool
pmt_is_false(pmt_t obj)
{
- return obj == PMT_BOOL_F;
+ return obj == PMT_F;
}
bool
@@ -138,15 +177,15 @@ pmt_is_bool(pmt_t obj)
pmt_t
pmt_from_bool(bool val)
{
- return val ? PMT_BOOL_T : PMT_BOOL_F;
+ return val ? PMT_T : PMT_F;
}
bool
pmt_to_bool(pmt_t val)
{
- if (val == PMT_BOOL_T)
+ if (val == PMT_T)
return true;
- if (val == PMT_BOOL_F)
+ if (val == PMT_F)
return false;
throw pmt_wrong_type("pmt_to_bool", val);
}
@@ -167,7 +206,7 @@ hash_string(const std::string &s)
unsigned int h = 0;
unsigned int g = 0;
- for (std::string::const_iterator p = s.begin(); p != s.end(); p++){
+ for (std::string::const_iterator p = s.begin(); p != s.end(); ++p){
h = (h << 4) + (*p & 0xff);
g = h & 0xf0000000;
if (g){
@@ -322,8 +361,6 @@ pmt_to_complex(pmt_t x)
// Pairs
////////////////////////////////////////////////////////////////////////////
-const pmt_t PMT_NIL = pmt_t(new pmt_null()); // singleton
-
pmt_null::pmt_null() {}
pmt_pair::pmt_pair(pmt_t car, pmt_t cdr) : d_car(car), d_cdr(cdr) {}
@@ -599,6 +636,40 @@ pmt_dict_values(pmt_t dict)
}
////////////////////////////////////////////////////////////////////////////
+// Any
+////////////////////////////////////////////////////////////////////////////
+
+pmt_any::pmt_any(const boost::any &any) : d_any(any) {}
+
+bool
+pmt_is_any(pmt_t obj)
+{
+ return obj->is_any();
+}
+
+pmt_t
+pmt_make_any(const boost::any &any)
+{
+ return pmt_t(new pmt_any(any));
+}
+
+boost::any
+pmt_any_ref(pmt_t obj)
+{
+ if (!obj->is_any())
+ throw pmt_wrong_type("pmt_any_ref", obj);
+ return _any(obj)->ref();
+}
+
+void
+pmt_any_set(pmt_t obj, const boost::any &any)
+{
+ if (!obj->is_any())
+ throw pmt_wrong_type("pmt_any_set", obj);
+ _any(obj)->set(any);
+}
+
+////////////////////////////////////////////////////////////////////////////
// General Functions
////////////////////////////////////////////////////////////////////////////
@@ -689,14 +760,14 @@ pmt_assq(pmt_t obj, pmt_t alist)
while (pmt_is_pair(alist)){
pmt_t p = pmt_car(alist);
if (!pmt_is_pair(p)) // malformed alist
- return PMT_BOOL_F;
+ return PMT_F;
if (pmt_eq(obj, pmt_car(p)))
return p;
alist = pmt_cdr(alist);
}
- return PMT_BOOL_F;
+ return PMT_F;
}
pmt_t
@@ -705,14 +776,14 @@ pmt_assv(pmt_t obj, pmt_t alist)
while (pmt_is_pair(alist)){
pmt_t p = pmt_car(alist);
if (!pmt_is_pair(p)) // malformed alist
- return PMT_BOOL_F;
+ return PMT_F;
if (pmt_eqv(obj, pmt_car(p)))
return p;
alist = pmt_cdr(alist);
}
- return PMT_BOOL_F;
+ return PMT_F;
}
pmt_t
@@ -721,14 +792,14 @@ pmt_assoc(pmt_t obj, pmt_t alist)
while (pmt_is_pair(alist)){
pmt_t p = pmt_car(alist);
if (!pmt_is_pair(p)) // malformed alist
- return PMT_BOOL_F;
+ return PMT_F;
if (pmt_equal(obj, pmt_car(p)))
return p;
alist = pmt_cdr(alist);
}
- return PMT_BOOL_F;
+ return PMT_F;
}
pmt_t
@@ -805,7 +876,7 @@ pmt_memq(pmt_t obj, pmt_t list)
return list;
list = pmt_cdr(list);
}
- return PMT_BOOL_F;
+ return PMT_F;
}
pmt_t
@@ -816,7 +887,7 @@ pmt_memv(pmt_t obj, pmt_t list)
return list;
list = pmt_cdr(list);
}
- return PMT_BOOL_F;
+ return PMT_F;
}
pmt_t
@@ -827,7 +898,7 @@ pmt_member(pmt_t obj, pmt_t list)
return list;
list = pmt_cdr(list);
}
- return PMT_BOOL_F;
+ return PMT_F;
}
bool
@@ -865,3 +936,62 @@ pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4)
{
return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, PMT_NIL))));
}
+
+pmt_t
+pmt_caar(pmt_t pair)
+{
+ return (pmt_car(pmt_car(pair)));
+}
+
+pmt_t
+pmt_cadr(pmt_t pair)
+{
+ return pmt_car(pmt_cdr(pair));
+}
+
+pmt_t
+pmt_cdar(pmt_t pair)
+{
+ return pmt_cdr(pmt_car(pair));
+}
+
+pmt_t
+pmt_cddr(pmt_t pair)
+{
+ return pmt_cdr(pmt_cdr(pair));
+}
+
+pmt_t
+pmt_caddr(pmt_t pair)
+{
+ return pmt_car(pmt_cdr(pmt_cdr(pair)));
+}
+
+pmt_t
+pmt_cadddr(pmt_t pair)
+{
+ return pmt_car(pmt_cdr(pmt_cdr(pmt_cdr(pair))));
+}
+
+bool
+pmt_is_eof_object(pmt_t obj)
+{
+ return pmt_eq(obj, PMT_EOF);
+}
+
+void
+pmt_dump_sizeof()
+{
+ printf("sizeof(pmt_t) = %3zd\n", sizeof(pmt_t));
+ printf("sizeof(pmt_base) = %3zd\n", sizeof(pmt_base));
+ printf("sizeof(pmt_bool) = %3zd\n", sizeof(pmt_bool));
+ printf("sizeof(pmt_symbol) = %3zd\n", sizeof(pmt_symbol));
+ printf("sizeof(pmt_integer) = %3zd\n", sizeof(pmt_integer));
+ printf("sizeof(pmt_real) = %3zd\n", sizeof(pmt_real));
+ printf("sizeof(pmt_complex) = %3zd\n", sizeof(pmt_complex));
+ printf("sizeof(pmt_null) = %3zd\n", sizeof(pmt_null));
+ printf("sizeof(pmt_pair) = %3zd\n", sizeof(pmt_pair));
+ printf("sizeof(pmt_vector) = %3zd\n", sizeof(pmt_vector));
+ printf("sizeof(pmt_dict) = %3zd\n", sizeof(pmt_dict));
+ printf("sizeof(pmt_uniform_vector) = %3zd\n", sizeof(pmt_uniform_vector));
+}
diff --git a/pmt/src/lib/pmt.h b/pmt/src/lib/pmt.h
index 030637c4d..dcf1ce668 100644
--- a/pmt/src/lib/pmt.h
+++ b/pmt/src/lib/pmt.h
@@ -24,10 +24,11 @@
#define INCLUDED_PMT_H
#include <boost/shared_ptr.hpp>
+#include <boost/any.hpp>
#include <complex>
#include <string>
#include <stdint.h>
-#include <iostream>
+#include <iosfwd>
#include <stdexcept>
/*!
@@ -82,8 +83,8 @@ public:
* I.e., there is a single false value, #f.
* ------------------------------------------------------------------------
*/
-extern const pmt_t PMT_BOOL_T; //< #t : boolean true constant
-extern const pmt_t PMT_BOOL_F; //< #f : boolean false constant
+extern const pmt_t PMT_T; //< #t : boolean true constant
+extern const pmt_t PMT_F; //< #f : boolean false constant
//! Return true if obj is #t or #f, else return false.
bool pmt_is_bool(pmt_t obj);
@@ -97,7 +98,7 @@ bool pmt_is_false(pmt_t obj);
//! Return #f is val is false, else return #t.
pmt_t pmt_from_bool(bool val);
-//! Return true if val is PMT_BOOL_T, return false when val is PMT_BOOL_F,
+//! Return true if val is PMT_T, return false when val is PMT_F,
// else raise wrong_type exception.
bool pmt_to_bool(pmt_t val);
@@ -225,6 +226,13 @@ void pmt_set_car(pmt_t pair, pmt_t value);
//! Stores \p value in the cdr field of \p pair.
void pmt_set_cdr(pmt_t pair, pmt_t value);
+pmt_t pmt_caar(pmt_t pair);
+pmt_t pmt_cadr(pmt_t pair);
+pmt_t pmt_cdar(pmt_t pair);
+pmt_t pmt_cddr(pmt_t pair);
+pmt_t pmt_caddr(pmt_t pair);
+pmt_t pmt_cadddr(pmt_t pair);
+
/*
* ------------------------------------------------------------------------
* Vectors
@@ -414,6 +422,28 @@ pmt_t pmt_dict_values(pmt_t dict);
/*
* ------------------------------------------------------------------------
+ * Any (wraps boost::any -- can be used to wrap pretty much anything)
+ *
+ * Cannot be serialized or used across process boundaries.
+ * See http://www.boost.org/doc/html/any.html
+ * ------------------------------------------------------------------------
+ */
+
+//! Return true if \p obj is an any
+bool pmt_is_any(pmt_t obj);
+
+//! make an any
+pmt_t pmt_make_any(const boost::any &any);
+
+//! Return underlying boost::any
+boost::any pmt_any_ref(pmt_t obj);
+
+//! Store \p any in \p obj
+void pmt_any_set(pmt_t obj, const boost::any &any);
+
+
+/*
+ * ------------------------------------------------------------------------
* General functions
* ------------------------------------------------------------------------
*/
@@ -618,11 +648,14 @@ std::ostream& operator<<(std::ostream &os, pmt_t obj);
/*!
* \brief Write portable byte-serial representation of \p obj to \p sink
*/
-void pmt_serialize(pmt_t obj, std::ostream &sink);
+bool pmt_serialize(pmt_t obj, std::streambuf &sink);
/*!
* \brief Create obj from portable byte-serial representation
*/
-pmt_t pmt_deserialize(std::istream &source);
+pmt_t pmt_deserialize(std::streambuf &source);
+
+
+void pmt_dump_sizeof(); // debugging
#endif /* INCLUDED_PMT_H */
diff --git a/pmt/src/lib/pmt_int.h b/pmt/src/lib/pmt_int.h
index 458443eaf..e82ce50e2 100644
--- a/pmt/src/lib/pmt_int.h
+++ b/pmt/src/lib/pmt_int.h
@@ -31,6 +31,8 @@
* See pmt.h for the public interface
*/
+#define PMT_LOCAL_ALLOCATOR 0 // define to 0 or 1
+
class pmt_base : boost::noncopyable {
protected:
pmt_base(){};
@@ -47,6 +49,7 @@ public:
virtual bool is_pair() const { return false; }
virtual bool is_vector() const { return false; }
virtual bool is_dict() const { return false; }
+ virtual bool is_any() const { return false; }
virtual bool is_uniform_vector() const { return false; }
virtual bool is_u8vector() const { return false; }
@@ -62,6 +65,10 @@ public:
virtual bool is_c32vector() const { return false; }
virtual bool is_c64vector() const { return false; }
+# if (PMT_LOCAL_ALLOCATOR)
+ void *operator new(size_t);
+ void operator delete(void *, size_t);
+#endif
};
class pmt_bool : public pmt_base
@@ -189,6 +196,20 @@ public:
pmt_t values() const;
};
+class pmt_any : public pmt_base
+{
+ boost::any d_any;
+
+public:
+ pmt_any(const boost::any &any);
+ //~pmt_any();
+
+ bool is_any() const { return true; }
+ const boost::any &ref() const { return d_any; }
+ void set(const boost::any &any) { d_any = any; }
+};
+
+
class pmt_uniform_vector : public pmt_base
{
public:
diff --git a/pmt/src/lib/pmt_pool.cc b/pmt/src/lib/pmt_pool.cc
new file mode 100644
index 000000000..16ab9c61e
--- /dev/null
+++ b/pmt/src/lib/pmt_pool.cc
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <pmt_pool.h>
+#include <algorithm>
+#include <stdint.h>
+
+static inline size_t
+ROUNDUP(size_t x, size_t stride)
+{
+ return ((((x) + (stride) - 1)/(stride)) * (stride));
+}
+
+pmt_pool::pmt_pool(size_t itemsize, size_t alignment, size_t allocation_size)
+ : d_itemsize(ROUNDUP(itemsize, alignment)),
+ d_alignment(alignment),
+ d_allocation_size(std::max(allocation_size, 16 * itemsize)),
+ d_freelist(0)
+{
+}
+
+pmt_pool::~pmt_pool()
+{
+ for (unsigned int i = 0; i < d_allocations.size(); i++){
+ delete [] d_allocations[i];
+ }
+}
+
+void *
+pmt_pool::malloc()
+{
+ omni_mutex_lock l(d_mutex);
+ item *p;
+
+ if (d_freelist){ // got something?
+ p = d_freelist;
+ d_freelist = p->d_next;
+ return p;
+ }
+
+ // allocate a new chunk
+ char *alloc = new char[d_allocation_size + d_alignment - 1];
+ d_allocations.push_back(alloc);
+
+ // get the alignment we require
+ char *start = (char *)(((uintptr_t)alloc + d_alignment-1) & -d_alignment);
+ char *end = alloc + d_allocation_size + d_alignment - 1;
+ size_t n = (end - start) / d_itemsize;
+
+ // link the new items onto the free list.
+ p = (item *) start;
+ for (size_t i = 0; i < n; i++){
+ p->d_next = d_freelist;
+ d_freelist = p;
+ p = (item *)((char *) p + d_itemsize);
+ }
+
+ // now return the first one
+ p = d_freelist;
+ d_freelist = p->d_next;
+ return p;
+}
+
+void
+pmt_pool::free(void *foo)
+{
+ if (!foo)
+ return;
+
+ omni_mutex_lock l(d_mutex);
+
+ item *p = (item *) foo;
+ p->d_next = d_freelist;
+ d_freelist = p;
+}
diff --git a/pmt/src/lib/pmt_pool.h b/pmt/src/lib/pmt_pool.h
new file mode 100644
index 000000000..fd9cc0638
--- /dev/null
+++ b/pmt/src/lib/pmt_pool.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_PMT_POOL_H
+#define INCLUDED_PMT_POOL_H
+
+#include <cstddef>
+#include <omnithread.h>
+#include <vector>
+
+/*!
+ * \brief very simple thread-safe fixed-size allocation pool
+ *
+ * FIXME may want to go to global allocation with per-thread free list.
+ * This would eliminate virtually all lock contention.
+ */
+class pmt_pool {
+
+ struct item {
+ struct item *d_next;
+ };
+
+ omni_mutex d_mutex;
+
+ size_t d_itemsize;
+ size_t d_alignment;
+ size_t d_allocation_size;
+ item *d_freelist;
+ std::vector<char *> d_allocations;
+
+public:
+ /*!
+ * \param itemsize size in bytes of the items to be allocated.
+ * \param alignment alignment in bytes of all objects to be allocated (must be power-of-2).
+ * \param allocation_size number of bytes to allocate at a time from the underlying allocator.
+ */
+ pmt_pool(size_t itemsize, size_t alignment = 16, size_t allocation_size = 4096);
+ ~pmt_pool();
+
+ void *malloc();
+ void free(void *p);
+};
+
+#endif /* INCLUDED_PMT_POOL_H */
diff --git a/pmt/src/lib/pmt_serialize.cc b/pmt/src/lib/pmt_serialize.cc
new file mode 100644
index 000000000..45f688be5
--- /dev/null
+++ b/pmt/src/lib/pmt_serialize.cc
@@ -0,0 +1,353 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <vector>
+#include <pmt.h>
+#include "pmt_int.h"
+#include "pmt_serial_tags.h"
+
+static pmt_t parse_pair(std::streambuf &sb);
+
+// ----------------------------------------------------------------
+// output primitives
+// ----------------------------------------------------------------
+
+static bool
+serialize_untagged_u8(unsigned int i, std::streambuf &sb)
+{
+ return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+
+// always writes big-endian
+static bool
+serialize_untagged_u16(unsigned int i, std::streambuf &sb)
+{
+ sb.sputc((i >> 8) & 0xff);
+ return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+
+// always writes big-endian
+static bool
+serialize_untagged_u32(unsigned int i, std::streambuf &sb)
+{
+ sb.sputc((i >> 24) & 0xff);
+ sb.sputc((i >> 16) & 0xff);
+ sb.sputc((i >> 8) & 0xff);
+ return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+
+#if 0
+// always writes big-endian
+static bool
+serialize_untagged_u64(uint64_t i, std::streambuf &sb)
+{
+ sb.sputc((i >> 56) & 0xff);
+ sb.sputc((i >> 48) & 0xff);
+ sb.sputc((i >> 40) & 0xff);
+ sb.sputc((i >> 32) & 0xff);
+ sb.sputc((i >> 24) & 0xff);
+ sb.sputc((i >> 16) & 0xff);
+ sb.sputc((i >> 8) & 0xff);
+ return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof();
+}
+#endif
+
+// ----------------------------------------------------------------
+// input primitives
+// ----------------------------------------------------------------
+
+
+// always reads big-endian
+static bool
+deserialize_untagged_u8(uint8_t *ip, std::streambuf &sb)
+{
+ std::streambuf::traits_type::int_type t;
+ int i;
+
+ t = sb.sbumpc();
+ i = t & 0xff;
+
+ *ip = i;
+ return t != std::streambuf::traits_type::eof();
+}
+
+// always reads big-endian
+static bool
+deserialize_untagged_u16(uint16_t *ip, std::streambuf &sb)
+{
+ std::streambuf::traits_type::int_type t;
+ int i;
+
+ t = sb.sbumpc();
+ i = t & 0xff;
+
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+
+ *ip = i;
+ return t != std::streambuf::traits_type::eof();
+}
+
+// always reads big-endian
+static bool
+deserialize_untagged_u32(uint32_t *ip, std::streambuf &sb)
+{
+ std::streambuf::traits_type::int_type t;
+ int i;
+
+ t = sb.sbumpc();
+ i = t & 0xff;
+
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+
+ *ip = i;
+ return t != std::streambuf::traits_type::eof();
+}
+
+#if 0
+// always reads big-endian
+static bool
+deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb)
+{
+ std::streambuf::traits_type::int_type t;
+ uint64_t i;
+
+ t = sb.sbumpc();
+ i = t & 0xff;
+
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+ t = sb.sbumpc();
+ i = (i << 8) | (t & 0xff);
+
+ *ip = i;
+ return t != std::streambuf::traits_type::eof();
+}
+#endif
+
+/*
+ * Write portable byte-serial representation of \p obj to \p sb
+ *
+ * N.B., Circular structures cause infinite recursion.
+ */
+bool
+pmt_serialize(pmt_t obj, std::streambuf &sb)
+{
+ bool ok = true;
+
+ tail_recursion:
+
+ if (pmt_is_bool(obj)){
+ if (pmt_eq(obj, PMT_T))
+ return serialize_untagged_u8(PST_TRUE, sb);
+ else
+ return serialize_untagged_u8(PST_FALSE, sb);
+ }
+
+ if (pmt_is_null(obj))
+ return serialize_untagged_u8(PST_NULL, sb);
+
+ if (pmt_is_symbol(obj)){
+ const std::string s = pmt_symbol_to_string(obj);
+ size_t len = s.size();
+ ok = serialize_untagged_u8(PST_SYMBOL, sb);
+ ok &= serialize_untagged_u16(len, sb);
+ for (size_t i = 0; i < len; i++)
+ ok &= serialize_untagged_u8(s[i], sb);
+ return ok;
+ }
+
+ if (pmt_is_pair(obj)){
+ ok = serialize_untagged_u8(PST_PAIR, sb);
+ ok &= pmt_serialize(pmt_car(obj), sb);
+ if (!ok)
+ return false;
+ obj = pmt_cdr(obj);
+ goto tail_recursion;
+ }
+
+ if (pmt_is_number(obj)){
+
+ if (pmt_is_integer(obj)){
+ long i = pmt_to_long(obj);
+ if (sizeof(long) > 4){
+ if (i < -2147483647 || i > 2147483647)
+ throw pmt_notimplemented("pmt_serialize (64-bit integers)", obj);
+ }
+ ok = serialize_untagged_u8(PST_INT32, sb);
+ ok &= serialize_untagged_u32(i, sb);
+ return ok;
+ }
+
+ if (pmt_is_real(obj))
+ throw pmt_notimplemented("pmt_serialize (real)", obj);
+
+ if (pmt_is_complex(obj))
+ throw pmt_notimplemented("pmt_serialize (complex)", obj);
+ }
+
+ if (pmt_is_vector(obj))
+ throw pmt_notimplemented("pmt_serialize (vector)", obj);
+
+ if (pmt_is_uniform_vector(obj))
+ throw pmt_notimplemented("pmt_serialize (uniform-vector)", obj);
+
+ if (pmt_is_dict(obj))
+ throw pmt_notimplemented("pmt_serialize (dict)", obj);
+
+
+ throw pmt_notimplemented("pmt_serialize (?)", obj);
+}
+
+/*
+ * Create obj from portable byte-serial representation
+ *
+ * Returns next obj from streambuf, or PMT_EOF at end of file.
+ * Throws exception on malformed input.
+ */
+pmt_t
+pmt_deserialize(std::streambuf &sb)
+{
+ uint8_t tag;
+ //uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ //uint32_t u64;
+ static char tmpbuf[1024];
+
+ if (!deserialize_untagged_u8(&tag, sb))
+ return PMT_EOF;
+
+ switch (tag){
+ case PST_TRUE:
+ return PMT_T;
+
+ case PST_FALSE:
+ return PMT_F;
+
+ case PST_NULL:
+ return PMT_NIL;
+
+ case PST_SYMBOL:
+ if (!deserialize_untagged_u16(&u16, sb))
+ goto error;
+ if (u16 > sizeof(tmpbuf))
+ throw pmt_notimplemented("pmt_deserialize: very long symbol",
+ PMT_F);
+ if (sb.sgetn(tmpbuf, u16) != u16)
+ goto error;
+ return pmt_intern(std::string(tmpbuf, u16));
+
+ case PST_INT32:
+ if (!deserialize_untagged_u32(&u32, sb))
+ goto error;
+ return pmt_from_long((int32_t) u32);
+
+ case PST_PAIR:
+ return parse_pair(sb);
+
+ case PST_DOUBLE:
+ case PST_COMPLEX:
+ case PST_VECTOR:
+ case PST_DICT:
+ case PST_UNIFORM_VECTOR:
+ case PST_COMMENT:
+ throw pmt_notimplemented("pmt_deserialize: tag value = ",
+ pmt_from_long(tag));
+
+ default:
+ throw pmt_exception("pmt_deserialize: malformed input stream, tag value = ",
+ pmt_from_long(tag));
+ }
+
+ error:
+ throw pmt_exception("pmt_deserialize: malformed input stream", PMT_F);
+}
+
+/*
+ * This is a mostly non-recursive implementation that allows us to
+ * deserialize very long lists w/o exhausting the evaluation stack.
+ *
+ * On entry we've already eaten the PST_PAIR tag.
+ */
+pmt_t
+parse_pair(std::streambuf &sb)
+{
+ uint8_t tag;
+ pmt_t val, expr, lastnptr, nptr;
+
+ //
+ // Keep appending nodes until we get a non-PAIR cdr.
+ //
+ lastnptr = PMT_NIL;
+ while (1){
+ expr = pmt_deserialize(sb); // read the car
+
+ nptr = pmt_cons(expr, PMT_NIL); // build new cell
+ if (pmt_is_null(lastnptr))
+ val = nptr;
+ else
+ pmt_set_cdr(lastnptr, nptr);
+ lastnptr = nptr;
+
+ if (!deserialize_untagged_u8(&tag, sb)) // get tag of cdr
+ throw pmt_exception("pmt_deserialize: malformed input stream", PMT_F);
+
+ if (tag == PST_PAIR)
+ continue; // keep on looping...
+
+ if (tag == PST_NULL){
+ expr = PMT_NIL;
+ break;
+ }
+
+ //
+ // default: push tag back and use pmt_deserialize to get the cdr
+ //
+ sb.sungetc();
+ expr = pmt_deserialize(sb);
+ break;
+ }
+
+ //
+ // At this point, expr contains the value of the final cdr in the list.
+ //
+ pmt_set_cdr(lastnptr, expr);
+ return val;
+}
diff --git a/pmt/src/lib/qa_pmt_prims.cc b/pmt/src/lib/qa_pmt_prims.cc
index cb687b0e1..4a665fe53 100644
--- a/pmt/src/lib/qa_pmt_prims.cc
+++ b/pmt/src/lib/qa_pmt_prims.cc
@@ -24,13 +24,14 @@
#include <cppunit/TestAssert.h>
#include <pmt.h>
#include <stdio.h>
+#include <sstream>
void
qa_pmt_prims::test_symbols()
{
- CPPUNIT_ASSERT(!pmt_is_symbol(PMT_BOOL_T));
- CPPUNIT_ASSERT(!pmt_is_symbol(PMT_BOOL_F));
- CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_BOOL_F), pmt_wrong_type);
+ CPPUNIT_ASSERT(!pmt_is_symbol(PMT_T));
+ CPPUNIT_ASSERT(!pmt_is_symbol(PMT_F));
+ CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_F), pmt_wrong_type);
pmt_t sym1 = pmt_string_to_symbol("test");
CPPUNIT_ASSERT(pmt_is_symbol(sym1));
@@ -76,13 +77,13 @@ void
qa_pmt_prims::test_booleans()
{
pmt_t sym = pmt_string_to_symbol("test");
- CPPUNIT_ASSERT(pmt_is_bool(PMT_BOOL_T));
- CPPUNIT_ASSERT(pmt_is_bool(PMT_BOOL_F));
+ CPPUNIT_ASSERT(pmt_is_bool(PMT_T));
+ CPPUNIT_ASSERT(pmt_is_bool(PMT_F));
CPPUNIT_ASSERT(!pmt_is_bool(sym));
- CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_BOOL_F);
- CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_BOOL_T);
- CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_BOOL_F));
- CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_BOOL_T));
+ CPPUNIT_ASSERT_EQUAL(pmt_from_bool(false), PMT_F);
+ CPPUNIT_ASSERT_EQUAL(pmt_from_bool(true), PMT_T);
+ CPPUNIT_ASSERT_EQUAL(false, pmt_to_bool(PMT_F));
+ CPPUNIT_ASSERT_EQUAL(true, pmt_to_bool(PMT_T));
CPPUNIT_ASSERT_THROW(pmt_to_bool(sym), pmt_wrong_type);
}
@@ -91,10 +92,10 @@ qa_pmt_prims::test_integers()
{
pmt_t p1 = pmt_from_long(1);
pmt_t m1 = pmt_from_long(-1);
- CPPUNIT_ASSERT(!pmt_is_integer(PMT_BOOL_T));
+ CPPUNIT_ASSERT(!pmt_is_integer(PMT_T));
CPPUNIT_ASSERT(pmt_is_integer(p1));
CPPUNIT_ASSERT(pmt_is_integer(m1));
- CPPUNIT_ASSERT_THROW(pmt_to_long(PMT_BOOL_T), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_to_long(PMT_T), pmt_wrong_type);
CPPUNIT_ASSERT_EQUAL(-1L, pmt_to_long(m1));
CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(p1));
}
@@ -104,10 +105,10 @@ qa_pmt_prims::test_reals()
{
pmt_t p1 = pmt_from_double(1);
pmt_t m1 = pmt_from_double(-1);
- CPPUNIT_ASSERT(!pmt_is_real(PMT_BOOL_T));
+ CPPUNIT_ASSERT(!pmt_is_real(PMT_T));
CPPUNIT_ASSERT(pmt_is_real(p1));
CPPUNIT_ASSERT(pmt_is_real(m1));
- CPPUNIT_ASSERT_THROW(pmt_to_double(PMT_BOOL_T), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_to_double(PMT_T), pmt_wrong_type);
CPPUNIT_ASSERT_EQUAL(-1.0, pmt_to_double(m1));
CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(p1));
CPPUNIT_ASSERT_EQUAL(1.0, pmt_to_double(pmt_from_long(1)));
@@ -118,10 +119,10 @@ qa_pmt_prims::test_complexes()
{
pmt_t p1 = pmt_make_rectangular(2, -3);
pmt_t m1 = pmt_make_rectangular(-3, 2);
- CPPUNIT_ASSERT(!pmt_is_complex(PMT_BOOL_T));
+ CPPUNIT_ASSERT(!pmt_is_complex(PMT_T));
CPPUNIT_ASSERT(pmt_is_complex(p1));
CPPUNIT_ASSERT(pmt_is_complex(m1));
- CPPUNIT_ASSERT_THROW(pmt_to_complex(PMT_BOOL_T), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_to_complex(PMT_T), pmt_wrong_type);
CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, -3), pmt_to_complex(p1));
CPPUNIT_ASSERT_EQUAL(std::complex<double>(-3, 2), pmt_to_complex(m1));
CPPUNIT_ASSERT_EQUAL(std::complex<double>(1.0, 0), pmt_to_complex(pmt_from_long(1)));
@@ -242,7 +243,7 @@ qa_pmt_prims::test_misc()
pmt_t alist = pmt_cons(p0, pmt_cons(p1, pmt_cons(p2, PMT_NIL)));
CPPUNIT_ASSERT(pmt_eq(p1, pmt_assv(k1, alist)));
- CPPUNIT_ASSERT(pmt_eq(PMT_BOOL_F, pmt_assv(k3, alist)));
+ CPPUNIT_ASSERT(pmt_eq(PMT_F, pmt_assv(k3, alist)));
pmt_t keys = pmt_cons(k0, pmt_cons(k1, pmt_cons(k2, PMT_NIL)));
pmt_t vals = pmt_cons(v0, pmt_cons(v1, pmt_cons(v2, PMT_NIL)));
@@ -293,3 +294,102 @@ qa_pmt_prims::test_io()
CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
}
+
+// ------------------------------------------------------------------------
+
+// class foo is used in test_any below.
+// It can't be declared in the scope of test_any because of template
+// namespace problems.
+
+class foo {
+public:
+ double d_double;
+ int d_int;
+ foo(double d=0, int i=0) : d_double(d), d_int(i) {}
+};
+
+bool operator==(const foo &a, const foo &b)
+{
+ return a.d_double == b.d_double && a.d_int == b.d_int;
+}
+
+std::ostream& operator<<(std::ostream &os, const foo obj)
+{
+ os << "<foo: " << obj.d_double << ", " << obj.d_int << ">";
+ return os;
+}
+
+void
+qa_pmt_prims::test_any()
+{
+ boost::any a0;
+ boost::any a1;
+ boost::any a2;
+
+ a0 = std::string("Hello!");
+ a1 = 42;
+ a2 = foo(3.250, 21);
+
+ pmt_t p0 = pmt_make_any(a0);
+ pmt_t p1 = pmt_make_any(a1);
+ pmt_t p2 = pmt_make_any(a2);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("Hello!"),
+ boost::any_cast<std::string>(pmt_any_ref(p0)));
+
+ CPPUNIT_ASSERT_EQUAL(42,
+ boost::any_cast<int>(pmt_any_ref(p1)));
+
+ CPPUNIT_ASSERT_EQUAL(foo(3.250, 21),
+ boost::any_cast<foo>(pmt_any_ref(p2)));
+}
+
+// ------------------------------------------------------------------------
+
+void
+qa_pmt_prims::test_serialize()
+{
+ std::stringbuf sb; // fake channel
+ pmt_t a = pmt_intern("a");
+ pmt_t b = pmt_intern("b");
+ pmt_t c = pmt_intern("c");
+
+ sb.str(""); // reset channel to empty
+
+ // write stuff to channel
+
+ pmt_serialize(PMT_NIL, sb);
+ pmt_serialize(pmt_intern("foobarvia"), sb);
+ pmt_serialize(pmt_from_long(123456789), sb);
+ pmt_serialize(pmt_from_long(-123456789), sb);
+ pmt_serialize(pmt_cons(PMT_NIL, PMT_NIL), sb);
+ pmt_serialize(pmt_cons(a, b), sb);
+ pmt_serialize(pmt_list1(a), sb);
+ pmt_serialize(pmt_list2(a, b), sb);
+ pmt_serialize(pmt_list3(a, b, c), sb);
+ pmt_serialize(pmt_list3(a, pmt_list3(c, b, a), c), sb);
+ pmt_serialize(PMT_T, sb);
+ pmt_serialize(PMT_F, sb);
+
+ // read it back
+
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_NIL));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_intern("foobarvia")));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(123456789)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(-123456789)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(PMT_NIL, PMT_NIL)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(a, b)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list1(a)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list2(a, b)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, b, c)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_list3(a, pmt_list3(c, b, a), c)));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_T));
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_F));
+
+ CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_EOF)); // last item
+
+
+ // FIXME add tests for real, complex, vector, uniform-vector, dict
+ // FIXME add tests for malformed input too.
+
+}
diff --git a/pmt/src/lib/qa_pmt_prims.h b/pmt/src/lib/qa_pmt_prims.h
index 8d379c5af..a390343bd 100644
--- a/pmt/src/lib/qa_pmt_prims.h
+++ b/pmt/src/lib/qa_pmt_prims.h
@@ -38,7 +38,9 @@ class qa_pmt_prims : public CppUnit::TestCase {
CPPUNIT_TEST(test_equivalence);
CPPUNIT_TEST(test_misc);
CPPUNIT_TEST(test_dict);
+ CPPUNIT_TEST(test_any);
CPPUNIT_TEST(test_io);
+ CPPUNIT_TEST(test_serialize);
CPPUNIT_TEST_SUITE_END();
private:
@@ -52,7 +54,9 @@ class qa_pmt_prims : public CppUnit::TestCase {
void test_equivalence();
void test_misc();
void test_dict();
+ void test_any();
void test_io();
+ void test_serialize();
};
#endif /* INCLUDED_QA_PMT_PRIMS_H */
diff --git a/pmt/src/scheme/Makefile.am b/pmt/src/scheme/Makefile.am
new file mode 100644
index 000000000..7700a1fc0
--- /dev/null
+++ b/pmt/src/scheme/Makefile.am
@@ -0,0 +1,21 @@
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+SUBDIRS = gnuradio
diff --git a/pmt/src/scheme/gnuradio/Makefile.am b/pmt/src/scheme/gnuradio/Makefile.am
new file mode 100644
index 000000000..12bc9b115
--- /dev/null
+++ b/pmt/src/scheme/gnuradio/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Copyright 2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+#pkgdatadir = $(datadir)/gnuradio
+
+EXTRA_DIST = \
+ gen-serial-tags.scm \
+ pmt-serial-tags.scm \
+ pmt-serialize.scm
+
+
+# really scheme source files
+pkgdata_DATA = \
+ pmt-serial-tags.scm \
+ pmt-serialize.scm
diff --git a/pmt/src/scheme/gnuradio/gen-serial-tags.scm b/pmt/src/scheme/gnuradio/gen-serial-tags.scm
new file mode 100755
index 000000000..5bcf8015a
--- /dev/null
+++ b/pmt/src/scheme/gnuradio/gen-serial-tags.scm
@@ -0,0 +1,118 @@
+#!/usr/bin/guile \
+-e main -s
+!#
+;;; -*-scheme-*-
+;;;
+;;; Copyright 2007 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License along
+;;; with this program; if not, write to the Free Software Foundation, Inc.,
+;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;;
+
+(use-modules (ice-9 format))
+
+(defmacro when (pred . body)
+ `(if ,pred (begin ,@body) #f))
+
+;; ----------------------------------------------------------------
+
+(define (main args)
+
+ (define (usage)
+ (format 0
+ "usage: ~a <pmt-serial-tags.scm> <pmt_serial_tags.h>~%"
+ (car args)))
+
+ (when (not (= (length args) 3))
+ (usage)
+ (format 0 "args: ~s~%" args)
+ (exit 1))
+
+ (let ((i-file (open-input-file (cadr args)))
+ (h-file (open-output-file (caddr args))))
+
+ (write-header-comment h-file "// ")
+ (display "#ifndef INCLUDED_PMT_SERIAL_TAGS_H\n" h-file)
+ (display "#define INCLUDED_PMT_SERIAL_TAGS_H\n" h-file)
+ (newline h-file)
+ (display "enum pst_tags {\n" h-file)
+
+ (for-each-in-file i-file
+ (lambda (form)
+ (let* ((name (cadr form))
+ (c-name (string-upcase (c-ify name)))
+ (value (caddr form)))
+ ;;(format h-file "static const int ~a\t= 0x~x;~%" c-name value)
+ (format h-file " ~a\t= 0x~x,~%" c-name value))))
+
+ (display "};\n" h-file)
+ (display "#endif\n" h-file)))
+
+(define (c-ify name)
+ (list->string (map (lambda (c)
+ (if (eqv? c #\-) #\_ c))
+ (string->list (symbol->string name)))))
+
+
+(define (write-header-comment o-port prefix)
+ (for-each (lambda (comment)
+ (format o-port "~a~a~%" prefix comment))
+ header-comment))
+
+(define header-comment
+ '(
+ ""
+ "Copyright 2007 Free Software Foundation, Inc."
+ ""
+ "This file is part of GNU Radio"
+ ""
+ "GNU Radio is free software; you can redistribute it and/or modify"
+ "it under the terms of the GNU General Public License as published by"
+ "the Free Software Foundation; either version 2, or (at your option)"
+ "any later version."
+ ""
+ "GNU Radio is distributed in the hope that it will be useful,"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
+ "GNU General Public License for more details."
+ ""
+ "You should have received a copy of the GNU General Public License along"
+ "with this program; if not, write to the Free Software Foundation, Inc.,"
+ "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
+ ""
+ ""
+ "THIS FILE IS MACHINE GENERATED FROM pmt-serial-tags.scm. DO NOT EDIT BY HAND."
+ "See pmt-serial-tags.scm for additional commentary."
+ ""))
+
+
+
+(define (for-each-in-file file f)
+ (let ((port (if (port? file)
+ file
+ (open-input-file file))))
+ (letrec
+ ((loop
+ (lambda (port form)
+ (cond ((eof-object? form)
+ (when (not (eq? port file))
+ (close-input-port port))
+ #t)
+ (else
+ (f form)
+ (set! form #f) ; for GC
+ (loop port (read port)))))))
+ (loop port (read port)))))
diff --git a/pmt/src/scheme/gnuradio/macros-etc.scm b/pmt/src/scheme/gnuradio/macros-etc.scm
new file mode 100644
index 000000000..518c1ffe1
--- /dev/null
+++ b/pmt/src/scheme/gnuradio/macros-etc.scm
@@ -0,0 +1,50 @@
+;;; -*- scheme -*-
+;;;
+;;; Copyright 2007 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License along
+;;; with this program; if not, write to the Free Software Foundation, Inc.,
+;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;;
+
+(define-module (gnuradio macros-etc)
+ :export (atom? when unless for-each-in-file))
+
+(define (atom? obj)
+ (not (pair? obj)))
+
+(defmacro when (pred . body)
+ `(if ,pred (begin ,@body) #f))
+
+(defmacro unless (pred . body)
+ `(if (not ,pred) (begin ,@body) #f))
+
+
+(define (for-each-in-file file f)
+ (let ((port (if (port? file)
+ file
+ (open-input-file file))))
+ (letrec
+ ((loop
+ (lambda (port form)
+ (cond ((eof-object? form)
+ (when (not (eq? port file))
+ (close-input-port port))
+ #t)
+ (else
+ (f form)
+ (set! form #f) ; for GC
+ (loop port (read port)))))))
+ (loop port (read port)))))
diff --git a/pmt/src/scheme/gnuradio/pmt-serial-tags.scm b/pmt/src/scheme/gnuradio/pmt-serial-tags.scm
new file mode 100644
index 000000000..4dd183034
--- /dev/null
+++ b/pmt/src/scheme/gnuradio/pmt-serial-tags.scm
@@ -0,0 +1,75 @@
+;;; -*-scheme-*-
+;;;
+;;; Copyright 2007 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (define at your option)
+;;; any later version.
+;;;
+;;; GNU Radio is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License along
+;;; with this program; if not, write to the Free Software Foundation, Inc.,
+;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;;
+
+;;; definitions of tag values used for marshalling pmt data
+
+(define pst-true #x00)
+(define pst-false #x01)
+(define pst-symbol #x02) ; untagged-int16 n; followed by n bytes of symbol name
+(define pst-int32 #x03)
+(define pst-double #x04)
+(define pst-complex #x05) ; complex<double>: real, imag
+(define pst-null #x06)
+(define pst-pair #x07) ; followed by two objects
+(define pst-vector #x08) ; untagged-int32 n; followed by n objects
+(define pst-dict #x09) ; untagged-int32 n; followed by n key/value tuples
+
+(define pst-uniform-vector #x0a)
+
+;; u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, c32, c64
+;;
+;; untagged-uint8 tag
+;; untagged-uint8 uvi (define uniform vector info, see below)
+;; untagged-int32 n-items
+;; untagged-uint8 npad
+;; npad bytes of zeros to align binary data
+;; n-items binary numeric items
+;;
+;; uvi:
+;; +-+-+-+-+-+-+-+-+
+;; |B| subtype |
+;; +-+-+-+-+-+-+-+-+
+;;
+;; B == 0, numeric data is little-endian.
+;; B == 1, numeric data is big-endian.
+
+ (define uvi-endian-mask #x80)
+ (define uvi-subtype-mask #x7f)
+
+ (define uvi-little-endian #x00)
+ (define uvi-big-endian #x80)
+
+ (define uvi-u8 #x00)
+ (define uvi-s8 #x01)
+ (define uvi-u16 #x02)
+ (define uvi-s16 #x03)
+ (define uvi-u32 #x04)
+ (define uvi-s32 #x05)
+ (define uvi-u64 #x06)
+ (define uvi-s64 #x07)
+ (define uvi-f32 #x08)
+ (define uvi-f64 #x09)
+ (define uvi-c32 #x0a)
+ (define uvi-c64 #x0b)
+
+
+(define pst-comment #x3b) ; ascii ';'
+(define pst-comment-end #x0a) ; ascii '\n'
diff --git a/pmt/src/scheme/gnuradio/pmt-serialize.scm b/pmt/src/scheme/gnuradio/pmt-serialize.scm
new file mode 100644
index 000000000..a39f9cf50
--- /dev/null
+++ b/pmt/src/scheme/gnuradio/pmt-serialize.scm
@@ -0,0 +1,48 @@
+;;;
+;;; Copyright 2007 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License along
+;;; with this program; if not, write to the Free Software Foundation, Inc.,
+;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;;
+
+;;; An implementation of pmt_serialize in scheme.
+;;; Currently handles only symbols and pairs. They're all we need for now.
+
+(define-module (gnuradio pmt-serialize)
+ :export (pmt-serialize))
+
+(load-from-path "gnuradio/pmt-serial-tags")
+
+(define (pmt-serialize obj put-byte)
+ (define (put-u16 x)
+ (put-byte (logand (ash x -8) #xff))
+ (put-byte (logand x #xff)))
+
+ (cond ((null? obj)
+ (put-byte pst-null))
+ ((symbol? obj)
+ (let* ((sym-as-bytes (map char->integer (string->list (symbol->string obj))))
+ (len (length sym-as-bytes)))
+ (put-byte pst-symbol)
+ (put-u16 len)
+ (for-each put-byte sym-as-bytes)))
+
+ ((pair? obj)
+ (put-byte pst-pair)
+ (pmt-serialize (car obj) put-byte)
+ (pmt-serialize (cdr obj) put-byte))
+ (else
+ (throw 'not-implemented "pmt-serialize" obj))))