Dot rules in nested conditional statements - COBOL - cobol

I'm wondering if anybody can explain to me the dot ruling in nested IF statements in COBOL. Example:
*The first if statement*
IF SUCCESSFUL-STATUS
PERFORM 8300-REPL-LNNTBI00
THRU 8300-REPL-LNNTBI00-EXIT
*The second if statement*
IF SUCCESSFUL-STATUS
DISPLAY 'RECORD ALREADY UPDATED :' WS-INF-REC
ELSE
DISPLAY 'UPDATE ERROR : ' WS-INF-REC ' / '
WS-RETURN-STATUS
READ INFILE INTO WS-INF-REC.
Which if statement does the dot placed after "WS-INF-REC" belong to? The first IF or the second IF-ELSE? I know that in most programming, it should be for the last if statement but just to make sure, is it the same for COBOL?

AFAIR a period always closes ALL preceding statements - regardless wether they are IF, PERFORM or whatever - so in your case the first IF-statement is closed as well. And since periods are so small and easily overlooked I use the following rule:
Avoid using periods, they are evil!
Only put a period where it is strictly required by the syntax rules and nowhere else. Use explicit scope-terminators like END-IF or END-PERFORM. They make your code more readable and clearly structured while periods tend to generate confusion because of multiple closures and their habit of hiding in plain view.

The period character "." ends all if statements. Remember that spacing is ignored by the compiler so therefore the READ statement is part of the ELSE of the second IF statement.
Us humans want to see the indentation used logically. And, if it were me, I would make the end-if's be explicit. I tend to have one period per paragraph:
* The first if statement *
IF SUCCESSFUL-STATUS
PERFORM 8300-REPL-LNNTBI00
THRU 8300-REPL-LNNTBI00-EXIT
* The second if statement*
IF SUCCESSFUL-STATUS
DISPLAY 'RECORD ALREADY UPDATED :' WS-INF-REC
ELSE
DISPLAY 'UPDATE ERROR : ' WS-INF-REC ' / '
WS-RETURN-STATUS
READ INFILE INTO WS-INF-REC
END-IF
END-IF
.

This is really bad, very archaic Cobol, but how it behaves is like this:
*The first if statement*
IF SUCCESSFUL-STATUS
PERFORM 8300-REPL-LNNTBI00
THRU 8300-REPL-LNNTBI00-EXIT
*The second if statement*
IF SUCCESSFUL-STATUS
DISPLAY 'RECORD ALREADY UPDATED :' WS-INF-REC
ELSE
DISPLAY 'UPDATE ERROR : ' WS-INF-REC ' / ' WS-RETURN-STATUS
READ INFILE INTO WS-INF-REC
END-IF ## from period
END-IF ## from period

Related

Delphi 5 Use Pos / PosIgnoreCase for whole words only

I know Delphi 5 is really old but I have no other choice for now because my employer doesn't want to change, so I am stuck with old functions etc.
I would like to know if there was a way to get the position of the whole words I am looking for:
I have a list of words (if, then, else, and etc) named KEYWORDS, and for each word in it I have to check in every .pas file if this word contains some uppercase characters.
On my code, I am reading each line, and for each line, I am using this to find if I find any word in the list and if it has some uppercase characters:
if(PosIgnoreCase(KEYWORDS[I], S) <> Pos(KEYWORDS[I], S)) //Then the keyword has some uppercases in this line and I must raise an error
My problem is that if I use some words that contains the keywords ( for example "MODIFICATION") this will detect the uppercase IF in it and raise an error
I tried using if(PosIgnoreCase(' ' + KEYWORDS[I] + ' ', S) <> Pos(' ' + KEYWORDS[I] + ' ', S))
but there may be some parentheses or other characters instead of the spaces so I would like to avoid making a new condition for each character.
Is there a clean way to do it ? I found myself struggling quite often with the lack of functions in Delphi 5
Sorry if my question is somewhat confusing, english is not my first language.
Thank you for your time.
Update (from comments):
My list of keywords only contains the reserved keywords on Delphi

How to leave a section before the end without a goto statement

In cobol a section (similar to a function in c) can look like this:
abc section.
command a
command b
if a = 4
go to abc-end
end-if
command c
command d.
abc-end.
exit.
Until now, the only possibility for me to leave the section before the end (on a = 4), was with the command "goto".
Is there any other way to do it without goto?
Thanks in advance for any help!
From the draft, FCD 1.0(E) 2010-08-06
The EXIT PARAGRAPH and EXIT SECTION statements provide a means of exiting a
structured procedure without executing any of the following statements within
the procedure.
Like this for your example.
abc section.
command a
command b
if a NOT EQUAL TO 4
command c
command d
end-if
.
Like this for something invented but with names to help grasp the thing.
30D-UNPACK-CRATE SECTION.
PERFORM 30DA-COMMON-PER-CRATE
IF NOT STANDARD-CRATE
PERFORM 30DD-NON-STANDARD-CRATE
END-IF
.
or
30D-UNPACK-CRATE SECTION.
PERFORM 30DA-COMMON-PER-CRATE
IF SPECIAL-CRATE
PERFORM 30DD-NON-STANDARD-CRATE
END-IF
.
This uses 88-level Condition Names, so might be
88 STANDARD-CRATE VALUE "A" THRU "D" "J" "2".
88 SPECIAL-CRATE VALUE "X" "Z".
Again, just examples.
Apart from the fact that you are already using SECTIONs (and if you have a SECTION all the paragraphs before the next section belong to that, so you can't have isolated paragraphs) the above could either be a SECTION or a paragraph. No need for PERFORM .... THRU ... or the ... SECTION. Except for local standards... and, with SECTIONs, how the program is already coded.
EXIT PARAGRAPH and EXIT SECTION.
These may or may not be available on thee compiler that you are using.
Be aware that they are functionally equivalent to a GO TO, with some caveats, so replacing GO TOs by them will give a false sense of... I don't know what, but it'll be false.
PERFORM THE-FIRST
THE-FIRST SECTION.
TF-1.
some code
.
TF-2.
some code
.
TF-9.
some code
.
Different program:
PERFORM A-PARAGRAPH THRU AP-9
A-PARAGRAPH.
some code
.
AP-1.
some code
.
AP-9.
some code
.
Often you will find the final paragraph of a SECTION just contains EXIT (and be aware that EXIT generates no code, it is just a placeholder) and a similar situation with PERFORM ... THRU ....
Usually PERFORM ... THRU ... will only contain two paragraphs, but there is nothing except local standards which says it is so.
EXIT SECTION will "GO TO" an assumed CONTINUE statement immediately prior to the full-stop/period which terminates the SECTION.
EXIT PARAGRAPH will "GO TO" an assumed CONTINUE statement immediately prior to the full-stop/period which terminates the paragraph
If EXIT PARAGRAPH is used within a SECTION, or within the range of a PERFORM ... THRU ... which contains more than one paragraph excluding any that solely uses EXIT, it will probably not work as the author expects nor as the next reader expects.
THE-FIRST SECTION.
TF-1.
some code
IF condition
EXIT PARAGRAPH
END-IF
some more code
IF condition
EXIT SECTION
END-IF
some more code
<EXIT PARAGRAPH will arrive here>
.
TF-2.
some code
.
TF-9.
some code
<EXIT SECTION will arrive here>
.
A-PARAGRAPH.
some code
IF condition
EXIT PARAGRAPH (a - just descriptive, not syntax)
END-IF
some more code
<EXIT PARAGRAPH (a) will arrive here>
.
AP-1.
some code
IF condition
EXIT PARAGRAPH (b - just descriptive, not syntax)
END-IF
some more code
<EXIT PARAGRAPH (b) will arrive here>
.
AP-9.
some code
.
So, if using EXIT PARAGRAPH in a SECTION or in a PERFORM ... THRU ... with more than one paragraph containing other than a single EXIT, then you're creating a potentially worse situation than using a plain GO TO (where it is blindingly obvious what the intended destination of the branch is) whilst using a construct which looks to be "structured".

When to use dots in COBOL?

I'm completely new to COBOL, and I'm wondering:
There seems to be no difference between
DISPLAY "foo"
and
DISPLAY "foo".
What does the dot at the end of a line actually do?
When should I use/avoid it?
The period ends the "sentence." It can have an effect on your logic. Consider...
IF A = B
PERFORM 100-DO
SET I-AM-DONE TO TRUE.
...and...
IF A = B
PERFORM 100-DO.
SET I-AM-DONE TO TRUE
The period ends the IF in both examples. In the first, the I-AM-DONE 88-level is set conditionally, in the second it is set unconditionally.
Many people prefer to use explicit scope terminators and use only a single period, often on a physical line by itself to make it stand out, to end a paragraph.
I'm typing this from memory, so if anyone has corrections, I'd appreciate it.
Cobol 1968 required the use of a period to end a division name, procedure division paragraph name, or procedure division paragraph. Each data division element ended with a period.
There were no explicit scope terminators in Cobol 68, like END-IF. A period was also used to end scope. Cobol 1974 brought about some changes that didn't have anything to do with periods.
Rather than try to remember the rules for periods, Cobol programmers tended to end every sentence in a Cobol program with a period.
With the introduction of scope terminators in Cobol 1985, Cobol coders could eliminate most of the periods within a procedure division paragraph. The only periods required in the procedure division of a Cobol 85 program are the to terminate the PROCEDURE DIVISION statement, to terminate code (if any) prior to first paragraph / section header, to terminate paragraph / section header, to terminate a paragraph / section and to terminate a program (if no paragraphs / sections).
Unfortunately, this freaked out the Cobol programmers that coded to the Cobol 68 and 74 standard. To this day, many Cobol shops enforce a coding rule about ending every procedure division sentence with a period.
Where to use!
There are 2 forms to use point.
You can use POINT after every VERB in a SECTION.
EXAMPLE:
0000-EXAMPLE SECTION.
MOVE 0 TO WK-I.
PERFORM UNTIL WK-I GREATER THAN 100
DISPLAY WK-I
ADD 1 TO WK-I
END-PERFORM.
DISPLAY WK-I.
IF WK-I EQUAL ZEROS
DISPLAY WK-I
END-IF.
0000-EXAMEPLE-END. EXIT.
Note that we are using point after every VERB, EXCEPT inside a PERFORM, IF, ETC...
Another form to use is: USING ONLY ONE POINT AT THE END OF SECTION, like here:
0000-EXAMPLE SECTION.
MOVE 0 TO WK-I
PERFORM UNTIL WK-I GREATER THAN 100
DISPLAY WK-I
ADD 1 TO WK-I
END-PERFORM
DISPLAY WK-I
IF WK-I EQUAL ZEROS
DISPLAY WK-I
END-IF
. <======== point here!!!!!!! only HERE!
0000-EXAMEPLE-END. EXIT.
BUT, we ALWAYS have after EXIT and SECTION.....
When it is my choice, I use full-stop/period only where necessary. However, local standards often dictate otherwise: so be it.
The problems caused by full-stops/periods are in the accidental making of something unconditional when code "with" is copied into code "without" whilst coder's brain is left safely in the carpark.
One extra thing to watch for is (hopefully) "old" programs which use NEXT SENTENCE in IBM Mainframe Cobol. "NEXT SENTENCE" means "after the next full-stop/period" which, in "sparse full-stop/period" code is the end of the paragraph/section. Accident waiting to happen. Get a spec-change to allow "NEXT SENTENCE" to be changed to "CONTINUE".
Just tested that in my cobol 85 program by removing all of the periods in procedures and it worked fine.
example:
PROCEDURE DIVISION.
MAIN-PROCESS.
READ DISK-IN
AT END
DISPLAY "NO RECORDS ON INPUT FILE"
STOP RUN
ADD 1 TO READ-COUNT.
PERFORM PROCESS-1 UNTIL END-OF-FILE.
WRITE-HEADER.
MOVE HEADER-INJ-1 TO HEADER-OUT-1
WRITE HEADER-OUT-1.
CLOSE-FILES.
CLOSE DISK-IN
CLOSE DISK-OUT
DISPLAY "READ: " READ-COUNT
DISPLAY "WRITTEN: " WRITE-COUNT
SORT SORT-FILE ON ASCENDING SER-S
USING DISK-OUT
GIVING DISK-OUT
STOP RUN.

Easiest way to remove Latex tag (but not its content)?

I am using TeXnicCenter to edit a LaTeX document.
I now want to remove a certain tag (say, emph{blabla}} which occurs multiple times in my document , but not tag's content (so in this example, I want to remove all emphasization).
What is the easiest way to do so?
May also be using another program easily available on Windows 7.
Edit: In response to regex suggestions, it is important that it can deal with nested tags.
Edit 2: I really want to remove the tag from the text file, not just disable it.
Using a regular expression do something like s/\\emph\{([^\}]*)\}/\1/g. If you are not familiar with regular expressions this says:
s -- replace
/ -- begin match section
\\emph\{ -- match \emph{
( -- begin capture
[^\}]* -- match any characters except (meaning up until) a close brace because:
[] a group of characters
^ means not or "everything except"
\} -- the close brace
and * means 0 or more times
) -- end capture, because this is the first (in this case only) capture, it is number 1
\} -- match end brace
/ -- begin replace section
\1 -- replace with captured section number 1
/ -- end regular expression, begin extra flags
g -- global flag, meaning do this every time the match is found not just the first time
This is with Perl syntax, as that is what I am familiar with. The following perl "one-liners" will accomplish two tasks
perl -pe 's/\\emph\{([^\}]*)\}/\1/g' filename will "test" printing the file to the command line
perl -pi -e 's/\\emph\{([^\}]*)\}/\1/g' filename will change the file in place.
Similar commands may be available in your editor, but if not this will (should) work.
Crowley should have added this as an answer, but I will do that for him, if you replace all \emph{ with { you should be able to do this without disturbing the other content. It will still be in braces, but unless you have done some odd stuff it shouldn't matter.
The regex would be a simple s/\\emph\{/\{/g but the search and replace in your editor will do that one too.
Edit: Sorry, used the wrong brace in the regex, fixed now.
\renewcommand{\emph}[1]{#1}
any reasonably advanced editor should let you do a search/replace using regular expressions, replacing emph{bla} by bla etc.

Funny CSV format help

I've been given a large file with a funny CSV format to parse into a database.
The separator character is a semicolon (;). If one of the fields contains a semicolon it is "escaped" by wrapping it in doublequotes, like this ";".
I have been assured that there will never be two adjacent fields with trailing/ leading doublequotes, so this format should technically be ok.
Now, for parsing it in VBScript I was thinking of
Replacing each instance of ";" with a GUID,
Splitting the line into an array by semicolon,
Running back through the array, replacing the GUIDs with ";"
It seems to be the quickest way. Is there a better way? I guess I could use substrings but this method seems to be acceptable...
Your method sounds fine with the caveat that there's absolutely no possibility that your GUID will occur in the text itself.
On approach I've used for this type of data before is to just split on the semi-colons regardless then, if two adjacent fields end and start with a quote, combine them.
For example:
Pax;is;a;good;guy";" so;says;his;wife.
becomes:
0 Pax
1 is
2 a
3 good
4 guy"
5 " so
6 says
7 his
8 wife.
Then, when you discover that fields 4 and 5 end and start (respectively) with a quote, you combine them by replacing the field 4 closing quote with a semicolon and removing the field 5 opening quote (and joining them of course).
0 Pax
1 is
2 a
3 good
4 guy; so
5 says
6 his
7 wife.
In pseudo-code, given:
input: A string, first character is input[0]; last
character is input[length]. Further, assume one dummy
character, input[length+1]. It can be anything except
; and ". This string is one line of the "CSV" file.
length: positive integer, number of characters in input
Do this:
set start = 0
if input[0] = ';':
you have a blank field in the beginning; do whatever with it
set start = 2
endif
for each c between 1 and length:
next iteration unless string[c] = ';'
if input[c-1] ≠ '"' or input[c+1] ≠ '"': // test for escape sequence ";"
found field consting of half-open range [start,c); do whatever
with it. Note that in the case of empty fields, start≥c, leaving
an empty range
set start = c+1
endif
end foreach
Untested, of course. Debugging code like this is always fun….
The special case of input[0] is to make sure we don't ever look at input[-1]. If you can make input[-1] safe, then you can get rid of that special case. You can also put a dummy character in input[0] and then start your data—and your parsing—from input[1].
One option would be to find instances of the regex:
[^"];[^"]
and then break the string apart with substring:
List<string> ret = new List<string>();
Regex r = new Regex(#"[^""];[^""]");
Match m;
while((m = r.Match(line)).Success)
{
ret.Add(line.Substring(0,m.Index + 1);
line = line.Substring(m.Index + 2);
}
(Sorry about the C#, I don't known VBScript)
Using quotes is normal for .csv files. If you have quotes in the field then you may see opening and closing and the embedded quote all strung together two or three in a row.
If you're using SQL Server you could try using T-SQL to handle everything for you.
SELECT * INTO MyTable FROM OPENDATASOURCE('Microsoft.JET.OLEDB.4.0',
'Data Source=F:\MyDirectory;Extended Properties="text;HDR=No"')...
[MyCsvFile#csv]
That will create and populate "MyTable". Read more on this subject here on SO.
I would recommend using RegEx to break up the strings.
Find every ';' that is not a part of
";" and change it to something else
that does not appear in your fields.
Then go through and replace ";" with ;
Now you have your fields with the correct data.
Most importers can swap out separator characters pretty easily.
This is basically your GUID idea. Just make sure the GUID is unique to your file before you start and you will be fine. I tend to start using 'Z'. After enough 'Z's, you will be unique (sometimes as few as 1-3 will do).
Jacob

Resources