rtc-template.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- python -*-
3 #
4 # @file rtc-template
5 # @brief rtc-template RTComponent source code generator tool
6 # @date $Date: 2007/07/23 08:06:27 $
7 # @author Noriaki Ando <n-ando@aist.go.jp>
8 #
9 # Copyright (C) 2004-2007
10 # Task-intelligence Research Group,
11 # Intelligent Systems Research Institute,
12 # National Institute of
13 # Advanced Industrial Science and Technology (AIST), Japan
14 # All rights reserved.
15 #
16 # $Id: rtc-template,v 1.8.2.2 2007/07/23 08:06:27 n-ando Exp $
17 #
18 
19 #
20 # $Log: rtc-template,v $
21 # Revision 1.8.2.2 2007/07/23 08:06:27 n-ando
22 # Modified for win32 porting about rtm-config.
23 #
24 # Revision 1.8.2.1 2007/07/20 17:29:03 n-ando
25 # A fix for win32 porting.
26 #
27 # Revision 1.8 2007/04/27 00:56:35 n-ando
28 # Example shown in help message was modified for new version.
29 #
30 # Revision 1.7 2007/04/23 07:31:28 n-ando
31 # Now "--conf" option can accept scope resolution operator of C++.
32 #
33 # Revision 1.6 2007/04/23 01:41:21 n-ando
34 # New option "--config" and configuration template code were added.
35 #
36 # Revision 1.5 2007/01/11 07:42:25 n-ando
37 # Modified for OMG RTC specificatin and OpenRTM-aist-0.4.0
38 # - Some command option was chaged and removed.
39 # - Now empty Struct class is used instead of *Profile classes for ezt dict.
40 # - Some bugs were fixed.
41 #
42 # Revision 1.4 2005/09/08 09:24:18 n-ando
43 # - A bug fix for merge function.
44 #
45 # Revision 1.3 2005/09/06 14:37:40 n-ando
46 # rtc-template's command options and data structure for ezt (Easy Template)
47 # are changed for RTComponent's service features.
48 # Now rtc-template can generate services' skeletons, stubs and
49 # implementation files.
50 # The implementation code generation uses omniidl's IDL parser.
51 #
52 # Revision 1.2 2005/08/26 11:32:26 n-ando
53 # "rtc-template" was completely rewritten to use ezt (Easy Template) module.
54 # "ezt" module is originally included in "Subversion".
55 #
56 # Now template code generator modules, which are named xxx_gen.py, are
57 # automatically imported from rtc-template, and command options and help
58 # menu are automatically generated.
59 #
60 # New template code generator has to inherit base_gen class in
61 # "base_gen.py" module to utilize this framework.
62 #
63 # Revision 1.1.1.1 2005/05/12 09:06:18 n-ando
64 # Public release.
65 #
66 #
67 
68 import getopt, sys
69 import re
70 import os
71 
72 platform = sys.platform
73 
74 class Struct:
75  def __init__(self):
76  return
77 
78 conf_path = ['']
79 
80 if platform == "win32":
81  python_path = os.environ['PYTHONPATH'].split(";")
82  pyhelper_path = python_path[0] + "\\OpenRTM_aist\\utils\\rtc-template"
83 else:
84  conf_path = os.popen("which rtm-config", "r").read().split("\n")
85  if conf_path[0] != '':
86  libdir_path = os.popen("rtm-config --libdir", "r").read().split("\n")
87  pyhelper_path = libdir_path[0] + "/py_helper"
88  else:
89  python_path = os.environ['PYTHONPATH'].split(":")
90  pyhelper_path = python_path[0] + "/OpenRTM_aist/utils/rtc-template"
91 sys.path.append(pyhelper_path)
92 
93 # Option format
94 opt_args_fmt = ["help",
95  "module-name=",
96  "module-type=",
97  "module-desc=",
98  "module-version=",
99  "module-vendor=",
100  "module-category=",
101  "module-comp-type=",
102  "module-act-type=",
103  "module-max-inst=",
104  "module-lang=",
105  "config=",
106  "inport=",
107  "outport=",
108  "service=",
109  "service-idl=",
110  "consumer=",
111  "consumer-idl=",
112  "idl-include=",
113  "backend="]
114 
115 
117  """
118  Help message
119  """
120  print """
121 Usage: rtc-template [OPTIONS]
122 
123 Options:
124 
125  [-h] Print short help.
126  [--help] Print details help.
127  [--backend[=backend] or -b] Specify template code generator.
128  [--module-name[=name]] Your module name.
129  [--module-desc[=description]] Module description.
130  [--module-version[=version]] Module version.
131  [--module-vendor[=vendor]] Module vendor.
132  [--module-category[=category]] Module category.
133  [--module-comp-type[=component_type]] Component type.
134  [--module-act-type[=activity_type]] Component's activity type.
135  [--module-max-inst[=max_instance]] Number of maximum instance.
136  [--module-lang[=language]] Language.
137  [--config[=ParamName:Type:Default]] Configuration variable.
138  [--inport[=PortName:Type]] InPort's name and type.
139  [--outport[=PortName:Type]] OutPort's name and type
140  [--service[=PortName:Name:Type]] Service Provider Port
141  [--service-idl[=IDL_file]] IDL file name for service
142  [--consumer[=PortName:Name:Type]] Service Consumer Port
143  [--consumer-idl[=IDL_file]] IDL file name for consumer
144  [--idl-include=[path]] Search path for IDL compile
145 
146 """
148  """
149  Help message
150  """
151  print """
152  --output[=output_file]:
153  Specify base name of output file. If 'XXX' is specified,
154  C++ source codes XXX.cpp, XXX.h, XXXComp.cpp Makefile.XXX is generated.
155 
156  --module-name[=name]:
157  Your component's base name. This string is used as module's
158  name and component's base name. A generated new component
159  class name is also names as this RTC_MODULE_NAME.
160  Only alphabetical and numerical characters are acceptable.
161 
162  --module-desc[=description]:
163  Short description. If space characters are included, string should be
164  quoted.
165 
166  --module-version[=version]:
167  Your module version. ex. 1.0.0
168 
169  --module-vendor[=vendor]:
170  Vendor's name of this component.
171 
172  --module-category[=category]:
173  This component module's category. ex. Manipulator MobileRobot, etc...
174 
175  --module-comp-type[=component_type]:
176  Specify component type.
177  'STATIC', 'UNIQUE', 'COMMUTATIVE' are acceptable.
178 
179  --module-act-type[=activity_type]:
180  Specify component activity's type.
181  'PERIODIC', 'SPORADIC', 'EVENT_DRIVEN' ace acceptable.
182 
183  --module-max-inst[=max_instance]:
184  Specify maximum number of component instance.
185 
186  --config=[ParamName:Type:Default]:
187  Specify configuration value. The 'ParamName' is used as the
188  configuration value identifier. This character string is also used as
189  variable name in the source code. The 'Type' is type of configuration
190  value. The type that can be converted to character string is allowed.
191  In C++ language, the type should have operators '<<' and '>>' that
192  are defined as
193  'istream& operator<<(Type)'
194  and
195  'ostream& operator>>(Type)'.
196 
197  --inport=[PortName:Type]:
198  Specify InPort's name and type. 'PortName' is used as this InPort's
199  name. This string is also used as variable name in soruce code.
200  'Type' is InPort's variable type. The acceptable types are,
201  Timed[ Short | Long | UShort | ULong | Float | Double | Char | Boolean
202  | Octet | String ] and its sequence types.
203 
204  --outport=[PortName:Type]:
205  Specify OutPort's name and type. 'PortName' is used as this OutPort's
206  name. This string is also used as variable name in soruce code.
207  'Type' is OutPort's variable type. The acceptable types are,
208  Timed[ Short | Long | UShort | ULong | Float | Double | Char | Boolean
209  | Octet | String ] and its sequence types.
210 
211  --service=[PortName:Name:Type]:
212  Specify service name, type and port name.
213  PortName: The name of Port to which the interface belongs.
214  This name is used as CorbaPort's name.
215  Name: The name of the service interface. This name is used as
216  the name of the interface, instance name and variable name.
217  Type: The type of the serivce interface.
218  This name is used as type name of the service.
219 
220  --service-idl=[IDL filename]:
221  Specify IDL file of service interface.
222  For simplicity, please define one interface in one IDL file, although
223  this IDL file can include two or more interface definition,
224 
225  --consumer=[PortName:Name:Type]:
226  Specify consumer name, type and port name.
227  PortName: The name of Port to which the consumer belongs.
228  This name is used as CorbaPort's name.
229  Name: The name of the consumer. This name is used as
230  the name of the consumer, instance name and variable name.
231  Type: The serivce interface type that is required by the consumer.
232  This name is used as type name of the consumer.
233 
234  --consumer-idl=[IDL filename]:
235  Specify IDL file of service consumer.
236  For simplicity, please define one interface in one IDL file, although
237  this IDL file can include two or more interface definition,
238 
239 
240 Example:
241  rtc-template -bcxx \\
242  --module-name=Sample --module-desc='Sample component' \\
243  --module-version=0.1 --module-vendor=AIST --module-category=Generic \\
244  --module-comp-type=DataFlowComponent --module-act-type=SPORADIC \\
245  --module-max-inst=10 \\
246  --config=int_param0:int:0 --config=int_param1:int:1 \\
247  --config=double_param0:double:3.14 --config=double_param1:double:9.99 \\
248  --config="str_param0:std::string:hoge" \\
249  --config="str_param1:std::string:foo" \\
250  --inport=Ref:TimedFloat --inport=Sens:TimedFloat \\
251  --outport=Ctrl:TimedDouble --outport=Monitor:TimedShort \\
252  --service=MySvcPort:myservice0:MyService \\
253  --consumer=YourSvcPort:yourservice0:YourService \\
254  --service-idl=MyService.idl --consumer-idl=YourService.idl
255 
256 """
257  return
258 
259 def usage():
260  usage_short()
261  usage_long()
262  return
263 
265  """
266  ModuleProfile class
267 
268  This class create RTM module profile for ezt.
269  """
270 
271  def __init__(self, name="", desc="", type="", version="", vendor="",
272  category="", comp_type="", act_type="",
273  max_inst="", lang=""):
274 
275  self.name = name
276  self.desc = desc
277  self.type = type
278  self.version = version
279  self.vendor = vendor
280  self.category = category
281  self.comp_type = comp_type
282  self.act_type = act_type
283  self.max_inst = max_inst
284  self.lang = lang
285  return
286 
287 
288  def setValue(self, member, value):
289  member = member.replace("-", "_")
290  if hasattr(self, member):
291  setattr(self, member, value)
292  else:
293  print "Invalid option: --module-" + member + " " + value
294  return
295 
296  def setName(self, name):
297  self.name = name
298  return
299 
300  def setDesc(self, desc):
301  self.desc = desc
302  return
303 
304  def setVersion(self, version):
305  self.version = version
306  return
307 
308  def setVendor(self, vendor):
309  self.vendor = vendor
310  return
311 
312  def setCategory(self, vategory):
313  self.category = category
314  return
315 
316  def setCompType(self, comp_type):
317  self.comp_type = comp_type
318  return
319 
320  def setActType(self, act):
321  self.act_type = act_type
322  return
323 
324  def setMaxInst(self, max_inst):
325  self.max_inst = max_inst
326  return
327 
328  def printProfile(self):
329  print "----- Module Profile -----"
330  print "Name ", self.name
331  print "Description ", self.desc
332  print "Version ", self.version
333  print "Vendor ", self.vendor
334  print "Category ", self.category
335  print "Component Type ", self.comp_type
336  print "Activity Type ", self.act_type
337  print "Max Instancese ", self.max_inst
338  print "Language ", self.lang
339  return
340 
341 
342 
344  """
345  MakeModuleProfile
346 
347  Create ModuleProfile list from command options
348  """
349  prof = ModuleProfile()
350  for opt, arg in opts:
351  if opt.find("--module-") == 0:
352  var = opt.replace("--module-","")
353  prof.setValue(var, arg)
354  return prof
355 
356 
357 def MakeConfig(opts):
358  """
359  MakeConfigurationParameters
360 
361  Create Configuration list from command options
362  """
363  prof_list = []
364  cnt = 0
365  for opt, arg in opts:
366  if opt == ("--config"):
367  try:
368  # For C++ scope resolution operator
369  arg = re.sub("::", "@@", arg)
370  name, type, default = arg.split(":")
371  name = re.sub("@@", "::", name)
372  type = re.sub("@@", "::", type)
373  default = re.sub("@@", "::", default)
374  except:
375  sys.stderr("Invalid option: " \
376  + opt \
377  + "=" \
378  + arg)
379  prof = Struct()
380  prof.name = name
381  prof.l_name = name.lower()
382  prof.u_name = name.upper()
383  prof.type = type
384  prof.default = default
385  prof_list.append(prof)
386  cnt += 1
387  return prof_list
388 
389 
390 def MakeDataPort(opts, port_type):
391  """
392  MakePortProfile
393 
394  Create PortProfile list from command options
395  """
396  prof_list = []
397  cnt = 0
398  for opt, arg in opts:
399  if opt == ("--" + port_type):
400  try:
401  name, type = arg.split(":")
402  except:
403  sys.stderr("Invalid option: " \
404  + opt \
405  + "=" \
406  + arg)
407  prof = Struct()
408  prof.name = name
409  prof.type = type
410  prof.num = cnt
411  prof_list.append(prof)
412  cnt += 1
413  return prof_list
414 
415 
416 def MakePortInterface(opts, port_type):
417  """
418  MakePortInterface
419 
420  Create Port interface profile list from command options
421  """
422  prof_list = []
423  cnt = 0
424  for opt, arg in opts:
425  if opt == "--" + port_type:
426  try:
427  port, name, type = arg.split(":")
428  except:
429  sys.stderr.write("Invalid option: " \
430  + opt \
431  + "=" \
432  + arg)
433  prof = Struct()
434  prof.port = port
435  prof.name = name
436  prof.type = type
437  prof.num = cnt
438  prof_list.append(prof)
439  cnt += 1
440  return prof_list
441 
442 def MakeCorbaPort(opts):
443  """
444  MakeCorbaPort
445 
446  Create Corba Port profile list from command options
447  """
448  prof_list = []
449  cnt = 0
450  for opt, arg in opts:
451  if opt == ("--" + "service") or opt == ("--" + "consumer"):
452  try:
453  port, name, type = arg.split(":")
454  except:
455  sys.stderr.write("Invalid option: " \
456  + opt \
457  + "=" \
458  + arg)
459  dup = False
460  for p in prof_list:
461  if p.name == port:
462  dup = True
463  if dup == False:
464  prof = Struct()
465  prof.name = port
466  prof.num = cnt
467  prof_list.append(prof)
468  cnt += 1
469  return prof_list
470 
471 
472 
473 def MakeServiceIDL(opts):
474  """
475  MakeServiceIDL
476 
477  Create ServiceIDL list from command options
478  """
479  idl_list = []
480 
481  for opt, arg in opts:
482  if opt.find("--service-idl") == 0:
483  svc_idl = Struct()
484  svc_idl.idl_fname = arg
485  svc_idl.idl_basename, dummy = arg.split(".")
486  idl_list.append(svc_idl)
487  return idl_list
488 
489 
490 def MakeConsumerIDL(opts):
491  idl_list = []
492  for opt, arg in opts:
493  if opt == "--consumer-idl":
494  svc_idl = Struct()
495  svc_idl.idl_fname = arg
496  svc_idl.idl_basename, dummy = arg.split(".")
497  idl_list.append(svc_idl)
498  return idl_list
499 
500 
501 
502 def find_opt(opts, value, default):
503  for opt, arg in opts:
504  if opt.find(value) == 0:
505  return arg
506 
507  return default
508 
509 
510 def find_opt_list(opts, value, default):
511  list = []
512  if len(default) > 0:
513  list += default
514  for opt, arg in opts:
515  if opt == ("--" + value):
516  list.append(arg)
517  return list
518 
519 
520 class Backend:
521  def __init__(self, mod_name, mod):
522  self.mod = mod
523  self.obj = getattr(mod, mod_name)
524  self.mod_name = mod_name
525 
526 
528  def __init__(self):
529  self.backends = {}
530  self.opts = []
531  self.available()
532  return
533 
534 
535  def available(self):
536  path_list = [pyhelper_path, "."]
537  for path in path_list:
538  for f in os.listdir(path):
539  if re.compile("_gen.py$").search(f):
540  mod_name = f.replace(".py", "")
541  opt_name = f.replace("_gen.py", "")
542  mod = __import__(mod_name, globals(), locals(), [])
543  try:
544  mod.usage()
545  be = Backend(mod_name, mod)
546  self.backends[opt_name] = be
547  except:
548  print "Invalid backend: ", f
549  pass
550 
551  return self.backends
552 
553 
554  def check_args(self, args):
555  for opt in args:
556  if opt.find('-b') == 0:
557  backend_name = opt.replace("-b", "")
558  if self.backends.has_key(backend_name):
559  self.opts.append(backend_name)
560  else:
561  print "No such backend: ", backend_name
562  sys.exit(-1)
563  elif opt.find('--backend=') == 0:
564  backend_name = opt.replace("--backend=", "")
565  if self.backends.has_key(backend_name):
566  self.opts.append(backend_name)
567  else:
568  print "No such backend: ", backend_name
569  sys.exit(-1)
570  return self.opts
571 
572 
573  def get_opt_fmts(self):
574  fmts = []
575  for be in self.opts:
576  fmts += self.backends[be].mod.get_opt_fmt()
577  return fmts
578 
579 
580  def usage_available(self):
581  print "The following backends are available."
582  space = 10
583  for key in self.backends:
584  desc = self.backends[key].mod.description()
585  print " -b" + key + ("." * (space - len(key))) + desc
586  print """
587 Backend [xxx] specific help can be available by the following options.
588  -bxxx --help|-h or --backend=xxx --help|-h
589  """
590  return
591 
592 
593  def usage(self):
594  for be in self.opts:
595  print self.backends[be].mod.usage()
596  print ""
597  return
598 
599  def usage_short(self):
600  for be in self.opts:
601  print self.backends[be].mod.usage_short()
602  print ""
603  return
604 
605 
606  def generate_code(self, data, opts):
607  for be in self.opts:
608  self.backends[be].obj(data, opts).print_all()
609  return
610 
611 
612 def fmtd_args(width, args):
613  arg_fmt = [""]
614  w = 0
615  line = 0
616  for a in args:
617  w += len(a) + 1
618  if w > width:
619  w = len(a) + 1
620  line += 1
621  arg_fmt.append("")
622  arg_fmt[line] += a + " "
623  return arg_fmt
624 
625 
626 
627 def main():
628  global opt_args_fmt
629  global conf_path
630 
631  backends = BackendLoader()
632  backends.check_args(sys.argv[1:])
633  opt_args_fmt += backends.get_opt_fmts()
634 
635  try:
636  opts, args = getopt.getopt(sys.argv[1:], "b:ho:v", opt_args_fmt)
637  except getopt.GetoptError:
638  print "Error: Invalid option.", getopt.GetoptError
639  usage_short()
640  backends.usage_available()
641  sys.exit(-1)
642 
643  if not opts:
644  usage_short()
645  backends.usage_available()
646  sys.exit(-1)
647 
648  output = None
649  verbose = False
650  output_cxx = False
651  output_python = False
652 
653  for o, a in opts:
654  if o == "-v":
655  verbose = True
656  if o in ("-h"):
657  usage_short()
658  backends.usage_available()
659  backends.usage_short()
660  sys.exit(0)
661  if o in ("--help"):
662  usage()
663  backends.usage_available()
664  backends.usage()
665  sys.exit(0)
666  if o in ("-o", "--output"):
667  output = a
668  # ...
669 
670  prefix = [' ']
671  if conf_path[0] != '':
672  prefix = os.popen("rtm-config --prefix", "r").read().split("\n")
673  idl_inc = []
674  if prefix[0] != '':
675  idl_inc.append(prefix[0] + "/include/rtm/idl")
676  idl_inc.append(prefix[0] + "/include/rtm")
677  idl_inc.append(".")
678 
679  # Create dictionary for ezt
680  data = {
681  'module': MakeModuleProfile(opts),
682  'config': MakeConfig(opts),
683  'inport': MakeDataPort(opts, "inport"),
684  'outport': MakeDataPort(opts, "outport"),
685  'service': MakePortInterface(opts, "service"),
686  'consumer': MakePortInterface(opts, "consumer"),
687  'corbaport': MakeCorbaPort(opts),
688  'service_idl': MakeServiceIDL(opts),
689  'consumer_idl': MakeConsumerIDL(opts),
690  'idl_include': find_opt_list(opts, "--idl-include", idl_inc),
691  'fname': output,
692  'args': sys.argv,
693  'fmtd_args': fmtd_args(70, sys.argv)
694  }
695 
696  if data['fname'] == None:
697  data['fname'] = data['module'].name
698 
699  backends.generate_code(data, opts)
700 
701  import README_src
702  readme_src = README_src.README_src(data)
703  readme_src.print_all()
704  return
705 
706 
707 if __name__ == "__main__":
708  main()
def __init__(self, name="", desc="", type="", version="", vendor="", category="", comp_type="", act_type="", max_inst="", lang="")
def split(input, delimiter)
Split string by delimiter.
Definition: StringUtil.py:323
def append(dest, src)
Definition: NVUtil.py:386


openrtm_aist_python
Author(s): Shinji Kurihara
autogenerated on Mon Feb 28 2022 23:01:06