ImCode Working Group C. de Oliveira Internet-Draft ImCode - Imagine Coding Laboratories Intended status: Informational 23 June 2026 Expires: 25 December 2026 Object-Oriented Programming Standard for Pure C draft-imcode-rfc-oop-c-00 Abstract This document defines RFC-OOP-C, a standard for object-oriented programming in pure C. It specifies naming conventions, class structure macros, method macros, validation macros, memory allocation patterns, lifecycle management, build-level configuration, struct versioning, Doxygen documentation requirements, and a conformance checker interface (the RFC-OOP-C Conformance Checker, RFC_Checker). The standard targets C11 (ISO/IEC 9899:2011) and is applicable to any C project on any microcontroller or platform whose toolchain supports C11. Supplementary guidance is provided for embedded systems including thread-safety and memory allocation strategies compatible with bare-metal, FreeRTOS and embOS. Copyright and License Copyright (c) 2026 ImCode - Imagine Coding Laboratories Inc. All rights reserved. SPDX-License-Identifier: Zlib The code components in this document are provided under the Zlib License. Permission is granted to use, alter, and redistribute freely, subject to: (1) origin must not be misrepresented; (2) altered versions must be marked as such; (3) this notice must not be removed from any distribution. The document text is additionally subject to the IETF Trust Legal Provisions as stated in the generated boilerplate. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Requirement-level keywords are defined in [BCP14]. de Oliveira Expires 25 December 2026 [Page 1] Internet-Draft RFC-OOP-C June 2026 This document specifies a Best Current Practice for C software development within ImCode projects and partner organizations. It does not represent an IETF standard. It is formatted following [RFC7322]. The ImCode Working Group retains full intellectual property rights over the standard and its implementations under the Zlib License (SPDX-License-Identifier: Zlib). This document is a product of the ImCode Working Group. It represents the consensus of the working group and has been approved for publication by the working group leadership. Information about the current status of this document and any reported errata is available at the project repository. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 25 December 2026. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 2. Requirements Language . . . . . . . . . . . . . . . . . . . . 4 3. Conventions of Nomenclature . . . . . . . . . . . . . . . . . 4 de Oliveira Expires 25 December 2026 [Page 2] Internet-Draft RFC-OOP-C June 2026 3.1. Symbol Category Table . . . . . . . . . . . . . . . . . . 4 3.2. Semantic Prefixes - Rule 11 . . . . . . . . . . . . . . . 5 4. AppControlClass - Root Class . . . . . . . . . . . . . . . . 6 4.1. Root Struct . . . . . . . . . . . . . . . . . . . . . . . 6 4.2. AppStatus Enum - Control Values . . . . . . . . . . . . . 7 4.3. Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . 7 4.4. Lifecycle Idempotency Rules . . . . . . . . . . . . . . . 8 4.5. AppControlClass_CheckingRunning . . . . . . . . . . . . . 8 4.6. Lifecycle Transition Functions . . . . . . . . . . . . . 9 4.7. Size by Build Level . . . . . . . . . . . . . . . . . . . 10 5. Class Macros . . . . . . . . . . . . . . . . . . . . . . . . 10 5.1. Global Symbols per Class . . . . . . . . . . . . . . . . 12 6. Method Macros . . . . . . . . . . . . . . . . . . . . . . . . 12 6.1. Build Level Suffix . . . . . . . . . . . . . . . . . . . 13 6.2. Compiler Compatibility . . . . . . . . . . . . . . . . . 14 7. Validation Macros . . . . . . . . . . . . . . . . . . . . . . 14 8. Memory Allocation Macros . . . . . . . . . . . . . . . . . . 15 8.1. AppControlClass_Destroy . . . . . . . . . . . . . . . . . 16 9. Build Levels - RFC_BUILD_LEVEL . . . . . . . . . . . . . . . 17 10. Formatting and Comments . . . . . . . . . . . . . . . . . . . 17 10.1. Formatting Rules (Rules 1-18) . . . . . . . . . . . . . 17 10.2. Doxygen Standard . . . . . . . . . . . . . . . . . . . . 18 10.3. Special Comments . . . . . . . . . . . . . . . . . . . . 19 11. Struct Versioning . . . . . . . . . . . . . . . . . . . . . . 19 12. RFC_Checker - Automatic Verification . . . . . . . . . . . . 19 12.1. Command-Line Interface . . . . . . . . . . . . . . . . . 19 12.2. Automatic Verifications . . . . . . . . . . . . . . . . 20 12.3. JSON Output Schema . . . . . . . . . . . . . . . . . . . 20 13. Legacy Migration . . . . . . . . . . . . . . . . . . . . . . 21 14. Security Considerations . . . . . . . . . . . . . . . . . . . 21 14.1. CLASS_INTEGRITY as Structural Control Value . . . . . . 21 14.2. RFC_ATOMIC on Processors Without Atomic Instructions . . 21 14.3. Dynamic Allocation and Heap Exhaustion . . . . . . . . . 22 14.4. Version Mismatch and Memory Safety . . . . . . . . . . . 22 14.5. use-after-free via _Destroy . . . . . . . . . . . . . . 22 14.6. Atomic Ordering Invariant . . . . . . . . . . . . . . . 22 14.7. classTimestamp Thread Safety . . . . . . . . . . . . . . 22 15. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 22 16. Conformance Checklist . . . . . . . . . . . . . . . . . . . . 22 17. Complete Macro Reference . . . . . . . . . . . . . . . . . . 23 18. References . . . . . . . . . . . . . . . . . . . . . . . . . 25 18.1. Normative References . . . . . . . . . . . . . . . . . . 25 18.2. Informative References . . . . . . . . . . . . . . . . . 25 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 26 de Oliveira Expires 25 December 2026 [Page 3] Internet-Draft RFC-OOP-C June 2026 1. Introduction RFC-OOP-C is a complete specification for object-oriented programming in pure C, applicable to any project written in C11 [C11], from desktop applications to deeply embedded firmware. All normative requirements apply to any microcontroller or processor whose toolchain supports C11 (ISO/IEC 9899:2011). Five principles guide all decisions: * Encapsulation: data and behavior in structs with explicit interfaces. * Explicit lifecycle: every object passes through documented, verifiable states. * Detectable failure: errors captured at compile-time, link-time, or runtime with clear diagnostics. * Traceability: event history, struct versioning, and mandatory Doxygen [DOXYGEN] docs. * Zero-dependency portability: pure C11, no external libraries required. 2. Requirements Language The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. 3. Conventions of Nomenclature RFC-OOP-C establishes deterministic naming rules per symbol category. Given any symbol, its category, origin, and role MUST be identifiable without consulting documentation. 3.1. Symbol Category Table +========+=================+========================+==============+ |Category| Convention | Example |Rule | +========+=================+========================+==============+ |Type/ | PascalCase | CounterClass |MUST use Class| |struct | | |suffix | +--------+-----------------+------------------------+--------------+ |Method | PascalCase | CounterClass_Create |MUST prefix | de Oliveira Expires 25 December 2026 [Page 4] Internet-Draft RFC-OOP-C June 2026 | | | |with type | +--------+-----------------+------------------------+--------------+ |Class | camel_Pascal | className_CounterClass |MUST use | |global | | |camelCase+type| |var | | | | +--------+-----------------+------------------------+--------------+ |Struct | camelCase | appStatus |No prefix | |field | | |required | +--------+-----------------+------------------------+--------------+ |RFC | SCREAMING_SNAKE | DECLARE_CLASS |MUST be | |macro | | |uppercase | +--------+-----------------+------------------------+--------------+ |Instance| _this | _this |MUST be _this,| |pointer | | |no variation | +--------+-----------------+------------------------+--------------+ |Loop | index[Ctx] | indexChannel |Rule 11: MUST | |index | | |NOT use i,j,k | +--------+-----------------+------------------------+--------------+ |Header | Class_Name.h | Class_Counter.h |MUST use | |file | | |Class_ prefix | +--------+-----------------+------------------------+--------------+ |Source | Class_Name.c | Class_Counter.c |MUST use | |file | | |Class_ prefix | +--------+-----------------+------------------------+--------------+ Table 1: Symbol naming conventions 3.2. Semantic Prefixes - Rule 11 Variable names MUST be descriptive. Single-letter names and context- free abbreviations MUST NOT be used in any scope. Function parameters and struct fields MAY use descriptive names without mandatory prefixes when purpose is clear. de Oliveira Expires 25 December 2026 [Page 5] Internet-Draft RFC-OOP-C June 2026 +===============+==================+==========================+ | Prefix | Role | Examples | +===============+==================+==========================+ | index[Ctx] | Iteration | indexKey indexChannel | +---------------+------------------+--------------------------+ | num[Ctx] | Total count | numKeys numChannels | +---------------+------------------+--------------------------+ | max[Ctx] | Upper limit | maxRetries maxChannels | +---------------+------------------+--------------------------+ | min[Ctx] | Lower limit | minValue minSamples | +---------------+------------------+--------------------------+ | count[Ctx] | Occurrences | countErrors countRetries | +---------------+------------------+--------------------------+ | total[Ctx] | Accumulated sum | totalBytes totalSamples | +---------------+------------------+--------------------------+ | temp[Ctx] | Temporary | tempBuffer tempValue | +---------------+------------------+--------------------------+ | result[Ctx] | Operation result | resultCode resultStatus | +---------------+------------------+--------------------------+ | offset[Ctx] | Displacement | offsetX offsetAddress | +---------------+------------------+--------------------------+ | previous[Ctx] | Previous value | previousStatus | +---------------+------------------+--------------------------+ Table 2: Semantic variable prefixes /* REQUIRED canonical for-loop form: */ for (int16_t indexKey = 0; indexKey < numKeys; indexKey++) { CounterClass_Increment(&keys[indexKey], 1); } /* PROHIBITED: */ for (int i = 0; i < n; i++) /* i, n, j, k forbidden */ 4. AppControlClass - Root Class AppControlClass is the REQUIRED first field of every derived class. It centralizes integrity verification, type identity, operational status, event history, and struct versioning. Its size varies by RFC_BUILD_LEVEL (Section 9). 4.1. Root Struct de Oliveira Expires 25 December 2026 [Page 6] Internet-Draft RFC-OOP-C June 2026 typedef struct AppControlClass { RFC_ATOMIC uint32_t integrity; RFC_ATOMIC AppStatus appStatus; uint8_t flags; /* bit0=ALLOC_DYN */ #if RFC_BUILD_LEVEL <= RFC_BUILD_HOM const char * const * className; uint16_t classSize; uint8_t classVersion; uint8_t historyDepth; AppControlEvent history[APPCONTROL_HISTORY_DEPTH]; RFC_ATOMIC uint8_t historyIndex; RFC_ATOMIC uint8_t historyCount; #endif } AppControlClass; NOTE: integrity MUST be written before appStatus in _Create and zeroed before appStatus in _Destroy. This ordering invariant is required for thread-safety. 4.2. AppStatus Enum - Control Values AppStatus values are Control Values: structured 32-bit patterns chosen to resist accidental assignment, detect bit-flip corruption, and encode build-level information. typedef enum { CLASS_CREATED = 0x00000347UL, /* initialized */ CLASS_PREPARED = 0x00888347UL, /* operational */ CLASS_RUNNING = 0x00AAA347UL, /* active */ CLASS_STOPPED = 0x00555347UL, /* stopped */ CLASS_FAILED = 0x00000666UL, /* failed */ } AppStatus; 4.3. Lifecycle +================+==========+================+=====================+ | From | Via | To | Condition | +================+==========+================+=====================+ | CLASS_CREATED | _Prepare | CLASS_PREPARED | Hardware configured | +----------------+----------+----------------+---------------------+ | CLASS_PREPARED | _Run | CLASS_RUNNING | Execution active | de Oliveira Expires 25 December 2026 [Page 7] Internet-Draft RFC-OOP-C June 2026 +----------------+----------+----------------+---------------------+ | CLASS_RUNNING | _Stop | CLASS_STOPPED | Ordered stop | +----------------+----------+----------------+---------------------+ | CLASS_RUNNING | _Fail | CLASS_FAILED | Failure recorded | +----------------+----------+----------------+---------------------+ | CLASS_STOPPED | _Prepare | CLASS_PREPARED | Restart without | | | | | _Destroy | +----------------+----------+----------------+---------------------+ | CLASS_FAILED | _Prepare | CLASS_PREPARED | Recovery | +----------------+----------+----------------+---------------------+ Table 3: AppControlClass lifecycle transitions _Destroy is a terminal operation from any state. After _Destroy: integrity == 0, flags == 0, appStatus == 0. If RFC_FLAG_ALLOC_DYNAMIC was set, FREE_CLASS is called automatically. The caller MUST set the pointer to NULL. 4.4. Lifecycle Idempotency Rules +==========+================+=================================+ | Call | State | Result | +==========+================+=================================+ | _Prepare | CLASS_PREPARED | Idempotent | +----------+----------------+---------------------------------+ | _Run | CLASS_RUNNING | Idempotent | +----------+----------------+---------------------------------+ | _Stop | CLASS_STOPPED | ASSEST_Void fires - no crash | +----------+----------------+---------------------------------+ | _Fail | CLASS_FAILED | Event recorded, state unchanged | +----------+----------------+---------------------------------+ Table 4: Defined behavior for repeated lifecycle calls 4.5. AppControlClass_CheckingRunning Returns 1 if the object is in an operational state. MUST be called exclusively via TEST_Class. de Oliveira Expires 25 December 2026 [Page 8] Internet-Draft RFC-OOP-C June 2026 uint8_t AppControlClass_CheckingRunning( AppControlClass * _this) { return(!( !_this || (_this->integrity != CLASS_INTEGRITY) || (_this->appStatus == CLASS_FAILED) || (_this->appStatus == CLASS_STOPPED) || (_this->appStatus == CLASS_CREATED) )); } 4.6. Lifecycle Transition Functions +===================================+===============================+ | Signature | Description | +===================================+===============================+ | AppControlClass_Create(base,name, | Called by INIT_CLASS. Sets | | size,ver,depth) | integrity=CLASS_INTEGRITY, | | | appStatus=CLASS_CREATED. | +-----------------------------------+-------------------------------+ | AppControlClass_Prepare(base) | Transitions to | | | CLASS_PREPARED. Clears | | | history if from | | | CLASS_FAILED. | +-----------------------------------+-------------------------------+ | AppControlClass_Run(base) | Transitions to | | | CLASS_RUNNING from | | | CLASS_PREPARED. | +-----------------------------------+-------------------------------+ | AppControlClass_Stop(base) | Transitions to | | | CLASS_STOPPED from | | | CLASS_RUNNING. | +-----------------------------------+-------------------------------+ | AppControlClass_Fail(base, | Transitions to | | failCode,timestamp) | CLASS_FAILED. Records | | | failCode in history ring | | | buffer. | +-----------------------------------+-------------------------------+ | AppControlClass_Destroy(base) | Terminal: zeroes via | | | setmem. Calls FREE_CLASS | | | if RFC_FLAG_ALLOC_DYNAMIC | | | set. | +-----------------------------------+-------------------------------+ Table 5: AppControlClass transition signatures de Oliveira Expires 25 December 2026 [Page 9] Internet-Draft RFC-OOP-C June 2026 4.7. Size by Build Level +==================+=======+=======+=======+======+=======+ | Field | DEV | TEST | HOM | PROD | Bytes | +==================+=======+=======+=======+======+=======+ | integrity | Y | Y | Y | Y | 4 | +------------------+-------+-------+-------+------+-------+ | appStatus | Y | Y | Y | Y | 4 | +------------------+-------+-------+-------+------+-------+ | flags | Y | Y | Y | Y | 1 | +------------------+-------+-------+-------+------+-------+ | className | Y | Y | Y | N | 4 | +------------------+-------+-------+-------+------+-------+ | classSize | Y | Y | N | N | 2 | +------------------+-------+-------+-------+------+-------+ | classVersion | Y | Y | Y | N | 1 | +------------------+-------+-------+-------+------+-------+ | historyDepth | Y | Y | Y | N | 1 | +------------------+-------+-------+-------+------+-------+ | history[] | Y | Y | Y | N | 96 | +------------------+-------+-------+-------+------+-------+ | hist.Index/Count | Y | Y | Y | N | 2 | +------------------+-------+-------+-------+------+-------+ | TOTAL | ~116B | ~114B | ~110B | 9B | | +------------------+-------+-------+-------+------+-------+ Table 6: AppControlClass per build level 5. Class Macros DECLARE_CLASS and CREATE_CLASS MUST be used in pairs within the same class module. RULE 16: ClassName_VERSION and ClassName_HISTORY_DEPTH MUST be #defined before DECLARE_CLASS in the same .h file. RULE 17: The first #include in Class_X.c MUST be "Class_X.h". de Oliveira Expires 25 December 2026 [Page 10] Internet-Draft RFC-OOP-C June 2026 /* DECLARE_CLASS -- opens struct + declares externs */ #define DECLARE_CLASS(CN) \ extern const char * const \ className_##CN##Class; \ extern const uint16_t \ classSize_##CN##Class; \ extern const uint8_t \ classVersion_##CN##Class; \ extern RFC_ATOMIC uint32_t \ classTimestamp_##CN##Class; \ _Static_assert(CN##Class_VERSION >= 1, \ #CN "_VERSION must be >= 1"); \ _Static_assert(CN##Class_HISTORY_DEPTH >= 1, \ #CN "_HISTORY_DEPTH must be >= 1"); \ typedef struct CN##Class { \ AppControlClass base; /* END_CLASS -- closes struct */ #define END_CLASS(CN) } CN##Class; /* CREATE_CLASS -- defines global symbols */ #define CREATE_CLASS(CN) \ const char * const \ className_##CN##Class = #CN "Class"; \ const uint16_t \ classSize_##CN##Class = SIZEOF(CN##Class); \ const uint8_t \ classVersion_##CN##Class = CN##Class_VERSION;\ RFC_ATOMIC uint32_t \ classTimestamp_##CN##Class = 0; /* INIT_CLASS -- first statement in METHOD_CREATE */ #define INIT_CLASS(CN) \ AppControlClass_Create( \ &_this->base, \ &className_##CN##Class, \ classSize_##CN##Class, \ classVersion_##CN##Class, \ CN##Class_HISTORY_DEPTH) /* setmem -- memset (dest,size,val); needs */ #define setmem(p, n, v) memset((p), (v), (n)) /* SIZEOF -- sizeof with uint16_t cast */ #define SIZEOF(x) ((uint16_t)(sizeof(x))) de Oliveira Expires 25 December 2026 [Page 11] Internet-Draft RFC-OOP-C June 2026 5.1. Global Symbols per Class +=============================+============+=======+==============+ | Symbol | Type |Seg | By | +=============================+============+=======+==============+ | className_CounterClass | const |.rodata| CREATE_CLASS | | | char*const | | | +-----------------------------+------------+-------+--------------+ | classSize_CounterClass | const |.rodata| CREATE_CLASS | | | uint16_t | | | +-----------------------------+------------+-------+--------------+ | classVersion_CounterClass | const |.rodata| CREATE_CLASS | | | uint8_t | | | +-----------------------------+------------+-------+--------------+ | classTimestamp_CounterClass | RFC_ATOMIC |.data | CREATE_CLASS | | | uint32_t | | | +-----------------------------+------------+-------+--------------+ Table 7: Symbols generated by CREATE_CLASS 6. Method Macros DefaultReturn MUST appear only in METHOD, never in DECLARE_METHOD. Rationale: DefaultReturn is consumed entirely by the C preprocessor and does not appear in the function signature; placing it only in the .c METHOD ensures a single point of definition that cannot silently diverge. de Oliveira Expires 25 December 2026 [Page 12] Internet-Draft RFC-OOP-C June 2026 #define DECLARE_METHOD(Ret, CN, Mth, ...) \ Ret CN##Class_##Mth( \ CN##Class * _this __VA_OPT__(,) __VA_ARGS__); #define DECLARE_METHOD_VOID(CN, Mth, ...) \ void CN##Class_##Mth( \ CN##Class * _this __VA_OPT__(,) __VA_ARGS__); #define DECLARE_METHOD_CREATE(CN, ...) \ CN##Class * \ CN##Class_Create##RFC_BUILD_SUFFIX( \ CN##Class * _this __VA_OPT__(,) __VA_ARGS__); #define METHOD(Ret, CN, Mth, Def, ...) \ Ret CN##Class_##Mth( \ CN##Class * _this __VA_OPT__(,) __VA_ARGS__)\ { ASSEST_Ret(_this, (Def)); /* Developer MUST close with: } */ #define METHOD_VOID(CN, Mth, ...) \ void CN##Class_##Mth( \ CN##Class * _this __VA_OPT__(,) __VA_ARGS__)\ { ASSEST_Void(_this); /* Developer MUST close with: } */ #define METHOD_CREATE(CN, ...) \ CN##Class * \ CN##Class_Create##RFC_BUILD_SUFFIX( \ CN##Class * _this __VA_OPT__(,) __VA_ARGS__)\ { ASSEST_Value(_this, NULL); /* Mandatory: INIT_CLASS first; return(_this); } */ 6.1. Build Level Suffix #if RFC_BUILD_LEVEL == RFC_BUILD_DEV #define RFC_BUILD_SUFFIX _DEV #elif RFC_BUILD_LEVEL == RFC_BUILD_TEST #define RFC_BUILD_SUFFIX _TEST #elif RFC_BUILD_LEVEL == RFC_BUILD_HOM #define RFC_BUILD_SUFFIX _HOM #elif RFC_BUILD_LEVEL == RFC_BUILD_PROD #define RFC_BUILD_SUFFIX _PROD #endif de Oliveira Expires 25 December 2026 [Page 13] Internet-Draft RFC-OOP-C June 2026 6.2. Compiler Compatibility +==================+===============+=============+ | Compiler | __VA_OPT__ | Min Version | +==================+===============+=============+ | GCC | YES | >= 8.0 | +------------------+---------------+-------------+ | Clang | YES | >= 6.0 | +------------------+---------------+-------------+ | IAR Embedded | YES | >= 9.x | +------------------+---------------+-------------+ | ARM Compiler 6 | YES | >= 6.14 | +------------------+---------------+-------------+ | Keil MDK (armcc) | NOT SUPPORTED | N/A | +------------------+---------------+-------------+ Table 8: Compiler __VA_OPT__ support 7. Validation Macros de Oliveira Expires 25 December 2026 [Page 14] Internet-Draft RFC-OOP-C June 2026 #ifdef RFC_SINGLE_THREAD #define RFC_ATOMIC /* no overhead */ #else #define RFC_ATOMIC _Atomic /* LDREX/STREX */ #endif /* CLASS_INTEGRITY: 0x55AA|build_level */ #define CLASS_INTEGRITY \ (0x55AA0000UL | (uint32_t)RFC_BUILD_LEVEL) /* DEV=0x55AA0000 PROD=0x55AA0003 */ #define TEST_Class(TC) \ ( !(TC) \ || (TC)->base.integrity \ != CLASS_INTEGRITY \ || !AppControlClass_CheckingRunning(\ &(TC)->base)) #define TEST_ClassType(TC, Cls) \ ( TEST_Class(TC) \ || (TC)->base.className \ != &className_##Cls##Class) #define TEST_Value(v) (!(v)) #define ASSEST_Ret(tc, y) if(TEST_Class(tc)) return(y) #define ASSEST_Void(tc) if(TEST_Class(tc)) return #define ASSEST_RetType(tc,c,y) \ if(TEST_ClassType(tc,c)) return(y) #define ASSEST_VoidType(tc,c) \ if(TEST_ClassType(tc,c)) return #define ASSEST_Value(v,y) if(TEST_Value(v)) return(y) #define ASSEST_ValueVoid(v) if(TEST_Value(v)) return 8. Memory Allocation Macros The flags field (bit 0 = RFC_FLAG_ALLOC_DYNAMIC) tracks heap origin. _Destroy detects this and releases via FREE_CLASS automatically. Common overrides include pvPortMalloc [FREERTOS-MEM] for FreeRTOS [FREERTOS] and OS_Malloc [EMBOS-MEM] for embOS [EMBOS]. RULE 18: MALLOC_CLASS and FREE_CLASS MUST be #defined before #include "RFC_OOP_C.h". de Oliveira Expires 25 December 2026 [Page 15] Internet-Draft RFC-OOP-C June 2026 #ifndef MALLOC_CLASS #define MALLOC_CLASS(n) malloc(n) #endif #ifndef FREE_CLASS #define FREE_CLASS(p) free(p) #endif /* FreeRTOS: MALLOC_CLASS(n) = pvPortMalloc(n) */ /* embOS: MALLOC_CLASS(n) = OS_Malloc(n) */ #define RFC_FLAG_ALLOC_DYNAMIC ((uint8_t)0x01U) #define RFC_IsAllocDynamic(pb) \ (((pb)->flags & RFC_FLAG_ALLOC_DYNAMIC) != 0U) #define RFC_SetAllocDynamic(pb) \ ((pb)->flags |= RFC_FLAG_ALLOC_DYNAMIC) static inline void * RFC_MarkDynamic(void * p) { if (p) RFC_SetAllocDynamic((AppControlClass *)p); return(p); } #define CALL_CREATE(Cls, ...) \ Cls##Class_Create##RFC_BUILD_SUFFIX(__VA_ARGS__) #define CALL_CREATE_ALLOC(Cls, ...) \ ((Cls##Class *) RFC_MarkDynamic( \ Cls##Class_Create##RFC_BUILD_SUFFIX(\ (Cls##Class *) \ MALLOC_CLASS(sizeof(Cls##Class)),\ ##__VA_ARGS__))) extern uint32_t LinuxTimeStamp(void); 8.1. AppControlClass_Destroy void AppControlClass_Destroy(AppControlClass * _this) { uint8_t isDynamic; ASSEST_Void(_this); isDynamic = RFC_IsAllocDynamic(_this); setmem(_this, sizeof(AppControlClass), 0); if (isDynamic) { FREE_CLASS(_this); } } de Oliveira Expires 25 December 2026 [Page 16] Internet-Draft RFC-OOP-C June 2026 9. Build Levels - RFC_BUILD_LEVEL RFC_BUILD_LEVEL MUST be uniform across all modules in the same binary. Mismatches detected at link-time via RFC_BUILD_SUFFIX. #define RFC_BUILD_DEV 0 /* all resources active */ #define RFC_BUILD_TEST 1 /* full diagnostics */ #define RFC_BUILD_HOM 2 /* history active */ #define RFC_BUILD_PROD 3 /* minimum -- 9 bytes */ #ifndef RFC_BUILD_LEVEL #define RFC_BUILD_LEVEL RFC_BUILD_DEV #endif #ifdef RFC_PROJECT_BUILD_LEVEL _Static_assert( RFC_BUILD_LEVEL == RFC_PROJECT_BUILD_LEVEL, "RFC_BUILD_LEVEL inconsistent" ); #endif 10. Formatting and Comments Code documentation MUST follow the Doxygen [DOXYGEN] standard defined in this section. 10.1. Formatting Rules (Rules 1-18) +====+=================+=======+===================================+ | # | Rule | Level | Specification | +====+=================+=======+===================================+ | 1 | Indentation | MUST | 4 spaces. Tabs MUST NOT appear. | +----+-----------------+-------+-----------------------------------+ | 2 | Function brace | MUST | Own line (Allman style). | +----+-----------------+-------+-----------------------------------+ | 6 | Control blocks | MUST | Braces always required. | +----+-----------------+-------+-----------------------------------+ | 8 | Pointer decl | MUST | Type * name (asterisk separated). | +----+-----------------+-------+-----------------------------------+ | 11 | Variable naming | MUST | Semantic prefixes - Section 3.2. | +----+-----------------+-------+-----------------------------------+ | 12 | Separator line | MUST | //--- (80 chars) before /** and | | | | | METHOD. | +----+-----------------+-------+-----------------------------------+ | 13 | CALL_CREATE | MUST | All instantiation via | | | | | CALL_CREATE. | de Oliveira Expires 25 December 2026 [Page 17] Internet-Draft RFC-OOP-C June 2026 +----+-----------------+-------+-----------------------------------+ | 14 | Version incr | MUST | ClassName_VERSION MUST increment | | | | | on layout change. | +----+-----------------+-------+-----------------------------------+ | 16 | #define order | MUST | ClassName_VERSION before | | | | | DECLARE_CLASS. | +----+-----------------+-------+-----------------------------------+ | 17 | First #include | MUST | First #include in Class_X.c is | | | | | Class_X.h. | +----+-----------------+-------+-----------------------------------+ | 18 | Allocator order | MUST | MALLOC/FREE_CLASS before | | | | | RFC_OOP_C.h. | +----+-----------------+-------+-----------------------------------+ Table 9: Mandatory formatting rules 10.2. Doxygen Standard /* Level 1 - File Header */ //-------------------------------------------------------------- /** * @file Class_Counter.c * @brief CounterClass implementation. * @author C. de Oliveira * @date YYYY-MM-DD * @version 2 */ /* Level 2 - Class (before DECLARE_CLASS) */ //-------------------------------------------------------------- /** * @class CounterClass * @brief uint32_t counter with limit detection. * @par Lifecycle * CALL_CREATE -> _Prepare -> _Run -> _Stop */ /* Level 3 - Method (before DECLARE_METHOD) */ //-------------------------------------------------------------- /** * @brief Increments counter by step. * @param[in,out] _this Instance pointer. * @param[in] step Increment (MUST be > 0). * @return Counter value after increment. * @retval 0 Invalid object, step==0, or overflow. */ de Oliveira Expires 25 December 2026 [Page 18] Internet-Draft RFC-OOP-C June 2026 10.3. Special Comments Hardware errata workarounds MUST cite the errata identifier, e.g., [SLAB-ES0435]. // WORKAROUND: Silicon Labs ES0435 Rev3 [SLAB-ES0435] // EUSART returns wrong value on first read after reset. // TODO: TICKET:123 Implement exponential moving average // FIXME: TICKET:456 Race condition with two ADCs 11. Struct Versioning Every class MUST define ClassName_VERSION. Implementations MUST verify classVersion before deserializing any stored object. if (versionOnDisk != CLASS_VERSION(Counter)) { AppControlClass_Fail(&_this->base, CounterClass_FAIL_VERSION_MISMATCH, CLASS_TIMESTAMP(Counter)); return(NULL); } Storage_Read(ADDR, &counter, CLASS_SIZE(Counter)); 12. RFC_Checker - Automatic Verification 12.1. Command-Line Interface rfc_checker {options} [] rfc_checker {options} --dir Options: --level --rules <1,2,...|all> --output --strict Exit codes: 0=ok 1=violations 2=error de Oliveira Expires 25 December 2026 [Page 19] Internet-Draft RFC-OOP-C June 2026 12.2. Automatic Verifications +===============================+=========+ | Verification | Rule | +===============================+=========+ | Semantic prefixes | Rule 11 | +-------------------------------+---------+ | for-loop form | Rule 11 | +-------------------------------+---------+ | 4 spaces, no tabs | Rule 1 | +-------------------------------+---------+ | Braces in control blocks | Rule 6 | +-------------------------------+---------+ | //--- before /** | Rule 12 | +-------------------------------+---------+ | METHOD_CREATE for _Create | Sec. 6 | +-------------------------------+---------+ | CALL_CREATE usage | Rule 13 | +-------------------------------+---------+ | @file exact filename | Sec. 10 | +-------------------------------+---------+ | @retval in DECLARE_METHOD | Sec. 10 | +-------------------------------+---------+ | _VERSION before DECLARE_CLASS | Rule 16 | +-------------------------------+---------+ | Class_X.h first #include | Rule 17 | +-------------------------------+---------+ Table 10: RFC_Checker automatic verifications 12.3. JSON Output Schema When --output json specified, RFC_Checker MUST produce valid JSON. Severity MUST be "error" for MUST violations and "warning" for SHOULD violations. de Oliveira Expires 25 December 2026 [Page 20] Internet-Draft RFC-OOP-C June 2026 { "rfc_build_level": "DEV", "files_checked": 2, "violations": [ { "file": "Class_Counter.c", "line": 42, "rule": "RULE-11", "severity": "error", "message": "variable i -- use semantic prefix" } ], "summary": { "errors": 1, "warnings": 0 } } 13. Legacy Migration Three phases: (1) Coexistence - RFC and legacy coexist, new modules in RFC; (2) Migration - convert one module at a time; (3) Conformance - full project passes RFC_Checker. Five steps per module: 1. Rename: adcControl.c to Class_AdcControl.c 2. Add Doxygen header and #include "RFC_OOP_C.h" 3. Wrap struct: DECLARE_CLASS / END_CLASS 4. Convert functions: METHOD / METHOD_VOID / METHOD_CREATE 5. Replace instantiations: CALL_CREATE in callers 14. Security Considerations 14.1. CLASS_INTEGRITY as Structural Control Value CLASS_INTEGRITY is a structural Control Value: 0x55AA upper word for bit-flip detection, lower byte encodes RFC_BUILD_LEVEL. CLASS_INTEGRITY MUST NOT be relied upon as a security boundary in adversarial environments. 14.2. RFC_ATOMIC on Processors Without Atomic Instructions On processors lacking hardware atomic instructions (ARM Cortex-M0/M0+ per [CORTEXM33] and [AAPCS]), C11 _Atomic disables global interrupts, which MAY introduce non-deterministic latency. Systems with hard real-time requirements SHOULD define RFC_SINGLE_THREAD. de Oliveira Expires 25 December 2026 [Page 21] Internet-Draft RFC-OOP-C June 2026 14.3. Dynamic Allocation and Heap Exhaustion CALL_CREATE_ALLOC result MUST always be checked against NULL. Safety-critical implementations SHOULD prefer static allocation via CALL_CREATE. 14.4. Version Mismatch and Memory Safety Implementations MUST verify classVersion before deserializing any stored object per Section 11. Failure produces undefined behavior that may be exploitable. 14.5. use-after-free via _Destroy After _Destroy on a heap-allocated object, the caller MUST set the pointer to NULL immediately. 14.6. Atomic Ordering Invariant integrity MUST be written before appStatus in _Create and zeroed before appStatus in _Destroy. 14.7. classTimestamp Thread Safety classTimestamp is RFC_ATOMIC but its update via LinuxTimeStamp() is not atomic with respect to the event it timestamps. This MUST NOT be relied upon for security-relevant timestamping. 15. IANA Considerations This document has no IANA actions. 16. Conformance Checklist MUST be applied before submitting any module. [RFC_Checker] items are verified automatically. File .h: * Filename: Class_[ClassName].h * VERSION and HISTORY_DEPTH before DECLARE_CLASS [RFC_Checker] * _Create: DECLARE_METHOD_CREATE [RFC_Checker] * @retval documents DefaultReturn [RFC_Checker] File .c: de Oliveira Expires 25 December 2026 [Page 22] Internet-Draft RFC-OOP-C June 2026 * First #include is "Class_X.h" [RFC_Checker] * INIT_CLASS is first statement in METHOD_CREATE * _Destroy zeroes struct via setmem Validation: * All instantiation via CALL_CREATE / CALL_CREATE_ALLOC [RFC_Checker] * CALL_CREATE_ALLOC result checked against NULL * Pointer set to NULL after _Destroy (heap objects) * classVersion verified before deserializing * RFC_Checker passes with zero violations 17. Complete Macro Reference +===============================+===========+======================+ |Macro |File |Purpose | +===============================+===========+======================+ |DECLARE_CLASS(CN) |.h |Opens struct + externs| | | |+ _Static_assert | +-------------------------------+-----------+----------------------+ |END_CLASS(CN) |.h |Closes struct | +-------------------------------+-----------+----------------------+ |CREATE_CLASS(CN) |.c |Defines global class | | | |symbols | +-------------------------------+-----------+----------------------+ |INIT_CLASS(CN) |body |Mandatory | | | |initialization | +-------------------------------+-----------+----------------------+ |setmem(p,n,v) |RFC_OOP_C.h|memset (dest,size,val)| +-------------------------------+-----------+----------------------+ |SIZEOF(x) |any |sizeof with uint16_t | | | |cast | +-------------------------------+-----------+----------------------+ |DECLARE_METHOD(Ret,CN,Mth,...) |.h |Prototype with return | +-------------------------------+-----------+----------------------+ |DECLARE_METHOD_VOID(CN,Mth,...)|.h |Void prototype | +-------------------------------+-----------+----------------------+ |DECLARE_METHOD_CREATE(CN,...) |.h |_Create with build | | | |suffix | +-------------------------------+-----------+----------------------+ |METHOD(Ret,CN,Mth,Def,...) |.c |Implementation + | de Oliveira Expires 25 December 2026 [Page 23] Internet-Draft RFC-OOP-C June 2026 | | |ASSEST_Ret | +-------------------------------+-----------+----------------------+ |METHOD_VOID(CN,Mth,...) |.c |Void + ASSEST_Void | +-------------------------------+-----------+----------------------+ |METHOD_CREATE(CN,...) |.c |_Create + ASSEST_Value| +-------------------------------+-----------+----------------------+ |RFC_ATOMIC |RFC_OOP_C.h|_Atomic or empty | +-------------------------------+-----------+----------------------+ |CLASS_INTEGRITY |RFC_OOP_C.h|Control value: | | | |0x55AA|build | +-------------------------------+-----------+----------------------+ |TEST_Class(TC) |any |Tests integrity + | | | |status | +-------------------------------+-----------+----------------------+ |TEST_ClassType(TC,Cls) |any |Tests specific type | +-------------------------------+-----------+----------------------+ |TEST_Value(v) |any |Tests NULL or zero | +-------------------------------+-----------+----------------------+ |ASSEST_Ret/Void |method |Object validation | +-------------------------------+-----------+----------------------+ |ASSEST_RetType/VoidType |method |Type-specific | | | |validation | +-------------------------------+-----------+----------------------+ |ASSEST_Value/ValueVoid |method |Argument validation | +-------------------------------+-----------+----------------------+ |MALLOC_CLASS(n) |RFC_OOP_C.h|Isolates allocator | +-------------------------------+-----------+----------------------+ |FREE_CLASS(p) |RFC_OOP_C.h|Isolates deallocator | +-------------------------------+-----------+----------------------+ |RFC_FLAG_ALLOC_DYNAMIC |RFC_OOP_C.h|Bit 0 of flags | +-------------------------------+-----------+----------------------+ |RFC_IsAllocDynamic(pb) |RFC_OOP_C.h|Tests bit 0 | +-------------------------------+-----------+----------------------+ |RFC_SetAllocDynamic(pb) |RFC_OOP_C.h|Sets bit 0 | +-------------------------------+-----------+----------------------+ |RFC_MarkDynamic(p) |RFC_OOP_C.h|Sets flag + returns | | | |ptr | +-------------------------------+-----------+----------------------+ |CALL_CREATE(Cls,...) |caller |Static allocation | +-------------------------------+-----------+----------------------+ |CALL_CREATE_ALLOC(Cls,...) |caller |Heap + | | | |RFC_FLAG_ALLOC_DYNAMIC| +-------------------------------+-----------+----------------------+ |RFC_BUILD_SUFFIX |internal |_DEV/_TEST/_HOM/_PROD | +-------------------------------+-----------+----------------------+ |LinuxTimeStamp() |project |extern uint32_t, ms | | | |since epoch | +-------------------------------+-----------+----------------------+ de Oliveira Expires 25 December 2026 [Page 24] Internet-Draft RFC-OOP-C June 2026 |RFC_SINGLE_THREAD |project |Disables RFC_ATOMIC | +-------------------------------+-----------+----------------------+ |RFC_PROJECT_BUILD_LEVEL |Makefile |_Static_assert on | | | |mismatch | +-------------------------------+-----------+----------------------+ Table 11: All RFC-OOP-C macros 18. References 18.1. Normative References [BCP14] IETF, "Best Current Practice 14", BCP 14, . [C11] ISO/IEC, "Programming Languages - C", ISO/IEC 9899:2011, December 2011. [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, May 2017, . 18.2. Informative References [AAPCS] ARM Limited, "Procedure Call Standard for the ARM Architecture", ARM IHI0042J, 2020. [CORTEXM33] ARM Limited, "Cortex-M33 Technical Reference Manual", ARM DDI 0553B, 2018. [DOXYGEN] van Heesch, D., "Doxygen Manual", https://www.doxygen.nl/manual/. [EMBOS] SEGGER Microcontroller, "embOS Real-Time Operating System Reference Guide", https://www.segger.com/products/rtos/embos/. [EMBOS-MEM] SEGGER Microcontroller, "embOS Memory Pools and OS_Malloc / OS_Free API", https://www.segger.com/products/rtos/embos/documentation/. de Oliveira Expires 25 December 2026 [Page 25] Internet-Draft RFC-OOP-C June 2026 [FREERTOS] Real Time Engineers Ltd., "FreeRTOS Reference Manual", https://www.freertos.org/Documentation. [FREERTOS-MEM] Real Time Engineers Ltd., "FreeRTOS Memory Management - pvPortMalloc and vPortFree", https://www.freertos.org/a00111.html. [RFC7322] Flanagan, H. and S. Ginoza, "RFC Style Guide", RFC 7322, September 2014, . [SLAB-ES0435] Silicon Labs, "EFM32PG28 Errata ES0435 Rev3", https://www.silabs.com/documents/public/errata/. Author's Address Celso de Oliveira ImCode - Imagine Coding Laboratories Email: celso.olvra@gmail.com de Oliveira Expires 25 December 2026 [Page 26]