/* * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Högskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include RCSID("$Id: output.c,v 1.3 2000/09/11 14:41:41 art Exp $"); #endif #include #include #include #include #include #include #include "sym.h" #include "output.h" #include "types.h" #include "lex.h" /* * The name of the current package that we're generating stubs for */ char *package = ""; /* * This is the list of packages so we know how to generate * all Execute_package(). */ List *packagelist = NULL; /* * Add this in front of the real functions implementing the server * functions called. */ char *prefix = ""; /* * File handles for the generated files themselves. */ fileblob headerfile, clientfile, serverfile, clienthdrfile, serverhdrfile, td_file, ydrfile; long tmpcnt = 0; /* * Function to convert error codes with. * (the default, the empty string, conveniently means no conversion.) */ char *error_function = ""; typedef enum { ENCODE_RX, DECODE_RX, ENCODE_MEM, DECODE_MEM } EncodeType; typedef enum { CLIENT, SERVER } Side; static void print_type (char *name, Type *type, enum argtype argtype, FILE *f); static Bool print_entry (List *list, Listitem *item, void *i); static void generate_hdr_struct (Symbol *s, FILE *f); static void generate_hdr_enum (Symbol *s, FILE *f); static void generate_hdr_const (Symbol *s, FILE *f); static void generate_hdr_typedef (Symbol *s, FILE *f); static int sizeof_type (Type *type); static int sizeof_symbol (Symbol *); static void encode_type (char *name, Type *type, FILE *f, EncodeType encodetype, Side side); static void display_type (char *where, char *name, Type *type, FILE *f); static Bool encode_entry (List *list, Listitem *item, void *arg); static void encode_struct (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side); static void encode_enum (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side); static void encode_typedef (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side); static void encode_symbol (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side); static void print_symbol (char *where, Symbol *s, char *name, FILE *f); static void print_type (char *name, Type *type, enum argtype argtype, FILE *f) { switch (type->type) { case TCHAR : fprintf (f, "char %s", name); break; case TUCHAR : fprintf (f, "unsigned char %s", name); break; case TSHORT : fprintf (f, "int16_t %s", name); break; case TUSHORT : fprintf (f, "u_int16_t %s", name); break; case TLONG : fprintf (f, "int32_t %s", name); break; case TULONG : fprintf (f, "u_int32_t %s", name); break; case TSTRING : if (type->size) fprintf (f, "char %s[%d]", name, type->size); else if (argtype != TIN) fprintf (f, "char **%s", name); else fprintf (f, "char *%s", name); break; case TPOINTER : { char *tmp; tmp = (char *)emalloc (strlen(name) + 2); *tmp = '*'; strcpy (tmp+1, name); print_type (tmp, type->subtype, argtype, f); free (tmp); break; } case TUSERDEF : if(type->symbol->type == TSTRUCT) fprintf (f, "struct %s %s", type->symbol->name, name); else fprintf (f, "%s %s", type->symbol->name, name); break; case TVARRAY : { char *s; s = (char *)emalloc (strlen (name) + 6); *s = '*'; strcpy (s + 1, name); strcat (s, "_len"); fprintf (f, "struct {\n"); if (type->indextype) print_type ("len", type->indextype, argtype, f); else fprintf (f, "unsigned %s", "len"); fprintf (f, ";\n"); strcpy(s + strlen(s) - 3, "val"); print_type ("*val", type->subtype, argtype, f); fprintf (f, ";\n} %s", name); free(s); break; } case TARRAY : print_type (name, type->subtype, argtype, f); fprintf (f, "[ %d ]", type->size); break; case TOPAQUE : fprintf (f, "char %s", name); break; default : abort(); } } static Bool print_entry (List *list, Listitem *item, void *i) { StructEntry *s = (StructEntry *)listdata (item); FILE *f = (FILE *)i; fprintf (f, " "); print_type (s->name, s->type, TIN, f); fprintf (f, ";\n"); return FALSE; } /* * Return the size of this type in bytes. * In the case of a variable-sized type, return -1. */ static Bool sizeof_struct_iter (List *list, Listitem *item, void *arg) { int *tot = (int *)arg; StructEntry *s = (StructEntry *)listdata (item); int sz; sz = sizeof_type (s->type); if (sz == -1) { *tot = -1; return TRUE; } else { *tot += sz; return FALSE; } } static int sizeof_struct (Symbol *s) { int tot = 0; listiter (s->u.list, sizeof_struct_iter, &tot); return tot; } static int sizeof_type (Type *t) { switch (t->type) { case TCHAR : case TUCHAR : /* return 1;*/ case TSHORT : case TUSHORT : /* return 2;*/ case TLONG : case TULONG : return 4; case TSTRING : if (t->size == 0) return -1; else return t->size; case TOPAQUE : return 1; case TUSERDEF : return sizeof_symbol (t->symbol); case TARRAY : { int sz = sizeof_type (t->subtype); if (sz == -1) return -1; else return t->size * sz; } case TVARRAY : return -1; case TPOINTER : return -1; default : abort (); } } static int sizeof_symbol (Symbol *s) { switch (s->type) { case TUNDEFINED : fprintf (stderr, "What is %s doing in sizeof_type?", s->name); return 0; case TSTRUCT : return sizeof_struct (s); case TENUM : return 4; case TCONST : return 0; case TENUMVAL : return 0; case TTYPEDEF : return sizeof_type (s->u.type); default : abort (); } } /* * Generate header contents */ static void generate_hdr_struct (Symbol *s, FILE *f) { fprintf (f, "struct %s {\n", s->name); if (s->u.list) listiter (s->u.list, print_entry, f); fprintf (f, "};\ntypedef struct %s %s;\n", s->name, s->name); } static void generate_hdr_enum (Symbol *s, FILE *f) { Listitem *item; Symbol *e; fprintf (f, "enum %s {\n", s->name); for (item = listhead (s->u.list); item && listnext (s->u.list, item); item = listnext (s->u.list, item)) { e = (Symbol *)listdata (item); fprintf (f, " %s = %d,\n", e->name, e->u.val); } e = (Symbol *)listdata (item); fprintf (f, " %s = %d\n};\ntypedef enum %s %s;\n", e->name, e->u.val, s->name, s->name); } static void generate_hdr_const (Symbol *s, FILE *f) { fprintf (f, "#define %s %d\n", s->name, s->u.val); } static void generate_hdr_typedef (Symbol *s, FILE *f) { fprintf (f, "typedef "); print_type (s->name, s->u.type, TIN, f); fprintf (f, ";\n"); } void generate_sizeof (Symbol *s, FILE *f) { int sz; if (s->type == TCONST) return; sz = sizeof_symbol (s); if (sz != -1) { char *name; name = estrdup (s->name); fprintf (f, "#define %s_SIZE %d\n", strupr (name), sz); free (name); } } void generate_header (Symbol *s, FILE *f) { switch (s->type) { case TUNDEFINED : fprintf (f, "What is %s doing in generate_header?", s->name); break; case TSTRUCT : generate_hdr_struct (s, f); break; case TENUM : generate_hdr_enum (s, f); break; case TCONST : generate_hdr_const (s, f); break; case TENUMVAL : break; case TTYPEDEF : generate_hdr_typedef (s, f); default : break; } putc ('\n', f); } /* * Generate functions for encoding and decoding. */ /* XXX - still assumes that a word is 32 bits */ static char * encode_function (Type *type, EncodeType encodetype) { if (type->flags & TASIS) return ""; else if (encodetype == ENCODE_RX || encodetype == ENCODE_MEM) return "htonl"; #if 0 if (type->type == TSHORT || type->type == TUSHORT) return "htons"; else if (type->type == TLONG || type->type == TULONG) return "htonl"; else abort(); #endif else if (encodetype == DECODE_RX || encodetype == DECODE_MEM) return "ntohl"; #if 0 if (type->type == TSHORT || type->type == TUSHORT) return "ntohs"; else if (type->type == TLONG || type->type == TULONG) return "ntohl"; else abort(); #endif else abort(); } /* * encode/decode long */ static void encode_long (char *name, Type *type, FILE *f, EncodeType encodetype) { switch (encodetype) { case ENCODE_RX : fprintf (f, "{ u_int32_t u;\n" "u = %s (%s);\n" "if(rx_Write(call, &u, sizeof(u)) != sizeof(u))\n" "goto fail;\n" "}\n", encode_function (type, encodetype), name); break; case DECODE_RX : fprintf (f, "{ u_int32_t u;\n" "if(rx_Read(call, &u, sizeof(u)) != sizeof(u))\n" "goto fail;\n" "%s = %s (u);\n" "}\n", name, encode_function (type, encodetype)); break; case ENCODE_MEM : fprintf (f, "{ int32_t tmp = %s(%s); " "if (*total_len < sizeof(int32_t)) goto fail;\n" "bcopy ((char*)&tmp, ptr, sizeof(int32_t)); " "ptr += sizeof(int32_t); " "*total_len -= sizeof(int32_t);}\n", encode_function (type, encodetype), name); break; case DECODE_MEM : fprintf (f, "{ int32_t tmp; " "if (*total_len < sizeof(int32_t)) goto fail;" "bcopy (ptr, (char *)&tmp, sizeof(int32_t)); " "%s = %s(tmp); " "ptr += sizeof(int32_t); " "*total_len -= sizeof(int32_t);}\n", name, encode_function (type, encodetype)); break; default : abort (); } } /* * print long */ static void print_long (char *where, char *name, Type *type, FILE *f) { fprintf (f, "printf(\" %s = %%d\", %s%s);", name, where, name); } /* * */ static void __attribute__ ((unused)) encode_char (char *name, Type *type, FILE *f, EncodeType encodetype) { switch (encodetype) { case ENCODE_RX : fprintf (f, "if(rx_Write(call, &%s, sizeof(%s)) != sizeof(%s))\n" "goto fail;\n", name, name, name); break; case DECODE_RX : fprintf (f, "if(rx_Read(call, &%s, sizeof(%s)) != sizeof(%s))\n" "goto fail;\n", name, name, name); break; case ENCODE_MEM : fprintf (f, "{ if (*total_len < sizeof(char)) goto fail;\n" "*((char *)ptr) = %s; " "ptr += sizeof(char); *total_len -= sizeof(char);}\n", name); break; case DECODE_MEM : fprintf (f, "{ if (*total_len < sizeof(char)) goto fail;\n" "%s = *((char *)ptr); " "ptr += sizeof(char); *total_len -= sizeof(char);}\n", name); break; default : abort (); } } static void __attribute__ ((unused)) encode_short (char *name, Type *type, FILE *f, EncodeType encodetype) { switch (encodetype) { case ENCODE_RX : fprintf (f, "{ int16_t u;\n" "u = %s (%s);\n" "if(rx_Write(call, &u, sizeof(u)) != sizeof(u))\n" "goto fail;\n" "}\n", encode_function (type, encodetype), name); break; case DECODE_RX : fprintf (f, "{ int16_t u;\n" "if(rx_Read(call, &u, sizeof(u)) != sizeof(u))\n" "goto fail;\n" "%s = %s (u);\n" "}\n", name, encode_function (type, encodetype)); break; case ENCODE_MEM : fprintf (f, "{ in16_t tmp = %s(%s); " "if (*total_len < sizeof(int16_t)) goto fail;\n" "bcopy ((char*)&tmp, ptr, sizeof(int16_t)); " "ptr += sizeof(int16_t); " "*total_len -= sizeof(int16_t);}\n", encode_function (type, encodetype), name); break; case DECODE_MEM : fprintf (f, "{ int16_t tmp; " "if (*total_len < sizeof(int16_t)) goto fail;\n" "bcopy (ptr, (char *)&tmp, sizeof(int16_t)); " "%s = %s(tmp); " "ptr += sizeof(int16_t); " "*total_len -= sizeof(int16_t); }\n", name, encode_function (type, encodetype)); break; default : abort (); } } /* * encode/decode TSTRING */ static void encode_string (char *name, Type *type, FILE *f, EncodeType encodetype, Side side) { Type lentype = {TULONG}; char *nname; asprintf (&nname, "(%s%s)", (type->size == 0) && side == CLIENT ? "*" : "", name); switch (encodetype) { case ENCODE_RX : fprintf (f, "{ unsigned len;\n" "char zero[4] = {0, 0, 0, 0};\n" "unsigned padlen;\n" "len = strlen(%s);\n" "padlen = (4 - (len %% 4)) %% 4;\n", name); encode_type ("len", &lentype, f, encodetype, side); fprintf (f, "if(rx_Write(call, %s, len) != len)\n" "goto fail;\n" "if(rx_Write(call, zero, padlen) != padlen)\n" "goto fail;\n" "}\n", name); break; case DECODE_RX : fprintf (f, "{ unsigned len;\n" "unsigned padlen;\n" "char zero[4] = {0, 0, 0, 0};\n"); encode_type ("len", &lentype, f, encodetype, side); if (type->size != 0) { fprintf (f, "if (len >= %u) {\n" "rx_Error(call) = ENOMEM;\n" "goto fail;\n" "}\n", type->size); } else { fprintf(f, "%s = malloc(len + 1);\n", nname); } fprintf (f, "if(rx_Read(call, %s, len) != len)\n" "goto fail;\n" "%s[len] = '\\0';\n" "padlen = (4 - (len %% 4)) %% 4;\n" "if(rx_Read(call, zero, padlen) != padlen)\n" "goto fail;\n" "}\n", nname, nname); break; case ENCODE_MEM : fprintf (f, "{\nunsigned len = strlen(%s);\n" "if (*total_len < len) goto fail;\n" "*total_len -= len;\n", name); encode_type ("len", &lentype, f, encodetype, side); fprintf (f, "strncpy (ptr, %s, len);\n", name); fprintf (f, "ptr += len + (4 - (len %% 4) %% 4);\n" "*total_len -= len + (4 - (len %% 4) %% 4);\n}\n"); break; case DECODE_MEM : fprintf (f, "{\nunsigned len;\n"); encode_type ("len", &lentype, f, encodetype, side); fprintf (f, "if (*total_len < len) goto fail;\n" "*total_len -= len;\n"); if (type->size != 0) { fprintf (f, "if(len >= %u)\n" "goto fail;\n", type->size); } else { fprintf (f, "%s = malloc(len + 1);\n", nname); } fprintf (f, "memcpy (%s, ptr, len);\n" "%s[len] = '\\0';\n" "ptr += len + (4 - (len %% 4)) %% 4;\n" "*total_len -= len + (4 - (len %% 4) %% 4);\n}\n", nname, nname); break; default : abort (); } free (nname); } /* * print TSTRING */ static void print_string (char *where, char *name, Type *type, FILE *f) { fprintf (f, "/* printing TSTRING %s%s */\n", where, name); fprintf (f, "printf(\" %s = %%s\", %s%s);", name, where, name); } /* * encode/decode TARRAY */ static void encode_array (char *name, Type *type, FILE *f, EncodeType encodetype, Side side) { if (type->subtype->type == TOPAQUE) { if (type->size % 4 != 0) error_message (1, "Opaque array should be" "multiple of 4"); switch (encodetype) { case ENCODE_RX : fprintf (f, "if(rx_Write (call, %s, %d) != %d)\n" "goto fail;", name, type->size, type->size); break; case DECODE_RX : fprintf (f, "if(rx_Read (call, %s, %d) != %d)\n" "goto fail;", name, type->size, type->size); break; case ENCODE_MEM : fprintf (f, "if (*total_len < %u) goto fail;\n" "memcpy (ptr, %s, %u);\n", type->size, name, type->size); fprintf (f, "ptr += %u; *total_len -= %u;\n", type->size, type->size); break; case DECODE_MEM : fprintf (f, "if (*total_len < %u) goto fail;" "memcpy (%s, ptr, %u);\n", type->size, name, type->size); fprintf (f, "ptr += %u; *total_len -= %u;\n", type->size, type->size); break; default : abort (); } } else { char tmp[256]; fprintf (f, "{\nint i%lu;\nfor(i%lu = 0; i%lu < %u;" "++i%lu){\n", tmpcnt, tmpcnt, tmpcnt, type->size,tmpcnt); snprintf(tmp, sizeof(tmp)-1, "%s[i%lu]", name, tmpcnt); tmpcnt++; if (type->flags) type->subtype->flags |= type->flags; encode_type (tmp , type->subtype, f, encodetype, side); tmpcnt--; fprintf (f, "}\n}\n"); } } /* * encode/decode TARRAY */ static void print_array (char *where, char *name, Type *type, FILE *f) { fprintf (f, "{\nunsigned int i%lu;\n", tmpcnt); fprintf (f, "/* printing ARRAY %s%s */\n", where, name); if (type->subtype->type == TOPAQUE) { if (type->size % 4 != 0) error_message (1, "print_array: Opaque array should be" "multiple of 4"); fprintf (f, "char *ptr = %s%s;\n", where, name); fprintf (f, "printf(\"0x\");"); fprintf (f, "for (i%lu = 0; i%lu < %d; ++i%lu)\n" "printf(\"%%x\", ptr[i%lu]);", tmpcnt, tmpcnt, type->size, tmpcnt, tmpcnt); } else { char *ptr; fprintf (f, "for (i%lu = 0; i%lu < %d; ++i%lu) {\n", tmpcnt, tmpcnt, type->size, tmpcnt); asprintf(&ptr, "%s%s[i%ld]", where, name, tmpcnt); tmpcnt++; display_type (ptr, "", type->subtype, f); tmpcnt--; free(ptr); fprintf (f, "\nif (i%lu != %d - 1) printf(\",\");\n", tmpcnt, type->size); fprintf (f, "}\n"); } fprintf (f, "}\n"); } /* * encode/decode TVARRAY */ static void encode_varray (char *name, Type *type, FILE *f, EncodeType encodetype, Side side) { char tmp[256]; Type lentype = {TULONG}; strcpy (tmp, name); strcat (tmp, ".len"); encode_type (tmp, type->indextype ? type->indextype : &lentype, f, encodetype, side); if (encodetype == DECODE_MEM || encodetype == DECODE_RX) { fprintf (f, "%s.val = (", name); print_type ("*", type->subtype, TIN, f); fprintf (f, ")malloc(sizeof("); print_type ("", type->subtype, TIN, f); fprintf (f, ") * %s);\n", tmp); } if (type->subtype->type == TOPAQUE) { switch (encodetype) { case ENCODE_RX : fprintf (f, "{\n" "char zero[4] = {0, 0, 0, 0};\n" "unsigned padlen = (4 - (%s %% 4)) %% 4;\n" "if(rx_Write (call, %s.val, %s) != %s)\n" "goto fail;\n" "if(rx_Write (call, zero, padlen) != padlen)\n" "goto fail;\n" "}\n", tmp, name, tmp, tmp); break; case DECODE_RX : fprintf (f, "{\n" "char zero[4] = {0, 0, 0, 0};\n" "unsigned padlen = (4 - (%s %% 4)) %% 4;\n" "if(rx_Read (call, %s.val, %s) != %s)\n" "goto fail;\n" "if(rx_Read (call, zero, padlen) != padlen)\n" "goto fail;\n" "}\n", tmp, name, tmp, tmp); break; case ENCODE_MEM : /* XXX bounce checking */ fprintf (f, "{\n" "char zero[4] = {0, 0, 0, 0};\n" "memcpy (ptr, %s.val, %s);\n" "memcpy (ptr + %s, zero, (4 - (%s %% 4)) %% 4);\n" "ptr += %s + (4 - (%s %% 4)) %% 4;\n" "}\n", name, tmp, tmp, tmp, tmp, tmp); break; case DECODE_MEM : /* XXX bounce checking */ fprintf (f, "{\n" "memcpy (%s.val, ptr, %s);\n" "ptr += %s + (4 - (%s %% 4)) %% 4;\n" "}\n", name, tmp, tmp, tmp); break; default : abort (); } } else { fprintf (f, "{\nint i%lu;\nfor(i%lu = 0; i%lu < %s;" "++i%lu){\n", tmpcnt, tmpcnt, tmpcnt, tmp, tmpcnt); snprintf(tmp, sizeof(tmp)-1, "%s.val[i%lu]", name, tmpcnt); tmpcnt++; if (type->flags) type->subtype->flags |= type->flags; encode_type (tmp , type->subtype, f, encodetype, side); tmpcnt--; fprintf (f, "}\n}\n"); } } /* * print TVARRAY */ static void print_varray (char *where, char *name, Type *type, FILE *f) { fprintf (f, "{\nunsigned int i%lu;\n", tmpcnt); fprintf (f, "/* printing TVARRAY %s%s */\n", where, name); if (type->subtype->type == TOPAQUE) { fprintf (f, "char *ptr = %s%s.val;\n", where, name); fprintf (f, "printf(\"0x\");"); fprintf (f, "for (i%lu = 0; i%lu < %s%s.len; ++i%lu)\n" "printf(\"%%x\", ptr[i%lu]);", tmpcnt, tmpcnt, where, name, tmpcnt, tmpcnt); } else { char *ptr; fprintf (f, "for (i%lu = 0; i%lu < %s%s.len; ++i%lu) {\n", tmpcnt, tmpcnt, where, name, tmpcnt); asprintf(&ptr, "%s%s.val[i%ld]", where, name, tmpcnt); tmpcnt++; display_type (ptr, "", type->subtype, f); tmpcnt--; free(ptr); fprintf (f, "\nif (i%lu != %s%s.len - 1) printf(\",\");\n", tmpcnt, where, name); fprintf (f, "}\n"); } fprintf (f, "}\n"); } /* * encode/decode pointer */ static void encode_pointer (char *name, Type *type, FILE *f, EncodeType encodetype, Side side) { Type booltype = {TULONG}; char tmp[256]; sprintf (tmp, "*(%s)", name); switch(encodetype) { case ENCODE_RX: abort (); case ENCODE_MEM: fprintf(f, "{ unsigned bool;\n" "bool = %s != NULL;\n", name); encode_type ("bool", &booltype, f, encodetype, side); fprintf (f, "if(%s) {\n", name); encode_type (tmp, type->subtype, f, encodetype, side); fprintf (f, "}\n" "}\n"); break; case DECODE_RX: abort(); case DECODE_MEM: fprintf(f, "{ unsigned bool;\n"); encode_type ("bool", &booltype, f, encodetype, side); fprintf (f, "if(bool) {\n"); fprintf (f, "%s = malloc(sizeof(%s));\n" "if (%s == NULL) return ENOMEM;\n", name, tmp, name); encode_type (tmp, type->subtype, f, encodetype, side); fprintf (f, "} else {\n" "%s = NULL;\n" "}\n" "}\n", name); break; default: abort (); } } /* * encode type */ static void encode_type (char *name, Type *type, FILE *f, EncodeType encodetype, Side side) { switch (type->type) { case TCHAR : case TUCHAR : #if 0 encode_char (name, type, f, encodetype); break; #endif case TSHORT : case TUSHORT : #if 0 encode_short (name, type, f, encodetype); break; #endif case TLONG : case TULONG : encode_long (name, type, f, encodetype); break; case TSTRING : encode_string (name, type, f, encodetype, side); break; case TOPAQUE : error_message (1, "Type opaque only allowed as part of an array"); break; case TUSERDEF : encode_symbol (type->symbol, name, f, encodetype, side); break; case TARRAY : encode_array (name, type, f, encodetype, side); break; case TVARRAY : encode_varray (name, type, f, encodetype, side); break; case TPOINTER : encode_pointer (name, type, f, encodetype, side); break; default : abort(); } } /* * print type */ static void display_type (char *where, char *name, Type *type, FILE *f) { assert (where); switch (type->type) { case TCHAR : case TUCHAR : #if 0 print_char (name, type, f, encodetype); break; #endif case TSHORT : case TUSHORT : #if 0 print_short (name, type, f, encodetype); break; #endif case TLONG : case TULONG : print_long (where, name, type, f); break; case TSTRING : print_string (where, name, type, f); break; case TOPAQUE : fprintf (f, "printf(\"printing TOPAQUE\\n\");"); break; case TUSERDEF : print_symbol (where, type->symbol, name, f); break; case TARRAY : print_array (where, name, type, f); break; case TVARRAY : print_varray (where, name, type, f); break; case TPOINTER : fprintf (f, "printf(\"printing TPOINTER\\n\");"); break; default : abort(); } } struct context { char *name; FILE *f; Symbol *symbol; EncodeType encodetype; Side side; }; /* * helpfunction for encode_struct */ static Bool encode_entry (List *list, Listitem *item, void *arg) { StructEntry *s = (StructEntry *)listdata (item); char tmp[256]; struct context *context = (struct context *)arg; strcpy (tmp, context->name); strcat (tmp, "."); strcat (tmp, s->name); if (s->type->type == TPOINTER && s->type->subtype->type == TUSERDEF && s->type->subtype->symbol->type == TSTRUCT && strcmp(s->type->subtype->symbol->name, context->symbol->name) == 0) { fprintf (context->f, "ptr = ydr_encode_%s(%s, ptr);\n", context->symbol->name, tmp); } else { encode_type (tmp, s->type, context->f, context->encodetype, context->side); } return FALSE; } /* * encode/decode TSTRUCT */ static void encode_struct (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side) { struct context context; context.name = name; context.symbol = s; context.f = f; context.encodetype = encodetype; context.side = side; listiter (s->u.list, encode_entry, (void *)&context); } /* * help function for print_struct */ struct printcontext { char *where; char *name; FILE *f; Symbol *symbol; }; static Bool print_structentry (List *list, Listitem *item, void *arg) { StructEntry *s = (StructEntry *)listdata (item); struct printcontext *context = (struct printcontext *)arg; char *tmp; char *tmp2; asprintf(&tmp, ".%s", s->name); asprintf(&tmp2, "%s%s", context->where, context->name); if (s->type->type == TPOINTER && s->type->subtype->type == TUSERDEF && s->type->subtype->symbol->type == TSTRUCT && strcmp(s->type->subtype->symbol->name, context->symbol->name) == 0) { fprintf (context->f, "ydr_print_%s%s(%s%s, ptr);\n", package, context->symbol->name, tmp2, tmp); } else { display_type (tmp2, tmp, s->type, context->f); } free(tmp); free(tmp2); fprintf (context->f, "\n"); return FALSE; } /* * print TSTRUCT */ static void print_struct (char *where, Symbol *s, char *name, FILE *f) { struct printcontext context; context.name = name; context.symbol = s; context.f = f; context.where = where ; fprintf (f, "/* printing TSTRUCT %s%s */\n", where, name); listiter (s->u.list, print_structentry, (void *)&context); } /* * encode/decode TENUM */ static void encode_enum (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side) { Type type = {TLONG}; encode_type (name, &type, f, encodetype, side); } /* * print TENUM */ static Bool gen_printenum (List *list, Listitem *item, void *arg) { Symbol *s = (Symbol *)listdata (item); FILE *f = (FILE *)arg; fprintf (f, "case %d:\n" "printf(\"%s\");\n" "break;\n", (int) s->u.val, s->name); return FALSE; } static void print_enum (char *where, Symbol *s, char *name, FILE *f) { fprintf (f, "/* print ENUM %s */\n", where); fprintf (f, "printf(\"%s = \");", name); fprintf (f, "switch(%s) {\n", where); listiter (s->u.list, gen_printenum, f); fprintf (f, "default:\n" "printf(\" unknown enum %%d\", %s);\n" "}\n", where); } /* * encode/decode TTYPEDEF */ static void encode_typedef (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side) { encode_type (name, s->u.type, f, encodetype, side); } /* * print TTYPEDEF */ static void print_typedef (char *where, Symbol *s, char *name, FILE *f) { display_type (where, name, s->u.type, f); } /* * Encode symbol/TUSERDEF */ static void encode_symbol (Symbol *s, char *name, FILE *f, EncodeType encodetype, Side side) { switch (s->type) { case TSTRUCT : encode_struct (s, name, f, encodetype, side); break; case TENUM : encode_enum (s, name, f, encodetype, side); break; case TTYPEDEF : encode_typedef (s, name, f, encodetype, side); break; default : abort(); } } /* * print symbol/TUSERDEF */ static void print_symbol (char *where, Symbol *s, char *name, FILE *f) { switch (s->type) { case TSTRUCT : print_struct (where, s, name, f); break; case TENUM : print_enum (where, s, name, f); break; case TTYPEDEF : print_typedef (where, s, name, f); break; default : abort(); } } /* * Generate the definition of an encode/decode function. */ static void generate_function_definition (Symbol *s, FILE *f, Bool encodep) { if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) { fprintf (f, "char *ydr_%scode_%s(%s *o, char *ptr, size_t *total_len)", encodep ? "en" : "de", s->name, s->name); } else if (s->type == TCONST || s->type == TENUMVAL || s->type == TTYPEDEF) ; else error_message (1, "What is %s (type %d) doing here?\n", s->name, s->type); } /* * Generate the definition of a print function. */ static void generate_printfunction_definition (Symbol *s, FILE *f) { if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) { fprintf (f, "void ydr_print_%s(%s *o)", s->name, s->name); } else if (s->type == TCONST || s->type == TENUMVAL || s->type == TTYPEDEF) ; else error_message (1, "What is %s (type %d) doing here?\n", s->name, s->type); } /* * Generate an encode/decode function */ void generate_function (Symbol *s, FILE *f, Bool encodep) { if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) { generate_function_definition (s, f, encodep); fprintf (f, "\n{\n"); encode_symbol (s, "(*o)", f, encodep ? ENCODE_MEM : DECODE_MEM, CLIENT); fprintf (f, "return ptr;\n" "fail:\n" "errno = EFAULT;\n" "return NULL;}\n"); } else if (s->type == TCONST || s->type == TENUMVAL || s->type == TTYPEDEF) ; else error_message (1, "What is %s (type %d) doing here?\n", s->name, s->type); } /* * Generate a print function */ void generate_printfunction (Symbol *s, FILE *f) { if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) { generate_printfunction_definition (s, f); fprintf (f, "\n{\n"); print_symbol ("(*o)", s, "", f); fprintf (f, "return;\n}\n"); } else if (s->type == TCONST || s->type == TENUMVAL || s->type == TTYPEDEF) ; else error_message (1, "What is %s (type %d) doing here?\n", s->name, s->type); } /* * Generate an prototype for an encode/decode function */ void generate_function_prototype (Symbol *s, FILE *f, Bool encodep) { if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) { generate_function_definition (s, f, encodep); fprintf (f, ";\n"); } else if (s->type == TCONST || s->type == TENUMVAL || s->type == TTYPEDEF) ; else error_message (1, "What is %s (type %d) doing here?\n", s->name, s->type); } /* * Generate an prototype for a print function */ void generate_printfunction_prototype (Symbol *s, FILE *f) { if (s->type == TSTRUCT || s->type == TENUM || s->type == TTYPEDEF) { generate_printfunction_definition (s, f); fprintf (f, ";\n"); } else if (s->type == TCONST || s->type == TENUMVAL || s->type == TTYPEDEF) ; else error_message (1, "What is %s (type %d) doing here?\n", s->name, s->type); } static Bool gen1 (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if ((a->argtype == TOUT || a->argtype == TINOUT) && a->type->type != TPOINTER && a->type->type != TSTRING) error_message (1, "Argument %s is OUT and not pointer or string.\n", a->name); fprintf (f, ", "); if (a->argtype == TIN) fprintf (f, "const "); print_type (a->name, a->type, a->argtype, f); fprintf (f, "\n"); return FALSE; } static Bool genin (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->argtype == TIN || a->argtype == TINOUT) { fprintf (f, ", %s ", a->argtype == TIN ? "const" : ""); print_type (a->name, a->type, a->argtype, f); fprintf (f, "\n"); } return FALSE; } static Bool genout (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); if (a->argtype == TOUT || a->argtype == TINOUT) return gen1 (list, item, arg); else return FALSE; } static Bool gendeclare (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->type->type == TPOINTER) print_type (a->name, a->type->subtype, TIN, f); else print_type (a->name, a->type, TIN, f); fprintf (f, ";\n"); return FALSE; } static Bool genfree_isarrayp(Type *type) { if (type->type == TVARRAY) return TRUE; if (type->type == TPOINTER) return genfree_isarrayp(type->subtype); if (type->type == TUSERDEF && type->symbol && type->symbol->type == TTYPEDEF) return genfree_isarrayp(type->symbol->u.type); return FALSE; } static Bool genfree (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (genfree_isarrayp(a->type)) fprintf(f, "free(%s.val);\n", a->name); else if (a->argtype != TIN && a->type->type == TSTRING && a->type->size == 0) fprintf (f, "free(%s);\n", a->name); return FALSE; } static Bool genencodein (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->argtype != TIN && a->argtype != TINOUT) return TRUE; else { if (a->type->type == TPOINTER) { char *tmp = (char *)emalloc (strlen (a->name) + 4); sprintf (tmp, "(*%s)", a->name); encode_type (tmp, a->type->subtype, f, ENCODE_RX, CLIENT); free (tmp); } else encode_type (a->name, a->type, f, ENCODE_RX, CLIENT); return FALSE; } } static Bool gendecodeout (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->argtype == TOUT || a->argtype == TINOUT) { if (a->type->type == TPOINTER) { char *tmp = (char *)emalloc (strlen (a->name) + 4); sprintf (tmp, "(*%s)", a->name); encode_type (tmp, a->type->subtype, f, DECODE_RX, CLIENT); free (tmp); } else if(a->type->type == TSTRING) { encode_type (a->name, a->type, f, DECODE_RX, CLIENT); } } return FALSE; } static Bool gendecodein (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->argtype != TIN && a->argtype != TINOUT) return TRUE; else { if (a->type->type == TPOINTER) { #if 0 char *tmp = (char *)emalloc (strlen (a->name) + 4); sprintf (tmp, "(*%s)", a->name); encode_type (tmp, a->type->subtype, f, DECODE_RX, SERVER); free (tmp); #endif encode_type (a->name, a->type->subtype, f, DECODE_RX, SERVER); } else encode_type (a->name, a->type, f, DECODE_RX, SERVER); return FALSE; } } static Bool genencodeout (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->argtype == TOUT || a->argtype == TINOUT) { if (a->type->type == TPOINTER) encode_type (a->name, a->type->subtype, f, ENCODE_RX, SERVER); else encode_type (a->name, a->type, f, ENCODE_RX, SERVER); } return FALSE; } static Bool findargtypeiter (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); int *type = (int *)arg; if (a->argtype == *type) { (*type)++; return TRUE; } return FALSE; } static Bool findargtype(List *list, int type) { int savedtype = type; listiter(list, findargtypeiter, &type); if (type != savedtype) return TRUE; return FALSE; } static Bool genargs (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->type->type == TPOINTER || (a->argtype != TIN && a->type->type == TSTRING && a->type->size == 0)) putc ('&', f); fputs (a->name, f); if (listnext (list, item)) fprintf (f, ", "); return FALSE; } /* * Generate the stub functions for this RPC call */ static void generate_simple_stub (Symbol *s, FILE *f, FILE *headerf) { Type type = {TLONG}; char *op; fprintf (headerf, "int %s%s(\nstruct rx_connection *connection\n", package, s->name); listiter (s->u.proc.arguments, gen1, headerf); fprintf (headerf, ");\n\n"); fprintf (f, "int %s%s(\nstruct rx_connection *connection\n", package, s->name); listiter (s->u.proc.arguments, gen1, f); fprintf (f, ")\n{\n" "struct rx_call *call;\n" "int ret = 0;\n" "call = rx_NewCall (connection);\n"); asprintf (&op, "%u", s->u.proc.id); encode_type (op, &type, f, ENCODE_RX, CLIENT); free (op); listiter (s->u.proc.arguments, genencodein, f); listiter (s->u.proc.arguments, gendecodeout, f); fprintf (f, "return %s(rx_EndCall (call,0));\n" "fail:\n" "ret = %s(rx_Error(call));\n" "rx_EndCall (call, 0);\n" "return ret;\n" "}\n", error_function, error_function); } static void generate_split_stub (Symbol *s, FILE *f, FILE *headerf) { Type type = {TLONG}; char *op; fprintf (headerf, "int Start%s%s(\nstruct rx_call *call\n", package, s->name); listiter (s->u.proc.arguments, genin, headerf); fprintf (headerf, ");\n\n"); fprintf (f, "int Start%s%s(\nstruct rx_call *call\n", package, s->name); listiter (s->u.proc.arguments, genin, f); fprintf (f, ")\n{\n"); asprintf (&op, "%u", s->u.proc.id); encode_type (op, &type, f, ENCODE_RX, CLIENT); free (op); listiter (s->u.proc.arguments, genencodein, f); fprintf (f, "return 0;\n"); /* XXX only in arg */ if (findargtype(s->u.proc.arguments, TIN) || findargtype(s->u.proc.arguments, TINOUT)) fprintf (f, "fail:\n" "return %s(rx_Error(call));\n", error_function); fprintf (f, "}\n\n"); fprintf (headerf, "int End%s%s(\nstruct rx_call *call\n", package, s->name); listiter (s->u.proc.arguments, genout, headerf); fprintf (headerf, ");\n\n"); fprintf (f, "int End%s%s(\nstruct rx_call *call\n", package, s->name); listiter (s->u.proc.arguments, genout, f); fprintf (f, ")\n{\n"); listiter (s->u.proc.arguments, gendecodeout, f); fprintf (f, "return 0;\n"); /* XXX only out arg */ if (findargtype(s->u.proc.arguments, TOUT) || findargtype(s->u.proc.arguments, TINOUT)) fprintf (f, "fail:\n" "return %s(rx_Error(call));\n", error_function); fprintf (f, "}\n\n"); } struct gen_args { FILE *f; int firstp; int arg_type; }; static Bool genmacro (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); struct gen_args *args = (struct gen_args *)arg; if (a->argtype == args->arg_type || a->argtype == TINOUT) { fprintf (args->f, "%s%s", args->firstp ? "" : ", ", a->name); args->firstp = 0; } return FALSE; } static void generate_multi (Symbol *s, FILE *f) { struct gen_args gen_args; fprintf (f, "\n#include "); fprintf (f, "\n#define multi_%s%s(", package, s->name); gen_args.f = f; gen_args.firstp = 1; gen_args.arg_type = TIN; listiter (s->u.proc.arguments, genmacro, &gen_args); fprintf (f, ") multi_Body("); fprintf (f, "Start%s%s(multi_call", package, s->name); gen_args.f = f; gen_args.firstp = 0; gen_args.arg_type = TIN; listiter (s->u.proc.arguments, genmacro, &gen_args); fprintf (f, "), End%s%s(multi_call", package, s->name); gen_args.f = f; gen_args.firstp = 0; gen_args.arg_type = TOUT; listiter (s->u.proc.arguments, genmacro, f); fprintf (f, "))\n"); } void generate_client_stub (Symbol *s, FILE *f, FILE *headerf) { if (s->u.proc.flags & TSPLIT) generate_split_stub (s, f, headerf); if (s->u.proc.flags & TSIMPLE) generate_simple_stub (s, f, headerf); } /* * A list of all the functions that are to be recognized by the * server, later used in generate_server_switch. */ static List *func_list; static void generate_standard_c_prologue (FILE *f, const char *filename, const char *basename) { fprintf (f, "/* Generated from %s.xg */\n", basename); fprintf (f, "#include \"%s.h\"\n\n", basename); fprintf (f, "#include \n"); fprintf (f, "#include \n"); fprintf (f, "#include \n"); fprintf (f, "#include \n"); fprintf (f, "#include \n"); fprintf (f, "#ifndef HAVE_BCOPY\n" "#define bcopy(a,b,c) memcpy((b),(a),(c))\n" "#endif /* !HAVE_BCOPY */\n\n"); fprintf (f, "#ifdef RCSID\n" "RCSID(\"%s generated from %s.xg with $Id: output.c,v 1.3 2000/09/11 14:41:41 art Exp $\");\n" "#endif\n\n", filename, basename); } /* * open all files */ void init_generate (const char *filename) { char *tmp; char *fileuppr; func_list = listnew (); asprintf (&tmp, "%s.h", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &headerfile); free (tmp); fileuppr = estrdup (filename); strupr (fileuppr); fprintf (headerfile.stream, "/* Generated from %s.xg */\n", filename); fprintf (headerfile.stream, "#ifndef _%s_\n" "#define _%s_\n\n", fileuppr, fileuppr); fprintf (headerfile.stream, "#include \n\n"); free (fileuppr); asprintf (&tmp, "%s.ydr.c", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &ydrfile); generate_standard_c_prologue (ydrfile.stream, tmp, filename); free (tmp); asprintf (&tmp, "%s.cs.c", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &clientfile); generate_standard_c_prologue (clientfile.stream, tmp, filename); fprintf (clientfile.stream, "#include \"%s.cs.h\"\n\n", filename); free (tmp); asprintf (&tmp, "%s.ss.c", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &serverfile); generate_standard_c_prologue (serverfile.stream, tmp, filename); fprintf (serverfile.stream, "#include \"%s.ss.h\"\n\n", filename); free (tmp); asprintf (&tmp, "%s.cs.h", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &clienthdrfile); free (tmp); fprintf (clienthdrfile.stream, "/* Generated from %s.xg */\n", filename); fprintf (clienthdrfile.stream, "#include \n"); fprintf (clienthdrfile.stream, "#include \"%s.h\"\n\n", filename); asprintf (&tmp, "%s.ss.h", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &serverhdrfile); free (tmp); fprintf (serverhdrfile.stream, "/* Generated from %s.xg */\n", filename); fprintf (serverhdrfile.stream, "#include \n"); fprintf (serverhdrfile.stream, "#include \"%s.h\"\n\n", filename); asprintf (&tmp, "%s.td.c", filename); if (tmp == NULL) err (1, "malloc"); eefopen (tmp, "w", &td_file); free (tmp); packagelist = listnew(); if (packagelist == NULL) err (1, "init_generate: listnew: packagelist"); } void close_generator (const char *filename) { char *fileupr = estrdup (filename); strupr (fileupr); fprintf (headerfile.stream, "\n#endif /* %s */\n", fileupr); eefclose (&headerfile); eefclose (&clientfile); eefclose (&serverfile); eefclose (&clienthdrfile); eefclose (&serverhdrfile); eefclose (&ydrfile); eefclose (&td_file); } /* * Generate the server-side stub function for the function in s and * write it to the file f. */ void generate_server_stub (Symbol *s, FILE *f, FILE *headerf, FILE *h_file) { fprintf (headerf, "int _%s%s(\nstruct rx_call *call);\n", package, s->name); fprintf (headerf, "int %s%s%s(\nstruct rx_call *call\n", prefix, package, s->name); listiter (s->u.proc.arguments, gen1, headerf); fprintf (headerf, ");\n\n"); fprintf (f, "int _%s%s(\nstruct rx_call *call)\n", package, s->name); fprintf (f, "{\n" "int _result;\n"); listiter (s->u.proc.arguments, gendeclare, f); fprintf (f, "\n"); listiter (s->u.proc.arguments, gendecodein, f); fprintf (f, "_result = %s%s%s(", prefix, package, s->name); if (/* s->u.proc.splitp */ 1) { fprintf (f, "call"); if (!listemptyp (s->u.proc.arguments)) fprintf (f, ", "); } listiter (s->u.proc.arguments, genargs, f); fprintf (f, ");\n"); fprintf (f, "if (_result) goto funcfail;\n"); listiter (s->u.proc.arguments, genencodeout, f); listiter (s->u.proc.arguments, genfree, f); fprintf (f, "return _result;\n"); if (!listemptyp(s->u.proc.arguments)) { fprintf(f, "fail:\n"); listiter (s->u.proc.arguments, genfree, f); fprintf(f, "return rx_Error(call);\n"); } fprintf(f, "funcfail:\n" "return _result;\n" "}\n\n"); listaddtail (func_list, s); if (s->u.proc.flags & TMULTI) generate_multi (s, h_file); } struct gencase_context { FILE *f; char *package; }; static Bool gencase (List *list, Listitem *item, void *arg) { Symbol *s = (Symbol *)listdata (item); struct gencase_context *c = (struct gencase_context *)arg; FILE *f = c->f; if (c->package == s->u.proc.package) { fprintf (f, "case %u: {\n" "_result = _%s%s(call);\n" "break;\n" "}\n", s->u.proc.id, s->u.proc.package, s->name); } return FALSE; } /* * */ void generate_server_switch (FILE *c_file, FILE *h_file) { Type optype = {TULONG}; Listitem *li; struct gencase_context c; c.f = c_file; li = listhead (packagelist); while (li) { c.package = (char *)listdata (li); fprintf (h_file, "int32_t %sExecuteRequest(struct rx_call *call);\n", c.package); fprintf (c_file, "int32_t %sExecuteRequest(struct rx_call *call)\n" "{\n" "unsigned opcode;\n" "int _result;\n", c.package); encode_type ("opcode", &optype, c_file, DECODE_RX, SERVER); fprintf (c_file, "switch(opcode) {\n"); listiter (func_list, gencase, &c); fprintf (c_file, "default:\n" "_result = RXGEN_OPCODE;\n" "fprintf (stderr, \"Ignoring %%d\\n\", opcode);\n" "}\n" "return _result;\n" "fail:\n" "return rx_Error(call);\n" "}\n\n"); li = listnext (packagelist, li); } } static Bool gentcpdump_decode (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; if (a->type->type == TPOINTER) encode_type (a->name, a->type->subtype, f, ENCODE_MEM, CLIENT); else encode_type (a->name, a->type, f, ENCODE_MEM, CLIENT); fprintf (f, "++found;\n"); return FALSE; } /* * */ static Bool gentcpdump_print (List *list, Listitem *item, void *arg) { Argument *a = (Argument *)listdata (item); FILE *f = (FILE *)arg; fprintf (f, "if (found > 0)\n\n" "{ --found;\n"); if (a->type->type == TPOINTER) display_type ("", a->name, a->type->subtype, f); else display_type ("", a->name, a->type, f); if (listnextp(item)) fprintf (f, "printf(\",\");\n"); fprintf (f, "} else\n" "goto failandquit;\n"); return FALSE; } /* * */ void generate_tcpdump_stub (Symbol *s, FILE *f) { fprintf (f, "void %s%s_print(char *ptr, size_t *total_len)\n" "{\n" "int found = 0;\n", package, s->name); listiter (s->u.proc.arguments, gendeclare, f); fprintf (f, "\n"); listiter (s->u.proc.arguments, gentcpdump_decode, f); if (!listemptyp(s->u.proc.arguments)) fprintf(f, "fail:\n"); fprintf (f, "printf(\"{\");"); listiter (s->u.proc.arguments, gentcpdump_print, f); fprintf (f, "printf(\"}\\n\");"); fprintf (f, "\nreturn ptr;\n"); if (!listemptyp(s->u.proc.arguments)) fprintf(f, "failandquit:\n" "printf(\"Error decoding paket\");\n" "return NULL;"); fprintf(f, "}\n\n"); } static Bool gentcpdump_case (List *list, Listitem *item, void *arg) { Symbol *s = (Symbol *)listdata (item); FILE *f = (FILE *)arg; fprintf (f, "case %u:\n" "printf(\"%s%s(\");\n" "ret = %s%s_print(ptr, &total_len);\n" "break;\n", s->u.proc.id, package, s->name, package, s->name); return FALSE; } /* * generate tcpdump patches */ void generate_tcpdump_patches(FILE *td_file, const char *filename) { Type optype = {TULONG}; fprintf(td_file, "/* generated by $Id: output.c,v 1.3 2000/09/11 14:41:41 art Exp $ */\n\n"); fprintf (td_file, "#include \n" "#include \n" "#include \"%s.h\"\n", filename); fprintf (td_file, "%stcpdump_print(const unsigned char *ptr," "unsigned int len," "unsigned char *bp2)\n" "{\n" "u_int32_t opcode;\n" "size_t *total_len = len;\n" "char *ret;\n", package); encode_type ("opcode", &optype, td_file, DECODE_MEM, CLIENT); fprintf (td_file, "switch(opcode) {\n"); listiter (func_list, gentcpdump_case, td_file); fprintf (td_file, "default:\n" "printf (\"Unknown opcode %%s->%%d\\n\", " "package, opcode);\n" "}\n" "fail:\n" "printf(\"Error decoding packet\\n\");\n" "}\n\n"); }