support string arrays in event_rpcgen

svn:r613
This commit is contained in:
Niels Provos 2007-12-24 23:59:41 +00:00
parent 03589ccb12
commit 7e3a7af7d0
4 changed files with 185 additions and 107 deletions

View File

@ -29,6 +29,7 @@ Changes in current version:
o add -Wstrict-aliasing to warnings and more cleanup o add -Wstrict-aliasing to warnings and more cleanup
o removed linger from http server socket; reported by Ilya Martynov o removed linger from http server socket; reported by Ilya Martynov
o event_rpcgen now allows creating integer arrays o event_rpcgen now allows creating integer arrays
o support string arrays in event_rpcgen
Changes in 1.4.0: Changes in 1.4.0:
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.

View File

@ -485,7 +485,7 @@ class EntryBytes(Entry):
def CodeArrayAdd(self, varname, value): def CodeArrayAdd(self, varname, value):
# XXX: copy here # XXX: copy here
return '%(varname)s = NULL;' % { 'varname' : varname } return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
def GetDeclaration(self, funcname): def GetDeclaration(self, funcname):
code = [ 'int %s(struct %s *, %s **);' % ( code = [ 'int %s(struct %s *, %s **);' % (
@ -581,16 +581,16 @@ class EntryInt(Entry):
return "0" return "0"
def CodeArrayFree(self, var): def CodeArrayFree(self, var):
return "" return []
def CodeArrayAssign(self, varname, srcvar): def CodeArrayAssign(self, varname, srcvar):
return "%(varname)s = %(srcvar)s" % { 'varname' : varname, return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname,
'srcvar' : srcvar } 'srcvar' : srcvar } ]
def CodeArrayAdd(self, varname, value): def CodeArrayAdd(self, varname, value):
"""Returns a new entry of this type.""" """Returns a new entry of this type."""
return '%(varname)s = %(value)s;' % { 'varname' : varname, return [ '%(varname)s = %(value)s;' % { 'varname' : varname,
'value' : value } 'value' : value } ]
def CodeUnmarshal(self, buf, tag_name, var_name, var_len): def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
code = ['if (evtag_unmarshal_int(%(buf)s, %(tag)s, &%(var)s) == -1) {', code = ['if (evtag_unmarshal_int(%(buf)s, %(tag)s, &%(var)s) == -1) {',
@ -622,11 +622,45 @@ class EntryString(Entry):
# Init base class # Init base class
Entry.__init__(self, type, name, tag) Entry.__init__(self, type, name, tag)
self._can_be_array = 1
self._ctype = 'char *' self._ctype = 'char *'
def GetInitializer(self): def GetInitializer(self):
return "NULL" return "NULL"
def CodeArrayFree(self, varname):
code = [
'if (%(var)s != NULL) free(%(var)s);' ]
return TranslateList(code, { 'var' : varname })
def CodeArrayAssign(self, varname, srcvar):
code = [
'if (%(var)s != NULL)',
' free(%(var)s);',
'%(var)s = strdup(%(srcvar)s);',
'if (%(var)s == NULL) {',
' event_warnx("%%s: strdup", __func__);',
' return (-1);',
'}' ]
return TranslateList(code, { 'var' : varname,
'srcvar' : srcvar })
def CodeArrayAdd(self, varname, value):
code = [
'if (%(value)s != NULL) {',
' %(var)s = strdup(%(value)s);',
' if (%(var)s == NULL) {',
' goto error;',
' }',
'} else {',
' %(var)s = NULL;',
'}' ]
return TranslateList(code, { 'var' : varname,
'value' : value })
def GetVarLen(self, var): def GetVarLen(self, var):
return 'strlen(%s)' % self.GetVarName(var) return 'strlen(%s)' % self.GetVarName(var)
@ -709,38 +743,45 @@ class EntryStruct(Entry):
return '-1' return '-1'
def CodeArrayAdd(self, varname, value): def CodeArrayAdd(self, varname, value):
return ( '%(varname)s = %(refname)s_new();\n' code = [
'if (%(varname)s == NULL) \n' '%(varname)s = %(refname)s_new();',
' goto error;' 'if (%(varname)s == NULL)',
) % self.GetTranslation({ 'varname' : varname }) ' goto error;' ]
return TranslateList(code, self.GetTranslation({ 'varname' : varname }))
def CodeArrayFree(self, var): def CodeArrayFree(self, var):
code = """%(refname)s_free(%(var)s);""" % self.GetTranslation( code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation(
{ 'var' : var }) { 'var' : var }) ]
return code return code
def CodeArrayAssign(self, var, srcvar): def CodeArrayAssign(self, var, srcvar):
code = """struct evbuffer *tmp = NULL; code = [
%(refname)s_clear(%(var)s); 'int had_error = 0;',
if ((tmp = evbuffer_new()) == NULL) { 'struct evbuffer *tmp = NULL;',
event_warn("%%s: evbuffer_new()", __func__); '%(refname)s_clear(%(var)s);',
goto error; 'if ((tmp = evbuffer_new()) == NULL) {',
} ' event_warn("%%s: evbuffer_new()", __func__);',
%(refname)s_marshal(tmp, %(srcvar)s); ' had_error = 1;',
if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) { ' goto done;',
event_warnx("%%s: %(refname)s_unmarshal", __func__); '}',
goto error; '%(refname)s_marshal(tmp, %(srcvar)s);',
} 'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {',
evbuffer_free(tmp); ' event_warnx("%%s: %(refname)s_unmarshal", __func__);',
return (0); ' had_error = 1;',
error: ' goto done;',
if (tmp != NULL) '}',
evbuffer_free(tmp); 'done:'
%(refname)s_clear(msg->%(name)s_data[off]); 'if (tmp != NULL)',
return (-1);""" % self.GetTranslation( ' evbuffer_free(tmp);',
{ 'var' : var, 'if (had_error) {',
'srcvar' : srcvar}) ' %(refname)s_clear(%(var)s);',
return code ' return (-1);',
'}' ]
return TranslateList(code, self.GetTranslation({
'var' : var,
'srcvar' : srcvar}))
def CodeGet(self): def CodeGet(self):
name = self._name name = self._name
@ -872,7 +913,7 @@ class EntryVarBytes(Entry):
def CodeArrayAdd(self, varname, value): def CodeArrayAdd(self, varname, value):
# xxx: copy # xxx: copy
return '%(varname)s = NULL;' % { 'varname' : varname } return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
def GetDeclaration(self, funcname): def GetDeclaration(self, funcname):
code = [ 'int %s(struct %s *, %s *, uint32_t *);' % ( code = [ 'int %s(struct %s *, %s *, uint32_t *);' % (
@ -1034,51 +1075,62 @@ class EntryArray(Entry):
return code.split('\n') return code.split('\n')
def CodeAssign(self): def CodeAssign(self):
code = [
'int',
'%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,',
' const %(ctype)s value)',
'{',
' if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)',
' return (-1);\n',
' {' ]
code = TranslateList(code, self.GetTranslation())
codearrayassign = self._entry.CodeArrayAssign( codearrayassign = self._entry.CodeArrayAssign(
'msg->%(name)s_data[off]' % self.GetTranslation(), 'value') 'msg->%(name)s_data[off]' % self.GetTranslation(), 'value')
code = """int code += map(lambda x: ' ' + x, codearrayassign)
%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,
const %(ctype)s value)
{
if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)
return (-1);\n
{
%(codearrayassign)s;
}
return (0);
}""" % self.GetTranslation({'codearrayassign' : codearrayassign})
return code.split('\n') code += TranslateList([
' }',
' return (0);',
'}' ], self.GetTranslation())
return code
def CodeAdd(self): def CodeAdd(self):
codearrayadd = self._entry.CodeArrayAdd( codearrayadd = self._entry.CodeArrayAdd(
'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(), 'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(),
'value') 'value')
code = \ code = [
"""%(ctype)s %(optpointer)s '%(ctype)s %(optpointer)s',
%(parent_name)s_%(name)s_add(struct %(parent_name)s *msg%(optaddarg)s) '%(parent_name)s_%(name)s_add('
{ 'struct %(parent_name)s *msg%(optaddarg)s)',
if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) { '{',
int tobe_allocated = msg->%(name)s_num_allocated; ' if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {',
%(ctype)s* new_data = NULL; ' int tobe_allocated = msg->%(name)s_num_allocated;',
tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; ' %(ctype)s* new_data = NULL;',
new_data = (%(ctype)s*) realloc(msg->%(name)s_data, ' tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;',
tobe_allocated * sizeof(%(ctype)s)); ' new_data = (%(ctype)s*) realloc(msg->%(name)s_data,',
if (new_data == NULL) ' tobe_allocated * sizeof(%(ctype)s));',
goto error; ' if (new_data == NULL)',
msg->%(name)s_data = new_data; ' goto error;',
msg->%(name)s_num_allocated = tobe_allocated; ' msg->%(name)s_data = new_data;',
} ' msg->%(name)s_num_allocated = tobe_allocated;',
%(codearrayadd)s; ' }' ]
msg->%(name)s_set = 1;
return %(optreference)s(msg->%(name)s_data[msg->%(name)s_length - 1]);
error:
--msg->%(name)s_length;
return (NULL);
}
""" % self.GetTranslation({ 'codearrayadd' : codearrayadd })
return code.split('\n') code = TranslateList(code, self.GetTranslation())
code += map(lambda x: ' ' + x, codearrayadd)
code += TranslateList([
' msg->%(name)s_set = 1;',
' return %(optreference)s(msg->%(name)s_data['
'msg->%(name)s_length - 1]);',
'error:',
' --msg->%(name)s_length;',
' return (NULL);',
'}' ], self.GetTranslation())
return code
def CodeComplete(self, structname, var_name): def CodeComplete(self, structname, var_name):
self._index = 'i' self._index = 'i'
@ -1148,25 +1200,33 @@ error:
return code.split('\n') return code.split('\n')
def CodeClear(self, structname): def CodeClear(self, structname):
translate = self.GetTranslation({ 'structname' : structname })
codearrayfree = self._entry.CodeArrayFree( codearrayfree = self._entry.CodeArrayFree(
'%(structname)s->%(name)s_data[i]' % self.GetTranslation( '%(structname)s->%(name)s_data[i]' % self.GetTranslation(
{ 'structname' : structname } )) { 'structname' : structname } ))
code = [ 'if (%(structname)s->%(name)s_set == 1) {',
' int i;', code = [ 'if (%(structname)s->%(name)s_set == 1) {' ]
' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {',
' %(codearrayfree)s', if codearrayfree:
' }', code += [
' int i;',
' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
code = TranslateList(code, translate)
if codearrayfree:
code += map(lambda x: ' ' + x, codearrayfree)
code += [
' }' ]
code += TranslateList([
' free(%(structname)s->%(name)s_data);', ' free(%(structname)s->%(name)s_data);',
' %(structname)s->%(name)s_data = NULL;', ' %(structname)s->%(name)s_data = NULL;',
' %(structname)s->%(name)s_set = 0;', ' %(structname)s->%(name)s_set = 0;',
' %(structname)s->%(name)s_length = 0;', ' %(structname)s->%(name)s_length = 0;',
' %(structname)s->%(name)s_num_allocated = 0;', ' %(structname)s->%(name)s_num_allocated = 0;',
'}' '}'
] ], translate)
code = TranslateList(code, self.GetTranslation(
{ 'structname' : structname,
'codearrayfree' : codearrayfree }))
return code return code
@ -1177,32 +1237,13 @@ error:
return code return code
def CodeFree(self, structname): def CodeFree(self, structname):
codearrayfree = self._entry.CodeArrayFree( code = self.CodeClear(structname);
'%(structname)s->%(name)s_data[i]' % self.GetTranslation(
{ 'structname' : structname } ))
code = [ 'if (%(structname)s->%(name)s_data != NULL) {' ]
if codearrayfree: code += TranslateList([
code += [ 'free(%(structname)s->%(name)s_data);' ],
' int i;', self.GetTranslation({'structname' : structname }))
' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {',
' %(codearrayfree)s',
' }' ]
code += [ return code
' free(%(structname)s->%(name)s_data);',
' %(structname)s->%(name)s_data = NULL;',
' %(structname)s->%(name)s_set = 0;',
' %(structname)s->%(name)s_length = 0;',
' %(structname)s->%(name)s_num_allocated = 0;',
'}'
]
code = '\n'.join(code) % self.GetTranslation(
{ 'structname' : structname,
'codearrayfree' : codearrayfree })
return code.split('\n')
def Declaration(self): def Declaration(self):
dcl = ['%s *%s_data;' % (self._ctype, self._name), dcl = ['%s *%s_data;' % (self._ctype, self._name),

View File

@ -1434,6 +1434,15 @@ rpc_test(void)
EVTAG_ASSIGN(run, how, "very fast but with some data in it"); EVTAG_ASSIGN(run, how, "very fast but with some data in it");
EVTAG_ASSIGN(run, fixed_bytes, EVTAG_ASSIGN(run, fixed_bytes,
(uint8_t*)"012345678901234567890123"); (uint8_t*)"012345678901234567890123");
if (EVTAG_ADD(run, notes, "this is my note") == NULL) {
fprintf(stderr, "Failed to add note.\n");
exit(1);
}
if (EVTAG_ADD(run, notes, "pps") == NULL) {
fprintf(stderr, "Failed to add note.\n");
exit(1);
}
} }
if (msg_complete(msg) == -1) { if (msg_complete(msg) == -1) {
@ -1473,7 +1482,7 @@ rpc_test(void)
} }
if (EVTAG_GET(msg2, attack, &attack) == -1) { if (EVTAG_GET(msg2, attack, &attack) == -1) {
fprintf(stderr, "Get not get attack.\n"); fprintf(stderr, "Could not get attack.\n");
exit(1); exit(1);
} }
@ -1482,6 +1491,32 @@ rpc_test(void)
exit(1); exit(1);
} }
/* get the very first run message */
if (EVTAG_GET(msg2, run, 0, &run) == -1) {
fprintf(stderr, "Failed to get run msg.\n");
exit(1);
} else {
/* verify the notes */
char *note_one, *note_two;
if (EVTAG_LEN(run, notes) != 2) {
fprintf(stderr, "Wrong number of note strings.\n");
exit(1);
}
if (EVTAG_GET(run, notes, 0, &note_one) == -1 ||
EVTAG_GET(run, notes, 1, &note_two) == -1) {
fprintf(stderr, "Could not get note strings.\n");
exit(1);
}
if (strcmp(note_one, "this is my note") ||
strcmp(note_two, "pps")) {
fprintf(stderr, "Incorrect note strings encoded.\n");
exit(1);
}
}
if (EVTAG_LEN(attack, how_often) != 3) { if (EVTAG_LEN(attack, how_often) != 3) {
fprintf(stderr, "Wrong number of how_often ints.\n"); fprintf(stderr, "Wrong number of how_often ints.\n");
exit(1); exit(1);

View File

@ -18,4 +18,5 @@ struct run {
optional bytes some_bytes = 2; optional bytes some_bytes = 2;
bytes fixed_bytes[24] = 3; bytes fixed_bytes[24] = 3;
array string notes = 4;
} }