blob: 2a2061216f304491fe1c1fb4fe8962bcdc7bcc3b [file] [log] [blame]
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -07001import plyproto.model as m
2import pdb
3import argparse
4import plyproto.parser as plyproto
5import traceback
6import sys
7import jinja2
8import os
Sapan Bhatia1e397df2017-05-24 12:17:28 +02009import copy
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070010
Sapan Bhatia504cc972017-04-27 01:56:28 +020011def count_messages(body):
12 count = 0
13 for e in body:
14 if (type(e)==m.MessageDefinition):
15 count+=1
16 return count
17
18def count_fields(body):
19 count = 0
20 for e in body:
21 if (type(e) in [m.LinkDefinition,m.FieldDefinition,m.LinkSpec]):
22 count+=1
23 return count
24
Sapan Bhatia1e397df2017-05-24 12:17:28 +020025def compute_rlinks(messages):
26 rev_links = {}
27
28 link_opposite = {
29 'manytomany': 'manytomany',
30 'manytoone' : 'onetomany',
31 'onetoone' : 'onetoone',
32 'onetomany' : 'manytoone'
33 }
34
35 for m in messages:
36 for l in m['links']:
37 rlink = copy.deepcopy(l)
38 rlink['_type'] = 'rlink' # An implicit link, not declared in the model
39 rlink['src_port'] = l['dst_port']
40 rlink['dst_port'] = l['src_port']
41 rlink['peer'] = m['name']
42 rlink['link_type'] = link_opposite[l['link_type']]
43
44 try:
45 rev_links[l['peer']].append(rlink)
46 except KeyError:
47 rev_links[l['peer']] = [rlink]
48
49 for m in messages:
50 try:
51 m['rlinks'] = rev_links[m['name']]
52 except KeyError:
53 pass
54
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070055class Stack(list):
56 def push(self,x):
57 self.append(x)
58
59''' XOS2Jinja overrides the underlying visitor pattern to transform the tree
60 in addition to traversing it '''
61class XOS2Jinja(m.Visitor):
62 stack = Stack()
Sapan Bhatia943dad52017-05-19 18:41:01 +020063 models = {}
Sapan Bhatia504cc972017-04-27 01:56:28 +020064 options = {}
65 message_options = {}
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070066 count_stack = Stack()
67 content=""
68 offset=0
Sapan Bhatia504cc972017-04-27 01:56:28 +020069 current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070070
71 def get_stack(self):
72 return stack
73
74 def __init__(self):
75 super(XOS2Jinja, self).__init__()
76
77 self.verbose = 0
78 self.first_field = True
79 self.first_method = True
80
81 def visit_PackageStatement(self, obj):
82 '''Ignore'''
83 return True
84
85 def visit_ImportStatement(self, obj):
86 '''Ignore'''
87 return True
88
89 def visit_OptionStatement(self, obj):
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020090 if not hasattr(obj,'mark_for_deletion'):
91 if (self.current_message_name):
92 self.message_options[obj.name.value.pval] = obj.value.value.pval
93 else:
94 self.options[obj.name.value.pval] = obj.value.value.pval
Sapan Bhatia504cc972017-04-27 01:56:28 +020095
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070096 return True
97
98 def visit_LU(self, obj):
99 return True
100
101 def visit_default(self, obj):
102 return True
103
104 def visit_FieldDirective(self, obj):
105 return True
106
107 def visit_FieldDirective_post(self, obj):
108
109 try:
110 name = obj.name.value.pval
111 except AttributeError:
112 name = obj.name.value
113
114 try:
115 value = obj.value.value.pval
116 except AttributeError:
117 try:
118 value = obj.value.value
119 except AttributeError:
120 value = obj.value.pval
121
122 self.stack.push([name,value])
123 return True
124
125 def visit_FieldType(self, obj):
126 '''Field type, if type is name, then it may need refactoring consistent with refactoring rules according to the table'''
127 return True
128
129 def visit_LinkDefinition(self, obj):
130 s={}
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700131
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200132 try:
133 s['link_type'] = obj.link_type.pval
134 except AttributeError:
135 s['link_type'] = obj.link_type
136
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700137 s['src_port'] = obj.src_port.value.pval
138 s['name'] = obj.src_port.value.pval
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200139
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700140 try:
141 s['dst_port'] = obj.dst_port.value.pval
142 except AttributeError:
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200143 s['dst_port'] = obj.dst_port
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200144
145
146 try:
147 s['through'] = obj.through.pval
148 except AttributeError:
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200149 s['through'] = obj.through
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200150
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200151 try:
152 s['peer'] = obj.name.pval
153 except AttributeError:
154 s['peer'] = obj.name
155
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700156 s['_type'] = 'link'
157 s['options'] = {'modifier':'optional'}
158
159 self.stack.push(s)
160 return True
161
162 def visit_FieldDefinition(self, obj):
163 self.count_stack.push(len(obj.fieldDirective))
164 return True
165
166 def visit_FieldDefinition_post(self, obj):
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700167 s= {}
168
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700169 if isinstance(obj.ftype, m.Name):
170 s['type'] = obj.ftype.value
171 else:
172 s['type'] = obj.ftype.name.pval
173 s['name'] = obj.name.value.pval
174 s['modifier'] = obj.field_modifier.pval
175 s['id'] = obj.fieldId.pval
176
177 opts = {'modifier':s['modifier']}
178 n = self.count_stack.pop()
179 for i in range(0, n):
180 k,v = self.stack.pop()
181 opts[k] = v
182
183 s['options'] = opts
Sapan Bhatia8a57c662017-04-11 10:39:47 -0700184 try:
185 last_link = self.stack[-1]['_type']
186 if (last_link=='link'):
187 s['link'] = True
188 except:
189 pass
190 s['_type'] = 'field'
191
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700192 self.stack.push(s)
193 return True
194
195 def visit_EnumFieldDefinition(self, obj):
196 if self.verbose > 4:
197 print "\tEnumField: name=%s, %s" % (obj.name, obj)
198
199 return True
200
201 def visit_EnumDefinition(self, obj):
202 '''New enum definition, refactor name'''
203 if self.verbose > 3:
204 print "Enum, [%s] body=%s\n\n" % (obj.name, obj.body)
205
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700206 return True
207
208 def visit_MessageDefinition(self, obj):
Sapan Bhatia504cc972017-04-27 01:56:28 +0200209 self.current_message_name = obj.name.value.pval
210 self.message_options = {}
211 self.count_stack.push(count_fields(obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700212 return True
213
214 def visit_MessageDefinition_post(self, obj):
215 stack_num = self.count_stack.pop()
216 fields = []
217 links = []
218 last_field = None
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200219 try:
220 obj.bases = map(lambda x:x.pval, obj.bases)
221 except AttributeError:
222 pass
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700223
224 for i in range(0,stack_num):
225 f = self.stack.pop()
226 if (f['_type']=='link'):
227 f['options']={i:d[i] for d in [f['options'],last_field['options']] for i in d}
228
229 links.insert(0,f)
230 else:
231 fields.insert(0,f)
232 last_field = f
233
Sapan Bhatia943dad52017-05-19 18:41:01 +0200234 model_def = {'name':obj.name.value.pval,'fields':fields,'links':links, 'bases':obj.bases, 'options':self.message_options}
235 self.stack.push(model_def)
236 self.models[obj.name.value.pval] = model_def
Sapan Bhatia504cc972017-04-27 01:56:28 +0200237 self.current_message_name = None
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700238 return True
239
240 def visit_MessageExtension(self, obj):
241 return True
242
243 def visit_MethodDefinition(self, obj):
244 return True
245
246 def visit_ServiceDefinition(self, obj):
247 return True
248
249 def visit_ExtensionsDirective(self, obj):
250 return True
251
252 def visit_Literal(self, obj):
253 return True
254
255 def visit_Name(self, obj):
256 return True
257
258 def visit_DotName(self, obj):
259 return True
260
Sapan Bhatia504cc972017-04-27 01:56:28 +0200261
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700262 def visit_Proto(self, obj):
Sapan Bhatia504cc972017-04-27 01:56:28 +0200263 self.count_stack.push(count_messages(obj.body))
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700264 return True
265
266 def visit_Proto_post(self, obj):
267 count = self.count_stack.pop()
268 messages = []
269 for i in range(0,count):
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200270 try:
271 m = self.stack.pop()
272 except IndexError:
Sapan Bhatia504cc972017-04-27 01:56:28 +0200273 pass
Sapan Bhatiac4f803f2017-04-21 11:50:39 +0200274
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700275 messages.insert(0,m)
276
Sapan Bhatia1e397df2017-05-24 12:17:28 +0200277 compute_rlinks(messages)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -0700278 self.messages = messages
279 return True
280
281 def visit_LinkSpec(self, obj):
282 count = self.count_stack.pop()
283 self.count_stack.push(count+1)
284 return True