1752587 Members
3906 Online
108788 Solutions
New Discussion юеВ

Re: DCL Scripting

 
Brett_59
Occasional Contributor

DCL Scripting - command procedure

What is the best way to read an input file that contains various records of configuration information, then assign each record as a replacement varable within a subsequent command procedure. An example would be great!Thanks, Brett

8 REPLIES 8
Jan van den Ende
Honored Contributor

Re: DCL Scripting

Brett,

This is a little too much appeal to my psychic powers!

Could you give an example file with ~ records, and jow you would like them changed?

As I read this, one interpretation could be a simple EDIT with global replace, another would be designing a complete text processor.

More detail, please!

Proost.

Have one on me.

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

Re: DCL Scripting

Brett,

Having done implementations along this line quite a few times, some more detail about precisely what is being attempted would be helpful.

In one case, I implemented an application analog to SYSGEN, with a fairly complete implementation of the computations to completely define users' queues, defaults, etc.

- Bob Gezelter, http://www.rlgsc.com
Hein van den Heuvel
Honored Contributor

Re: DCL Scripting


Brett, you'll need to provide some more concrete examples about what you are tryign to do, what the input might roughly look like, where/how the data obtained will be used.

Maybe you can just execute the config information, notably when written as "$ param = value"
Or when written as "param = value" using:

$loop:
$read/end=... file record
$'record
$goto loop

However, that is very uncontrolled and error prone.

So I turned up my mind reading power setting to the very max and came up with this....

Let's say you have a script needing a bunch of parameters like test_xxx = yyy

Create a file test.ini containing:

$ type test.ini
! here are the config overides
sleep = 12
scratch = some_device:

Now read that in a loop and do some basic validation. Like making sure there is an equal sign. Decide whether to ignore, or report bad lines.

Make the script for example be:
$ type test.com
$!default settings
$test_aap = "noot"
$test_scratch = "sys$login:"
$test_mies = 12345
$test_sleep = 999
$
$param_file = f$search("test.ini")
$if param_file.nes.""
$then
$close/nolog params
$open/error=init_done params 'param_file
$init_loop:
$ read/end=init_done params record
$ record = f$edit(record,"UNCOMMENT,COLLAPSE")
$ if record.nes.""
$ then
$ name = f$elem(0,"=",record)
$ value = f$elem(1,"=",record)
$ if value.eqs."" then goto init_loop
$ if f$type(value).eqs."INTEGER"
$ then
$ test_'name = 'value
$ else
$ test_'name = value
$ endif
$ endif
$ goto init_loop
$init_done:
$close/nolog params
$
$show symb test_*
$exit

And you'll get:

$ @test
TEST_AAP = "noot"
TEST_MIES = 12345 Hex = 00003039 Octal = 00000030071
TEST_SCRATCH = "some_device:"
TEST_SLEEP = 12 Hex = 0000000C Octal = 00000000014

No you can make that as fancy as needed.
Like you coudl test for existance (or not) for a symbol to be set. Check for quotes, or not. Check for presence in an (indexed) file. Protect against empty strings, Protect against bad names, and so on.

Or you could have sub-sections, say delimited by [section_name].
Example of that below.

hth,
Hein.

$
$ typ test.ini
! here are the config overides
[process_1]
sleep = 12
scratch = some_device:
[process_2]
sleep = 13


$
$ type test.com
$!default settings
$test_aap = "noot"
$test_scratch = "sys$login:"
$test_mies = 12345
$test_sleep = 999
$section = ""
$
$param_file = f$search("test.ini")
$if param_file.nes.""
$then
$close/nolog params
$open/error=init_done params 'param_file
$init_loop:
$ read/end=init_done params record
$ record = f$edit(record,"UNCOMMENT,COLLAPSE")
$ if record.nes.""
$ then
$ if f$extr(0,1,record).eqs."[" then section = f$extr(1,f$loc("]",record)-1,record) + "_"
$ name = f$elem(0,"=",record)
$ value = f$elem(1,"=",record)
$ if value.eqs."=" then goto init_loop
$ if f$type(value).eqs."INTEGER"
$ then
$ test_'section''name' = 'value
$ else
$ test_'section''name' = value
$ endif
$ endif
$ goto init_loop
$init_done:
$close/nolog params
$
$show symb test_*
$exit
$
$ @test
TEST_AAP = "noot"
TEST_MIES = 12345 Hex = 00003039 Octal = 00000030071
TEST_PROCESS_1_SCRATCH = "some_device:"
TEST_PROCESS_1_SLEEP = 12 Hex = 0000000C Octal = 00000000014
TEST_PROCESS_2_SLEEP = 13 Hex = 0000000D Octal = 00000000015
TEST_SCRATCH = "sys$login:"
TEST_SLEEP = 999 Hex = 000003E7 Octal = 00000001747

Hoff
Honored Contributor

Re: DCL Scripting

Some options:

- using an implementation environment other than DCL? (DCL has its place, but it's also a comparatively blunt weapon.)

- using XML or another format suited for the data transfer and data manipulation. (There are tools around to deal with XML for you.)

- reading the data in using a standard DCL "read until EOF" loop (as Hein shows in his reply, and as examples are available elsewhere), and defining a logical name or a global symbol for the data?

- through more formal assistance with your DCL coding requirements?

- with a look at the OpenVMS User's Guide or (if you can find a copy) my Writing Real Programs in DCL?

- by re-architecting the particular problem here to avoid this cascading requirement? Could be use of an indexed file, or otherwise. (Inter-procedural dependencies using global symbols and logical names to propogate data can tend to lead to odd errors, as the approach is non-reentrant, subtle, and comparatively tough to clean up on errors.)

I'm sure I've missed an option or three...

Stephen Hoffman
HoffmanLabs LLC
Brett_59
Occasional Contributor

Re: DCL Scripting

I currently have a job scheduler that passes 8 parameters to a command procedure, which assigns the values as symbols to eliminate any hard coding. The problem is that I need to increase the number of parameters being passed to the command procedure, which exceeds the limit of the job scheduler.

What I would like to do is modify the command procedure to initially read in a file that contains parameter information (12 records) and then use the values within the command procedure.
Example of command procedure:
$ username = P1
$ business_model_instance = P2
$ warehouse_model_instance = P3
$ bit_string = P4
$ environment = P5
$ ods_admin = P6
$ warehouse_admin = P7

! Production or Development?
$!
$ @wipdss_base_root:[config]wipdss_env.com 'environment

Thanks, Brett
Hoff
Honored Contributor

Re: DCL Scripting

If the symbols are short, cram them into the existing parameters.

Multiplex one or more the available P1 through P8.

You can use f$element and such to process a | or , or # separated list within a parameter, and reconstitute the parameters.

Another option is to use a small temporary file, say MY_XYZ_pid.TMP or some other unique value, and write out the parameters there. You can use a format such as:

$ MY_FOO=xyz
$ MY_BAR=pdq
$ MY_THIS=here

The sneaky trick is that you can then @ the file, and use the values. (AUTOGEN uses a form of this.) This isolates you from previous runs and dreck left around in the global symbol tables, and allows you to isolate and test and verify the procedures.

If you do this, I'd suggest use of a prefix on the soon-to-be symbols such as MY_ or PARAM_ (or whatever) to visually identify the source of the symbols.

You can also open the file and process the values directly using implicit parameter labeling. Parameter P1 could be the first line read, and Pn the last. SMOP.

I'd not pass stuff around using global symbols or shared logical names. That's a very inviting, but much harder to keep a lid on it all. The dependencies get far tougher to locate.

OPEN, CLOSE, READ and WRITE are standard DCL commands, and there are a gazillion examples around. I would encourage a look at the OpenVMS User's Guide and other materials that introduce DCL programming, as well. When working with DCL, you'll receive a larger benefit than the time that was originally spent skimming the manuals.

And one wrinkle:

Before you OPEN a file, always issue a CLOSE /NOLOG on the channel. This because DCL can hold a file open, and will pick up where it left off if several OPEN commands are aimed at the same file. CLOSE /NOLOG avoids this.

Here's a trivial file read loop:

$ CLOSE/NOLOG iochan
$ OPEN/READ iochan SYS$SCRATCH:XYZ.TMP
$LOOP:
$ READ/END=EOF iochan data
$ WRITE SYS$OUTPUT "Data <''data'>"
$ GOTO LOOP
$DONE:
$ EXIT

--

Stephen Hoffman
HoffmanLabs LLC
Jan van den Ende
Honored Contributor

Re: DCL Scripting

@ Hoff:

>>>
$ READ/END=EOF iochan data
$ WRITE SYS$OUTPUT "Data <''data'>"
$ GOTO LOOP
$DONE:
<<<

Slight, but relevant nitpickings:

At END_OF_FILE you specify to proceed to lable EOF.

But instead of EOF: you expect DONE: to provide the loop exit.
Secondly, it is considered real bad habit to NOT close a file after finishing with it!

fwiw

Proost.

Have one on me.

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

Re: DCL Scripting

Ok, so I'm composing DCL in a 48x18 window without a test run.