summaryrefslogtreecommitdiff
path: root/source3/aparser
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-05-14 14:05:10 +0000
committerAndrew Tridgell <tridge@samba.org>2000-05-14 14:05:10 +0000
commitb7022e94d2ab62d522b0a7c2886cce3afaff6872 (patch)
tree6663fe08efd72d9a95d9cf4cf70baa07ded15aca /source3/aparser
parentb7f9a2794273266a0c64a6c02f88d65d37554ea9 (diff)
downloadsamba-b7022e94d2ab62d522b0a7c2886cce3afaff6872.tar.gz
samba-b7022e94d2ab62d522b0a7c2886cce3afaff6872.tar.bz2
samba-b7022e94d2ab62d522b0a7c2886cce3afaff6872.zip
vastly improved awk based code generator
now handles recursive function definitions, unions etc it is sufficient for some basic types like UNISTR2 and BUFFER5 to be defined in the *.struct file and used successfully this generator uses templates (in *.tpl files) for all code generation, allowing easy replacement of the backend functions (This used to be commit 14ded82dc92ae6eff7639351f391a33b9cc31c0d)
Diffstat (limited to 'source3/aparser')
-rw-r--r--source3/aparser/Makefile11
-rw-r--r--source3/aparser/dump.awk55
-rw-r--r--source3/aparser/harness.awk13
-rw-r--r--source3/aparser/header.awk60
-rw-r--r--source3/aparser/main.awk63
-rw-r--r--source3/aparser/parsefn.awk123
-rw-r--r--source3/aparser/parser.c145
-rw-r--r--source3/aparser/parser.h36
-rw-r--r--source3/aparser/parsetree.awk64
-rw-r--r--source3/aparser/spool.struct76
-rw-r--r--source3/aparser/template.awk17
-rw-r--r--source3/aparser/templates/fn_end.tpl33
-rw-r--r--source3/aparser/templates/fn_start.tpl9
-rw-r--r--source3/aparser/templates/harness_start.tpl7
-rw-r--r--source3/aparser/templates/ifptr_end.tpl1
-rw-r--r--source3/aparser/templates/ifptr_start.tpl1
-rw-r--r--source3/aparser/templates/module_end.tpl3
-rw-r--r--source3/aparser/templates/module_start.tpl5
-rw-r--r--source3/aparser/templates/prs_.align.tpl1
-rw-r--r--source3/aparser/templates/prs_array.tpl7
-rw-r--r--source3/aparser/templates/prs_case.tpl1
-rw-r--r--source3/aparser/templates/prs_case_end.tpl1
-rw-r--r--source3/aparser/templates/prs_pointer.tpl1
-rw-r--r--source3/aparser/templates/prs_struct.tpl1
-rw-r--r--source3/aparser/templates/prs_struct_alloc.tpl1
-rw-r--r--source3/aparser/templates/prs_uint16.tpl1
-rw-r--r--source3/aparser/templates/prs_uint32.tpl1
-rw-r--r--source3/aparser/templates/union_end.tpl5
-rw-r--r--source3/aparser/templates/union_start.tpl1
-rw-r--r--source3/aparser/util.awk33
-rw-r--r--source3/aparser/vluke.c4
31 files changed, 612 insertions, 168 deletions
diff --git a/source3/aparser/Makefile b/source3/aparser/Makefile
index e74e99de18..160b11155a 100644
--- a/source3/aparser/Makefile
+++ b/source3/aparser/Makefile
@@ -1,20 +1,17 @@
CFLAGS=-Wall -g
CC=gcc
-%.h : %.struct
- igawk -f parser.awk < $*.struct > $*.h
-
OBJ = vluke.o parser.o
+AWKPROGS=dump.awk harness.awk header.awk parsefn.awk main.awk parsetree.awk template.awk util.awk
all: test.h vluke
-test.h : test.struct
+test.h : $(AWKPROGS)
+ igawk -f main.awk spool.struct
vluke: test.h $(OBJ)
$(CC) $(CFLAGS) -o vluke $(OBJ)
clean:
- rm -f *.o test.h
+ rm -f *.o test.h prs_*.[ch]
-test: vluke
- ./vluke test.dat > test.out
diff --git a/source3/aparser/dump.awk b/source3/aparser/dump.awk
new file mode 100644
index 0000000000..0a72bb8414
--- /dev/null
+++ b/source3/aparser/dump.awk
@@ -0,0 +1,55 @@
+# dump the current parse tree
+
+function dump_union(f, struct_num, union,
+ LOCAL, i)
+{
+ xprintf(f,"\tunion %s %s {\n",
+ structs[struct_num, "unions", union, "switch"],
+ union);
+ for (i=0;i<structs[struct_num, "unions", union, "num_elems"];i++) {
+ xprintf(f,"\t\tcase %d %s %s;\n",
+ structs[struct_num, "unions", union, i, "value"],
+ structs[struct_num, "unions", union, i, "type"],
+ structs[struct_num, "unions", union, i, "elem"]);
+ }
+ xprintf(f,"\t}\n");
+}
+
+function dump_array(f, struct_num, elem_num,
+ LOCAL, i)
+{
+ xprintf(f,"\t{%s} %s %s;\n",
+ structs[struct_num, elem_num, "array_len"],
+ structs[struct_num, elem_num, "type"],
+ structs[struct_num, elem_num, "elem"]);
+}
+
+function dump_elem(f, struct_num, elem_num)
+{
+ if (structs[struct_num, elem_num, "type"] == "union") {
+ dump_union(f, struct_num, structs[struct_num, elem_num, "elem"]);
+ } else if (structs[struct_num, elem_num, "array_len"]) {
+ dump_array(f, struct_num, elem_num);
+ } else {
+ xprintf(f,"\t%s %s;\n",
+ structs[struct_num, elem_num, "type"],
+ structs[struct_num, elem_num, "elem"]);
+ }
+}
+
+function dump_structs(f, NIL,
+ LOCAL, i, j)
+{
+ xprintf(f,"/* dump of parsed structures */\n\n\n");
+ for (i=0;i < num_structs;i++) {
+ xprintf(f,"/* structure %d */\n", i);
+ xprintf(f,"struct %s {\n", structs[i, "name"]);
+ for (j=0;j<structs[i, "num_elems"];j++) {
+ dump_elem(f, i, j);
+ }
+ xprintf(f,"};\n\n");
+ }
+ xprintf(f,"/* end dump */\n\n");
+}
+
+
diff --git a/source3/aparser/harness.awk b/source3/aparser/harness.awk
new file mode 100644
index 0000000000..345fd6e191
--- /dev/null
+++ b/source3/aparser/harness.awk
@@ -0,0 +1,13 @@
+function produce_harness(f,
+ LOCAL, v, struct_num)
+{
+ struct_num=structs[test];
+
+ v["MODULE"]=module;
+ v["TEST"]=test;
+ v["TEST_FUNC"]=moduletest;
+ v["STRUCTNAME"] = structs[struct_num, "name"];
+ v["FUNCNAME"] = v["MODULE"] "_io_" v["STRUCTNAME"];
+
+ print_template(f, "harness_start.tpl", v);
+}
diff --git a/source3/aparser/header.awk b/source3/aparser/header.awk
new file mode 100644
index 0000000000..e7e5b2cff4
--- /dev/null
+++ b/source3/aparser/header.awk
@@ -0,0 +1,60 @@
+# produce a header file for a parsed struct file
+
+function header_union(f, struct_num, union,
+ LOCAL, i)
+{
+ xprintf(f,"\tunion {\n");
+ for (i=0;i<structs[struct_num, "unions", union, "num_elems"];i++) {
+ xprintf(f,"\t\t%s %s;\n",
+ structs[struct_num, "unions", union, i, "type"],
+ structs[struct_num, "unions", union, i, "elem"]);
+ }
+ xprintf(f,"\t} %s;\n", union);
+}
+
+function header_array(f, struct_num, elem_num)
+{
+ xprintf(f,"\t%s *%s; /* array of length %s */ \n",
+ structs[struct_num, elem_num, "type"],
+ structs[struct_num, elem_num, "elem"],
+ structs[struct_num, elem_num, "array_len"]);
+}
+
+function header_elem(f, struct_num, elem_num)
+{
+ if (structs[struct_num, elem_num, "type"] == ".align") return;
+
+ if (structs[struct_num, elem_num, "type"] == "union") {
+ header_union(f, struct_num, structs[struct_num, elem_num, "elem"]);
+ } else if (structs[struct_num, elem_num, "array_len"]) {
+ header_array(f, struct_num, elem_num);
+ } else {
+ xprintf(f,"\t%s %s;\n",
+ structs[struct_num, elem_num, "type"],
+ structs[struct_num, elem_num, "elem"]);
+ }
+}
+
+function header_struct(f, struct_num,
+ LOCAL, i)
+{
+ xprintf(f,"/* structure %s */\n",
+ structs[struct_num, "name"]);
+ xprintf(f,"typedef struct {\n");
+ for (i=0;i < structs[struct_num, "num_elems"];i++) {
+ header_elem(f, struct_num, i);
+ }
+ xprintf(f,"} %s;\n\n\n", structs[struct_num, "name"]);
+}
+
+
+function produce_headers(f, NIL,
+ LOCAL, i)
+{
+ xprintf(f,"/* auto-generated headers for %s */\n\n\n", module);
+ for (i=0;i < num_structs;i++) {
+ header_struct(f, i);
+ }
+ xprintf(f,"/* end auto-generated headers */\n\n");
+}
+
diff --git a/source3/aparser/main.awk b/source3/aparser/main.awk
new file mode 100644
index 0000000000..c3e8c2539c
--- /dev/null
+++ b/source3/aparser/main.awk
@@ -0,0 +1,63 @@
+# the main program
+
+@include dump.awk
+@include parsetree.awk
+@include header.awk
+@include util.awk
+@include template.awk
+@include parsefn.awk
+@include harness.awk
+
+/^module/ {
+ start_module($2);
+ next;
+}
+
+/^test/ {
+ test=$2;
+ next;
+}
+
+/^struct.*\{/ {
+ start_struct($2);
+ next;
+}
+
+/^[ \t]*union.*\{/ {
+ start_union($2, $3);
+ next;
+}
+
+/^[ \t]*case.*;/ {
+ split($0,a,"[ \t;]*");
+ parse_case(a[3],a[4],a[5]);
+ next;
+}
+
+/^\};/ {
+ end_struct();
+ next;
+}
+
+/^[ \t]*\}/ {
+ end_union();
+ next;
+}
+
+/^[ \t]*\{.*\}.*;/ {
+ split($0,a,"[ \t;{}]*");
+ add_array(a[2], a[3], a[4]);
+ next;
+}
+
+/.*;/ {
+ split($0,a,"[ \t;]*");
+ add_elem(a[2], a[3]);
+}
+
+END {
+ dump_structs("debug.out");
+ produce_headers("prs_"module".h");
+ produce_parsers("prs_"module".c");
+ produce_harness("test.h");
+}
diff --git a/source3/aparser/parsefn.awk b/source3/aparser/parsefn.awk
new file mode 100644
index 0000000000..b3421a7e54
--- /dev/null
+++ b/source3/aparser/parsefn.awk
@@ -0,0 +1,123 @@
+# build parse functions for a parsed struct file
+
+function parse_elem(f, v, struct_num, elem_num,
+ LOCAL, type, elem)
+{
+ type = structs[struct_num, elem_num, "type"];
+ elem = structs[struct_num, elem_num, "elem"];
+ v["ELEM"] = noptr(elem);
+ v["TYPE"] = type;
+ if (structs[type] != "") {
+ if (isaptr(elem)) {
+ print_template(f, "prs_struct_alloc.tpl", v);
+ } else {
+ print_template(f, "prs_struct.tpl", v);
+ }
+ } else {
+ print_template(f, "prs_"type".tpl", v);
+ }
+}
+
+
+function parse_pointer(f, v, struct_num, elem_num,
+ LOCAL, elem)
+{
+ elem = structs[struct_num, elem_num, "elem"];
+ v["ELEM"] = noptr(elem);
+ print_template(f, "prs_pointer.tpl", v);
+}
+
+function parse_array(f, v, struct_num, elem_num,
+ LOCAL, elem, type)
+{
+ elem = structs[struct_num, elem_num, "elem"];
+ type = structs[struct_num, elem_num, "type"];
+ v["ARRAYLEN"] = structs[struct_num, elem_num, "array_len"]
+ v["ELEM"] = elem;
+ v["TYPE"] = type;
+ print_template(f, "prs_array.tpl", v);
+}
+
+function parse_union(f, v, struct_num, elem_num,
+ LOCAL, union, type, i, elem, value)
+{
+ union = structs[struct_num, elem_num, "elem"];
+ v["UNION"] = noptr(union);
+ v["SWITCH"] = structs[struct_num, "unions", union, "switch"];
+
+ print_template(f, "union_start.tpl", v);
+ for (i=0;i<structs[struct_num, "unions", union, "num_elems"];i++) {
+ elem = structs[struct_num, "unions", union, i, "elem"];
+ type = structs[struct_num, "unions", union, i, "type"];
+ value = structs[struct_num, "unions", union, i, "value"];
+ v["ELEM"] = v["UNION"]"->"noptr(elem);
+ v["TYPE"] = type;
+ v["VALUE"] = value;
+ print_template(f, "prs_case.tpl", v);
+ if (structs[type] != "") {
+ print_template(f, "prs_struct.tpl", v);
+ } else {
+ print_template(f, "prs_"type".tpl", v);
+ }
+ print_template(f, "prs_case_end.tpl", v);
+ }
+
+ print_template(f, "union_end.tpl", v);
+}
+
+function parse_ptr_elem(f, v, struct_num, elem_num,
+ LOCAL, elem, type)
+{
+ elem = structs[struct_num, elem_num, "elem"];
+ type = structs[struct_num, elem_num, "type"];
+ v["ELEM"] = noptr(elem);
+ print_template(f, "ifptr_start.tpl", v);
+ if (type == "union") {
+ parse_union(f, v, struct_num, elem_num);
+ } else {
+ parse_elem(f, v, struct_num, elem_num);
+ }
+ print_template(f, "ifptr_end.tpl", v);
+}
+
+
+function struct_parser(f, v, struct_num,
+ LOCAL, i)
+{
+ v["STRUCTNAME"] = structs[struct_num, "name"];
+ v["FUNCNAME"] = v["MODULE"] "_io_" v["STRUCTNAME"];
+ print_template(f, "fn_start.tpl", v);
+
+ # first all the structure pointers, scalars and arrays
+ for (i=0;i<structs[struct_num, "num_elems"];i++) {
+ if (isaptr(structs[struct_num, i, "elem"])) {
+ parse_pointer(f, v, struct_num, i);
+ } else if (structs[struct_num, i, "array_len"]) {
+ parse_array(f, v, struct_num, i);
+ } else {
+ parse_elem(f, v, struct_num, i);
+ }
+ }
+
+ # now the structures
+ for (i=0;i<structs[struct_num, "num_elems"];i++) {
+ if (!isaptr(structs[struct_num, i, "elem"])) continue;
+ parse_ptr_elem(f, v, struct_num, i);
+ }
+
+ print_template(f, "fn_end.tpl", v);
+}
+
+function produce_parsers(f,
+ LOCAL, v)
+{
+ v["MODULE"]=module;
+
+ print_template(f, "module_start.tpl", v);
+
+ for (i=0;i < num_structs;i++) {
+ struct_parser(f, v, i);
+ }
+
+ print_template(f, "module_end.tpl", v);
+}
diff --git a/source3/aparser/parser.c b/source3/aparser/parser.c
index f938c58e8b..72042ba9f7 100644
--- a/source3/aparser/parser.c
+++ b/source3/aparser/parser.c
@@ -198,101 +198,6 @@ BOOL prs_align(prs_struct *ps)
return True;
}
-/*******************************************************************
- Reads or writes an NTTIME structure.
-********************************************************************/
-
-BOOL smb_io_time(char *desc, NTTIME *nttime, prs_struct *ps, int depth)
-{
- if (nttime == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "smb_io_time");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("low ", ps, depth, &nttime->low)) /* low part */
- return False;
- if(!prs_uint32("high", ps, depth, &nttime->high)) /* high part */
- return False;
-
- return True;
-}
-
-
-/*******************************************************************
- Reads or writes a UNISTR2 structure.
- XXXX NOTE: UNISTR2 structures need NOT be null-terminated.
- the uni_str_len member tells you how long the string is;
- the uni_max_len member tells you how large the buffer is.
-********************************************************************/
-
-BOOL smb_io_unistr2(char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct *ps, int depth)
-{
- if (uni2 == NULL)
- return False;
-
- if (buffer) {
-
- prs_debug(ps, depth, desc, "smb_io_unistr2");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("uni_max_len", ps, depth, &uni2->uni_max_len))
- return False;
- if(!prs_uint32("undoc ", ps, depth, &uni2->undoc))
- return False;
- if(!prs_uint32("uni_str_len", ps, depth, &uni2->uni_str_len))
- return False;
-
- /* oops! XXXX maybe issue a warning that this is happening... */
- if (uni2->uni_max_len > MAX_UNISTRLEN)
- uni2->uni_max_len = MAX_UNISTRLEN;
- if (uni2->uni_str_len > MAX_UNISTRLEN)
- uni2->uni_str_len = MAX_UNISTRLEN;
-
- /* buffer advanced by indicated length of string
- NOT by searching for null-termination */
- if(!prs_unistr2(True, "buffer ", ps, depth, uni2))
- return False;
-
- } else {
-
- prs_debug(ps, depth, desc, "smb_io_unistr2 - NULL");
- depth++;
- memset((char *)uni2, '\0', sizeof(*uni2));
-
- }
-
- return True;
-}
-
-/******************************************************************
- Stream a unicode string, length/buffer specified separately,
- in uint16 chars. We use DBG_RW_PCVAL, not DBG_RW_PSVAL here
- as the unicode string is already in little-endian format.
- ********************************************************************/
-
-BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
-{
- char *p = (char *)str->buffer;
- char *q = prs_mem_get(ps, str->uni_str_len * sizeof(uint16));
- if (q == NULL)
- return False;
-
- /* If we're using big-endian, reverse to get little-endian. */
- if(ps->bigendian_data)
- DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, p, str->uni_str_len)
- else
- DBG_RW_PCVAL(charmode, name, depth, ps->data_offset, ps->io, q, p, str->uni_str_len * 2)
- ps->data_offset += (str->uni_str_len * sizeof(uint16));
-
- return True;
-}
void print_asc(int level, unsigned char *buf,int len)
{
@@ -358,54 +263,44 @@ void dump_data(int level,char *buf1,int len)
}
/*******************************************************************
- Stream a uint64_struct
+ Stream a pointer
********************************************************************/
-BOOL prs_uint64(char *desc, prs_struct *ps, int depth, UINT64_S *data64)
+BOOL prs_pointer(char *desc, prs_struct *ps, int depth, void **p)
{
- prs_debug(ps, depth, desc, "prs_uint64");
- return prs_uint32("low", ps, depth+1, &data64->low) &&
- prs_uint32("high", ps, depth+1, &data64->high);
+ uint32 v;
+ if (!prs_uint32(desc, ps, depth, &v)) return False;
+ *p = (void *) (v ? 1 : 0);
+ return True;
}
+/******************************************************************
+ Stream an array of uint16s. Length is number of uint16s.
+ ********************************************************************/
-
-/*******************************************************************
-reads or writes a BUFFER5 structure.
-the buf_len member tells you how large the buffer is.
-********************************************************************/
-BOOL smb_io_buffer5(char *desc, BUFFER5 *buf5, prs_struct *ps, int depth)
+BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
{
- prs_debug(ps, depth, desc, "smb_io_buffer5");
- depth++;
-
- if (buf5 == NULL) return False;
-
- prs_align(ps);
- prs_uint32("buf_len", ps, depth, &(buf5->buf_len));
+ char *q = prs_mem_get(ps, len * sizeof(uint16));
+ if (q == NULL)
+ return False;
- /* reading: alloc the buffer first */
- if ( ps->io )
- {
- buf5->buffer=(uint16 *)malloc( sizeof(uint16)*buf5->buf_len );
- }
-
- prs_uint16s(True, "buffer", ps, depth, buf5->buffer, buf5->buf_len);
+ DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data16s, len)
+ ps->data_offset += (len * sizeof(uint16));
return True;
}
/******************************************************************
- Stream an array of uint16s. Length is number of uint16s.
+ Stream an array of uint32s. Length is number of uint32s.
********************************************************************/
-BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
+BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
{
- char *q = prs_mem_get(ps, len * sizeof(uint16));
+ char *q = prs_mem_get(ps, len * sizeof(uint32));
if (q == NULL)
return False;
- DBG_RW_PSVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data16s, len)
- ps->data_offset += (len * sizeof(uint16));
+ DBG_RW_PIVAL(charmode, name, depth, ps->data_offset, ps->io, ps->bigendian_data, q, data32s, len)
+ ps->data_offset += (len * sizeof(uint32));
return True;
}
diff --git a/source3/aparser/parser.h b/source3/aparser/parser.h
index 196aa6b855..ec3fc7edc2 100644
--- a/source3/aparser/parser.h
+++ b/source3/aparser/parser.h
@@ -32,39 +32,10 @@ typedef char pstring[1024];
/* zero a structure given a pointer to the structure */
#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }
-typedef struct {
- uint32 low;
- uint32 high;
-} UINT64_S;
-
-typedef struct
-{
- uint32 low;
- uint32 high;
-} NTTIME;
-
#define MAX_UNISTRLEN 256
#define MAX_STRINGLEN 256
#define MAX_BUFFERLEN 512
-/* UNISTR2 - unicode string size (in uint16 unicode chars) and buffer */
-typedef struct unistr2_info
-{
- uint32 uni_max_len;
- uint32 undoc;
- uint32 uni_str_len;
- /* unicode characters. ***MUST*** be little-endian. **NOT** necessarily null-terminated */
- uint16 buffer[MAX_UNISTRLEN];
-
-} UNISTR2;
-
-/* BUFFER5 */
-typedef struct buffer5_info
-{
- uint32 buf_len;
- uint16 *buffer; /* data */
-} BUFFER5;
-
typedef struct _prs_struct
{
BOOL io; /* parsing in or out of data stream */
@@ -86,13 +57,10 @@ BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32);
BOOL prs_init(prs_struct *ps, uint32 size, uint8 align, BOOL io);
void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name);
BOOL prs_align(prs_struct *ps);
-BOOL smb_io_time(char *desc, NTTIME *nttime, prs_struct *ps, int depth);
-BOOL smb_io_unistr2(char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct *ps, int depth);
-BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str);
void print_asc(int level, unsigned char *buf,int len);
BOOL prs_read(prs_struct *ps, int fd, size_t len, int timeout);
void dump_data(int level,char *buf1,int len);
-BOOL prs_uint64(char *name, prs_struct *ps, int depth, UINT64_S *data64);
-BOOL smb_io_buffer5(char *desc, BUFFER5 *buf5, prs_struct *ps, int depth);
BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len);
+BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len);
+BOOL prs_pointer(char *desc, prs_struct *ps, int depth, void **p);
diff --git a/source3/aparser/parsetree.awk b/source3/aparser/parsetree.awk
new file mode 100644
index 0000000000..e0f946a663
--- /dev/null
+++ b/source3/aparser/parsetree.awk
@@ -0,0 +1,64 @@
+# build the parse tree for a struct file
+
+function start_module(name)
+{
+ module=name;
+ num_structs=0;
+}
+
+function start_struct(name)
+{
+ current_struct=num_structs;
+ structs[name]=current_struct;
+ structs[current_struct, "name"]=name;
+ structs[current_struct, "num_elems"]=0;
+ structs[current_struct, "num_unions"]=0;
+}
+
+function end_struct()
+{
+ num_structs++;
+ current_struct="";
+}
+
+function add_elem(type, elem,
+ LOCAL, elem_num)
+{
+ elem_num=structs[current_struct, "num_elems"];
+ structs[current_struct, elem_num, "type"] = type;
+ structs[current_struct, elem_num, "elem"] = elem;
+ structs[current_struct, elem_num, "array_len"] = "";
+ structs[current_struct, "num_elems"]++;
+ return elem_num;
+}
+
+function add_array(array_len, type, elem,
+ LOCAL, elem_num)
+{
+ elem_num=add_elem(type, elem);
+ structs[current_struct, elem_num, "array_len"] = array_len;
+}
+
+function start_union(switch, elem)
+{
+ current_union=elem;
+ add_elem("union", elem);
+ structs[current_struct, "unions", current_union, "switch"] = switch;
+ structs[current_struct, "unions", current_union, "num_elems"] = 0;
+}
+
+function parse_case(value, type, elem,
+ LOCAL, elem_num)
+{
+ elem_num =structs[current_struct, "unions", current_union, "num_elems"];
+ structs[current_struct, "unions", current_union, elem_num, "type"] = type;
+ structs[current_struct, "unions", current_union, elem_num, "elem"] = elem;
+ structs[current_struct, "unions", current_union, elem_num, "value"] = value;
+ structs[current_struct, "unions", current_union, "num_elems"]++;
+}
+
+function end_union()
+{
+ current_union="";
+}
+
diff --git a/source3/aparser/spool.struct b/source3/aparser/spool.struct
new file mode 100644
index 0000000000..319a09941d
--- /dev/null
+++ b/source3/aparser/spool.struct
@@ -0,0 +1,76 @@
+module spool
+test PRINTER_DRIVER_INFO_LEVEL_3
+
+struct BUFFER5 {
+ .align 4;
+ uint32 buf_len;
+ {buf_len} uint16 buffer;
+};
+
+struct UNISTR2 {
+ .align 4;
+ uint32 max_len;
+ uint32 undoc;
+ uint32 str_len;
+ {str_len} uint16 buffer;
+};
+
+struct UINT64_S {
+ uint32 low;
+ uint32 high;
+};
+
+struct NTTIME {
+ uint32 low;
+ uint32 high;
+};
+
+struct PRINTER_DRIVER_INFO_LEVEL_3 {
+ .align 4;
+ uint32 cversion;
+ UNISTR2 *name;
+ UNISTR2 *environment;
+ UNISTR2 *driverpath;
+ UNISTR2 *datafile;
+ UNISTR2 *configfile;
+ UNISTR2 *helpfile;
+ UNISTR2 *monitorname;
+ UNISTR2 *defaultdatatype;
+ uint32 dependentfiles_len;
+ BUFFER5 *dependentfiles;
+};
+
+struct PRINTER_DRIVER_INFO_LEVEL_6 {
+ .align 4;
+ uint32 dummy1;
+ uint32 version;
+ UNISTR2 *name;
+ UNISTR2 *environment;
+ UNISTR2 *driverpath;
+ UNISTR2 *datafile;
+ UNISTR2 *configfile;
+ UNISTR2 *helpfile;
+ UNISTR2 *monitorname;
+ UNISTR2 *defaultdatatype;
+ uint32 dependentfiles_len;
+ BUFFER5 *dependentfiles;
+ uint32 previousnames_len;
+ BUFFER5 *previousnames;
+ NTTIME driverdate;
+ UINT64_S driverversion;
+ uint32 dummy4;
+ UNISTR2 *mfgname;
+ UNISTR2 *oemurl;
+ UNISTR2 *hardwareid;
+ UNISTR2 *provider;
+};
+
+
+struct PRINTER_DRIVER_INFO {
+ .align 4;
+ uint32 level;
+ union level *info {
+ case 3 PRINTER_DRIVER_INFO_LEVEL_3 info_3;
+ case 6 PRINTER_DRIVER_INFO_LEVEL_6 info_6;
+ }
+};
diff --git a/source3/aparser/template.awk b/source3/aparser/template.awk
new file mode 100644
index 0000000000..ddaa604b99
--- /dev/null
+++ b/source3/aparser/template.awk
@@ -0,0 +1,17 @@
+# template file handling
+
+function print_template(f, tplname, v,
+ LOCAL, i, pat, line)
+{
+ if (numlines(tplname) <= 0) fatal("no template "tplname);
+ while ((getline line < tplname) > 0) {
+ while ((i = match(line,"@[a-zA-Z_]*@")) != 0) {
+ pat=substr(line,i+1,RLENGTH-2);
+ if (v[pat] == "") fatal("no value for "pat" in "tplname);
+ gsub("@"pat"@", v[pat], line);
+ }
+
+ xprintf(f, "%s\n", line);
+ }
+ close(tplname);
+}
diff --git a/source3/aparser/templates/fn_end.tpl b/source3/aparser/templates/fn_end.tpl
new file mode 100644
index 0000000000..b5c36fff35
--- /dev/null
+++ b/source3/aparser/templates/fn_end.tpl
@@ -0,0 +1,33 @@
+
+ return True;
+
+fail:
+ ZERO_STRUCTP(il);
+ return False;
+} /* @FUNCNAME@ */
+
+/*******************************************************************
+parse a @STRUCTNAME@ structure
+********************************************************************/
+BOOL @FUNCNAME@_alloc(char *desc, @STRUCTNAME@ **q_u,
+ prs_struct *ps, int depth)
+{
+ @STRUCTNAME@ *il;
+ BOOL ret;
+
+ if (!UNMARSHALLING(ps)) return False;
+
+ il=(@STRUCTNAME@ *)malloc(sizeof(@STRUCTNAME@));
+ if (il == NULL) return False;
+ ZERO_STRUCTP(il);
+
+ ret = @FUNCNAME@(desc, il, ps, depth);
+ if (!ret) {
+ free(il);
+ return False;
+ }
+ *q_u = il;
+ return True;
+}
+
+
diff --git a/source3/aparser/templates/fn_start.tpl b/source3/aparser/templates/fn_start.tpl
new file mode 100644
index 0000000000..deecc670e3
--- /dev/null
+++ b/source3/aparser/templates/fn_start.tpl
@@ -0,0 +1,9 @@
+/*******************************************************************
+parse a @STRUCTNAME@ structure
+********************************************************************/
+BOOL @FUNCNAME@(char *desc, @STRUCTNAME@ *il,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "@FUNCNAME@");
+ depth++;
+
diff --git a/source3/aparser/templates/harness_start.tpl b/source3/aparser/templates/harness_start.tpl
new file mode 100644
index 0000000000..375b110536
--- /dev/null
+++ b/source3/aparser/templates/harness_start.tpl
@@ -0,0 +1,7 @@
+#define TEST_STRUCT @STRUCTNAME@
+#define TEST_NAME "@TEST@"
+#define TEST_FUNC @FUNCNAME@_alloc
+
+
+#include "prs_@MODULE@.h"
+#include "prs_@MODULE@.c"
diff --git a/source3/aparser/templates/ifptr_end.tpl b/source3/aparser/templates/ifptr_end.tpl
new file mode 100644
index 0000000000..990635cf45
--- /dev/null
+++ b/source3/aparser/templates/ifptr_end.tpl
@@ -0,0 +1 @@
+ }
diff --git a/source3/aparser/templates/ifptr_start.tpl b/source3/aparser/templates/ifptr_start.tpl
new file mode 100644
index 0000000000..ffffe49e91
--- /dev/null
+++ b/source3/aparser/templates/ifptr_start.tpl
@@ -0,0 +1 @@
+ if (il->@ELEM@) {
diff --git a/source3/aparser/templates/module_end.tpl b/source3/aparser/templates/module_end.tpl
new file mode 100644
index 0000000000..661f7edb95
--- /dev/null
+++ b/source3/aparser/templates/module_end.tpl
@@ -0,0 +1,3 @@
+
+
+/* end auto-generated structure parsers for @MODULE@ */
diff --git a/source3/aparser/templates/module_start.tpl b/source3/aparser/templates/module_start.tpl
new file mode 100644
index 0000000000..fef9d296ff
--- /dev/null
+++ b/source3/aparser/templates/module_start.tpl
@@ -0,0 +1,5 @@
+/* auto-generated structure parsers for @MODULE@
+ generated by aparser
+*/
+
+
diff --git a/source3/aparser/templates/prs_.align.tpl b/source3/aparser/templates/prs_.align.tpl
new file mode 100644
index 0000000000..d5b2ceb082
--- /dev/null
+++ b/source3/aparser/templates/prs_.align.tpl
@@ -0,0 +1 @@
+ if(!prs_align(ps)) goto fail;
diff --git a/source3/aparser/templates/prs_array.tpl b/source3/aparser/templates/prs_array.tpl
new file mode 100644
index 0000000000..ca707148db
--- /dev/null
+++ b/source3/aparser/templates/prs_array.tpl
@@ -0,0 +1,7 @@
+ if (il->@ARRAYLEN@ > 0) {
+ il->@ELEM@ = (@TYPE@ *)malloc(sizeof(@TYPE@)*il->@ARRAYLEN@);
+ if (!il->@ELEM@) goto fail;
+ if (!prs_@TYPE@s(True, "@ELEM@", ps, depth+1, il->@ELEM@, il->@ARRAYLEN@)) goto fail;
+ } else {
+ il->@ELEM@ = NULL;
+ }
diff --git a/source3/aparser/templates/prs_case.tpl b/source3/aparser/templates/prs_case.tpl
new file mode 100644
index 0000000000..2f81c35828
--- /dev/null
+++ b/source3/aparser/templates/prs_case.tpl
@@ -0,0 +1 @@
+ case @VALUE@:
diff --git a/source3/aparser/templates/prs_case_end.tpl b/source3/aparser/templates/prs_case_end.tpl
new file mode 100644
index 0000000000..eb540f7be8
--- /dev/null
+++ b/source3/aparser/templates/prs_case_end.tpl
@@ -0,0 +1 @@
+ break;
diff --git a/source3/aparser/templates/prs_pointer.tpl b/source3/aparser/templates/prs_pointer.tpl
new file mode 100644
index 0000000000..f268c259bc
--- /dev/null
+++ b/source3/aparser/templates/prs_pointer.tpl
@@ -0,0 +1 @@
+ if (!prs_pointer("@ELEM@_ptr", ps, depth+1, (void **)&il->@ELEM@)) goto fail;
diff --git a/source3/aparser/templates/prs_struct.tpl b/source3/aparser/templates/prs_struct.tpl
new file mode 100644
index 0000000000..ab8246db8e
--- /dev/null
+++ b/source3/aparser/templates/prs_struct.tpl
@@ -0,0 +1 @@
+ if (!@MODULE@_io_@TYPE@("@ELEM@", &il->@ELEM@, ps, depth+1)) goto fail;
diff --git a/source3/aparser/templates/prs_struct_alloc.tpl b/source3/aparser/templates/prs_struct_alloc.tpl
new file mode 100644
index 0000000000..9eae5c92fc
--- /dev/null
+++ b/source3/aparser/templates/prs_struct_alloc.tpl
@@ -0,0 +1 @@
+ if (!@MODULE@_io_@TYPE@_alloc("@ELEM@", &il->@ELEM@, ps, depth+1)) goto fail;
diff --git a/source3/aparser/templates/prs_uint16.tpl b/source3/aparser/templates/prs_uint16.tpl
new file mode 100644
index 0000000000..36b8298fb2
--- /dev/null
+++ b/source3/aparser/templates/prs_uint16.tpl
@@ -0,0 +1 @@
+ if (!prs_uint16("@ELEM@", ps, depth+1, &il->@ELEM@)) goto fail;
diff --git a/source3/aparser/templates/prs_uint32.tpl b/source3/aparser/templates/prs_uint32.tpl
new file mode 100644
index 0000000000..2e2fd638e4
--- /dev/null
+++ b/source3/aparser/templates/prs_uint32.tpl
@@ -0,0 +1 @@
+ if (!prs_uint32("@ELEM@", ps, depth+1, &il->@ELEM@)) goto fail;
diff --git a/source3/aparser/templates/union_end.tpl b/source3/aparser/templates/union_end.tpl
new file mode 100644
index 0000000000..511adbcf60
--- /dev/null
+++ b/source3/aparser/templates/union_end.tpl
@@ -0,0 +1,5 @@
+ default:
+ DEBUG(5,("No handler for case %d in @FUNCNAME@\n",
+ (int)il->@SWITCH@));
+ goto fail;
+ }
diff --git a/source3/aparser/templates/union_start.tpl b/source3/aparser/templates/union_start.tpl
new file mode 100644
index 0000000000..aa052be697
--- /dev/null
+++ b/source3/aparser/templates/union_start.tpl
@@ -0,0 +1 @@
+ switch (il->@SWITCH@) {
diff --git a/source3/aparser/util.awk b/source3/aparser/util.awk
new file mode 100644
index 0000000000..93f9a4dcd2
--- /dev/null
+++ b/source3/aparser/util.awk
@@ -0,0 +1,33 @@
+function isaptr(elem)
+{
+ if (substr(elem, 1, 1) == "*") {
+ return 1;
+ }
+ return 0;
+}
+
+function noptr(elem)
+{
+ if (!isaptr(elem)) return elem;
+ return substr(elem, 2);
+}
+
+function xprintf(f, fmt, v1, v2, v3, v4, v5, v6, v7)
+{
+ printf(fmt, v1, v2, v3, v4, v5, v6) > f;
+}
+
+function fatal(why)
+{
+ printf("FATAL: %s\n", why);
+ exit 1;
+}
+
+function numlines(fname,
+ LOCAL, line, count)
+{
+ count=0;
+ while ((getline line < fname) > 0) count++;
+ close(fname);
+ return count;
+}
diff --git a/source3/aparser/vluke.c b/source3/aparser/vluke.c
index fb7cc36b88..82dbf20036 100644
--- a/source3/aparser/vluke.c
+++ b/source3/aparser/vluke.c
@@ -29,10 +29,10 @@ int main(int argc, char *argv[])
prs_init(&ps, 0, 4, MARSHALL);
ps.is_dynamic=True;
prs_read(&ps, fd, st.st_size, 0);
- dump_data(0, ps.data_p, ps.buffer_size);
ps.data_offset = 0;
ps.io = UNMARSHALL;
ret = TEST_FUNC(desc, &q_u, &ps, 1);
- printf("ret=%d\n", ret);
+ printf("\nret=%s\n\n\n", ret?"OK":"Bad");
+ dump_data(0, ps.data_p, ps.buffer_size);
return !ret;
}