def outputC(specification, options, hFile, cFile): """ Outputs C header file. Given the specification construct a valid C header file that describes all the binary packets. Args: specification (dict): The specification object. options (dict): A dictionary of options to modify output. hFile (file): A file-like object to which to save the header. cFile (file): A file-like object to which to save the C code. """ assert isinstance(specification, dict) assert hasattr(hFile, 'write') assert hasattr(cFile, 'write') writeOut(cFile, '/** @file {} */'.format(options['cFilename'])) writeOut(cFile, '#include "{}"'.format(options['hFilename'])) defName = "STRUCTSPEC_{}_H".format(specification['id'].upper()) writeOut(hFile, '/** @file {} */'.format(options['hFilename'])) writeOut(hFile, '#ifndef {}'.format(defName)) writeOut(hFile, '#define {}'.format(defName)) writeOut(hFile, '#ifdef __cplusplus') writeOut(hFile, 'extern "C"') writeOut(hFile, '{') writeOut(hFile, '#endif /* __cplusplus */') writeOut(hFile, '') writeOut((hFile, cFile), '/**') prefix = ' * ' writeOut((hFile, cFile), '@brief\t{}'.format(specification['title']), prefix) if 'description' in specification: writeOut((hFile, cFile), ' *') writeOutBlock((hFile, cFile), '@details\t'.format(specification['description']), prefix) for tag in ('version', 'date', 'author'): if tag in specification: writeOut((hFile, cFile), ' *') writeOut((hFile, cFile), '@{}\t{}'.format(tag, specification[tag]), prefix) for tag in ('documentation', 'metadata'): if tag in specification: writeOut((hFile, cFile), ' *') writeOut((hFile, cFile), '[{}]({})'.format(tag.title(), specification[tag]), prefix) writeOut((hFile, cFile), ' */') writeOut((hFile, cFile), '') writeOut(hFile, '#include <stdint.h>') writeOut(hFile, '') for enumerationName, enumeration in specification['enums'].items(): if not enumeration.get('preprocessor', False): writeOut(hFile, '/**') writeOut(hFile, '@enum\t{}'.format(enumerationName), ' * ') else: writeOut(hFile, '/*') if 'title' in enumeration: writeOut(hFile, enumeration['title'], ' * ') else: writeOut(hFile, enumerationName, ' * ') if 'description' in enumeration: writeOut(hFile, ' *') writeOutBlock(hFile, enumeration['description'], ' * ') writeOut(hFile, ' */') if enumeration.get('preprocessor', False): for optionName, option in enumeration['options'].items(): line = [] if 'description' in option: writeOut(hFile, '/**') writeOutBlock(hFile, option['description'], ' * ') writeOut(hFile, ' */') line.append('#define ') line.append(optionName) if 'value' in option: line.append(' {}'.format(option['value'])) if 'title' in option: line.append(' /** {} */'.format(option['title'])) writeOut(hFile, ''.join(line)) else: writeOut(hFile, "typedef enum {") lastOption = enumeration['options'].keys()[-1] for optionName, option in enumeration['options'].items(): line = [] if 'description' in option: writeOut(hFile, ' /**') writeOutBlock(hFile, option['description'], ' * ') writeOut(hFile, ' */') line.append(optionName) if 'value' in option: line.append(' = {}'.format(option['value'])) if 'title' in option: line.append(' /** {} */'.format(option['title'])) if optionName != lastOption: line.append(',') writeOut(hFile, ''.join(line), ' ') writeOut(hFile, "}} {};".format(enumerationName)) writeOut(hFile, '') for packetName, packet in specification['packets'].items(): writeOut(hFile, "typedef struct {") for structureName, structure in packet['structure'].items(): line = [] if 'description' in structure: writeOut(hFile, ' /**') writeOutBlock(hFile, structure['description'], ' * ') writeOut(hFile, ' */') if structure['type'].startswith('#/'): typeName = structure['type'][structure['type'].rfind('/') + 1:] else: typeName = structure['type'] line.append(typeName) line.append(' ') line.append(structureName) if 'count' in structure: if structure['count'].startswith('#/'): countLabel = structure['count'][:-len(schemaVal)] countLabel = countLabel[countLabel.rfind('/') + 1:] else: countLabel = structure['count'] line.append('[{}]'.format(countLabel)) if 'size' in structure: if structure['size'].startswith('#/'): sizeLabel = structure['size'][:-len(schemaVal)] sizeLabel = sizeLabel[sizeLabel.rfind('/') + 1:] sizeInBits = resolveJsonPointer(specification, structure['size'][1:]) else: sizeLabel = structure['size'] try: sizeInBits = int(sizeLabel) except ValueError: sizeInBits = 0 if sizeInBits != typeSizes.get(typeName, -1): line.append(' : {}'.format(sizeLabel)) if 'title' in structure: line.append(' /** {} */'.format(structure['title'])) line.append(';') writeOut(hFile, ''.join(line), ' ') writeOut(hFile, "}} {};".format(packetName)) writeOut(hFile, '') writeOut(hFile, '#ifdef __cplusplus') writeOut(hFile, '}') writeOut(hFile, '#endif /* __cplusplus */') writeOut(hFile, '#endif /* {} */'.format(defName))
def outputC(specification, options, hFile, cFile): """ Outputs C header file. Given the specification construct a valid C header file that describes all the binary packets. Args: specification (dict): The specification object. options (dict): A dictionary of options to modify output. hFile (file): A file-like object to which to save the header. cFile (file): A file-like object to which to save the C code. """ assert isinstance(specification, dict) assert hasattr(hFile, 'write') assert hasattr(cFile, 'write') writeOut(cFile, '/** @file {} */'.format(options['cFilename'])) writeOut(cFile, '#include "{}"'.format(options['hFilename'])) defName = "STRUCTSPEC_{}_H".format(specification['id'].upper()) writeOut(hFile, '/** @file {} */'.format(options['hFilename'])) writeOut(hFile, '#ifndef {}'.format(defName)) writeOut(hFile, '#define {}'.format(defName)) writeOut(hFile, '#ifdef __cplusplus') writeOut(hFile, 'extern "C"') writeOut(hFile, '{') writeOut(hFile, '#endif /* __cplusplus */') writeOut(hFile, '') writeOut((hFile, cFile), '/**') prefix = ' * ' writeOut((hFile, cFile), '@brief\t{}'.format(specification['title']), prefix) if 'description' in specification: writeOut((hFile, cFile), ' *') writeOutBlock((hFile, cFile), '@details\t'.format( specification['description']), prefix) for tag in ('version', 'date', 'author'): if tag in specification: writeOut((hFile, cFile), ' *') writeOut((hFile, cFile), '@{}\t{}'.format(tag, specification[tag]), prefix) for tag in ('documentation', 'metadata'): if tag in specification: writeOut((hFile, cFile), ' *') writeOut((hFile, cFile), '[{}]({})'.format(tag.title(), specification[tag]), prefix) writeOut((hFile, cFile), ' */') writeOut((hFile, cFile), '') writeOut(hFile, '#include <stdint.h>') writeOut(hFile, '') for enumerationName, enumeration in specification['enums'].items(): if not enumeration.get('preprocessor', False): writeOut(hFile, '/**') writeOut(hFile, '@enum\t{}'.format(enumerationName), ' * ') else: writeOut(hFile, '/*') if 'title' in enumeration: writeOut(hFile, enumeration['title'], ' * ') else: writeOut(hFile, enumerationName, ' * ') if 'description' in enumeration: writeOut(hFile, ' *') writeOutBlock(hFile, enumeration['description'], ' * ') writeOut(hFile, ' */') if enumeration.get('preprocessor', False): for optionName, option in enumeration['options'].items(): line = [] if 'description' in option: writeOut(hFile, '/**') writeOutBlock(hFile, option['description'], ' * ') writeOut(hFile, ' */') line.append('#define ') line.append(optionName) if 'value' in option: line.append(' {}'.format(option['value'])) if 'title' in option: line.append(' /** {} */'.format(option['title'])) writeOut(hFile, ''.join(line)) else: writeOut(hFile, "typedef enum {") lastOption = enumeration['options'].keys()[-1] for optionName, option in enumeration['options'].items(): line = [] if 'description' in option: writeOut(hFile, ' /**') writeOutBlock(hFile, option['description'], ' * ') writeOut(hFile, ' */') line.append(optionName) if 'value' in option: line.append(' = {}'.format(option['value'])) if 'title' in option: line.append(' /** {} */'.format(option['title'])) if optionName != lastOption: line.append(',') writeOut(hFile, ''.join(line), ' ') writeOut(hFile, "}} {};".format(enumerationName)) writeOut(hFile, '') for packetName, packet in specification['packets'].items(): writeOut(hFile, "typedef struct {") for structureName, structure in packet['structure'].items(): line = [] if 'description' in structure: writeOut(hFile, ' /**') writeOutBlock(hFile, structure['description'], ' * ') writeOut(hFile, ' */') if structure['type'].startswith('#/'): typeName = structure['type'][structure['type'].rfind('/') + 1:] else: typeName = structure['type'] line.append(typeName) line.append(' ') line.append(structureName) if 'count' in structure: if structure['count'].startswith('#/'): countLabel = structure['count'][:-len(schemaVal)] countLabel = countLabel[countLabel.rfind('/') + 1:] else: countLabel = structure['count'] line.append('[{}]'.format(countLabel)) if 'size' in structure: if structure['size'].startswith('#/'): sizeLabel = structure['size'][:-len(schemaVal)] sizeLabel = sizeLabel[sizeLabel.rfind('/') + 1:] sizeInBits = resolveJsonPointer(specification, structure['size'][1:]) else: sizeLabel = structure['size'] try: sizeInBits = int(sizeLabel) except ValueError: sizeInBits = 0 if sizeInBits != typeSizes.get(typeName, -1): line.append(' : {}'.format(sizeLabel)) if 'title' in structure: line.append(' /** {} */'.format(structure['title'])) line.append(';') writeOut(hFile, ''.join(line), ' ') writeOut(hFile, "}} {};".format(packetName)) writeOut(hFile, '') writeOut(hFile, '#ifdef __cplusplus') writeOut(hFile, '}') writeOut(hFile, '#endif /* __cplusplus */') writeOut(hFile, '#endif /* {} */'.format(defName))
def populateWorkLists(packet, specification, structDefList, structAccretions): """ Loads work lists based on packet portion of spec. Given the portion of the specification definining a packets, the specification itself, and the work lists, populate them with the relevant information gleaned from the packet definition. Args: packet (dict): The definition of the individual packet being processed. specification (dict): The specification object. structDefList (list): List of items in the structure. structAccretions (dict): Structure information collected since last processing time. Returns: A tuple containing the bitfield count and bitfield length. """ assert isinstance(packet, dict) assert isinstance(specification, dict) assert isinstance(structDefList, list) assert isinstance(structAccretions, dict) assert isinstance(structAccretions['formatList'], list) and \ isinstance(structAccretions['countList'], list) and \ isinstance(structAccretions['varList'], list) and \ isinstance(structAccretions['bitFields'], list) bitFieldCount = bitFieldLen = 0 for structureName, structure in packet['structure'].items(): endianness = structure.get('endianness', packet.get('endianness', specification.get('endianness', ''))).encode('utf-8') if structure['type'].startswith('#/'): handleStructBreaks(structDefList, structAccretions, endianness) typeName = structure['type'][structure['type'].rfind('/') + 1:] structDefList.append({ 'type': 'substructure', 'itemName': structureName, 'itemType': typeName, 'description': structure.get('description', None), 'title': structure.get('title', None) }) else: typeName = structure['type'] if 'count' in structure: if structure['count'].startswith('#/'): countLabel = structure['count'][:-len(schemaVal)] countLabel = countLabel[countLabel.rfind('/') + 1:] structAccretions['formatList'].append('{}') structAccretions['countList'].append(countLabel) else: countLabel = structure['count'] structAccretions['formatList'].append(countLabel) gotBitField = False if 'size' in structure: if structure['size'].startswith('#/'): sizeLabel = structure['size'][:-len(schemaVal)] sizeLabel = sizeLabel[sizeLabel.rfind('/') + 1:] sizeInBits = resolveJsonPointer(specification, structure['size'][1:]) else: sizeLabel = structure['size'] try: sizeInBits = int(sizeLabel) except ValueError: sizeInBits = 0 if sizeInBits != typeSizes.get(typeName, -1) or \ sizeInBits % 8 != 0: gotBitField = True if typeName in typeFormatChar and not gotBitField: bitFieldCount = handleBitFields(bitFieldLen, bitFieldCount, structAccretions) bitFieldLen = 0 structAccretions['formatList'].append(typeFormatChar[typeName]) structAccretions['varList'].append( "packet['{}']".format(structureName)) structAccretions['titles'].append(structure.get('title', None)) structAccretions['descriptions'].append(structure.get('title', None)) elif gotBitField: bitFieldLen += sizeInBits structAccretions['bitFields'].append( ("packet['{}']".format(structureName), bitFieldCount, sizeInBits, typeName)) bitFieldCount = handleBitFields(bitFieldLen, bitFieldCount, structAccretions) handleStructBreaks(structDefList, structAccretions, endianness) return bitFieldCount
def populateWorkLists(packet, specification, structDefList, structAccretions): """ Loads work lists based on packet portion of spec. Given the portion of the specification definining a packets, the specification itself, and the work lists, populate them with the relevant information gleaned from the packet definition. Args: packet (dict): The definition of the individual packet being processed. specification (dict): The specification object. structDefList (list): List of items in the structure. structAccretions (dict): Structure information collected since last processing time. Returns: A tuple containing the bitfield count and bitfield length. """ assert isinstance(packet, dict) assert isinstance(specification, dict) assert isinstance(structDefList, list) assert isinstance(structAccretions, dict) assert isinstance(structAccretions['formatList'], list) and \ isinstance(structAccretions['countList'], list) and \ isinstance(structAccretions['varList'], list) and \ isinstance(structAccretions['bitFields'], list) bitFieldCount = bitFieldLen = 0 for structureName, structure in packet['structure'].items(): endianness = structure.get( 'endianness', packet.get('endianness', specification.get('endianness', ''))).encode('utf-8') if structure['type'].startswith('#/'): handleStructBreaks(structDefList, structAccretions, endianness) typeName = structure['type'][structure['type'].rfind('/') + 1:] structDefList.append({ 'type': 'substructure', 'itemName': structureName, 'itemType': typeName, 'description': structure.get('description', None), 'title': structure.get('title', None) }) else: typeName = structure['type'] if 'count' in structure: if structure['count'].startswith('#/'): countLabel = structure['count'][:-len(schemaVal)] countLabel = countLabel[countLabel.rfind('/') + 1:] structAccretions['formatList'].append('{}') structAccretions['countList'].append(countLabel) else: countLabel = structure['count'] structAccretions['formatList'].append(countLabel) gotBitField = False if 'size' in structure: if structure['size'].startswith('#/'): sizeLabel = structure['size'][:-len(schemaVal)] sizeLabel = sizeLabel[sizeLabel.rfind('/') + 1:] sizeInBits = resolveJsonPointer(specification, structure['size'][1:]) else: sizeLabel = structure['size'] try: sizeInBits = int(sizeLabel) except ValueError: sizeInBits = 0 if sizeInBits != typeSizes.get(typeName, -1) or \ sizeInBits % 8 != 0: gotBitField = True if typeName in typeFormatChar and not gotBitField: bitFieldCount = handleBitFields(bitFieldLen, bitFieldCount, structAccretions) bitFieldLen = 0 structAccretions['formatList'].append(typeFormatChar[typeName]) structAccretions['varList'].append( "packet['{}']".format(structureName)) structAccretions['titles'].append(structure.get('title', None)) structAccretions['descriptions'].append( structure.get('title', None)) elif gotBitField: bitFieldLen += sizeInBits structAccretions['bitFields'].append( ("packet['{}']".format(structureName), bitFieldCount, sizeInBits, typeName)) bitFieldCount = handleBitFields(bitFieldLen, bitFieldCount, structAccretions) handleStructBreaks(structDefList, structAccretions, endianness) return bitFieldCount