|
- Written and documented by David Deley
Introduction to CMac Chapter 3: Caveats
There are a few differences between CMAC and other programming
languages you may be familiar with, like C. These are small things you
often end up learning the hard way, by experience. I mention these
early on so you'll be aware of them. I also encourage others to append
other caveats they've learned.
1. EXPRESSION EVALUATION IS STRICTLY LEFT-TO-RIGHT
CMAC doesn't have operator precedence as you may be used to in
other languages. Expression evaluation is strictly left-to-right. For
example, the following code doesn't work as expected:
You have to add parenthesis:
2. SINGLE QUOTED STRINGS vs. DOUBLE QUOTED STRINGS
Double quoted strings interpret the backslash \ character as a special character.
| Code: |
"\a" = 0x07 bell
"\b" = 0x08 backspace
"\f" = 0x0C form feed
"\n" = 0x0A newline
"\r" = 0x0D carriage return
"\t" = tab or space (see below*)
"\v" = 0x0B vertical tab
"\\" = 0x5C backslash
"\"" = 0x22 double quote
"\'" = 0x27 single quote
"\xHH" or "\XHH" = 0xHH where HH is a hexadecimal number
str Example = "First line\nSecond line\nThird line";
|
* "\t" will enter a 0x09 horizontal tab character if "Tab Expand"
is set to "Tabs" under TOOLS -> CUSTOMIZE... -> Editing, or it
will enter a 0x20 space character if "Tab Expand" is set to "Spaces".
Two double quotes together inside a double quoted string make a double quote:
| Code: |
| "He said, ""Goodbye!"" and then left." |
same as:
| Code: |
| "He said, \"Goodbye!\" and then left." |
Result:
| Quote: |
| He said, "Goodbye!" and then left. |
Single quoted strings interpret the vertical bar | character as a
special character. A vertical bar followed by a number will insert that
character value. A few examples:
| Code: |
'|12' = form feed
'|10' = newline
'|13' = carriage return
'|124' = "|" vertical bar
'||' = "|" vertical bar
'|65' = 'A'
'|90' = 'Z'
'|97' = 'a'
'|122' = 'z'
str Example = 'First line|10Second line|10Third line';
|
Two single quotes together inside a single quoted string make a single quote:
| Code: |
| 'He said, ''Goodbye!'' and then left.' |
Result:
| Quote: |
| He said, 'Goodbye!' and then left. |
3. MACROS MUST BE EITHER PROTOTYPED OR DEFINED BEFORE THEY ARE CALLED BY OTHER MACROS.
For example, the following will work because macro "mysub" is defined before macro "test" which calls it.
| Code: |
void mysub()
{
...
}
void test()
{
mysub();
} |
The other way is to prototype macro "mysub" at the beginning of the
file. The following will work even though macro "mysub" is defined
below macro "test" which calls it:
| Code: |
macro_file mycmac;
prototype mycmac {
void mysub();
}
void test()
{
mysub();
}
void mysub()
{
...
}
|
4. WINDOW ID vs. WINDOW NUMBER
There's a difference between a window number and a window ID. A window number is a number between 1 - 127 (assuming that's the highest number of windows we can have. The limit might be 255.) A window ID is something different. It's a very large number. Some system functions ask for a window ID while other system functions ask for a window number. 'TranslateWindowID' converts a window ID to a window number.
NOTE: A window's number may change as windows are added and deleted.
A window's ID will not change. I therefore recommend you always work
with window ID's and use 'TranslateWindowID' to get the window number
when you need it. Window numbers are useful when you want to cycle
through all existing windows.
It turns out that the Switch_Window
system function has an undocumented feature. The documentation says it
accepts a window number to switch to. But it is also smart enough to
also accept a window ID. A window number is a number between 1 and 127
(or maybe 255, I'm not sure what the upper limit is). On the other hand
a window ID has the lower 16 bits set to zero, so in hex a window ID
looks like 0xnnnn0000. Thus it is easy to tell a window number from a
window ID. Note this is undocumented so you should always use a window
number with Switch_Window.
5. STRINGS ARE 254 CHARACTERS UNLESS YOU SPECIFY A LENGTH
If you do this: then your string MyString is only 254 characters long
(that is, the string will hold 254 characters and no more). If you need
a longer string you have to specify the length. MAX_LINE_LENGTH is a system constant (currently 16383) you can use to specify the longest possible string:
| Code: |
| str MyString[MAX_LINE_LENGTH]; |
6. EXPLICIT STRINGS IN CMAC CODE
The longest explicit string in CMAC code you can specify is 253 characters. Any longer and
bad things happen!
| Code: |
str MyString[500];
MyString = "<no more than 253 characters between quotes>"; |
7. GLOBAL VARIABLES
If you set a global integer variable to zero (0) the global variable will disappear.
If you set a global string variable to "" (zero length string) the global variable will disappear.
This does not cause a problem, because if you reference a non-existant
global integer you will get zero (0), and if you reference a
non-existant global string you will get "" (zero length string).
GLOBAL ALIASES
Example:
| Code: |
global {
int Decimal_Places "!CALC_DECIMAL_PLACES";
str Disp_Str "!CALC_DISP_STR";
} |
Here Disp_Str is your global alias you can use like a local variable, and
!CALC_DISP_STR is the global variable created. (Some CMAC functions require a local
variable and will not accept a global alias. You may equate a local
variable to the global alias and then use your local variable.)
| Code: |
str ds;
ds = Disp_Str;
int x = svl(ds); //Then something like this will work. |
If instead you were to just declare
| Code: |
global {
int Decimal_Places
str Disp_Str
} |
then the global variables created are the same as the alias names.
Global variables with names not preceded by a ' ! ', '@', or '~' are
restored at the beginning of each editing session if the restore
feature is enabled. (This is often not necessary or wanted, which is
why so many global variable names start with '!' or '@'.)
8. DlgAddCtrl and ctrlid
Do not use -1 for ctrlid for any control which actually does
something (e.g. PushButton). Multi-Edit 9.10 doesn't generate good
ctrlid values when you use -1, so make up a unique ctrlid number for
each control or the control won't work. Use -1 only for static
elements, such as static text, bitmaps, or icons. Also do not use any
of the following numbers as they have special meaning:
32767 - dlg_WCmd_Init
998 - ? (cased with 1)
2 - User aborted dialog (by Xing out or pressing Escape key)
1 - User pressed Return key (with no default button or focus button)
Do not use a number > 60,000 (this is the mistake Multi-Edit
9.10 makes when you use -1). To prevent conflicts with future versions
of Multi-Edit, I suggest using numbers below 30,000. So ctrlid numbers
in the range [1000 - 30,000] should be OK. (See Introduction to CMAC. 12: Dialogs {currently under construction}).
|