M2C Identifier Conversion (v.3.3, 2016-3-26) (1) Output Styles ----------------- M2C provides two user selectable output styles: * Verbatim output * C Style output In verbatim mode, identifiers from the Modula-2 source are used verbatim in the output. However, module qualifiers are prepended to public identifiers and scope indicators are appended to local identifiers except for local variables. In C style mode, identifiers from the Modula-2 source are transformed to match common C conventions in order to make the output appear more natural. The most natural looking output is achieved when the input source closely follows the recommended naming convention for Modula-2 sources. C style mode is unavailable when the use of lowline in identifiers is enabled. (2) Recommended Naming Convention For Modula-2 Sources ------------------------------------------------------ (2.1) Module identifiers * shall always start with a capital letter * user defined libraries shall use title-case (2.2) Type identifiers * shall always start with a capital letter * user defined libraries shall use title-case (2.3) Variable, constant, procedure and function identifiers * shall always start with a lowercase letter * user defined libraries shall use all-lowercase or camel-case (2.4) For the most natural appearance of C output in C style mode * identifiers should use camel-case or title-case as recommended * constant identifiers that end in a capital H should be avoided * variable/function identifiers that end in a capital T should be avoided * C reserved words and main should not be used as local variables * Private and Local should not be used as module identifiers Care should be taken to ensure that the resulting length of synthesised output identifiers will not exceed the significant character limit of the underlying C compiler. C99 only requires a minimum of 32 significant characters. * resulting length for public identifiers length = module identifier length + identifier length + 2 * resulting length for private identifiers length = identifier length + 9 * resulting length for local identifiers (except local variables) length = surrounding function identifier length + identifier length + 9 * resulting length for local variable identifiers length = identifier length In C style mode, each capital letter increases identifier length by 1. NB: The Modula-2 standard library may export all-uppercase identifiers or camel-case and title-case identifiers that contain all-uppercase acronyms. (3) Scopes ---------- There are three scopes: (3.1) public scope * any identifier declared within a definition part has public scope * public scope identifiers are qualified with a public scope qualifier * all public scope identifiers have storage class extern (3.2) private scope * any global identifier not declared in a definition part has private scope * private scope identifiers are qualified with a private scope qualifier * all private scope identifiers have storage class static (3.3) local scope * any non-global identifier has local scope * local variable identifiers are never qualified * other local scope identifiers are qualified with a local scope qualifier * local variable identifiers have storage class auto * other local scope identifiers have storage class static (4) Qualifiers -------------- (4.1) public scope qualifiers Since C does not support qualified naming, a public scope qualifier is prepended to all identifiers defined with public scope. The public scope qualifier is composed of the module identifier of the module in which the identifier is defined within the Modula-2 source, then followed by two lowlines. (4.2) private qualifier Since C does not support qualified naming, a universal private scope qualifier is prepended to all identifiers defined with private scope. The private scope qualifier is composed of the word private (C style output) or Private (Verbatim output) followed by two lowlines. (4.3) local qualifier Since C only supports local variables, but not local types, local constants and local functions, a scope qualifier is prepended to constant, type and function identifiers defined with local scope. The local scope qualifier is composed of the world local (C style output) or Local (Verbatim outut) followed by the function identifier of the function in which the local identifier is defined, followed by two lowlines. If the length of the resulting qualified identifier would exceed the limit of significant characters of the underlying C compiler, the identifier of the surrounding function within the scope qualifier is replaced with its ordinal. Ordinal numbers are assigned to functions on a per file basis, but only to functions in which any local constant, type or function is defined within the Modula-2 source. The ordinal number is base-16 encoded and its first digit is always decimal. (5) Collision Prevention ------------------------ The Modula-2 to C name translation rules are designed not to produce conflicts as long as the Modula-2 source follows the recommended naming convention. When the recommended naming convention is not followed, name conflicts may or will occur, depending on output mode. There are five possible name collision scenarios. (5.1) Identifier recommended to be in title-case starts with lowercase letter (5.2) Identifier recommended to be in camel-case starts with capital letter (5.3) Constant identifier ends in capital letter H (5.4) Variable or function identifier ends in capital letter T (5.5) Module identifier matches private, local or builtin qualifier. (5.6) Parameter or variable identifier matches a C reserved word In C style output mode all scenarios may lead to a collision. In verbatim output mode, scenarios 5.1 to 5.4 will never lead to a collision but scenarios 5.5 and 5.6 will always lead to a collision. To prevent collisions, identifiers are transformed depending on collision scenario and selected output mode. In C style output mode, a designated output identifier that may cause a collision under scenarios 5.1 or 5.2 will be prefixed to prevent any possibility of a collision. If the identifier is lowercase, prefix X_ is prepended. If it is uppercase, prefix x_ is prepended. Examples: MODULE foobar => FOOBAR_H => x_FOOBAR_H PROCEDURE Foobar => foobar => X_foobar Also in C style output mode, a designated output identifier that may cause a collision under scenarios 5.3 or 5.4 will be suffixed with a lowline to rule out any possibility of a collision. Examples: CONST foobarH => FOOBAR_H => FOOBAR_H_ PROCEDURE fooBarT => foobar_t => foobar_t_ Regardless of output mode, a module identifier that leads to a designated output qualifier that matches a private, local or builtin qualifier will be treated as if it was substituted by MOD, followed by two lowlines followed by the ASCII codes of the first two characters of the actual module identifier. Examples: (* Verbatim mode *) MODULE Private; VAR foo; => MOD__5272__foo (* C Style mode *) MODULE Private; VAR foo; => m_o_d__5272__foo Regardless of output mode, a designated output identifier that matches a reserved word of the C language and thereby causes a collision under scenario 5.6 will be suffixed with a lowline to prevent the collision. Example: VAR switch => switch => switch_ (6) Transformation Rules for Verbatim Mode ------------------------------------------ (6.1) C Include guards * generated from module identifiers * prefixed with MODULE__ * suffixed with __H includeGuard := 'MODULE__' moduleIdent '__H' ; moduleIdent := verbatim copy from Modula-2 source ; Example: MODULE FooBar => MODULE__FooBar__H (6.2) Module qualifier for public identifiers * generated from module identifiers * suffixed with __ moduleQualifier := moduleIdent '__' ; moduleIdent := verbatim copy from Modula-2 source ; Example: MODULE FooBar => FooBar__ (6.3) Public type, constant, variable and function identifiers * generated from source identifier * prefixed with module qualifier publicIdent := moduleQualifier sourceIdent ; sourceIdent := verbatim copy from Modula-2 source ; Example: MODULE FooBar; VAR bazBam; => FooBar__bazBam (6.4) Private type, constant, variable and function identifiers * generated from source identifier * prefixed with private qualifier privateIdent := privateQualifier sourceIdent ; privateQualifier := 'Private__' ; sourceIdent := verbatim copy from Modula-2 source ; Example: TYPE FooBar => Private__FooBar (6.5) Local type, constant, variable and function identifiers (a) Local variable identifiers * copied from source identifier localVarIdent := verbatim copy from Modula-2 source ; Example: VAR localVar => localVar (b) Local type, constant and function identifiers * generated from source identifier * prefixed with local qualifier localTypeConstFuncIdent := localQualifier enclosingFunctionQualifier sourceIdent ; localQualifier := 'Local__' ; enclosingFunctionQualifier := ( functionIdent | functionOrdinal ) '__' ; functionIdent := verbatim copy from Modula-2 source ; functionOrdinal := Base10Digit Base16Digit* ; sourceIdent := verbatim copy from Modula-2 source ; Example: PROCEDURE Outer; PROCEDURE Inner; => Local__Outer__Inner (7) Transformation Rules for C Style Mode ----------------------------------------- Lowercase/lowline transformation * capital letters are prepended with lowline, except first character * all capital letters are transformed to lowercase * lowercase letters and digits are copied verbatim Uppercase/lowline transformation * capital letters are prepended with lowline, except first character * lowercase letters are transformed to uppercase * digits are copied verbatim (7.1) C Include guards * generated from module identifiers * transformed to uppercase/lowline * suffixed with _H includeGuard := upperModuleIdent '_H' ; upperModuleIdent := uppercase/lowline transformation of module identifier from Modula-2 source ; Example: MODULE FooBar => FOO_BAR_H (7.2) Module qualifier for public identifiers * generated from module identifiers * transformed to lowercase/lowline * suffixed with __ moduleQualifier := lowerModuleIdent '__' ; lowerModuleIdent := lowercase/lowline transformation of module identifier from Modula-2 source ; Example: MODULE FooBar => foo_bar__ (7.3) Public type, constant, variable and function identifiers (a) Public type identifiers * generated from source identifier * prefixed with module qualifier * transformed to lowercase/lowline * suffixed with _t publicTypeIdent := moduleQualifier lowerSourceIdent '_t' ; lowerSourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: MODULE FooBar; TYPE BazBam; => foo_bar__baz_bam_t (b) Public constant identifiers * generated from source identifier * prefixed with module qualifier * transformed to uppercase/lowline publicIdent := moduleQualifier upperSourceIdent ; upperSourceIdent := uppercase/lowline transformation of identifier from Modula-2 source ; Example: MODULE FooBar; CONST bazBam; => FOO_BAR__BAZ_BAM (c) Public variable and function identifiers * generated from source identifier * prefixed with module qualifier * transformed to lowercase/lowline publicIdent := moduleQualifier lowerSourceIdent ; lowerSourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: DEFINITION MODULE FooBar; VAR bazBam; => foo_bar__baz_bam (7.4) Private type, constant, variable and function identifiers (a) Private type identifiers * generated from source identifier * prefixed with private qualifier * transformed to lowercase/lowline * suffixed with _t privateTypeIdent := lowerPrivateQualifier lowerSourceIdent '_t' ; lowerPrivateQualifier := 'private__' ; lowerSourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: IMPLEMENTATION MODULE ...; TYPE FooBar => private__foo_bar_t (b) Private constant identifiers * generated from source identifier * prefixed with uppercase private qualifier * transformed to uppercase/lowline privateConsIdent := upperPrivateQualifier upperSourceIdent ; upperPrivateQualifier := 'PRIVATE__' ; upperSourceIdent := uppercase/lowline transformation of identifier from Modula-2 source ; Example: IMPLEMENTATION MODULE ...; CONST fooBar => PRIVATE__FOO_BAR (c) Private variable identifiers * generated from source identifier * transformed to lowercase/lowline privateIdent := lowerSourceIdent ; lowerSourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: VAR fooBar => foo_bar (d) Private function identifiers * generated from source identifier * prefixed with private qualifier * transformed to lowercase/lowline privateFunctionIdent := lowerPrivateQualifier lowerSourceIdent ; lowerPrivateQualifier := 'private__' ; lowerSourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: IMPLEMENTATION MODULE ...; PROCEDURE fooBar => private__foo_bar (7.5) Local type, constant, variable and function identifiers (a) Local type identifiers * generated from source identifier * prefixed with local qualifier * transformed to lowercase/lowline * suffixed with _t localTypeIdent := lowerLocalQualifier lowerEnclosingFunctionQualifier sourceIdent '_t' ; lowerEnclosingFunctionQualifier := ( functionIdent | functionOrdinal ) '__' ; functionIdent := lowercase/lowline transformation of enclosing function identifier ; functionOrdinal := Base10Digit Base16Digit* ; sourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: PROCEDURE Outer; TYPE FooBar; => local__outer__foo_bar_t (b) Local constant identifiers * generated from source identifier * prefixed with uppercase local qualifier * transformed to uppercase/lowline localConstIdent := upperLocalQualifier upperEnclosingFunctionQualifier sourceIdent ; upperEnclosingFunctionQualifier := ( functionIdent | functionOrdinal ) '__' ; functionIdent := uppercase/lowline transformation of enclosing function identifier ; functionOrdinal := Base10Digit Base16Digit* ; sourceIdent := uppercase/lowline transformation of identifier from Modula-2 source ; Example: PROCEDURE Outer; CONST fooConst; => LOCAL__OUTER__FOO_CONST (c) Local variable identifiers * copied from source identifier localVarIdent := verbatim copy from Modula-2 source ; Example: VAR localVar => local_var (d) Local function identifiers * generated from source identifier * prefixed with local qualifier * transformed to lowercase/lowline localFunctionIdent := lowerLocalQualifier lowerEnclosingFunctionQualifier sourceIdent ; lowerEnclosingFunctionQualifier := ( functionIdent | functionOrdinal ) '__' ; functionIdent := lowercase/lowline transformation of enclosing function identifier ; functionOrdinal := Base10Digit Base16Digit* ; sourceIdent := lowercase/lowline transformation of identifier from Modula-2 source ; Example: PROCEDURE Outer; PROCEDURE Inner; => local__outer__inner (8) Conversion Scenarios ------------------------ (8.1) C include guards (a) Verbatim output foolib => MODULE__foolib__H fooLib => MODULE__fooLib__H fooLIB => MODULE__fooLIB__H FooLib => MODULE__FooLib__H FooLIB => MODULE__FooLIB__H FOOLIB => MODULE__FOOLIB__H (a) C style output foolib => x_FOOLIB_H fooLib => x_FOO_LIB_H fooLIB => x_FOO_L_I_B_H FooLib => FOO_LIB_H FooLIB => FOO_L_I_B_H FOOLIB => F_O_O_L_I_B_H (8.2) Public qualifier prefixes (a) Verbatim output foolib => foolib__ fooLib => fooLib__ fooLIB => fooLIB__ FooLib => FooLib__ FooLIB => FooLIB__ FOOLIB => FOOLIB__ (b) C style output foolib => X_foolib__ fooLib => X_foo_lib__ fooLIB => X_foo_l_i_b__ FooLib => foo_lib__ FooLIB => foo_l_i_b__ FOOLIB => f_o_o_l_i_b__ (8.3) Private qualifier prefixes (a) Verbatim output Private__ (b) C style output private__ (8.4) Local qualifier prefixes (a) Verbatim output fooproc => Local__fooproc__ fooProc => Local__fooProc__ fooPROC => Local__fooPROC__ FooProc => Local__FooProc__ FooPROC => Local__FooPROC__ FOOPROC => Local__FOOPROC__ (b) C style output fooproc => local__fooproc__ fooProc => local__foo_proc__ fooPROC => local__foo_p_r_o_c__ FooProc => local__X_foo_proc__ FooPROC => local__X_foo_p_r_o_c__ FOOPROC => local__X_f_o_o_p_r_o_c__ (8.5) Constant identifiers (a) Verbatim output foobar => foobar fooBar => fooBar fooBAR => fooBAR FooBar => FooBar FooBAR => FooBAR FOOBAR => FOOBAR (b) C style output foobar => FOOBAR fooBar => FOO_BAR fooBAR => FOO_B_A_R FooBar => x_FOO_BAR FooBAR => x_FOO_B_A_R FOOBAR => x_F_O_O_B_A_R (8.6) Type identifiers (a) Verbatim output foobar => foobar fooBar => fooBar fooBAR => fooBAR FooBar => FooBar FooBAR => FooBAR FOOBAR => FOOBAR (b) C style output foobar => X_foobar_t fooBar => X_foo_bar_t fooBAR => X_foo_b_a_r_t FooBar => foo_bar_t FooBAR => foo_b_a_r_t FOOBAR => f_o_o_b_a_r_t (8.7) Variable and function identifiers (a) Verbatim output foobar => foobar fooBar => fooBar fooBAR => fooBAR FooBar => FooBar FooBAR => FooBAR FOOBAR => FOOBAR (b) C style output foobar => foobar fooBar => foo_bar fooBAR => foo_b_a_r FooBar => X_foo_bar FooBAR => X_foo_b_a_r FOOBAR => X_f_o_o_b_a_r (9) Conversion of built-in identifiers --------------------------------------- [V] indicates verbatim output mode [C] indicates a C style output mode (9.1) Built-in constant identifiers * NIL [V], [C] : NULL * TRUE [V], [C] : true * FALSE [V], [C] : false (9.2) Built-in type identifiers * OCTET [V], [C] : uint8_t * CHAR [V], [C] : unsigned char * BOOLEAN [V], [C] : bool * CARDINAL [V], [C] : unsigned * INTEGER [V], [C] : int * SHORTCARD [V], [C] : unsigned short * SHORTINT [V], [C] : short * LONGCARD [V], [C] : unsigned long * LONGINT [V], [C] : long int * REAL [V], [C] : float * LONGREAL [V], [C] : double (9.3) Built-in procedure identifiers * FOO [V] : BUILTIN__FOO [C] : builtin__foo (9.4) SYSTEM and UNSAFE identifiers * WORD [V], [C] : uint8_t * ADDRESS [V], [C] : (void *) * SYSTEM.FOO [V] : SYSTEM__FOO [C] : system__foo * UNSAFE.FOO [V] : UNSAFE__FOO [C] : unsafe__foo END OF FILE