HOME | COMPANY | SOFTWARE | DOCUMENTATION | EDUCATION & TRAINING | SALES & SERVICE | |
"The Official Guide to Programming with OmniMark" |
|
International Edition |
Previous chapter is Chapter 20, "Macros".
This chapter describes the differences between OmniMark V2 and OmniMark V3. This section is provided primarily for programmers who are accustomed to OmniMark V2 and wish to move to OmniMark V3. It will also be useful for programmers who must take OmniMark V2 programs, and run them with OmniMark V3. Programmers who are new to OmniMark and have no old programs to maintain may skip this section.
Essentially, these changes fall into one or more of the following categories:
Each reader may have their own view of how different features fall into these classifications. The organization presented here is just one possibility.
The changes introduced in OmniMark V3 have been made carefully:
However, there have been some incompatibilities introduced now, to avoid larger problems later. To the programmer concerned with backwards compatibility, the key areas of interest are:
Each of these sections ends with a subsection describing the possible incompatibilities that may arise, and providing techniques for overcoming them.
The other sections describe either completely new features or generalizations of existing ones. Such changes will not impact programs that work under OmniMark V2.
Readers familiar with OmniMark V2 or responsible for maintaining V2 programs should read the whole chapter. There will be many new features of interest. (Readers who are not familiar with OmniMark V2 should read the whole manual.)
The purpose of the reduced language features is to make string, numeric, and test expressions more concise. This makes larger expressions much smaller, leaving the larger-scale structure of the program more apparent to the reader of the program.
This change is necessary because new features in OmniMark (the new string operators and value-returning functions) reduce the need to split functionality across multiple actions. This will likely result in much more complex expressions, in OmniMark, and it is important that these expressions do not obscure the higher-level structure of the program.
The features that implement the reduced language are:
The rule for when type heralds are required is quite simple: the COUNTER, SWITCH and STREAM heralds are only required in the LOCAL, GLOBAL, or function argument declaration which defines them. The PATTERN keyword is only required with the built-in pattern variables in the SGML-ERROR rule.
Although SAVE and SAVE-CLEAR are local declarations they do not actually declare the shelves they name, and so the names of the saved shelves can be used unheralded in these declarations. The following is permitted:
DOWN-TRANSLATE GLOBAL COUNTER column-widths VARIABLE ... ELEMENT table SAVE column-widths ...
Because of this new use, it can no longer appear in macro names or macro argument separators.
The old names are still recognized, but are now deprecated. The new names are designed to be more descriptive and to avoid conflicts with actions, functions or programmer-defined shelves.
The "DECLARE HERALDED-NAMES" declaration must immediately follow the translation type if there is one.
Most OmniMark V2 programs will continue to run unchanged under OmniMark V3. The ones that do not can be made to run using the techniques described in Section 21.1.2, "Impact of the Reduced Language".
OmniMark V3 still allows the heralded style of name references used by previous releases of OmniMark. The main reason for this is to ease the transition from previous releases of OmniMark. In general, explicit type heralding is unnecessary and discouraged. Mixing the heralded and unheralded forms is especially discouraged because it results in confusing code:
SET x TO COUNTER x + x
Nevertheless, heralds do have their uses.
Heralded names can be used to access variables which would otherwise be hidden by variables of the same name declared in a nested scope. For example, in the following, COUNTER value identifies the outer value, while using value without a herald would identify the inner STREAM value:
DO LOCAL COUNTER value LOCAL COUNTER x DO LOCAL STREAM value SET x TO COUNTER value DONE DONE
The herald narrows the identification of the name to just those objects of the specified type. This use of heralds is also strongly discouraged. In general, it is poor practise to give different variables in a scope the same name as another variable in a containing scope. It is better to use distinct names.
Finally, heralds are required when referencing quoted variable names.
Quoting names in declarations does not change how they are interpreted. In particular, even if a variable name in a declaration is quoted, it still "hides" any use of that name as a keyword within the scope of the declaration.
Traditionally, quoted variable names are used for three reasons:
Sometimes, OmniMark programs are generated from other sources, and it may be convenient to use the names of objects in that source as variable names in the OmniMark program.
One example is an OmniMark program generated to process database fields. In this case, it may be desirable to name the variables after the fields whose data they contain. Many databases allow blanks and other special characters in field names.
In these situations, quoted variable names are recommended to ease the process of generating these programs.
The macro argument format item, "%@", allows macro arguments to be inserted inside of quoted strings. By combining this feature with quoted variable names macros can construct shelf names using the macro arguments. An example of this is given in Section 20.3.4, "Defining Operations On A Group Of Shelves".
The use of quoted names in this circumstance can be a useful structuring technique.
OmniMark V3 provides the "DECLARE NAME-LETTERS" declaration to extend the set of characters that can be used in unquoted names. Where this extension necessary, the NAME-LETTERS declaration is recommended. Quoted names are deprecated in this situation.
As with previous releases of OmniMark, OmniMark V3 allows programs to use variables without declaring them. However, the list of restrictions on such programs has been extended, as follows:
In OmniMark V3, COUNTERs, SWITCHes, STREAMs, and PATTERNs do not each have their own "name space". They share the name space with each other and with OmniMark keywords. Within a local scope, names can only have one interpretation.
This change has allowed type heralds to be dispensed with, but has the disadvantages that:
The hiding of keywords by variable names has the most potential to cause problems.
For example, if you declare a COUNTER named item within a local scope, you can't use ITEM to index a shelf, nor can you use the "ITEM OF" operator. (The operators "@" and "@ OF" can still be used, though.)
Declaring a name within a scope excludes it from being used as a keyword anywhere in that scope. This even applies to usages of the keyword in the same scope which occur before the declaration. The following is in error:
DOWN-TRANSLATE GLOBAL COUNTER table-columns VARIABLE ... ELEMENT table DO SAVE table-columns LOCAL COUNTER save ... DONE
GLOBAL variables exist in a single scope that encompasses the entire program. So, the names of global shelves cannot be used as a keyword anywhere within the program.
Similarly, function names (see Section 12.1.1, "Function Names") also inhabit the global name space. Because they are global, declaring a function excludes that function's name from being used as a keyword anywhere within the program.
A rule to disambiguate keywords and variables which have the same name is necessary, because there are contexts in an OmniMark program where it is impossible to tell the difference between a keyword and a variable with the same name.
An example that illustrates the problem is:
GLOBAL STREAM name GLOBAL STREAM close FIND 'hello' CLOSE name
This program fragment would be syntactically legal whether "CLOSE" referred to the action CLOSE or the STREAM shelf close.
The reason that variable names (and function names) were given precedence over keywords is to ensure that OmniMark V3 programs remain upwardly compatible with future releases. If a future release introduces a new keyword which happens to be used as a variable or function name in an OmniMark V3 program, the keyword is hidden by that variable or function name. Thus, the meaning of the program does not change.
OmniMark V3 allows programmers to protect keywords from being interpreted as function or variable names by immediately preceding the keyword with a backquote ("`"). No white space characters are permitted between the backquote and the keyword that it protects.
DOWN-TRANSLATE ... ELEMENT table DO LOCAL SWITCH done REPEAT EXIT WHEN done ... AGAIN `DONE
In this example, the first two instances of "done" refer to the local SWITCH variable. If the third were not backquoted it would as well. (And that would be a syntactic error).
Note should be made of the fact that a backquote is not a separate token: no white space, comments or anything else is allowed between the backquote and the following keyword. For example, the following is in error, because a backquote is not allowed by itself.
DO LOCAL STREAM done INITIAL {"Hello!%n"} OUTPUT done ` DONE
Note that except for OUTPUT and SGML, built-in shelf names are not keywords of the sort that are subject to backquoting. You can't put a backquote in front of a name that starts with "#".
OUTPUT and SGML can be backquoted in all contexts. Specifically, it is legal to backquote OUTPUT whether it refers to the action or to the built-in stream. OmniMark always treats these words as keywords instead of names, and that is why the backquote is permitted only for these streams.
Function names are not keywords. They share the same name space, just like programmer-defined variables, but because they are programmer-defined names, they can never be identified by a backquoted name.
This new role for the backquote ("`") character means that it is no longer available as part of a macro name or a macro argument separator.
Backquoting should not be commonly used. It should only ever be considered a "safety hatch" -- avoiding names that are OmniMark keywords should always considered the preferred technique. Heavy use of backquoting quickly becomes ugly, and reduces readability:
`DO `LOCAL `STREAM done `INITIAL {"Hello!%n"} `OUTPUT done `DONE
The consequences of the reduced language features may prevent correct OmniMark V2 programs from running under OmniMark V3.
The "DECLARE HERALDED-NAMES" declaration and the -herald command-line option provide a last resort in this situation. They turn off the ability to omit type heralds and the special role of the backquote character ("`").
This means that any OmniMark V2 program which does not compile because of the reduced language features can be made to compile and run by adding either the "DECLARE HERALDED-NAMES" declaration to the program, or by running OmniMark with the -herald command-line option.
However, it also means that much of the benefit of the reduced language is no longer available.
These features can be used by:
"DECLARE HERALDED-NAMES" is intended for programs which:
The -herald command-line option is intended for programs which:
Programs with either the "DECLARE HERALDED-NAMES" declaration or the -herald command-line option differ from other OmniMark V3 programs in the following ways:
Programs which use either the "DECLARE HERALDED-NAMES" declaration or the -herald command-line option are the same as OmniMark V3 programs in all other ways, including (but not limited to):
"DECLARE HERALDED-NAMES" applies to the entire program. It must immediately (except for comments) follow the translation type (if there is one).
DECLARE HERALDED-NAMES and -herald are supported only to ease the use of programs written for use with earlier releases of OmniMark, and they should not be used for other purposes. Their use in conjunction with major new features, such as functions, is particularly deprecated.
When an OmniMark programmer encounters difficulties running an OmniMark V2 program under V3, the following procedure may help evaluate possible solutions. The solutions are presented with the most desirable ones first. Alternative solutions should be considered as temporary workarounds only, and should only be used until the correct solution can be implemented:
OmniMark V3 provides new features to support server programs. Server-based processing is described in Chapter 2, "Types of OmniMark Programs". These new features are:
Process programs are driven by PROCESS-START, PROCESS, and PROCESS-END rules.
Process programs are described in Section 2.3, "Process Programs: Server-Based Translation Programs".
The "DO SGML-PARSE" action is described in Chapter 17, "SGML Document and Subdocument Parsing".
Local referent sets are especially useful for server programs which must perform a task for a client, and then continue processing. Server programs cannot wait for termination for referents to be resolved.
Local referent sets are described in Section 11.3, "Server Applications: Local Referent Sets".
Writing referents to buffers and other referents is described in Section 11.2.1, "Writing Referents to Different Types of Streams".
External functions are described in Section 12.3, "External Functions". External output functions are described in Section 12.3.4, "External Output Functions". External source functions are described in Section 12.3.3, "Externally-Defined Sources".
Process programs are specified by omitting the translation type. This can cause problems with down-translations written for OmniMark V2 that omit the translation type. This is easily solved.
The following features have not been documented for a very long time and are no longer implemented. They may impact programs that were written for the very earliest versions of OmniMark and its precursor, XTRAN:
This should not affect any reasonably current programs.
This should not affect any reasonably current programs.
The following changes were made to make OmniMark more consistent. Some of these correct situations which have been a source of confusion to some of our users. Most users will never have run into them and will be unaffected by these changes.
Parenthesization can always be used to obtain the desired results.
This is documented in Section 6.4.3.2, "Reopening Streams".
The problem that arises is that if a TRANSLATE rule outputs an attribute using the "%v" format item, and the content of the attribute causes that same TRANSLATE rule to fire, the program will enter an infinite loop.
The solution to this problem is to explicitly specify the "z" modifier on the "%v" format item in such situations.
This has been fixed. If this causes a problem, then the programmer should choose another escape character. In general, changing the escape character is deprecated.
In this case, WHITE-SPACE behaves exactly like the pattern BLANK or "%n":
This is unlikely to cause any change in behaviour for the large majority of programs, and provides predictable behaviour for programs which really must do things like this.
The error message can be avoided by testing the existence of the element before using any operators on it.
This section lists changes which will not affect existing programs, but which are very useful for new programs.
OmniMark V3 programmers can now take advantage of a number of syntactic improvments:
ELEMENT #IMPLIED DO SELECT OCCURRENCE CASE 1 OUTPUT "1st" CASE 2 OUTPUT "2nd" CASE 3 OUTPUT "3rd" CASE 4 TO 20 LOCAL COUNTER occ SET occ TO OCCURRENCE OUTPUT "%d(occ)th" ELSE OUTPUT "Another" DONE OUTPUT " element %q%n" SUPPRESS
This construct is documented in Section 8.1.2.2, "Selecting Actions Based On Numeric Values".
These are documented in Section 9.3, "Test Expressions".
These are described in more detail in Section 9.2.2.4, "Dynamic String Concatenation" and Section 9.2.2.5, "String Repetition".
Note that if you use these characters your programs may have a different appearance on other systems, and some electronic mail systems might not be able to handle them.
Note that if you use these characters your programs may have a different appearance on other systems, and some electronic mail systems might not be able to handle them.
DO WHEN KEY OF THIS REFERENT < ATTRIBUTE chap-num = DATE "xY" <= "06" ... DONE
Test expressions can also be combined in a multi-value comparison test, but they will usually need to be parenthesized.
These are described in Section 9.1.2.4.1, "Multi-Part Numeric Comparison Tests", Section 9.2.4.2, "Multi-Part String Comparison Tests", and Section 9.3.3, "Multi-Part Switch Comparisons".
PROCESS LOCAL COUNTER i LOCAL STREAM s LOCAL SWITCH w SET s TO "Hello, World.%n" SET i TO 5 SET w TO FALSE OUTPUT s ||* i WHEN NOT w
Switches may be set to TRUE, FALSE, or any other boolean expression.
OmniMark V3 provides improved control over input and output with the following features:
Opening files in either TEXT-MODE or BINARY-MODE is described in Section 6.4.3.1.1, "Open Modifiers". Reading files in TEXT-MODE or BINARY-MODE is described in Section 10.4.2.1, "Binary And Text-Mode Files".
These are documented in Using OmniMark 3 [eum13].
OmniMark V3 provides the following features to allow programmers to improve the modularity of their programs:
This allows local variables to be declared near where they are needed, which is a great advantage when a rule or a function is particularly large.
OmniMark V3 provides the following new SGML-processing rules:
OmniMark V3 supports the following new operations on shelves:
The ability to use LASTMOST as an indexer inside of a USING prefix allows the default indexing behaviour of shelves to be restored within a context where it has been affected by passing it as a function argument, or by specifying a USING prefix on an enclosing compound action.
Finally, the following new features have also been provided:
OmniMark V3R0a is a maintenance release and introduces very little new functionality. The new features are:
Copyright © OmniMark Technologies Corporation, 1988-1997. All rights reserved.
EUM27, release 2, 1997/04/11.