cancel
Showing results for 
Search instead for 
Did you mean: 

!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
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 = ""
$
.
John Gillings
Honored Contributor

Re: !AD in F$FAO

Uwe,

Questions about F$TYPE

This is exactly what I meant about DCL being polymorphic. DCL will sometimes treat your symbol A as a string, and sometimes as an integer.

The doc for F$TYPE says:

"Returns the data type of a symbol. The string INTEGER is returned if the symbol is equated to an integer, or if the symbol is equated to a string whose characters for a valid integer.

The string STRING is returned if the symbol is equated to a character string whos characters do not form a valid integer"

So, that means F$TYPE is of no use in determining how F$FAO will treat the symbol, sorry! :-(

Consider:

$ a="12"
$ b=a+a
$ s=F$FAO("!UL",a)

in these cases A is treated as a string. On the other hand:

$ s=F$FAO("!UL",'a')

"works", because DCL has interpreted the value of A as INTEGER

Hein is correct that most cases where this trick is used represent "holes" in DCL, but anything left over are cases where someone insists on using DCL where a "real" programming language would be more appropriate.
A crucible of informative mistakes
John Gillings
Honored Contributor

Re: !AD in F$FAO

Jan,

> I have difficulty trying to devise a way of breaking it, "on purpose or unintentionally".

That's easy! Someone could decide that the ability to read arbitrary addresses is a potential security risk and decide to filter the FAO control string. Simplest implementation would be to search for the "nonsensical" directives and refuse to call SYS$FAO if any were found.

Another, less likely possibility, would be to completely reimplement F$FAO, not just call the system service. DCL could then attempt to "do what you mean" with directives in the control string, so perhaps !AD could look at the size argument and extract that many characters from the string argument. As I said, unlikely as it would be lots of work for very little apparent return, BUT, as long as the DOCUMENTED behaviour for F$FAO didn't change, it would be fair game!

If engineering wanted users to be able to be able to read arbitrary addresses, the obvious implementation would be a new lexical function (say):

$ contents=F$PEEK(address)

where "contents" is set to the 32 bit value at the specified address. (I'll bet Guy could knock that together in a few minutes).

It's easy enough to do, but some would argue that it's inappropriate use of DCL. That this capability hasn't been implemented, or even requested, in over 25 years suggests that it's not really necessary.

Hein has mentioned the rarely used EXAMINE command, but I've never been able to do anything interesting with it.
A crucible of informative mistakes
Peter Hofman
Frequent Advisor

Re: !AD in F$FAO

Funny, this discussion has just lead to documenting (part of) this stuff :-)
Willem Grooters
Honored Contributor

Re: !AD in F$FAO

I prefer to keep DCL-procedures as simple as possible. If !AS will just do what is expected - put some symbol in a string - that is enough. All extra code is an burdon in maintenance, and especially when the code is to be maintained by others than the original author. When you're used to the VMS-style of parameter passing (thanks for the explanation, John (Jan, hij verdient zijn punten!)) this extra code is obvious and easy to follow. However, you can imagine yourself what would happen if someone is to maintain this code without this knowledge.
Second - what is the benefit of using the explicitly unsupported codes?
Third - DCL is NOT! a programming language, though I know it can be abused that way. It's intended use (interface to the OS)justifies the limitations.
Willem Grooters
OpenVMS Developer & System Manager
Jan van den Ende
Honored Contributor

Re: !AD in F$FAO

John,
Hein is correct that most cases where this trick is used represent "holes" in DCL, but anything left over are cases where someone insists on using DCL where a "real" programming language would be more appropriate.
/quote>

I have a tendency to agree with both.
Yes, a compiled language is "more appropriate", but still, I agree with Hein that it can be considered a "hole" that something can not be done with DCL. And, in my view, "appropiateness" is a relative concept!
I have a (certainly not fully black<->white) tendency to consider compiled languages the right choice for applications, where my gut feelings favour DCL for system manager stuff, like various bootstrap (take that VERY loosely) routines.
I tend to take those from site to site, and a given compiler is certainly not guaranteed at each site.


Simplest implementation would be to search for the "nonsensical" directives and refuse to call SYS$FAO if any were found.

that would break F$FAO and SYS$FAO in the same way, so that does not break the parity in behavior.


... to completely reimplement F$FAO ...

Which would surely imply an eqully complete reimplementation of the documentation.

And, if the past may be considered any guide to the future, VMS Engeneering __DOES HAVE__ a fantastic track record for going to great lengts to __NOT__ break old behavior as side-effect of changes/new features!
I would _EXPECT_ a total redesign to carry a slightly different name, and FAO declared obsolete.
Like the various $LOGICAL things were declared obsolete, and replaced by $TRNLNM, at the intro of VMS V4 (yes, back in 1983 or 1984). I still trip over them, even in MUCH newer stuff by DEC/COMPAQ/HP.
And I DO mean "trip over", because we make as much use as possible of dedicated LNM-tables, entries of which are NOT found by $LOGICAL & friends.


... or even requested, in over 25 years suggests that it's not really necessary.

Touche

Peter:

Funny, this discussion has just lead to documenting (part of) this stuff :-)

And now for the big thing: get this documentation available where it is likely to be found! If you did not stumble over this thread, it would be far away to SUPPOSE there MIGHT be something, and then compose a set of search engine arguments that would bring up THIS thread!

Willem:

and especially when the code is to be maintained by others than the original author.

Agree. I would be somewhat more forgiving, but it definitely can only be maintained only by the more-experienced DCL gurus, and being undocumented just raises that bar by quite a distance!


DCL is NOT! a programming language, though I know it can be abused that way.

Define "Programming language".
DCL allows specifying a sequence of instructions in a formalised syntax to be executed by a processing unit, and in __MY__ definition that constitutes a programming language. Opinions thereoff can vary of course.


(Jan, hij verdient zijn punten!)

translates as: He DOES deserve his points!
You will notice I used his next replies to boost his totals in this thread.

Cheers.

Have one on me.

Jan
Don't rust yours pelled jacker to fine doll missed aches.
Lawrence Czlapinski
Trusted Contributor

Re: !AD in F$FAO

Jan, I agree with you that system manager stuff should be done in DCL.
1. A system manager is expected to know DCL. 2. A replacement system manager may not know the langauge another system manager picked. Be kind to your successors.
3. Language might become UNSUPPORTED by vendor. [Not enough customers to warrant continued support.] A complied language version could become unsupported by the vendor in the future. An unsupported version might not be a problem till someone has to change it in the future.
4. Customer might SWITCH APPLICATION LANGUAGES. The customer may not be aware of these language usages. The customer may port or even rewrite applications to a different language in the future.
Ex 1: Customer might replace FORTRAN with C (or C++) for instance.
Ex 2: Customer [US Department of Defense]
requires new programs to be in a new language, ADA. Didn't last.
5. LOSE LANGUAGE LICENSE: The customer might move the applications that use the language to a different system.
6. The complied language might exist on the system at some future time if the applications get ported to some new language.
7. The system might be replaced and redeployed without the compiled LANGUAGE.
8. Murphy's Law "If anything can go wrong, it will." If anything can go wrong, it "might".
9. There aren't many programmers left for the language. A programmer for that language isn't available or affordable.
10. The cost of programmers for that language has become too expensive.
11. Language is no longer taught in most colleges/universities. FORTRAN, for instance, isn't taught any more in many colleges/universities.
12. Most programmers don't learn the language that was used. [FORTRAN, ADA or whatever]
13. The cost of a programmer in the language becomes unaffordable for the company. Fine, till code needs to be changed.
14. Some other reason that isn't on this list. [It wasn't even thought of, but it went wrong anyway.]
Lawrence



Cass Witkowski
Trusted Contributor

Re: !AD in F$FAO

I love reading forum because you learn something new every day. I didn't know about the examine command or forgot it a long time ago. From a DCL programming stand point it's not very useful since you can't easily assign the output to a symbol. (Of course now that I said this someone will prove me wrong) :)

What I find facsinating is the new thinking that this conversation stream opens up. What if you could peek values from memory. Maybe you would need the same privs to do that as you would need to do the analyze/system command. What if you could peek using a symbol? Would that be useful.

If it was readily available could you see some programs to check the status of certain things.

What I like about the DCL programming language is the immediacy of results. Having to compile and link slows down the creativity process

I myself would like to see DCL have a symbol type of datetime. I would love to be able to do simple time comparisions between two dates. Or add a delta time to an absolute.
Jan van den Ende
Honored Contributor

Re: !AD in F$FAO

Cass,

Starting with your last question first, because that is easiest:

$ abs_time = f$file("xyz","CDT") ! any timespec
$ delta = "300-12:0:0" !any-valid-deltatime
$ newtime = f$cvtime("''abs_time' + ''delta'")
$ show symbol newtime.

Difference between two abs. times?
-- Coming to this theatre soon! One of the many fantastic new features by Guy Peleg.

Some of your other functionality is probably more redily available (again: coming soon, by Guy Peleg) by way of DCL$CTRLT
Check out:
http://forums1.itrc.hp.com/service/forums/questionanswer.do?threadId=761205

I have in this forum already seen quite ingeneous ways of PIPEing to get (a.o.) SDA output.

But, that said:

YES!!!! wouldn't it be GREAT to be able to have SDA values into DCL symbols!

Guy Peleg, still seeking suggestions for new goodies?

Proost.

Have one on me.

Jan

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

Re: !AD in F$FAO

Cass,

F$DELTA is in V7.3-2, but in the mean time it is possible to calculate a delta time by successive approximation (see attched DCL procedure)



A crucible of informative mistakes
John Gillings
Honored Contributor

Re: !AD in F$FAO

Jan,

You can read any USER READ location in system space, which includes most of the things you can read from SDA. All that's needed is to find the value for the symbol.

Attached is an insane DCL procedure to define a global DCL symbol to the SDA symbol value. Example:

$ DEFSYM EXE$GQ_BOOTTIME

Global symbol EXE$GQ_BOOTTIME will be set to the value of the system symbol. Note I don't recommend this for production use - the overheads are just plain stupid!
A crucible of informative mistakes
Cass Witkowski
Trusted Contributor

Re: !AD in F$FAO

John,

Thanks for the DCL procedures.

I think that having a datetime symbol type would make manipulating date and times much easier with much less string manipulation.

Cass