Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

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