Preprocessing in Slick-CŪ is identical to C/C++. Preprocessing allows you to conditionally compile source code or define textual replacements.
This chapter includes the following topics:
The syntax of the Slick-CŪ language conditional if block is any of the following examples:
#if expression
[statements]
{#elif expression
[statements]}
[#else
statements]]
#endif
There may be nothing more than space or tab characters preceding a #. Text on the same line following #else or #endif is not permitted. The expression specified MUST be valid. To display an error message and end the compile, use the #error directive: #error expression.
Usually, preprocessing is used to write macros that operate on multiple operating systems or environments. The table below shows the constants that are automatically defined by the Slick-C translator.
|
Constant |
Description |
|---|---|
|
__PCDOS__ |
Non-zero if the current operating system is Windows. Use machine() built-in function to determine at run time which of these operating systems you are running. |
|
__UNIX__ |
Non-zero if current operating system is UNIX compatible. |
|
__NT__ |
Non-zero if the current operating system is Microsoft Windows NTŪ compatible. |
|
__VERSION__ |
Version number of SlickEditŪ. |
|
__COLUMN__ |
Number of characters from start of current line. |
|
__FILE__ |
Current file name. |
|
__LINE__ |
Current line number. |
|
__PATH__ |
Current file name and path. |
|
__DATE__ |
Current date. |
|
__TIME__ |
Current time. |
Use the Slick-C translator -d option to define a constant for use by preprocessing. To test if a constant has been defined, use the defined() function.
Example:
#if !defined(my_constant)
#define my_constant "default value"
#endif
#if __PCDOS__
name="c:\util\myprog"
#elif __UNIX__
name="/usr/bin/myprog"
#else
#error "Don't know what to do for this OS"
#endifThe #pragma preprocessor directive is used to change various options during the course of a compile. The syntax is:
#pragma option(OptionName [, ( on | off ) ] )
Slick-CŪ options (OptionName) are shown in the table below.
For each option, if the second argument is not given, the value is restored to the command line invocation value.
All #pragma options may be specified by command line compiler options. Run vst.exe (UNIX: vst) with no arguments to view compiler options. You can use the VST environment variable to specify compiler options for all of your macros.
|
OptionName |
Default Value |
Description |
|---|---|---|
|
On |
Enables autodeclvars and autodeclctls. See those options for more information. | |
|
On |
When enabled, the compiler attempts to automatically declare control variables. This option is automatically enabled when autodecl, pedantic, strict, or strict2 is enabled. | |
|
On |
When enabled, the compiler attempts to automatically declare typeless variables when an assignment is made. This option is automatically enabled when autodecl is enabled. This option is automatically disabled when pedantic, strict, or strict2 is enabled. | |
|
Off |
Allows you to configure properties and built-in functions as deprecated. When enabled, the Slick-C compiler catches when a deprecated item is used and flags it as an error. A function is considered as deprecated if it has a Javadoc function comment containing the @deprecated tag. Deprecation is automatically enabled when pedantic is enabled. Note that using the deprecation pragma may result in your macro not loading when you upgrade to a new release of SlickEdit if the code calls a function that becomes deprecated. | |
|
Off |
Enabling this option automatically enables all existing and future strict syntax and type-checking options. Unlike other Slick-C pragmas, the meaning of pedantic could be augmented in future releases of SlickEdit. This means that if you use the pedantic pragma in your own macros, they may not load when you upgrade to a new release of SlickEdit if, for example, a function it is using becomes deprecated or stricter type checking reveals a problem. | |
|
Off |
This is used to generate code for variables without having the type information. When enabled, any variable can be redeclared as a typeless variable. | |
|
Off |
This option is used to turn on a high level of type checking and syntax enforcement in the Slick-C translator. It automatically enables autodeclctls, autodeclvars, strictnumbers, strictparens, strictsemicolons, and strictstrings. We recommend using #pragma option(strict,on) in user-written macros because it gives the best combination of high level of error checking and forward compatibility. | |
|
Off |
Second generation of strict Slick-C compilation checks. Automatically enables all options that strict enables, plus strictarglists, strictincludes, and twopass. | |
|
Off |
When disabled, a function can have implicitly typeless arguments. When enabled, formal parameter lists for functions and prototypes must have types. The example illustrates an error case: void first_char(s) {
return substr(s,1,1);
}
This option is automatically enabled when pedantic or strict2 is enabled. | |
|
Off |
When enabled, Slick-C variables with boolean types cannot be assigned to integers without using a cast. This means, for example, that the following would be flagged as an error: boolean b = 0; This option is automatically enabled within classes and namespaces. | |
|
Off |
When enabled, the ellipsis must be given as the last argument to a function or prototype for type checking to succeed when calling function with extra arguments. This option is automatically enabled when pedantic or strict2 is enabled. | |
|
Off |
When enabled, verifies that all #import and #include statements precede any real code in the current module. This is required for twopass compilation. This option is automatically enabled when pedantic or strict2 is enabled. | |
|
Off |
When enabled, enforces naming conventions for symbols declared in Slick-C classes, namespaces, and enumerated types. See Slick-CŪ Naming Conventions for more information. This option is automatically enabled when pedantic is enabled. | |
|
Off |
When enabled, Slick-C numeric constants are treated strictly as integer or double precision floating point types, rather than than typeless variables. This makes it possible to use precise type inference with integer types, like i := 0;. This option is automatically enabled when pedantic is enabled. It is also automatically enabled within classes and namespaces. | |
|
Off |
Use this pragma for more readable code. When enabled, parentheses must be given on all built-in functions. This option is automatically enabled when pedantic, strict, or strict2 is enabled. | |
|
Off |
When enabled, all function calls require the function to be previously declared or imported. When disabled, when the Slick-C compiler encounters a function call to a previously undefined function, it assumes that the function is a global function. The function call is resolved at link time, and an error will show up at run time if the function does not exist or is not provided enough parameters. This option is automatically enabled within classes and namespaces. | |
|
On |
When enabled, and an explicit return type is given to a function, the compiler will flag an error if a return statement is potentially missing. | |
|
Off |
Use this pragma so that smart editing features work, and to prevent compilation errors. When enabled, semicolons must terminate all statements. This option is automatically enabled when pedantic, strict, or strict2 is enabled. | |
|
Off |
When enabled, Slick-C string constants are treated strictly as string types, rather than typeless variables. This means, for example, that you can no longer assign "0" to an integer variable. This option is automatically enabled when pedantic, strict, or strict2 is enabled. | |
|
Off |
When enabled, the Slick-C compiler does a two-pass compilation. This allows the compiler to verify all function call signatures even for functions that are declared later in the file. This option is automatically enabled when pedantic or strict2 is enabled. |
The #region directive lets you specify a block of code that you can expand or collapse when using Selective Display. The #endregion directive marks the end of a #region block. A #region block must be terminated with #endregion. The syntax of these directives is:
#region name
#endregion name
The name parameter (optional) is used to indicate the name of the region. This name is displayed in the editor window when the region is collapsed.
Example:
#region Region_1
void Test() {}
void Test2() {}
void Test3() {}
#endregion Region_1
defmain()
{
}The syntax of the include statement is:
#include string_constant
This statement includes the file specified by string_constant for compiling. If string_constant does not specify a path, the Slick-CŪ translator will look in the same directory of the main source file. Otherwise, the path specified by string_constant is searched. If the file is not found, the Slick-C translator looks for the include file in the directories specified by the VSLICKINCLUDE and VSLICKPATH environment variables (see "environment variables" in Help → Index). Include files may be nested.
Unlike C++, Slick-C header files do not require guards. Our preprocessor automatically guards against recursive header file inclusion, and will never include the same header file twice for a single module either.
#import is a preprocessing directive but it is more than a #include in that it does the following:
Imports all public declarations from a Slick-CŪ module.
Uses an implicit header guard to prevent recursive or multiple importation of the same module.
#imports are not recursive. If you #import a module (abc.e) that #imports another module (def.e), you will not get the declarations from def.e. This is an important consideration for compilation performance and to minimize inter-module dependencies.
#require is a preprocessing directive, like #import, but it is recursive. If you want a module to always pull in another required module when it is #imported, use the #require directive. For example, a class (Abc) that derives from another class (Def) should #require the parent class module (Def.e). That way when another module #imports Abc.e, it will also have the declaration for the parent class Abc. As a general rule, a module needs to use #require when its classes or function signatures use types that are declared in another module. Use #import when your code (within function bodies) needs to call functions or use classes and global variables from other modules.
When processing a #import, the following rules are in effect:
All function definitions are treated as prototypes.
Global variable definitions are treated as declarations.
Static globals are ignored.
Forms, menus, event tables, and event handlers are ignored.
#includes continue to be treated as part of the #import.
Examples:
#import "stdcmds.e"
#import "slickedit/stringutil.e"
#import "slickedit/search.sh"