1751873 Members
5094 Online
108782 Solutions
New Discussion юеВ

!AD in F$FAO

 
SOLVED
Go to solution
Jan van den Ende
Honored Contributor

!AD in F$FAO

As a result of a previous thread:



I'm also hoping that Jan will see this - he questioned the use of !AD in F$FAO. Jan, this is probably the MOST unsupported part of those procedures because it's EXPLICITLY not supported by the (correct!) documentation.

If you want to know more, please post a new discussion topic...


Volker, yes, I am indeed interested!
And as far as I have come to know some of the regulars in here, I expect to be not the only one.

So, WHY should these functions be NOT supported?
Even if they require some special, maybe complex, "Instructions for Use", that would not
make it fully unique, and the benefits could well outweigh the effort!
(for those to whom that does not apply: they are not forced to use them!)

Please shine some light in the darkness.

Cheers.

Have one on me,

Jan
Don't rust yours pelled jacker to fine doll missed aches.
20 REPLIES 20
Uwe Zessin
Honored Contributor

Re: !AD in F$FAO

My guess is because you can create nice errors:

$ write sys$output f$fao("*!AD","abcd")
%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000000000038248, PC=0000000000110001, PS=7FFABF50
$

... and engineering does not want to debug your complex procedures ;-)
.
Jan van den Ende
Honored Contributor

Re: !AD in F$FAO

Uwe,

not a valid point.
There are LOTs of ways to feed F$FAO (documented) combinations of params & values that cause similar errors.
But then, if you feed those combinations, at least the docs TELL (well, no always all too clear) you what you did wrong. As an example: let any newbee (and take that rather loosely!) try to get some decent results from F$GETQUI ( finding out how and when to use FREEZE_CONTEXT should explain the idea here).

Cheers.

Have one on me.

(at the moment I am at a Bavaria 8.6 .
Well worth a try, but probably kind-of hard to get by outside the Netherlands. Comparable to, but different from, Triple. The name derives from the percentage).

Jan
Don't rust yours pelled jacker to fine doll missed aches.
Jan van den Ende
Honored Contributor

Re: !AD in F$FAO

Sorry all,

I noticed a big lapse in the original posting:

I refered to "a" previous thread. It is this one:

http://forums1.itrc.hp.com/service/forums/questionanswer.do?threadId=744705

and specifically the 5th answer.

You might notice that it is not just !AD, but also !AC that is used.

Cheers.

Have one on me.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
John Gillings
Honored Contributor
Solution

Re: !AD in F$FAO

Jan,

I was afraid of this!

F$FAO is really just a jacket around the system service SYS$FAO. DCL passes the control string straight through, with no parsing. So, we don't do anything to remove directives that don't make sense in DCL. They will do "something", but not necessarily anything predictable, or useful.

The problem here is DCL doesn't give you any control over the internal representation of symbols, or over the passing mechanism used when calling lexical functions. Generally in DCL, symbols are treated as polymorphic objects, with the interpetation taken by context. However, with F$FAO, we need to have a simple rule to decide how parameters are passed.

Symbols of STRING type are passed into SYS$FAO by descriptor. Symbols of INTEGER type are passed by immediate value (since that's what the directives that require numeric values expect). Use F$TYPE to see the type of a particular symbol, and see HELP = for more details on how DCL decides.

OK, so knowing that, the only really useful string directive for normal use is !AS.

!AC is inserts a counted ASCII string, with the argument passed by reference. As a data type, ASCICs don't exist in DCL. Although they could be constructed (painfully!), there really is no need for them, and nowhere that they come from. Similarly !AZ. But note that even if you constructed one, you couldn't use it because there's no way to pass the string by reference. (not quite true, see below).

So why am I using !AD? Look carefully at the code. I'm exploiting the DCL implementation for F$FAO to use !AD to read data at a known virtual address. A numeric symbol is loaded with the address I want to read, it gets passed by immediate value in a context where the directive is expecting an address, so we're effectively passing the object at the target address by reference. Since F$FAO returns the result as a string, we then need to use F$CVUI to convert it back to INTEGER (and/or extract a bit field).

Then general code is:

$ addr=some-known-virtual-address
$ size=1,2,3 or 4 bytes
$ contents=F$CVUI(0,8*size,-
F$FAO("!AD",size,addr))

If the object at the location happens to be an ASCIZ or ASCIC, you could use !AZ or !AC to read and format it (as used in GETCALLER.COM).

So, using this trick, if you know the start of a data structure (like CTL$AG_CLIDATA), you can navigate around it from DCL, following pointers and extracting fields.

You can think of:

F$CVUI(0,32,F$FAO("!AD",4,ptr))

as being a pointer dereference operator. If you consider the amount of processing involved, it's a rather extreme example of inherent inefficiency in interpretive languages!

However useful this may be, it simply is NOT supported or documented and probably never will be. If anyone decides to change F$FAO in a manner that breaks this coincidental usage, then this code will break (most likely with ugly ACCVIOs). That will be unfortunate for some, but engineering won't care!

Something else that's sometimes useful is the !AF directive, to make a string "printable" (all non-printable characters are replaced by "."). Extending the hack, it becomes:

$ string="some dcl symbol"
$ formatted=F$FAO("!AF",F$LENGTH(string),
F$CVUI(32,32,F$FAO("!AD",8,string)))

How this works left as an exercise for the reader. Similarly we can create and use ASCIZ and ASCIC strings. For example:

$ C[0,8]=10
$ ASCIC=C+"ABCDEFGHIJKL"
$ S=F$FAO("!AC",-
F$CVUI(32,32,F$FAO("!AD",8,ASCIC)))
$ show sym s
S = "ABCDEFGHIJ"

$ Z[0,8]=0
$ ASCIZ="ABCDEFG"+Z+"HIJKL"
$ S=F$FAO("!AZ",-
F$CVUI(32,32,F$FAO("!AD",8,ASCIZ)))
$ show sym s
S = "ABCDEFG"


Please don't ask for this to be documented or supported. It won't happen! Have fun playing with it by all means, but don't complain if we ever break it (intentionally or by accident!). One could argue that anything you really need this trick for should probably be writting in a "proper" programming language.

A crucible of informative mistakes
Hein van den Heuvel
Honored Contributor

Re: !AD in F$FAO

Thanks John for the extensive writeup.
IMHO that should nicely close the topic.

Basically, every time you see F$FAO.. !AD axploited in a command file it is pointing out a missing functionallity in DCL.

It would be much more productive to formalize/generalize the reasons for using the constructions.

For example (poorly researched by me!):
- general purpose 64-bit time/date handling (Guy may have done this already)
- extensions to examine command. Maybe simply more data types (time, ascid, ascic, asciz,?). Maybe a /pointer or /output_symbol additions.

I'm not saying OpenVMS engineering should do this, just observing that this could be a better solution then armwrestling with f$fao.

DCL functionallity has to stop somewhere. I do not know where. But at some point you just have to accept to have to write a program or possibly a perl script to get a specific job done.

Just my 2c.

Hein.
Uwe Zessin
Honored Contributor

Re: !AD in F$FAO

Yes, I agree, a nice explanation. I am sure Jan will still not like to hear it and I am eagerly waiting for his response ;-)

John,
I think there is a minor error in your message when you say:
> Use F$TYPE to see the type of a particular symbol,

Because, when I try this:
$ a="12"
$ write sys$output f$type(a)
INTEGER
$

To me, this looks like |a| is a symbol of type string and when I look into HELP it says:
""Returns the *data type* of a symbol""
apparently F$TYPE() looks at the _contents_ of the symbol.
.
Jan van den Ende
Honored Contributor

Re: !AD in F$FAO

John,

first let me add my "thanks" to those of Hein.
Very interesting reading!

Probably my lack of knowledge, but I have difficulty trying to devise a way of breaking it, "on purpose or unintentionally".
My reasoning from "just passes it unaltered to SYS$FAO" would be, that breaking F$FAO can only come about by breaking SYS$FAO, and THAT surely WOULD be within the care of Engeneering!
And of course I agree, one probably should write stuff like this in a compiled language,
but, in practise (and just look at the originating stream for a real-life example) there may be very valid reasons to prefer DCL.
The inefficiency aspect appeals to me and my age-fellows (the 50+) probably much more than is normal nowadays.
It really is absolutely and utterly dwarfed by using GUI's, let alone Java!!
-- looking at which answers sometimes get 10 points, this deserves at least 50.

Hein,
..."pointing out a missing functionallity in DCL."
Heartily agreed! If ever you notice Guy running out of things to do :-), you are kindly requested to point him to this thread!!
Although, there may be an imbalance between the effort required, and the gain in use.
I am not under the impression that it will immediately become heavily used!


Uwe, maybe I do disappoint you now, but I am not SO VERY dissatified with the answer!. My curiosity HAS been satisfied, and I learned some interesting stuff. It just gets added to my toolbox!

About F$TYPE you are fully correct. And this is also the way it is documented (and has been for as long as I remember).
Just an interesting, clarifying expiriment:
$ Say = "write sys$output"
$ xx = "ABC"
$ say f$type(xx)
$ xx = xx - "AB"
$ say f$type(xx)
$ xx = xx - "C"
$ say f$type(xx)

.. I tripped over it some times, and I have corrected much more code that had this trap in positions that would _NORMALLY_ not have to deal with empty strings!

Thanks a lot all.

Cheers.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Bojan Nemec
Honored Contributor

Re: !AD in F$FAO

The strange thing of F$TYPE() is also that SHOW SYMBOL doesnt work in the same maner. See example:

$ a=12
$ sh sym a
A = 12 Hex = 0000000C Octal = 00000000014
$ write sys$output f$type(a)
INTEGER
$ a:=12
$ sh sym a
A = "12"
$ write sys$output f$type(a)
INTEGER

In the second a settings show symbol knows that this is a string, but f$type not.

Bojan
Uwe Zessin
Honored Contributor

Re: !AD in F$FAO

Bojan,
please re-read my message. F$TYPE(), as documented, looks at the *value* of the symbol and reports what type it is.

There is a nice examples in the online help:
$ x = F$CONTEXT("PROCESS",CTX,"USERNAME","SMITH")
$ TYPE = F$TYPE(CTX)
$ SHOW SYMBOL TYPE
TYPE = "PROCESS_CONTEXT"
$ x = F$CONTEXT("PROCESS",CTX,"CANCEL")
$ TYPE = F$TYPE(CTX)
$ SHOW SYMBOL TYPE
TYPE = ""

(Remember that this overlays the TYPE verb ;-)


Or take a non-existing symbol:
$ SYM_TYP = F$TYPE(abc)
$ show symbol SYM_TYP
SYM_TYP = ""
$
.