| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- const {
- normalizeTypeText,
- parseDeclarator,
- parseFirstDeclarator,
- resolveType,
- splitDeclarations,
- splitDeclarators
- } = require('./struct-c-syntax.js')
- function isAsciiArray(typeText, dataType, name, arrayLength) {
- if (!arrayLength || arrayLength < 2 || arrayLength > 32) return false
- const normalizedType = normalizeTypeText(typeText).toLowerCase()
- if (normalizedType === 'char' || normalizedType === 'signed char') return true
- return dataType === 'uint8_t' && /(^|_)(model|name|text|str|string|chip|version|ver|serial|sn)($|_)/i.test(name)
- }
- function getDataTypeByteLength(dataType) {
- if (dataType === 'float' || dataType === 'int32_t' || dataType === 'uint32_t') return 4
- if (dataType === 'int8_t' || dataType === 'uint8_t') return 1
- return 2
- }
- function getBitFieldDataType(bitWidth) {
- const width = Math.max(1, Math.round(Number(bitWidth) || 1))
- if (width <= 8) return 'uint8_t'
- if (width <= 16) return 'uint16_t'
- return 'uint32_t'
- }
- function isBitType(typeText) {
- return normalizeTypeText(typeText).toLowerCase() === 'bit'
- }
- function alignLayoutToByte(layoutState) {
- if (layoutState.bitOffset % 8 !== 0) {
- layoutState.bitOffset += 8 - (layoutState.bitOffset % 8)
- }
- }
- function getLayoutByteStart(layoutState) {
- return Math.floor(layoutState.bitOffset / 8)
- }
- function advanceLayoutBytes(layoutState, byteLength) {
- layoutState.bitOffset += Math.max(1, Number(byteLength) || 1) * 8
- }
- function createBitFieldRegister(field, bitWidth, layoutState, name) {
- const width = Math.max(0, Math.round(Number(bitWidth) || 0))
- if (width === 0) {
- alignLayoutToByte(layoutState)
- return []
- }
- const byteStart = getLayoutByteStart(layoutState)
- const bitOffset = layoutState.bitOffset % 8
- layoutState.bitOffset += width
- if (!name) return []
- return [{
- bitOffset,
- bitWidth: width,
- byteStart,
- dataType: getBitFieldDataType(width),
- isBitField: true,
- name,
- unit: 'bit'
- }]
- }
- function createRegisterFromField(field, dataType, originalTypeText, layoutState) {
- const arrayLength = field.arrayDimensions.reduce((total, value) => total * value, 1)
- const hasArray = field.arrayDimensions.length > 0
- const bitFieldWidth = field.bitWidth !== null && field.bitWidth !== undefined
- ? field.bitWidth
- : (isBitType(originalTypeText) ? 1 : null)
- if (bitFieldWidth !== null && bitFieldWidth !== undefined) {
- if (hasArray) {
- const registers = []
- for (let index = 0; index < arrayLength; index += 1) {
- registers.push(...createBitFieldRegister(
- field,
- bitFieldWidth,
- layoutState,
- field.name ? `${field.name}[${index}]` : ''
- ))
- }
- return registers
- }
- return createBitFieldRegister(field, bitFieldWidth, layoutState, field.name)
- }
- alignLayoutToByte(layoutState)
- if (hasArray && isAsciiArray(originalTypeText, dataType, field.name, arrayLength)) {
- const byteStart = getLayoutByteStart(layoutState)
- advanceLayoutBytes(layoutState, arrayLength)
- return [{
- byteStart,
- dataType: 'ascii',
- name: field.name,
- textByteLength: String(arrayLength)
- }]
- }
- if (!hasArray) {
- const byteStart = getLayoutByteStart(layoutState)
- advanceLayoutBytes(layoutState, getDataTypeByteLength(dataType))
- return [{
- byteStart,
- dataType,
- name: field.name
- }]
- }
- const registers = []
- for (let index = 0; index < arrayLength; index += 1) {
- const byteStart = getLayoutByteStart(layoutState)
- advanceLayoutBytes(layoutState, getDataTypeByteLength(dataType))
- registers.push({
- byteStart,
- dataType,
- name: `${field.name}[${index}]`
- })
- }
- return registers
- }
- function parseStructFields(body, aliases) {
- const registers = []
- const layoutState = {
- bitOffset: 0
- }
- const declarations = splitDeclarations(body)
- declarations.forEach((statement) => {
- if (!statement || statement.indexOf('(') >= 0) return
- const parts = splitDeclarators(statement)
- if (!parts.length) return
- const first = parseFirstDeclarator(parts[0])
- if (!first) return
- const dataType = resolveType(first.typeText, aliases)
- if (!dataType) return
- const declarators = [first.declarator].concat(parts.slice(1))
- declarators.forEach((declaratorText) => {
- const field = parseDeclarator(declaratorText)
- if (!field) return
- registers.push(...createRegisterFromField(field, dataType, first.typeText, layoutState))
- })
- })
- return registers.map((register) => ({
- ...register,
- structByteLength: Math.ceil(layoutState.bitOffset / 8)
- }))
- }
- module.exports = {
- parseStructFields
- }
|