• Solutions
    • FERC XBRL Reporting
    • FDTA Financial Reporting
    • SEC Compliance
    • Windows Clipboard Management
    • Legato Scripting
  • Products
    • GoFiler Suite
    • XBRLworks
    • SEC Exhibit Explorer
    • SEC Extractor
    • Clipboard Scout
    • Legato
  • Education
    • Training
    • SEC and EDGAR Compliance
    • Legato Developers
  • Blog
  • Support
  • Skip to blog entries
  • Skip to archive page
  • Skip to right sidebar

Friday, November 17. 2017

LDC #59: The Program Before the Program

Programming can contain many layers of abstraction. A useful layer is to change manner in which the computer actually sees your program. Language ‘directives’ do just that. In this article we will explore three of the commonly used program directives and discuss how they can be used with Legato.


Directives


Directives tell the script processor to perform certain tasks during the initial preprocess parsing. Directives are useful in a number of important ways: to allow aliases to be defined, to include other sections of programs, and finally to direct certain sections of the program to be included or not included in the final executable portion of the script.


Like many other programming languages, Legato uses the ‘#’ character before a statement to indicate that it is a directive. The # must be the first item on the line and the statement encompasses the complete text line. Directives are not actually “run” or “executed”. Rather, they tell the script engine do things, like pretend the string IDCANCEL is really the number 2. Directives are all processed by the script engine in the first stage of program execution known as the preprocess phase.


There are a number of directives we will cover in this article:


#define — Defines a term to be replaced in the code.


#pragma — Specifies an action to be performed during script preprocessing.


#include — Directs the script engine to include a file as if it were part of the main file.


In a later articles I will cover conditional directives and resources.


#define — A Programmer’s Best Friend


We’ve used the #define directive in previous blog posts, but let’s examine it more formally. The #define directive is actually very simple: a string of characters is defined to be another string of characters. For example (expressed in various places in the script):


#define MY_NAME      201

   ... (in resource) ...
CONTROL "", MY_NAME, "edit", ES_LEFT|WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP, 53, 15, 119, 12, 0

   ... (in procedure) ...
name = EditGetText(MY_NAME);


At every point that MY_NAME appears, the value 201 will be substituted. This is useful in that a named value can be used in both a resource definition for a dialog and within the procedures to reference the dialog control. While during the development process numbers could be used, defined terms are better for creating easily organized and readable code. In addition, if a value ever needs to be changed, using a define allows you to change that value once in the original definition rather than everywhere it appears in the code.


The format is as follows:


#define name replacement_text


Where the name is the name or text of the item to be replaced. The name must follow the variable naming rules and cannot contain spaces, operators or other information. The replacement_text is then the text to replace the name with. The text can be a complex series of data containing variables, expressions and any data desired by the programmer. The name may also contain other references to defined terms. The replacement can be recursive and the use of parenthesis is recommended for anything that might be ambiguous, Also note that the define directive does not support complex macros with parameters.


While the text of a define can be upper and lower case, it is general practice to use all capitals to help differentiate it from other variables and information. So readers know that “MY_NAME” is a definition and “my_name” is a variable or function name.


A define statement can be repeated within the code so long as the replacement text is the same. Defines can also be used in resource editors.


Improperly defined defines will result in errors at the point of definition. For example, redefining a term with a different value will generate an error. Syntax errors within the defined text (or caused by the defined text’s insertion) will be displayed at the point of parsing where the term was replaced.


Finally, defines can be placed in code sections or, as stated above, within resource sections.


The SDK Definition


Unless specifically directed otherwise, the SDK header file “LegatoDefaultSDK.h” is automatically included in the script engine. It contains thousands of definitions ranging from language-function specific definitions as well as selected conventional definitions from the Windows SDK.


An example of of language-function definitions is flag information for the Word Parse Object. It has the prototype:


handle = WordParseCreate ( [int mode], [string data] );


In the SDK the following is defined for the function:


#define WP_GENERAL                   0x00000000  /* General – Stops on Word Spaces       */
#define WP_SGML_TAG                  0x00000001  /* Tags – Stops on SGML Tags            */
#define WP_PROGRAM                   0x00000002  /* Program                              */
#define WP_PROGRAM_GROUP             0x00000003  /* Program Groups                       */
#define WP_TAG_ENCAPSULATE           0x00000004  /* Parse Tags <> Adobe/Encapsulated     */


If you compare this to the documentation, you will notice some similarities and differences. First, there is an additional mode, for parsing Adobe (which is undocumented). Second. the modes are defined as hexadecimal in the SDK and integer in the documentation. This is because under the hood, the mode becomes part of a larger set of definitions:


                                                 /****************************************/
                                                 /* ** Parse Data                        */
                                                 /*  * Modes                             */
#define WP_MODE_MASK                 0x0000000F  /* Mode Mask                            */
                                                 /*  o Parse Type                        */
#define WP_GENERAL                   0x00000000  /* General – Stops on Word Spaces       */
#define WP_SGML_TAG                  0x00000001  /* Tags – Stops on SGML Tags            */
#define WP_PROGRAM                   0x00000002  /* Program                              */
#define WP_PROGRAM_GROUP             0x00000003  /* Program Groups                       */
#define WP_TAG_ENCAPSULATE           0x00000004  /* Parse Tags <> Adobe/Encapsulated     */
                                                 /*  o Flags                             */
#define WP_BIG_WORD_BUFFER           0x00000010  /* Use 1mb Word Buffer                  */
                                                 /*  * Output Flags                      */
#define WP_OUT_FLAG_MASK             0xFFFF0000  /* Mask for Output Flags                */
                                                 /*  o General                           */
#define WP_EOB                       0x00010000  /* End of Buffer                        */
#define WP_LEADER_BREAK              0x00020000  /* Stopped for Leader or Ellipse        */
#define WP_STOP_POSITION             0x00040000  /* Stop Position Hit (passed)           */
#define WP_OVERFLOW                  0x00080000  /* Buffer Overflow                      */
                                                 /*  o Tag Mode                          */
#define WP_TAG_BREAK                 0x02000000  /* Word Broke on Tag Syntax             */
                                                 /*  o Program Mode                      */
#define WP_PROGRAM_SPACE             0x01000000  /* Broke on Program White Space         */
#define WP_PROGRAM_BREAK             0x02000000  /* Broke on Program Syntax              */
#define WP_PROGRAM_BREAK_SET         0x04000000  /* Item Is Program Syntax               */
#define WP_PROGRAM_SYNTAX_ERROR      0x08000000  /* Program Syntax Error                 */
#define WP_PROGRAM_STRING            0x10000000  /* Return Expression Group              */
#define WP_PROGRAM_PARAMETER         0x20000000  /* Function Group - ()                  */
#define WP_PROGRAM_ARRAY             0x40000000  /* Array Group - []                     */
#define WP_PROGRAM_FAIL_CLOSE        0x80000000  /* Failed to Close Expression           */
                                                 /*                                      */
                                                 /* ** Program Parse Results             */
                                                 /*  * Control                           */
#define WP_RESULT_MASK               0x0000FFFF  /* Parse Result Mask                    */
#define WP_RESULT_GROUP_MASK         0x0000FF00  /* Parse Result Mask                    */
#define WP_RESULT_CALLER_MASK        0xFFFF0000  /* Reserved (Caller Bits/Space)         */
                                                 /*  * Comments                          */
#define WP_RESULT_COMMENT            0x00000100  /* Comment Group                        */
#define WP_RESULT_COMMENT_EOL        0x00000101  /* Comment to EOL               / /     */
#define WP_RESULT_COMMENT_OPEN       0x00000102  /* Comment to Open              / *     */
#define WP_RESULT_COMMENT_CLOSE      0x00000103  /* Comment to Close             * /     */
                                                 /*  * Control                           */
#define WP_RESULT_CONTROL            0x00000200  /* Control Group                        */
#define WP_RESULT_END                0x00000201  /* Expression End               ;       */
#define WP_RESULT_NEXT               0x00000202  /* Next Item/Parameter          ,       */
#define WP_RESULT_BLOCK_OPEN         0x00000203  /* Block/Group Open             {       */
#define WP_RESULT_BLOCK_CLOSE        0x00000204  /* Block/Group Close            }       */
#define WP_RESULT_LABEL              0x00000205  /* Label / ID                   :       */
                                                 /*  * Logical Operators                 */
#define WP_RESULT_LOGICAL_OPERATOR   0x00000300  /* Logical Group                        */
#define WP_RESULT_LOGICAL_NOT        0x00000301  /* Logical NOT                  !       */
#define WP_RESULT_LOGICAL_AND        0x00000302  /* Logical AND                  &&      */
#define WP_RESULT_LOGICAL_OR         0x00000303  /* Logical OR                   ||      */
#define WP_RESULT_EQUAL_TO           0x00000304  /* Equal to                     ==      */
#define WP_RESULT_GREATER_EQUAL      0x00000305  /* Greater Than                 >=      */
#define WP_RESULT_LESS_EQUAL         0x00000306  /* Less Than Equal              <=      */
#define WP_RESULT_NOT_EQUAL_TO       0x00000307  /* Not Equal                    !=      */
#define WP_RESULT_GREATER            0x00000308  /* Greater Than                 >       */
#define WP_RESULT_LESS               0x00000309  /* Less Than                    <       */
                                                 /*  * Math                              */
#define WP_RESULT_MATH_OPERATOR      0x00000400  /* Math Group                           */
#define WP_RESULT_MATH_ASSIGN        0x00000401  /* Assign (Equal)               =       */
#define WP_RESULT_MATH_PLUS          0x00000402  /* Plus                         +       */
#define WP_RESULT_MATH_MINUS         0x00000403  /* Minus                        -       */
#define WP_RESULT_MATH_MULTIPLY      0x00000404  /* Multiply (pointer)           *       */
#define WP_RESULT_MATH_DIVIDE        0x00000405  /* Divide                       /       */
#define WP_RESULT_MATH_MODULUS       0x00000406  /* Modulus                      %       */
#define WP_RESULT_MATH_INVERT        0x00000407  /* Invert                       ~       */
                                                 /*  * Bitwise Math                      */
#define WP_RESULT_BITWISE_OPERATOR   0x00000500  /* Bitwise Group                        */
#define WP_RESULT_MATH_AND           0x00000501  /* Math And                     &       */
#define WP_RESULT_MATH_OR            0x00000502  /* Math OR                      |       */
#define WP_RESULT_MATH_XOR           0x00000503  /* Math XOR                     ^       */
#define WP_RESULT_SHIFT_LEFT         0x00000504  /* Shift Left                   <<      */
#define WP_RESULT_SHIFT_RIGHT        0x00000505  /* Shift Right                  >>      */
                                                 /*  * Postfix/Prefix                    */
#define WP_RESULT_POSTFIX            0x00000600  /* Postfix Group                        */
#define WP_RESULT_INCREMENT          0x00000601  /* Increment                    ++      */
#define WP_RESULT_DECREMENT          0x00000602  /* Decrement                    --      */
#define WP_RESULT_NAMESPACE          0x00000603  /* Namespace                    ::      */
#define WP_RESULT_MEMBER             0x00000604  /* Member                       .       */
#define WP_RESULT_MEMBER_POINTER     0x00000605  /* Member as Pointer            ->      */
                                                 /*  * Assignment                        */
#define WP_RESULT_ASSIGNMENT         0x00000700  /* Assignment Group                     */
#define WP_RESULT_ASSIGN_PLUS        0x00000701  /* Assign w/Plus                +=      */
#define WP_RESULT_ASSIGN_MINUS       0x00000702  /* Assign w/Minus               -=      */
#define WP_RESULT_ASSIGN_MULTIPLY    0x00000703  /* Assign w/Times               *=      */
#define WP_RESULT_ASSIGN_DIVIDE      0x00000704  /* Assign w/Divide              /=      */
#define WP_RESULT_ASSIGN_MODULUS     0x00000705  /* Assign w/Modulus             %=      */
#define WP_RESULT_ASSIGN_AND         0x00000706  /* Assign w/Bitwise AND         &=      */
#define WP_RESULT_ASSIGN_OR          0x00000707  /* Assign w/Bitwise OR          |=      */
#define WP_RESULT_ASSIGN_XOR         0x00000708  /* Assign w/Bitwise XOR         ^=      */
#define WP_RESULT_ASSIGN_SHIFT_LEFT  0x00000709  /* Assign w/Shift Left          <<=     */
#define WP_RESULT_ASSIGN_SHIFT_RIGHT 0x0000070A  /* Assign w/Shift Right         >>=     */
                                                 /*  * Non-C                             */
#define WP_RESULT_NON_C              0x00000800  /* Non-C Group                          */
#define WP_RESULT_NC_NOT_EQUAL       0x00000801  /* Not Equal                    <>      */
#define WP_RESULT_NC_ASSIGN_CAT      0x00000802  /* Assign and Cat               .=      */
#define WP_RESULT_NC_EQUAL_TYPE      0x00000803  /* Equal Strict                 ===     */
#define WP_RESULT_NC_NOT_EQUAL_TYPE  0x00000804  /* Not Equal Strict             !==     */

It would be near impossible, even for the biggest nerd, to remember all the bit positions when taken together with the thousands of other definitions.


If you want to use your own SDK, you can by using a pragma to direct the script engine not to load the preprocessed information. There’s more on that below.


The #pragma Statement


Pragma (or from “pragmatic”) is a directive that tells the script engine to process or not process certain events, errors, or in a certain environment. The form is:


#pragma directive [options]


where the directive specifies a predefined action and options specifies an optional set of parameters which may or may not be required depending on the directive.


The actions types are as follows (they are case insensitive):


AllowBreak


Allows the script to be broken with the Pause/Break key. When running in IDE mode, this is the default.


AppVersion version


Checks the ‘version’ string against the application. On failure, a message box is displayed and forces the script to exit. The version is in the form ‘0.0a’ or major version number, minor version number, and release letter. This is one of only a few directives or functions that will result in an uncommanded message box on error:



C


Specifies a pragma comment. Pragma comments survive code crunching to allow non-program data to be included in the source file. The ScriptGetComments SDK function can be used to read pragma comments from a file.


DebugTrace


When present, a debug trace file is created. If no additional parameter is provided, the debug trace file will be placed into the “LegatoLog” folder for the vendor in the application data folder (%appdata%). If a name is provided without qualified path, the path is added to the LegatoLog folder. If a full path is provided, the trace file is created at the specified location (see Section 2.7 Debugging Tools of the reference manual for more information). Adding “Robust” prior to the filename will cause the file to be flushed on each log entry. This is useful if the application isn’t crashing but significantly slows down the script engine.


Disable


When present, the script will exit as if an exit statement was processed. This is useful to quickly disable a script.


NoSDK


Directs the script engine to remove the predefined terms with the SDK. If for some reason a developer decided that the SDK defaults were not appropriate, using this pragma resets the predefined values. Note that since this action resets the defined terms in the preprocessor, no defines can be placed prior to this directive. This directive does not remove the predefined data for resources. 


ScriptVersion version


Checks the ‘version’ string against the script engine. On failure, a message box is displayed and forces the script to exit. The version is in the form ‘0.0a’ or major version number, minor version number and release letter. This is one of only a few directives or functions that will result in an uncommanded message box on error:



The #include Statement


We’ve also touched on the #include directive before, particularly when we’ve dealt with external resource files. The #include directive allows a program to be assembled from a series of files. This makes organizing a program much simpler by allowing resources, defines, and even various sections of a program to be broken into separate files. This can also allow for subroutines to be placed in discrete files, which in turn permits them to be used in multiple separate script programs.


The format is as follows:


#include "filename"


#include <filename>


Where filename is the reference name. If in quotes, specifies a relative filename or an absolute filename. This cannot be a variable and must be in double quotes. If in angle brackets, the file is expected to be located in the application program path at “Script\Include\”.  Note that this is not a preprocessed string literal and therefore does not process backslashes as escape characters. When a path is relative, it is relative to the file containing the directive.


Includes can be used to hold common data and definitions, code segments, or resources, If the extension is “.rc”, the content is considered a resource script. Defines within such files are processed for both resources and script code.


Finally, for the sake of conditional directives, a pseudo definition will appear only in included files called “_INCLUDE_FILE”. When defined this indicates the current script file has been included in another file. This can be used specify whether code should included on a conditional basis.


Conclusion


Understanding and using directives opens many opportunities to increase the utility of your programs. Probably the simplest is the #define directive, which is pretty much a necessity to create easy to read and maintain code, but the other directives allow you as the programmer a great deal of versatility behind the scenes, so to speak.


 


 


Scott Theis is the President of Novaworks and the principal developer of the Legato scripting language. He has extensive expertise with EDGAR, HTML, XBRL, and other programming languages.

Additional Resources

Novaworks’ Legato Resources

Legato Script Developers LinkedIn Group

Primer: An Introduction to Legato 

Posted by
Scott Theis
in Development at 09:28
Trackbacks
Trackback specific URI for this entry

No Trackbacks

Comments
Display comments as (Linear | Threaded)
No comments
The author does not allow comments to this entry

Quicksearch

Categories

  • XML Accounting
  • XML AICPA News
  • XML FASB News
  • XML GASB News
  • XML IASB News
  • XML Development
  • XML Events
  • XML FERC
  • XML eForms News
  • XML FERC Filing Help
  • XML Filing Technology
  • XML Information Technology
  • XML Investor Education
  • XML MSRB
  • XML EMMA News
  • XML FDTA
  • XML MSRB Filing Help
  • XML Novaworks News
  • XML GoFiler Online Updates
  • XML GoFiler Updates
  • XML XBRLworks Updates
  • XML SEC
  • XML Corporation Finance
  • XML DERA
  • XML EDGAR News
  • XML Investment Management
  • XML SEC Filing Help
  • XML XBRL
  • XML Data Quality Committee
  • XML GRIP Taxonomy
  • XML IFRS Taxonomy
  • XML US GAAP Taxonomy

Calendar

Back May '25 Forward
Mo Tu We Th Fr Sa Su
Thursday, May 15. 2025
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Feeds

  • XML
Sign Up Now
Get SEC news articles and blog posts delivered monthly to your inbox!
Based on the s9y Bulletproof template framework

Compliance

  • FERC
  • EDGAR
  • EMMA

Software

  • GoFiler Suite
  • SEC Exhibit Explorer
  • SEC Extractor
  • XBRLworks
  • Legato Scripting

Company

  • About Novaworks
  • News
  • Site Map
  • Support

Follow Us:

  • LinkedIn
  • YouTube
  • RSS
  • Newsletter
  • © 2024 Novaworks, LLC
  • Privacy
  • Terms of Use
  • Trademarks and Patents
  • Contact Us