Mixing "C" and BCX Code

! Inline "C" Code operator

Purpose: BCX allows you pass inline "C" code using the exclamation mark (!) as an operator.

 Syntax: ``` ! /* "C" statement goes here */ ```

Remarks: When ! is used outside of a BCX FUNCTION or SUB procedure, the emitted "C" code is located in the main function of the "C" translation.

Example: The following sample shows how to create a "C" coded local DWORD variable.

```
PRINT GetMachineName\$()

FUNCTION GetMachineName\$
LOCAL A\$
! DWORD b; /* allocate a local variable in "C" and include "C" comments! */
b = 256
GetComputerName(A\$, &b) ' the & operator means "PASS THE ADDRESS" of b
FUNCTION = A\$
END FUNCTION

```

\$CCODE directive

Purpose: BCX allows you pass inline "C" code using a \$CCODE directive placed before and after the "C" code.

 Syntax 1: ``` \$CCODE /* "C" statements go here */ \$CCODE ```

Remarks: When \$CCODE ... \$CCODE is used without an optional parameter or if it is outside of a BCX FUNCTION or SUB procedure, the emitted "C" code is located in the main function of the "C" translation..

Example:

```
PRINT "BCX Code Here."

\$CCODE

// declare the variables:
int nNumber;
int *pPointer;

// now, give a value to them:
nNumber = 15;
pPointer = &nNumber;

// print out the value of nNumber:
printf("nNumber is equal to : %d\n", nNumber);

// now, alter nNumber through pPointer:
*pPointer = 25;

// prove that nNumber has changed as a result of the above
// by printing its value again:
printf("nNumber is equal to : %d\n", nNumber);

\$CCODE

PRINT "BCX Code Here."

```

Result:

```
BCX Code Here.
nNumber is equal to : 15
nNumber is equal to : 25
BCX Code Here.

```
 Syntax 2: ``` \$CCODE HEADER /* "C" statements go here */ \$CCODE ``` Parameters: HEADER [OPTIONAL] When the \$CCODE HEADER directive is used, everything sandwiched between the \$CCODE HEADER and the terminating \$CCODE statements is placed at the file scope level of the emitted "C" source in the 'User Defined Constants' section. \$CCODE HEADER is useful, particularly, for inlined "C" source pragma statements.

Example:

```

#if VERSION == 1
#define INCFILE "vers1.h"
#elif VERSION == 2
#define INCFILE "vers2.h" // and so on
#else
#define INCFILE "versN.h"
#endif
#include INCFILE

\$CCODE

```
 Syntax 3: ``` \$CCODE ENUM /* "C" statements go here */ \$CCODE ``` Parameters: ENUM [OPTIONAL] When the \$CCODE ENUM directive is used, everything sandwiched between the \$CCODE ENUM and the terminating \$CCODE statements is placed at the file scope level of the emitted "C" source in the 'User's GLOBAL Enumerations' section.

Example:

```
\$CCODE ENUM

enum a{a=100,b,c,d=200,e,f};

\$CCODE

PRINT a, b, c, d, e, f

```

Result:

```
100 101 102 200 201 202

```
 Syntax 4: ``` \$CCODE CONST /* "C" statements go here */ \$CCODE ``` Parameters: CONST [OPTIONAL] When the \$CCODE CONST directive is used, everything sandwiched between the \$CCODE CONST and the terminating \$CCODE statements is placed at the file scope level of the emitted "C" source in the 'User Defined Constants' section.
 Syntax 5: ``` \$CCODE UDT /* "C" statements go here */ \$CCODE ``` Parameters: UDT [OPTIONAL] When the \$CCODE UDT directive is used, everything sandwiched between the \$CCODE UDT and the terminating \$CCODE statements is placed at the file scope level of the emitted "C" source in the 'User Defined Types And Unions' section.

Example:

For \$CCODE CONST and \$CCODE UDT.

```
\$CCODE CONST

#define QWERTY_CLASS struct _QWERTY*

\$CCODE

\$CCODE UDT

typedef struct _QWERTY
{
int   a;
float b;
char  c[80];
}
QWERTY, *LPQWERTY;

\$CCODE

GLOBAL MyType [10,10,10] AS QWERTY

MyType [2,3,4].a  =  1
MyType [2,3,4].b! =  2.345
MyType [2,3,4].c\$ = "hello world from a poly-dimensional udt!"

PRINT        MyType[2,3,4].a
PRINT        MyType[2,3,4].b!
PRINT UCASE\$(MyType[2,3,4].c\$)

```

Result:

```
1
2.345
HELLO WORLD FROM A POLY-DIMENSIONAL UDT!

```
 Syntax 6: ``` \$CCODE SET /* "C" statements go here */ \$CCODE ``` Parameters: SET [OPTIONAL] When the \$CCODE SET directive is used, everything sandwiched between the \$CCODE SET and the terminating \$CCODE statements is placed at the file scope level of the emitted "C" source in the 'User's GLOBAL SET Statements' section.

Example:

```
TYPE foo
A AS INTEGER
B AS INTEGER
C AS BYTE
END TYPE

\$CCODE SET

static foo MyFoo[]=
{
{12,13},
{19,20}
};

\$CCODE

? MyFoo[0].A
? MyFoo[0].B
? MyFoo[0].C
? MyFoo[1].A
? MyFoo[1].B
? MyFoo[1].C

```

Result:

```
12
13
0
19
20
0

```
 Syntax 7: ``` \$CCODE FUNCSUB /* "C" statements go here */ \$CCODE ``` Parameters: FUNCSUB [OPTIONAL] When the \$CCODE FUNCSUB directive is used, everything sandwiched between the \$CCODE FUNCSUB and the terminating \$CCODE statements is placed at the file scope level of the emitted "C" source in the 'User's C code' section.

Remarks: \$CCODE FUNCSUB is used to enclose a complete "C" code procedure. A prototype is not needed in this case because the placement in the emitted "C" source is before the main procedure.

Example:

```
DIM a\$
DIM b\$

a\$ = "     this   is    a     test      "

b\$ = Remove_All_White_Space(a\$)

PRINT b\$

END PROGRAM

\$CCODE FUNCSUB

char* Remove_All_White_Space(char* str1)
{
char *obuf,*nbuf;
if (str1)
{
for (obuf=str1,nbuf=str1;*obuf;
++obuf)
{
if (!isspace(*obuf))
*nbuf++=*obuf;
}
*nbuf=0;
}
return str1;
}

\$CCODE

```

Remarks: The top to bottom order of placement of the "C" code translated from the \$CCODE directives is

2. \$CCODE ENUM
3. \$CCODE CONST
4. \$CCODE UDT
5. \$CCODE SET
6. \$CCODE FUNCSUB

Purpose: The \$HEADER directive works like \$CCODE except everything sandwiched between two \$HEADER statements is placed at the file scope level of the emitted "C" source. \$HEADER is useful particularly for pragma statements and declaring prototypes for inlined "C" source functions. A \$HEADER directive is placed before and after the "C" code.

 Syntax: ``` \$HEADER /* "C" statements go here */ \$HEADER ```

Example:

```

#define KitchenSinkIsIncluded

#ifndef KitchenSinkIsIncluded
#include <KitchenSink.h>
#else
#define CallThePlumber 1
#endif

```

\$CPROTO directive

Purpose: The \$CPROTO directive is used for declaring prototypes for inlined "C" source functions.

 Syntax 1: ``` \$CPROTO ! ProcedureDataType ProcedureName(ParameterDataType); ```

Remarks: When using \$CPROTO with a "C" language prototype, a space-exclamation mark-space must precede the prototype. Also remember, that in "C", a semicolon is required at the end of of the prototype.

Everything following the \$CPROTO ! is placed at the file scope level of the emitted "C" source in the 'User's Prototypes' section.

Example:

```
\$CPROTO ! char* Remove_All_White_Space(char*);

DIM a\$
DIM b\$

a\$ = "     this   is    a     test      "

b\$ = Remove_All_White_Space(a\$)

PRINT b\$

END PROGRAM

\$CCODE
char* Remove_All_White_Space(char* str1)
{
char *obuf,*nbuf;
if (str1)
{
for (obuf=str1,nbuf=str1;*obuf;
++obuf)
{
if (!isspace(*obuf))
*nbuf++=*obuf;
}
*nbuf=0;
}
return str1;
}
\$CCODE

```
 Syntax 2: ``` \$CPROTO [FUNCTION/SUB] Foo\$(a%, b\$) ```

Remarks: \$CPROTO, also, will accept a BCX FUNCTION or SUB declaration which will be translated to "C" code and placed correctly in the 'User Prototypes' section of the "C" translation.

Example:

```
\$CPROTO FUNCTION Remove_All_White_Space\$(a\$)

DIM a\$
DIM b\$

a\$ = "     this   is    a     test      "

b\$ = Remove_All_White_Space(a\$)

PRINT b\$

END PROGRAM

! char* Remove_All_White_Space(char* str1)
!  {
!   char *obuf,*nbuf;
!   if (str1)
!    {
!     for (obuf=str1,nbuf=str1;*obuf;
!      ++obuf)
!      {
!       if (!isspace(*obuf))
!       *nbuf++=*obuf;
!      }
!    *nbuf=0;
!    }
!   return str1;
!  }

```

\$PRAGMA directive

Purpose : The \$PRAGMA directive is translated to the C keyword #pragma. The utility and syntax varies between compilers for the #pragma directives.

 Syntax: ``` \$PRAGMA compiler specific instruction and arguments ```

Example: To include the Dwmapi.lib library to a code compilation using Microsoft or Pelles C, use this

```
\$PRAGMA comment(lib, "Dwmapi.lib")

```

For a MinGW compiler use this

```
\$PRAGMA lib "Dwmapi.lib"

```

Remarks:

Details for using pragma directives with the Microsoft compiler are available on their Microsoft Pragma directives and the __pragma and _Pragma keywords page.

Pragma information for the MinGW compilers can be found at Pragmas Accepted by GCC page.

Here is a snippet of code from the BCX translator which shows how \$PRAGMA is used to suppress a MinGW compiler generated warning. A \$PRAGMA "diagnostic ignored" is placed immediately before the cast to CPP_FARPROC that causes the warning. The \$PRAGMA "diagnosic pop" restores the diagnostics to their previous condition.

```
\$IFDEF (__GNUC__)
\$PRAGMA GCC diagnostic ignored "-Wcast-function-type"