1. PreProcessor

<< Click to Display Table of Contents >>

Navigation:  2. Components > 1. PreProcessor & EXE-Compiler >

1. PreProcessor

MACRO - Definitions

Previous Top Next


Preprocessor-Directives

 

MACRO. Definition

Macro definition

 

 

Intention

 

Define your own Commands!

Bundle them to build your personalized robot-language.

Use available commands and put them together to MACROs (to new commands).

Customize the scrip-language to your needs.

 

While not starting with a '#, this is an preprocessor command. Imagine that you can define your own commands. Save them in include files and call them in your scripts.

 

Macronames always start with a "%" (percentage sign, ASC 37). Before the script is executed, all MACROS are expanded to their content.

 

Macros can be used to make your own Instruction.

They can also be used to make your own "condition commands".

In this case, you may end up in the Editor with %IF_Something"

with a incorrect Formatting. Because Number of IXX. / EXX.

do not match.

To handle this, the SPRE-Editor now supports these two Pseudo-Instructions:

  'EIF+

  'EIF-

 

  These will not influence the Script in any way, just correct the Formatting of the Script in the Editor.

 

See Example below.

 

VAN.$$NUA=1

%IF_OR $$NUA|$$NUA|$$NUA

'EIF+

  MBX.Was here

EIF.

 

DMP.1

MBX.1

ENR.

'===========================================================

 

: %IF_OR 1

SAV.$$M00

#IF PARAMS=1

CAL.$$M00=(§§§01>0)

#EIF

#IF PARAMS=2

CAL.$$M00=(§§§01>0) OR (§§§02>0)

#EIF

#IF PARAMS=3

CAL.$$M00=(§§§01>0) OR (§§§02>0) OR (§§§03>0)

#EIF

#IF PARAMS=4

CAL.$$M00=(§§§01>0) OR (§§§02>0) OR (§§§03>0) OR (§§§04>0)

#EIF

IVV.$$M00>0

  #IF RECURS<0

EIF.

#EIF.

SAV.Restore

END%

 

 

Important:

We recommend that the Macro-Definitions are being placed at the End of the Script.

As Macros are collected in a separate Pass, they can still be used inside the script.

This way stepping through the script and testing will be easier, as you do not have always to go through the Macro-Definitions first.

 

Order of Processing in the Pre-Processor:

There is an Order of processing inside the Pre-Processor, the following Commands are processed sequentially:

1. #INC:

2. #LIB:

2. #ONCE / #OEND / #OREM

4. #VARD

5. #IFVA / #ELSA / # EIFA and #IFVL

6. #SCSA / #CASE / #CSEA / #ENSA

7. Macros etc.

8. Collecting Labels

 

This is important, because of this you can use the Preprocessor to remove Macro-Lines and Labels from the Code.

You can not use t to remove #INC: or #LIB: from the Code as its processed before, with highest Priority.

ts even processed before #ONCE: therefore #ONCE will not protect from these directives.

 

Generally the Priority of #ONCE ... #OEND is the highest.

Anything that is in there will be removed from the Code if the Condition s "Duplicate".

Of course the Directives themselves will also be removed from the final Code as well before Execution.

 

Generally Directives are processed and removed in one step.

 

In the next step the Compiler defines numerical Variables in Model-Space 255.

These Variables are available from that Moment and can be used inside #IFVA, #IFVL #SCSA, and wth #CASE .

 

For example like this:

#VARD $$VER=3

#IFVL $$VER>1

 

Here is a Real-Life Sample from the "Twitter-Button Bar" from Sample-Code Folder.

Using this System, we can remove Lines with Macros from the Code before the Script starts running.

 

#VARD $$VER=1

%SetText Letztes Diktat|Zuletzt diktierten Text wiederherstellen und einfügen.

#IFVL $$VER>1

%SetText UnDo|Letzte Textänderung im Arbeitsbereich rückgängig machen.

'-------

%SetText Schiller//Goethe|Zwischenablage-Text in Schillers oder Goethe's poetischem Stil neu interpretieren.

#IFVA $$VER>1  

  %SetText E. Roth//Sam Hawkins|Zwischenablage-Text im humorvollen Stil von Eugen Roth oder SAm Hawkins neu dichten.

  %SetText W. Busch//Morgenstern|Zwischenablage-Text in Wilhelm Buschs oder Christian Morgenstern's satirischem Versmaß umwandeln.

  %SetText Dichter//Erhard|Zwischenablage-Text im Stil eines wählbaren Dichters oder RMB: Heinz Erhardt's Stil neu interpretieren.

#EIFA

 

    Important Implications:

This will also prevent the use for the "higher Constructs" (1.-6.) Inside Macros, because at the Time of Macro-Expansion, they simply do not exist anymore.

 

You can generally nest these Construction. Again there is a Priority that the most outer Construct will remove anything inside if the Condition is not "True".

It does not matter f a "inner Condition" is true or not, f the outer Condition is False.

 

' This the case where its removed from the Code

#VARD $$VER=3

#IFVA $$VER>3

  #IFVA $$VER>1

  .. Will be removed

  #EIFA 

#EIFA

 

' This the case where ts not removed

#VARD $$VER=3

#IFVA $$VER>2

  #IFVA $$VER>1

  .. Will not be removed

  #EIFA 

#EIFA

 

You also need to understand that the #SCSA are generally processed after the #IFVA and therefore have a general Priority.

However that seems to not be any problem, as it does not Matter when a Construct is removed. In cases like below, first the #IFVA are processed and in the next Pass the #SCSA are processed.

The result is the same.

 

#VARD $$VER=3

#SCSA $$VER

#CASE 1

  #IFVA=3

    ... will be removed from the #SCSA

  #EIFA

#CASE 2

 

#CSEA

 

#ENSA

 

 

Syntax

 

: %Macroname P1

[Macro Content]

...

END%

 

 

 

 

Let's see an very easy MACRO example:

 

: %PrintIt 1

 DBP.Hallo my dear §§§01

END%

 

Lets look at this in detail. The Line:

 

: %PrintIt 1

 

starts the MACRO definition and defines that there will be at least one parameter at runtime. Calling the MACRO with less parameters will lead you to an error:

 

"Macrodefinition contains less parameters as Macrocall"

 

Now if we call the Macro later in our script we must give the MACRO one parameter, for example a number or a text or a variable. Like this:

 

%PrintIt Tomas

 

If we start the script, the Macro will be executed.

The DBP. command will write something like this in the Editor-Text-Area.

 

[10:22:14] [12] Hallo my dear Thomas

 

In the first bracket you can see the time when the Message was written. In the second bracket you will see the linenumber of the DBP.-command. In our case its the linenumber of our MACRO.

 

Executing MACROs in Single step mode will make the Editor "stay on the MACRO line" until the MACRO is completely executed. You can use the DBM.-command.

 

DBM.2

 

will make you see every line that was executed inside the MACRO.

 

Macros make sense, if you need to call subprograms several times in a script.

 

Like this:

 

DBM.2

 

: %PrintIt 1

DBP.Hallo my dear §§§01

:MyDupLabel

END%

 

%PrintIt Thomas

%PrintIt Ralf

 

ENR.

 

 

Now imagine you call your Macro several times and it contains a label (Jump mark for GTO./ JMP. (=GOTO).

 

What would happen?

The Macro would expand the Label each time and we would get a Error message:

"Duplicate Label ignored."

 

Similar problems could arise, if we used fixed variable names inside Macros, and these Macros would call themselves. Or would call other Macros that call these Macros.

 

To prevent these type of "duplication problems", the §§§95 to §§§99 preprocessor variables are provided. They will be expanded to a numeric value at preprocessing time.

This value has a defined format and will be increased by 1, each time a new MACRO Definition is been expanded. This way you can easily create unique labels and variable names.

 

 

Let's see an example:

 

: %MoreClicks 1

' Get the parameter into a variable

VAR.$$V§§§97=§§§01

IVV.$$V§§§97=0

 JMP.Label§§§98

EIF.

FOR.$$X§§§97|1|$$V§§§97

MLC.

NEX.

:Label§§§98

END%

 

 

If we call our Macro like this:

 

%MoreClicks 3

%MoreClicks 4

 

The source code line

 

VAR.$$V§§§97=§§§01

 

will expand to something like that for the first Macro call:

 

VAR.$$V01=3

 

and like this for the second Macro call:

 

VAR.$$V02=4

 

As we can see, the §§§01 contains the first given parameter. You can call a MACRO with more parameters then defined, but not with less. We could give more parameters to our MACROS like that:

 

%MoreClicks 3|hallo|99

 

They are separated with the pipe symbol. In this case the additional parameters will be in

 

§§§01 -> 3

§§§02 -> hallo

§§§03 -> 99

 

We can also check how many parameters have been given to our MACRO using the #IF ... #EIF - Decisions in Macros option. The number of given parameters is available inside the §§§00 also.

 

You can use the special-preprocessor variables §§§95 to §§§99 and the §§§00 to make Macro-unique Labels and temporary variables inside the Macros.

 

Macros can call themselves. They can call Macros that contain calls to themselves.

They can be nested to any depth. This way you can use recursion to solve your problems. However, the resolver does not check for unlimited nesting.

 

You can use the #IF ... #EIF - Decisions in Macros #IF RECURS option to prevent unlimited Macro nesting, which will possibly lead to an memory error or stack overflow. Inside Macro-Definitions you can use these special variables:

 

- §§§95 - unique variable-counter variable, Format "000"

- §§§96 - unique variable-counter variable, Format "00"

- §§§97 - unique variable-counter variable, kein Format

- §§§98 - unique-Label counter-variable, kein Format

- §§§99 - actual recursion-depth at expansion time

- §§§00 - number of Parameters given to the Macro at call-time

 

Macro-Parameter Substitution:

 

§§§01 through §§§90 will be substituted with the Macro parameters, which are given to the Macro at call-time. Macro-Parameter must be separated with | (Pipe-Symbol/ASC 124).

 

 

Important Note:

Macro Names are case-sensitive!

Using false written Macro-Names will not give an error-message!

These lines will just be ignored.

 

 

 

 

Parameter Explanation

 

Macroname - must start with %. Can be of any length. Can not contain spaces.

 

P1 - Number, defines the minimum number of parameters required for this definition

 

You can call a MACRO with more parameters but not with less.

 

 

 

Example

 

'-----------------------------------------------------------

' Macro-Example 1

'-----------------------------------------------------------

 

: %Press 1

PRT.Forall

#IF PARAMS=1

SCW.ct|button|§§§01

MLC.

PRT.Nur 1 Parameter

#EIF

#IF PARAMS=2

SCW.ct|button|§§§01

MLC.

PRT.Zweiter: §§§02

#EIF

END%

 

STW.ct|PBWindowClass:0|TestApp

FOR.§§LOP|1|4

 %Press Button 1

 %Press Button 2

 %Press Button 3|we did it!

NEX.

 

DMP.

MBX.Thats all.

END.

ENR.

'-----------------------------------------------------------

 

'----------------------------------------

' Macro-Example 2

'----------------------------------------

' Minimum Number of parameters is set to zero

: %MyMacroA 0

PRT.Number of Parameters:§§§00-Parameter=§§§01

END%

 

' Minimum Number of parameters is set to 1

: %MyMacroB 1

%MyMacroA Mytext

PRT.Number of Parameters:§§§00

END%

 

 

%MyMacroA Mytext

 

%MyMacroB Mytext

 

 

DMP.

END.

 

'----------------------------------------

' Macro-Example 3

'----------------------------------------

PRT.Running

: %Parameter 1

' Example for Macro-unique variable using §§§97

VAR.$$V§§§97=unique Variable

JMP.Label§§§98

PRT.Forall

#IF PARAMS=1

 PRT.Only 1 Parameter: §§§01

#ELS

 PRT.Not only 1 Parameter: §§§01,§§§02

#EIF

#IF PARAMS>2

 PRT.More then 1 Parameter: §§§01,§§§02

#ELS

 PRT.3 or more then 3 Parameter

#EIF

' Example for a Macro-unique Label, using §§§98

:Label§§§98

PRT.$$V§§§97

PRT.Macro-Recursion-Depth=§§§99

PRT.Macro- got §§§00 Parameters.

#IF RECURS<5

 %Parameter §§§01

#EIF

END%

 

 

%Parameter 1

%Parameter 1|2

%Parameter 1|2|3

 

DMP.

MBX.1

END.

 

'----------------------------------------

' Macro-Example 3

'----------------------------------------

' Macro prüft und korrigiert parameter 1 gegen

' parameter 2 als Lower Bound und

' falls vorhanden gegen parameter 3 als upper bound

: %Check_Bounds 2

'Here we are!

IVV.§§§01<§§§02

 : §§§01=§§§02

EIF.

#IF PARAMS>2

IVV.§§§01>§§§03

 : §§§01=§§§03

EIF.

#ELS

PRT.Nur ein Parameter

#EIF

PRT.Hallo

END%

 

 

'----------------------------------------

' Macro-Example 4

'----------------------------------------

PRT.1-----

%Parameter 1

PRT.2-----

' Mit DMP.1 kann man sich das expandierte Skript anzeigen lassen.

DMP.1

MBX.Warten

ENR.

'===========================================================

 

: %Parameter 1

#IF RECURS<3

%Parameter §§§01

PRT.Hallo Depth is: §§§99

#EIF

END%

 

 

'----------------------------------------

' Macro-Example 5 using VBS.

'----------------------------------------

'Sample:

STW.ct|ConsoleWindowClass|Eingabeaufforderung

MLI.

VAR.$$NAM=DIR{ENTER}

%VB_Sendkeys $$NAM

ENR.

'------------------------------------

: %VB_Sendkeys

' Use TOS

#IF PARAMS=0

GSB.VB_Sendkeys|$tos$

#EIF

#IF PARAMS=1

GSB.VB_Sendkeys|§§§01

#EIF

END%

'------------------------------------

' P1 - Zu sendender Text

:VB_Sendkeys

SAV.Save|$$NAM

IVV.§§_00|=|1

  $$NAM=§§_01

ELS.

  $$NAM=Hallo Welt!{ENTER}

EIF.

' Auflösung da VBS. nur vorsichtig, binärkompatibel auflöst.

VAR.$$NAM=$$NAM

 

VBS.VB|Test|$$NAM

Option Explicit

  Function Test(x)

  Dim a

  Set a = CreateObject("WScript.Shell")

  a.SendKeys x(0)

  End Function

VBE.

SAV.Restore

RET.

 

 

 

 

Remarks

 

Macro Names are case-sensitive!

Using false written Macro-Names will not give an error-message!

  These lines will just be ignored.

 

 

 

Limitations:

 

-

 

See also:

 

See also:

! Smarty's Preprocessor

1.1 #INC: - Pre-Processor File-Include

1.2 #ONCE / # OEND - Multiple Include Protection

1.8 : - MACRO-Definitions

1.4 #IF ... #EIF - Decisions in Macros

 

See these commands:

DBM. - DeBugMode

VBS. - VB-Script Start

VBE. - VB-Script End