Operating System - OpenVMS
1753506 Members
5183 Online
108795 Solutions
New Discussion

if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

 
Edmundo T Rodriguez
Frequent Advisor

if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

Hello!

DCL with OpenVMS v7.3-2

The following lines are giving me a headache, failing inside a command procedure as a subroutine or using them in a gosub but not out side of main. When I say “out of it”, I meant that if you use the line(s) by itself as a procedure, and pass to it a value (let say any number from 10 to 90), the procedure performs the comparison and produces a result giving a value to “cnt” which is return by writing to sys$output (wso “’’ficn’”)

But if I use the same lines and pass a value to them as a subroutine or a gosub from the main program, it seems like it perform the comparison but doesn’t carry the result a couple lines down to f$fao("!''cnt'*."), so “ficn” is actually doesn't obtain any.

Why “cnt” does not get the value inside the subroutine?

Even if I use a global symbol it fails!
I been examing this problem for couple of days.

Don't jump into conslusion before reading it well, you can see that I enter here the lines so you can used them as calling a subroutine or gosub to a label
(just remove/transpose the commented line)

...

cnt = 0
ficn = 0
wso := write sys$output

...

$_endloopvfi:
$ close fiin
$ vfindex = f$extract(27,5,"''fi'")
$! call SetCN 'vfindex
$ gosub SetCN
$ wso "[''ln';1H''dsa$dev' ''vfindex' % | ''ficn'X"
$ purge/keep=1 'vfi
$ endif
$ else

...

==============================================
$SetCN: ! SUBROUTINE !
$!
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$!
$ ficn = f$fao("!''CNT'*.")
$ cnt = 0
$ wait 00:00:00.5
$ return
$!exit
$!ENDSUBROUTINE !
===============================================

13 REPLIES 13
Hoff
Honored Contributor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

Reposting my reply from your previous (and now-closed) thread:

http://forums11.itrc.hp.com/service/forums/questionanswer.do?threadId=1420534

Works OK here with V8.3; what I've appended below works. Check for DCL patches and for contextual information.


$ set verify
$ vfindex = 100
$
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ cnt = 0
$ wait 00:00:05
$
$ call SetCNCall
$ gosub SetCNGosub
$
$ vfindex = 5
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ cnt = 0
$ wait 00:00:05
$
$ call SetCNCall
$ gosub SetCNGosub
$ exit
$
$SetCNCall: SUBROUTINE
$ set verify
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ cnt = 0
$ wait 00:00:05
$ return
$ exit
$ ENDSUBROUTINE
$
$SetCNGoSub:
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ cnt = 0
$ wait 00:00:05
$ return
$
Edmundo T Rodriguez
Frequent Advisor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

Hoff!

You say it works for you but I don't see a returned value from "cnt" and ficn = f$fao("!''CNT'*.") is 0

I want to see the following line printing something base on received value:

$ wso "[''ln';1H''dsa$dev' ''vfindex' % | ''ficn'X"

For now forget about the value of "dsa$dev" and the sequences!

Hoff
Honored Contributor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

Without intending offense, please stop telling me what to ignore, and please don't tell me what isn't relevant - if some part of the DCL code you've posted is not pertinent or is not relevant to the question, then please get rid of it.

Build a complete and concise reproducer. Post it.

How I code DCL will likely not match how you post DCL.

In other words...

Complete.

Concise.

Please don't make me dig through unrelated DCL.

And here I am, guessing at what has happened...

Depending on what you're doing, you might not see a symbol value returned. Check the symbol scope and procedure level rules around the CALL and GOSUB mechanisms, as a start.

That whatever you're reporting - and that I don't know what you're reporting is clearly going to be a problem - is due to some sort of symbol scoping, either directly or due to the rules around CALL and GOSUB. CALL in particular increments the procedure level, and is very close to what @ provides. It's a fairly isolated world, and there are documented ways to get values back; globa-scopel symbols, logical names, or return values are typical.

I've tweaked my example to display the output from the f$fao lexical functions:

$ set verify
$ vfindex = 100
$
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ write sys$output "''ficn'"
$ cnt = 0
$ wait 00:00:05
$
$ call SetCNCall
$ gosub SetCNGosub
$
$ vfindex = 5
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ write sys$output "''ficn'"
$ cnt = 0
$ wait 00:00:05
$
$ call SetCNCall
$ gosub SetCNGosub
$ exit
$
$SetCNCall: SUBROUTINE
$ set verify
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ write sys$output "''ficn'"
$ cnt = 0
$ wait 00:00:05
$ return
$ exit
$ ENDSUBROUTINE
$
$SetCNGoSub:
$ if vfindex .ge. 1 .and. vfindex .lt. 21 then CNT = 26
$ if vfindex .ge. 21 .and. vfindex .lt. 41 then CNT = 37
$ if vfindex .ge. 41 .and. vfindex .lt. 61 then CNT = 49
$ if vfindex .ge. 61 .and. vfindex .lt. 81 then CNT = 61
$ if vfindex .ge. 81 then CNT = 73
$ ficn = f$fao("!''CNT'*.")
$ write sys$output "''ficn'"
$ cnt = 0
$ wait 00:00:05
$ return
$


Edmundo T Rodriguez
Frequent Advisor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y


Hello again!

> Without intending offense, please stop telling me what to ignore,
> and please don't tell me what isn't relevant - if some part of the
> DCL code you've posted is not pertinent or is not relevant to the
> question, then please get rid of it.

> Build a complete and concise reproducer. Post it.

> How I code DCL will likely not match how you post DCL

Sir, Doensn't have to match ...

I being working with OpenVMS for more than twenty years and I
DESIGNED AND EXECUTED VERY COMPLICATE PROCEDURES OF HUNDRED OF LINES, but this procedure for a reason that I don't understand is not producing the results based on principles of DCL.

This is my problem, and if any one decided to colloborate with a solution
should understand that I am asking for a solution based on the provided
information which in this case is quiet clear.

If I stated to "forget for now about 'dsa$dev' and '' sequences"
is to make problem esier to understand, not to bother you or anybody else.

So I will say what ever I need to say to help other understand the issue.


The line of code after the gosub or the call in the main program

$ wso "[''ln';1H''dsa$dev' ''vfindex' % | ''ficn'X"

is expecting four values (ln, dsa$dev, vfindex, ficn)

I am only asking why the value "ficn" is not appearing at that line!

Why any of the 'expession' lines

if vfindex .ge. xy .and. vfindex .lt. yx then CNT = xx

are not able to produce a value in "cnt" than when passed to the
lexical f$fao("!''CNT'*.") can NOT print "ficn" ?


am I making the problem statement clear enough?
John Gillings
Honored Contributor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

Edmundo,

DCL can be very tricky. I think the issue is in data typing. You are using numeric comparisons "vfindex.GE.1", but the assignment to vfindex is of string type.

$ vfindex = f$extract(27,5,"''fi'")

If the extracted string contains any non-numeric characters, the resulting value will behave as zero. Your IF matrix has no branch for zero, so CNT will remain at its initialised value of 0. The F$FAO will therefore return a null string.

I'd have coded this as:

$ vfindex = F$INTEGER(F$EXTRACT(27,5,fi))

I'm being defensive and explicitly coding my assumption that the substring is a valid integer (also note that there's no need to quote and substitute the symbol fi). I'd have also had a sanity check if the remainder of my code assumed the value would never be less than 1.

You can confirm my guess by checking the actual value of vfindex under the conditions you believe are failing.

Without knowing what you want done with ficn if the extracted string is non-numeric, negative or 0, I don't know how to set the value of CNT.

Guessing further about this code:

I don't like lots of magic numbers in code, so all those IF statements look really ugly to me. Hard to understand and hard to maintain.
It appears that "vfindex" is a percentage and you're generating bars of "." characters with length proportional to the percentage, scaled to the width of a 132 character wide screen? Why not code that directly, and use the actual terminal width?

Find the width one at the beginning of your program:

$ width=F$GETDVI("SYS$COMMAND","DEVBUFSIZ")

Instead of the your GOSUB, use just one line:

$ ficn=F$EXTRACT(0,width,F$FAO("!"+F$STRING(F$INTEGER(F$EXTRACT(29,3,fi))*width/100)+"*."))

This gives better granularity than just 5 steps, and deals with invalid values (null string), and oversize values, limiting the string to the actual width of the screen(why extract 5 characters when you're presumably expecting a maximum of 3 digits?). This code will also accommodate to different screen widths. Remember 80 and 132 are artefacts of ancient Character Cell Terminal technology, most people use terminal emulators which can be set to arbitrary widths.

Since you're writing a prefix to the bar, you may want to adjust the width variable downwards to account for that.

$ width=F$GETDVI("SYS$COMMAND","DEVBUFSIZ")-prefix_width

Go a bit further and instead of parsing output, use F$GETDVI to determine your percentages.
A crucible of informative mistakes
Hoff
Honored Contributor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

I suspect some miscommunications here.

I'm interpreting your DCL code postings here as somewhat incomplete examples of what's going on within your application. If they're complete examples, then that ... stuff makes it appear otherwise.

That you're setting out telling me to ignore stuff is useful information but (and as the Inbox Zero folks are fond of) if you're not using something, get rid of it. Simplify. Yank it out of the DCL code for testing.

If you have complete DCL code, we can have a look at it.

More concise code is easier. The more you can prune out of your DCL code, the easier it is for us to look at and potentially solve this for you. (And given we're free labor and free technical support assistance, do you want to run up the effort involved of us, and potentially get your question ignored? I'd guess not, but I know a few folks that are rude, and I've certainly been accused of that, too.)

But this stuff is not intended as rude.

This is not intended to belittle your experience and skills.

If anything, following this same sequence and this pattern is something I do when I have bugs in my code; it helps me find them, and if the problem turns out to be a bug in somebody else's code, I have a concise reproducer I can hand them.

A reproducer which then gets me a fix back at best speed; the support folks are not spending their time testing and reproducing the bug and potentially also having difficulty reproducing the bug. Why might there be difficulty here? Because we all code differently; while I have made my share of mistakes in DCL and I'm very far from an expert in this DCL stuff, I've tried to learn from those DCL coding mistakes. And (ulterior motive) that also makes seeing your code more interesting, because I might learn from one of your mistakes, too.

I've shown my DCL work.

Please show yours.

Thanks.
Jan van den Ende
Honored Contributor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y

Edmundo,

>>>
$ SetCN: ! SUBROUTINE !
.
.
.
$ cnt = 0
$ wait 00:00:00.5
$ return
<<<

... but a called subroutine is new procedure level.

Replace
$ cnt = 0
by
$ cnt == 0

and cnt will now be global, and hence visible to the outer level.

hth

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Edmundo T Rodriguez
Frequent Advisor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y


Hello John Gillings, you hit right on the target
(not to say almost in the "Bulls-eye")

I am sorry I didn't provided all the following details before but I tough they were not so relevant base on my expectation
and base you response you prove it was not necessary.

The actual code is a little bit to long for displaying (140 lines) but the main idea is using the HP fragmentation report generator output and after picking the Volume index for each one of the disk then displaying the
index + an "X" in the line of the volume at the proper column depending based on the specific fragmentation group level provided by that application.

Note: This report need to work in INTERACTIVE and BATCH mode!


Example of the actual output (except for "X" value which I am looking for)


Volume FI excellent good fair poor bad
-----------------------------------------------------------------------
DSA0: 59.7 % |
DSA10: 80.4 % |
DSA20: 3.5 % |
DSA100: 97.9 % |
DSA150: 53.9 % |
DSA200: 47.8 % |
DSA250: 94.6 % |
DSA300: 25.6 % |
DSA400: 34.2 % |
DSA500: 13.7 % |
DSA600: 62.9 % |
DSA700: 81.3 % |
-----------------------------------------------------------------------
% 1-20.9 21-40.9 41-60.9 61-80.9 81-100
-----------------------------------------------------------------------


So yes, I am trying to to display an "X" in the pertinetn column for each disk (not a dottet line, that was an entry I did in the FAO declaration in order to see what was going on)

When the procedure pass through all those lines to associate the frag-index with a group level had the purpose to be straigh forward without considering any report setting besides 80 column (Naturally is much better the way you propose because it considers any variation on the end-user screen)

And YES, the result of the record extract "''fi'" doesn't need to be quoted
but was my idea that it could possibly be used as an string in the full stengh
of the screen line. (Not always the best)

And NO, the record extract can NOT be converted to integer at theat point because then the index is presented as "0" because the record string.

I will give it a try to your one line code and see how it works!

$ ficn=F$EXTRACT(0,width,F$FAO("!"+F$STRING(F$INTEGER(F$EXTRACT(29,3,fi))*width/100)+"*."))

Hein van den Heuvel
Honored Contributor

Re: if xyx .ge. n1 .and. xyz .lt. n2 then abc = y


You may also want to try:

$ CNT = f$elem( (vfindex-1)/20, ";", "26;37;49;61;73;73" )

Or with substitute:

$ CNT = f$elem( ('vfindex'-1)/20, ";", "26;37;49;61;73;73" )

Hein.