Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 57 additions & 16 deletions cparser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1135,22 +1135,63 @@ proc parseStructBody(p: var Parser, stmtList: PNode,
# handle anonymous unions / structs
if p.tok.xkind == pxSemiColon:
if pfAnonymousAsFields in p.options.flags:
let tdef = sstmts[^1][0]
let odef = tdef[2]
for i in 0..<sstmts.len-1:
stmtList.add(sstmts[i])
let rlist = odef[2]
for field in rlist:
if gotUnion and field[0][0].kind == nkPostfix and
not startsWith($(field[0][0][1]),"ano_"):
let name = "anon" & $cntAnonUnions & "_" & $field[0][0][1]
field[0][0][1] = newIdentNodeP(name, p)
elif gotUnion and
not startsWith($(field[0][1]),"ano_"):
let name = "anon" & $cntAnonUnions & "_" & $field[0][1]
field[0][1] = newIdentNodeP(name, p)
result.add(field)
getTok(p, nil)
# Be defensive: inner struct/union may yield no typesection
# (e.g. due to preprocessing oddities). If so, fall back to
# emitting a regular anonymous field instead of flattening.
if sstmts.len > 0 and sstmts[^1].len > 0:
let tdef = sstmts[^1][0]
if tdef.len > 2:
let odef = tdef[2]
for i in 0..<sstmts.len-1:
stmtList.add(sstmts[i])
if odef.len > 2:
let rlist = odef[2]
for field in rlist:
# Only handle actual field definitions; pass others through
if field.kind == nkIdentDefs and field.len > 0 and gotUnion:
let nameNode = field[0]
if nameNode.kind == nkPostfix:
# postfix form like: name*
if not startsWith($(nameNode[1]), "ano_"):
let name = "anon" & $cntAnonUnions & "_" & $nameNode[1]
nameNode[1] = newIdentNodeP(name, p)
elif nameNode.kind == nkIdent:
if not startsWith($(nameNode), "ano_"):
let name = "anon" & $cntAnonUnions & "_" & $nameNode
# Replace the ident in place
field[0] = newIdentNodeP(name, p)
result.add(field)
getTok(p, nil)
else:
# Structure node unexpected; degrade gracefully
let def = newNodeP(nkIdentDefs, p)
var t = pointer(p, baseTyp)
let i = fieldIdent("ano_" & p.hashPosition, p)
t = parseTypeSuffix(p, t)
addSon(def, i, t, emptyNode)
addSon(result, def)
getTok(p, nil)
stmtList.add(sstmts)
else:
# Missing expected child nodes; fallback to anonymous field
let def = newNodeP(nkIdentDefs, p)
var t = pointer(p, baseTyp)
let i = fieldIdent("ano_" & p.hashPosition, p)
t = parseTypeSuffix(p, t)
addSon(def, i, t, emptyNode)
addSon(result, def)
getTok(p, nil)
stmtList.add(sstmts)
else:
# No statements collected for inner type; fallback
let def = newNodeP(nkIdentDefs, p)
var t = pointer(p, baseTyp)
let i = fieldIdent("ano_" & p.hashPosition, p)
t = parseTypeSuffix(p, t)
addSon(def, i, t, emptyNode)
addSon(result, def)
getTok(p, nil)
stmtList.add(sstmts)
else:
let def = newNodeP(nkIdentDefs, p)
var t = pointer(p, baseTyp)
Expand Down
46 changes: 46 additions & 0 deletions testsuite/results/i2c_master.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
##
## SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
##
## SPDX-License-Identifier: Apache-2.0
##

import
esp_err, driver/i2c_types, hal/gpio_types

##
## @brief I2C master bus specific configurations
##

type
INNER_C_STRUCT_i2c_master_3* {.bycopy.} = object
enable_internal_pullup* {.bitsize: 1.}: uint32_t
## !< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible
allow_pd* {.bitsize: 1.}: uint32_t
## !< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode.
## By this approach, the system can power off I2C's power domain.
## This can save power, but at the expense of more RAM being consumed

i2c_master_bus_config_t* {.bycopy.} = object
i2c_port*: i2c_port_num_t
## !< I2C port number, `-1` for auto selecting, (not include LP I2C instance)
sda_io_num*: gpio_num_t
## !< GPIO number of I2C SDA signal, pulled-up internally
scl_io_num*: gpio_num_t
## !< GPIO number of I2C SCL signal, pulled-up internally
anon2_clk_source*: i2c_clock_source_t
## !< Clock source of I2C master bus
when SOC_LP_I2C_SUPPORTED:
var lp_source_clk*: lp_i2c_clock_source_t
## !< LP_UART source clock selection
glitch_ignore_cnt*: uint8_t
## !< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle)
intr_priority*: cint
## !< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3).
trans_queue_depth*: csize_t
## !< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction)
flags*: INNER_C_STRUCT_i2c_master_3
## !< I2C master config flags


const
I2C_DEVICE_ADDRESS_NOT_USED* = (0xffff) ## !< Skip carry address bit in driver transmit and receive
50 changes: 50 additions & 0 deletions testsuite/tests/i2c_master.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#anonymousAsFields


#pragma once

#include <stdint.h>
#include "esp_err.h"
#include "driver/i2c_types.h"
#include "hal/gpio_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief I2C master bus specific configurations
*/
typedef struct {
i2c_port_num_t i2c_port; /*!< I2C port number, `-1` for auto selecting, (not include LP I2C instance) */
gpio_num_t sda_io_num; /*!< GPIO number of I2C SDA signal, pulled-up internally */
gpio_num_t scl_io_num; /*!< GPIO number of I2C SCL signal, pulled-up internally */
union {
i2c_clock_source_t clk_source; /*!< Clock source of I2C master bus */
#if SOC_LP_I2C_SUPPORTED
lp_i2c_clock_source_t lp_source_clk; /*!< LP_UART source clock selection */
#endif
};
uint8_t glitch_ignore_cnt; /*!< If the glitch period on the line is less than this value, it can be filtered out, typically value is 7 (unit: I2C module clock cycle)*/
int intr_priority; /*!< I2C interrupt priority, if set to 0, driver will select the default priority (1,2,3). */
size_t trans_queue_depth; /*!< Depth of internal transfer queue, increase this value can support more transfers pending in the background, only valid in asynchronous transaction. (Typically max_device_num * per_transaction)*/
struct {
uint32_t enable_internal_pullup: 1; /*!< Enable internal pullups. Note: This is not strong enough to pullup buses under high-speed frequency. Recommend proper external pull-up if possible */
uint32_t allow_pd: 1; /*!< If set, the driver will backup/restore the I2C registers before/after entering/exist sleep mode.
By this approach, the system can power off I2C's power domain.
This can save power, but at the expense of more RAM being consumed */
} flags; /*!< I2C master config flags */
} i2c_master_bus_config_t;

#define I2C_DEVICE_ADDRESS_NOT_USED (0xffff) /*!< Skip carry address bit in driver transmit and receive */


#ifdef __cplusplus
}
#endif
Loading