Documente Academic
Documente Profesional
Documente Cultură
Renato C. PROTTI
What is xml ?
xml stands for eXtensible Markup Language.
By analogy to HTML and some other languages, xml is mostly used to "describe" text.
This means that the only function of xml is to describe (markup)
Instead of describing how data has to display (the way data looks) like HTML, XML describes how data
just is (not the way it looks)!
see W3C - World Wide Web Consortium for more info on html, xml , ...
Example:
MAKE_NEEDLE
When called, this macro will receive as parameters :
Background_Bitmap and centrepoint target position, needle_Bitmap and rotation_point position, Variable
for rotation angle calculation, ... and some flags to drive details.
Using the parameters, FS will display the background, place the needle_bitmap with rotation_point
corresponding to the centrepoint and then start rotating this needle_bitmap the amount represented by
the associated variable.
All the variables (Parameters) are described in the Parameters.doc of Panel SDK.
Note that some are read only and some can be altered through usage of Events.
Events are internal functions used to modify the FS-Variables.
The modifications are made via the Events and not directly on the variable, this is to ensure FS keeps
control over the variable values and avoids inconsistencies.
1/10
Edlin :-))
2/10
3/10
Remember that in xml all data description begins with a beginning tag and an ends with an ending tag (End
tag = "/" followed by Beg-tag) ei. <Hello> ..... </Hello>
Image
Image
Name
ImageSizes
DegreesPointsTo
Bright
PointsTo
UseTransparency
Luminous
Alpha
NoBilinear
Note that in gauges.dtd all definitions are also made using xml.
In this short extract of the file we find the description if Image definition.
Every definition is two parts : !ELEMENT and !ATTLIST
Image
(Axis? , Nonlinearity?) >
1. <!ELEMENT
After <!ELEMENT we find the Element.Type (Image) and the description of sub elements needed or allowed
after <Image> and before </Image> tag
Axis and Nonlinearity will be described somewhere in the dtd file with their AttributesList
2.
<!ATTLIST
Image
Name
ImageSizes
...
CDATA #REQUIRED
CDATA #IMPLIED
<!ATTLIST describes all the attributes required or allowed for this Element.Type (Image)
Name
CDATA #REQUIRED means : there must be an attribute Name as String
ImageSizes CDATA #IMPLIED means : there should be an attribute ImageSizes as String, and if not
present, the real image sizes will be used.
In the gauge source, there was :
<Image Name="gauge_bckgrnd.bmp" ImageSizes="469,70,469,70" />,
The definition is "Well Formed" as it contains Name and ImageSizes before the ending "/>" and that the
values of both attributes are Strings between quotes.
3.
PointsTo
(East | South | West | North ) 'East'
Other Attributes descriptions are optional attributes : PointsTo is an enumeration list with allowed values :
(East or South or West or North) if omitted East is assumed.
Look what our statement becomes once parsed :
<Image Name="gauge_bckgrnd.bmp" ImageSizes="469,70,469,70" />,
is converted in :
<Image Name="gauge_background.bmp" ImageSizes="469,70,469,70" DegreesPointsTo="0" Bright="No" PointsTo="East"
UseTransparency="Yes" Luminous="No" Alpha="No" NoBilinear="No" />
4/10
Beside the functions of dealing with objects to display, reading Aircraft or Environment Variables, setting
values thru Events, FS-9 internal Parser can call some functions to Calculate, Test and Branch.
It is also able to manage some local variables that can be used in other functions.
Let's have a look on Calculations and Tests philosophy.
The calculations an tests functions use a storage technique called Stack.
Stack technique is often used when data storage cannot be defined at coding time, but is to be allowed on
demand according to the amount of data to be processed.
Some systems or machines are "stack oriented", meaning that they have special sublogic or hardware to deal
very quickly with a stack structure.
But what is it ?
Imagine the MainMemory as a spreadsheet where there is only one column.
Imagine the column goes from row1 to row4096.
While coding your program, you put the constants and defined variables from row1 down to row96.
But you know you'll need to get external values to be handled sometimes two at a time and sometime five at
a time and even different next time.
Imagine for some reasons that you'll call asynchronous processes that will also need room for a given time
and free it when they exit processing.
Once again, stack is a good solution to temporarily allow and free memory
If you determine that beginning from row4096 and growing toward row3000 (with decrementing addresses),
you can call that portion of memory "The Stack".
If you fill the space with values beginning at row4096 then row4095 then row4094 you just need to know
where you are (TopStackPointer)
In our example, row3000 will be TopStackLimit not to be exceeded.
If you don't need anymore one value (the last) you just increment your TopStackPointer and you forget the
value.
When a new process starts, it just need to know where the TSP is pointing, store that value and use as many
cells it needs for its job, then before leaving it restores the previous value in the TSP and things are reset as
before.
With this technique, you can call a sub-process as many times as wanted and everyone uses its amount of
needed storage, then restores it at the end for next candidate.
The constraint of this LIFO Stack technique is that only the TopOfStack cell is known, one must know what is
usable under it.
So it's nothing else : The last value is used first - The name : "Last In First Out"
Two operations :
Push : Decrement TSP and Place data into current location.
Pop : Get the data from current location and increment TSP
Example of use :
Suppose we need to add two values ... A = B + C
We "push the first (B) onto top of the stack" (update TSP).
We "push the second (C) onto top of the stack" (Update TSP).
We call the "additionner" that "pops both values from top of the stack" (updates TSP).
It makes calculation and "push the result onto top of the stack" Update TSP) and exits.
We now "pop the result (A) from top of the stack" (Update TSP) and we have the result.
5/10
Now, suppose that instead of calling the "additionner", wa call a "calculator", we need to tell not only the
values, but also the operation to perform.
To perform A = B + C, the operation will be :
TSP next = 4020
Push B onto Stack updating TSP next = 4019
Push C onto Stack updating TSP next = 4018
Push "PLUS" onto Stack updating TSP next = 4017
Call "Calculator" (it will pop 4018, seeing that its a plus, it knows it needs two more values, it pops 4019 and
4020 updating TSP next = 4020
After computing its addition, it pushes A onto the stack updating next = 4019.
On return we pop A from 4019 and update to next = 4020 as before.
To calculate the sum : A = B + C was executed like :
Push B : Push C : Push "+" : Pop A (assuming that Push and Pop update the TSP).
Imagine now that we will use a Macro to facilitate pushes and pops.
It should be some expression like :
Macro:
CALC(BC+=A)
Generating :
Push B
Push C
Push +
Call CALC
Pop A
Suppose now that the calculation is a little more complex A = (B + C) * D
our expression would become :
CALC(BC+D*=A)
Generating
Push B
Push C
Push +
Call CALC
Push D
Push *
Call CALC
Pop A
As we can see :
Operands are always placed before operators.
Parentheses are no more needed
Order of operations is critic (but this was true in normal notation too)
This way of proceeding with calculation is called the postfixed notation better known as Inverted Polish
Notation. (Polish because the first description of the method was made by : Jan Lukasiewicz, a Polish
mathematician 1878-1956)
This method is widely used (internally) in the stack oriented computers.
Some words about Testing using the Stack.
Testing is exactly the same kind of job as adding :
b+c is done by push b, push c, push + call CALC
and a<b is done by in push a, push b, push < call CALC
The only difference is that when + is evaluated, the result is a+b and when < is evaluated, the result is 0 or
1 (False or True) according to a and b
Our internal FS-9 Calculator and Expression Evaluator needs to find its arguments on the stack and organized
(you guessed it !) according to IPN rules.
6/10
In the same way, results are always found on top of stack on exit.
With these informations we can now proceed to our detailed investigation into gauges.xml syntax and
principles of operation.
(E:AMBIENT WIND
DIRECTION, Degrees)
(L:My Variable,bool)
(>K:GEAR_DOWN)
(M:X)
Beside Variables, FS-9 xml-Parser offers 50 internal registers related to stack operations.
Stack Operations and Registers :
c - Clear the stack
d - Duplicate TopOfStack value
r - Reverse TopOfStack values
s# - Store TOS value to register
l# - Load Register to TOS value
sp#- Store and Pop TOS to Reg
7/10
Rule : The third operand defines which of first or Second operand will take place as result of the
operation
Color="%('GREEN' 'YELLOW' (A:Value, percent) 49.99 < ?)"
The third operand "(A:Value,percent) < 51.59" defines which of first "GREEN" or Second "YELLOW"
operand will take place as result of the operation.
If (A:Value,percent) < 51.59 then "GREEN" else "YELLOW"
Push "GREEN"
Push "YELLOW"
Push (A:Value,percent)
Push 49.99
Push <
Evaluate (Pop operator and operands - replace by result (0 or 1) then Pop operand #=result. (on Top of
Stack we find "GREEN" if 1 operand is popped and "YELLOW" if 0 operand is popped.
So "GREEN" if (A:Value,percent) < 49.99
or "YELLOW" if (A:Value,percent) not < 49.99
Just a little more complex with two ? tests :
Color="%('GREEN' 'YELLOW' (A:Value, percent) sp1 l1 49.99 < ? 'RED' l1 79.99 < ?)"
Push "GREEN"
Push "YELLOW"
Push (A:Value,percent)
Store and pop (A:Value,percent) to Reg-1
Push Reg-1
Push 49.99
Push <
Evaluate --> GREEN if (A:Value,percent) < 49.99
or "YELLOW" if (A:Value,percent) not < 49.99
Push "RED"
Push Reg-1
Push 79.99
Push <
Evaluate --> "PREVIOUS COLOR" if (A:Value,percent) < 79.99
or "RED if (A:Value,percent) not < 79.99
To summerize :
GREEN if (A:Value,percent) < 49.99
YELLOW if 49.99 < (A:Value,percent) < 79.99
RED if 79.99 < (A:Value,percent)
In this example, GREEN, YELLOW or RED is the value of Attribute : Color
Rule : Every character between <String> ... and ... </String> is part of the string.
We'll have to choose a message to be displayes according to the value of (L:MSG,enum)
<String>
%((L:MSG, enum))%{case} %{:00} %{:01}PARKING BRAKE ON%{:02}IGNITION A ON %{:03}IGNITION B ON
%{:04}L REV ARMED %{:05}R REV ARMED %{:06}L PACK OFF %{:07}R PACK OFF %{:08}NO SMOKING %{:09}SEAT
BELTS %{:10}LANDING LIGHTS %{:11}TAXI LIGHTS %{:12}L 14TH SOV CLSD %{:13}14TH ISOL OPEN %{:14}R 14TH
SOV CLSD %{:15}L 10TH SOV CLSD %{:16}APU LCV OPEN %{:17}10TH ISOL OPEN %{:18}R 10TH SOV CLSD %{end}
</String>
8/10
Rule : This xml-Tag describe how ths sublogic will deal with the selected value
<Case Value="1"> ... Execute until </Case> if value of selected variable is = "1"
Example:
<Element>
<Position X="47" Y="278" />
<Select>
<Value>(A:Value, enum) </Value>
<Case Value="0">
<Image Name="Image0.bmp" Bright="Yes" ImageSizes="25,5,25,5" />
</Image>
</Case>
<Case Value="1">
<Image Name="Image1.bmp" Bright="Yes" ImageSizes="25,5,25,5" />
</Image>
</Case>
<Case Value="2">
<Image Name="Image2.bmp" Bright="Yes" ImageSizes="25,5,25,5" />
</Image>
</Case>
</Select>
</Element>
9/10
Push L:DUMMY03,bool
Evaluate
True : Push 6 then pop to (>L:MSG) (note the > to signify write to ...)
False : Push 0 then pop to (>L:MSG)
Translated : If L:DUMMY03 then L:MAG = 6 else L:MSG = 0
10/10