netmsgs  1.2.2
RoadNarrows Robotics Network Messaging Package
NetMsgsGenC.py
Go to the documentation of this file.
1 ###############################################################################
2 #
3 # Package: NetMsgs
4 #
5 # File: NetMsgsGenC.py
6 #
7 
8 """
9 NetMsgs Generate C files module.
10 
11 A pair of C .h header and .c source files are generated from a RoadNarrows
12 NetMsg XML specification.
13 """
14 
15 ## \file
16 ## \package NetMsgs.NetMsgsGenC
17 ##
18 ## $LastChangedDate: 2010-08-04 15:07:55 -0600 (Wed, 04 Aug 2010) $
19 ## $Rev: 550 $
20 ##
21 ## \brief NetMsgs Generate C files module.
22 ##
23 ## A pair of C .h header and .c source files are generated from a RoadNarrows
24 ## NetMsg XML specification.
25 ##
26 ## \todo Support hungarian optional keyword.
27 ## \todo Make a smarter EvalNum to simplify the equation with unknowns.
28 ##
29 ## \sa
30 ## \htmlonly
31 ## <a href="../pydoc/NetMsgs.NetMsgsGenC.html">PyDoc Generated Documentation</a>
32 ## \endhtmlonly
33 ##
34 ## \author Robin Knight (robin.knight@roadnarrows.com)
35 ##
36 ## \copyright
37 ## \h_copy 2009-2017. RoadNarrows LLC.\n
38 ## http://www.roadnarrows.com\n
39 ## All Rights Reserved
40 ##
41 
42 # Permission is hereby granted, without written agreement and without
43 # license or royalty fees, to use, copy, modify, and distribute this
44 # software and its documentation for any purpose, provided that
45 # (1) The above copyright notice and the following two paragraphs
46 # appear in all copies of the source code and (2) redistributions
47 # including binaries reproduces these notices in the supporting
48 # documentation. Substantial modifications to this software may be
49 # copyrighted by their authors and need not follow the licensing terms
50 # described here, provided that the new terms are clearly indicated in
51 # all files where they apply.
52 #
53 # IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
54 # OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
55 # PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
56 # DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
57 # EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
58 # THE POSSIBILITY OF SUCH DAMAGE.
59 #
60 # THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
61 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
62 # FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
63 # "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
64 # PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
65 #
66 ###############################################################################
67 
68 import sys
69 import os
70 import time
71 
72 import NetMsgs.NetMsgsBase as nmBase
73 import NetMsgs.NetMsgsXmlParser as NMXmlParser
74 
75 
76 #-----------------------------------------------------------------------------
77 # CLASS: NetMsgsGenC
78 #-----------------------------------------------------------------------------
80  """ RoadNarrows Net Messages C Source Generator Class.
81 
82  The NetMsgsGenC class reads the post-parsed database of a NetMsgsXmlParser
83  class instance and generates a C .h and .c file pair. The C files expects
84  the libnetmsgs C library.
85  """
86 
87  #--
88  def __init__(self, xml, hfilepath, cfilepath, **kwargs):
89  """ Initialize NetMsgsGenC instance.
90 
91  Parameters:
92  xml - NetMsgsXMLParser class instance.
93  hfilepath - Generated output h file.
94  cfilepath - Generated output c file.
95  kwargs - Optional keyword arguments.
96  debug - Set debugging level: 0 == off, 1, 2, 3.
97  incprefix - Generated .h include prefix in .c file.
98  """
99  ## parsed xml instance
100  self.mXml = xml
101 
102  ## output .h header file name
103  self.mHFilePath = hfilepath
104 
105  ## output .c header file name
106  self.mCFilePath = cfilepath
107 
108  ## debug level
109  self.mDebug = kwargs.get('debug', 0)
110 
111  ## include prefix
112  self.mIncPrefix = kwargs.get('incprefix', '')
113 
114  ## do [not] prepend RN Hungarian notation to message fields
115  self.mHungarian = kwargs.get('hungarian', False)
116 
117  ## output .h header file basename
118  self.mHBaseName = os.path.basename(self.mHFilePath)
119 
120  ## output .c header file basename
121  self.mCBaseName = os.path.basename(self.mCFilePath)
122 
123  self.AugmentXmlDB()
124  ##
125 
126  #--
127  def AugmentXmlDB(self):
128  """ Augument the XML database of parsed XML values with C generated
129  parameters.
130  """
131  self.mXml['genc'] = { }
132  encoding = self.mXml['netmsgs']['encoding'].lower()
133  if not encoding:
134  encoding = 'itv'
135  if encoding == 'itv':
136  self.mXml['genc']['encoding_prefix'] = encoding.upper()
137  else:
138  self.mXml['genc']['encoding_prefix'] = encoding.capitalize()
139 
140  endian = self.mXml['netmsgs']['endian'].lower()
141  if not endian:
142  endian = 'big'
143  self.mXml['genc']['endian_desc'] = endian + '-endian'
144  self.mXml['genc']['endian_enum'] = 'NMEndian'+endian.capitalize()
145 
146  # perform pass 0 through database, setting C specific information
147  self.Pass0()
148  ##
149 
150  #--
151  def Pass0(self):
152  """ Make initial pass through the XML database and augument with
153  specific C information.
154 
155  No generated C code is written to file output.
156  """
157  for xid in self.mXml['field_types'][nmBase.NMKeyOrder]:
158  maxlen = self.Pass0XmlDef([xid], self.mXml['field_types'][xid], 0)
159  for xid in self.mXml['msg_types'][nmBase.NMKeyOrder]:
160  maxlen = self.Pass0XmlDef([xid], self.mXml['msg_types'][xid], 0)
161  #self.mXml.PrettyPrintDB("Pass 0")
162  ##
163 
164  #--
165  def Pass0XmlDef(self, pathXids, xdef, depth):
166  """ Process the given XmL definition and add C specific data.
167 
168  No generated C code is written to file output.
169 
170  Parameters:
171  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
172  identifiers.
173  xdef - XML ftypedef, msgdef, or fielddef XML specification.
174  depth - Recursive definition depth.
175 
176  Return:
177  Maximum number of packed bytes required for this encoded definition.
178  """
179  ns = self.mXml['meta']['ns'] # namespace
180  xid = pathXids[-1] # 'basename'
181  xdef['genc'] = { } # add 'genc' dictionary to xdef
182  ftype = xdef['ftype'] # XML field type
183 
184  # base field type
185  base_ftype = self.BaseFType(ftype)
186  xdef['base_ftype'] = base_ftype
187 
188  # pad field 'type'
189  if ftype == 'pad':
190  maxlen = self.Pass0XmlDefPad(pathXids, xdef, depth)
191 
192  # structure field type
193  elif ftype == 'struct':
194  maxlen = self.Pass0XmlDefStruct(pathXids, xdef, depth)
195 
196  # vector field type
197  elif ftype == 'vector':
198  maxlen = self.Pass0XmlDefVector(pathXids, xdef, depth)
199 
200  # string field type
201  elif ftype == 'string':
202  maxlen = self.Pass0XmlDefString(pathXids, xdef, depth)
203 
204  # simple field type
205  elif nmBase.NMBuiltInFieldTypes.has_key(ftype):
206  maxlen = self.Pass0XmlDefSimple(pathXids, xdef, depth)
207 
208  # typdef'ed derived field type
209  else:
210  maxlen = self.Pass0XmlDefDerived(pathXids, xdef, depth)
211 
212  return maxlen
213  ##
214 
215  #--
216  def Pass0XmlDefPad(self, pathXids, xdef, depth):
217  """ Process pad XML definition.
218 
219  Parameters:
220  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
221  identifiers.
222  xdef - XML ftypedef, msgdef, or fielddef XML specification.
223  depth - Recursive definition depth.
224 
225  Return:
226  Maximum number of packed bytes required for this encoded definition.
227  """
228  # maximum pad field length (bytes)
229  if self.IsDeprecated(xdef):
230  maxlen = 0
231  active_cnt = 0
232  else:
233  eq_sum = repr(nmBase.NMBuiltInFieldTypes['pad']['flen'])+'*'+xdef['count']
234  maxlen = self.EvalNum(eq_sum)
235  active_cnt = 1
236 
237  xdef['genc']['type_spec'] = None
238  xdef['genc']['id'] = None
239  xdef['genc']['const_expr'] = None
240  xdef['genc']['comment'] = 'message padding'
241  xdef['genc']['maxlen'] = maxlen
242  xdef['genc']['active_cnt'] = active_cnt
243 
244  return maxlen
245  ##
246 
247  #--
248  def Pass0XmlDefStruct(self, pathXids, xdef, depth):
249  """ Process struct XML definition.
250 
251  Parameters:
252  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
253  identifiers.
254  xdef - XML ftypedef, msgdef, or fielddef XML specification.
255  depth - Recursive definition depth.
256 
257  Return:
258  Maximum number of packed bytes required for this encoded definition.
259  """
260  encoding = self.mXml['netmsgs']['encoding'] # message encoding
261  eq_sum = [nmBase.NMFHdrLen[encoding]['struct']] # field header length
262  active_cnt = 0 # active field count
263 
264  if self.IsDeprecated(xdef):
265  maxlen = 0
266  else:
267  # recurse into structure definition
268  for fname in xdef['fields'][nmBase.NMKeyOrder]:
269  n = self.Pass0XmlDef(pathXids+[fname], xdef['fields'][fname], depth+1)
270  eq_sum += [n]
271  if n > 0:
272  active_cnt += 1
273  maxlen = self.EvalNum(*eq_sum) # max length of structure
274 
275  ns = self.mXml['meta']['ns'] # namespace
276  xid = pathXids[-1] # 'basename'
277  type_spec = 'struct' # C type specifier
278  cid = self.MakeCId(xid, depth==0) # C indentifier
279  const_expr = None # C constant expression
280  msgdef = "%s%sMsgDef" % (ns, ''.join(pathXids)) # assoc. message def
281 
282  # augment db
283  xdef['genc']['type_spec'] = type_spec
284  xdef['genc']['id'] = cid
285  xdef['genc']['const_expr'] = const_expr
286  xdef['genc']['comment'] = "%s structure" % (xid)
287  xdef['genc']['msgdef'] = msgdef
288  xdef['genc']['maxlen'] = maxlen
289  xdef['genc']['active_cnt'] = active_cnt
290 
291  return maxlen
292  ##
293 
294  #--
295  def Pass0XmlDefVector(self, pathXids, xdef, depth):
296  """ Process vector XML definition.
297 
298  Parameters:
299  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
300  identifiers.
301  xdef - XML ftypedef, msgdef, or fielddef XML specification.
302  depth - Recursive definition depth.
303 
304  Return:
305  Maximum number of packed bytes required for this encoded definition.
306  """
307  ns = self.mXml['meta']['ns'] # namespace
308  xid = pathXids[-1] # 'basename'
309  type_spec = 'struct' # C type specifier
310  cid = self.MakeCId(xid, depth==0) # C indentifier
311  vtype = xdef['vtype'] # vector item field type
312  vtype_spec = self.MakeTypeSpec(vtype) # vector item C specifier
313  base_vtype = self.BaseFType(vtype) # vector item base field type
314  base_vname = self.BaseXRef(vtype) # vector item base field name
315 
316  fsize = xdef.get('size', 'NMFVAL_LEN_MAX_VECTOR')
317  if nmBase.IsIdentifier(fsize) and fsize != 'NMFVAL_LEN_MAX_VECTOR':
318  macro_len = {
319  'name': fsize,
320  'token_seq': None,
321  'comment': None,
322  }
323  else:
324  nlist = pathXids + ['len']
325  macro_len = {
326  'name': self.MakeCppMacroName(*nlist),
327  'token_seq': '(' + fsize + ')',
328  'comment': "%s maximum vector length" % (' '.join(pathXids)),
329  }
330  const_expr = macro_len['name']
331  fielddef = "%s%sFieldDef" % (ns, ''.join(pathXids))
332 
333  # maximum vector field length (bytes)
334  encoding = self.mXml['netmsgs']['encoding'] # message encoding
335  eq_sum = [nmBase.NMFHdrLen[encoding]['vector']] # field header length
336  if macro_len['token_seq']:
337  maxcount = macro_len['token_seq']
338  else:
339  maxcount = macro_len['name']
340  if base_vname == 'this':
341  fhdrlen = '0'
342  flen = repr(nmBase.NMBuiltInFieldTypes[base_vtype]['flen'])
343  elif self.IsSimple(base_vtype):
344  fhdrlen = '0'
345  flen = repr(nmBase.NMBuiltInFieldTypes[base_vtype]['flen'])
346  else:
347  fhdrlen = repr(nmBase.NMFHdrLen[encoding][base_vtype])
348  flen = self.mXml['field_types'][base_vname]['genc']['maxlen']
349 
350  if self.IsDeprecated(xdef):
351  maxlen = 0
352  active_cnt = 0
353  else:
354  eq_sum += [flen + '*' + maxcount]
355  maxlen = self.EvalNum(*eq_sum)
356  active_cnt = 1
357 
358  # augment db
359  xdef['genc']['type_spec'] = type_spec
360  xdef['genc']['id'] = cid
361  xdef['genc']['const_expr'] = const_expr
362  xdef['genc']['comment'] = "%s vector" % (xid)
363  xdef['genc']['vtype_spec'] = vtype_spec
364  xdef['genc']['base_vtype'] = base_vtype
365  xdef['genc']['base_vname'] = base_vname
366  xdef['genc']['macro_len'] = macro_len
367  xdef['genc']['fielddef'] = fielddef
368  xdef['genc']['maxlen'] = maxlen
369  xdef['genc']['active_cnt'] = active_cnt
370 
371  return maxlen
372  ##
373 
374  #--
375  def Pass0XmlDefString(self, pathXids, xdef, depth):
376  """ Process string XML definition.
377 
378  Parameters:
379  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
380  identifiers.
381  xdef - XML ftypedef, msgdef, or fielddef XML specification.
382  depth - Recursive definition depth.
383 
384  Return:
385  Maximum number of packed bytes required for this encoded definition.
386  """
387  ns = self.mXml['meta']['ns'] # namespace
388  xid = pathXids[-1] # 'basename'
389  ftype = xdef['ftype'] # XML type
390  type_spec = nmBase.NMBuiltInFieldTypes[ftype]['T'] # C type specifier
391  cid = self.MakeCId(xid, depth==0) # C indentifier
392 
393  fsize = xdef.get('size', 'NMFVAL_LEN_MAX_STRING')
394  if nmBase.IsIdentifier(fsize) and fsize != 'NMFVAL_LEN_MAX_STRING':
395  macro_len = {
396  'name': fsize,
397  'token_seq': None,
398  'comment': None,
399  }
400  else:
401  nlist = pathXids + ['len']
402  macro_len = {
403  'name': self.MakeCppMacroName(*nlist),
404  'token_seq': '(' + fsize + ')',
405  'comment': "%s maximum string length" % (' '.join(pathXids)),
406  }
407 
408  const_expr = macro_len['name'] + '+1'
409 
410  # maximum string field length (bytes)
411  encoding = self.mXml['netmsgs']['encoding'] # message encoding
412  eq_sum = [nmBase.NMFHdrLen[encoding]['string']] # field header length
413  if macro_len['token_seq']:
414  maxcount = macro_len['token_seq']
415  else:
416  maxcount = macro_len['name']
417 
418  if self.IsDeprecated(xdef):
419  maxlen = 0
420  active_cnt = 0
421  else:
422  eq_sum += [maxcount]
423  maxlen = self.EvalNum(*eq_sum)
424  active_cnt = 1
425 
426  # augment db
427  xdef['genc']['type_spec'] = type_spec
428  xdef['genc']['id'] = cid
429  xdef['genc']['const_expr'] = const_expr
430  xdef['genc']['comment'] = "%s string" % (xid)
431  xdef['genc']['macro_len'] = macro_len
432  xdef['genc']['maxlen'] = maxlen
433  xdef['genc']['active_cnt'] = active_cnt
434 
435  return maxlen
436  ##
437 
438  #--
439  def Pass0XmlDefSimple(self, pathXids, xdef, depth):
440  """ Process simple XML definition.
441 
442  Parameters:
443  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
444  identifiers.
445  xdef - XML ftypedef, msgdef, or fielddef XML specification.
446  depth - Recursive definition depth.
447 
448  Return:
449  Maximum number of packed bytes required for this encoded definition.
450  """
451  ns = self.mXml['meta']['ns'] # namespace
452  xid = pathXids[-1] # 'basename'
453  ftype = xdef['ftype'] # XML type
454  base_ftype = xdef['base_ftype'] # base field type
455  type_spec = nmBase.NMBuiltInFieldTypes[ftype]['T'] # C type specifier
456  cid = self.MakeCId(xid, depth==0) # C indentifier
457  const_expr = None # C constant expression
458 
459  # maximum simple field length (bytes)
460  encoding = self.mXml['netmsgs']['encoding'] # message encoding
461  fhdr_len = nmBase.NMFHdrLen[encoding]['simple'] # field header length
462  flen = nmBase.NMBuiltInFieldTypes[base_ftype]['flen']
463 
464  if self.IsDeprecated(xdef):
465  maxlen = 0
466  active_cnt = 0
467  else:
468  eq_sum = [fhdr_len, flen]
469  maxlen = self.EvalNum(*eq_sum)
470  active_cnt = 1
471 
472  # augment db
473  xdef['genc']['type_spec'] = type_spec
474  xdef['genc']['id'] = cid
475  xdef['genc']['const_expr'] = const_expr
476  xdef['genc']['comment'] = "%s" % (xid)
477  xdef['genc']['maxlen'] = maxlen
478  xdef['genc']['active_cnt'] = active_cnt
479 
480  return maxlen
481  ##
482 
483  #--
484  def Pass0XmlDefDerived(self, pathXids, xdef, depth):
485  """ Process derived type XML definition.
486 
487  Parameters:
488  pathXids - Path (list) of XML ftypedef, msgdef, or fielddef
489  identifiers.
490  xdef - XML ftypedef, msgdef, or fielddef XML specification.
491  depth - Recursive definition depth.
492 
493  Return:
494  Maximum number of packed bytes required for this encoded definition.
495  """
496  ns = self.mXml['meta']['ns'] # namespace
497  xid = pathXids[-1] # 'basename'
498  fname = xdef['ftype'] # XML type is really a derived nam
499  type_spec = self.MakeTypeSpec(fname) # C type specifier
500  cid = self.MakeCId(xid, depth==0) # C indentifier
501  const_expr = None # C constant expression
502  base_ftype = xdef['base_ftype'] # base XML type
503 
504  bname = self.BaseXRef(fname)
505  if bname == 'this':
506  bname = fname
507  bdef = self.mXml['field_types'][bname]
508  maxlen = bdef['genc']['maxlen']
509  active_cnt = bdef['genc']['active_cnt']
510 
511  if base_ftype == 'struct':
512  comment = "%s structure" % (xid)
513  xdef['genc']['msgdef'] = "%s%sMsgDef" % (ns, fname)
514  elif base_ftype == 'vector':
515  vtype_spec = bdef['genc']['vtype_spec']
516  const_expr = bdef['genc']['const_expr']
517  comment = "%s vector" % (xid)
518 
519  xdef['genc']['vtype_spec'] = vtype_spec
520  xdef['genc']['base_vtype'] = bdef['vtype']
521  xdef['genc']['base_vname'] = bname
522  xdef['genc']['macro_len'] = bdef['genc']['macro_len']
523  xdef['genc']['fielddef'] = "%s%sFieldDef" % (ns, bname)
524  elif base_ftype == 'string':
525  bname = self.BaseXRef(fname)
526  if bname == 'this':
527  bname = fname
528  bdef = self.mXml['field_types'][bname]
529  const_expr = bdef['genc']['const_expr']
530  comment = "%s string" % (xid)
531 
532  xdef['genc']['macro_len'] = bdef['genc']['macro_len']
533  else:
534  comment = xid
535 
536  # augment db
537  xdef['genc']['type_spec'] = type_spec
538  xdef['genc']['id'] = cid
539  xdef['genc']['const_expr'] = const_expr
540  xdef['genc']['comment'] = comment
541  xdef['genc']['maxlen'] = maxlen
542  xdef['genc']['active_cnt'] = active_cnt
543 
544  return maxlen
545  ##
546 
547 
548  #.............................................................................
549  # Generate Source Functions
550  #.............................................................................
551 
552  #--
553  def GenSource(self):
554  """ Generate C .h and .c source file pair.
555 
556  Exceptions:
557  Raises NetMsgError exception on error.
558  """
559  self.GenHSource()
560  self.GenCSource()
561  #self.mXml.PrettyPrintDB("Final")
562  ##
563 
564  #--
565  def GenHSource(self):
566  """ Generate h header.
567 
568  Exceptions:
569  Raises NetMsgError exception on error.
570  """
571  # open C header file for writing
572  try:
573  fp = open(self.mHFilePath, 'w')
574  except IOError, err:
575  raise nmBase.NetMsgsError("Error: %s" % (err))
576  self.PrettyPrintTopComment(fp, self.mHBaseName, self.mXml['meta']['brief'])
577  self.HGenPrologue(fp)
578  self.HGenMsgIds(fp)
579  self.HGenFieldTypes(fp)
580  self.HGenMsgTypes(fp)
581  self.HGenExternData(fp)
582  self.HGenProtoTypes(fp)
583  self.HGenEpilogue(fp)
584  fp.close()
585  ##
586 
587  #--
588  def GenCSource(self):
589  """ Generate h header.
590 
591  Exceptions:
592  Raises NetMsgError exception on error.
593  """
594  # open C source file for writing
595  try:
596  fp = open(self.mCFilePath, 'w')
597  except IOError, err:
598  raise nmBase.NetMsgsError("Error: %s" % (err))
599  self.PrettyPrintTopComment(fp, self.mCBaseName, self.mXml['meta']['brief'])
600  self.CGenPrologue(fp)
601  self.PrettyPrintMajorDivComment(fp, "Private Interface")
602  self.CGenFieldTypes(fp)
603  self.CGenMsgTypes(fp)
604  self.PrettyPrintMajorDivComment(fp, "Public Interface")
605  self.CGenLookupTbls(fp)
606  self.CGenPublicFuncDefs(fp)
607  self.CGenEpilogue(fp)
608  fp.close()
609  ##
610 
611 
612  #.............................................................................
613  # H File Generator Functions
614  #.............................................................................
615 
616  #--
617  def HGenPrologue(self, fp):
618  """ Generate .h header file prologue.
619 
620  Prologue includes core header file includes plus any prologue specified
621  in the XML file.
622 
623  Parameters:
624  fp - Opened output file pointer.
625  """
626  hdef = "_" + self.mHBaseName.replace(".", "_").upper()
627  prologue = self.mXml['meta']['h']['prologue']
628  fp.write(
629 """
630 
631 #ifndef %s
632 #define %s
633 
634 #include "rnr/rnrconfig.h"
635 #include "rnr/netmsgs.h"
636 
637 """ % (hdef, hdef))
638  if prologue:
639  fp.write("%s\n\n" % (prologue))
640  fp.write("""
641 C_DECLS_BEGIN
642 
643 """)
644  ##
645 
646  #--
647  def HGenMsgIds(self, fp):
648  """ Generate .h Message Id enumeration.
649 
650  Parameters:
651  fp - Opened output file pointer.
652  """
653  ns = self.mXml['meta']['ns']
654  msgorder = self.mXml['msg_types'][nmBase.NMKeyOrder]
655  section = 'msg_types'
656  if len(msgorder) == 0:
657  return
658  self.PrettyPrintBriefComment(fp, "%s Message Id Enumeration" % (ns))
659  fp.write("typedef enum\n")
660  fp.write("{\n")
661  n = 0
662  nmBase.PrettyPrintCols(fp, 0,
663  2, ns + 'MsgIdNone',
664  40, '= '+repr(n)+',',
665  48, '///< no message\n')
666  for msgid in msgorder:
667  msgdef = self.mXml[section][msgid]
668  n += 1
669  enum = ns + "MsgId" + msgid
670  if not self.IsDeprecated(msgdef):
671  comment = "%s" % (msgid)
672  else:
673  comment = "%s (deprecated)" % (msgid)
674  nmBase.PrettyPrintCols(fp, 0,
675  2, enum,
676  40, '= '+repr(n)+',',
677  48, "///< %s\n" % (comment))
678  n += 1
679  nmBase.PrettyPrintCols(fp, 0,
680  2, ns+'MsgIdNumOf',
681  40, '= '+repr(n),
682  48, '///< number of message ids\n')
683  fp.write("} %s;\n" % (ns+'MsgId_T'))
684  fp.write("\n")
685  ##
686 
687  #--
688  def HGenFieldTypes(self, fp):
689  """ Generate .h header file field types section.
690 
691  Parameters:
692  fp - Opened output file pointer.
693  """
694  section = 'field_types'
695  if len(self.mXml[section][nmBase.NMKeyOrder]) == 0:
696  return
697  self.PrettyPrintMajorDivComment(fp, "Extended Field Types")
698  for ftid in self.mXml[section][nmBase.NMKeyOrder]:
699  ftdef = self.mXml[section][ftid]
701  "Field Type %s Declarations" % (self.mXml['meta']['ns']+ftid))
702  self.HGenTypedef(fp, ftid, ftdef, "%s Field Type" % (ftid))
703  ##
704 
705  #--
706  def HGenMsgTypes(self, fp):
707  """ Generate .h header file message types section.
708 
709  Parameters:
710  fp - Opened output file pointer.
711  """
712  section = 'msg_types'
713  if len(self.mXml[section][nmBase.NMKeyOrder]) == 0:
714  return
715  self.PrettyPrintMajorDivComment(fp, "Message Types")
716  for msgid in self.mXml[section][nmBase.NMKeyOrder]:
717  msgdef = self.mXml[section][msgid]
718  if not self.IsDeprecated(msgdef):
719  if msgdef['genc']['active_cnt'] > 0:
721  "Message %s Declarations" % (self.mXml['meta']['ns']+msgid))
722  self.HGenTypedef(fp, msgid, msgdef, "Message %s Structure" % (msgid))
723  ##
724 
725  #--
726  def HGenTypedef(self, fp, xid, xdef, brief):
727  """ Generate a commented type definition subsection.
728 
729  Parameters:
730  fp - Opened output file pointer.
731  xid - Unique id in XML database section.
732  xdef - XML ftypedef, msgdef, or fielddef XML database entry.
733  brief - Brief comment string.
734  """
735  ns = self.mXml['meta']['ns'] # namespace
736  ftype = xdef['ftype'] # field type
737 
738  type_spec = xdef['genc']['type_spec'] # C type specifier
739  cid = xdef['genc']['id'] # C identifier
740  const_expr = xdef['genc']['const_expr'] # C array constant expression
741 
742  if self.IsDeprecated(xdef):
743  return
744 
745  # generate all #defines directly associated with the typedef
746  self.HGenTypedefMacros(fp, xid, xdef)
747 
748  # generate C structure typedef
749  if ftype == 'struct':
750  if xdef['genc']['active_cnt'] == 0:
751  return
752  self.PrettyPrintBriefComment(fp, brief)
753  fp.write("typedef %s\n{\n" % (type_spec))
754  self.HGenStructDeclList(fp, xdef['fields'], 1)
755  nmBase.PrettyPrintCols(fp, 0,
756  0, "} %s;" % (cid),
757  46, "///< %s\n" % (xdef['genc'].get('comment', cid[2:])))
758 
759  # generate C vector typedef
760  elif ftype == 'vector':
761  vtype_spec = xdef['genc']['vtype_spec']
762  self.PrettyPrintBriefComment(fp, brief)
763  fp.write("typedef ")
764  self.WriteVectortDecl(fp, 0, vtype_spec, cid, const_expr)
765 
766  # generate any other C typedef
767  else:
768  self.PrettyPrintBriefComment(fp, brief)
769  self.WriteTypedefStmt(fp, type_spec, cid, const_expr)
770 
771  fp.write("\n")
772  ##
773 
774  #--
775  def HGenStructDeclList(self, fp, fields, depth):
776  """ Generate comment structure declaration list (members).
777 
778  Parameters:
779  fp - Opened output file pointer.
780  fields - XML database field definition 'fields' entry.
781  depth - Current structure depth.
782  """
783  ns = self.mXml['meta']['ns'] # namespace
784  for fname in fields[nmBase.NMKeyOrder]:
785  fdef = fields[fname] # XML db field definition
786  ftype = fdef['ftype'] # field type
787  base_ftype = fdef['base_ftype'] # base field type
788 
789  type_spec = fdef['genc']['type_spec'] # C type specifier
790  cid = fdef['genc']['id'] # C identifier
791  const_expr = fdef['genc']['const_expr'] # C array constant expression
792 
793  # deprecated fields are not declared
794  if self.IsDeprecated(fdef):
795  continue
796 
797  # pad are not declared
798  elif ftype == 'pad':
799  continue
800 
801  # structure embedded structure member
802  elif ftype == 'struct':
803  fp.write("%*sstruct\n" % (depth*2, ''))
804  fp.write("%*s{\n" % (depth*2, ''))
805  self.HGenStructDeclList(fp, fdef['fields'], depth+1)
806  nmBase.PrettyPrintCols(fp, 0,
807  depth*2, "} %s;" % (cid),
808  46, "///< %s\n" % (fdef['genc'].get('comment', cid[2:])))
809 
810  # string type
811  elif ftype == 'string':
812  self.WriteStructDecl(fp, depth*2, type_spec, cid, const_expr)
813 
814  # structure vector member
815  elif ftype == 'vector':
816  vtype_spec = fdef['genc']['vtype_spec']
817  self.WriteVectortDecl(fp, depth*2, vtype_spec, cid, const_expr)
818 
819  # simple type
820  elif self.IsSimple(ftype):
821  self.WriteStructDecl(fp, depth*2, type_spec, cid, const_expr)
822 
823  # derived string type (dimensioning already declared in typedef)
824  elif base_ftype == 'string':
825  self.WriteStructDecl(fp, depth*2, type_spec, cid, None)
826 
827  # derived vector type (dimensioning already declared in typedef)
828  elif base_ftype == 'vector':
829  self.WriteStructDecl(fp, depth*2, type_spec, cid, None)
830 
831  # other type
832  else:
833  self.WriteStructDecl(fp, depth*2, type_spec, cid, const_expr)
834  ##
835 
836  #--
837  def HGenTypedefMacros(self, fp, xid, xdef):
838  """ Generation .h cpp #defines macros associated with field or message
839  typedefs.
840 
841  Parameters:
842  fp - Opened output file pointer.
843  xid - Unique id in XML database section.
844  xdef - XML ftypedef, msgdef, or fielddef XML database entry.
845  """
846  if self.IsDeprecated(xdef):
847  return
848 
849  for macro in ['macro_len']: # add others as needed
850  if xdef['genc'].has_key(macro) and xdef['genc'][macro]['token_seq']:
851  fp.write("/*! %s */\n" % (xdef['genc'][macro]['comment']))
852  fp.write("#define %s %s\n\n" % \
853  (xdef['genc'][macro]['name'], xdef['genc'][macro]['token_seq']))
854 
855  if xdef['ftype'] == 'struct':
856  for fname in xdef['fields'][nmBase.NMKeyOrder]:
857  self.HGenTypedefMacros(fp, fname, xdef['fields'][fname])
858  ##
859 
860  #--
861  def HGenExternData(self, fp):
862  """ Generate .h header public external data.
863 
864  Parameters:
865  fp - Opened output file pointer.
866  """
867  ns = self.mXml['meta']['ns']
868  self.PrettyPrintMajorDivComment(fp, "External Data")
869  fp.write("""\
870 //
871 // %s Message Definition Look-Up Table.
872 // (indexed by %sMsgId_T enum)
873 //
874 """ % (ns, ns))
875  fp.write("extern const NMMsgDef_T *%sMsgDefLookupTbl[];\n\n" % (ns))
876 
877  fp.write("""\
878 //
879 // %s Maximum Message Body Length (bytes) Look-Up Table.
880 // (indexed by %sMsgId_T enum)
881 //
882 """ % (ns, ns))
883  fp.write("extern size_t %sMsgMaxLenLookupTbl[];\n\n" % (ns))
884  ##
885 
886  #--
887  def HGenProtoTypes(self, fp):
888  """ Generate .h header function prototypes.
889 
890  Parameters:
891  fp - Opened output file pointer.
892  """
893  ns = self.mXml['meta']['ns']
894  encoding_pre = self.mXml['genc']['encoding_prefix']
895  endian_desc = self.mXml['genc']['endian_desc']
896  endian_enum = self.mXml['genc']['endian_enum']
897 
898  self.PrettyPrintMajorDivComment(fp, "Function Prototypes")
899 
900  self.WriteFuncDef(fp, 'const', 'NMMsgDef_T *', "%sLookupMsgDef" % (ns),
901  [(None, "%sMsgId_T" % (ns), "eMsgId")])
902 
903  self.WriteFuncDef(fp, None, 'size_t', "%sLookupMsgMaxLen" % (ns),
904  [(None, "%sMsgId_T" % (ns), "eMsgId")])
905 
906  self.WriteFuncDef(fp, None, 'int', "%sPackMsg" % (ns),
907  [(None, "%sMsgId_T" % (ns), "eMsgId"),
908  (None, "void *", "pStruct"),
909  (None, "byte_t", "buf[]"),
910  (None, "size_t", "bufSize"),
911  (None, "bool_t", "bTrace")])
912 
913  self.WriteFuncDef(fp, None, 'int', "%sUnpackMsg" % (ns),
914  [(None, "%sMsgId_T" % (ns), "eMsgId"),
915  (None, "byte_t", "buf[]"),
916  (None, "size_t", "uMsgLen"),
917  (None, "void *", "pStruct"),
918  (None, "bool_t", "bTrace")])
919 
920  for msgid in self.mXml['msg_types'][nmBase.NMKeyOrder]:
921  msgdef = self.mXml['msg_types'][msgid]
922  if self.IsDeprecated(msgdef) or msgdef['genc']['active_cnt'] == 0:
923  continue
924  self.WriteFuncDef(fp, 'INLINE_IN_H', 'int', "%sPack%s" % (ns, msgid),
925  [(None, "%s%s_T *" % (ns, msgid), "pStruct"),
926  (None, "byte_t", "buf[]"),
927  (None, "size_t", "bufSize"),
928  (None, "bool_t", "bTrace")],
929  stmts="""\
930 return %sPackMsg(%sMsgId%s, pStruct, buf, bufSize, bTrace);""" % \
931  (ns, ns, msgid),
932  comments="""\
933 \\brief Pack a %s%s %s message in %s byte order
934  into the output buffer.
935 
936 \\param [in] pStruct Pointer to the associated, populated message
937  structure.
938 \\param [out] buf Output message buffer.
939 \\param bufSize Size of output buffer.
940 \\param bTrace Do [not] trace packing.
941 
942 \\return
943 On success, returns the number of bytes packed.
944 On error, returns the appropriate \\h_lt 0 negated NM_ECODE.""" % \
945  (ns, msgid, encoding_pre, endian_desc))
946 
947  self.WriteFuncDef(fp, 'INLINE_IN_H', 'int', "%sUnpack%s" % (ns, msgid),
948  [(None, "byte_t", "buf[]"),
949  (None, "size_t", "uMsgLen"),
950  (None, "%s%s_T *" % (ns, msgid), "pStruct"),
951  (None, "bool_t", "bTrace")],
952  stmts="""\
953 return %sUnpackMsg(%sMsgId%s, buf, uMsgLen, pStruct, bTrace);""" % \
954  (ns, ns, msgid),
955  comments="""\
956 \\brief Unpack a %s%s %s message in %s byte order
957  from the input buffer.
958 
959 \\param [in] buf Output message buffer.
960 \\param uMsgLen Length of message (bytes) in input buffer.
961 \\param [out] pStruct Pointer to the associated message structure.
962 \\param bTrace Do [not] trace packing.
963 
964 \\return
965 On success, returns the number of bytes unpacked.
966 On error, returns the appropriate \\h_lt 0 negated NM_ECODE.""" % \
967  (ns, msgid, encoding_pre, endian_desc))
968  ##
969 
970  #--
971  def HGenEpilogue(self, fp):
972  """ Generate .h header file epilogue.
973 
974  Parameters:
975  fp - Opened output file pointer.
976  """
977  hdef = "_" + self.mHBaseName.replace(".", "_").upper()
978  epilogue = self.mXml['meta']['h']['epilogue']
979  fp.write(
980 """
981 C_DECLS_END
982 """)
983  if epilogue:
984  fp.write("\n\n%s" % (epilogue))
985  fp.write(
986 """
987 
988 #endif // %s\n""" % (hdef))
989  ##
990 
991 
992  #.............................................................................
993  # C File Generator Functions
994  #.............................................................................
995 
996  #--
997  def CGenPrologue(self, fp):
998  """ Generate .c source file prologue.
999 
1000  Prologue includes core header file includes plus any prologue specified
1001  in the XML file.
1002 
1003  Parameters:
1004  fp - Opened output file pointer.
1005  """
1006  incpre = self.mIncPrefix.strip()
1007  if len(incpre) > 0 and incpre[-1] != os.path.sep:
1008  incpre += os.path.sep
1009  prologue = self.mXml['meta']['c']['prologue']
1010  fp.write(
1011 """
1012 
1013 #include "rnr/rnrconfig.h"
1014 #include "rnr/log.h"
1015 #include "rnr/netmsgs.h"
1016 
1017 #include "%s%s"
1018 
1019 #ifndef EOFDEF
1020 /*! End of Field Definition entry. */
1021 #define EOFDEF {NULL, 0, NMFTypeNone, 0, }
1022 #endif // EOFDEF
1023 
1024 """ % (incpre, self.mHBaseName))
1025  if prologue:
1026  fp.write("%s\n\n" % (prologue))
1027  ##
1028 
1029  #--
1030  def CGenFieldTypes(self, fp):
1031  """ Generate .c field and message definitions from 'field_types' section.
1032 
1033  Parameters:
1034  fp - Opened output file pointer.
1035  """
1036  ns = self.mXml['meta']['ns'] # namespace
1037  for ftid in self.mXml['field_types'][nmBase.NMKeyOrder]:
1038  ftdef = self.mXml['field_types'][ftid]
1039  ftype = ftdef['ftype']
1040  if ftype in ['struct', 'vector']:
1041  self.PrettyPrintMinorDivComment(fp, "Field Type %s%s Definition" % \
1042  (ns, ftid))
1043  self.CGenDefsR(fp, [ftid], ftdef)
1044  ##
1045 
1046  #--
1047  def CGenMsgTypes(self, fp):
1048  """ Generate .c field and message definitions from 'msg_types' section.
1049 
1050  Parameters:
1051  fp - Opened output file pointer.
1052  """
1053  ns = self.mXml['meta']['ns'] # namespace
1054  for msgid in self.mXml['msg_types'][nmBase.NMKeyOrder]:
1055  msgdef = self.mXml['msg_types'][msgid]
1056  if not self.IsDeprecated(msgdef):
1057  self.PrettyPrintMinorDivComment(fp, "Message %s%s Definition" % \
1058  (ns, msgid))
1059  self.CGenDefsR(fp, [msgid], msgdef)
1060  ##
1061 
1062  #--
1063  def CGenDefsR(self, fp, pathXids, xdef):
1064  """ Recursively generate .c message related data C definition statements.
1065 
1066  Data generated:
1067  field ID enum declarations
1068  field definition arrays
1069  message/struct definitions
1070 
1071  Parameters:
1072  fp - Opened output file pointer.
1073  pathXids - Path list of XML ftypedef, msgdef, or fielddef
1074  identifiers.
1075  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1076  """
1077  if xdef['ftype'] == 'struct':
1078  for fname in xdef['fields'][nmBase.NMKeyOrder]:
1079  self.CGenDefsR(fp, pathXids+[fname], xdef['fields'][fname])
1080  self.CGenFIdEnum(fp, pathXids, xdef)
1081  self.CGenAnonStruct(fp, pathXids, xdef)
1082  self.CGenFieldDefs(fp, pathXids, xdef)
1083  self.CGenMsgDef(fp, pathXids, xdef)
1084  elif xdef['ftype'] == 'vector':
1085  self.CGenVectorItemFieldDef(fp, pathXids, xdef)
1086  ##
1087 
1088  #--
1089  def CGenFIdEnum(self, fp, pathXids, xdef):
1090  """ Generate .c field id enum declaration for the given definition.
1091 
1092  Parameters:
1093  fp - Opened output file pointer.
1094  pathXids - Path list of XML identifiers.
1095  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1096  """
1097  ns = self.mXml['meta']['ns'] # namespace
1098  fields = xdef['fields'] # field
1099  nsname = ns + ''.join(pathXids) # global name substring
1100  self.PrettyPrintBriefComment(fp, "%s Field Id Enumeration" % (nsname))
1101  fp.write("typedef enum\n{\n")
1102  enum = 0
1103  nmBase.PrettyPrintCols(fp, 0,
1104  2, "%sFIdReserved" % (nsname),
1105  40, "= %d," % (enum),
1106  48, "///< reserved field id\n",
1107  force=True)
1108  enum += 1
1109  for fname in fields[nmBase.NMKeyOrder]:
1110  fdef = fields[fname]
1111  if fdef['ftype'] == 'pad':
1112  fname = '_pad' + repr(enum)
1113  if not self.IsDeprecated(fdef):
1114  comment = "%s field id" % (fname)
1115  else:
1116  comment = "%s field id (deprecated)" % (fname)
1117  nmBase.PrettyPrintCols(fp, 0,
1118  2, "%sFId%s" % (nsname, fname),
1119  40, "= %d," % (enum),
1120  48, "///< %s\n" % (comment),
1121  force=True)
1122  enum += 1
1123  nmBase.PrettyPrintCols(fp, 0,
1124  2, "%sFIdNumOf" % (nsname),
1125  40, "= %d" % (enum),
1126  48, "///< number of fields\n",
1127  force=True)
1128  fp.write("} %sFId_T;\n\n" % (nsname))
1129  ##
1130 
1131  #--
1132  def CGenAnonStruct(self, fp, pathXids, xdef):
1133  """ Generate .c anonomous structure type.
1134 
1135  Anonomous structures mirror any inline, non-global 'struct' field
1136  types. External structures are required to calculate member offsets
1137  correctlhy.
1138 
1139  Parameters:
1140  fp - Opened output file pointer.
1141  pathXids - Path list of XML identifiers.
1142  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1143  """
1144  ftype = xdef['ftype'] # (derivied) XML field type
1145 
1146  if self.IsDeprecated(xdef): # deprecated element
1147  return
1148  elif len(pathXids) <= 1: # global struct defined in .h
1149  return
1150  elif self.mXml['field_types'].has_key(ftype): # typedef struct defined in .h
1151  return
1152  if xdef['genc']['active_cnt'] == 0:
1153  return
1154 
1155  ns = self.mXml['meta']['ns'] # namespace
1156  xname = ''.join(pathXids) # XML full concatenated name
1157  nsname = ns + xname # global name substring
1158  fields = xdef['fields'] # fields
1159 
1160  anon_type_spec = '_' + xname + '_T' # anonomum structure type specifier
1161 
1162  self.PrettyPrintBriefComment(fp,
1163  "%s Anonumous Struture Type" % (' '.join(pathXids)))
1164  fp.write("typedef struct\n{\n")
1165  self.HGenStructDeclList(fp, xdef['fields'], 1)
1166  fp.write("} %s;\n\n" % (anon_type_spec))
1167 
1168  # augment database
1169  xdef['genc']['anon_type_spec'] = anon_type_spec
1170  ##
1171 
1172  #--
1173  def CGenFieldDefs(self, fp, pathXids, xdef):
1174  """ Generate .c field definition array for the given definition.
1175 
1176  Parameters:
1177  fp - Opened output file pointer.
1178  pathXids - Path list of XML identifiers.
1179  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1180  """
1181  ns = self.mXml['meta']['ns'] # namespace
1182  fields = xdef['fields'] # fields
1183  nsname = ns + ''.join(pathXids) # global name substring
1184  pid = xdef['genc']['id'] # parent C identifer
1185  eofdef = "EOFDEF" # end of field def macro
1186  enum = 1 # field enum
1187 
1188  struct_id = xdef['genc'].get('anon_type_spec', pid)
1189 
1190  self.PrettyPrintBriefComment(fp, "%s Field Definitions" % (nsname))
1191  fp.write("static const NMFieldDef_T %sFieldDefs[] =\n{\n" % (nsname))
1192  for fname in fields[nmBase.NMKeyOrder]:
1193  fdef = fields[fname] # XML field definition
1194  ftype = fdef['ftype'] # field type
1195  base_ftype = fdef['base_ftype'] # base field type
1196  cid = fdef['genc']['id'] # C identifier
1197 
1198  if self.IsDeprecated(fdef):
1199  continue
1200 
1201  # pad 'field'
1202  if ftype == 'pad':
1203  sFName = '_pad'+repr(enum)
1204  eFId = "%sFId%s" % (nsname, sFName)
1205  eFType = "NMFType%s" % (base_ftype.capitalize())
1206  uOffset = "(size_t)0"
1207  else:
1208  sFName = fname
1209  eFId = "%sFId%s" % (nsname, fname)
1210  eFType = "NMFType%s" % (base_ftype.capitalize())
1211  uOffset = "memberoffset(%s, %s)" % (struct_id, cid)
1212 
1213  this, this_init = self.CMakeFieldDefThis(ftype, fdef)
1214 
1215  self.WriteFDefEntry(fp, sFName, eFId, eFType, uOffset, this, this_init)
1216  enum += 1
1217 
1218  nmBase.PrettyPrintCols(fp, 0, 2, eofdef+'\n')
1219  fp.write("};\n\n")
1220  ##
1221 
1222  #--
1223  def CGenVectorItemFieldDef(self, fp, pathXids, xdef):
1224  """ Generate .c vector item field definition array for the given definition.
1225 
1226  Parameters:
1227  fp - Opened output file pointer.
1228  pathXids - Path list of XML identifiers.
1229  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1230  """
1231  ns = self.mXml['meta']['ns'] # namespace
1232  fname = pathXids[-1] # XML field name
1233  nsname = ns + ''.join(pathXids) # global name substring
1234  eofdef = "EOFDEF" # end of field def macro
1235  ftype = xdef['ftype'] # field type
1236  vtype = xdef['vtype'] # vector item field type
1237  cid = xdef['genc']['id'] # C identifier
1238  base_vtype = xdef['genc']['base_vtype'] # base vector item field type
1239  base_vname = xdef['genc']['base_vname'] # base vector item base name
1240 
1241  if self.IsDeprecated(xdef):
1242  return
1243 
1244  if base_vname == 'this':
1245  base_fdef = xdef
1246  else:
1247  base_vname = xdef['genc']['base_vname']
1248  base_fdef = self.mXml['field_types'][base_vname]
1249 
1250  fielddef = "%sFieldDef" % (nsname)
1251  sFName = fname
1252  eFId = "0"
1253  eFType = "NMFType%s" % (base_vtype.capitalize())
1254  uOffset = "(size_t)0"
1255 
1256  this, this_init = self.CMakeFieldDefThis(base_vtype, base_fdef)
1257 
1258  self.PrettyPrintBriefComment(fp, "%s Field Definitions" % (nsname))
1259  fp.write("static const NMFieldDef_T %s[] =\n{\n" % (fielddef))
1260  self.WriteFDefEntry(fp, sFName, eFId, eFType, uOffset, this, this_init)
1261  nmBase.PrettyPrintCols(fp, 0, 2, eofdef+'\n')
1262  fp.write("};\n\n")
1263  ##
1264 
1265  #--
1266  def CMakeFieldDefThis(self, ftype, fdef):
1267  """ Make C field definition this specific initialization for field type.
1268 
1269  Parameters:
1270  ftype - XML field type.
1271  fdef - XML field definition.
1272 
1273  Return
1274  Returns the pair (this, this_init) where:
1275  this - C union name.
1276  this_int - List of (.member, value) pairs.
1277  """
1278  nothis_ftype = ['bool', 'char', 'p32', 'p64']
1279 
1280  # pad 'field'
1281  if ftype == 'pad':
1282  return self.CMakeFieldDefThisPad(ftype, fdef)
1283 
1284  # simple number field
1285  elif ftype in nmBase.NMFTypeNumber:
1286  return self.CMakeFieldDefThisNumber(ftype, fdef)
1287 
1288  # field with no extra infor
1289  elif ftype in nothis_ftype:
1290  return '', []
1291 
1292  # string field
1293  elif ftype == 'string':
1294  return self.CMakeFieldDefThisString(ftype, fdef)
1295 
1296  # structure field
1297  elif ftype == 'struct':
1298  return self.CMakeFieldDefThisStruct(ftype, fdef)
1299 
1300  # vector field
1301  elif ftype == 'vector':
1302  return self.CMakeFieldDefThisVector(ftype, fdef)
1303 
1304  # derived type
1305  else:
1306  return self.CMakeFieldDefThisDerived(ftype, fdef)
1307  ##
1308 
1309  #--
1310  def CMakeFieldDefThisPad(self, ftype, fdef):
1311  """ Make C field definition this specific initialization for pad 'field'.
1312 
1313  Parameters:
1314  ftype - XML field type.
1315  fdef - XML field definition.
1316 
1317  Return
1318  Returns the pair (this, this_init) where:
1319  this - C union name.
1320  this_int - List of (.member, value) pairs.
1321  """
1322  this = "m_pad"
1323  this_init = [('m_uCount', "(byte_t)(%s)" % fdef.get('count', "1"))]
1324  return this, this_init
1325  ##
1326 
1327  #--
1328  def CMakeFieldDefThisNumber(self, ftype, fdef):
1329  """ Make C field definition this specific initialization for number field.
1330 
1331  Parameters:
1332  ftype - XML field type.
1333  fdef - XML field definition.
1334 
1335  Return
1336  Returns the pair (this, this_init) where:
1337  this - C union name.
1338  this_int - List of (.member, value) pairs.
1339  """
1340  this_init = [] # this initialization list
1341  bits = "" # present bits
1342  bitssep = "" # bits separator
1343 
1344  if ftype[0] == 's':
1345  this = 'm_u' + ftype[1:]
1346  casttype = nmBase.NMBuiltInFieldTypes['u'+ftype[1:]]['T']
1347  else:
1348  this = 'm_' + ftype
1349  casttype = nmBase.NMBuiltInFieldTypes[ftype]['T']
1350  if fdef.has_key('min'):
1351  val = fdef['min']
1352  bits += "%sNMBITS_HAS_MIN" % (bitssep)
1353  bitssep = "|"
1354  else:
1355  val = '0'
1356  this_init += [('m_valMin', "(%s)(%s)" % (casttype, val))]
1357 
1358  if fdef.has_key('max'):
1359  val = fdef['max']
1360  bits += "%sNMBITS_HAS_MAX" % (bitssep)
1361  bitssep = "|"
1362  else:
1363  val = '0'
1364  this_init += [('m_valMax', "(%s)(%s)" % (casttype, val))]
1365 
1366  if fdef.has_key('const'):
1367  val = fdef['const']
1368  bits += "%sNMBITS_HAS_CONST" % (bitssep)
1369  bitssep = "|"
1370  else:
1371  val = '0'
1372  this_init += [('m_valConst', "(%s)(%s)" % (casttype, val))]
1373 
1374  if not bits:
1375  bits = "0"
1376  this_init = [('m_bits', "(byte_t)(%s)" % bits)] + this_init
1377 
1378  return this, this_init
1379  ##
1380 
1381  #--
1382  def CMakeFieldDefThisString(self, ftype, fdef):
1383  """ Make C field definition this specific initialization for string field.
1384 
1385  Parameters:
1386  ftype - XML field type.
1387  fdef - XML field definition.
1388 
1389  Return
1390  Returns the pair (this, this_init) where:
1391  this - C union name.
1392  this_int - List of (.member, value) pairs.
1393  """
1394  this = 'm_string'
1395  this_init = [] # this initialization list
1396  casttype = nmBase.NMBuiltInFieldTypes[ftype]['T']
1397 
1398  val = fdef['genc']['const_expr']
1399  this_init += [('m_uMaxCount', "(size_t)%s" % (val))]
1400 
1401  if fdef.has_key('const'):
1402  val = fdef['const']
1403  else:
1404  val = 'NULL'
1405  this_init += [('m_sConst', "(%s *)(%s)" % (casttype, val))]
1406 
1407  return this, this_init
1408  ##
1409 
1410  #--
1411  def CMakeFieldDefThisStruct(self, ftype, fdef):
1412  """ Make C field definition this specific initialization for struct field.
1413 
1414  Parameters:
1415  ftype - XML field type.
1416  fdef - XML field definition.
1417 
1418  Return
1419  Returns the pair (this, this_init) where:
1420  this - C union name.
1421  this_int - List of (.member, value) pairs.
1422  """
1423  this = 'm_struct'
1424  this_init = [('', "&%s" % (fdef['genc']['msgdef']))]
1425  return this, this_init
1426  ##
1427 
1428  #--
1429  def CMakeFieldDefThisVector(self, ftype, fdef):
1430  """ Make C field definition this specific initialization for vector field.
1431 
1432  Parameters:
1433  ftype - XML field type.
1434  fdef - XML field definition.
1435 
1436  Return
1437  Returns the pair (this, this_init) where:
1438  this - C union name.
1439  this_int - List of (.member, value) pairs.
1440  """
1441  this = 'm_vector'
1442  this_init = [] # this initialization list
1443 
1444  val = fdef['genc']['const_expr']
1445  this_init += [('m_uMaxCount', "(size_t)%s" % (val))]
1446  this_init += [('m_uElemSize',
1447  "sizeof(%s)" % (fdef['genc']['vtype_spec']))]
1448  this_init += [('m_pThisElem', (fdef['genc']['fielddef']))]
1449 
1450  return this, this_init
1451  ##
1452 
1453  #--
1454  def CMakeFieldDefThisDerived(self, ftype, fdef):
1455  """ Make C field definition this specific initialization for vector field.
1456 
1457  Parameters:
1458  ftype - XML field type.
1459  fdef - XML field definition.
1460 
1461  Return
1462  Returns the pair (this, this_init) where:
1463  this - C union name.
1464  this_int - List of (.member, value) pairs.
1465  """
1466  base_ftype = fdef['base_ftype'] # base field type
1467  if base_ftype in nmBase.NMFTypeNumber:
1468  return self.CMakeFieldDefThisNumber(base_ftype, fdef)
1469  elif base_ftype == 'string':
1470  return self.CMakeFieldDefThisString(base_ftype, fdef)
1471  elif base_ftype == 'struct':
1472  return self.CMakeFieldDefThisStruct(base_ftype, fdef)
1473  elif base_ftype == 'vector':
1474  return self.CMakeFieldDefThisVector(base_ftype, fdef)
1475  else:
1476  return ('', [])
1477  ##
1478 
1479  #--
1480  def CGenMsgDef(self, fp, pathXids, xdef):
1481  """ Generate .c source file [sub]message definition from the given
1482  definition.
1483 
1484  Parameters:
1485  fp - Opened output file pointer.
1486  pathXids - Path list of XML identifiers.
1487  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1488  """
1489  ns = self.mXml['meta']['ns'] # namespace
1490  xname = ''.join(pathXids) # XML full concatenated name
1491  nsname = ns + xname # global name substring
1492 
1493  if self.IsDeprecated(xdef):
1494  return
1495 
1496  # only top-level stucture definitions under 'msg_types' section have
1497  # message ids.
1498  if len(pathXids) == 1 and self.mXml['msg_types'].has_key(pathXids[0]):
1499  msgid_enum = "%sMsgId%s" % (ns, xname),
1500  else:
1501  msgid_enum = "%sMsgIdNone" % (ns),
1502  self.PrettyPrintBriefComment(fp, "%s Message Definition" % (nsname))
1503  fp.write("static const NMMsgDef_T %sMsgDef =\n{\n" % (nsname))
1504  nmBase.PrettyPrintCols(fp, 0,
1505  2, ".m_sMsgName",
1506  22, "=",
1507  24, "\"%s\"," % (nsname),
1508  2, ".m_eMsgId",
1509  22, "=",
1510  24, "%s," % (msgid_enum),
1511  2, ".m_uCount",
1512  22, "=",
1513  24, "(size_t)(%d)," % (xdef['genc']['active_cnt']),
1514  2, ".m_pFields",
1515  22, "=",
1516  24, "%sFieldDefs\n" % (nsname))
1517  fp.write("};\n\n")
1518  ##
1519 
1520  #--
1521  def CGenLookupTbls(self, fp):
1522  """ Generate .c source file look-up tables.
1523 
1524  Parameters:
1525  fp - Opened output file pointer.
1526  """
1527  ns = self.mXml['meta']['ns'] # namespace
1528  self.PrettyPrintBriefComment(fp,
1529  "%s Message Definition Look-Up Table. Indexed by %sMsgId_T enum." % \
1530  (ns, ns))
1531  fp.write("const NMMsgDef_T *%sMsgDefLookupTbl[] =\n" % ns)
1532  fp.write("{\n")
1533  nmBase.PrettyPrintCols(fp, 0,
1534  2, "NULL,",
1535  40, "///< [%sMsgIdNone]\n" % (ns))
1536  for msgid in self.mXml['msg_types'][nmBase.NMKeyOrder]:
1537  if not self.IsDeprecated(self.mXml['msg_types'][msgid]):
1538  nmBase.PrettyPrintCols(fp, 0,
1539  2, "&%s%sMsgDef," % (ns, msgid),
1540  40, "///< [%sMsgId%s]\n" % (ns, msgid))
1541  else:
1542  nmBase.PrettyPrintCols(fp, 0,
1543  2, "NULL,",
1544  40, "///< [%sMsgId%s]\n" % (ns, msgid))
1545  nmBase.PrettyPrintCols(fp, 0,
1546  2, "NULL",
1547  40, "///< [%sMsgIdNumOf]\n" % (ns))
1548  fp.write("};\n\n")
1549 
1550  self.PrettyPrintBriefComment(fp,
1551  "%s Message Maximum Size Look-Up Table. Indexed by %sMsgId_T enum." % \
1552  (ns, ns))
1553  fp.write("size_t %sMsgMaxLenLookupTbl[] =\n" % ns)
1554  fp.write("{\n")
1555  nmBase.PrettyPrintCols(fp, 0,
1556  2, "(size_t)(0),",
1557  40, "///< [%sMsgIdNone]\n" % (ns))
1558  for msgid in self.mXml['msg_types'][nmBase.NMKeyOrder]:
1559  nmBase.PrettyPrintCols(fp, 0,
1560  2, "(size_t)(%s)," % (self.mXml['msg_types'][msgid]['genc']['maxlen']),
1561  40, "///< [%sMsgId%s]\n" % (ns, msgid))
1562  nmBase.PrettyPrintCols(fp, 0,
1563  2, "(size_t)(0)",
1564  40, "///< [%sMsgIdNumOf]\n" % (ns))
1565  fp.write("};\n\n")
1566  ##
1567 
1568  #--
1569  def CGenPublicFuncDefs(self, fp):
1570  """ Generate .c source file function definitions.
1571 
1572  Parameters:
1573  fp - Opened output file pointer.
1574  """
1575  ns = self.mXml['meta']['ns']
1576  encoding_pre = self.mXml['genc']['encoding_prefix']
1577  endian_desc = self.mXml['genc']['endian_desc']
1578  endian_enum = self.mXml['genc']['endian_enum']
1579 
1580  self.PrettyPrintMajorDivComment(fp, "Functions")
1581 
1582  # lookup message definition function
1583  self.WriteFuncDef(fp, 'const', 'NMMsgDef_T *', "%sLookupMsgDef" % (ns),
1584  [(None, "%sMsgId_T" % (ns), "eMsgId")],
1585  stmts="""\
1586 if( (uint_t)eMsgId >= (uint_t)%sMsgIdNumOf )
1587 {
1588  return NULL;
1589 }
1590 else
1591 {
1592  return %sMsgDefLookupTbl[(uint_t)eMsgId];
1593 }""" % (ns, ns),
1594  comments="""\
1595 \\brief Look up the message definition associated with the message id.
1596 
1597 \\param eMsgId Message Id.
1598 
1599 \\return
1600 On success, returns the pointer to the NMMsgDef_T.
1601 On error, NULL is returned.""")
1602 
1603  # lookup message maximum lenght function
1604  self.WriteFuncDef(fp, None, 'size_t', "%sLookupMsgMaxLen" % (ns),
1605  [(None, "%sMsgId_T" % (ns), "eMsgId")],
1606  stmts="""\
1607 if( (uint_t)eMsgId >= (uint_t)%sMsgIdNumOf )
1608 {
1609  return (size_t)0;
1610 }
1611 else
1612 {
1613  return %sMsgMaxLenLookupTbl[(uint_t)eMsgId];
1614 }""" % (ns, ns),
1615  comments="""\
1616 \\brief Look up the message maximum length associated with the message id.
1617 
1618 The maximum length is the total number of packed bytes possible for the
1619 given message. The message may be much shorter.
1620 
1621 \\param eMsgId Message Id.
1622 
1623 \\return
1624 On success, returns the number of bytes.
1625 On error, 0 is returned.""")
1626 
1627  # packing function
1628  self.WriteFuncDef(fp, None, 'int', "%sPackMsg" % (ns),
1629  [(None, "%sMsgId_T" % (ns), "eMsgId"),
1630  (None, "void *", "pStruct"),
1631  (None, "byte_t", "buf[]"),
1632  (None, "size_t", "bufSize"),
1633  (None, "bool_t", "bTrace")],
1634  stmts="""\
1635 const NMMsgDef_T *pMsgDef;
1636 
1637 if( (pMsgDef = %sLookupMsgDef(eMsgId)) == NULL )
1638 {
1639  LOGERROR("%%s(ecode=%%d): msgid=%%u.",
1640  nmStrError(NM_ECODE_MSGID), NM_ECODE_MSGID, eMsgId);
1641  return -NM_ECODE_MSGID;
1642 }
1643 
1644 if( bTrace )
1645 {
1646  return nmPack%sMsgDebug(pMsgDef, pStruct, buf, bufSize, %s);
1647 }
1648 else
1649 {
1650  return nmPack%sMsg(pMsgDef, pStruct, buf, bufSize, %s);
1651 }""" % (ns, encoding_pre, endian_enum, encoding_pre, endian_enum),
1652  comments="""\
1653 \\brief Pack a %s message in %s byte order.
1654 
1655 \\param eMsgId Message Id.
1656 \\param [in] pStruct Pointer to the associated, populated message
1657  structure.
1658 \\param [out] buf Output message buffer.
1659 \\param bufSize Size of output buffer.
1660 \\param bTrace Do [not] trace packing.
1661 
1662 \\return
1663 On success, returns the number of bytes packed.
1664 On error, returns the appropriate \< 0 negated NM_ECODE.""" % \
1665  (encoding_pre, endian_desc))
1666 
1667  # unpacking function
1668  self.WriteFuncDef(fp, None, 'int', "%sUnpackMsg" % (ns),
1669  [(None, "%sMsgId_T" % (ns), "eMsgId"),
1670  (None, "byte_t", "buf[]"),
1671  (None, "size_t", "uMsgLen"),
1672  (None, "void *", "pStruct"),
1673  (None, "bool_t", "bTrace")],
1674  stmts="""\
1675 const NMMsgDef_T *pMsgDef;
1676 
1677 if( (pMsgDef = %sLookupMsgDef(eMsgId)) == NULL )
1678 {
1679  LOGERROR("%%s(ecode=%%d): msgid=%%u.",
1680  nmStrError(NM_ECODE_MSGID), NM_ECODE_MSGID, eMsgId);
1681  return -NM_ECODE_MSGID;
1682 }
1683 
1684 if( bTrace )
1685 {
1686  return nmUnpack%sMsgDebug(pMsgDef, buf, uMsgLen, pStruct, %s);
1687 }
1688 else
1689 {
1690  return nmUnpack%sMsg(pMsgDef, buf, uMsgLen, pStruct, %s);
1691 }""" % (ns, encoding_pre, endian_enum, encoding_pre, endian_enum),
1692  comments="""\
1693 \\brief Unpack a %s message in %s byte order.
1694 
1695 \\param eMsgId Message Id.
1696 \\param [in] buf Input message buffer.
1697 \\param uMsgLen Length of message (bytes) in input buffer.
1698 \\param [out] pStruct Pointer to the associated message structure.
1699 \\param bTrace Do [not] trace packing.
1700 
1701 \\return
1702 On success, returns the number of bytes unpacked.
1703 On error, returns the appropriate \< 0 negated NM_ECODE.""" % \
1704  (encoding_pre, endian_desc))
1705  ##
1706 
1707  #--
1708  def CGenEpilogue(self, fp):
1709  """ Generate .c source file epilogue.
1710 
1711  Parameters:
1712  fp - Opened output file pointer.
1713  """
1714  epilogue = self.mXml['meta']['c']['epilogue']
1715  if epilogue:
1716  fp.write("\n\n%s" % (epilogue))
1717  ##
1718 
1719 
1720  #.............................................................................
1721  # CPP and C Statement Utilities
1722  #.............................................................................
1723 
1724  #--
1725  def MakeCppMacroName(self, *names):
1726  """ Make CPP #define macro name.
1727 
1728  Parameters:
1729  names - List of argument subnames.
1730 
1731  Returns:
1732  String "NS_ARG1_..._ARGN"
1733  """
1734  defname = self.mXml['meta']['ns']
1735  for n in names:
1736  defname += '_' + n
1737  return defname.upper()
1738  ##
1739 
1740  #--
1741  def MakeTypeSpec(self, ftype):
1742  """ Make C type specifier.
1743 
1744  Parameters:
1745  ftype - Field type.
1746 
1747  Returns:
1748  Type specifier.
1749  """
1750  if nmBase.NMBuiltInFieldTypes.has_key(ftype):
1751  type_spec = nmBase.NMBuiltInFieldTypes[ftype]['T']
1752  else:
1753  type_spec = self.mXml['meta']['ns'] + ftype + '_T'
1754  return type_spec
1755  ##
1756 
1757  #--
1758  def MakeCId(self, xid, isGlobal):
1759  """ Make C indentifier.
1760 
1761  Parameters:
1762  xid - XML [sub]definition id.
1763  isGlobal - Identifier does [not] have global scope.
1764 
1765  Returns:
1766  C identifier.
1767  """
1768  if isGlobal:
1769  cid = self.mXml['meta']['ns'] + xid + '_T'
1770  else:
1771  pre = 'm_'
1772  if self.mHungarian: pre += nmBase.NMBuiltInFieldTypes[ftype]['pre']
1773  cid = pre + xid
1774  return cid
1775 
1776  #--
1777  def WriteStructDecl(self, fp, indent, type_spec, cid, const_expr, **kwargs):
1778  """ Write commented structure declarator.
1779 
1780  struct_decl ::-
1781  type_spec cid ;
1782  | type_spec cid [ const_expr ] ;
1783 
1784  Parameters:
1785  fp - Opened output file pointer.
1786  indent - Indentation.
1787  type_spec - C type specifier.
1788  cid - C identifier.
1789  const_expr - C array constant expression. None of not an array.
1790  kwargs - Optional keyword arguments.
1791  'comment':string - Overide default comment.
1792  """
1793  if const_expr:
1794  post = '[' + const_expr + ']'
1795  else:
1796  post = ''
1797  comment = kwargs.get('comment', cid[2:])
1798  nmBase.PrettyPrintCols(fp, 0,
1799  indent, type_spec,
1800  26, cid+post+';',
1801  46, "///< %s\n" % (comment))
1802  ##
1803 
1804  #--
1805  def WriteVectortDecl(self, fp, indent, vtype_spec, cid, const_expr):
1806  """ Write commented structure vector declarator.
1807 
1808  struct_vector_decl ::-
1809  struct {
1810  size_t m_count ;
1811  union {
1812  void * m_pAlign ;
1813  vtype_spec m_buf [ const_expr ] ;
1814  } u ;
1815  } cid ;
1816 
1817  Parameters:
1818  fp - Opened output file pointer.
1819  indent - Indentation.
1820  vtype_spec - C vector items type specifier.
1821  cid - C identifier.
1822  const_expr - C array constant expression. None of not an array.
1823  kwargs - Optional keyword arguments.
1824  'comment':string - Overide default comment.
1825  """
1826  fp.write("%*s%s\n" % (indent, '', 'struct'))
1827  fp.write("%*s{\n" % (indent, ''))
1828  self.WriteStructDecl(fp, indent+2, 'size_t', 'm_count', None,
1829  comment="vector item count")
1830  fp.write("%*s%s\n" % (indent+2, '', 'union'))
1831  fp.write("%*s{\n" % (indent+2, ''))
1832  self.WriteStructDecl(fp, indent+4, 'void', '*m_pAlign', None,
1833  comment="force alignment")
1834  self.WriteStructDecl(fp, indent+4, vtype_spec, 'm_buf', const_expr,
1835  comment="the item vector")
1836  fp.write("%*s} u; ///< aligned vector items\n" % (indent+2, ''))
1837  nmBase.PrettyPrintCols(fp, 0,
1838  indent, "} %s;" % (cid),
1839  46, "///< vector\n")
1840  ##
1841 
1842  #--
1843  def WriteTypedefStmt(self, fp, type_spec, cid, const_expr):
1844  """ Write typedef declaration.
1845 
1846  typedef_spec ::-
1847  typedef type_spec cid ;
1848  | typedef type_spec cid [ const_expr ] ;
1849 
1850  Parameters:
1851  fp - Opened output file pointer.
1852  type_spec - C type specifier.
1853  cid - C identifier.
1854  const_expr - C array constant expression. None of not an array.
1855  """
1856  if const_expr:
1857  post = '[' + const_expr + ']'
1858  else:
1859  post = ''
1860  fp.write("typedef %s %s%s;\n" % (type_spec, cid, post))
1861  ##
1862 
1863  #--
1864  def WriteFuncDef(self, fp, type_qual, type_spec, funcname, funcargs,
1865  **kwargs):
1866  """ Write function declaration statement.
1867 
1868  func_def ::-
1869  extern type_qual type_spec funcname ( arg_list ) ;
1870  | extern type_spec funcname ( arg_list ) ;
1871  | type_qual type_spec funcname ( arg_list ) { stmts }
1872  | type_spec funcname ( arg_list ) { stmts }
1873 
1874  arg_list ::-
1875  empty
1876  ! arg_decl
1877  | arg_list , arg_decl
1878 
1879  arg_decl ::-
1880  type_qual type_spec cid
1881  type_spec cid
1882 
1883  Parameters:
1884  fp - Opened output file pointer.
1885  type_qual - C function type qualifier(s).
1886  type_spec - C function type specifier(s).
1887  funcname - C function identifier.
1888  funcargs - List of function arguments 3-tuple:
1889  (type_qual(s), type_spec(s), cid)
1890  kwargs - Dictionary of optional arguments.
1891  'comments': string
1892  'stmts': string
1893  """
1894  comments = kwargs.get('comments', '')
1895  stmts = kwargs.get('stmts', '')
1896  if type_qual:
1897  s = "%s %s %s(" % (type_qual, type_spec, funcname)
1898  else:
1899  s = "%s %s(" % (type_spec, funcname)
1900  if not stmts:
1901  s = 'extern ' + s
1902  if comments:
1903  fp.write("/*!\n")
1904  for l in comments.splitlines():
1905  fp.write(" * %s\n" % l)
1906  fp.write(" */\n")
1907  fp.write(s)
1908  cursor = len(s)
1909  indent = cursor + 1
1910  i = 1
1911  n = len(funcargs)
1912  sep = ',\n'
1913  for arg3tuple in funcargs:
1914  if i == n:
1915  sep = ''
1916  if arg3tuple[0]:
1917  s = "%s %s %s%s" % (arg3tuple[0], arg3tuple[1], arg3tuple[2], sep)
1918  else:
1919  s = "%s %s%s" % (arg3tuple[1], arg3tuple[2], sep)
1920  nmBase.PrettyPrintCols(fp, cursor, indent, s, force=True)
1921  cursor = 0
1922  i += 1
1923  if stmts:
1924  fp.write(" )\n")
1925  fp.write("{\n")
1926  for stmt in stmts.splitlines():
1927  fp.write(" %s\n" % stmt)
1928  fp.write("}\n\n")
1929  else:
1930  fp.write(" );\n\n")
1931  ###
1932 
1933  #--
1934  def WriteFDefEntry(self, fp, sFName, eFId, eFType, uOffset, this, this_init):
1935  """ Write an NMFieldDef_T entry.
1936 
1937  Parameters:
1938  fp - Opened output file pointer.
1939  sFName - m_sFName value.
1940  eFId - m_eFId value.
1941  eFType - m_eFType value.
1942  uOffset - m_uOffset value.
1943  this - m_this.<this>
1944  this_init - List of (member, value) this pairs.
1945  """
1946  fp.write(" {\n")
1947  nmBase.PrettyPrintCols(fp, 0,
1948  4, ".m_sFName",
1949  30, "=",
1950  32, "\"%s\"," % (sFName),
1951  4, ".m_eFId",
1952  30, "=",
1953  32, "%s," % (eFId),
1954  4, ".m_eFType",
1955  30, "=",
1956  32, "%s," % (eFType),
1957  4, ".m_uOffset",
1958  30, "=",
1959  32, "%s,\n" % (uOffset))
1960  for dotassign in this_init:
1961  if dotassign[0]:
1962  this_mem = '.' + dotassign[0]
1963  else:
1964  this_mem = ''
1965  this_val = dotassign[1]
1966  nmBase.PrettyPrintCols(fp, 0,
1967  4, ".m_this.%s%s" % (this, this_mem),
1968  30, "=",
1969  32, "%s,\n" % this_val)
1970  fp.write(" },\n")
1971  ##
1972 
1973  #--
1974  def IsSimple(self, ftype):
1975  """ Returns True (False) is field type is (not) simple.
1976 
1977  Parameters:
1978  ftype - (Derived) field type.
1979 
1980  Return:
1981  True or False.
1982  """
1983  ftype = self.BaseFType(ftype)
1984  if ftype == 'pad':
1985  return False
1986  elif nmBase.NMBuiltInFieldTypes[ftype]['comp'] == 'simple':
1987  return True
1988  else:
1989  return False
1990  ##
1991 
1992  #--
1993  def IsDeprecated(self, xdef):
1994  """ Returns True (False) is definition is (not) deprecated.
1995 
1996  Parameters:
1997  xdef - XML ftypedef, msgdef, or fielddef XML specification.
1998 
1999  Return:
2000  True or False.
2001  """
2002  dispo = xdef.get('disposition', 'active')
2003  if dispo == 'deprecated':
2004  return True
2005  else:
2006  return False
2007  ##
2008 
2009  #--
2010  def BaseXRef(self, fname):
2011  """ Returns the base field XML cross-reference name for the given XML
2012  name.
2013 
2014  Parameters:
2015  fname - (Derived) field name.
2016 
2017  Return:
2018  Returns 'this' if fname is a base field, otherwise the XML
2019  cross-referenced field name is returned.
2020  """
2021  if nmBase.NMBuiltInFieldTypes.has_key(fname):
2022  return 'this'
2023  ftype = self.mXml['field_types'][fname]['ftype']
2024  while not nmBase.NMBuiltInFieldTypes.has_key(ftype):
2025  fname = ftype
2026  ftype = self.mXml['field_types'][fname]['ftype']
2027  return fname
2028  ##
2029 
2030  #--
2031  def BaseFType(self, ftype):
2032  """ Returns the base field type for the given field type.
2033 
2034  Parameters:
2035  ftype - (Derived) field type.
2036 
2037  Return:
2038  Base field type.
2039  """
2040  if ftype == 'pad':
2041  return ftype
2042  while not nmBase.NMBuiltInFieldTypes.has_key(ftype):
2043  if self.mXml['field_types'].has_key(ftype):
2044  ftype = self.mXml['field_types'][ftype]['ftype']
2045  else:
2046  raise nmBase.NetMsgsError("Error: %s is not a defined ftype" % (ftype))
2047  return ftype
2048  ##
2049 
2050  #--
2051  def EvalNum(self, *args):
2052  """ Evaluate a summation of terms.
2053 
2054  Paramters:
2055  args List of summation terms, with each term one of:
2056  an equation, string, number
2057 
2058  Examples:
2059  5 -> '5'
2060  5, '(3 * 10)' -> '35'
2061  5, 'MY_MAX', '1*255' -> '300+MY_MAX'
2062 
2063  Return:
2064  Returns string of the evaluated results.
2065  """
2066  #n = 0
2067  #s = ''
2068  expr = ''
2069  for arg in args:
2070  # if arg is None:
2071  # continue
2072  if type(arg) == str:
2073  arg = arg.replace("NMFVAL_LEN_MAX_STRING",
2074  repr(nmBase.NMStringMaxCount))
2075  arg = arg.replace("NMFVAL_LEN_MAX_VECTOR",
2076  repr(nmBase.NMVectorMaxCount))
2077  else:
2078  arg = repr(arg)
2079  if expr:
2080  expr = expr + '+' + arg
2081  else:
2082  expr = arg
2083  return self._Simplify(expr)
2084 
2085  # try:
2086  # n += eval(arg)
2087  # except:
2088  # s += '+(' + arg + ')'
2089  #n = int(n)
2090  #return repr(n) + s
2091  ##
2092 
2093  #--
2094  def _Simplify(self, expr):
2095  """ Simplify algebraic expression. The simplification is very simple.
2096 
2097  The distribution law is not applied.
2098 
2099  Parameters:
2100  expr - Algebraic expression in string format.
2101 
2102  Return:
2103  Simplified algebraic expression in string format.
2104  """
2105  expr = expr.replace(' ', '')
2106  tree = self._MakeTree(expr)
2107  val = self._EvalTree(tree)
2108  if type(val) == str:
2109  return val
2110  else:
2111  return repr(val)
2112  ##
2113 
2114  #--
2115  def _EvalTree(self, tree):
2116  """ Evaluate algebraic expression in a tree format.
2117 
2118  tree: expr
2119  [lexpr, op, rexpr]
2120 
2121  Only '+' and '*' operators are supported.
2122 
2123  Parameters:
2124  tree - Algebraic expression tree
2125 
2126  Return:
2127  Evaluated number or string.
2128  """
2129  if type(tree) == list:
2130  lval = self._EvalTree(tree[0])
2131  op = tree[1]
2132  rval = self._EvalTree(tree[2])
2133  if type(lval) == str:
2134  if type(rval) == str:
2135  return '('+lval+op+rval+')'
2136  elif rval == 0:
2137  if op == '+':
2138  return lval
2139  elif op == '*':
2140  return 0
2141  elif (rval == 1) and (op == '*'):
2142  return lval
2143  else:
2144  return '('+lval+op+repr(rval)+')'
2145  elif type(rval) == str:
2146  if type(lval) == str:
2147  return '('+lval+op+rval+')'
2148  elif lval == 0:
2149  if op == '+':
2150  return rval
2151  elif op == '*':
2152  return 0
2153  elif (lval == 1) and (op == '*'):
2154  return rval
2155  else:
2156  return '('+repr(lval)+op+rval+')'
2157  elif op == '+':
2158  return lval + rval
2159  elif op == '*':
2160  return lval * rval
2161  else: # error
2162  return '('+repr(lval)+op+repr(rval)+')'
2163  else:
2164  try:
2165  return eval(tree)
2166  except:
2167  return tree
2168  ##
2169 
2170  #--
2171  def _MakeTree(self, expr):
2172  """ Make expression tree.
2173 
2174  tree: expr
2175  [lexpr, op, rexpr]
2176 
2177  Parameters:
2178  tree - Algebraic expression tree
2179 
2180  Return:
2181  Expression tree.
2182  """
2183  if not expr:
2184  return ''
2185  if self._ParenExprParen(expr):
2186  return self._MakeTree(expr[1:-1])
2187  else:
2188  k = self._FindLowOp(expr, 0)
2189  if k is None:
2190  return expr
2191  else:
2192  return [self._MakeTree(expr[:k]), expr[k], self._MakeTree(expr[k+1:])]
2193  ##
2194 
2195  #--
2196  def _ParenExprParen(self, expr, start=0):
2197  """ Test if expression is of form '(' expr ')'
2198 
2199  Parameters:
2200  expr - Algebraic expression string.
2201  start - Start index in expr.
2202 
2203  Return:
2204  True or False.
2205  """
2206  if expr[start] != '(':
2207  return False
2208  n = self._FindRParen(expr, lparen=start)
2209  if n == len(expr)-1:
2210  return True
2211  else:
2212  return False
2213  ##
2214 
2215  #--
2216  def _FindRParen(self, expr, lparen=0):
2217  """ Find corresponding right parentheses.
2218 
2219  Parameters:
2220  expr - Algebraic expression string.
2221  lparen - Start index in expression of left parenthesis.
2222 
2223  Return:
2224  Right parenthesis index in expr.
2225  """
2226  depth = 1
2227  n = lparen + 1
2228  for c in expr[lparen+1:]:
2229  if c == '(':
2230  depth += 1
2231  elif c == ')':
2232  depth -= 1
2233  if depth == 0:
2234  return n
2235  n += 1
2236  return None
2237  ##
2238 
2239  #--
2240  def _FindLowOp(self, expr, start=0):
2241  """ Find operator with lowest precedence in expression.
2242 
2243  Only '+' and '*' operators are supported.
2244 
2245  Parameters:
2246  expr - Algebraic expression string.
2247  start - Start index in search.
2248 
2249  Return:
2250  Operator index in expression if found. Else None.
2251  """
2252  n = start
2253  op = ''
2254  m = 0
2255  while n < len(expr):
2256  c = expr[n]
2257  if c == '+':
2258  return n
2259  elif c == '*':
2260  op = c
2261  m = n
2262  elif c == '(':
2263  n = self._FindRParen(expr, lparen=n)
2264  n += 1
2265  if op == '*':
2266  return m
2267  else:
2268  return None
2269  ##
2270 
2271 
2272  #.............................................................................
2273  # Pretty Printing
2274  #.............................................................................
2275 
2276  #--
2277  def PrettyPrintTopComment(self, fp, srcbasename, brief):
2278  """ Prints source file top comment block.
2279 
2280  Parameters:
2281  fp - Opened output file pointer.
2282  srcbasename - Base name of source file.
2283  brief - Brief comment.
2284  """
2285  xmlfilename = self.mXml.GetXMLFileName()
2286  now = time.localtime()
2287  thisdate = "%d.%02d.%02d" % (now.tm_year, now.tm_mon, now.tm_mday)
2288  thistime = "%02d:%02d:%02d" % (now.tm_hour, now.tm_min, now.tm_sec)
2289  fp.write("""\
2290 ///////////////////////////////////////////////////////////////////////////////
2291 //
2292 // File: %s
2293 //
2294 /*!
2295  * \\file
2296  *
2297  * \\brief %s
2298  *
2299  * \\warning This file was auto-generated on %s %s from the NetMsgs
2300  * XML specification %s.
2301  *
2302  * \\par Copyright:
2303  * (C) %d. RoadNarrows LLC
2304  * (http://www.roadnarrows.com)
2305  * All Rights Reserved
2306  */
2307 ///////////////////////////////////////////////////////////////////////////////
2308 """ % (srcbasename, brief, thisdate, thistime, xmlfilename, now.tm_year))
2309  ##
2310 
2311  #--
2312  def PrettyPrintMajorDivComment(self, fp, comment):
2313  """ Prints major file division comment block.
2314 
2315  Parameters:
2316  fp - Opened output file pointer.
2317  comment - Major division comment line.
2318  """
2319  fp.write("""\
2320 
2321 //-----------------------------------------------------------------------------
2322 // %s
2323 //-----------------------------------------------------------------------------
2324 
2325 """ % (comment))
2326  ##
2327 
2328  #--
2329  def PrettyPrintMinorDivComment(self, fp, comment):
2330  """ Prints minor file division comment block.
2331 
2332  Parameters:
2333  fp - Opened output file pointer.
2334  comment - Minor division comment line.
2335  """
2336  fp.write("""\
2337 
2338 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2339 // %s
2340 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2341 
2342 """ % (comment))
2343  ##
2344 
2345  #--
2346  def PrettyPrintBriefComment(self, fp, brief):
2347  """ Print doxygen brief comment block.
2348 
2349  Parameters:
2350  fp - Opened output file pointer.
2351  brief - Brief comment.
2352  """
2353  fp.write("""\
2354 /*!
2355  * %s
2356  */
2357 """ % (brief))
2358  ##
2359 ##
mHBaseName
output .h header file basename
Definition: NetMsgsGenC.py:118
def WriteStructDecl(self, fp, indent, type_spec, cid, const_expr, kwargs)
def CMakeFieldDefThisDerived(self, ftype, fdef)
def CGenFIdEnum(self, fp, pathXids, xdef)
def CMakeFieldDefThisString(self, ftype, fdef)
def Pass0XmlDefStruct(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:248
def PrettyPrintTopComment(self, fp, srcbasename, brief)
def CGenVectorItemFieldDef(self, fp, pathXids, xdef)
def HGenTypedefMacros(self, fp, xid, xdef)
Definition: NetMsgsGenC.py:837
def HGenTypedef(self, fp, xid, xdef, brief)
Definition: NetMsgsGenC.py:726
def CGenAnonStruct(self, fp, pathXids, xdef)
def Pass0XmlDefString(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:375
def WriteFDefEntry(self, fp, sFName, eFId, eFType, uOffset, this, this_init)
def CMakeFieldDefThisStruct(self, ftype, fdef)
def HGenStructDeclList(self, fp, fields, depth)
Definition: NetMsgsGenC.py:775
NetMsgs Base Data Module.
Definition: NetMsgsBase.py:1
def Pass0XmlDefDerived(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:484
mXml
parsed xml instance
Definition: NetMsgsGenC.py:100
def WriteVectortDecl(self, fp, indent, vtype_spec, cid, const_expr)
def Pass0XmlDefPad(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:216
mCBaseName
output .c header file basename
Definition: NetMsgsGenC.py:121
def _FindRParen(self, expr, lparen=0)
def Pass0XmlDef(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:165
NetMsgs XML parser module.
def WriteFuncDef(self, fp, type_qual, type_spec, funcname, funcargs, kwargs)
def CMakeFieldDefThisNumber(self, ftype, fdef)
def CGenFieldDefs(self, fp, pathXids, xdef)
def _FindLowOp(self, expr, start=0)
def MakeCId(self, xid, isGlobal)
def PrettyPrintBriefComment(self, fp, brief)
def __init__(self, xml, hfilepath, cfilepath, kwargs)
Definition: NetMsgsGenC.py:88
mHFilePath
output .h header file name
Definition: NetMsgsGenC.py:103
mHungarian
do [not] prepend RN Hungarian notation to message fields
Definition: NetMsgsGenC.py:115
def WriteTypedefStmt(self, fp, type_spec, cid, const_expr)
def MakeCppMacroName(self, names)
def Pass0XmlDefSimple(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:439
def PrettyPrintMinorDivComment(self, fp, comment)
def _ParenExprParen(self, expr, start=0)
def PrettyPrintMajorDivComment(self, fp, comment)
def CGenMsgDef(self, fp, pathXids, xdef)
def CMakeFieldDefThisVector(self, ftype, fdef)
def CGenDefsR(self, fp, pathXids, xdef)
mCFilePath
output .c header file name
Definition: NetMsgsGenC.py:106
def Pass0XmlDefVector(self, pathXids, xdef, depth)
Definition: NetMsgsGenC.py:295
def CMakeFieldDefThisPad(self, ftype, fdef)
def CMakeFieldDefThis(self, ftype, fdef)