From: Niels Provos Date: Mon, 24 Dec 2007 23:59:41 +0000 (+0000) Subject: support string arrays in event_rpcgen X-Git-Tag: release-2.0.1-alpha~443 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7e3a7af7d068a9b97d5d802d104cb30dd75a0e07;p=libevent support string arrays in event_rpcgen svn:r613 --- diff --git a/ChangeLog b/ChangeLog index d4f473b8..43686100 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,7 +29,8 @@ Changes in current version: o add -Wstrict-aliasing to warnings and more cleanup o removed linger from http server socket; reported by Ilya Martynov o event_rpcgen now allows creating integer arrays - + o support string arrays in event_rpcgen + 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 demote most http warnings to debug messages diff --git a/event_rpcgen.py b/event_rpcgen.py index 0c6b9b02..68ed132a 100755 --- a/event_rpcgen.py +++ b/event_rpcgen.py @@ -485,7 +485,7 @@ class EntryBytes(Entry): def CodeArrayAdd(self, varname, value): # XXX: copy here - return '%(varname)s = NULL;' % { 'varname' : varname } + return [ '%(varname)s = NULL;' % { 'varname' : varname } ] def GetDeclaration(self, funcname): code = [ 'int %s(struct %s *, %s **);' % ( @@ -581,16 +581,16 @@ class EntryInt(Entry): return "0" def CodeArrayFree(self, var): - return "" + return [] def CodeArrayAssign(self, varname, srcvar): - return "%(varname)s = %(srcvar)s" % { 'varname' : varname, - 'srcvar' : srcvar } + return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname, + 'srcvar' : srcvar } ] def CodeArrayAdd(self, varname, value): """Returns a new entry of this type.""" - return '%(varname)s = %(value)s;' % { 'varname' : varname, - 'value' : value } + return [ '%(varname)s = %(value)s;' % { 'varname' : varname, + 'value' : value } ] def CodeUnmarshal(self, buf, tag_name, var_name, var_len): code = ['if (evtag_unmarshal_int(%(buf)s, %(tag)s, &%(var)s) == -1) {', @@ -622,10 +622,44 @@ class EntryString(Entry): # Init base class Entry.__init__(self, type, name, tag) + self._can_be_array = 1 self._ctype = 'char *' 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): return 'strlen(%s)' % self.GetVarName(var) @@ -709,38 +743,45 @@ class EntryStruct(Entry): return '-1' def CodeArrayAdd(self, varname, value): - return ( '%(varname)s = %(refname)s_new();\n' - 'if (%(varname)s == NULL) \n' - ' goto error;' - ) % self.GetTranslation({ 'varname' : varname }) + code = [ + '%(varname)s = %(refname)s_new();', + 'if (%(varname)s == NULL)', + ' goto error;' ] + + return TranslateList(code, self.GetTranslation({ 'varname' : varname })) def CodeArrayFree(self, var): - code = """%(refname)s_free(%(var)s);""" % self.GetTranslation( - { 'var' : var }) + code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation( + { 'var' : var }) ] return code def CodeArrayAssign(self, var, srcvar): - code = """struct evbuffer *tmp = NULL; - %(refname)s_clear(%(var)s); - if ((tmp = evbuffer_new()) == NULL) { - event_warn("%%s: evbuffer_new()", __func__); - goto error; - } - %(refname)s_marshal(tmp, %(srcvar)s); - if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) { - event_warnx("%%s: %(refname)s_unmarshal", __func__); - goto error; - } - evbuffer_free(tmp); - return (0); -error: - if (tmp != NULL) - evbuffer_free(tmp); - %(refname)s_clear(msg->%(name)s_data[off]); - return (-1);""" % self.GetTranslation( - { 'var' : var, - 'srcvar' : srcvar}) - return code + code = [ + 'int had_error = 0;', + 'struct evbuffer *tmp = NULL;', + '%(refname)s_clear(%(var)s);', + 'if ((tmp = evbuffer_new()) == NULL) {', + ' event_warn("%%s: evbuffer_new()", __func__);', + ' had_error = 1;', + ' goto done;', + '}', + '%(refname)s_marshal(tmp, %(srcvar)s);', + 'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {', + ' event_warnx("%%s: %(refname)s_unmarshal", __func__);', + ' had_error = 1;', + ' goto done;', + '}', + 'done:' + 'if (tmp != NULL)', + ' evbuffer_free(tmp);', + 'if (had_error) {', + ' %(refname)s_clear(%(var)s);', + ' return (-1);', + '}' ] + + return TranslateList(code, self.GetTranslation({ + 'var' : var, + 'srcvar' : srcvar})) def CodeGet(self): name = self._name @@ -872,7 +913,7 @@ class EntryVarBytes(Entry): def CodeArrayAdd(self, varname, value): # xxx: copy - return '%(varname)s = NULL;' % { 'varname' : varname } + return [ '%(varname)s = NULL;' % { 'varname' : varname } ] def GetDeclaration(self, funcname): code = [ 'int %s(struct %s *, %s *, uint32_t *);' % ( @@ -1034,51 +1075,62 @@ class EntryArray(Entry): return code.split('\n') 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( 'msg->%(name)s_data[off]' % self.GetTranslation(), 'value') - 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 - { - %(codearrayassign)s; - } - return (0); -}""" % self.GetTranslation({'codearrayassign' : codearrayassign}) + code += map(lambda x: ' ' + x, codearrayassign) - return code.split('\n') + code += TranslateList([ + ' }', + ' return (0);', + '}' ], self.GetTranslation()) + + return code def CodeAdd(self): codearrayadd = self._entry.CodeArrayAdd( 'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(), 'value') - code = \ -"""%(ctype)s %(optpointer)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; - %(ctype)s* new_data = NULL; - tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; - new_data = (%(ctype)s*) realloc(msg->%(name)s_data, - tobe_allocated * sizeof(%(ctype)s)); - if (new_data == NULL) - goto error; - 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 }) + code = [ + '%(ctype)s %(optpointer)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;', + ' %(ctype)s* new_data = NULL;', + ' tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;', + ' new_data = (%(ctype)s*) realloc(msg->%(name)s_data,', + ' tobe_allocated * sizeof(%(ctype)s));', + ' if (new_data == NULL)', + ' goto error;', + ' msg->%(name)s_data = new_data;', + ' msg->%(name)s_num_allocated = tobe_allocated;', + ' }' ] + + code = TranslateList(code, self.GetTranslation()) + + code += map(lambda x: ' ' + x, codearrayadd) - return code.split('\n') + 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): self._index = 'i' @@ -1148,25 +1200,33 @@ error: return code.split('\n') def CodeClear(self, structname): + translate = self.GetTranslation({ 'structname' : structname }) codearrayfree = self._entry.CodeArrayFree( '%(structname)s->%(name)s_data[i]' % self.GetTranslation( { 'structname' : structname } )) - code = [ 'if (%(structname)s->%(name)s_set == 1) {', - ' int i;', - ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {', - ' %(codearrayfree)s', - ' }', + + code = [ 'if (%(structname)s->%(name)s_set == 1) {' ] + + 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);', ' %(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 = TranslateList(code, self.GetTranslation( - { 'structname' : structname, - 'codearrayfree' : codearrayfree })) + ], translate) return code @@ -1177,32 +1237,13 @@ error: return code def CodeFree(self, structname): - codearrayfree = self._entry.CodeArrayFree( - '%(structname)s->%(name)s_data[i]' % self.GetTranslation( - { 'structname' : structname } )) - code = [ 'if (%(structname)s->%(name)s_data != NULL) {' ] + code = self.CodeClear(structname); - if codearrayfree: - code += [ - ' int i;', - ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {', - ' %(codearrayfree)s', - ' }' ] + code += TranslateList([ + 'free(%(structname)s->%(name)s_data);' ], + self.GetTranslation({'structname' : structname })) - 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') + return code def Declaration(self): dcl = ['%s *%s_data;' % (self._ctype, self._name), diff --git a/test/regress.c b/test/regress.c index 78c69d18..11f62135 100644 --- a/test/regress.c +++ b/test/regress.c @@ -1434,6 +1434,15 @@ rpc_test(void) EVTAG_ASSIGN(run, how, "very fast but with some data in it"); EVTAG_ASSIGN(run, fixed_bytes, (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) { @@ -1473,7 +1482,7 @@ rpc_test(void) } if (EVTAG_GET(msg2, attack, &attack) == -1) { - fprintf(stderr, "Get not get attack.\n"); + fprintf(stderr, "Could not get attack.\n"); exit(1); } @@ -1482,6 +1491,32 @@ rpc_test(void) 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, ¬e_one) == -1 || + EVTAG_GET(run, notes, 1, ¬e_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) { fprintf(stderr, "Wrong number of how_often ints.\n"); exit(1); diff --git a/test/regress.rpc b/test/regress.rpc index 395efc01..f8a4b1c1 100644 --- a/test/regress.rpc +++ b/test/regress.rpc @@ -18,4 +18,5 @@ struct run { optional bytes some_bytes = 2; bytes fixed_bytes[24] = 3; + array string notes = 4; }