For Programmers: Free Programming Magazines  


Home > Archive > Cobol > July 2007 > unstring empty string









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author unstring empty string
Frank Swarbrick

2007-07-27, 6:55 pm

Something unexpected (to me). Consider the following code, which is used to
unstring key/value pair parameters and deal with them one by one.

WORKING-STORAGE SECTION.
01 WS-INIT-PARM.
05 PIC X OCCURS 0 TO 60 DEPENDING ON WS-INIT-PARM-LEN.

PROCEDURE DIVISION.
0010-CHECK-INITPARMS.
MOVE 1 TO PPTR
PERFORM WITH TEST AFTER UNTIL END-OF-PARMS
UNSTRING WS-INIT-PARM
DELIMITED BY ', ' OR SPACES OR ','
INTO PARM, COUNT IN PARM-LEN
WITH POINTER PPTR
NOT ON OVERFLOW
SET END-OF-PARMS TO TRUE
END-UNSTRING
PERFORM 0011-CHECK-PARM
END-PERFORM
EXIT.

0011-CHECK-PARM.
UNSTRING PARM DELIMITED BY '=' INTO PARM-NAME, PARM-VALUE
EVALUATE PARM-NAME
WHEN 'SYSTYPE'
MOVE PARM-VALUE TO PARM-SYS
WHEN 'ATMSYS'
MOVE PARM-VALUE TO PARM-ATMSYS
END-EVALUATE
EXIT.

This works except in the case where WS-INIT-PARM-LEN = ZERO (meaning there
are no parms). I would have expected that, not only are PARM and PARM-LEN
not set (they aren't), but that the "NOT ON OVERFLOW" branch would be taken
immediately. This was not the case. In fact the OVERFLOW condition was set
immediately (I verified this by adding the "ON OVERFLOW" clause and saw that
it took that branch instead).

I won't claim that this does not follow the standard, because it appears to.
From ISO/IEC 1989:2002(E), 14.8.44.3:

"15) Either of the following situations causes an overflow condition:
a) An UNSTRING is initiated, and the value in the data item referenced by
identifier-7 is less than 1 or greater
than the number of character positions described for the data item
referenced by identifier-1.
b) If, during execution of an UNSTRING statement, all receiving areas have
been acted upon, and the data
item referenced by identifier-1 contains characters that have not been
examined."

With in the example above identifier-7 refers to PPTR and identifier-1
refers to WS-INIT-PARM. PPTR of 1 is greater than the number of character
positions referenced by WS-INIT-PARM (zero).

I guess it kind of makes sense, in that it doesn't make all that much sense
to attempt to unstring an empty string, but I would have liked it to work
otherwise (NOT ON OVERFLOW, which to me means there is no data left to
unstring). Instead I have to add an extra IF WS-INIT-PARM = ZERO to bypass
the unstring altogether.

Ah well. Just posting this for the heck of it. I don't expect to find any
other alternatives, though it be interested to hear one.

Other alternatives I tried were:
Make WS-INIT-PARM just a regular PIC X(60), initialized to spaces. In this
case it worked, but ended up performing the UNSTRING 60 times. Yuck!

I also tried the above, but initializing to LOW-VALUES instead of spaces.
This works OK, I guess. It does UNSTRING only once, setting PARM to all
LOW-VALUES and PARM-LEN to 60. The "NOT ON UNSTRING" condition is set.
Still, I think the ODO method is the most elegant, if not for the fact that
it doesn't work exactly as I want (as stated above).

Ah well!

Frank

Frank Swarbrick

2007-07-27, 6:55 pm

>>> On 7/27/2007 at 10:01 AM, in message
<46A9C297.6F0F.0085.0@efirstbank.com>,
Frank Swarbrick<Frank.Swarbrick@efirstbank.com> wrote:
> Something unexpected (to me). Consider the following code, which is used


> to
> unstring key/value pair parameters and deal with them one by one.
>
> WORKING-STORAGE SECTION.
> 01 WS-INIT-PARM.
> 05 PIC X OCCURS 0 TO 60 DEPENDING ON WS-INIT-PARM-LEN.
>
> PROCEDURE DIVISION.
> 0010-CHECK-INITPARMS.
> MOVE 1 TO PPTR
> PERFORM WITH TEST AFTER UNTIL END-OF-PARMS
> UNSTRING WS-INIT-PARM
> DELIMITED BY ', ' OR SPACES OR ','
> INTO PARM, COUNT IN PARM-LEN
> WITH POINTER PPTR
> NOT ON OVERFLOW
> SET END-OF-PARMS TO TRUE
> END-UNSTRING
> PERFORM 0011-CHECK-PARM
> END-PERFORM
> EXIT.
>
> 0011-CHECK-PARM.
> UNSTRING PARM DELIMITED BY '=' INTO PARM-NAME, PARM-VALUE
> EVALUATE PARM-NAME
> WHEN 'SYSTYPE'
> MOVE PARM-VALUE TO PARM-SYS
> WHEN 'ATMSYS'
> MOVE PARM-VALUE TO PARM-ATMSYS
> END-EVALUATE
> EXIT.


For what it's worth, I was able to simplify this as follows:

0010-CHECK-INITPARMS.
MOVE 1 TO PPTR
PERFORM UNTIL PPTR > FUNCTION LENGTH(WS-INIT-PARM)
UNSTRING WS-INIT-PARM
DELIMITED BY ', ' OR SPACES OR ','
INTO PARM, COUNT IN PARM-LEN
WITH POINTER PPTR
END-UNSTRING
PERFORM 0011-CHECK-PARM
END-PERFORM
EXIT.

Not only do I avoid the annoying check for a length of zero (not present in
the example above), but I also got rid of the END-OF-PARMS flag.
I'm pretty happy with this now. Thanks for listening!

Frank

Louis Krupp

2007-07-27, 6:55 pm

Frank Swarbrick wrote:
<snip>
> DELIMITED BY ', ' OR SPACES OR ','

<snip>

So you recognize (1) a comma, (2) a comma followed by a space, or (3)
any number of spaces... What happens when someone follows a comma with
more than one space? (They're going to do that, you know.)

Louis
Howard Brazee

2007-07-27, 6:55 pm

On Fri, 27 Jul 2007 13:16:23 -0600, Louis Krupp
<lkrupp@pssw.nospam.com.invalid> wrote:

><snip>
><snip>
>
>So you recognize (1) a comma, (2) a comma followed by a space, or (3)
>any number of spaces... What happens when someone follows a comma with
>more than one space? (They're going to do that, you know.)


That's pretty much why I have moved from UNSTRING to reference
modification now that it's available. Reference Modification isn't
in the spirit of CoBOL, but it is quick, flexible, and obvious.
Richard

2007-07-27, 6:55 pm

On Jul 28, 4:46 am, "Frank Swarbrick" <Frank.Swarbr...@efirstbank.com>
wrote:
>
> <46A9C297.6F0F.008...@efirstbank.com>,
>
>
>
> Frank Swarbrick<Frank.Swarbr...@efirstbank.com> wrote:
>
>
>
>
> For what it's worth, I was able to simplify this as follows:
>
> 0010-CHECK-INITPARMS.
> MOVE 1 TO PPTR
> PERFORM UNTIL PPTR > FUNCTION LENGTH(WS-INIT-PARM)


OR WS-Init-Parm(PPtr:) = SPACES

> UNSTRING WS-INIT-PARM
> DELIMITED BY ', ' OR SPACES OR ','
> INTO PARM, COUNT IN PARM-LEN
> WITH POINTER PPTR
> END-UNSTRING
> PERFORM 0011-CHECK-PARM
> END-PERFORM
> EXIT.


I would have used 'ALL SPACES'

Also you need to space fill Parm and Parm-Name and Parm-Value before
each appropriate UNSTRING.


Rick Smith

2007-07-27, 6:55 pm


"Louis Krupp" <lkrupp@pssw.nospam.com.invalid> wrote in message
news:13akh4r5ku4kv8f@corp.supernews.com...
> Frank Swarbrick wrote:
> <snip>
> <snip>
>
> So you recognize (1) a comma, (2) a comma followed by a space, or (3)
> any number of spaces... What happens when someone follows a comma with
> more than one space? (They're going to do that, you know.)


Mr Krupp, your item 3 is not correct. Despite the plural form,
in the context of an UNSTRING statement, the literal SPACES
means one occurence; ALL SPACES is the expression for
"any number of spaces". See the General Rules for the
UNSTRING statement.

Interestingly, this is a case where a regular expression
becomes handy. For example, ...

DELIMITED BY R'(,[:space:]*)|([:space:]+)'

Where R' (or R") introduces a regular expression, which, in
this case, means either, a comma followed by zero or more
spaces, or, alternatively, one or more spaces (ALL SPACES).

Of course, this form of regular expression is not available in
COBOL; but, I have begun work on a proposal for adding
it to the standard. I just don't know when I will finish, or
whether WG4 will look at the proposal favorably.



Frank Swarbrick

2007-07-27, 6:55 pm

>>> On 7/27/2007 at 2:17 PM, in message
<13akkrq1tvm42bf@corp.supernews.com>,
Rick Smith<ricksmith@mfi.net> wrote:

> "Louis Krupp" <lkrupp@pssw.nospam.com.invalid> wrote in message
> news:13akh4r5ku4kv8f@corp.supernews.com...
>
> Mr Krupp, your item 3 is not correct. Despite the plural form,
> in the context of an UNSTRING statement, the literal SPACES
> means one occurence; ALL SPACES is the expression for
> "any number of spaces". See the General Rules for the
> UNSTRING statement.
>
> Interestingly, this is a case where a regular expression
> becomes handy. For example, ...
>
> DELIMITED BY R'(,[:space:]*)|([:space:]+)'
>
> Where R' (or R") introduces a regular expression, which, in
> this case, means either, a comma followed by zero or more
> spaces, or, alternatively, one or more spaces (ALL SPACES).
>
> Of course, this form of regular expression is not available in
> COBOL; but, I have begun work on a proposal for adding
> it to the standard. I just don't know when I will finish, or
> whether WG4 will look at the proposal favorably.


Certainly an interesting idea. I find regular expressions to be pretty
unreadable, but they certainly are powerful. I guess as long as you can
write it it doesn't matter too much that you can't read it! Plus I'm sure
if I actually made much use of them I'd get more used to them.

Frank

Frank Swarbrick

2007-07-27, 6:55 pm

OK, here's the latest and greatest, taking some suggestions, and not taking
others (see below for why).

ID DIVISION.
PROGRAM-ID. UNSTR.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-INIT-PARM-LEN PIC S9(4) BINARY.
01 WS-INIT-PARM.
05 PIC X OCCURS 0 TO 60 DEPENDING ON WS-INIT-PARM-LEN.
01 PARMS-STUFF.
05 PPTR PIC S9(3) COMP.
05 PARM PIC X(60).
05 PARM-LEN PIC S9(3) COMP-3.
05 PARM-NAME PIC X(60).
05 PARM-NAME-LEN PIC S9(4) COMP.
05 PARM-VALUE PIC X(60).
05 PARM-VAL-LEN PIC S9(4) COMP.
05 PARM-DELIM PIC X.
05 PARM-SYS PIC X VALUE LOW-VALUES.
88 PARM-SYS-IS-DEV VALUES 'D' 'X' 'T'.
05 PARM-ATMSYS PIC X(4) VALUE LOW-VALUES.

LINKAGE SECTION.
01 INPUT-PARM.
05 INPUT-LEN PIC S9(4) COMP.
05 INPUT-DATA PIC X(80).

PROCEDURE DIVISION USING INPUT-PARM.
MOVE INPUT-LEN TO WS-INIT-PARM-LEN
MOVE INPUT-DATA TO WS-INIT-PARM
DISPLAY '(' WS-INIT-PARM ')'
PERFORM 0010-CHECK-INITPARMS
IF PARM-SYS = LOW-VALUES
DISPLAY 'SYSTYPE NOT SET'
ELSE
DISPLAY 'SYSTYPE = ' PARM-SYS
END-IF
IF PARM-ATMSYS = LOW-VALUES
DISPLAY 'ATMSYS NOT SET'
ELSE
DISPLAY 'ATMSYS = ' PARM-ATMSYS
END-IF
STOP RUN.

0010-CHECK-INITPARMS.
MOVE 1 TO PPTR
PERFORM UNTIL PPTR > FUNCTION LENGTH(WS-INIT-PARM)
UNSTRING WS-INIT-PARM
DELIMITED BY ',' OR ALL SPACES
INTO PARM, COUNT IN PARM-LEN
WITH POINTER PPTR
END-UNSTRING
PERFORM 0011-CHECK-PARM
END-PERFORM
EXIT.

0011-CHECK-PARM.
IF PARM-LEN > ZERO
UNSTRING PARM
DELIMITED BY '=' OR ALL SPACES
INTO PARM-NAME, DELIMITER IN PARM-DELIM
PARM-VALUE
IF PARM-DELIM = '='
EVALUATE PARM-NAME
WHEN 'SYSTYPE'
MOVE PARM-VALUE TO PARM-SYS
WHEN 'ATMSYS'
MOVE PARM-VALUE TO PARM-ATMSYS
END-EVALUATE
ELSE
DISPLAY 'IGNORING INVALID KW/VAL PAIR'
END-IF
ELSE
DISPLAY 'IGNORING PARM-LEN ZERO'
END-IF
EXIT.

END PROGRAM UNSTR.


Here is the output from many test cases (separated by
'---------------------------')
(SYSTYPE=D,ATMSYS=TAT2)
SYSTYPE = D
ATMSYS = TAT2
---------------------------
(SYSTYPE=D ATMSYS=TAT2)
SYSTYPE = D
ATMSYS = TAT2
---------------------------
(SYSTYPE=D ATMSYS=TAT2)
SYSTYPE = D
ATMSYS = TAT2
---------------------------
(SYSTYPE=D, ATMSYS=TAT2)
IGNORING PARM-LEN ZERO
SYSTYPE = D
ATMSYS = TAT2
---------------------------
(SYSTYPE=D ATMSYS=)
SYSTYPE = D
ATMSYS =
---------------------------
(SYSTYPE=D ATMSYS)
IGNORING INVALID KW/VAL PAIR
SYSTYPE = D
ATMSYS NOT SET
---------------------------
(SYSTYPE= ATMSYS=)
SYSTYPE =
ATMSYS =
---------------------------
(SYSTYPE ATMSYS=ABCD)
IGNORING INVALID KW/VAL PAIR
SYSTYPE NOT SET
ATMSYS = ABCD
---------------------------
(SYSTYPE ATMSYS)
IGNORING INVALID KW/VAL PAIR
IGNORING INVALID KW/VAL PAIR
SYSTYPE NOT SET
ATMSYS NOT SET
---------------------------
(SYSTYPE=D,ATMSYS=TAT2,,,)
IGNORING PARM-LEN ZERO
IGNORING PARM-LEN ZERO
SYSTYPE = D
ATMSYS = TAT2
---------------------------
( SYSTYPE=D ATMSYS=TAT2 )
IGNORING PARM-LEN ZERO
SYSTYPE = D
ATMSYS = TAT2
---------------------------
(=D ATMSYS=TAT2 )
SYSTYPE NOT SET
ATMSYS = TAT2

All of the test results meet my expectations. Obviously, I may have missed
a necessary test.

Anyway, I ended up not initializing PARM, PARM-NAME and PARM-VALUE, as
suggested by Richard. Here are my reasons:

PARM will always be set by the primary unstring because (my observation is)
the first target always gets set to a value, even if it just spaces.

For PARM-NAME and PARM-VALUE I'm instead depending on the '=' delimiter
between the keyword and the value. If the delimiter is not present I simply
ignore the results. It does not matter at this point if PARM-VALUE was not
initialized, since I am not checking it. On the other hand, if the '='
delimiter is present then PARM-VALUE will always be set during the unstring,
therefore no need to initialize.

Not that it would hurt me to initialize these fields. I just choose to be
stubborn! :-)

I did utilize ALL SPACES instead of just spaces. I also eliminated the
check of ', ' (comma/space), since it really isn't necessary (though could
save one UNSTRING iteration if present).

There's doesn't seem to be a need for me to check WS-Init-Parm(PPtr:) =
SPACES. The environment strips trailing spaces automatically. (And even if
it didn't I would think the ALL SPACES delimiter would handle it.)

With regard to using reference modification, I think that, as slightly
convoluted as my code ended up being I think it probably worked out better.
Not that I don't use ref-mod. Just not in this case.

Thanks for the hints! I don't enjoy COBOL all the time, but it can
occasionally be fun. :-)

Frank

Doug Miller

2007-07-27, 6:55 pm

In article <46AA1FC7.6F0F.0085.0@efirstbank.com>, "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote:
>
>All of the test results meet my expectations. Obviously, I may have missed
>a necessary test.


Here are a few more I think you should try:

(SYSTYPE=D,,,,ATMSYS=TAT2)
(SYSTYPE= D,ATMSYS=TAT2)
(SYSTYPE = D, ATMSYS = TAT2)
(SYSTYPE = D ATMSYS = TAT2)
(SYSTYPE=D,JUNK, ATMSYS=TAT2)
(SYSTYPE=D, JUNK ATMSYS=TAT2)
(SYSTYPE=D JUNK ATMSYS=TAT2)
(SYSTYPE=D JUNK,ATMSYS=TAT2)

--
Regards,
Doug Miller (alphag at milmac dot com)

It's time to throw all their damned tea in the harbor again.
Frank Swarbrick

2007-07-27, 9:55 pm

>>> On 7/27/2007 at 4:52 PM, in message
<PGuqi.29229$2v1.8277@newssvr14.news.prodigy.net>, Doug
Miller<spambait@milmac.com> wrote:
> In article <46AA1FC7.6F0F.0085.0@efirstbank.com>, "Frank Swarbrick"
> <Frank.Swarbrick@efirstbank.com> wrote:
> missed
>
> Here are a few more I think you should try:
>
> (SYSTYPE=D,,,,ATMSYS=TAT2)
> (SYSTYPE= D,ATMSYS=TAT2)
> (SYSTYPE = D, ATMSYS = TAT2)
> (SYSTYPE = D ATMSYS = TAT2)
> (SYSTYPE=D,JUNK, ATMSYS=TAT2)
> (SYSTYPE=D, JUNK ATMSYS=TAT2)
> (SYSTYPE=D JUNK ATMSYS=TAT2)
> (SYSTYPE=D JUNK,ATMSYS=TAT2)


--------------------------
(SYSTYPE=D,,,,ATMSYS=TAT2)
IGNORING PARM-LEN ZERO
IGNORING PARM-LEN ZERO
IGNORING PARM-LEN ZERO
SYSTYPE = D
ATMSYS = TAT2
--------------------------
(SYSTYPE= D,ATMSYS=TAT2)
IGNORING INVALID KW/VAL PAIR
SYSTYPE =
ATMSYS = TAT2
--------------------------
(SYSTYPE = D, ATMSYS = TAT2)
IGNORING INVALID KW/VAL PAIR
IGNORING INVALID KW/VAL PAIR
IGNORING PARM-LEN ZERO
IGNORING INVALID KW/VAL PAIR
IGNORING INVALID KW/VAL PAIR
SYSTYPE NOT SET
ATMSYS NOT SET
--------------------------
(SYSTYPE = D ATMSYS = TAT2)
IGNORING INVALID KW/VAL PAIR
IGNORING INVALID KW/VAL PAIR
IGNORING INVALID KW/VAL PAIR
IGNORING INVALID KW/VAL PAIR
SYSTYPE NOT SET
ATMSYS NOT SET
--------------------------
(SYSTYPE=D,JUNK, ATMSYS=TAT2
IGNORING INVALID KW/VAL PAIR
IGNORING PARM-LEN ZERO
SYSTYPE = D
ATMSYS = TAT2
--------------------------
(SYSTYPE=D, JUNK ATMSYS=TAT2
IGNORING PARM-LEN ZERO
IGNORING INVALID KW/VAL PAIR
SYSTYPE = D
ATMSYS = TAT2
--------------------------
(SYSTYPE=D JUNK ATMSYS=TAT2)
IGNORING INVALID KW/VAL PAIR
SYSTYPE = D
ATMSYS = TAT2
--------------------------
(SYSTYPE=D JUNK,ATMSYS=TAT2)
IGNORING INVALID KW/VAL PAIR
SYSTYPE = D
ATMSYS = TAT2

All look good to me. Of course I'm just ignoring the ones that have spaces
before and/or after the equals sign, but I'm OK with that.

Thanks for the suggestions!

Frank

Doug Miller

2007-07-28, 3:55 am

In article <46AA3A09.6F0F.0085.0@efirstbank.com>, "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote:
><PGuqi.29229$2v1.8277@newssvr14.news.prodigy.net>, Doug
>Miller<spambait@milmac.com> wrote:
>
>--------------------------
>(SYSTYPE=D,,,,ATMSYS=TAT2)
>IGNORING PARM-LEN ZERO
>IGNORING PARM-LEN ZERO
>IGNORING PARM-LEN ZERO
>SYSTYPE = D
>ATMSYS = TAT2


Looks good.

>--------------------------
>(SYSTYPE= D,ATMSYS=TAT2)
>IGNORING INVALID KW/VAL PAIR
>SYSTYPE =
>ATMSYS = TAT2


Looks like an 'oopsie' to me...

>--------------------------
>(SYSTYPE = D, ATMSYS = TAT2)
>IGNORING INVALID KW/VAL PAIR
>IGNORING INVALID KW/VAL PAIR
>IGNORING PARM-LEN ZERO
>IGNORING INVALID KW/VAL PAIR
>IGNORING INVALID KW/VAL PAIR
>SYSTYPE NOT SET
>ATMSYS NOT SET


I'd call that another one.

>--------------------------
>(SYSTYPE = D ATMSYS = TAT2)
>IGNORING INVALID KW/VAL PAIR
>IGNORING INVALID KW/VAL PAIR
>IGNORING INVALID KW/VAL PAIR
>IGNORING INVALID KW/VAL PAIR
>SYSTYPE NOT SET
>ATMSYS NOT SET


And that.

>--------------------------
>(SYSTYPE=D,JUNK, ATMSYS=TAT2
>IGNORING INVALID KW/VAL PAIR
>IGNORING PARM-LEN ZERO
>SYSTYPE = D
>ATMSYS = TAT2
>--------------------------
>(SYSTYPE=D, JUNK ATMSYS=TAT2
>IGNORING PARM-LEN ZERO
>IGNORING INVALID KW/VAL PAIR
>SYSTYPE = D
>ATMSYS = TAT2
>--------------------------
>(SYSTYPE=D JUNK ATMSYS=TAT2)
>IGNORING INVALID KW/VAL PAIR
>SYSTYPE = D
>ATMSYS = TAT2
>--------------------------
>(SYSTYPE=D JUNK,ATMSYS=TAT2)
>IGNORING INVALID KW/VAL PAIR
>SYSTYPE = D
>ATMSYS = TAT2
>
>All look good to me. Of course I'm just ignoring the ones that have spaces
>before and/or after the equals sign, but I'm OK with that.


IMO, you shouldn't be, because that's a *very* likely anomaly in your input.

>Thanks for the suggestions!
>
>Frank
>


--
Regards,
Doug Miller (alphag at milmac dot com)

It's time to throw all their damned tea in the harbor again.
Louis Krupp

2007-07-28, 7:55 am

Rick Smith wrote:
> "Louis Krupp" <lkrupp@pssw.nospam.com.invalid> wrote in message
> news:13akh4r5ku4kv8f@corp.supernews.com...
>
> Mr Krupp, your item 3 is not correct. Despite the plural form,
> in the context of an UNSTRING statement, the literal SPACES
> means one occurence; ALL SPACES is the expression for
> "any number of spaces". See the General Rules for the
> UNSTRING statement.

<snip>

Thanks; I stand corrected...

Louis
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com