Pull some changes from RELEASE-3_1 in gen_sct and *.sct

This commit is contained in:
Douglas Clowes
2015-02-19 09:48:38 +11:00
parent bf8be461ee
commit a5498a2a77
3 changed files with 632 additions and 259 deletions

View File

@ -5,7 +5,7 @@ driver isotech_ps = {
vendor = isotech; device = ps; protocol = std; vendor = isotech; device = ps; protocol = std;
class = environment; class = environment;
simulation_group = environment_simulation; simulation_group = environment_simulation;
protocol_args = '"\r"'; protocol_args = '{terminator \r}';
group = { group = {
readable = 5 readable = 5
mutable = true mutable = true

View File

@ -8,7 +8,7 @@ driver julabo_lh45_gen = {
simulation_group = environment_simulation simulation_group = environment_simulation
add_args = '{id 1} {ctrl_sensor "bath"} {tol 5.0}'; add_args = '{id 1} {ctrl_sensor "bath"} {tol 5.0}';
make_args = 'id ctrl_sensor tol'; make_args = 'id ctrl_sensor tol';
protocol_args = '"\r"'; protocol_args = '{terminator \r}';
# #
# Unnamed group has variables at device level # Unnamed group has variables at device level
# #
@ -22,7 +22,7 @@ driver julabo_lh45_gen = {
permlink = 'T.SP01'; permlink = 'T.SP01';
writeable = 1; write_function = setPoint; write_command = 'out_sp_00'; writeable = 1; write_function = setPoint; write_command = 'out_sp_00';
driveable = sensor/'value'; driveable = sensor/'value';
lowerlimit = 10; upperlimit = 90; tolerance = '${tol}'; lowerlimit = -20; upperlimit = 90; tolerance = '${tol}';
} }
var overtemp_warnlimit = { var overtemp_warnlimit = {
read_command = 'in_sp_03'; read_command = 'in_sp_03';

View File

@ -30,17 +30,10 @@
# #
import os import os
import re
import ply.lex as lex import ply.lex as lex
import ply.yacc as yacc import ply.yacc as yacc
global Verbose
global DriverDump
global CodeDump
global FunctionTypes
global DriveableFunctionTypes
global NumberOfLinesIn
global NumberOfLinesOut
states = ( states = (
('tcl', 'exclusive'), ('tcl', 'exclusive'),
) )
@ -63,6 +56,34 @@ DriveableFunctionTypes = [
Verbose = False Verbose = False
DriverDump = False DriverDump = False
CodeDump = False CodeDump = False
PrintedFileName = -1
NumberOfLinesIn = 0
NumberOfLinesOut = 0
SourceFileList = []
SourceLineList = []
def PrintParseError(message):
global PrintedFileName
global lexer
global SourceLineList, SourceData
curr_line = lexer.lineno
curr_file = SourceLineList[curr_line - 1][0]
if curr_file != PrintedFileName:
PrintedFileName = curr_file
SourceFile = SourceFileList[curr_file]
print "in", SourceFile
print message
print "%4d:" % SourceLineList[curr_line - 1][1], SourceData[curr_line - 1]
def PrintPostError(message):
global PrintedFileName
global SourceLineList
curr_file = 0
if curr_file != PrintedFileName:
PrintedFileName = curr_file
SourceFile = SourceFileList[curr_file]
print "in", SourceFile
print message
# #
# Tokenizer: This recognizes the tokens which can be keywords, identifiers, # Tokenizer: This recognizes the tokens which can be keywords, identifiers,
@ -96,6 +117,7 @@ reserved = {
'VAR' : 'VAR', 'VAR' : 'VAR',
'PROPERTY' : 'PROPERTY', 'PROPERTY' : 'PROPERTY',
'CONTROL' : 'CONTROL', 'CONTROL' : 'CONTROL',
'CONDITIONAL' : 'CONDITIONAL',
'DATA' : 'DATA', 'DATA' : 'DATA',
'NXSAVE' : 'NXSAVE', 'NXSAVE' : 'NXSAVE',
'MUTABLE' : 'MUTABLE', 'MUTABLE' : 'MUTABLE',
@ -212,16 +234,17 @@ def t_tcl_newline(t):
t.lexer.lineno += t.value.count("\n") t.lexer.lineno += t.value.count("\n")
def t_tcl_error(t): def t_tcl_error(t):
print("Illegal tcl character '%s'" % t.value[0]) message = "Illegal tcl character '%s'" % t.value[0]
PrintParseError(message)
t.lexer.skip(1) t.lexer.skip(1)
def t_TEXT_STRING1(t): def t_TEXT_STRING1(t):
r'\'[^\']+\'' r'\'[^\']*\''
t.value = t.value[1:-1] t.value = t.value[1:-1]
return t return t
def t_TEXT_STRING2(t): def t_TEXT_STRING2(t):
r"\"[^\"]+\"" r"\"[^\"]*\""
t.value = t.value[1:-1] t.value = t.value[1:-1]
return t return t
@ -240,7 +263,8 @@ def t_FLOATER(t):
try: try:
t.value = float(t.value) t.value = float(t.value)
except ValueError: except ValueError:
print "Floating value invalid:", t.value message = "Floating value invalid: " + repr(t.value)
PrintParseError(message)
t.value = 0.0 t.value = 0.0
return t return t
@ -249,7 +273,8 @@ def t_INTEGER(t):
try: try:
t.value = int(t.value) t.value = int(t.value)
except ValueError: except ValueError:
print "Integer value too large:", t.value message = "Integer value too large: " + repr(t.value)
PrintParseError(message)
t.value = 0 t.value = 0
return t return t
@ -270,7 +295,9 @@ def t_newline(t):
t.lexer.lineno += t.value.count("\n") t.lexer.lineno += t.value.count("\n")
def t_error(t): def t_error(t):
print("Illegal character '%s'" % t.value[0]) message = "Illegal character '%s' at line %d" % \
(t.value[0], t.lexer.lineno)
PrintParseError(message)
t.lexer.skip(1) t.lexer.skip(1)
# #
@ -430,6 +457,7 @@ def p_var_typ_ass(p):
| DATA EQUALS true_false | DATA EQUALS true_false
| NXSAVE EQUALS true_false | NXSAVE EQUALS true_false
| MUTABLE EQUALS true_false | MUTABLE EQUALS true_false
| CONDITIONAL EQUALS text_string
''' '''
p[0] = { p[1] : p[3] } p[0] = { p[1] : p[3] }
@ -532,6 +560,14 @@ def p_code(p):
| CODE code_type id_or_str EQUALS LBRACE tcl_code_block RBRACE | CODE code_type id_or_str EQUALS LBRACE tcl_code_block RBRACE
| CODE code_type id_or_str EQUALS TCL_BEG code_block TCL_END | CODE code_type id_or_str EQUALS TCL_BEG code_block TCL_END
''' '''
if p[3].lower() == 'preamble':
name = 'preamble'
elif p[3].lower() == 'postamble':
name = 'postamble'
elif p[3].lower() == 'mkdriver':
name = 'mkDriver'
elif p[3].lower() == 'mkwrapper':
name = 'mkWrapper'
p[0] = { 'Code' : { 'name' : p[3], 'type' : p[2], 'text' : p[6] }} p[0] = { 'Code' : { 'name' : p[3], 'type' : p[2], 'text' : p[6] }}
def p_code_type(p): def p_code_type(p):
@ -585,7 +621,10 @@ def p_empty(p):
pass pass
def p_error(t): def p_error(t):
print("Syntax error at '%s'" % t.value), t message = "Syntax error at line %d" % lexer.lineno
message += " " + repr(t)
message += " " + repr(t.value)
PrintParseError(message)
# #
# Utility functions # Utility functions
@ -598,6 +637,54 @@ def make_path(MyVar):
path += MyVar['name'] path += MyVar['name']
return path return path
def generate_filename(MyDriver):
global args
old_name = "sct_%s.tcl" % MyDriver['name']
new_name = "%s_sct.tcl" % MyDriver['name']
if 'PathName' in MyDriver:
full_old_name = os.path.join(MyDriver['PathName'], old_name)
full_new_name = os.path.join(MyDriver['PathName'], new_name)
else:
full_old_name = old_name
full_new_name = new_name
# This block of code generates shell commands to help the old->new rename
if Move:
fd = open("git_mv.sh", "a")
fd.write( "git mv " + full_old_name + " " + full_new_name + "\n")
fd.close()
fd = open("grep_sed.sh", "a")
fd.write( "for f in $(grep " + old_name + " instrument -Irl" + "); do\n")
fd.write( " echo ${f}\n")
fd.write( " sed -i ${f} -e 's/" + old_name + "/" + new_name + "/'\n")
fd.write( "done\n")
fd.close()
if args.sct == "before":
MyDriver['filename'] = old_name
MyDriver['fullname'] = full_old_name
else:
MyDriver['filename'] = new_name
MyDriver['fullname'] = full_new_name
def parse_args(arg_str):
'''
Parse the TCL argument string into a list of identifiers (in order) plus
a map of identifier to default value (or None) returned as a 2-tuple
'''
arg_list = re.findall(r'({[^}]+}|[A-Za-z0-9_]+)', arg_str)
arg_lst = []
arg_map = {}
for arg in arg_list:
if arg.startswith('{'):
bits = arg[1:-1].split(None, 1)
arg_lst.append(bits[0])
arg_map[bits[0]] = bits[1]
else:
arg_lst.append(arg)
arg_map[arg] = None
return (arg_lst, arg_map)
# #
# This section handles building a driver tree from the Abstract Syntax Tree # This section handles building a driver tree from the Abstract Syntax Tree
# generated by the parser. The driver tree has all of the defaults and # generated by the parser. The driver tree has all of the defaults and
@ -709,7 +796,8 @@ def build_variable(MyDriver, p):
MyDriver['Funcs'][MyVar[func]]['type'] = func MyDriver['Funcs'][MyVar[func]]['type'] = func
else: else:
# TODO FIXME error message # TODO FIXME error message
print 'Error: Function type mismatch: var = ' + str(MyVar) + ', code = ' + str(MyDriver['Funcs'][MyVar[func]]) + ', func = ' + str(func) message = 'Error: Function type mismatch: var = ' + str(MyVar) + ', code = ' + str(MyDriver['Funcs'][MyVar[func]]) + ', func = ' + str(func)
PrintPostError(message)
MyDriver['Funcs'][MyVar[func]]['reference_count'] += 1 MyDriver['Funcs'][MyVar[func]]['reference_count'] += 1
if 'permlink' in MyVar: if 'permlink' in MyVar:
device_type, node_type = MyVar['permlink'].split('.') device_type, node_type = MyVar['permlink'].split('.')
@ -802,6 +890,30 @@ def adjust_group(MyGroup):
if Verbose: if Verbose:
print 'post adjust_group', MyGroup print 'post adjust_group', MyGroup
def check_func_code(MyDriver):
for name in MyDriver['Funcs']:
#print name
left_paren_count = 0
right_paren_count = 0
left_brack_count = 0
right_brack_count = 0
left_brace_count = 0
right_brace_count = 0
for idx, line in enumerate(MyDriver['Funcs'][name]['text']):
#print "%4d:" % (idx + 1), line
left_paren_count += line.count('(')
right_paren_count += line.count(')')
left_brack_count += line.count('[')
right_brack_count += line.count(']')
left_brace_count += line.count('{')
right_brace_count += line.count('}')
if left_paren_count != right_paren_count:
PrintPostError("Warning: Mismatched Parens in function %s (%d != %d)" % (name, left_paren_count, right_paren_count))
if left_brack_count != right_brack_count:
PrintPostError("Warning: Mismatched Brackets in function %s (%d != %d)" % (name, left_brack_count, right_brack_count))
if left_brace_count != right_brace_count:
PrintPostError("Warning: Mismatched Braces in function %s (%d != %d)" % (name, left_brace_count, right_brace_count))
def build_driver(MyDriver, TheTree): def build_driver(MyDriver, TheTree):
if Verbose: if Verbose:
print "TheTree:", TheTree print "TheTree:", TheTree
@ -834,7 +946,34 @@ def build_driver(MyDriver, TheTree):
MyDriver[key] = item[key] MyDriver[key] = item[key]
for item in MyDriver['Permlink']: for item in MyDriver['Permlink']:
if len(MyDriver['Permlink'][item]) > 1: if len(MyDriver['Permlink'][item]) > 1:
print 'Error: duplicate permlink entries for "%s"' % item, MyDriver['Permlink'][item] message = 'Error: duplicate permlink entries for "%s"' % item
message += " " + repr(MyDriver['Permlink'][item])
PrintPostError(message)
if 'add_args' in MyDriver:
MyDriver['add_args_lst'], MyDriver['add_args_map'] = parse_args(MyDriver['add_args'])
if Verbose:
print "ADD_ARGS:", MyDriver['add_args']
arg_map = MyDriver['add_args_map']
for arg in arg_map:
print ' %s:' % arg, arg_map[arg]
if 'make_args' in MyDriver:
MyDriver['make_args_lst'], MyDriver['make_args_map'] = parse_args(MyDriver['make_args'])
if Verbose:
print "MAKE_ARGS:", MyDriver['make_args']
arg_map = MyDriver['make_args_map']
for arg in arg_map:
print ' %s:' % arg, arg_map[arg]
if 'protocol_args' in MyDriver:
MyDriver['protocol_args_lst'], MyDriver['protocol_args_map'] = parse_args(MyDriver['protocol_args'])
if Verbose:
print "PROTOCOL_ARGS:", MyDriver['protocol_args']
arg_map = MyDriver['protocol_args_map']
for arg in arg_map:
print ' %s:' % arg, arg_map[arg]
if 'add_args_lst' in MyDriver and 'make_args_lst' in MyDriver:
if MyDriver['add_args_lst'] != MyDriver['make_args_lst']:
print "Add_Args:", MyDriver['add_args_lst']
print "Make_Args:", MyDriver['make_args_lst']
if Verbose: if Verbose:
print "MyDriver:", MyDriver print "MyDriver:", MyDriver
# #
@ -872,10 +1011,10 @@ def dump_driver_groups(groups, indent):
if Comment in groups[item]: if Comment in groups[item]:
print indent + ' # %s = \'%s\'' % (Comment, groups[item][Comment]) print indent + ' # %s = \'%s\'' % (Comment, groups[item][Comment])
for subitem in sorted([x for x in groups[item] if not x in Deferred]): for subitem in sorted([x for x in groups[item] if not x in Deferred]):
print indent + ' ', subitem, '=', groups[item][subitem] print indent + ' ', subitem, '= \'%s\'' % groups[item][subitem]
if 'GroupProperty' in groups[item]: if 'GroupProperty' in groups[item]:
for subitem in groups[item]['GroupProperty']: for subitem in groups[item]['GroupProperty']:
print indent + ' GroupProperty', subitem, '=', groups[item]['GroupProperty'][subitem] print indent + ' GroupProperty', subitem, '= \'%s\'' % groups[item]['GroupProperty'][subitem]
dump_driver_vars(groups[item]['Vars'], indent) dump_driver_vars(groups[item]['Vars'], indent)
dump_driver_groups(groups[item]['Groups'], indent + ' ') dump_driver_groups(groups[item]['Groups'], indent + ' ')
print indent + '}' print indent + '}'
@ -893,6 +1032,12 @@ def dump_driver_funcs(funcs):
def dump_driver(MyDriver): def dump_driver(MyDriver):
print 'DRIVER ' + MyDriver['name'] + ' = {' print 'DRIVER ' + MyDriver['name'] + ' = {'
Comments = ['PathName', 'Permlink'] Comments = ['PathName', 'Permlink']
Comments += ['add_args_lst']
Comments += ['add_args_map']
Comments += ['make_args_lst']
Comments += ['make_args_map']
Comments += ['protocol_args_lst']
Comments += ['protocol_args_map']
Deferred = ['Groups', 'Funcs', 'Deferred', 'name'] + Comments Deferred = ['Groups', 'Funcs', 'Deferred', 'name'] + Comments
for Comment in sorted(Comments): for Comment in sorted(Comments):
if Comment in MyDriver: if Comment in MyDriver:
@ -924,21 +1069,29 @@ def put_preamble(MyDriver):
txt += ['namespace eval %s {' % MyDriver['namespace']] txt += ['namespace eval %s {' % MyDriver['namespace']]
txt += [' set debug_threshold %s' % str( MyDriver['debug_threshold'])] txt += [' set debug_threshold %s' % str( MyDriver['debug_threshold'])]
if len(MyDriver['Permlink']) > 0: if len(MyDriver['Permlink']) > 0:
if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): if 'make_args_lst' in MyDriver and 'id' in MyDriver['make_args_lst']:
pass pass
else: else:
txt += [' if { ![info exists ::scobj::permlink_device_counter]} {'] txt += [' if { ![info exists ::scobj::permlink_device_counter]} {']
txt += [' set ::scobj::permlink_device_counter 0'] txt += [' set ::scobj::permlink_device_counter 0']
txt += [' }'] txt += [' }']
func = 'preamble'
if func in MyDriver['Funcs']:
txt += ['# %s hook code starts' % func]
txt += MyDriver['Funcs'][func]['text']
txt += ['# %s hook code ends' % func]
txt += ['}'] txt += ['}']
txt += [''] txt += ['']
txt += ['proc %s::debug_log {tc_root debug_level debug_string} {' % MyDriver['namespace']] txt += ['proc %s::debug_log {tc_root debug_level debug_string} {' % MyDriver['namespace']]
txt += [' set catch_status [ catch {'] txt += [' set catch_status [ catch {']
txt += [' set debug_threshold [hgetpropval ${tc_root} debug_threshold]'] txt += [' set debug_threshold [hgetpropval ${tc_root} debug_threshold]']
txt += [' if {${debug_level} >= ${debug_threshold}} {'] txt += [' if {${debug_level} >= ${debug_threshold}} {']
txt += [' set fd [open "../log/%s_[basename ${tc_root}].log" "a"]' % MyDriver['name']] txt += [' set now [clock seconds]']
txt += [' set line "[clock format [clock seconds] -format "%T"] ${debug_string}"'] txt += [' set ts [clock format ${now} -format "%Y%m%d"]']
txt += [' puts ${fd} "${line}"'] txt += [' set log_file_name "../log/%s_[basename ${tc_root}]_${ts}.log"' % MyDriver['name']]
txt += [' set fd [open "${log_file_name}" "a"]']
txt += [' set ts [clock format ${now} -format "%T"]']
txt += [' puts ${fd} "${ts} ${debug_string}"']
txt += [' close ${fd}'] txt += [' close ${fd}']
txt += [' }'] txt += [' }']
txt += [' } catch_message ]'] txt += [' } catch_message ]']
@ -1158,7 +1311,12 @@ def put_checkstatus_function(MyDriver, func):
txt += ['# %s hook code goes here' % func] txt += ['# %s hook code goes here' % func]
txt += [' if {[sct driving]} {'] txt += [' if {[sct driving]} {']
txt += [' set sp "[sct target]"'] txt += [' set sp "[sct target]"']
txt += [' if {[hpropexists [sct] simulated] && [sct simulated] == "true"} {']
txt += [' set pv "${sp}"']
txt += [' hupdateif ${tc_root}/[sct driveable] ${sp}']
txt += [' } else {']
txt += [' set pv "[hval ${tc_root}/[sct driveable]]"'] txt += [' set pv "[hval ${tc_root}/[sct driveable]]"']
txt += [' }']
txt += [' if { abs(${pv} - ${sp}) <= [sct tolerance] } {'] txt += [' if { abs(${pv} - ${sp}) <= [sct tolerance] } {']
txt += [' if { [hpropexists [sct] settle_time] } {'] txt += [' if { [hpropexists [sct] settle_time] } {']
txt += [' if { [hpropexists [sct] settle_time_start] } {'] txt += [' if { [hpropexists [sct] settle_time_start] } {']
@ -1217,14 +1375,14 @@ def put_pid_function(MyDriver, func):
txt += [' set p_value [expr {[sct pid_pvalue] * [sct pid_error]}]'] txt += [' set p_value [expr {[sct pid_pvalue] * [sct pid_error]}]']
txt += [' set d_value [expr {[sct pid_dvalue] * (${pv} - [sct oldval])}]'] txt += [' set d_value [expr {[sct pid_dvalue] * (${pv} - [sct oldval])}]']
txt += [' sct pid_deriv [sct pid_error]'] txt += [' sct pid_deriv [sct pid_error]']
txt += [' sct pid_integ [expr {[sct pid_integ] + [sct pid_error]}]'] txt += [' sct pid_integ [expr {[sct pid_integ] + [sct pid_error] * [sct pid_ivalue]}]']
txt += [' if { [sct pid_integ] > [sct pid_imax] } {'] txt += [' if { [sct pid_integ] > [sct pid_imax] } {']
txt += [' sct pid_integ [sct pid_imax]'] txt += [' sct pid_integ [sct pid_imax]']
txt += [' }'] txt += [' }']
txt += [' if { [sct pid_integ] < -[sct pid_imax] } {'] txt += [' if { [sct pid_integ] < -[sct pid_imax] } {']
txt += [' sct pid_integ -[sct pid_imax]'] txt += [' sct pid_integ -[sct pid_imax]']
txt += [' }'] txt += [' }']
txt += [' set i_value [expr {[sct pid_ivalue] * [sct pid_integ]}]'] txt += [' set i_value [sct pid_integ]']
txt += [' set pid [expr {${p_value} + ${i_value} + ${d_value}}]'] txt += [' set pid [expr {${p_value} + ${i_value} + ${d_value}}]']
if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0:
txt += ['# %s hook code starts' % func] txt += ['# %s hook code starts' % func]
@ -1239,22 +1397,15 @@ def put_pid_function(MyDriver, func):
txt += ['}'] txt += ['}']
emit(txt) emit(txt)
def put_group(MyDriver, MyGroup): def put_var(MyDriver, MyGroup, MyVar):
readable_or_writeable = False readable_or_writeable = False
txt = [] txt = []
postfix = []
if MyGroup['name']: if MyGroup['name']:
txt += [''] nodename = MyGroup['path'] + '/' + MyVar['name']
txt += [' hfactory ${scobj_hpath}/%s plain spy none' % MyGroup['path']]
if 'GroupProperty' in MyGroup:
for key in sorted(MyGroup['GroupProperty']):
txt += [' hsetprop ${scobj_hpath}/%s %s "%s"' % (MyGroup['path'], key, MyGroup['GroupProperty'][key])]
groupname = MyGroup['path'] + '/'
else: else:
groupname = '' nodename = MyVar['name']
for var in sorted(MyGroup['Vars']):
txt += ['']
MyVar = MyGroup['Vars'][var]
nodename = groupname + MyVar['name']
# Check driveable attributes are present if required # Check driveable attributes are present if required
if 'driveable' in MyVar and MyVar['driveable']: if 'driveable' in MyVar and MyVar['driveable']:
for attr in ('lowerlimit', 'upperlimit', 'tolerance'): for attr in ('lowerlimit', 'upperlimit', 'tolerance'):
@ -1276,6 +1427,7 @@ def put_group(MyDriver, MyGroup):
msg = 'PID: %s does not have required attribute: %s' % (nodename, attr) msg = 'PID: %s does not have required attribute: %s' % (nodename, attr)
print 'Warning:', msg print 'Warning:', msg
txt += [' # Warning: ' + msg] txt += [' # Warning: ' + msg]
txt += [' hfactory ${scobj_hpath}/%s plain %s %s' % (nodename, MyVar['priv'], MyVar['type'])] txt += [' hfactory ${scobj_hpath}/%s plain %s %s' % (nodename, MyVar['priv'], MyVar['type'])]
if MyVar['readable'] > 0: if MyVar['readable'] > 0:
readable_or_writeable = True readable_or_writeable = True
@ -1283,7 +1435,10 @@ def put_group(MyDriver, MyGroup):
if fetch_func == 'none': if fetch_func == 'none':
fetch_func = 'getValue' fetch_func = 'getValue'
read_func = MyVar['read_function'] read_func = MyVar['read_function']
if 'read_command' in MyVar:
read_command = MyVar['read_command'] read_command = MyVar['read_command']
else:
read_command = ''
txt += [' hsetprop ${scobj_hpath}/%s read ${ns}::%s ${scobj_hpath} %s {%s}' % (nodename, fetch_func, read_func, read_command)] txt += [' hsetprop ${scobj_hpath}/%s read ${ns}::%s ${scobj_hpath} %s {%s}' % (nodename, fetch_func, read_func, read_command)]
txt += [' hsetprop ${scobj_hpath}/%s %s ${ns}::%s ${scobj_hpath}' % (nodename, read_func, read_func)] txt += [' hsetprop ${scobj_hpath}/%s %s ${ns}::%s ${scobj_hpath}' % (nodename, read_func, read_func)]
if MyVar['writeable'] > 0 or MyVar['driveable']: if MyVar['writeable'] > 0 or MyVar['driveable']:
@ -1328,12 +1483,13 @@ def put_group(MyDriver, MyGroup):
if 'permlink' in MyVar: if 'permlink' in MyVar:
device_type, node_type = MyVar['permlink'].split('.') device_type, node_type = MyVar['permlink'].split('.')
if device_type.startswith("#"): if device_type.startswith("#"):
if 'make_args' in MyDriver and 'permlink' in MyDriver['make_args'].split(): if 'make_args_lst' in MyDriver and 'permlink' in MyDriver['make_args_lst']:
idx = int(device_type[1:]) idx = int(device_type[1:])
device_type = '[string index ${permlink} %d]' % idx device_type = '[string index ${permlink} %d]' % idx
else: else:
print 'Error: permlink required in make_ags' message = 'Error: permlink required in make_ags'
if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): PrintPostError(message)
if 'make_args_lst' in MyDriver and 'id' in MyDriver['make_args_lst']:
permlink = device_type + '[format "%02d" ${id}]' + node_type permlink = device_type + '[format "%02d" ${id}]' + node_type
else: else:
permlink = device_type + '${permlink_device_number}' + node_type permlink = device_type + '${permlink_device_number}' + node_type
@ -1357,17 +1513,10 @@ def put_group(MyDriver, MyGroup):
if 'nxalias' not in MyVar['Property']: if 'nxalias' not in MyVar['Property']:
nxalias = '${name}_' + make_path(MyVar) nxalias = '${name}_' + make_path(MyVar)
txt += [' hsetprop ${scobj_hpath}/%s nxalias "%s"' % (nodename, nxalias)] txt += [' hsetprop ${scobj_hpath}/%s nxalias "%s"' % (nodename, nxalias)]
if not MyGroup['name']:
if 'GroupProperty' in MyGroup:
txt += ['']
for key in sorted(MyGroup['GroupProperty']):
txt += [' hsetprop ${scobj_hpath} %s "%s"' % (key, MyGroup['GroupProperty'][key])]
if readable_or_writeable: if readable_or_writeable:
txt += [''] txt += ['']
txt += [' if {[string equal -nocase "${simulation_flag}" "false"]} {'] txt += [' if {[string equal -nocase "${simulation_flag}" "false"]} {']
for var in sorted(MyGroup['Vars']):
MyVar = MyGroup['Vars'][var]
nodename = groupname + MyVar['name']
if MyVar['readable'] > 0: if MyVar['readable'] > 0:
poll_period = MyVar['readable'] poll_period = MyVar['readable']
if poll_period < 1: if poll_period < 1:
@ -1375,20 +1524,74 @@ def put_group(MyDriver, MyGroup):
if poll_period > 3600: if poll_period > 3600:
poll_period = 3600 poll_period = 3600
txt += [' ${sct_controller} poll ${scobj_hpath}/%s %s' % (nodename, poll_period)] txt += [' ${sct_controller} poll ${scobj_hpath}/%s %s' % (nodename, poll_period)]
for var in sorted(MyGroup['Vars']):
MyVar = MyGroup['Vars'][var]
nodename = groupname + MyVar['name']
if MyVar['writeable'] > 0 or MyVar['driveable']: if MyVar['writeable'] > 0 or MyVar['driveable']:
txt += [' ${sct_controller} write ${scobj_hpath}/%s' % nodename] txt += [' ${sct_controller} write ${scobj_hpath}/%s' % nodename]
if MyVar['driveable']: if MyVar['driveable']:
# Generate <dev>_<group...>_<name> at runtime for driveable # Generate <dev>_<group...>_<name> at runtime for driveable
driveable = '${name}_' + make_path(MyVar) driveable = '${name}_' + make_path(MyVar)
MyDriver['Deferred'] += ['ansto_makesctdrive %s ${scobj_hpath}/%s ${scobj_hpath}/%s ${sct_controller}' % (driveable, nodename, MyVar['driveable'])] postfix += [' ansto_makesctdrive %s ${scobj_hpath}/%s ${scobj_hpath}/%s ${sct_controller}' % (driveable, nodename, MyVar['driveable'])]
txt += [' hsetprop ${scobj_hpath}/%s simulated false' % nodename]
txt += [' } else {'] txt += [' } else {']
txt += [' %s::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for %s"' % (MyDriver['namespace'], MyDriver['name'])] txt += [' %s::sics_log 9 "simulation_flag=${simulation_flag} => No poll/write for %s"' % (MyDriver['namespace'], MyDriver['name'])]
txt += [' hsetprop ${scobj_hpath}/%s simulated true' % nodename]
txt += [' }'] txt += [' }']
if 'conditional' in MyVar:
for idx, line in enumerate(txt):
if len(line) > 0:
txt[idx] = ' ' + line
txt.insert(0, ' if {%s} {' % MyVar['conditional'])
txt.append(' }')
if len(postfix) > 0:
for idx, line in enumerate(postfix):
if len(line) > 0:
postfix[idx] = ' ' + line
postfix.insert(0, ' if {%s} {' % MyVar['conditional'])
postfix.append(' }')
return (txt, postfix)
def put_group(MyDriver, MyGroup):
txt = []
dfr = []
if MyGroup['name']:
txt += ['']
txt += [' hfactory ${scobj_hpath}/%s plain spy none' % MyGroup['path']]
else:
pass
for var in sorted(MyGroup['Vars']):
txt += ['']
MyVar = MyGroup['Vars'][var]
infix, postfix = put_var(MyDriver, MyGroup, MyVar)
txt += infix
dfr += postfix
if MyGroup['name']:
if 'GroupProperty' in MyGroup:
for key in sorted(MyGroup['GroupProperty']):
txt += [' hsetprop ${scobj_hpath}/%s %s "%s"' % (MyGroup['path'], key, MyGroup['GroupProperty'][key])]
else:
if 'GroupProperty' in MyGroup:
txt += ['']
for key in sorted(MyGroup['GroupProperty']):
txt += [' hsetprop ${scobj_hpath} %s "%s"' % (key, MyGroup['GroupProperty'][key])]
for grp in sorted(MyGroup['Groups']): for grp in sorted(MyGroup['Groups']):
txt += put_group(MyDriver, MyGroup['Groups'][grp]) txt += put_group(MyDriver, MyGroup['Groups'][grp])
txt += dfr
if 'conditional' in MyGroup:
for idx, line in enumerate(txt):
if len(line) > 0:
txt[idx] = ' ' + line
if len(txt[0]) == 0:
txt.pop(0)
txt.insert(0, ' if {%s} {' % MyGroup['conditional'])
txt.insert(0, '')
txt.append(' }')
return txt return txt
def put_mkDriver(MyDriver): def put_mkDriver(MyDriver):
@ -1398,8 +1601,8 @@ def put_mkDriver(MyDriver):
else: else:
line = 'proc %s::mkDriver { sct_controller name device_class simulation_flag ip_address tcp_port } {' % (MyDriver['namespace']) line = 'proc %s::mkDriver { sct_controller name device_class simulation_flag ip_address tcp_port } {' % (MyDriver['namespace'])
txt += [line] txt += [line]
if 'make_args' in MyDriver: if 'make_args_lst' in MyDriver:
make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args_lst']])
txt += [' %s::sics_log 9 "%s::mkDriver ${sct_controller} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] txt += [' %s::sics_log 9 "%s::mkDriver ${sct_controller} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)]
else: else:
txt += [' %s::sics_log 9 "%s::mkDriver ${sct_controller} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}"' % (MyDriver['namespace'], MyDriver['namespace'])] txt += [' %s::sics_log 9 "%s::mkDriver ${sct_controller} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}"' % (MyDriver['namespace'], MyDriver['namespace'])]
@ -1413,7 +1616,7 @@ def put_mkDriver(MyDriver):
txt += ['# %s hook code ends' % func] txt += ['# %s hook code ends' % func]
else: else:
if len(MyDriver['Permlink']) > 0: if len(MyDriver['Permlink']) > 0:
if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): if 'make_args_lst' in MyDriver and 'id' in MyDriver['make_args_lst']:
pass pass
else: else:
txt += [' set permlink_device_number [format "%02d" [incr ::scobj::permlink_device_counter]]'] txt += [' set permlink_device_number [format "%02d" [incr ::scobj::permlink_device_counter]]']
@ -1425,6 +1628,7 @@ def put_mkDriver(MyDriver):
ms_line = ' MakeSICSObj ${name} SCT_OBJECT' ms_line = ' MakeSICSObj ${name} SCT_OBJECT'
txt += [ms_line] txt += [ms_line]
txt += [''] txt += ['']
txt += [' sicslist setatt ${name} driver %s' % MyDriver['name']]
txt += [' sicslist setatt ${name} klass ${device_class}'] txt += [' sicslist setatt ${name} klass ${device_class}']
txt += [' sicslist setatt ${name} long_name ${name}'] txt += [' sicslist setatt ${name} long_name ${name}']
if 'DriverProperty' in MyDriver: if 'DriverProperty' in MyDriver:
@ -1436,6 +1640,7 @@ def put_mkDriver(MyDriver):
for group in sorted(MyDriver['Groups']): for group in sorted(MyDriver['Groups']):
txt += put_group(MyDriver, MyDriver['Groups'][group]) txt += put_group(MyDriver, MyDriver['Groups'][group])
txt += [' hsetprop ${scobj_hpath} driver %s' % MyDriver['name']]
txt += [' hsetprop ${scobj_hpath} klass ${device_class}'] txt += [' hsetprop ${scobj_hpath} klass ${device_class}']
txt += [' hsetprop ${scobj_hpath} data true'] txt += [' hsetprop ${scobj_hpath} data true']
txt += [' hsetprop ${scobj_hpath} debug_threshold %s' % str(MyDriver['debug_threshold'])] txt += [' hsetprop ${scobj_hpath} debug_threshold %s' % str(MyDriver['debug_threshold'])]
@ -1456,7 +1661,7 @@ def put_mkDriver(MyDriver):
txt += ['}'] txt += ['}']
emit(txt) emit(txt)
def put_postamble(MyDriver): def put_add_driver(MyDriver):
txt = [''] txt = ['']
if 'add_args' in MyDriver: if 'add_args' in MyDriver:
line = 'proc %s::add_driver {name device_class simulation_flag ip_address tcp_port %s} {' % (MyDriver['namespace'], MyDriver['add_args']) line = 'proc %s::add_driver {name device_class simulation_flag ip_address tcp_port %s} {' % (MyDriver['namespace'], MyDriver['add_args'])
@ -1464,8 +1669,8 @@ def put_postamble(MyDriver):
line = 'proc %s::add_driver {name device_class simulation_flag ip_address tcp_port} {' % (MyDriver['namespace']) line = 'proc %s::add_driver {name device_class simulation_flag ip_address tcp_port} {' % (MyDriver['namespace'])
txt += [line] txt += [line]
txt += [' set catch_status [ catch {'] txt += [' set catch_status [ catch {']
if 'make_args' in MyDriver: if 'make_args_lst' in MyDriver:
make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args_lst']])
txt += [' %s::sics_log 9 "%s::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] txt += [' %s::sics_log 9 "%s::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)]
else: else:
txt += [' %s::sics_log 9 "%s::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}"' % (MyDriver['namespace'], MyDriver['namespace'])] txt += [' %s::sics_log 9 "%s::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}"' % (MyDriver['namespace'], MyDriver['namespace'])]
@ -1478,18 +1683,29 @@ def put_postamble(MyDriver):
txt += [' makesctcontroller sct_${name} aqadapter ${tcp_port}'] txt += [' makesctcontroller sct_${name} aqadapter ${tcp_port}']
txt += [' } else {'] txt += [' } else {']
if 'protocol_args' in MyDriver: if 'protocol_args' in MyDriver:
protocol_args = MyDriver['protocol_args'].replace('\\', '\\\\').replace('"', '\\"') protocol_args = []
txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${ip_address}:${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['protocol'], protocol_args)] for arg in MyDriver['protocol_args_lst']:
txt += [' makesctcontroller sct_${name} %s ${ip_address}:${tcp_port} %s' % (MyDriver['protocol'], MyDriver['protocol_args'])] if 'add_args_lst' in MyDriver and arg in MyDriver['add_args_lst']:
protocol_args.append('${%s}' % arg)
elif arg in MyDriver['protocol_args_map'] and MyDriver['protocol_args_map'][arg] is not None:
protocol_args.append(MyDriver['protocol_args_map'][arg])
else:
PrintPostError('Protocol arg %s is not in add_args and has no default' % arg)
tmp = ' '.join(protocol_args).replace('\\', '\\\\').replace('"', '\\"')
txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${ip_address}:${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['protocol'], tmp)]
tmp = ' '.join(protocol_args)
txt += [' makesctcontroller sct_${name} %s ${ip_address}:${tcp_port} %s' % (MyDriver['protocol'], tmp)]
else: else:
txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${ip_address}:${tcp_port}"' % (MyDriver['namespace'], MyDriver['protocol'])] txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${ip_address}:${tcp_port}"' % (MyDriver['namespace'], MyDriver['protocol'])]
txt += [' makesctcontroller sct_${name} %s ${ip_address}:${tcp_port}' % MyDriver['protocol']] txt += [' makesctcontroller sct_${name} %s ${ip_address}:${tcp_port}' % MyDriver['protocol']]
txt += [' }'] txt += [' }']
txt += [' } else {'] txt += [' } else {']
txt += [' %s::sics_log 9 "simulation_flag={simulation_flag} => No sctcontroller for %s"' % (MyDriver['namespace'], MyDriver['name'])] txt += [' %s::sics_log 9 "simulation_flag=${simulation_flag} => Null sctcontroller for %s"' % (MyDriver['namespace'], MyDriver['name'])]
txt += [' %s::sics_log 9 "makesctcontroller sct_${name} aqadapter NULL"' % MyDriver['namespace']]
txt += [' makesctcontroller sct_${name} aqadapter NULL']
txt += [' }'] txt += [' }']
if 'make_args' in MyDriver: if 'make_args_lst' in MyDriver:
make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args_lst']])
txt += [' %s::sics_log 1 "%s::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] txt += [' %s::sics_log 1 "%s::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)]
txt += [' %s::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s' % (MyDriver['namespace'], make_args)] txt += [' %s::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} %s' % (MyDriver['namespace'], make_args)]
else: else:
@ -1501,13 +1717,21 @@ def put_postamble(MyDriver):
txt += [' } catch_message ]'] txt += [' } catch_message ]']
txt += [' handle_exception ${catch_status} ${catch_message}'] txt += [' handle_exception ${catch_status} ${catch_message}']
txt += ['}'] txt += ['}']
txt += [''] emit(txt)
def put_postamble(MyDriver):
txt = ['']
txt += ['namespace eval %s {' % MyDriver['namespace']] txt += ['namespace eval %s {' % MyDriver['namespace']]
txt += [' namespace export debug_threshold'] txt += [' namespace export debug_threshold']
txt += [' namespace export debug_log'] txt += [' namespace export debug_log']
txt += [' namespace export sics_log'] txt += [' namespace export sics_log']
txt += [' namespace export mkDriver'] txt += [' namespace export mkDriver']
txt += [' namespace export add_driver'] txt += [' namespace export add_driver']
func = 'postamble'
if func in MyDriver['Funcs']:
txt += ['# %s hook code starts' % func]
txt += MyDriver['Funcs'][func]['text']
txt += ['# %s hook code ends' % func]
txt += ['}'] txt += ['}']
txt += [''] txt += ['']
if 'add_args' in MyDriver: if 'add_args' in MyDriver:
@ -1516,15 +1740,17 @@ def put_postamble(MyDriver):
line = 'proc add_%s {name ip_address tcp_port} {' % MyDriver['name'] line = 'proc add_%s {name ip_address tcp_port} {' % MyDriver['name']
txt += [line] txt += [line]
txt += [' set simulation_flag "[string tolower [SplitReply [%s]]]"' % MyDriver['simulation_group']] txt += [' set simulation_flag "[string tolower [SplitReply [%s]]]"' % MyDriver['simulation_group']]
line = ' %s::add_driver ${name} "%s" "${simulation_flag}" ${ip_address} ${tcp_port}' % (MyDriver['namespace'], MyDriver['class']) line = ' %s::add_driver ${name} "%s"' % (MyDriver['namespace'], MyDriver['class'])
if 'add_args' in MyDriver: for arg in ['simulation_flag', 'ip_address', 'tcp_port']:
for arg in MyDriver['add_args'].split(): line += ' ${%s}' % arg
line += ' "${%s}"' % arg if 'add_args_lst' in MyDriver:
for arg in MyDriver['add_args_lst']:
line += ' ${%s}' % arg
txt += [line] txt += [line]
txt += ['}'] txt += ['}']
txt += [''] txt += ['']
txt += ['clientput "file evaluation of sct_%s.tcl"' % MyDriver['name']] txt += ['clientput "file evaluation of %s"' % MyDriver['filename']]
txt += ['%s::sics_log 9 "file evaluation of sct_%s.tcl"' % (MyDriver['namespace'], MyDriver['name'])] txt += ['%s::sics_log 9 "file evaluation of %s"' % (MyDriver['namespace'], MyDriver['filename'])]
emit(txt) emit(txt)
def put_read_config(MyDriver): def put_read_config(MyDriver):
@ -1559,14 +1785,52 @@ def put_read_config(MyDriver):
txt += [' continue'] txt += [' continue']
txt += [' }'] txt += [' }']
txt += [' if { [string equal -nocase [dict get $v "driver"] "%s"] } {' % MyDriver['name']] txt += [' if { [string equal -nocase [dict get $v "driver"] "%s"] } {' % MyDriver['name']]
if ('WrapperProperty' in MyDriver) and ('nosctcontroller' in MyDriver['WrapperProperty']):
txt += [' %s::sics_log 9 "No sctcontroller for %s"' % (MyDriver['namespace'], MyDriver['name'])]
txt += [' set ip_address [dict get $v ip]']
txt += [' set tcp_port [dict get $v port]']
else:
txt += [' if { ![string equal -nocase "${simulation_flag}" "false"] } {'] txt += [' if { ![string equal -nocase "${simulation_flag}" "false"] } {']
txt += [' set asyncqueue "null"'] txt += [' set asyncqueue "null"']
txt += [' ${ns}::sics_log 9 "simulation_flag=${simulation_flag} => using null asyncqueue"'] txt += [' ${ns}::sics_log 9 "simulation_flag=${simulation_flag} => using null asyncqueue"']
txt += [' ${ns}::sics_log 9 "makesctcontroller sct_${name} aqadapter NULL"']
txt += [' makesctcontroller sct_${name} aqadapter NULL']
txt += [' } elseif { [dict exists $v "asyncqueue"] } {'] txt += [' } elseif { [dict exists $v "asyncqueue"] } {']
txt += [' set asyncqueue [dict get $v "asyncqueue"]'] txt += [' set asyncqueue [dict get $v "asyncqueue"]']
txt += [' if { [string equal -nocase ${asyncqueue} "sct"] } {'] txt += [' if { [string equal -nocase ${asyncqueue} "sct"] } {']
txt += [' set ip_address [dict get $v ip]'] txt += [' set ip_address [dict get $v ip]']
txt += [' set tcp_port [dict get $v port]'] txt += [' set tcp_port [dict get $v port]']
if 'protocol_args_lst' in MyDriver:
txt += [' set arg_list [list]']
txt += [' set missing_list [list]']
default_list = []
for arg in [key for key in MyDriver['protocol_args_lst'] if MyDriver['protocol_args_map'][key] is not None]:
default_list += [arg, MyDriver['protocol_args_map'][arg]]
if len(default_list) > 0:
txt += [' array unset default_map']
txt += [' array set default_map [list %s]' % ' '.join(default_list)]
txt += [' foreach arg {' + ' '.join(MyDriver['protocol_args_lst']) + '} {']
txt += [' if {[dict exists $u $arg]} {']
txt += [' lappend arg_list "[dict get $u $arg]"']
txt += [' } elseif {[dict exists $v $arg]} {']
txt += [' lappend arg_list "[dict get $v $arg]"']
if len(default_list) > 0:
txt += [' } elseif {[info exists default_map($arg)]} {']
txt += [' lappend arg_list $default_map($arg)']
txt += [' } else {']
txt += [' ${ns}::sics_log 9 "Missing configuration value $arg"']
txt += [' lappend missing_list $arg']
txt += [' }']
txt += [' }']
txt += [' if { [llength $missing_list] > 0 } {']
txt += [' error "$name is missing configuration values $missing_list"']
txt += [' }']
protocol_args = ' {*}$arg_list'
else:
protocol_args = ''
txt += [' makesctcontroller sct_${name} %s ${ip_address}:${tcp_port}%s' % (MyDriver['protocol'], protocol_args)]
txt += [' } else {']
txt += [' makesctcontroller sct_${name} aqadapter ${asyncqueue}']
txt += [' }'] txt += [' }']
txt += [' } else {'] txt += [' } else {']
txt += [' if { [dict exists $v "asyncprotocol"] } {'] txt += [' if { [dict exists $v "asyncprotocol"] } {']
@ -1574,8 +1838,14 @@ def put_read_config(MyDriver):
txt += [' } else {'] txt += [' } else {']
txt += [' set asyncprotocol ${name}_protocol'] txt += [' set asyncprotocol ${name}_protocol']
txt += [' MakeAsyncProtocol ${asyncprotocol}'] txt += [' MakeAsyncProtocol ${asyncprotocol}']
txt += [' if { [dict exists $v "terminator"] } {'] txt += [' if { [dict exists $v "sendterminator"] } {']
txt += [' ${asyncprotocol} sendterminator "[dict get $v "sendterminator"]"']
txt += [' } elseif { [dict exists $v "terminator"] } {']
txt += [' ${asyncprotocol} sendterminator "[dict get $v "terminator"]"'] txt += [' ${asyncprotocol} sendterminator "[dict get $v "terminator"]"']
txt += [' }']
txt += [' if { [dict exists $v "replyterminator"] } {']
txt += [' ${asyncprotocol} replyterminator "[dict get $v "replyterminator"]"']
txt += [' } elseif { [dict exists $v "terminator"] } {']
txt += [' ${asyncprotocol} replyterminator "[dict get $v "terminator"]"'] txt += [' ${asyncprotocol} replyterminator "[dict get $v "terminator"]"']
txt += [' }'] txt += [' }']
txt += [' }'] txt += [' }']
@ -1586,15 +1856,25 @@ def put_read_config(MyDriver):
txt += [' if { [dict exists $v "timeout"] } {'] txt += [' if { [dict exists $v "timeout"] } {']
txt += [' ${asyncqueue} timeout "[dict get $v "timeout"]"'] txt += [' ${asyncqueue} timeout "[dict get $v "timeout"]"']
txt += [' }'] txt += [' }']
txt += [' makesctcontroller sct_${name} aqadapter ${asyncqueue}']
txt += [' }'] txt += [' }']
if 'make_args' in MyDriver: if 'make_args_lst' in MyDriver:
txt += [' set arg_list [list]'] txt += [' set arg_list [list]']
txt += [' set missing_list [list]'] txt += [' set missing_list [list]']
txt += [' foreach arg {' + MyDriver['make_args'] + '} {'] default_list = []
for arg in [key for key in MyDriver['make_args_lst'] if MyDriver['make_args_map'][key] is not None]:
default_list += [arg, MyDriver['make_args_map'][arg]]
if len(default_list) > 0:
txt += [' array unset default_map']
txt += [' array set default_map [list %s]' % ' '.join(default_list)]
txt += [' foreach arg {' + ' '.join(MyDriver['make_args_lst']) + '} {']
txt += [' if {[dict exists $u $arg]} {'] txt += [' if {[dict exists $u $arg]} {']
txt += [' lappend arg_list "[dict get $u $arg]"'] txt += [' lappend arg_list "[dict get $u $arg]"']
txt += [' } elseif {[dict exists $v $arg]} {'] txt += [' } elseif {[dict exists $v $arg]} {']
txt += [' lappend arg_list "[dict get $v $arg]"'] txt += [' lappend arg_list "[dict get $v $arg]"']
if len(default_list) > 0:
txt += [' } elseif {[info exists default_map($arg)]} {']
txt += [' lappend arg_list $default_map($arg)']
txt += [' } else {'] txt += [' } else {']
txt += [' ${ns}::sics_log 9 "Missing configuration value $arg"'] txt += [' ${ns}::sics_log 9 "Missing configuration value $arg"']
txt += [' lappend missing_list $arg'] txt += [' lappend missing_list $arg']
@ -1603,17 +1883,10 @@ def put_read_config(MyDriver):
txt += [' if { [llength $missing_list] > 0 } {'] txt += [' if { [llength $missing_list] > 0 } {']
txt += [' error "$name is missing configuration values $missing_list"'] txt += [' error "$name is missing configuration values $missing_list"']
txt += [' }'] txt += [' }']
txt += [' if { [string equal -nocase ${asyncqueue} "sct"] } {'] make_args = ' {*}$arg_list'
txt += [' ${ns}::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port} {*}$arg_list']
txt += [' } else {']
txt += [' ${ns}::add_driver ${name} ${device_class} ${simulation_flag} "aqadapter" ${asyncqueue} {*}$arg_list']
txt += [' }']
else: else:
txt += [' if { [string equal -nocase ${asyncqueue} "sct"] } {'] make_args = ''
txt += [' ${ns}::add_driver ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}'] txt += [' ${ns}::mkDriver sct_${name} ${name} ${device_class} ${simulation_flag} ${ip_address} ${tcp_port}' + make_args]
txt += [' } else {']
txt += [' ${ns}::add_driver ${name} ${device_class} ${simulation_flag} "aqadapter" ${asyncqueue}']
txt += [' }']
txt += [' }'] txt += [' }']
txt += [' }'] txt += [' }']
txt += [' }'] txt += [' }']
@ -1661,13 +1934,12 @@ def generate_driver(MyDriver):
global NumberOfLinesOut global NumberOfLinesOut
global fdo global fdo
NumberOfLinesOut = 0 NumberOfLinesOut = 0
full_filename = filename = "sct_%s.tcl" % MyDriver['name'] generate_filename(MyDriver)
if 'PathName' in MyDriver: fdo = open(MyDriver['fullname'], 'w')
full_filename = os.path.join(MyDriver['PathName'], filename)
fdo = open(full_filename, 'w')
put_preamble(MyDriver) put_preamble(MyDriver)
put_standard_code(MyDriver) put_standard_code(MyDriver)
put_mkDriver(MyDriver) put_mkDriver(MyDriver)
put_add_driver(MyDriver)
put_postamble(MyDriver) put_postamble(MyDriver)
put_read_config(MyDriver) put_read_config(MyDriver)
put_check_config(MyDriver) put_check_config(MyDriver)
@ -1678,7 +1950,9 @@ def generate_driver(MyDriver):
print "Function:", f, "Type:", MyDriver['Funcs'][f]['type'], '#Uses:', MyDriver['Funcs'][f]['reference_count'] print "Function:", f, "Type:", MyDriver['Funcs'][f]['type'], '#Uses:', MyDriver['Funcs'][f]['reference_count']
for l in MyDriver['Funcs'][f]['text']: for l in MyDriver['Funcs'][f]['text']:
print " ", l print " ", l
print "Produced file %s with %d lines." % (filename, NumberOfLinesOut) if Verbose:
print "Produced file %s with %d lines." % \
( MyDriver['filename'], NumberOfLinesOut)
def process_drivers(TheDrivers): def process_drivers(TheDrivers):
if Verbose: if Verbose:
@ -1692,61 +1966,143 @@ def process_drivers(TheDrivers):
MyDriver['Permlink'] = {} MyDriver['Permlink'] = {}
MyDriver['Deferred'] = [] MyDriver['Deferred'] = []
build_driver(MyDriver, TheDrivers[driver]) build_driver(MyDriver, TheDrivers[driver])
check_func_code(MyDriver)
if Verbose: if Verbose:
print "MyDriver:", MyDriver['name'], '=', MyDriver print "MyDriver:", MyDriver['name'], '=', MyDriver
if DriverDump or Verbose: if DriverDump or Verbose:
dump_driver(MyDriver) dump_driver(MyDriver)
generate_driver(MyDriver) generate_driver(MyDriver)
def process_source(source_files): def load_file(source_file, depth_list):
global PathName global SourceFileList, SourceLineList
# find the file and set the name
SourceFile = os.path.realpath(os.path.abspath(source_file))
if not os.path.isfile(SourceFile):
#print source_file, SourceFile, SourceFileList
if len(SourceFileList) > 0:
trial_name = os.path.join(os.path.dirname(SourceFileList[0]), source_file)
#print trial_name
if os.path.isfile(trial_name):
SourceFile = os.path.realpath(os.path.abspath(trial_name))
if SourceFile in depth_list:
PrintPostError('Error: recursive include of: %s' % SourceFile)
for idx, name in enumerate(depth_list):
PrintPostError(' ' * idx + name)
raise Exception('Bad recursive include of "' + SourceFile + '"')
SourceFileList.append(SourceFile)
curr_file = len(SourceFileList) - 1
fd = open(SourceFile, 'r')
LocalData = []
line_no = 0
execing = False
exec_input = []
exec_line = 0
for line in fd:
line_no += 1
line = line.rstrip('\n')
if execing:
match = re.match(r'\s*%end', line, flags=re.IGNORECASE)
if match:
#print "exec_input:"
#for temp_line in exec_input:
# print " " + temp_line
kw = {}
kw['exec_output'] = []
exec('\n'.join(exec_input)) in kw
#print "exec_output:"
for line in kw['exec_output']:
# print " " + line
LocalData.append(line)
SourceLineList.append((curr_file, exec_line))
exec_input = []
execing = False
else:
exec_input.append(line)
continue
match = re.match(r'\s*%exec', line, flags=re.IGNORECASE)
if match:
execing = True
exec_line = line_no
continue
match = re.match(r'\s*%include\s+', line, flags=re.IGNORECASE)
if match:
new_source = re.sub(r'\s*%include\s+(.*)', r'\1', line, flags=re.IGNORECASE)
LocalData += load_file(new_source, depth_list + [SourceFile])
continue
LocalData.append(line)
SourceLineList.append((curr_file, line_no))
fd.close()
return LocalData
def dump_source_files(data):
global SourceFileList, SourceLineList
print "SourceFileList:", SourceFileList
print "SourceLineList:", SourceLineList
curr_file = -1
for line_no, line in enumerate(data):
if SourceLineList[line_no][0] != curr_file:
curr_file = SourceLineList[line_no][0]
print "File:", SourceFileList[curr_file]
print "%4d:" % SourceLineList[line_no][1], line
def process_source(source_file):
global PathName, SourceFile
global TheDrivers global TheDrivers
global NumberOfLinesIn global NumberOfLinesIn, NumberOfLinesOut
global SourceData
global PrintedFileName
global SourceFileList, SourceLineList
TheDrivers = {} TheDrivers = {}
# PrintedFileName = -1
# Build the lexer NumberOfLinesIn = 0
# NumberOfLinesOut = 0
lexer = lex.lex() SourceFileList = list()
SourceLineList = list()
#
# Build the parser
#
#yaccer = yacc.yacc(tabmodule="gen_sct",outputdir="/tmp",write_tables=0,debug=0)
yaccer = yacc.yacc()
for source_file in source_files:
PathName = os.path.realpath(os.path.abspath(os.path.dirname(source_file))) PathName = os.path.realpath(os.path.abspath(os.path.dirname(source_file)))
fd = open(source_file, 'r') SourceData = load_file(source_file, [])
data = fd.read() NumberOfLinesIn = len(SourceData)
fd.close()
NumberOfLinesIn = data.count('\n')
start_line = lexer.lineno start_line = lexer.lineno
yaccer.parse(data) yaccer.parse('\n'.join(SourceData))
stop_line = lexer.lineno stop_line = lexer.lineno
print 'Consumed file %s with %d lines (%d, %d)' % (source_file, if Verbose:
NumberOfLinesIn, start_line, stop_line - 1) print 'Consumed file %s with %d lines (%d, %d)' % \
(source_file, NumberOfLinesIn, start_line, stop_line - 1)
lexer.lineno = 1 lexer.lineno = 1
process_drivers(TheDrivers) process_drivers(TheDrivers)
if args.list:
dump_source_files(SourceData)
def main(): def main():
global lexer, yaccer
global Verbose global Verbose
global Move
global DriverDump global DriverDump
global CodeDump global CodeDump
global args
import argparse import argparse
# RELEASE-3_1="before", RELEASE-3_2="after"
default_sct = "before"
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("-c", "--code", help="dump code", parser.add_argument("-c", "--code", help="dump code",
action="store_true") action="store_true")
parser.add_argument("-d", "--driver", help="dump driver", parser.add_argument("-d", "--driver", help="dump driver",
action="store_true") action="store_true")
parser.add_argument("-l", "--list", help="list output",
action="store_true")
parser.add_argument("-m", "--move", help="generate move commands",
action="store_true")
parser.add_argument("--sct",
help="where to put the sct in the filename [%s]" % default_sct,
choices=["before", "after"], default=default_sct)
parser.add_argument("-v", "--verbose", help="verbose output", parser.add_argument("-v", "--verbose", help="verbose output",
action="store_true") action="store_true")
parser.add_argument("driver_source", help="driver source file", nargs="*") parser.add_argument("driver_source", help="driver source file", nargs="*")
args = parser.parse_args() args = parser.parse_args()
if args.verbose:
print args print args
if args.code: if args.code:
CodeDump = True CodeDump = True
@ -1756,13 +2112,30 @@ def main():
DriverDump = True DriverDump = True
else: else:
DriverDump = False DriverDump = False
if args.move:
Move = True
else:
Move = False
if args.verbose: if args.verbose:
Verbose = True Verbose = True
else: else:
Verbose = False Verbose = False
source_files = args.driver_source source_files = args.driver_source #
if source_files: if source_files and len(source_files) > 0:
process_source(source_files) # Build the lexer
#
lexer = lex.lex()
#
# Build the parser
#
#yaccer = yacc.yacc(tabmodule="gen_sct",outputdir="/tmp",write_tables=0,debug=0)
yaccer = yacc.yacc(debug=0)
for source_file in source_files:
process_source(source_file)
if __name__ == "__main__": if __name__ == "__main__":
main() main()