name change
[obnox/wireshark/wip.git] / plugins / lua / elua_tree.c
1 /*
2  * elua_tree.c
3  *
4  * Ethereal's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #include "elua.h"
30 #include <epan/expert.h>
31
32 static gint elua_ett = -1;
33
34 static GPtrArray* outstanding_stuff = NULL;
35
36 #define PUSH_TREEITEM(L,i) g_ptr_array_add(outstanding_stuff,push_TreeItem(L,i))
37
38 void* push_TreeItem(lua_State*L, TreeItem t) {
39     void** p = (void**)pushTreeItem(L,t);
40     g_ptr_array_add(outstanding_stuff,p);
41         return p;
42 }
43
44 void clear_outstanding_trees(void) {
45     while (outstanding_stuff->len) {
46         void** p = (void**)g_ptr_array_remove_index_fast(outstanding_stuff,0);
47         *p = NULL;
48     }
49 }
50
51 ELUA_CLASS_DEFINE(TreeItem,NOP)
52
53 /* ProtoTree class */
54 static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
55     TvbRange tvbr;
56     Proto proto;
57     ProtoField field;
58     int hfid = -1;
59     int ett = -1;
60     ftenum_t type = FT_NONE;
61         TreeItem tree_item  = shiftTreeItem(L,1);
62         proto_item* item = NULL;
63         
64     if (!tree_item) {
65         return luaL_error(L,"not a TreeItem!");
66     }
67     if (! ( field = shiftProtoField(L,1) ) ) {
68         if (( proto = shiftProto(L,1) )) {
69             hfid = proto->hfid;
70             type = FT_PROTOCOL;
71                         ett = proto->ett;
72         }
73     } else {
74         hfid = field->hfid;
75         type = field->type;
76         ett = field->ett;
77     }
78
79     tvbr = shiftTvbRange(L,1);
80
81     if (!tvbr) {
82         tvbr = ep_alloc(sizeof(struct _eth_tvbrange));
83         tvbr->tvb = lua_tvb;
84         tvbr->offset = 0;
85         tvbr->len = 0;
86     }
87     
88     if (hfid > 0 ) {
89         if (lua_gettop(L)) {
90             switch(type) {
91                 case FT_PROTOCOL:
92                     item = proto_tree_add_item(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,FALSE);
93                     lua_pushnumber(L,0);
94                     lua_insert(L,1);
95                     break;
96                 case FT_UINT8:
97                 case FT_UINT16:
98                 case FT_UINT24:
99                 case FT_UINT32:
100                 case FT_FRAMENUM:
101                     item = proto_tree_add_uint(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(guint32)luaL_checknumber(L,1));
102                     break;
103                 case FT_INT8:
104                 case FT_INT16:
105                 case FT_INT24:
106                 case FT_INT32:
107                     item = proto_tree_add_int(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(gint32)luaL_checknumber(L,1));
108                     break;
109                 case FT_FLOAT:
110                     item = proto_tree_add_float(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(float)luaL_checknumber(L,1));
111                     break;
112                 case FT_DOUBLE:
113                     item = proto_tree_add_double(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,(double)luaL_checknumber(L,1));
114                     break;
115                 case FT_STRING:
116                 case FT_STRINGZ:
117                     item = proto_tree_add_string(tree_item->tree,hfid,tvbr->tvb,tvbr->offset,tvbr->len,luaL_checkstring(L,1));
118                     break;
119                 case FT_UINT64:
120                 case FT_INT64:
121                 case FT_ETHER:
122                 case FT_BYTES:
123                 case FT_UINT_BYTES:
124                 case FT_IPv4:
125                 case FT_IPv6:
126                 case FT_IPXNET:
127                 case FT_GUID:
128                 case FT_OID:
129                 default:
130                     luaL_error(L,"FT_ not yet supported");
131                     return 0;
132             }
133             
134             lua_remove(L,1);
135
136         } else {
137             item = proto_tree_add_item(tree_item->tree, hfid, tvbr->tvb, tvbr->offset, tvbr->len, little_endian);
138         }
139         
140         if ( lua_gettop(L) ) {
141             const gchar* s = lua_tostring(L,1);
142             
143             if (s) proto_item_set_text(item,"%s",s);
144
145             lua_remove(L,1);
146
147         }        
148     
149     } else if (tvbr) {
150         if (lua_gettop(L)) {
151             const gchar* s = lua_tostring(L,1);
152
153             item = proto_tree_add_text(tree_item->tree, tvbr->tvb, tvbr->offset, tvbr->len,"%s",s);
154             lua_remove(L,1);
155         }
156     } else {
157         if (lua_gettop(L)) {
158             const gchar* s = lua_tostring(L,1);
159             item = proto_tree_add_text(tree_item->tree, lua_tvb, 0, 0,"%s",s);
160             lua_remove(L,1);
161         }
162     }
163
164     while(lua_gettop(L)) {
165         const gchar* s = lua_tostring(L,1);
166
167         if (s) proto_item_append_text(item, " %s", s);
168
169         lua_remove(L,1);
170
171     }
172     
173
174         tree_item = ep_alloc(sizeof(struct _eth_treeitem));
175         tree_item->item = item;
176         tree_item->tree = proto_item_add_subtree(item,ett > 0 ? ett : elua_ett);
177
178     PUSH_TREEITEM(L,tree_item);
179     
180     return 1;
181 }
182
183
184 ELUA_METHOD TreeItem_add(lua_State *L) { return TreeItem_add_item_any(L,FALSE); }
185 ELUA_METHOD TreeItem_add_le(lua_State *L) { return TreeItem_add_item_any(L,TRUE); }
186
187 ELUA_METHOD TreeItem_set_text(lua_State *L) {
188     TreeItem ti = checkTreeItem(L,1);
189     
190     if (ti) {
191         const gchar* s = luaL_checkstring(L,2);
192         proto_item_set_text(ti->item,"%s",s);
193     }
194     
195     return 0;
196 }
197
198 ELUA_METHOD TreeItem_append_text(lua_State *L) {
199     TreeItem ti = checkTreeItem(L,1);
200     const gchar* s;
201     
202     if (ti) {
203         s = luaL_checkstring(L,2);
204         proto_item_append_text(ti->item,"%s",s);
205     }
206     return 0;
207 }
208
209 ELUA_METHOD TreeItem_set_len(lua_State *L) {
210     TreeItem ti = checkTreeItem(L,1);
211     int len;
212
213     if (ti) {
214         len = luaL_checkint(L,2);
215         proto_item_set_len(ti->item,len);
216     }
217     
218     return 0;
219 }
220
221 ELUA_METHOD TreeItem_set_expert_flags(lua_State *L) {
222     TreeItem ti = checkTreeItem(L,1);
223         int group = luaL_checkint(L,2);
224         int severity = luaL_checkint(L,3);
225
226     if ( ti && ti->item ) {
227             proto_item_set_expert_flags(ti->item,group,severity);
228     }
229
230     return 0;
231 }
232
233 ELUA_METHOD TreeItem_add_expert_info(lua_State *L) {
234     TreeItem ti = checkTreeItem(L,1);
235         int group = luaL_checkint(L,2);
236         int severity = luaL_checkint(L,3);
237         const gchar* str = luaL_optstring(L,4,"Expert Info");
238         
239     if ( ti && ti->item ) {
240         expert_add_info_format(lua_pinfo, ti->item, group, severity, "%s", str);
241     }
242     
243     return 0;
244 }
245
246 ELUA_METHOD TreeItem_set_generated(lua_State *L) {
247     TreeItem ti = checkTreeItem(L,1);
248     if (ti) {
249         PROTO_ITEM_SET_GENERATED(ti->item);
250     }
251     return 0;
252 }
253
254
255 ELUA_METHOD TreeItem_set_hidden(lua_State *L) {
256     TreeItem ti = checkTreeItem(L,1);
257     if (ti) {
258         PROTO_ITEM_SET_HIDDEN(ti->item);
259     }
260     return 0;
261 }
262
263 static const luaL_reg TreeItem_methods[] = {
264     {"add",       TreeItem_add},
265     {"add_le",       TreeItem_add_le},
266     {"set_text",       TreeItem_set_text},
267     {"append_text",       TreeItem_append_text},
268     {"set_len",       TreeItem_set_len},
269     {"set_expert_flags",       TreeItem_set_expert_flags},
270     {"add_expert_info",       TreeItem_add_expert_info},
271     {"set_generated",       TreeItem_set_generated},
272     {"set_hidden",       TreeItem_set_hidden},
273     {0, 0}
274 };
275 static const luaL_reg TreeItem_meta[] = {
276     {0, 0}
277 };
278
279
280
281 int TreeItem_register(lua_State *L) {
282         gint* etts[] = { &elua_ett };
283         
284         ELUA_REGISTER_CLASS(TreeItem);    
285     outstanding_stuff = g_ptr_array_new();
286         
287         proto_register_subtree_array(etts,1);
288
289     return 1;
290 }