diff --git a/site_ansto/instrument/util/gen_sct.py b/site_ansto/instrument/util/gen_sct.py index 85ecb308..275b9df1 100755 --- a/site_ansto/instrument/util/gen_sct.py +++ b/site_ansto/instrument/util/gen_sct.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Script Context Driver Generator # Author: Douglas Clowes (douglas.clowes@ansto.gov.au) Jan/Feb 2014 -# vim: ft=python ts=8 sts=2 sw=2 expandtab autoindent smartindent +# vim: ft=python ts=8 sts=4 sw=4 expandtab autoindent smartindent # # This program generates Script Context Driver TCL files. # @@ -166,28 +166,28 @@ t_RBRACE = r'}' t_SLASH = r'/' def t_TCL_BEG(t): - r'{%%' - if Verbose: - print 'TCL_BEG' - t.lexer.begin('tcl') - return t + r'{%%' + if Verbose: + print 'TCL_BEG' + t.lexer.begin('tcl') + return t def t_tcl_TCL_END(t): - r'.*%%}' - if Verbose: - print 'TCL_END' - t.lexer.begin('INITIAL') - return t + r'.*%%}' + if Verbose: + print 'TCL_END' + t.lexer.begin('INITIAL') + return t t_tcl_ignore = "" def t_tcl_CODE_STRING(t): - r'.+' - if t.value[0] == '@': - t.value = t.value[1:] - if Verbose: - print 'TCL:', t.value - return t + r'.+' + if t.value[0] == '@': + t.value = t.value[1:] + if Verbose: + print 'TCL:', t.value + return t def t_tcl_newline(t): r'\n+' @@ -198,51 +198,51 @@ def t_tcl_error(t): t.lexer.skip(1) def t_TEXT_STRING1(t): - r'\'[^\']+\'' - t.value = t.value[1:-1] - return t + r'\'[^\']+\'' + t.value = t.value[1:-1] + return t def t_TEXT_STRING2(t): - r"\"[^\"]+\"" - t.value = t.value[1:-1] - return t + r"\"[^\"]+\"" + t.value = t.value[1:-1] + return t def t_CODE_STRING(t): - r'\@.*' - t.value = t.value[1:] - return t + r'\@.*' + t.value = t.value[1:] + return t def t_COMMENT(t): - r'\#.*' - pass - # No Return Value. Token discarded + r'\#.*' + pass + # No Return Value. Token discarded def t_FLOATER(t): - r'-?\d+\.\d*([eE]\d+)?' - try: - t.value = float(t.value) - except ValueError: - print "Floating value invalid:", t.value - t.value = 0.0 - return t + r'-?\d+\.\d*([eE]\d+)?' + try: + t.value = float(t.value) + except ValueError: + print "Floating value invalid:", t.value + t.value = 0.0 + return t def t_INTEGER(t): - r'-?\d+' - try: - t.value = int(t.value) - except ValueError: - print "Integer value too large:", t.value - t.value = 0 - return t + r'-?\d+' + try: + t.value = int(t.value) + except ValueError: + print "Integer value too large:", t.value + t.value = 0 + return t def t_ID(t): - r'[a-zA-Z_][a-zA-Z_0-9]*' - t.type = reserved.get(t.value.upper(), 'ID') # Check for reserved words - # Force reserved words to lower case for map lookup and comparisson - if t.value.upper() in reserved: - t.type = reserved[t.value.upper()] - t.value = t.value.lower() - return t + r'[a-zA-Z_][a-zA-Z_0-9]*' + t.type = reserved.get(t.value.upper(), 'ID') # Check for reserved words + # Force reserved words to lower case for map lookup and comparisson + if t.value.upper() in reserved: + t.type = reserved[t.value.upper()] + t.value = t.value.lower() + return t # Ignored characters t_ignore = " \t;" @@ -276,293 +276,293 @@ precedence = ( # The head token - it all reduces to this # def p_driver(p): - 'driver : DRIVER id_or_str EQUALS driver_block' - p[0] = [{ 'Driver' : {p[2] : p[4]}}] - if Verbose: - print "Driver:", p[0] - global PathName - global TheDrivers - TheDrivers[p[2]] = p[4] + [{'PathName':PathName}] + 'driver : DRIVER id_or_str EQUALS driver_block' + p[0] = [{ 'Driver' : {p[2] : p[4]}}] + if Verbose: + print "Driver:", p[0] + global PathName + global TheDrivers + TheDrivers[p[2]] = p[4] + [{'PathName':PathName}] def p_driver_block(p): - 'driver_block : LBRACE driver_statement_list RBRACE' - p[0] = p[2] + 'driver_block : LBRACE driver_statement_list RBRACE' + p[0] = p[2] def p_driver_statement_list(p): - '''driver_statement_list : driver_statement - | driver_statement_list driver_statement - ''' - if len(p) == 2: - p[0] = [p[1]] - else: - p[0] = p[1] + [p[2]] + '''driver_statement_list : driver_statement + | driver_statement_list driver_statement + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + [p[2]] def p_driver_statement(p): - '''driver_statement : driver_assignment - | group - | code - | driver_property - ''' - p[0] = p[1] + '''driver_statement : driver_assignment + | group + | code + | driver_property + ''' + p[0] = p[1] def p_driver_assignment(p): - ''' - driver_assignment : VENDOR EQUALS id_or_str - | DEVICE EQUALS id_or_str - | PROTOCOL EQUALS id_or_str - | CLASS EQUALS id_or_str - | SIMULATION_GROUP EQUALS id_or_str - | ADD_ARGS EQUALS text_string - | MAKE_ARGS EQUALS text_string - | PROTOCOL_ARGS EQUALS text_string - | DEBUG_THRESHOLD EQUALS value - ''' - p[0] = { p[1] : p[3] } + ''' + driver_assignment : VENDOR EQUALS id_or_str + | DEVICE EQUALS id_or_str + | PROTOCOL EQUALS id_or_str + | CLASS EQUALS id_or_str + | SIMULATION_GROUP EQUALS id_or_str + | ADD_ARGS EQUALS text_string + | MAKE_ARGS EQUALS text_string + | PROTOCOL_ARGS EQUALS text_string + | DEBUG_THRESHOLD EQUALS value + ''' + p[0] = { p[1] : p[3] } # # The GROUP block # def p_group(p): - ''' - group : GROUP group_id EQUALS LBRACE group_statement_list RBRACE - ''' - p[0] = { 'Group' : [{'name': p[2]}] + p[5] } + ''' + group : GROUP group_id EQUALS LBRACE group_statement_list RBRACE + ''' + p[0] = { 'Group' : [{'name': p[2]}] + p[5] } def p_group_id(p): - ''' - group_id : id_or_str - | empty - ''' - p[0] = p[1] + ''' + group_id : id_or_str + | empty + ''' + p[0] = p[1] def p_group_statement_list(p): - ''' - group_statement_list : group_statement - | group_statement_list group_statement - ''' - if len(p) == 2: - p[0] = [p[1]] - else: - p[0] = p[1] + [p[2]] + ''' + group_statement_list : group_statement + | group_statement_list group_statement + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + [p[2]] def p_group_statement(p): - '''group_statement : group_assignment - | variable - | group - ''' - p[0] = p[1] + '''group_statement : group_assignment + | variable + | group + ''' + p[0] = p[1] def p_group_assignment(p): - '''group_assignment : group_property - | var_typ_ass - | property - ''' - p[0] = p[1] + '''group_assignment : group_property + | var_typ_ass + | property + ''' + p[0] = p[1] # # The VAR block # def p_variable(p): - ''' - variable : VAR id_or_str EQUALS LBRACE variable_statement_list RBRACE - | VAR id_or_str - ''' - if len(p) > 3: - p[0] = { 'Variable' : [{'name' : p[2]}] + p[5] } - else: - p[0] = { 'Variable' : [{'name' : p[2]}] } + ''' + variable : VAR id_or_str EQUALS LBRACE variable_statement_list RBRACE + | VAR id_or_str + ''' + if len(p) > 3: + p[0] = { 'Variable' : [{'name' : p[2]}] + p[5] } + else: + p[0] = { 'Variable' : [{'name' : p[2]}] } def p_variable_statement_list(p): - '''variable_statement_list : variable_statement - | variable_statement_list variable_statement - ''' - if len(p) == 2: - p[0] = [p[1]] - else: - p[0] = p[1] + [p[2]] + '''variable_statement_list : variable_statement + | variable_statement_list variable_statement + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + [p[2]] def p_variable_statement(p): - '''variable_statement : var_typ_ass - | var_val_ass - | property - ''' - p[0] = p[1] + '''variable_statement : var_typ_ass + | var_val_ass + | property + ''' + p[0] = p[1] def p_var_typ_ass(p): - ''' - var_typ_ass : READABLE EQUALS INTEGER - | WRITEABLE EQUALS INTEGER - | READ_COMMAND EQUALS text_string - | READ_FUNCTION EQUALS id_or_str - | FETCH_FUNCTION EQUALS id_or_str - | WRITE_COMMAND EQUALS text_string - | WRITE_FUNCTION EQUALS id_or_str - | CHECK_FUNCTION EQUALS id_or_str - | PID_FUNCTION EQUALS id_or_str - | CHECKRANGE_FUNCTION EQUALS id_or_str - | CHECKLIMITS_FUNCTION EQUALS id_or_str - | CHECKSTATUS_FUNCTION EQUALS id_or_str - | HALT_FUNCTION EQUALS id_or_str - | TYPE EQUALS type_code - | PRIV EQUALS priv_code - | CONTROL EQUALS true_false - | DATA EQUALS true_false - | NXSAVE EQUALS true_false - | MUTABLE EQUALS true_false - ''' - p[0] = { p[1] : p[3] } + ''' + var_typ_ass : READABLE EQUALS INTEGER + | WRITEABLE EQUALS INTEGER + | READ_COMMAND EQUALS text_string + | READ_FUNCTION EQUALS id_or_str + | FETCH_FUNCTION EQUALS id_or_str + | WRITE_COMMAND EQUALS text_string + | WRITE_FUNCTION EQUALS id_or_str + | CHECK_FUNCTION EQUALS id_or_str + | PID_FUNCTION EQUALS id_or_str + | CHECKRANGE_FUNCTION EQUALS id_or_str + | CHECKLIMITS_FUNCTION EQUALS id_or_str + | CHECKSTATUS_FUNCTION EQUALS id_or_str + | HALT_FUNCTION EQUALS id_or_str + | TYPE EQUALS type_code + | PRIV EQUALS priv_code + | CONTROL EQUALS true_false + | DATA EQUALS true_false + | NXSAVE EQUALS true_false + | MUTABLE EQUALS true_false + ''' + p[0] = { p[1] : p[3] } def p_var_path(p): - ''' - var_path : id_or_str - | var_path SLASH id_or_str - ''' - if len(p) == 2: - p[0] = p[1] - else: - p[0] = p[1] + '/' + p[3] + ''' + var_path : id_or_str + | var_path SLASH id_or_str + ''' + if len(p) == 2: + p[0] = p[1] + else: + p[0] = p[1] + '/' + p[3] def p_var_val_ass(p): - ''' - var_val_ass : VALUE EQUALS FLOATER - | VALUE EQUALS text_string - | VALUE EQUALS INTEGER - | ALLOWED EQUALS text_string - | UNITS EQUALS text_string - | LOWERLIMIT EQUALS value - | UPPERLIMIT EQUALS value - | TOLERANCE EQUALS value - | PERMLINK EQUALS text_string - | DRIVEABLE EQUALS var_path - ''' - p[0] = { p[1] : p[3] } + ''' + var_val_ass : VALUE EQUALS FLOATER + | VALUE EQUALS text_string + | VALUE EQUALS INTEGER + | ALLOWED EQUALS text_string + | UNITS EQUALS text_string + | LOWERLIMIT EQUALS value + | UPPERLIMIT EQUALS value + | TOLERANCE EQUALS value + | PERMLINK EQUALS text_string + | DRIVEABLE EQUALS var_path + ''' + p[0] = { p[1] : p[3] } def p_driver_property(p): - ''' - driver_property : DRIVER_PROPERTY id_or_str EQUALS value - ''' - p[0] = { 'DriverProperty' : ( p[2], p[4] ) } + ''' + driver_property : DRIVER_PROPERTY id_or_str EQUALS value + ''' + p[0] = { 'DriverProperty' : ( p[2], p[4] ) } def p_group_property(p): - ''' - group_property : GROUP_PROPERTY id_or_str EQUALS value - ''' - p[0] = { 'GroupProperty' : ( p[2], p[4] ) } + ''' + group_property : GROUP_PROPERTY id_or_str EQUALS value + ''' + p[0] = { 'GroupProperty' : ( p[2], p[4] ) } def p_property(p): - ''' - property : PROPERTY id_or_str EQUALS value - ''' - p[0] = { 'Property' : ( p[2], p[4] ) } + ''' + property : PROPERTY id_or_str EQUALS value + ''' + p[0] = { 'Property' : ( p[2], p[4] ) } def p_value(p): - ''' - value : number - | id_or_str - | true_false - ''' - p[0] = p[1] + ''' + value : number + | id_or_str + | true_false + ''' + p[0] = p[1] def p_number(p): - ''' - number : INTEGER - | FLOATER - ''' - p[0] = p[1] + ''' + number : INTEGER + | FLOATER + ''' + p[0] = p[1] def p_type_code(p): - ''' - type_code : FLOAT - | INT - | TEXT - | NONE - ''' - p[0] = p[1] + ''' + type_code : FLOAT + | INT + | TEXT + | NONE + ''' + p[0] = p[1] def p_priv_code(p): - ''' - priv_code : SPY - | USER - | MANAGER - | READONLY - | INTERNAL - ''' - p[0] = p[1] + ''' + priv_code : SPY + | USER + | MANAGER + | READONLY + | INTERNAL + ''' + p[0] = p[1] def p_true_false(p): - ''' - true_false : TRUE - | FALSE - ''' - p[0] = p[1] + ''' + true_false : TRUE + | FALSE + ''' + p[0] = p[1] # # The CODE block # def p_code(p): - ''' - code : CODE code_type id_or_str EQUALS LBRACE code_block RBRACE - | CODE code_type id_or_str EQUALS TCL_BEG code_block TCL_END - ''' - p[0] = { 'Code' : { 'name' : p[3], 'type' : p[2], 'text' : p[6] }} + ''' + code : CODE code_type id_or_str EQUALS LBRACE code_block RBRACE + | CODE code_type id_or_str EQUALS TCL_BEG code_block TCL_END + ''' + p[0] = { 'Code' : { 'name' : p[3], 'type' : p[2], 'text' : p[6] }} def p_code_type(p): - ''' - code_type : READ_FUNCTION - | FETCH_FUNCTION - | WRITE_FUNCTION - | CHECK_FUNCTION - | PID_FUNCTION - | CHECKRANGE_FUNCTION - | CHECKLIMITS_FUNCTION - | CHECKSTATUS_FUNCTION - | HALT_FUNCTION - | empty - ''' - p[0] = p[1] + ''' + code_type : READ_FUNCTION + | FETCH_FUNCTION + | WRITE_FUNCTION + | CHECK_FUNCTION + | PID_FUNCTION + | CHECKRANGE_FUNCTION + | CHECKLIMITS_FUNCTION + | CHECKSTATUS_FUNCTION + | HALT_FUNCTION + | empty + ''' + p[0] = p[1] def p_code_block(p): - '''code_block : empty - | code_block CODE_STRING - ''' - if len(p) == 2: - p[0] = [] - else: - p[0] = p[1] + [p[2]] + '''code_block : empty + | code_block CODE_STRING + ''' + if len(p) == 2: + p[0] = [] + else: + p[0] = p[1] + [p[2]] def p_id_or_str(p): - ''' - id_or_str : ID - | text_string - ''' - p[0] = p[1] + ''' + id_or_str : ID + | text_string + ''' + p[0] = p[1] def p_text_string(p): - ''' - text_string : TEXT_STRING1 - | TEXT_STRING2 - ''' - p[0] = p[1] + ''' + text_string : TEXT_STRING1 + | TEXT_STRING2 + ''' + p[0] = p[1] def p_empty(p): - ''' - empty : - ''' - pass + ''' + empty : + ''' + pass def p_error(t): - print("Syntax error at '%s'" % t.value), t + print("Syntax error at '%s'" % t.value), t # # Utility functions # def make_path(MyVar): - path = MyVar['path'] - if len(path) > 0: - path = path.replace('/', '_') - path += '_' - path += MyVar['name'] - return path + path = MyVar['path'] + if len(path) > 0: + path = path.replace('/', '_') + path += '_' + path += MyVar['name'] + return path # # This section handles building a driver tree from the Abstract Syntax Tree @@ -570,1037 +570,1037 @@ def make_path(MyVar): # cascading context explicitly stated to make the code generation simpler. # def init_context(): - global ContextStack, ContextIndex - ContextStack = [{}] - ContextIndex = 0 - ContextStack[ContextIndex]['type'] = 'none' - ContextStack[ContextIndex]['priv'] = 'user' - ContextStack[ContextIndex]['readable'] = 0 - ContextStack[ContextIndex]['writeable'] = 0 - ContextStack[ContextIndex]['driveable'] = None - ContextStack[ContextIndex]['control'] = 'true' - ContextStack[ContextIndex]['data'] = 'true' - ContextStack[ContextIndex]['mutable'] = 'false' - ContextStack[ContextIndex]['nxsave'] = 'true' - ContextStack[ContextIndex]['read_function'] = 'rdValue' - ContextStack[ContextIndex]['write_function'] = 'setValue' - ContextStack[ContextIndex]['fetch_function'] = 'getValue' - ContextStack[ContextIndex]['check_function'] = 'noResponse' - ContextStack[ContextIndex]['checkrange_function'] = 'checkrange' - ContextStack[ContextIndex]['path'] = '' + global ContextStack, ContextIndex + ContextStack = [{}] + ContextIndex = 0 + ContextStack[ContextIndex]['type'] = 'none' + ContextStack[ContextIndex]['priv'] = 'user' + ContextStack[ContextIndex]['readable'] = 0 + ContextStack[ContextIndex]['writeable'] = 0 + ContextStack[ContextIndex]['driveable'] = None + ContextStack[ContextIndex]['control'] = 'true' + ContextStack[ContextIndex]['data'] = 'true' + ContextStack[ContextIndex]['mutable'] = 'false' + ContextStack[ContextIndex]['nxsave'] = 'true' + ContextStack[ContextIndex]['read_function'] = 'rdValue' + ContextStack[ContextIndex]['write_function'] = 'setValue' + ContextStack[ContextIndex]['fetch_function'] = 'getValue' + ContextStack[ContextIndex]['check_function'] = 'noResponse' + ContextStack[ContextIndex]['checkrange_function'] = 'checkrange' + ContextStack[ContextIndex]['path'] = '' def push_context(): - global ContextStack, ContextIndex - ContextIndex = ContextIndex + 1 - if len(ContextStack) <= ContextIndex: - ContextStack.append({}) - ContextStack[ContextIndex] = {} - for k in ContextStack[ContextIndex - 1].keys(): - ContextStack[ContextIndex][k] = ContextStack[ContextIndex - 1][k] + global ContextStack, ContextIndex + ContextIndex = ContextIndex + 1 + if len(ContextStack) <= ContextIndex: + ContextStack.append({}) + ContextStack[ContextIndex] = {} + for k in ContextStack[ContextIndex - 1].keys(): + ContextStack[ContextIndex][k] = ContextStack[ContextIndex - 1][k] def pop_context(): - global ContextStack, ContextIndex - ContextIndex = ContextIndex - 1 + global ContextStack, ContextIndex + ContextIndex = ContextIndex - 1 def build_code(MyDriver, p): - if Verbose: - print 'Code:', p - print "Function:", p['name'] - MyCode = {} - MyCode['name'] = p['name'] - MyCode['reference_count'] = 0 - if 'type' in p: - MyCode['type'] = p['type'] - MyCode['text'] = p['text'] - if Verbose: - for line in p['text']: - print " Line:", line - return MyCode + if Verbose: + print 'Code:', p + print "Function:", p['name'] + MyCode = {} + MyCode['name'] = p['name'] + MyCode['reference_count'] = 0 + if 'type' in p: + MyCode['type'] = p['type'] + MyCode['text'] = p['text'] + if Verbose: + for line in p['text']: + print " Line:", line + return MyCode def build_variable(MyDriver, p): - global FunctionTypes - global DriveableFunctionTypes - if Verbose: - print 'Variable:', p - MyVar = {} - MyVar['Property'] = {} - # Copy items for this variable - for item in p: + global FunctionTypes + global DriveableFunctionTypes if Verbose: - print "Variable Item:", item - for key in item.keys(): - if key == 'Property': - MyVar['Property'][item[key][0]] = item[key][1] - else: - MyVar[key] = item[key] - # copy the defaults for missing items - for key in ContextStack[ContextIndex]: - if key == 'Property': - for key2 in ContextStack[ContextIndex][key]: - if key2 not in MyVar['Property']: - MyVar['Property'][key2] = ContextStack[ContextIndex][key][key2] - elif not key in MyVar: - MyVar[key] = ContextStack[ContextIndex][key] - if 'sdsinfo' not in MyVar['Property']: - MyVar['Property']['sdsinfo'] = '::nexus::scobj::sdsinfo' - # set the type if not explicitly set - if 'type' not in MyVar['Property']: - if 'driveable' in MyVar and MyVar['driveable']: - MyVar['Property']['type'] = 'drivable' - else: - MyVar['Property']['type'] = 'part' - # if this variable is driveable - if 'driveable' in MyVar and MyVar['driveable']: - # insert defaults for missing driveable functions - if 'checklimits_function' not in MyVar: - MyVar['checklimits_function'] = 'checklimits' - if 'checkstatus_function' not in MyVar: - MyVar['checkstatus_function'] = 'checkstatus' - if 'halt_function' not in MyVar: - MyVar['halt_function'] = 'halt' - - for func in FunctionTypes + DriveableFunctionTypes: - if func in MyVar and MyVar[func] != 'none': - if Verbose: - print 'Var:', MyVar['name'], 'Func:', func, '=', MyVar[func] - if MyVar[func] not in MyDriver['Funcs']: - MyDriver['Funcs'][MyVar[func]] = { 'type' : func, 'text' : [], 'reference_count' : 0 } + print 'Variable:', p + MyVar = {} + MyVar['Property'] = {} + # Copy items for this variable + for item in p: if Verbose: - print MyVar['name'], 'Add func ' + MyVar[func], MyDriver['Funcs'][MyVar[func]] - elif not MyDriver['Funcs'][MyVar[func]]['type'] == func: - # allow override of type none else error message - if not MyDriver['Funcs'][MyVar[func]]['type']: - if Verbose: - print MyVar['name'], 'Mod func type:', MyDriver['Funcs'][MyVar[func]], '= ' + func - MyDriver['Funcs'][MyVar[func]]['type'] = func + print "Variable Item:", item + for key in item.keys(): + if key == 'Property': + MyVar['Property'][item[key][0]] = item[key][1] + else: + MyVar[key] = item[key] + # copy the defaults for missing items + for key in ContextStack[ContextIndex]: + if key == 'Property': + for key2 in ContextStack[ContextIndex][key]: + if key2 not in MyVar['Property']: + MyVar['Property'][key2] = ContextStack[ContextIndex][key][key2] + elif not key in MyVar: + MyVar[key] = ContextStack[ContextIndex][key] + if 'sdsinfo' not in MyVar['Property']: + MyVar['Property']['sdsinfo'] = '::nexus::scobj::sdsinfo' + # set the type if not explicitly set + if 'type' not in MyVar['Property']: + if 'driveable' in MyVar and MyVar['driveable']: + MyVar['Property']['type'] = 'drivable' else: - # TODO FIXME error message - print 'Error: Function type mismatch: var = ' + str(MyVar) + ', code = ' + str(MyDriver['Funcs'][MyVar[func]]) + ', func = ' + str(func) - MyDriver['Funcs'][MyVar[func]]['reference_count'] += 1 - if 'permlink' in MyVar: - device_type, node_type = MyVar['permlink'].split('.') - if node_type not in MyDriver['Permlink']: - MyDriver['Permlink'][node_type] = []; - MyDriver['Permlink'][node_type] += [make_path(MyVar)]; - if Verbose: - print '==>>MyVar:', MyVar - return MyVar + MyVar['Property']['type'] = 'part' + # if this variable is driveable + if 'driveable' in MyVar and MyVar['driveable']: + # insert defaults for missing driveable functions + if 'checklimits_function' not in MyVar: + MyVar['checklimits_function'] = 'checklimits' + if 'checkstatus_function' not in MyVar: + MyVar['checkstatus_function'] = 'checkstatus' + if 'halt_function' not in MyVar: + MyVar['halt_function'] = 'halt' + + for func in FunctionTypes + DriveableFunctionTypes: + if func in MyVar and MyVar[func] != 'none': + if Verbose: + print 'Var:', MyVar['name'], 'Func:', func, '=', MyVar[func] + if MyVar[func] not in MyDriver['Funcs']: + MyDriver['Funcs'][MyVar[func]] = { 'type' : func, 'text' : [], 'reference_count' : 0 } + if Verbose: + print MyVar['name'], 'Add func ' + MyVar[func], MyDriver['Funcs'][MyVar[func]] + elif not MyDriver['Funcs'][MyVar[func]]['type'] == func: + # allow override of type none else error message + if not MyDriver['Funcs'][MyVar[func]]['type']: + if Verbose: + print MyVar['name'], 'Mod func type:', MyDriver['Funcs'][MyVar[func]], '= ' + func + MyDriver['Funcs'][MyVar[func]]['type'] = func + else: + # TODO FIXME error message + print 'Error: Function type mismatch: var = ' + str(MyVar) + ', code = ' + str(MyDriver['Funcs'][MyVar[func]]) + ', func = ' + str(func) + MyDriver['Funcs'][MyVar[func]]['reference_count'] += 1 + if 'permlink' in MyVar: + device_type, node_type = MyVar['permlink'].split('.') + if node_type not in MyDriver['Permlink']: + MyDriver['Permlink'][node_type] = []; + MyDriver['Permlink'][node_type] += [make_path(MyVar)]; + if Verbose: + print '==>>MyVar:', MyVar + return MyVar def build_group(MyDriver, p): - if Verbose: - print 'Group:', p[0]['name'], p - push_context() - MyGroup = {} - MyGroup['Groups'] = {} - MyGroup['Vars'] = {} - # the sequence of both variables and non-variables is significant - # Therefore, they have to be processed in a single sequence - if p[0]['name']: - if len(ContextStack[ContextIndex]['path']) > 0: - ContextStack[ContextIndex]['path'] += '/' - ContextStack[ContextIndex]['path'] += p[0]['name'] - MyGroup['path'] = ContextStack[ContextIndex]['path'] - for item in p: - if 'Variable' in item: - MyVar = build_variable(MyDriver, item['Variable']) - MyGroup['Vars'][MyVar['name']] = MyVar - elif 'Group' in item: - MySubGroup = build_group(MyDriver, item['Group']) - MyGroup['Groups'][MySubGroup['name']] = MySubGroup - else: - if Verbose: - print "Group Item:", item - if 'GroupProperty' in item: - if 'GroupProperty' not in MyGroup: - MyGroup['GroupProperty'] = {} - MyGroup['GroupProperty'][item['GroupProperty'][0]] = item['GroupProperty'][1] - elif 'Property' in item: - if 'Property' not in MyGroup: - MyGroup['Property'] = {} - MyGroup['Property'][item['Property'][0]] = item['Property'][1] - if 'Property' not in ContextStack[ContextIndex]: - ContextStack[ContextIndex]['Property'] = {} - ContextStack[ContextIndex]['Property'][item['Property'][0]] = item['Property'][1] - else: - for key in item: - MyGroup[key] = item[key] - if key in ContextStack[ContextIndex]: - ContextStack[ContextIndex][key] = item[key] - pop_context() - return MyGroup + if Verbose: + print 'Group:', p[0]['name'], p + push_context() + MyGroup = {} + MyGroup['Groups'] = {} + MyGroup['Vars'] = {} + # the sequence of both variables and non-variables is significant + # Therefore, they have to be processed in a single sequence + if p[0]['name']: + if len(ContextStack[ContextIndex]['path']) > 0: + ContextStack[ContextIndex]['path'] += '/' + ContextStack[ContextIndex]['path'] += p[0]['name'] + MyGroup['path'] = ContextStack[ContextIndex]['path'] + for item in p: + if 'Variable' in item: + MyVar = build_variable(MyDriver, item['Variable']) + MyGroup['Vars'][MyVar['name']] = MyVar + elif 'Group' in item: + MySubGroup = build_group(MyDriver, item['Group']) + MyGroup['Groups'][MySubGroup['name']] = MySubGroup + else: + if Verbose: + print "Group Item:", item + if 'GroupProperty' in item: + if 'GroupProperty' not in MyGroup: + MyGroup['GroupProperty'] = {} + MyGroup['GroupProperty'][item['GroupProperty'][0]] = item['GroupProperty'][1] + elif 'Property' in item: + if 'Property' not in MyGroup: + MyGroup['Property'] = {} + MyGroup['Property'][item['Property'][0]] = item['Property'][1] + if 'Property' not in ContextStack[ContextIndex]: + ContextStack[ContextIndex]['Property'] = {} + ContextStack[ContextIndex]['Property'][item['Property'][0]] = item['Property'][1] + else: + for key in item: + MyGroup[key] = item[key] + if key in ContextStack[ContextIndex]: + ContextStack[ContextIndex][key] = item[key] + pop_context() + return MyGroup def build_driver(MyDriver, TheTree): - if Verbose: - print "TheTree:", TheTree - init_context() - for item in [x for x in TheTree if 'Code' in x]: - MyCode = build_code(MyDriver, item['Code']) - MyDriver['Funcs'][MyCode['name']] = MyCode - for item in [x for x in TheTree if 'Group' in x]: - MyGroup = build_group(MyDriver, item['Group']) - MyDriver['Groups'][MyGroup['name']] = MyGroup - for item in TheTree: if Verbose: - print "Driver Item:", item - if 'Group' in item: - continue - elif 'Code' in item: - continue - else: - if 'DriverProperty' in item: - if 'DriverProperty' not in MyDriver: - MyDriver['DriverProperty'] = {} - MyDriver['DriverProperty'][item['DriverProperty'][0]] = item['DriverProperty'][1] - continue - for key in item: - MyDriver[key] = item[key] - for item in MyDriver['Permlink']: - if len(MyDriver['Permlink'][item]) > 1: - print 'Error: duplicate permlink entries for "%s"' % item, MyDriver['Permlink'][item] - if Verbose: - print "MyDriver:", MyDriver + print "TheTree:", TheTree + init_context() + for item in [x for x in TheTree if 'Code' in x]: + MyCode = build_code(MyDriver, item['Code']) + MyDriver['Funcs'][MyCode['name']] = MyCode + for item in [x for x in TheTree if 'Group' in x]: + MyGroup = build_group(MyDriver, item['Group']) + MyDriver['Groups'][MyGroup['name']] = MyGroup + for item in TheTree: + if Verbose: + print "Driver Item:", item + if 'Group' in item: + continue + elif 'Code' in item: + continue + else: + if 'DriverProperty' in item: + if 'DriverProperty' not in MyDriver: + MyDriver['DriverProperty'] = {} + MyDriver['DriverProperty'][item['DriverProperty'][0]] = item['DriverProperty'][1] + continue + for key in item: + MyDriver[key] = item[key] + for item in MyDriver['Permlink']: + if len(MyDriver['Permlink'][item]) > 1: + print 'Error: duplicate permlink entries for "%s"' % item, MyDriver['Permlink'][item] + if Verbose: + print "MyDriver:", MyDriver # # Driver Dump Functions # def dump_driver_vars(vars, indent): - global FunctionTypes - global DriveableFunctionTypes - for item in sorted(vars): - print indent + ' VAR %s = {' % item - for subitem in sorted([i for i in vars[item] if i not in FunctionTypes + DriveableFunctionTypes]): - print indent + ' %s =' % subitem, vars[item][subitem] - for subitem in sorted([i for i in vars[item] if i in FunctionTypes]): - print indent + ' %s =' % subitem, vars[item][subitem] - for subitem in sorted([i for i in vars[item] if i in DriveableFunctionTypes]): - print indent + ' %s =' % subitem, vars[item][subitem] - print indent + ' }' + global FunctionTypes + global DriveableFunctionTypes + for item in sorted(vars): + print indent + ' VAR %s = {' % item + for subitem in sorted([i for i in vars[item] if i not in FunctionTypes + DriveableFunctionTypes]): + print indent + ' %s =' % subitem, vars[item][subitem] + for subitem in sorted([i for i in vars[item] if i in FunctionTypes]): + print indent + ' %s =' % subitem, vars[item][subitem] + for subitem in sorted([i for i in vars[item] if i in DriveableFunctionTypes]): + print indent + ' %s =' % subitem, vars[item][subitem] + print indent + ' }' def dump_driver_groups(groups, indent): - for item in sorted(groups): - if item: - print indent + 'GROUP ' + item + ' = {' - else: - print indent + 'GROUP = {' - for subitem in sorted([x for x in groups[item] if not x in ['Groups', 'Vars']]): - print indent + ' ', subitem, '=', groups[item][subitem] - dump_driver_vars(groups[item]['Vars'], indent) - dump_driver_groups(groups[item]['Groups'], indent + ' ') - print indent + '}' + for item in sorted(groups): + if item: + print indent + 'GROUP ' + item + ' = {' + else: + print indent + 'GROUP = {' + for subitem in sorted([x for x in groups[item] if not x in ['Groups', 'Vars']]): + print indent + ' ', subitem, '=', groups[item][subitem] + dump_driver_vars(groups[item]['Vars'], indent) + dump_driver_groups(groups[item]['Groups'], indent + ' ') + print indent + '}' def dump_driver_funcs(funcs): - for item in sorted(funcs): - if 'type' in funcs[item] and funcs[item]['type']: - print ' CODE ' + funcs[item]['type'] + ' ' + item + ' = {' - else: - print ' CODE ' + item + ' = {' - for line in funcs[item]['text']: - print ' @%s' % line - print ' }' + for item in sorted(funcs): + if 'type' in funcs[item] and funcs[item]['type']: + print ' CODE ' + funcs[item]['type'] + ' ' + item + ' = {' + else: + print ' CODE ' + item + ' = {' + for line in funcs[item]['text']: + print ' @%s' % line + print ' }' def dump_driver(MyDriver): - print 'DRIVER ' + MyDriver['name'] + ' = {' - for item in sorted([x for x in MyDriver if x not in ['Groups', 'Funcs']]): - print ' ' + item + ' =', MyDriver[item] - #print 'Groups:', MyDriver['Groups'] - dump_driver_groups(MyDriver['Groups'], ' ') - #print 'Funcs:', MyDriver['Funcs'] - dump_driver_funcs(MyDriver['Funcs']) - print '}' + print 'DRIVER ' + MyDriver['name'] + ' = {' + for item in sorted([x for x in MyDriver if x not in ['Groups', 'Funcs']]): + print ' ' + item + ' =', MyDriver[item] + #print 'Groups:', MyDriver['Groups'] + dump_driver_groups(MyDriver['Groups'], ' ') + #print 'Funcs:', MyDriver['Funcs'] + dump_driver_funcs(MyDriver['Funcs']) + print '}' # # Code Generation Functions # def emit(txt): - global NumberOfLinesOut - NumberOfLinesOut += len(txt) - for line in txt: - fdo.write(line) - if not line.endswith('\n'): - fdo.write('\n') + global NumberOfLinesOut + NumberOfLinesOut += len(txt) + for line in txt: + fdo.write(line) + if not line.endswith('\n'): + fdo.write('\n') def put_preamble(MyDriver): - txt = [] - txt += ['# Generated driver for %s' % MyDriver['name']] - txt += ['# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent'] - txt += ['#'] - txt += [''] - txt += ['namespace eval %s {' % MyDriver['namespace']] - txt += [' set debug_threshold %s' % str( MyDriver['debug_threshold'])] - if len(MyDriver['Permlink']) > 0: - if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): - pass - else: - txt += [' if { ![info exists ::scobj::permlink_device_counter]} {'] - txt += [' set ::scobj::permlink_device_counter 0'] - txt += [' }'] - txt += ['}'] - txt += [''] - txt += ['proc %s::debug_log {tc_root debug_level debug_string} {' % MyDriver['namespace']] - txt += [' set catch_status [ catch {'] - txt += [' set debug_threshold [hgetpropval ${tc_root} debug_threshold]'] - txt += [' if {${debug_level} >= ${debug_threshold}} {'] - txt += [' set fd [open "../log/%s_[basename ${tc_root}].log" "a"]' % MyDriver['name']] - txt += [' set line "[clock format [clock seconds] -format "%T"] ${debug_string}"'] - txt += [' puts ${fd} "${line}"'] - txt += [' close ${fd}'] - txt += [' }'] - txt += [' } catch_message ]'] - txt += ['}'] - txt += [''] - txt += ['proc %s::sics_log {debug_level debug_string} {' % MyDriver['namespace']] - txt += [' set catch_status [ catch {'] - txt += [' set debug_threshold ${%s::debug_threshold}' % MyDriver['namespace']] - txt += [' if {${debug_level} >= ${debug_threshold}} {'] - txt += [' sicslog "%s::${debug_string}"' % MyDriver['namespace']] - txt += [' }'] - txt += [' } catch_message ]'] - txt += ['}'] - emit(txt) + txt = [] + txt += ['# Generated driver for %s' % MyDriver['name']] + txt += ['# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent'] + txt += ['#'] + txt += [''] + txt += ['namespace eval %s {' % MyDriver['namespace']] + txt += [' set debug_threshold %s' % str( MyDriver['debug_threshold'])] + if len(MyDriver['Permlink']) > 0: + if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): + pass + else: + txt += [' if { ![info exists ::scobj::permlink_device_counter]} {'] + txt += [' set ::scobj::permlink_device_counter 0'] + txt += [' }'] + txt += ['}'] + txt += [''] + txt += ['proc %s::debug_log {tc_root debug_level debug_string} {' % MyDriver['namespace']] + txt += [' set catch_status [ catch {'] + txt += [' set debug_threshold [hgetpropval ${tc_root} debug_threshold]'] + txt += [' if {${debug_level} >= ${debug_threshold}} {'] + txt += [' set fd [open "../log/%s_[basename ${tc_root}].log" "a"]' % MyDriver['name']] + txt += [' set line "[clock format [clock seconds] -format "%T"] ${debug_string}"'] + txt += [' puts ${fd} "${line}"'] + txt += [' close ${fd}'] + txt += [' }'] + txt += [' } catch_message ]'] + txt += ['}'] + txt += [''] + txt += ['proc %s::sics_log {debug_level debug_string} {' % MyDriver['namespace']] + txt += [' set catch_status [ catch {'] + txt += [' set debug_threshold ${%s::debug_threshold}' % MyDriver['namespace']] + txt += [' if {${debug_level} >= ${debug_threshold}} {'] + txt += [' sicslog "%s::${debug_string}"' % MyDriver['namespace']] + txt += [' }'] + txt += [' } catch_message ]'] + txt += ['}'] + emit(txt) def put_write_function(MyDriver, func): - txt = [''] - txt += ['# function to write a parameter value on a device'] - txt += ['proc %s::%s {tc_root nextState cmd_str} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"' % func] - txt += [' if { [hpropexists [sct] geterror] } {'] - txt += [' hdelprop [sct] geterror'] - txt += [' }'] - txt += [' set par [sct target]'] - txt += [' set cmd "${cmd_str}${par}"'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] + txt = [''] + txt += ['# function to write a parameter value on a device'] + txt += ['proc %s::%s {tc_root nextState cmd_str} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"' % func] txt += [' if { [hpropexists [sct] geterror] } {'] - txt += [' debug_log ${tc_root} 9 "[sct] error: [sct geterror]"'] - txt += [' error "[sct geterror]"'] + txt += [' hdelprop [sct] geterror'] txt += [' }'] - else: - txt += ['# %s hook code goes here' % func] - txt += [' if { [hpropexists [sct] driving] } {'] - txt += [' if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } {'] - txt += [' sct driving 1'] - txt += [' }'] - txt += [' }'] - txt += [' debug_log ${tc_root} 1 "%s sct send ${cmd}"' % func] - txt += [' if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {'] - txt += [' sct send "${cmd}"'] - txt += [' }'] - txt += [' return ${nextState}'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt += [' set par [sct target]'] + txt += [' set cmd "${cmd_str}${par}"'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' debug_log ${tc_root} 9 "[sct] error: [sct geterror]"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + else: + txt += ['# %s hook code goes here' % func] + txt += [' if { [hpropexists [sct] driving] } {'] + txt += [' if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } {'] + txt += [' sct driving 1'] + txt += [' }'] + txt += [' }'] + txt += [' debug_log ${tc_root} 1 "%s sct send ${cmd}"' % func] + txt += [' if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {'] + txt += [' sct send "${cmd}"'] + txt += [' }'] + txt += [' return ${nextState}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_check_function(MyDriver, func): - txt = [''] - txt += ['# function to check the write parameter on a device'] - txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] resp=[sct result]"' % func] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' return "idle"'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['# function to check the write parameter on a device'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] resp=[sct result]"' % func] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' return "idle"'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_fetch_function(MyDriver, func): - txt = [''] - txt += ['# function to request the read of a parameter on a device'] - txt += ['proc %s::%s {tc_root nextState cmd_str} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"' % func] - txt += [' if { [hpropexists [sct] geterror] } {'] - txt += [' hdelprop [sct] geterror'] - txt += [' }'] - txt += [' set cmd "${cmd_str}"'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] + txt = [''] + txt += ['# function to request the read of a parameter on a device'] + txt += ['proc %s::%s {tc_root nextState cmd_str} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"' % func] txt += [' if { [hpropexists [sct] geterror] } {'] - txt += [' debug_log ${tc_root} 9 "[sct] error: [sct geterror]"'] - txt += [' error "[sct geterror]"'] + txt += [' hdelprop [sct] geterror'] txt += [' }'] - else: - txt += ['# %s hook code goes here' % func] - txt += [' debug_log ${tc_root} 1 "%s sct send ${cmd}"' % func] - txt += [' if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {'] - txt += [' sct send "${cmd}"'] - txt += [' }'] - txt += [' return ${nextState}'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt += [' set cmd "${cmd_str}"'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' debug_log ${tc_root} 9 "[sct] error: [sct geterror]"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + else: + txt += ['# %s hook code goes here' % func] + txt += [' debug_log ${tc_root} 1 "%s sct send ${cmd}"' % func] + txt += [' if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {'] + txt += [' sct send "${cmd}"'] + txt += [' }'] + txt += [' return ${nextState}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_read_function(MyDriver, func): - txt = [''] - txt += ['# function to parse the read of a parameter on a device'] - txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] result=[sct result]"' % func] - txt += [' if { [hpropexists [sct] geterror] } {'] - txt += [' hdelprop [sct] geterror'] - txt += [' }'] - txt += [' set data [sct result]'] - txt += [' set nextState "idle"'] - txt += [' if {[string equal -nocase -length 7 ${data} "ASCERR:"]} {'] - txt += [' # the protocol driver has reported an error'] - txt += [' sct geterror "${data}"'] - txt += [' error "[sct geterror]"'] - txt += [' }'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] + txt = [''] + txt += ['# function to parse the read of a parameter on a device'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] result=[sct result]"' % func] txt += [' if { [hpropexists [sct] geterror] } {'] - txt += [' debug_log ${tc_root} 9 "[sct] error: [sct geterror]"'] + txt += [' hdelprop [sct] geterror'] + txt += [' }'] + txt += [' set data [sct result]'] + txt += [' set nextState "idle"'] + txt += [' if {[string equal -nocase -length 7 ${data} "ASCERR:"]} {'] + txt += [' # the protocol driver has reported an error'] + txt += [' sct geterror "${data}"'] txt += [' error "[sct geterror]"'] txt += [' }'] - else: - txt += ['# %s hook code goes here' % func] - txt += [' if { ${data} != [sct oldval] } {'] - txt += [' debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]"'] - txt += [' sct oldval ${data}'] - txt += [' sct update ${data}'] - txt += [' sct utime readtime'] - txt += [' }'] - txt += [' return ${nextState}'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' debug_log ${tc_root} 9 "[sct] error: [sct geterror]"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + else: + txt += ['# %s hook code goes here' % func] + txt += [' if { ${data} != [sct oldval] } {'] + txt += [' debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]"'] + txt += [' sct oldval ${data}'] + txt += [' sct update ${data}'] + txt += [' sct utime readtime'] + txt += [' }'] + txt += [' return ${nextState}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_checkrange_function(MyDriver, func): - txt = [''] - txt += ['# check function for hset change'] - txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] target=[sct target]"' % func] - txt += [' set setpoint [sct target]'] - txt += [' if { [hpropexists [sct] lowerlimit] } {'] - txt += [' set lolimit [sct lowerlimit]'] - txt += [' } else {'] - txt += [' # lowerlimit not set, use target'] - txt += [' set lolimit [sct target]'] - txt += [' }'] - txt += [' if { [hpropexists [sct] upperlimit] } {'] - txt += [' set hilimit [sct upperlimit]'] - txt += [' } else {'] - txt += [' # upperlimit not set, use target'] - txt += [' set hilimit [sct target]'] - txt += [' }'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {'] - txt += [' error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"'] - txt += [' }'] - txt += [' return OK'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['# check function for hset change'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] target=[sct target]"' % func] + txt += [' set setpoint [sct target]'] + txt += [' if { [hpropexists [sct] lowerlimit] } {'] + txt += [' set lolimit [sct lowerlimit]'] + txt += [' } else {'] + txt += [' # lowerlimit not set, use target'] + txt += [' set lolimit [sct target]'] + txt += [' }'] + txt += [' if { [hpropexists [sct] upperlimit] } {'] + txt += [' set hilimit [sct upperlimit]'] + txt += [' } else {'] + txt += [' # upperlimit not set, use target'] + txt += [' set hilimit [sct target]'] + txt += [' }'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {'] + txt += [' error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"'] + txt += [' }'] + txt += [' return OK'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_checklimits_function(MyDriver, func): - txt = [''] - txt += ['# checklimits function for driveable interface'] - txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] target=[sct target]"' % func] - txt += [' set setpoint [sct target]'] - txt += [' if { [hpropexists [sct] lowerlimit] } {'] - txt += [' set lolimit [sct lowerlimit]'] - txt += [' } else {'] - txt += [' # lowerlimit not set, use target'] - txt += [' set lolimit [sct target]'] - txt += [' }'] - txt += [' if { [hpropexists [sct] upperlimit] } {'] - txt += [' set hilimit [sct upperlimit]'] - txt += [' } else {'] - txt += [' # upperlimit not set, use target'] - txt += [' set hilimit [sct target]'] - txt += [' }'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {'] - txt += [' sct driving 0'] - txt += [' error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"'] - txt += [' }'] - txt += [' return OK'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['# checklimits function for driveable interface'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] target=[sct target]"' % func] + txt += [' set setpoint [sct target]'] + txt += [' if { [hpropexists [sct] lowerlimit] } {'] + txt += [' set lolimit [sct lowerlimit]'] + txt += [' } else {'] + txt += [' # lowerlimit not set, use target'] + txt += [' set lolimit [sct target]'] + txt += [' }'] + txt += [' if { [hpropexists [sct] upperlimit] } {'] + txt += [' set hilimit [sct upperlimit]'] + txt += [' } else {'] + txt += [' # upperlimit not set, use target'] + txt += [' set hilimit [sct target]'] + txt += [' }'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {'] + txt += [' sct driving 0'] + txt += [' error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"'] + txt += [' }'] + txt += [' return OK'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_checkstatus_function(MyDriver, func): - txt = [''] - txt += ['# checkstatus function for driveable interface'] - txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' if {[sct driving]} {'] - txt += [' set sp "[sct target]"'] - txt += [' set pv "[hval ${tc_root}/[sct driveable]]"'] - txt += [' if { abs(${pv} - ${sp}) <= [sct tolerance] } {'] - txt += [' if { [hpropexists [sct] settle_time] } {'] - txt += [' if { [hpropexists [sct] settle_time_start] } {'] - txt += [' if { [sct utime] - [sct settle_time_start] >= [sct settle_time]} {'] - txt += [' sct driving 0'] - txt += [' return "idle"'] - txt += [' }'] - txt += [' return "busy"'] - txt += [' } else {'] - txt += [' sct utime settle_time_start'] - txt += [' return "busy"'] - txt += [' }'] - txt += [' }'] - txt += [' sct driving 0'] - txt += [' return "idle"'] - txt += [' }'] - txt += [' if { [hpropexists [sct] settle_time_start] } {'] - txt += [' hdelprop [sct] settle_time_start'] - txt += [' }'] - txt += [' return "busy"'] - txt += [' } else {'] - txt += [' return "idle"'] - txt += [' }'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['# checkstatus function for driveable interface'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' if {[sct driving]} {'] + txt += [' set sp "[sct target]"'] + txt += [' set pv "[hval ${tc_root}/[sct driveable]]"'] + txt += [' if { abs(${pv} - ${sp}) <= [sct tolerance] } {'] + txt += [' if { [hpropexists [sct] settle_time] } {'] + txt += [' if { [hpropexists [sct] settle_time_start] } {'] + txt += [' if { [sct utime] - [sct settle_time_start] >= [sct settle_time]} {'] + txt += [' sct driving 0'] + txt += [' return "idle"'] + txt += [' }'] + txt += [' return "busy"'] + txt += [' } else {'] + txt += [' sct utime settle_time_start'] + txt += [' return "busy"'] + txt += [' }'] + txt += [' }'] + txt += [' sct driving 0'] + txt += [' return "idle"'] + txt += [' }'] + txt += [' if { [hpropexists [sct] settle_time_start] } {'] + txt += [' hdelprop [sct] settle_time_start'] + txt += [' }'] + txt += [' return "busy"'] + txt += [' } else {'] + txt += [' return "idle"'] + txt += [' }'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_halt_function(MyDriver, func): - txt = [''] - txt += ['# halt function for driveable interface'] - txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] driving=[sct driving]"' % func] - txt += [' ### TODO hset [sct] [hval [sct]]'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' sct driving 0'] - txt += [' return "idle"'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['# halt function for driveable interface'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] driving=[sct driving]"' % func] + txt += [' ### TODO hset [sct] [hval [sct]]'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' sct driving 0'] + txt += [' return "idle"'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_pid_function(MyDriver, func): - txt = [''] - txt += ['# pid function for PID control'] - txt += ['proc %s::%s {tc_root sp pv} {' % (MyDriver['namespace'], func)] - txt += [' set catch_status [ catch {'] - txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] pv=${pv} sp=${sp}"' % func] - txt += [' sct pid_error [expr ${sp} - ${pv}]'] - txt += [' set p_value [expr [sct pid_pvalue] * [sct pid_error]]'] - txt += [' set d_value [expr [sct pid_dvalue] * (${pv} - [sct oldval])]'] - txt += [' sct pid_deriv [sct pid_error]'] - txt += [' sct pid_integ [expr [sct pid_integ] + [sct pid_error]]'] - txt += [' if { [sct pid_integ] > [sct pid_imax] } {'] - txt += [' sct pid_integ [sct pid_imax]'] - txt += [' }'] - txt += [' if { [sct pid_integ] < -[sct pid_imax] } {'] - txt += [' sct pid_integ -[sct pid_imax]'] - txt += [' }'] - txt += [' set i_value [expr [sct pid_ivalue] * [sct pid_integ]]'] - txt += [' set pid [expr ${p_value} + ${i_value} + ${d_value}]'] - if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' sct pid_output ${pid}'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += [' return ${pid}'] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['# pid function for PID control'] + txt += ['proc %s::%s {tc_root sp pv} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log ${tc_root} 1 "%s tc_root=${tc_root} sct=[sct] pv=${pv} sp=${sp}"' % func] + txt += [' sct pid_error [expr ${sp} - ${pv}]'] + txt += [' set p_value [expr [sct pid_pvalue] * [sct pid_error]]'] + txt += [' set d_value [expr [sct pid_dvalue] * (${pv} - [sct oldval])]'] + txt += [' sct pid_deriv [sct pid_error]'] + txt += [' sct pid_integ [expr [sct pid_integ] + [sct pid_error]]'] + txt += [' if { [sct pid_integ] > [sct pid_imax] } {'] + txt += [' sct pid_integ [sct pid_imax]'] + txt += [' }'] + txt += [' if { [sct pid_integ] < -[sct pid_imax] } {'] + txt += [' sct pid_integ -[sct pid_imax]'] + txt += [' }'] + txt += [' set i_value [expr [sct pid_ivalue] * [sct pid_integ]]'] + txt += [' set pid [expr ${p_value} + ${i_value} + ${d_value}]'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' sct pid_output ${pid}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += [' return ${pid}'] + txt += ['}'] + emit(txt) def put_group(MyDriver, MyGroup): - readable_or_writeable = False - txt = [] - if MyGroup['name']: - txt += [''] - 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: - groupname = '' - for var in sorted(MyGroup['Vars']): - txt += [''] - MyVar = MyGroup['Vars'][var] - nodename = groupname + MyVar['name'] - # Check driveable attributes are present if required - if 'driveable' in MyVar and MyVar['driveable']: - for attr in ('lowerlimit', 'upperlimit', 'tolerance'): - if attr not in MyVar: - msg = 'Driveable: %s does not have required attribute: %s' % (nodename, attr) - print 'Warning:', msg - txt += [' # Warning: ' + msg] - # Check PID attributes are present if required - if 'pid_function' in MyVar: - for attr in ('pid_pvalue', - 'pid_ivalue', - 'pid_dvalue', - 'pid_imax', - 'pid_error', - 'pid_deriv', - 'pid_integ', - ): - if attr not in MyVar['Property']: - msg = 'PID: %s does not have required attribute: %s' % (nodename, attr) - print 'Warning:', msg - txt += [' # Warning: ' + msg] - txt += [' hfactory ${scobj_hpath}/%s plain %s %s' % (nodename, MyVar['priv'], MyVar['type'])] - if MyVar['readable'] > 0: - readable_or_writeable = True - fetch_func = MyVar['fetch_function'] - if fetch_func == 'none': - fetch_func = 'getValue' - read_func = MyVar['read_function'] - read_command = MyVar['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)] - if MyVar['writeable'] > 0 or MyVar['driveable']: - readable_or_writeable = True - check_func = MyVar['check_function'] - checkrange_func = MyVar['checkrange_function'] - write_func = MyVar['write_function'] - if 'write_command' in MyVar: - write_command = MyVar['write_command'] - else: - write_command = '' - txt += [' hsetprop ${scobj_hpath}/%s write ${ns}::%s ${scobj_hpath} %s {%s}' % (nodename, write_func, check_func, write_command)] - txt += [' hsetprop ${scobj_hpath}/%s %s ${ns}::%s ${scobj_hpath}' % (nodename, check_func, check_func)] - txt += [' hsetprop ${scobj_hpath}/%s check ${ns}::%s ${scobj_hpath}' % (nodename, checkrange_func)] - if MyVar['driveable']: - halt_func = MyVar['halt_function'] - checklimits_func = MyVar['checklimits_function'] - checkstatus_func = MyVar['checkstatus_function'] - txt += [' hsetprop ${scobj_hpath}/%s driving 0' % nodename] - txt += [' hsetprop ${scobj_hpath}/%s checklimits ${ns}::%s ${scobj_hpath}' % (nodename, checklimits_func)] - txt += [' hsetprop ${scobj_hpath}/%s checkstatus ${ns}::%s ${scobj_hpath}' % (nodename, checkstatus_func)] - txt += [' hsetprop ${scobj_hpath}/%s halt ${ns}::%s ${scobj_hpath}' % (nodename, halt_func)] - txt += [' hsetprop ${scobj_hpath}/%s driveable %s' % (nodename, MyVar['driveable'])] - if 'control' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s control %s' % (nodename, MyVar['control'])] - if 'data' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s data %s' % (nodename, MyVar['data'])] - if 'mutable' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s mutable %s' % (nodename, MyVar['mutable'])] - if 'nxsave' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s nxsave %s' % (nodename, MyVar['nxsave'])] - if 'lowerlimit' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s lowerlimit %s' % (nodename, MyVar['lowerlimit'])] - if 'upperlimit' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s upperlimit %s' % (nodename, MyVar['upperlimit'])] - if 'tolerance' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s tolerance %s' % (nodename, MyVar['tolerance'])] - if 'units' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s units %s' % (nodename, MyVar['units'])] - if 'allowed' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s values %s' % (nodename, MyVar['allowed'])] - if 'permlink' in MyVar: - device_type, node_type = MyVar['permlink'].split('.') - if device_type.startswith("#"): - if 'make_args' in MyDriver and 'permlink' in MyDriver['make_args'].split(): - idx = int(device_type[1:]) - device_type = '[string index ${permlink} %d]' % idx - else: - print 'Error: permlink required in make_ags' - if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): - permlink = device_type + '[format "%02d" ${id}]' + node_type - else: - permlink = device_type + '${permlink_device_number}' + node_type - txt += [' hsetprop ${scobj_hpath}/%s permlink data_set "%s"' % (nodename, permlink)] - txt += [' hsetprop ${scobj_hpath}/%s @description "%s"' % (nodename, permlink)] - if 'value' in MyVar: - txt += [' hsetprop ${scobj_hpath}/%s oldval %s' % (nodename, MyVar['value'])] - txt += [' hset ${scobj_hpath}/%s %s' % (nodename, MyVar['value'])] + readable_or_writeable = False + txt = [] + if MyGroup['name']: + txt += [''] + 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: - if MyVar['type'] == 'none': - pass - elif MyVar['type'] == 'int': - txt += [' hsetprop ${scobj_hpath}/%s oldval 0' % nodename] - elif MyVar['type'] == 'float': - txt += [' hsetprop ${scobj_hpath}/%s oldval 0.0' % nodename] - else: - txt += [' hsetprop ${scobj_hpath}/%s oldval UNKNOWN' % nodename] - for key in sorted(MyVar['Property']): - txt += [' hsetprop ${scobj_hpath}/%s %s "%s"' % (nodename, key, MyVar['Property'][key])] - # Generate __ at runtime for nxalias - if 'nxalias' not in MyVar['Property']: - nxalias = '${name}_' + make_path(MyVar) - 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: - txt += [''] - txt += [' if {[string equal -nocase [SplitReply [%s]] "false"]} {' % MyDriver['simulation_group']] + groupname = '' for var in sorted(MyGroup['Vars']): - MyVar = MyGroup['Vars'][var] - nodename = groupname + MyVar['name'] - if MyVar['readable'] > 0: - poll_period = MyVar['readable'] - if poll_period < 1 or poll_period > 300: - poll_period = 5 - 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']: - txt += [' ${sct_controller} write ${scobj_hpath}/%s' % nodename] - if MyVar['driveable']: - # Generate __ at runtime for driveable - driveable = '${name}_' + make_path(MyVar) - txt += [' ansto_makesctdrive %s ${scobj_hpath}/%s ${scobj_hpath}/%s ${sct_controller}' % (driveable, nodename, MyVar['driveable'])] - txt += [' } else {'] - txt += [' %s::sics_log 9 "[%s] => No poll/write for %s"' % (MyDriver['namespace'], MyDriver['simulation_group'], MyDriver['name'])] - txt += [' }'] - for grp in sorted(MyGroup['Groups']): - txt += put_group(MyDriver, MyGroup['Groups'][grp]) - return txt + txt += [''] + MyVar = MyGroup['Vars'][var] + nodename = groupname + MyVar['name'] + # Check driveable attributes are present if required + if 'driveable' in MyVar and MyVar['driveable']: + for attr in ('lowerlimit', 'upperlimit', 'tolerance'): + if attr not in MyVar: + msg = 'Driveable: %s does not have required attribute: %s' % (nodename, attr) + print 'Warning:', msg + txt += [' # Warning: ' + msg] + # Check PID attributes are present if required + if 'pid_function' in MyVar: + for attr in ('pid_pvalue', + 'pid_ivalue', + 'pid_dvalue', + 'pid_imax', + 'pid_error', + 'pid_deriv', + 'pid_integ', + ): + if attr not in MyVar['Property']: + msg = 'PID: %s does not have required attribute: %s' % (nodename, attr) + print 'Warning:', msg + txt += [' # Warning: ' + msg] + txt += [' hfactory ${scobj_hpath}/%s plain %s %s' % (nodename, MyVar['priv'], MyVar['type'])] + if MyVar['readable'] > 0: + readable_or_writeable = True + fetch_func = MyVar['fetch_function'] + if fetch_func == 'none': + fetch_func = 'getValue' + read_func = MyVar['read_function'] + read_command = MyVar['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)] + if MyVar['writeable'] > 0 or MyVar['driveable']: + readable_or_writeable = True + check_func = MyVar['check_function'] + checkrange_func = MyVar['checkrange_function'] + write_func = MyVar['write_function'] + if 'write_command' in MyVar: + write_command = MyVar['write_command'] + else: + write_command = '' + txt += [' hsetprop ${scobj_hpath}/%s write ${ns}::%s ${scobj_hpath} %s {%s}' % (nodename, write_func, check_func, write_command)] + txt += [' hsetprop ${scobj_hpath}/%s %s ${ns}::%s ${scobj_hpath}' % (nodename, check_func, check_func)] + txt += [' hsetprop ${scobj_hpath}/%s check ${ns}::%s ${scobj_hpath}' % (nodename, checkrange_func)] + if MyVar['driveable']: + halt_func = MyVar['halt_function'] + checklimits_func = MyVar['checklimits_function'] + checkstatus_func = MyVar['checkstatus_function'] + txt += [' hsetprop ${scobj_hpath}/%s driving 0' % nodename] + txt += [' hsetprop ${scobj_hpath}/%s checklimits ${ns}::%s ${scobj_hpath}' % (nodename, checklimits_func)] + txt += [' hsetprop ${scobj_hpath}/%s checkstatus ${ns}::%s ${scobj_hpath}' % (nodename, checkstatus_func)] + txt += [' hsetprop ${scobj_hpath}/%s halt ${ns}::%s ${scobj_hpath}' % (nodename, halt_func)] + txt += [' hsetprop ${scobj_hpath}/%s driveable %s' % (nodename, MyVar['driveable'])] + if 'control' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s control %s' % (nodename, MyVar['control'])] + if 'data' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s data %s' % (nodename, MyVar['data'])] + if 'mutable' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s mutable %s' % (nodename, MyVar['mutable'])] + if 'nxsave' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s nxsave %s' % (nodename, MyVar['nxsave'])] + if 'lowerlimit' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s lowerlimit %s' % (nodename, MyVar['lowerlimit'])] + if 'upperlimit' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s upperlimit %s' % (nodename, MyVar['upperlimit'])] + if 'tolerance' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s tolerance %s' % (nodename, MyVar['tolerance'])] + if 'units' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s units %s' % (nodename, MyVar['units'])] + if 'allowed' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s values %s' % (nodename, MyVar['allowed'])] + if 'permlink' in MyVar: + device_type, node_type = MyVar['permlink'].split('.') + if device_type.startswith("#"): + if 'make_args' in MyDriver and 'permlink' in MyDriver['make_args'].split(): + idx = int(device_type[1:]) + device_type = '[string index ${permlink} %d]' % idx + else: + print 'Error: permlink required in make_ags' + if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): + permlink = device_type + '[format "%02d" ${id}]' + node_type + else: + permlink = device_type + '${permlink_device_number}' + node_type + txt += [' hsetprop ${scobj_hpath}/%s permlink data_set "%s"' % (nodename, permlink)] + txt += [' hsetprop ${scobj_hpath}/%s @description "%s"' % (nodename, permlink)] + if 'value' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s oldval %s' % (nodename, MyVar['value'])] + txt += [' hset ${scobj_hpath}/%s %s' % (nodename, MyVar['value'])] + else: + if MyVar['type'] == 'none': + pass + elif MyVar['type'] == 'int': + txt += [' hsetprop ${scobj_hpath}/%s oldval 0' % nodename] + elif MyVar['type'] == 'float': + txt += [' hsetprop ${scobj_hpath}/%s oldval 0.0' % nodename] + else: + txt += [' hsetprop ${scobj_hpath}/%s oldval UNKNOWN' % nodename] + for key in sorted(MyVar['Property']): + txt += [' hsetprop ${scobj_hpath}/%s %s "%s"' % (nodename, key, MyVar['Property'][key])] + # Generate __ at runtime for nxalias + if 'nxalias' not in MyVar['Property']: + nxalias = '${name}_' + make_path(MyVar) + 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: + txt += [''] + txt += [' if {[string equal -nocase [SplitReply [%s]] "false"]} {' % MyDriver['simulation_group']] + for var in sorted(MyGroup['Vars']): + MyVar = MyGroup['Vars'][var] + nodename = groupname + MyVar['name'] + if MyVar['readable'] > 0: + poll_period = MyVar['readable'] + if poll_period < 1 or poll_period > 300: + poll_period = 5 + 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']: + txt += [' ${sct_controller} write ${scobj_hpath}/%s' % nodename] + if MyVar['driveable']: + # Generate __ at runtime for driveable + driveable = '${name}_' + make_path(MyVar) + txt += [' ansto_makesctdrive %s ${scobj_hpath}/%s ${scobj_hpath}/%s ${sct_controller}' % (driveable, nodename, MyVar['driveable'])] + txt += [' } else {'] + txt += [' %s::sics_log 9 "[%s] => No poll/write for %s"' % (MyDriver['namespace'], MyDriver['simulation_group'], MyDriver['name'])] + txt += [' }'] + for grp in sorted(MyGroup['Groups']): + txt += put_group(MyDriver, MyGroup['Groups'][grp]) + return txt def put_mkDriver(MyDriver): - txt = [''] - if 'make_args' in MyDriver: - line = 'proc %s::mkDriver { sct_controller name %s } {' % (MyDriver['namespace'], MyDriver['make_args']) - else: - line = 'proc %s::mkDriver { sct_controller name } {' % (MyDriver['namespace']) - txt += [line] - if 'make_args' in MyDriver: - make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) - txt += [' %s::sics_log 9 "%s::mkDriver ${sct_controller} ${name} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] - else: - txt += [' %s::sics_log 9 "%s::mkDriver for ${name}"' % (MyDriver['namespace'], MyDriver['namespace'])] - txt += [' set ns "[namespace current]"'] - txt += [' set catch_status [ catch {'] - txt += [''] - if len(MyDriver['Permlink']) > 0: - if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): - pass + txt = [''] + if 'make_args' in MyDriver: + line = 'proc %s::mkDriver { sct_controller name %s } {' % (MyDriver['namespace'], MyDriver['make_args']) else: - txt += [' set permlink_device_number [format "%02d" [incr ::scobj::permlink_device_counter]]'] - txt += [''] - txt += [' MakeSICSObj ${name} SCT_OBJECT'] - txt += [''] - txt += [' sicslist setatt ${name} klass %s' % MyDriver['class']] - txt += [' sicslist setatt ${name} long_name ${name}'] - if 'DriverProperty' in MyDriver: - for key in MyDriver['DriverProperty']: - txt += [' sicslist setatt ${name} %s "%s"' % (key, MyDriver['DriverProperty'][key])] - txt += [''] - txt += [' set scobj_hpath /sics/${name}'] + line = 'proc %s::mkDriver { sct_controller name } {' % (MyDriver['namespace']) + txt += [line] + if 'make_args' in MyDriver: + make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) + txt += [' %s::sics_log 9 "%s::mkDriver ${sct_controller} ${name} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] + else: + txt += [' %s::sics_log 9 "%s::mkDriver for ${name}"' % (MyDriver['namespace'], MyDriver['namespace'])] + txt += [' set ns "[namespace current]"'] + txt += [' set catch_status [ catch {'] + txt += [''] + if len(MyDriver['Permlink']) > 0: + if 'make_args' in MyDriver and 'id' in MyDriver['make_args'].split(): + pass + else: + txt += [' set permlink_device_number [format "%02d" [incr ::scobj::permlink_device_counter]]'] + txt += [''] + txt += [' MakeSICSObj ${name} SCT_OBJECT'] + txt += [''] + txt += [' sicslist setatt ${name} klass %s' % MyDriver['class']] + txt += [' sicslist setatt ${name} long_name ${name}'] + if 'DriverProperty' in MyDriver: + for key in MyDriver['DriverProperty']: + txt += [' sicslist setatt ${name} %s "%s"' % (key, MyDriver['DriverProperty'][key])] + txt += [''] + txt += [' set scobj_hpath /sics/${name}'] - for group in sorted(MyDriver['Groups']): - txt += put_group(MyDriver, MyDriver['Groups'][group]) + for group in sorted(MyDriver['Groups']): + txt += put_group(MyDriver, MyDriver['Groups'][group]) - txt += [' hsetprop ${scobj_hpath} klass %s' % MyDriver['class']] - txt += [' hsetprop ${scobj_hpath} debug_threshold %s' % str(MyDriver['debug_threshold'])] - func = 'mkDriver' - if func in MyDriver['Funcs']: - txt += ['# %s hook code starts' % func] - txt += MyDriver['Funcs'][func]['text'] - txt += ['# %s hook code ends' % func] - else: - txt += ['# %s hook code goes here' % func] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + txt += [' hsetprop ${scobj_hpath} klass %s' % MyDriver['class']] + txt += [' hsetprop ${scobj_hpath} debug_threshold %s' % str(MyDriver['debug_threshold'])] + func = 'mkDriver' + if func in MyDriver['Funcs']: + txt += ['# %s hook code starts' % func] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# %s hook code ends' % func] + else: + txt += ['# %s hook code goes here' % func] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_postamble(MyDriver): - txt = [''] - txt += ['namespace eval %s {' % MyDriver['namespace']] - txt += [' namespace export debug_threshold'] - txt += [' namespace export debug_log'] - txt += [' namespace export sics_log'] - txt += [' namespace export mkDriver'] - txt += ['}'] - txt += [''] - if 'add_args' in MyDriver: - line = 'proc add_%s {name IP port %s} {' % (MyDriver['name'], MyDriver['add_args']) - else: - line = 'proc add_%s {name IP port} {' % MyDriver['name'] - txt += [line] - txt += [' set catch_status [ catch {'] - if 'make_args' in MyDriver: - make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) - txt += [' %s::sics_log 9 "add_%s ${name} ${IP} ${port} %s"' % (MyDriver['namespace'], MyDriver['name'], make_args)] - else: - txt += [' %s::sics_log 9 "add_%s ${name} ${IP} ${port}"' % (MyDriver['namespace'], MyDriver['name'])] - txt += [' if {[string equal -nocase [SplitReply [%s]] "false"]} {' % MyDriver['simulation_group']] - txt += [' if {[string equal -nocase "aqadapter" "${IP}"]} {'] - txt += [' %s::sics_log 9 "makesctcontroller sct_${name} aqadapter ${port}"' % MyDriver['namespace']] - txt += [' makesctcontroller sct_${name} aqadapter ${port}'] - txt += [' } else {'] - if 'protocol_args' in MyDriver: - protocol_args = MyDriver['protocol_args'].replace('\\', '\\\\').replace('"', '\\"') - txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${IP}:${port} %s"' % (MyDriver['namespace'], MyDriver['protocol'], protocol_args)] - txt += [' makesctcontroller sct_${name} %s ${IP}:${port} %s' % (MyDriver['protocol'], MyDriver['protocol_args'])] - else: - txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${IP}:${port}"' % (MyDriver['namespace'], MyDriver['protocol'])] - txt += [' makesctcontroller sct_${name} %s ${IP}:${port}' % MyDriver['protocol']] - txt += [' }'] - txt += [' } else {'] - txt += [' %s::sics_log 9 "[%s] => No sctcontroller for %s"' % (MyDriver['namespace'], MyDriver['simulation_group'], MyDriver['name'])] - txt += [' }'] - if 'make_args' in MyDriver: - make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) - txt += [' %s::sics_log 1 "%s::mkDriver sct_${name} ${name} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] - txt += [' %s::mkDriver sct_${name} ${name} %s' % (MyDriver['namespace'], make_args)] - else: - txt += [' %s::sics_log 1 "%s::mkDriver sct_${name} ${name}"' % (MyDriver['namespace'], MyDriver['namespace'])] - txt += [' %s::mkDriver sct_${name} ${name}' % (MyDriver['namespace'])] + txt = [''] + txt += ['namespace eval %s {' % MyDriver['namespace']] + txt += [' namespace export debug_threshold'] + txt += [' namespace export debug_log'] + txt += [' namespace export sics_log'] + txt += [' namespace export mkDriver'] + txt += ['}'] + txt += [''] + if 'add_args' in MyDriver: + line = 'proc add_%s {name IP port %s} {' % (MyDriver['name'], MyDriver['add_args']) + else: + line = 'proc add_%s {name IP port} {' % MyDriver['name'] + txt += [line] + txt += [' set catch_status [ catch {'] + if 'make_args' in MyDriver: + make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) + txt += [' %s::sics_log 9 "add_%s ${name} ${IP} ${port} %s"' % (MyDriver['namespace'], MyDriver['name'], make_args)] + else: + txt += [' %s::sics_log 9 "add_%s ${name} ${IP} ${port}"' % (MyDriver['namespace'], MyDriver['name'])] + txt += [' if {[string equal -nocase [SplitReply [%s]] "false"]} {' % MyDriver['simulation_group']] + txt += [' if {[string equal -nocase "aqadapter" "${IP}"]} {'] + txt += [' %s::sics_log 9 "makesctcontroller sct_${name} aqadapter ${port}"' % MyDriver['namespace']] + txt += [' makesctcontroller sct_${name} aqadapter ${port}'] + txt += [' } else {'] + if 'protocol_args' in MyDriver: + protocol_args = MyDriver['protocol_args'].replace('\\', '\\\\').replace('"', '\\"') + txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${IP}:${port} %s"' % (MyDriver['namespace'], MyDriver['protocol'], protocol_args)] + txt += [' makesctcontroller sct_${name} %s ${IP}:${port} %s' % (MyDriver['protocol'], MyDriver['protocol_args'])] + else: + txt += [' %s::sics_log 9 "makesctcontroller sct_${name} %s ${IP}:${port}"' % (MyDriver['namespace'], MyDriver['protocol'])] + txt += [' makesctcontroller sct_${name} %s ${IP}:${port}' % MyDriver['protocol']] + txt += [' }'] + txt += [' } else {'] + txt += [' %s::sics_log 9 "[%s] => No sctcontroller for %s"' % (MyDriver['namespace'], MyDriver['simulation_group'], MyDriver['name'])] + txt += [' }'] + if 'make_args' in MyDriver: + make_args = ' '.join(["${%s}"%arg for arg in MyDriver['make_args'].split()]) + txt += [' %s::sics_log 1 "%s::mkDriver sct_${name} ${name} %s"' % (MyDriver['namespace'], MyDriver['namespace'], make_args)] + txt += [' %s::mkDriver sct_${name} ${name} %s' % (MyDriver['namespace'], make_args)] + else: + txt += [' %s::sics_log 1 "%s::mkDriver sct_${name} ${name}"' % (MyDriver['namespace'], MyDriver['namespace'])] + txt += [' %s::mkDriver sct_${name} ${name}' % (MyDriver['namespace'])] # TODO #txt += [' %s::sics_log "makesctemon ${name} /sics/${name}/emon/monmode /sics/${name}/emon/isintol /sics/${name}/emon/errhandler"' % (MyDriver['namespace'])] # txt += [' makesctemon ${name} /sics/${name}/emon/monmode /sics/${name}/emon/isintol /sics/${name}/emon/errhandler'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - txt += [''] - txt += ['clientput "file evaluation of sct_%s.tcl"' % MyDriver['name']] - txt += ['%s::sics_log 9 "file evaluation of sct_%s.tcl"' % (MyDriver['namespace'], MyDriver['name'])] - emit(txt) + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + txt += [''] + txt += ['clientput "file evaluation of sct_%s.tcl"' % MyDriver['name']] + txt += ['%s::sics_log 9 "file evaluation of sct_%s.tcl"' % (MyDriver['namespace'], MyDriver['name'])] + emit(txt) def put_read_config(MyDriver): - txt = [''] - txt += ['proc %s::read_config {} {' % MyDriver['namespace']] - txt += [' set catch_status [ catch {'] - txt += [' set ns "%s"' % MyDriver['namespace']] - txt += [' dict for {k v} $::config_dict {'] - txt += [' if { [dict exists $v "implementation"] } {'] - txt += [' if { !([dict exists $v "name"] && [dict exists $v "enabled"]) } {'] - txt += [' continue'] - txt += [' }'] - txt += [' set name [dict get $v name]'] - txt += [' set enabled [string tolower [dict get $v "enabled"]]'] - txt += [' set implementation [dict get $v "implementation"]'] - txt += [' if { !([dict exists $::config_dict $implementation]) } {'] - txt += [' continue'] - txt += [' }'] - txt += [' set v [dict get $::config_dict $implementation]'] - txt += [' if { !([dict exists $v "driver"]) } {'] - txt += [' continue'] - txt += [' }'] - txt += [' if { [string equal -nocase [dict get $v "driver"] "%s"] } {' % MyDriver['name']] - txt += [' if { [string equal -nocase $enabled "true" ] || [string equal -nocase $enabled "always"] } {'] - txt += [' if { ![string equal -nocase [SplitReply [%s]] "false"] } {' % MyDriver['simulation_group']] - txt += [' set asyncqueue "null"'] - txt += [' ${ns}::sics_log 9 "[%s] => using null asyncqueue"' % MyDriver['simulation_group']] - txt += [' } elseif { [dict exists $v "asyncqueue"] } {'] - txt += [' set asyncqueue [dict get $v "asyncqueue"]'] - txt += [' } else {'] - txt += [' if { [dict exists $v "asyncprotocol"] } {'] - txt += [' set asyncprotocol [dict get $v "asyncprotocol"]'] - txt += [' } else {'] - txt += [' set asyncprotocol ${name}_protocol'] - txt += [' MakeAsyncProtocol ${asyncprotocol}'] - txt += [' if { [dict exists $v "terminator"] } {'] - txt += [' ${asyncprotocol} sendterminator "[dict get $v "terminator"]"'] - txt += [' ${asyncprotocol} replyterminator "[dict get $v "terminator"]"'] - txt += [' }'] - txt += [' }'] - txt += [' set asyncqueue ${name}_queue'] - txt += [' set IP [dict get $v ip]'] - txt += [' set PORT [dict get $v port]'] - txt += [' MakeAsyncQueue ${asyncqueue} ${asyncprotocol} ${IP} ${PORT}'] - txt += [' if { [dict exists $v "timeout"] } {'] - txt += [' ${asyncqueue} timeout "[dict get $v "timeout"]"'] - txt += [' }'] - txt += [' }'] - if 'make_args' in MyDriver: - txt += [' set arg_list [list]'] - txt += [' foreach arg {' + MyDriver['make_args'] + '} {'] - txt += [' if {[dict exists $v $arg]} {'] - txt += [' lappend arg_list "[dict get $v $arg]"'] + txt = [''] + txt += ['proc %s::read_config {} {' % MyDriver['namespace']] + txt += [' set catch_status [ catch {'] + txt += [' set ns "%s"' % MyDriver['namespace']] + txt += [' dict for {k v} $::config_dict {'] + txt += [' if { [dict exists $v "implementation"] } {'] + txt += [' if { !([dict exists $v "name"] && [dict exists $v "enabled"]) } {'] + txt += [' continue'] + txt += [' }'] + txt += [' set name [dict get $v name]'] + txt += [' set enabled [string tolower [dict get $v "enabled"]]'] + txt += [' set implementation [dict get $v "implementation"]'] + txt += [' if { !([dict exists $::config_dict $implementation]) } {'] + txt += [' continue'] + txt += [' }'] + txt += [' set v [dict get $::config_dict $implementation]'] + txt += [' if { !([dict exists $v "driver"]) } {'] + txt += [' continue'] + txt += [' }'] + txt += [' if { [string equal -nocase [dict get $v "driver"] "%s"] } {' % MyDriver['name']] + txt += [' if { [string equal -nocase $enabled "true" ] || [string equal -nocase $enabled "always"] } {'] + txt += [' if { ![string equal -nocase [SplitReply [%s]] "false"] } {' % MyDriver['simulation_group']] + txt += [' set asyncqueue "null"'] + txt += [' ${ns}::sics_log 9 "[%s] => using null asyncqueue"' % MyDriver['simulation_group']] + txt += [' } elseif { [dict exists $v "asyncqueue"] } {'] + txt += [' set asyncqueue [dict get $v "asyncqueue"]'] + txt += [' } else {'] + txt += [' if { [dict exists $v "asyncprotocol"] } {'] + txt += [' set asyncprotocol [dict get $v "asyncprotocol"]'] txt += [' } else {'] - txt += [' ${ns}::sics_log 9 "Missing configuration value $arg"'] - txt += [' error "Missing configuration value $arg"'] + txt += [' set asyncprotocol ${name}_protocol'] + txt += [' MakeAsyncProtocol ${asyncprotocol}'] + txt += [' if { [dict exists $v "terminator"] } {'] + txt += [' ${asyncprotocol} sendterminator "[dict get $v "terminator"]"'] + txt += [' ${asyncprotocol} replyterminator "[dict get $v "terminator"]"'] + txt += [' }'] + txt += [' }'] + txt += [' set asyncqueue ${name}_queue'] + txt += [' set IP [dict get $v ip]'] + txt += [' set PORT [dict get $v port]'] + txt += [' MakeAsyncQueue ${asyncqueue} ${asyncprotocol} ${IP} ${PORT}'] + txt += [' if { [dict exists $v "timeout"] } {'] + txt += [' ${asyncqueue} timeout "[dict get $v "timeout"]"'] txt += [' }'] txt += [' }'] - txt += [' add_%s ${name} "aqadapter" ${asyncqueue} {*}$arg_list' % MyDriver['name']] - else: - txt += [' add_%s ${name} "aqadapter" ${asyncqueue}' % MyDriver['name']] - txt += [' }'] - txt += [' }'] - txt += [' }'] - txt += [' }'] - txt += [' } catch_message ]'] - txt += [' handle_exception ${catch_status} ${catch_message}'] - txt += ['}'] - emit(txt) + if 'make_args' in MyDriver: + txt += [' set arg_list [list]'] + txt += [' foreach arg {' + MyDriver['make_args'] + '} {'] + txt += [' if {[dict exists $v $arg]} {'] + txt += [' lappend arg_list "[dict get $v $arg]"'] + txt += [' } else {'] + txt += [' ${ns}::sics_log 9 "Missing configuration value $arg"'] + txt += [' error "Missing configuration value $arg"'] + txt += [' }'] + txt += [' }'] + txt += [' add_%s ${name} "aqadapter" ${asyncqueue} {*}$arg_list' % MyDriver['name']] + else: + txt += [' add_%s ${name} "aqadapter" ${asyncqueue}' % MyDriver['name']] + txt += [' }'] + txt += [' }'] + txt += [' }'] + txt += [' }'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) def put_check_config(MyDriver): - txt = [''] - txt += ['if { [info exists ::config_dict] } {'] - txt += [' %s::read_config' % MyDriver['namespace']] - txt += ['} else {'] - txt += [' %s::sics_log 5 "No config dict"' % MyDriver['namespace']] - txt += ['}'] - emit(txt) + txt = [''] + txt += ['if { [info exists ::config_dict] } {'] + txt += [' %s::read_config' % MyDriver['namespace']] + txt += ['} else {'] + txt += [' %s::sics_log 5 "No config dict"' % MyDriver['namespace']] + txt += ['}'] + emit(txt) def put_standard_code(MyDriver): - # emit all of the functions in Funcs - for func in sorted(MyDriver['Funcs']): - theFunc = MyDriver['Funcs'][func] - # Don't generate functions which are not referenced - #if theFunc['reference_count'] == 0: - # continue - if theFunc['type'] == 'read_function': - put_read_function(MyDriver, func); - elif theFunc['type'] == 'write_function': - put_write_function(MyDriver, func); - elif theFunc['type'] == 'fetch_function': - put_fetch_function(MyDriver, func); - elif theFunc['type'] == 'check_function': - put_check_function(MyDriver, func); - elif theFunc['type'] == 'checkrange_function': - put_checkrange_function(MyDriver, func); - elif theFunc['type'] == 'checklimits_function': - put_checklimits_function(MyDriver, func); - elif theFunc['type'] == 'checkstatus_function': - put_checkstatus_function(MyDriver, func); - elif theFunc['type'] == 'halt_function': - put_halt_function(MyDriver, func); - elif theFunc['type'] == 'pid_function': - put_pid_function(MyDriver, func); + # emit all of the functions in Funcs + for func in sorted(MyDriver['Funcs']): + theFunc = MyDriver['Funcs'][func] + # Don't generate functions which are not referenced + #if theFunc['reference_count'] == 0: + # continue + if theFunc['type'] == 'read_function': + put_read_function(MyDriver, func); + elif theFunc['type'] == 'write_function': + put_write_function(MyDriver, func); + elif theFunc['type'] == 'fetch_function': + put_fetch_function(MyDriver, func); + elif theFunc['type'] == 'check_function': + put_check_function(MyDriver, func); + elif theFunc['type'] == 'checkrange_function': + put_checkrange_function(MyDriver, func); + elif theFunc['type'] == 'checklimits_function': + put_checklimits_function(MyDriver, func); + elif theFunc['type'] == 'checkstatus_function': + put_checkstatus_function(MyDriver, func); + elif theFunc['type'] == 'halt_function': + put_halt_function(MyDriver, func); + elif theFunc['type'] == 'pid_function': + put_pid_function(MyDriver, func); def generate_driver(MyDriver): - global NumberOfLinesOut - global fdo - NumberOfLinesOut = 0 - full_filename = filename = "sct_%s.tcl" % MyDriver['name'] - if 'PathName' in MyDriver: - full_filename = os.path.join(MyDriver['PathName'], filename) - fdo = open(full_filename, 'w') - put_preamble(MyDriver) - put_standard_code(MyDriver) - put_mkDriver(MyDriver) - put_postamble(MyDriver) - put_read_config(MyDriver) - put_check_config(MyDriver) - fdo.close() - if CodeDump or Verbose: - print "Code Fragments:", MyDriver['Funcs'] - for f in sorted(MyDriver['Funcs'].keys()): - print "Function:", f, "Type:", MyDriver['Funcs'][f]['type'], '#Uses:', MyDriver['Funcs'][f]['reference_count'] - for l in MyDriver['Funcs'][f]['text']: - print " ", l - print "Produced file %s with %d lines." % (filename, NumberOfLinesOut) + global NumberOfLinesOut + global fdo + NumberOfLinesOut = 0 + full_filename = filename = "sct_%s.tcl" % MyDriver['name'] + if 'PathName' in MyDriver: + full_filename = os.path.join(MyDriver['PathName'], filename) + fdo = open(full_filename, 'w') + put_preamble(MyDriver) + put_standard_code(MyDriver) + put_mkDriver(MyDriver) + put_postamble(MyDriver) + put_read_config(MyDriver) + put_check_config(MyDriver) + fdo.close() + if CodeDump or Verbose: + print "Code Fragments:", MyDriver['Funcs'] + for f in sorted(MyDriver['Funcs'].keys()): + print "Function:", f, "Type:", MyDriver['Funcs'][f]['type'], '#Uses:', MyDriver['Funcs'][f]['reference_count'] + for l in MyDriver['Funcs'][f]['text']: + print " ", l + print "Produced file %s with %d lines." % (filename, NumberOfLinesOut) def process_drivers(TheDrivers): - if Verbose: - print "TheDrivers:", TheDrivers - for driver in TheDrivers: - MyDriver = {'name':driver} - MyDriver['namespace'] = '::scobj::%s' % driver - MyDriver['debug_threshold'] = '5' - MyDriver['Groups'] = {} - MyDriver['Funcs'] = {} - MyDriver['Permlink'] = {} - build_driver(MyDriver, TheDrivers[driver]) if Verbose: - print "MyDriver:", MyDriver['name'], '=', MyDriver - if DriverDump or Verbose: - dump_driver(MyDriver) - generate_driver(MyDriver) + print "TheDrivers:", TheDrivers + for driver in TheDrivers: + MyDriver = {'name':driver} + MyDriver['namespace'] = '::scobj::%s' % driver + MyDriver['debug_threshold'] = '5' + MyDriver['Groups'] = {} + MyDriver['Funcs'] = {} + MyDriver['Permlink'] = {} + build_driver(MyDriver, TheDrivers[driver]) + if Verbose: + print "MyDriver:", MyDriver['name'], '=', MyDriver + if DriverDump or Verbose: + dump_driver(MyDriver) + generate_driver(MyDriver) def process_source(source_files): - global PathName - global TheDrivers - global NumberOfLinesIn + global PathName + global TheDrivers + global NumberOfLinesIn - TheDrivers = {} + TheDrivers = {} - # - # Build the lexer - # - lexer = lex.lex() + # + # 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() + # + # 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))) - fd = open(source_file, 'r') - data = fd.read() - fd.close() - NumberOfLinesIn = data.count('\n') - start_line = lexer.lineno - yaccer.parse(data) - stop_line = lexer.lineno - print 'Consumed file %s with %d lines (%d, %d)' % (source_file, - NumberOfLinesIn, start_line, stop_line - 1) - lexer.lineno = 1 + for source_file in source_files: + PathName = os.path.realpath(os.path.abspath(os.path.dirname(source_file))) + fd = open(source_file, 'r') + data = fd.read() + fd.close() + NumberOfLinesIn = data.count('\n') + start_line = lexer.lineno + yaccer.parse(data) + stop_line = lexer.lineno + print 'Consumed file %s with %d lines (%d, %d)' % (source_file, + NumberOfLinesIn, start_line, stop_line - 1) + lexer.lineno = 1 - process_drivers(TheDrivers) + process_drivers(TheDrivers) def main(): - global Verbose - global DriverDump - global CodeDump - import argparse + global Verbose + global DriverDump + global CodeDump + import argparse - parser = argparse.ArgumentParser() - parser.add_argument("-c", "--code", help="dump code", - action="store_true") - parser.add_argument("-d", "--driver", help="dump driver", - action="store_true") - parser.add_argument("-v", "--verbose", help="verbose output", - action="store_true") - parser.add_argument("driver_source", help="driver source file", nargs="*") - args = parser.parse_args() - print args - if args.code: - CodeDump = True - else: - CodeDump = False - if args.driver: - DriverDump = True - else: - DriverDump = False - if args.verbose: - Verbose = True - else: - Verbose = False - source_files = args.driver_source - if source_files: - process_source(source_files) + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--code", help="dump code", + action="store_true") + parser.add_argument("-d", "--driver", help="dump driver", + action="store_true") + parser.add_argument("-v", "--verbose", help="verbose output", + action="store_true") + parser.add_argument("driver_source", help="driver source file", nargs="*") + args = parser.parse_args() + print args + if args.code: + CodeDump = True + else: + CodeDump = False + if args.driver: + DriverDump = True + else: + DriverDump = False + if args.verbose: + Verbose = True + else: + Verbose = False + source_files = args.driver_source + if source_files: + process_source(source_files) if __name__ == "__main__": - main() + main()