Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
glibc/sunrpc/rpc_cout.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
811 lines (745 sloc)
18.5 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* From: @(#)rpc_cout.c 1.13 89/02/22 | |
* | |
* Copyright (c) 2010, Oracle America, Inc. | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* * 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. | |
* * Neither the name of the "Oracle America, Inc." 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 COPYRIGHT HOLDERS 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 | |
* COPYRIGHT HOLDER 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. | |
*/ | |
/* | |
* rpc_cout.c, XDR routine outputter for the RPC protocol compiler | |
*/ | |
#include <ctype.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include "rpc_parse.h" | |
#include "rpc_util.h" | |
#include "proto.h" | |
static void emit_enum (definition * def); | |
static void emit_program (const definition * def); | |
static void emit_union (const definition * def); | |
static void emit_struct (definition * def); | |
static void emit_typedef (const definition * def); | |
static void emit_inline (int indent, declaration * decl, int flag); | |
static void emit_single_in_line (int indent, declaration *decl, int flag, | |
relation rel); | |
static int findtype (const definition * def, const char *type); | |
static int undefined (const char *type); | |
static void print_generic_header (const char *procname, int pointerp); | |
static void print_ifopen (int indent, const char *name); | |
static void print_ifarg (const char *arg); | |
static void print_ifsizeof (int indent, const char *prefix, const char *type); | |
static void print_ifclose (int indent); | |
static void print_ifstat (int indent, const char *prefix, const char *type, | |
relation rel, const char *amax, | |
const char *objname, const char *name); | |
static void print_stat (int indent, const declaration * dec); | |
static void print_header (const definition * def); | |
static void print_trailer (void); | |
static char *upcase (const char *str); | |
/* | |
* Emit the C-routine for the given definition | |
*/ | |
void | |
emit (definition * def) | |
{ | |
if (def->def_kind == DEF_CONST) | |
{ | |
return; | |
} | |
if (def->def_kind == DEF_PROGRAM) | |
{ | |
emit_program (def); | |
return; | |
} | |
if (def->def_kind == DEF_TYPEDEF) | |
{ | |
/* now we need to handle declarations like | |
struct typedef foo foo; | |
since we don't want this to be expanded | |
into 2 calls to xdr_foo */ | |
if (strcmp (def->def.ty.old_type, def->def_name) == 0) | |
return; | |
}; | |
print_header (def); | |
switch (def->def_kind) | |
{ | |
case DEF_UNION: | |
emit_union (def); | |
break; | |
case DEF_ENUM: | |
emit_enum (def); | |
break; | |
case DEF_STRUCT: | |
emit_struct (def); | |
break; | |
case DEF_TYPEDEF: | |
emit_typedef (def); | |
break; | |
default: | |
/* can't happen */ | |
break; | |
} | |
print_trailer (); | |
} | |
static int | |
findtype (const definition * def, const char *type) | |
{ | |
if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) | |
{ | |
return 0; | |
} | |
else | |
{ | |
return (streq (def->def_name, type)); | |
} | |
} | |
static int | |
undefined (const char *type) | |
{ | |
definition *def; | |
def = (definition *) FINDVAL (defined, type, findtype); | |
return (def == NULL); | |
} | |
static void | |
print_generic_header (const char *procname, int pointerp) | |
{ | |
f_print (fout, "\n"); | |
f_print (fout, "bool_t\n"); | |
if (Cflag) | |
{ | |
f_print (fout, "xdr_%s (", procname); | |
f_print (fout, "XDR *xdrs, "); | |
f_print (fout, "%s ", procname); | |
if (pointerp) | |
f_print (fout, "*"); | |
f_print (fout, "objp)\n{\n"); | |
} | |
else | |
{ | |
f_print (fout, "xdr_%s (xdrs, objp)\n", procname); | |
f_print (fout, "\tXDR *xdrs;\n"); | |
f_print (fout, "\t%s ", procname); | |
if (pointerp) | |
f_print (fout, "*"); | |
f_print (fout, "objp;\n{\n"); | |
} | |
} | |
static void | |
print_header (const definition * def) | |
{ | |
print_generic_header (def->def_name, | |
def->def_kind != DEF_TYPEDEF || | |
!isvectordef (def->def.ty.old_type, | |
def->def.ty.rel)); | |
/* Now add Inline support */ | |
if (inlineflag == 0) | |
return; | |
/*May cause lint to complain. but ... */ | |
f_print (fout, "\tregister int32_t *buf;\n\n"); | |
} | |
static void | |
print_prog_header (const proc_list * plist) | |
{ | |
print_generic_header (plist->args.argname, 1); | |
} | |
static void | |
print_trailer (void) | |
{ | |
f_print (fout, "\treturn TRUE;\n"); | |
f_print (fout, "}\n"); | |
} | |
static void | |
print_ifopen (int indent, const char *name) | |
{ | |
tabify (fout, indent); | |
f_print (fout, " if (!xdr_%s (xdrs", name); | |
} | |
static void | |
print_ifarg (const char *arg) | |
{ | |
f_print (fout, ", %s", arg); | |
} | |
static void | |
print_ifsizeof (int indent, const char *prefix, const char *type) | |
{ | |
if (indent) | |
{ | |
fprintf (fout, ",\n"); | |
tabify (fout, indent); | |
} | |
else | |
fprintf (fout, ", "); | |
if (streq (type, "bool")) | |
fprintf (fout, "sizeof (bool_t), (xdrproc_t) xdr_bool"); | |
else | |
{ | |
fprintf (fout, "sizeof ("); | |
if (undefined (type) && prefix) | |
{ | |
f_print (fout, "%s ", prefix); | |
} | |
fprintf (fout, "%s), (xdrproc_t) xdr_%s", type, type); | |
} | |
} | |
static void | |
print_ifclose (int indent) | |
{ | |
f_print (fout, "))\n"); | |
tabify (fout, indent); | |
f_print (fout, "\t return FALSE;\n"); | |
} | |
static void | |
print_ifstat (int indent, const char *prefix, const char *type, relation rel, | |
const char *amax, const char *objname, const char *name) | |
{ | |
const char *alt = NULL; | |
switch (rel) | |
{ | |
case REL_POINTER: | |
print_ifopen (indent, "pointer"); | |
print_ifarg ("(char **)"); | |
f_print (fout, "%s", objname); | |
print_ifsizeof (0, prefix, type); | |
break; | |
case REL_VECTOR: | |
if (streq (type, "string")) | |
{ | |
alt = "string"; | |
} | |
else if (streq (type, "opaque")) | |
{ | |
alt = "opaque"; | |
} | |
if (alt) | |
{ | |
print_ifopen (indent, alt); | |
print_ifarg (objname); | |
} | |
else | |
{ | |
print_ifopen (indent, "vector"); | |
print_ifarg ("(char *)"); | |
f_print (fout, "%s", objname); | |
} | |
print_ifarg (amax); | |
if (!alt) | |
{ | |
print_ifsizeof (indent + 1, prefix, type); | |
} | |
break; | |
case REL_ARRAY: | |
if (streq (type, "string")) | |
{ | |
alt = "string"; | |
} | |
else if (streq (type, "opaque")) | |
{ | |
alt = "bytes"; | |
} | |
if (streq (type, "string")) | |
{ | |
print_ifopen (indent, alt); | |
print_ifarg (objname); | |
} | |
else | |
{ | |
if (alt) | |
{ | |
print_ifopen (indent, alt); | |
} | |
else | |
{ | |
print_ifopen (indent, "array"); | |
} | |
print_ifarg ("(char **)"); | |
if (*objname == '&') | |
{ | |
f_print (fout, "%s.%s_val, (u_int *) %s.%s_len", | |
objname, name, objname, name); | |
} | |
else | |
{ | |
f_print (fout, "&%s->%s_val, (u_int *) &%s->%s_len", | |
objname, name, objname, name); | |
} | |
} | |
print_ifarg (amax); | |
if (!alt) | |
{ | |
print_ifsizeof (indent + 1, prefix, type); | |
} | |
break; | |
case REL_ALIAS: | |
print_ifopen (indent, type); | |
print_ifarg (objname); | |
break; | |
} | |
print_ifclose (indent); | |
} | |
static void | |
emit_enum (definition * def) | |
{ | |
(void) def; | |
print_ifopen (1, "enum"); | |
print_ifarg ("(enum_t *) objp"); | |
print_ifclose (1); | |
} | |
static void | |
emit_program (const definition * def) | |
{ | |
decl_list *dl; | |
version_list *vlist; | |
proc_list *plist; | |
for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) | |
for (plist = vlist->procs; plist != NULL; plist = plist->next) | |
{ | |
if (!newstyle || plist->arg_num < 2) | |
continue; /* old style, or single argument */ | |
print_prog_header (plist); | |
for (dl = plist->args.decls; dl != NULL; | |
dl = dl->next) | |
print_stat (1, &dl->decl); | |
print_trailer (); | |
} | |
} | |
static void | |
emit_union (const definition * def) | |
{ | |
declaration *dflt; | |
case_list *cl; | |
declaration *cs; | |
char *object; | |
const char *vecformat = "objp->%s_u.%s"; | |
const char *format = "&objp->%s_u.%s"; | |
print_stat (1, &def->def.un.enum_decl); | |
f_print (fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); | |
for (cl = def->def.un.cases; cl != NULL; cl = cl->next) | |
{ | |
f_print (fout, "\tcase %s:\n", cl->case_name); | |
if (cl->contflag == 1) /* a continued case statement */ | |
continue; | |
cs = &cl->case_decl; | |
if (!streq (cs->type, "void")) | |
{ | |
object = alloc (strlen (def->def_name) + strlen (format) + | |
strlen (cs->name) + 1); | |
if (isvectordef (cs->type, cs->rel)) | |
{ | |
s_print (object, vecformat, def->def_name, | |
cs->name); | |
} | |
else | |
{ | |
s_print (object, format, def->def_name, | |
cs->name); | |
} | |
print_ifstat (2, cs->prefix, cs->type, cs->rel, cs->array_max, | |
object, cs->name); | |
free (object); | |
} | |
f_print (fout, "\t\tbreak;\n"); | |
} | |
dflt = def->def.un.default_decl; | |
if (dflt != NULL) | |
{ | |
if (!streq (dflt->type, "void")) | |
{ | |
f_print (fout, "\tdefault:\n"); | |
object = alloc (strlen (def->def_name) + strlen (format) + | |
strlen (dflt->name) + 1); | |
if (isvectordef (dflt->type, dflt->rel)) | |
{ | |
s_print (object, vecformat, def->def_name, | |
dflt->name); | |
} | |
else | |
{ | |
s_print (object, format, def->def_name, | |
dflt->name); | |
} | |
print_ifstat (2, dflt->prefix, dflt->type, dflt->rel, | |
dflt->array_max, object, dflt->name); | |
free (object); | |
f_print (fout, "\t\tbreak;\n"); | |
} | |
else | |
{ | |
f_print (fout, "\tdefault:\n"); | |
f_print (fout, "\t\tbreak;\n"); | |
} | |
} | |
else | |
{ | |
f_print (fout, "\tdefault:\n"); | |
f_print (fout, "\t\treturn FALSE;\n"); | |
} | |
f_print (fout, "\t}\n"); | |
} | |
static void | |
inline_struct (definition *def, int flag) | |
{ | |
decl_list *dl; | |
int i, size; | |
decl_list *cur = NULL; | |
decl_list *psav; | |
bas_type *ptr; | |
char *sizestr; | |
const char *plus; | |
char ptemp[256]; | |
int indent = 1; | |
if (flag == PUT) | |
f_print (fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); | |
else | |
f_print (fout, | |
"\t\treturn TRUE;\n\t} else if (xdrs->x_op == XDR_DECODE) {\n"); | |
i = 0; | |
size = 0; | |
sizestr = NULL; | |
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) | |
{ /* xxx */ | |
/* now walk down the list and check for basic types */ | |
if ((dl->decl.prefix == NULL) && | |
((ptr = find_type (dl->decl.type)) != NULL) && | |
((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) | |
{ | |
if (i == 0) | |
cur = dl; | |
++i; | |
if (dl->decl.rel == REL_ALIAS) | |
size += ptr->length; | |
else | |
{ | |
/* this is required to handle arrays */ | |
if (sizestr == NULL) | |
plus = ""; | |
else | |
plus = "+ "; | |
if (ptr->length != 1) | |
s_print (ptemp, " %s %s * %d", plus, dl->decl.array_max, | |
ptr->length); | |
else | |
s_print (ptemp, " %s%s ", plus, dl->decl.array_max); | |
/*now concatenate to sizestr !!!! */ | |
if (sizestr == NULL) | |
sizestr = strdup (ptemp); | |
else | |
{ | |
sizestr = realloc (sizestr, strlen (sizestr) + | |
strlen (ptemp) + 1); | |
if (sizestr == NULL) | |
{ | |
f_print (stderr, "Fatal error : no memory \n"); | |
crash (); | |
}; | |
sizestr = strcat (sizestr, ptemp); | |
/*build up length of array */ | |
} | |
} | |
} | |
else | |
{ | |
if (i > 0) | |
{ | |
if (sizestr == NULL && size < inlineflag) | |
{ | |
/* don't expand into inline code if size < inlineflag */ | |
while (cur != dl) | |
{ | |
print_stat (indent + 1, &cur->decl); | |
cur = cur->next; | |
} | |
} | |
else | |
{ | |
/* were already looking at a xdr_inlineable structure */ | |
tabify (fout, indent + 1); | |
if (sizestr == NULL) | |
f_print (fout, "buf = XDR_INLINE (xdrs, %d * BYTES_PER_XDR_UNIT);", size); | |
else if (size == 0) | |
f_print (fout, | |
"buf = XDR_INLINE (xdrs, (%s) * BYTES_PER_XDR_UNIT);", | |
sizestr); | |
else | |
f_print (fout, | |
"buf = XDR_INLINE (xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);", | |
size, sizestr); | |
f_print (fout, "\n"); | |
tabify (fout, indent + 1); | |
fprintf (fout, "if (buf == NULL) {\n"); | |
psav = cur; | |
while (cur != dl) | |
{ | |
print_stat (indent + 2, &cur->decl); | |
cur = cur->next; | |
} | |
f_print (fout, "\n\t\t} else {\n"); | |
cur = psav; | |
while (cur != dl) | |
{ | |
emit_inline (indent + 1, &cur->decl, flag); | |
cur = cur->next; | |
} | |
tabify (fout, indent + 1); | |
f_print (fout, "}\n"); | |
} | |
} | |
size = 0; | |
i = 0; | |
free (sizestr); | |
sizestr = NULL; | |
print_stat (indent + 1, &dl->decl); | |
} | |
} | |
if (i > 0) | |
{ | |
if (sizestr == NULL && size < inlineflag) | |
{ | |
/* don't expand into inline code if size < inlineflag */ | |
while (cur != dl) | |
{ | |
print_stat (indent + 1, &cur->decl); | |
cur = cur->next; | |
} | |
} | |
else | |
{ | |
/* were already looking at a xdr_inlineable structure */ | |
if (sizestr == NULL) | |
f_print (fout, | |
"\t\tbuf = XDR_INLINE (xdrs, %d * BYTES_PER_XDR_UNIT);", | |
size); | |
else if (size == 0) | |
f_print (fout, | |
"\t\tbuf = XDR_INLINE (xdrs, (%s) * BYTES_PER_XDR_UNIT);", | |
sizestr); | |
else | |
f_print (fout, | |
"\t\tbuf = XDR_INLINE (xdrs, (%d + %s)* BYTES_PER_XDR_UNIT);", | |
size, sizestr); | |
f_print (fout, "\n\t\tif (buf == NULL) {\n"); | |
psav = cur; | |
while (cur != NULL) | |
{ | |
print_stat (indent + 2, &cur->decl); | |
cur = cur->next; | |
} | |
f_print (fout, "\t\t} else {\n"); | |
cur = psav; | |
while (cur != dl) | |
{ | |
emit_inline (indent + 2, &cur->decl, flag); | |
cur = cur->next; | |
} | |
f_print (fout, "\t\t}\n"); | |
} | |
} | |
} | |
/* this may be const. i haven't traced this one through yet. */ | |
static void | |
emit_struct (definition * def) | |
{ | |
decl_list *dl; | |
int j, size, flag; | |
bas_type *ptr; | |
int can_inline; | |
if (inlineflag == 0) | |
{ | |
/* No xdr_inlining at all */ | |
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) | |
print_stat (1, &dl->decl); | |
return; | |
} | |
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) | |
if (dl->decl.rel == REL_VECTOR) | |
{ | |
f_print (fout, "\tint i;\n"); | |
break; | |
} | |
size = 0; | |
can_inline = 0; | |
/* | |
* Make a first pass and see if inling is possible. | |
*/ | |
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) | |
if ((dl->decl.prefix == NULL) && | |
((ptr = find_type (dl->decl.type)) != NULL) && | |
((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) | |
{ | |
if (dl->decl.rel == REL_ALIAS) | |
size += ptr->length; | |
else | |
{ | |
can_inline = 1; | |
break; /* can be inlined */ | |
} | |
} | |
else | |
{ | |
if (size >= inlineflag) | |
{ | |
can_inline = 1; | |
break; /* can be inlined */ | |
} | |
size = 0; | |
} | |
if (size > inlineflag) | |
can_inline = 1; | |
if (can_inline == 0) | |
{ /* can not inline, drop back to old mode */ | |
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) | |
print_stat (1, &dl->decl); | |
return; | |
}; | |
flag = PUT; | |
for (j = 0; j < 2; j++) | |
{ | |
inline_struct (def, flag); | |
if (flag == PUT) | |
flag = GET; | |
} | |
f_print (fout, "\t return TRUE;\n\t}\n\n"); | |
/* now take care of XDR_FREE case */ | |
for (dl = def->def.st.decls; dl != NULL; dl = dl->next) | |
print_stat (1, &dl->decl); | |
} | |
static void | |
emit_typedef (const definition * def) | |
{ | |
const char *prefix = def->def.ty.old_prefix; | |
const char *type = def->def.ty.old_type; | |
const char *amax = def->def.ty.array_max; | |
relation rel = def->def.ty.rel; | |
print_ifstat (1, prefix, type, rel, amax, "objp", def->def_name); | |
} | |
static void | |
print_stat (int indent, const declaration * dec) | |
{ | |
const char *prefix = dec->prefix; | |
const char *type = dec->type; | |
const char *amax = dec->array_max; | |
relation rel = dec->rel; | |
char name[256]; | |
if (isvectordef (type, rel)) | |
{ | |
s_print (name, "objp->%s", dec->name); | |
} | |
else | |
{ | |
s_print (name, "&objp->%s", dec->name); | |
} | |
print_ifstat (indent, prefix, type, rel, amax, name, dec->name); | |
} | |
static void | |
emit_inline (int indent, declaration * decl, int flag) | |
{ | |
switch (decl->rel) | |
{ | |
case REL_ALIAS: | |
emit_single_in_line (indent, decl, flag, REL_ALIAS); | |
break; | |
case REL_VECTOR: | |
tabify (fout, indent); | |
f_print (fout, "{\n"); | |
tabify (fout, indent + 1); | |
f_print (fout, "register %s *genp;\n\n", decl->type); | |
tabify (fout, indent + 1); | |
f_print (fout, | |
"for (i = 0, genp = objp->%s;\n", decl->name); | |
tabify (fout, indent + 2); | |
f_print (fout, "i < %s; ++i) {\n", decl->array_max); | |
emit_single_in_line (indent + 2, decl, flag, REL_VECTOR); | |
tabify (fout, indent + 1); | |
f_print (fout, "}\n"); | |
tabify (fout, indent); | |
f_print (fout, "}\n"); | |
break; | |
default: | |
break; | |
/* ?... do nothing I guess */ | |
} | |
} | |
static void | |
emit_single_in_line (int indent, declaration *decl, int flag, relation rel) | |
{ | |
char *upp_case; | |
int freed = 0; | |
tabify (fout, indent); | |
if (flag == PUT) | |
f_print (fout, "IXDR_PUT_"); | |
else | |
{ | |
if (rel == REL_ALIAS) | |
f_print (fout, "objp->%s = IXDR_GET_", decl->name); | |
else | |
f_print (fout, "*genp++ = IXDR_GET_"); | |
} | |
upp_case = upcase (decl->type); | |
/* hack - XX */ | |
if (!strcmp (upp_case, "INT")) | |
{ | |
free (upp_case); | |
freed = 1; | |
/* Casting is safe since the `freed' flag is set. */ | |
upp_case = (char *) "LONG"; | |
} | |
if (!strcmp (upp_case, "U_INT")) | |
{ | |
free (upp_case); | |
freed = 1; | |
/* Casting is safe since the `freed' flag is set. */ | |
upp_case = (char *) "U_LONG"; | |
} | |
if (flag == PUT) | |
{ | |
if (rel == REL_ALIAS) | |
f_print (fout, "%s(buf, objp->%s);\n", upp_case, decl->name); | |
else | |
f_print (fout, "%s(buf, *genp++);\n", upp_case); | |
} | |
else | |
{ | |
f_print (fout, "%s(buf);\n", upp_case); | |
} | |
if (!freed) | |
free (upp_case); | |
} | |
static char * | |
upcase (const char *str) | |
{ | |
char *ptr, *hptr; | |
ptr = malloc (strlen (str) + 1); | |
if (ptr == NULL) | |
{ | |
f_print (stderr, "malloc failed\n"); | |
exit (1); | |
} | |
hptr = ptr; | |
while (*str != '\0') | |
*ptr++ = toupper (*str++); | |
*ptr = '\0'; | |
return hptr; | |
} |