00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 import getopt, sys
00069 import re
00070 import os
00071
00072 platform = sys.platform
00073
00074 class Struct:
00075 def __init__(self):
00076 return
00077
00078 conf_path = ['']
00079
00080 if platform == "win32":
00081 python_path = os.environ['PYTHONPATH'].split(";")
00082 pyhelper_path = python_path[0] + "\\OpenRTM_aist\\utils\\rtc-template"
00083 else:
00084 conf_path = os.popen("which rtm-config", "r").read().split("\n")
00085 if conf_path[0] != '':
00086 libdir_path = os.popen("rtm-config --libdir", "r").read().split("\n")
00087 pyhelper_path = libdir_path[0] + "/py_helper"
00088 else:
00089 python_path = os.environ['PYTHONPATH'].split(":")
00090 pyhelper_path = python_path[0] + "/OpenRTM_aist/utils/rtc-template"
00091 sys.path.append(pyhelper_path)
00092
00093
00094 opt_args_fmt = ["help",
00095 "module-name=",
00096 "module-type=",
00097 "module-desc=",
00098 "module-version=",
00099 "module-vendor=",
00100 "module-category=",
00101 "module-comp-type=",
00102 "module-act-type=",
00103 "module-max-inst=",
00104 "module-lang=",
00105 "config=",
00106 "inport=",
00107 "outport=",
00108 "service=",
00109 "service-idl=",
00110 "consumer=",
00111 "consumer-idl=",
00112 "idl-include=",
00113 "backend="]
00114
00115
00116 def usage_short():
00117 """
00118 Help message
00119 """
00120 print """
00121 Usage: rtc-template [OPTIONS]
00122
00123 Options:
00124
00125 [-h] Print short help.
00126 [--help] Print details help.
00127 [--backend[=backend] or -b] Specify template code generator.
00128 [--module-name[=name]] Your module name.
00129 [--module-desc[=description]] Module description.
00130 [--module-version[=version]] Module version.
00131 [--module-vendor[=vendor]] Module vendor.
00132 [--module-category[=category]] Module category.
00133 [--module-comp-type[=component_type]] Component type.
00134 [--module-act-type[=activity_type]] Component's activity type.
00135 [--module-max-inst[=max_instance]] Number of maximum instance.
00136 [--module-lang[=language]] Language.
00137 [--config[=ParamName:Type:Default]] Configuration variable.
00138 [--inport[=PortName:Type]] InPort's name and type.
00139 [--outport[=PortName:Type]] OutPort's name and type
00140 [--service[=PortName:Name:Type]] Service Provider Port
00141 [--service-idl[=IDL_file]] IDL file name for service
00142 [--consumer[=PortName:Name:Type]] Service Consumer Port
00143 [--consumer-idl[=IDL_file]] IDL file name for consumer
00144 [--idl-include=[path]] Search path for IDL compile
00145
00146 """
00147 def usage_long():
00148 """
00149 Help message
00150 """
00151 print """
00152 --output[=output_file]:
00153 Specify base name of output file. If 'XXX' is specified,
00154 C++ source codes XXX.cpp, XXX.h, XXXComp.cpp Makefile.XXX is generated.
00155
00156 --module-name[=name]:
00157 Your component's base name. This string is used as module's
00158 name and component's base name. A generated new component
00159 class name is also names as this RTC_MODULE_NAME.
00160 Only alphabetical and numerical characters are acceptable.
00161
00162 --module-desc[=description]:
00163 Short description. If space characters are included, string should be
00164 quoted.
00165
00166 --module-version[=version]:
00167 Your module version. ex. 1.0.0
00168
00169 --module-vendor[=vendor]:
00170 Vendor's name of this component.
00171
00172 --module-category[=category]:
00173 This component module's category. ex. Manipulator MobileRobot, etc...
00174
00175 --module-comp-type[=component_type]:
00176 Specify component type.
00177 'STATIC', 'UNIQUE', 'COMMUTATIVE' are acceptable.
00178
00179 --module-act-type[=activity_type]:
00180 Specify component activity's type.
00181 'PERIODIC', 'SPORADIC', 'EVENT_DRIVEN' ace acceptable.
00182
00183 --module-max-inst[=max_instance]:
00184 Specify maximum number of component instance.
00185
00186 --config=[ParamName:Type:Default]:
00187 Specify configuration value. The 'ParamName' is used as the
00188 configuration value identifier. This character string is also used as
00189 variable name in the source code. The 'Type' is type of configuration
00190 value. The type that can be converted to character string is allowed.
00191 In C++ language, the type should have operators '<<' and '>>' that
00192 are defined as
00193 'istream& operator<<(Type)'
00194 and
00195 'ostream& operator>>(Type)'.
00196
00197 --inport=[PortName:Type]:
00198 Specify InPort's name and type. 'PortName' is used as this InPort's
00199 name. This string is also used as variable name in soruce code.
00200 'Type' is InPort's variable type. The acceptable types are,
00201 Timed[ Short | Long | UShort | ULong | Float | Double | Char | Boolean
00202 | Octet | String ] and its sequence types.
00203
00204 --outport=[PortName:Type]:
00205 Specify OutPort's name and type. 'PortName' is used as this OutPort's
00206 name. This string is also used as variable name in soruce code.
00207 'Type' is OutPort's variable type. The acceptable types are,
00208 Timed[ Short | Long | UShort | ULong | Float | Double | Char | Boolean
00209 | Octet | String ] and its sequence types.
00210
00211 --service=[PortName:Name:Type]:
00212 Specify service name, type and port name.
00213 PortName: The name of Port to which the interface belongs.
00214 This name is used as CorbaPort's name.
00215 Name: The name of the service interface. This name is used as
00216 the name of the interface, instance name and variable name.
00217 Type: The type of the serivce interface.
00218 This name is used as type name of the service.
00219
00220 --service-idl=[IDL filename]:
00221 Specify IDL file of service interface.
00222 For simplicity, please define one interface in one IDL file, although
00223 this IDL file can include two or more interface definition,
00224
00225 --consumer=[PortName:Name:Type]:
00226 Specify consumer name, type and port name.
00227 PortName: The name of Port to which the consumer belongs.
00228 This name is used as CorbaPort's name.
00229 Name: The name of the consumer. This name is used as
00230 the name of the consumer, instance name and variable name.
00231 Type: The serivce interface type that is required by the consumer.
00232 This name is used as type name of the consumer.
00233
00234 --consumer-idl=[IDL filename]:
00235 Specify IDL file of service consumer.
00236 For simplicity, please define one interface in one IDL file, although
00237 this IDL file can include two or more interface definition,
00238
00239
00240 Example:
00241 rtc-template -bcxx \\
00242 --module-name=Sample --module-desc='Sample component' \\
00243 --module-version=0.1 --module-vendor=AIST --module-category=Generic \\
00244 --module-comp-type=DataFlowComponent --module-act-type=SPORADIC \\
00245 --module-max-inst=10 \\
00246 --config=int_param0:int:0 --config=int_param1:int:1 \\
00247 --config=double_param0:double:3.14 --config=double_param1:double:9.99 \\
00248 --config="str_param0:std::string:hoge" \\
00249 --config="str_param1:std::string:foo" \\
00250 --inport=Ref:TimedFloat --inport=Sens:TimedFloat \\
00251 --outport=Ctrl:TimedDouble --outport=Monitor:TimedShort \\
00252 --service=MySvcPort:myservice0:MyService \\
00253 --consumer=YourSvcPort:yourservice0:YourService \\
00254 --service-idl=MyService.idl --consumer-idl=YourService.idl
00255
00256 """
00257 return
00258
00259 def usage():
00260 usage_short()
00261 usage_long()
00262 return
00263
00264 class ModuleProfile:
00265 """
00266 ModuleProfile class
00267
00268 This class create RTM module profile for ezt.
00269 """
00270
00271 def __init__(self, name="", desc="", type="", version="", vendor="",
00272 category="", comp_type="", act_type="",
00273 max_inst="", lang=""):
00274
00275 self.name = name
00276 self.desc = desc
00277 self.type = type
00278 self.version = version
00279 self.vendor = vendor
00280 self.category = category
00281 self.comp_type = comp_type
00282 self.act_type = act_type
00283 self.max_inst = max_inst
00284 self.lang = lang
00285 return
00286
00287
00288 def setValue(self, member, value):
00289 member = member.replace("-", "_")
00290 if hasattr(self, member):
00291 setattr(self, member, value)
00292 else:
00293 print "Invalid option: --module-" + member + " " + value
00294 return
00295
00296 def setName(self, name):
00297 self.name = name
00298 return
00299
00300 def setDesc(self, desc):
00301 self.desc = desc
00302 return
00303
00304 def setVersion(self, version):
00305 self.version = version
00306 return
00307
00308 def setVendor(self, vendor):
00309 self.vendor = vendor
00310 return
00311
00312 def setCategory(self, vategory):
00313 self.category = category
00314 return
00315
00316 def setCompType(self, comp_type):
00317 self.comp_type = comp_type
00318 return
00319
00320 def setActType(self, act):
00321 self.act_type = act_type
00322 return
00323
00324 def setMaxInst(self, max_inst):
00325 self.max_inst = max_inst
00326 return
00327
00328 def printProfile(self):
00329 print "----- Module Profile -----"
00330 print "Name ", self.name
00331 print "Description ", self.desc
00332 print "Version ", self.version
00333 print "Vendor ", self.vendor
00334 print "Category ", self.category
00335 print "Component Type ", self.comp_type
00336 print "Activity Type ", self.act_type
00337 print "Max Instancese ", self.max_inst
00338 print "Language ", self.lang
00339 return
00340
00341
00342
00343 def MakeModuleProfile(opts):
00344 """
00345 MakeModuleProfile
00346
00347 Create ModuleProfile list from command options
00348 """
00349 prof = ModuleProfile()
00350 for opt, arg in opts:
00351 if opt.find("--module-") == 0:
00352 var = opt.replace("--module-","")
00353 prof.setValue(var, arg)
00354 return prof
00355
00356
00357 def MakeConfig(opts):
00358 """
00359 MakeConfigurationParameters
00360
00361 Create Configuration list from command options
00362 """
00363 prof_list = []
00364 cnt = 0
00365 for opt, arg in opts:
00366 if opt == ("--config"):
00367 try:
00368
00369 arg = re.sub("::", "@@", arg)
00370 name, type, default = arg.split(":")
00371 name = re.sub("@@", "::", name)
00372 type = re.sub("@@", "::", type)
00373 default = re.sub("@@", "::", default)
00374 except:
00375 sys.stderr("Invalid option: " \
00376 + opt \
00377 + "=" \
00378 + arg)
00379 prof = Struct()
00380 prof.name = name
00381 prof.l_name = name.lower()
00382 prof.u_name = name.upper()
00383 prof.type = type
00384 prof.default = default
00385 prof_list.append(prof)
00386 cnt += 1
00387 return prof_list
00388
00389
00390 def MakeDataPort(opts, port_type):
00391 """
00392 MakePortProfile
00393
00394 Create PortProfile list from command options
00395 """
00396 prof_list = []
00397 cnt = 0
00398 for opt, arg in opts:
00399 if opt == ("--" + port_type):
00400 try:
00401 name, type = arg.split(":")
00402 except:
00403 sys.stderr("Invalid option: " \
00404 + opt \
00405 + "=" \
00406 + arg)
00407 prof = Struct()
00408 prof.name = name
00409 prof.type = type
00410 prof.num = cnt
00411 prof_list.append(prof)
00412 cnt += 1
00413 return prof_list
00414
00415
00416 def MakePortInterface(opts, port_type):
00417 """
00418 MakePortInterface
00419
00420 Create Port interface profile list from command options
00421 """
00422 prof_list = []
00423 cnt = 0
00424 for opt, arg in opts:
00425 if opt == "--" + port_type:
00426 try:
00427 port, name, type = arg.split(":")
00428 except:
00429 sys.stderr.write("Invalid option: " \
00430 + opt \
00431 + "=" \
00432 + arg)
00433 prof = Struct()
00434 prof.port = port
00435 prof.name = name
00436 prof.type = type
00437 prof.num = cnt
00438 prof_list.append(prof)
00439 cnt += 1
00440 return prof_list
00441
00442 def MakeCorbaPort(opts):
00443 """
00444 MakeCorbaPort
00445
00446 Create Corba Port profile list from command options
00447 """
00448 prof_list = []
00449 cnt = 0
00450 for opt, arg in opts:
00451 if opt == ("--" + "service") or opt == ("--" + "consumer"):
00452 try:
00453 port, name, type = arg.split(":")
00454 except:
00455 sys.stderr.write("Invalid option: " \
00456 + opt \
00457 + "=" \
00458 + arg)
00459 dup = False
00460 for p in prof_list:
00461 if p.name == port:
00462 dup = True
00463 if dup == False:
00464 prof = Struct()
00465 prof.name = port
00466 prof.num = cnt
00467 prof_list.append(prof)
00468 cnt += 1
00469 return prof_list
00470
00471
00472
00473 def MakeServiceIDL(opts):
00474 """
00475 MakeServiceIDL
00476
00477 Create ServiceIDL list from command options
00478 """
00479 idl_list = []
00480
00481 for opt, arg in opts:
00482 if opt.find("--service-idl") == 0:
00483 svc_idl = Struct()
00484 svc_idl.idl_fname = arg
00485 svc_idl.idl_basename, dummy = arg.split(".")
00486 idl_list.append(svc_idl)
00487 return idl_list
00488
00489
00490 def MakeConsumerIDL(opts):
00491 idl_list = []
00492 for opt, arg in opts:
00493 if opt == "--consumer-idl":
00494 svc_idl = Struct()
00495 svc_idl.idl_fname = arg
00496 svc_idl.idl_basename, dummy = arg.split(".")
00497 idl_list.append(svc_idl)
00498 return idl_list
00499
00500
00501
00502 def find_opt(opts, value, default):
00503 for opt, arg in opts:
00504 if opt.find(value) == 0:
00505 return arg
00506
00507 return default
00508
00509
00510 def find_opt_list(opts, value, default):
00511 list = []
00512 if len(default) > 0:
00513 list += default
00514 for opt, arg in opts:
00515 if opt == ("--" + value):
00516 list.append(arg)
00517 return list
00518
00519
00520 class Backend:
00521 def __init__(self, mod_name, mod):
00522 self.mod = mod
00523 self.obj = getattr(mod, mod_name)
00524 self.mod_name = mod_name
00525
00526
00527 class BackendLoader:
00528 def __init__(self):
00529 self.backends = {}
00530 self.opts = []
00531 self.available()
00532 return
00533
00534
00535 def available(self):
00536 path_list = [pyhelper_path, "."]
00537 for path in path_list:
00538 for f in os.listdir(path):
00539 if re.compile("_gen.py$").search(f):
00540 mod_name = f.replace(".py", "")
00541 opt_name = f.replace("_gen.py", "")
00542 mod = __import__(mod_name, globals(), locals(), [])
00543 try:
00544 mod.usage()
00545 be = Backend(mod_name, mod)
00546 self.backends[opt_name] = be
00547 except:
00548 print "Invalid backend: ", f
00549 pass
00550
00551 return self.backends
00552
00553
00554 def check_args(self, args):
00555 for opt in args:
00556 if opt.find('-b') == 0:
00557 backend_name = opt.replace("-b", "")
00558 if self.backends.has_key(backend_name):
00559 self.opts.append(backend_name)
00560 else:
00561 print "No such backend: ", backend_name
00562 sys.exit(-1)
00563 elif opt.find('--backend=') == 0:
00564 backend_name = opt.replace("--backend=", "")
00565 if self.backends.has_key(backend_name):
00566 self.opts.append(backend_name)
00567 else:
00568 print "No such backend: ", backend_name
00569 sys.exit(-1)
00570 return self.opts
00571
00572
00573 def get_opt_fmts(self):
00574 fmts = []
00575 for be in self.opts:
00576 fmts += self.backends[be].mod.get_opt_fmt()
00577 return fmts
00578
00579
00580 def usage_available(self):
00581 print "The following backends are available."
00582 space = 10
00583 for key in self.backends:
00584 desc = self.backends[key].mod.description()
00585 print " -b" + key + ("." * (space - len(key))) + desc
00586 print """
00587 Backend [xxx] specific help can be available by the following options.
00588 -bxxx --help|-h or --backend=xxx --help|-h
00589 """
00590 return
00591
00592
00593 def usage(self):
00594 for be in self.opts:
00595 print self.backends[be].mod.usage()
00596 print ""
00597 return
00598
00599 def usage_short(self):
00600 for be in self.opts:
00601 print self.backends[be].mod.usage_short()
00602 print ""
00603 return
00604
00605
00606 def generate_code(self, data, opts):
00607 for be in self.opts:
00608 self.backends[be].obj(data, opts).print_all()
00609 return
00610
00611
00612 def fmtd_args(width, args):
00613 arg_fmt = [""]
00614 w = 0
00615 line = 0
00616 for a in args:
00617 w += len(a) + 1
00618 if w > width:
00619 w = len(a) + 1
00620 line += 1
00621 arg_fmt.append("")
00622 arg_fmt[line] += a + " "
00623 return arg_fmt
00624
00625
00626
00627 def main():
00628 global opt_args_fmt
00629 global conf_path
00630
00631 backends = BackendLoader()
00632 backends.check_args(sys.argv[1:])
00633 opt_args_fmt += backends.get_opt_fmts()
00634
00635 try:
00636 opts, args = getopt.getopt(sys.argv[1:], "b:ho:v", opt_args_fmt)
00637 except getopt.GetoptError:
00638 print "Error: Invalid option.", getopt.GetoptError
00639 usage_short()
00640 backends.usage_available()
00641 sys.exit(-1)
00642
00643 if not opts:
00644 usage_short()
00645 backends.usage_available()
00646 sys.exit(-1)
00647
00648 output = None
00649 verbose = False
00650 output_cxx = False
00651 output_python = False
00652
00653 for o, a in opts:
00654 if o == "-v":
00655 verbose = True
00656 if o in ("-h"):
00657 usage_short()
00658 backends.usage_available()
00659 backends.usage_short()
00660 sys.exit(0)
00661 if o in ("--help"):
00662 usage()
00663 backends.usage_available()
00664 backends.usage()
00665 sys.exit(0)
00666 if o in ("-o", "--output"):
00667 output = a
00668
00669
00670 prefix = [' ']
00671 if conf_path[0] != '':
00672 prefix = os.popen("rtm-config --prefix", "r").read().split("\n")
00673 idl_inc = []
00674 if prefix[0] != '':
00675 idl_inc.append(prefix[0] + "/include/rtm/idl")
00676 idl_inc.append(prefix[0] + "/include/rtm")
00677 idl_inc.append(".")
00678
00679
00680 data = {
00681 'module': MakeModuleProfile(opts),
00682 'config': MakeConfig(opts),
00683 'inport': MakeDataPort(opts, "inport"),
00684 'outport': MakeDataPort(opts, "outport"),
00685 'service': MakePortInterface(opts, "service"),
00686 'consumer': MakePortInterface(opts, "consumer"),
00687 'corbaport': MakeCorbaPort(opts),
00688 'service_idl': MakeServiceIDL(opts),
00689 'consumer_idl': MakeConsumerIDL(opts),
00690 'idl_include': find_opt_list(opts, "--idl-include", idl_inc),
00691 'fname': output,
00692 'args': sys.argv,
00693 'fmtd_args': fmtd_args(70, sys.argv)
00694 }
00695
00696 if data['fname'] == None:
00697 data['fname'] = data['module'].name
00698
00699 backends.generate_code(data, opts)
00700
00701 import README_src
00702 readme_src = README_src.README_src(data)
00703 readme_src.print_all()
00704 return
00705
00706
00707 if __name__ == "__main__":
00708 main()