Error: syntax error, unexpected "Identifier", expecting EXTERNAL or GLOBAL - syntax

Hi I was wondering if yall could help me figure this error out. Im rather new to cobol as it is my first (and only) cobol class in my major.
I keep getting this error lab3a.cob:23: Error: syntax error, unexpected "Identifier", expecting EXTERNAL or GLOBAL
whenever I try to compile. And I cant seem to see what I'm doing wrong.
My Code
IDENTIFICATION DIVISION.
PROGRAM-ID. "LAB3A".
Author. Fielding Featherston
* Takes inputs from file and seperates.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT InFile
ASSIGN to "lab3-in.dat"
ORGANIZATION is LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD InFile.
01 InString.
05 PIC X(13).
05 Instrument PIC X(12).
88 Brass value "Bugle" "Flugelhorn"
"Sousaphone" "Trombone"
"Trumpet" "Tuba".
88 Percussion value "Bass Drum" "Bells" "Bongos"
"Castanets" "Chimes" "Cymbals"
"Snare Drum" "Xylophone".
88 Strings value "Banjo" "Bass" "Cello" "Guitar"
"Harp" "Lyre"
"Mandolin" "Violin".
88 Woodwind value "Bagpipes" "Bassoon" "Clarinet"
"Flute" "Oboe"
"Piccolo" "Saxophone".
WORKING-STORAGE SECTION.
01 BrassCount PIC 9(3).
01 PerCount PIC 9(3).
01 StringCount PIC 9(3).
01 WoodCount PIC 9(3).
01 OtherCount PIC 9(3).
01 BrassStr PIC ZZ9.
01 PerStr PIC ZZ9.
01 StringStr PIC ZZ9.
01 WoodStr PIC ZZ9.
01 OtherStr PIC ZZ9.
01 InStringLength PIC 99.
01 EndFileStr PIC X VALUE "n".
88 EndFile VALUE "y"
When Set to False is "y".
PROCEDURE DIVISION.
000-Main.
Open Input InFile
Perform until EndFile
Read InFile
At end
Set EndFile to FALSE
Not at End
PERFORM 100-SeperateStrings
PERFORM 200-ClassCount
END-READ
END-PERFORM
CLOSE InFile
Move BrassCount to BrassStr
Move PerCount to PerStr
Move StringCount to StringStr
Move WoodCount to WoodStr
Move OtherCount to OtherStr
DISPLAY "Counts"
DISPLAY " Brass: " FUNCTION TRIM(BrassStr)
DISPLAY " Percussion: " FUNCTION TRIM(PerStr)
DISPLAY " String: " FUNCTION TRIM(StringStr)
DISPLAY " Woodwind: " FUNCTION TRIM(WoodStr)
DISPLAY " OTHER: " FUNCTION TRIM(OtherStr)
STOP RUN.
100-SeperateStrings.
MOVE FUNCTION Length(InString) to InStringLength
UNSTRING InString (14:InStringLength)
INTO Instrument
END-UNSTRING.
200-ClassCount.
IF Brass
Add 1 to BrassCount
ELSE IF Percussion
Add 1 to PerCount
ELSE IF Strings
Add 1 to StringCount
ELSE IF Woodwind
Add 1 to WoodCount
ELSE
Add 1 to OtherCount
END-IF.

An EXTERNAL or GLOBAL clause in the context of the error may only occur in a record description entry; that is, a data entry that begins with 1 or 01. Given that the error occurs between two 88 level items, it appears the compiler is confused about where it is while scanning the source code.
There is some unusual formatting that may be creating a problem with an the compiler. In particular, line 22 contains a number of TAB characters that should not, but may, confuse the compiler. Also, lines 33 and 46 contain a number of TAB characters at the end of each source line causing the lines to exceed 72 characters.
Another possible issue is expansion of tabs, whether each TAB character is replaced by 4 or 8 spaces by the compiler. Again this will affect whether the text exceeds 72 characters. In the absence of a SOURCE FORMAT directive, source text after column 72 is ignored.
Until you know the effect that tabs have on the source code, I suggest replacing all tabs with spaces.

Related

how to limit 00 to 99 counter to 60

For a simple starter project I was putting together a 2-7segement display 00 to 99 counter coded on sketch.
//The line below is the array containing all the binary numbers for the digits on a SSD from 0 to 9
const int number[11] = {0b1000000, 0b1111001, 0b0100100, 0b0110000, 0b0011001, 0b0010010, 0b0000010, 0b1111000, 0b0000000, 0b0010000};
I believe that my solution is either to change this part of the code or add another line, I'm just unsure.
Any advice?
I have tried adding another line to set one of the displays to stop at 6 but it didn't compile with the rest of the code.

COBOL "File not found" while opening a file

I am trying to familiarize myself with COBOL. I try to start the following program:
identification division.
program-id. Bestand.
date-written. 08.05.2020
environment division.
input-output section.
file-control.
select bestand-datei-ein assign to
"C:\Users\Michael\Desktop\Microfocus\Programme\aus.txt".
select bestand-datei-aus assign to
"C:\Users\Michael\Desktop\Microfocus\Programme\aus.txt".
data division.
file section.
fd bestand-datei-ein label records are omitted.
01 bestand-satz-ein.
05 e-teile-nr PIC X(6).
05 e-bestand-menge PIC 9(5).
05 e-eingang-menge PIC 9(4).
05 e-stueck-preis PIC 999V99.
fd bestand-datei-aus label records are omitted.
01 bestand-satz-aus.
05 a-teile-nr PIC X(6).
05 filler PIC X(4).
05 a-bestand-menge PIC 9(5).
05 filler PIC X(3).
05 a-eingang-menge PIC 9(4).
05 filler PIC X(3).
05 a-stueck-preis PIC 999.99.
05 filler PIC X(3).
05 a-bestand-menge-neu PIC 9(5).
05 filler PIC X(3).
05 a-kosten PIC 9(6).99.
01 a PIC X.
working-storage section.
01 bestand-datei-ein-ende PIC X.
procedure division.
a000-haupt-steuerung-routine.
open input bestand-datei-ein
output bestand-datei-aus.
move 'N' to bestand-datei-ein-ende.
read bestand-datei-ein
at end move 'J' to bestand-datei-ein-ende.
perform b010-listen-bestandsdaten
until bestand-datei-ein-ende = 'J'.
close bestand-datei-aus
bestand-datei-ein.
accept a.
stop run.
b010-listen-bestandsdaten.
move spaces to bestand-satz-aus.
move e-teile-nr to a-teile-nr.
move e-bestand-menge to a-bestand-menge.
move e-eingang-menge to a-eingang-menge.
move e-stueck-preis to a-stueck-preis.
add e-bestand-menge, e-eingang-menge
giving a-bestand-menge-neu.
multiply a-bestand-menge-neu by e-stueck-preis
giving a-kosten.
read bestand-datei-ein
at end
move 'J' to bestand-datei-ein-ende.
I always get the error message "File not found: C: \ Users \ Michael \ Desktop \ Microfocus \ Program \ aus.txt" when I start the program and the should be opened.
I work with Micro Focus Visual Cobol for Visual Studio
Any idea ?
From comment:
The problem has now been solved. The file names were not displayed correctly in the code (cut and paste errors). It should read "ein.txt" and aus.txt. The problem was that the file names in the file system were set so that the extension is not displayed. I named the input file "ein.txt" and basically created a file named "ein.txt.txt". Therefore the file was not found.

Understand VB6 disassemble code

I have an old VB executable that has been used for a long time in my project.
The current implementation of the application contains a debug window that's
not needed any more.
Of course, the source code was lost and can not be modified.
My idea is to modify the HEX code of the instance that's opening the annoying debug window.
For that purpose, I use VB Decompiler by DotFix software, and I suppose that I found the code responsible for that instance. Unfortunately, I can't understand how it works.
Let's see the disassemble code:
loc_8F420C: var_8A = 0
loc_8F4219: If (Len(var_88) = &H30) Then
loc_8F4225: Call {3014B1BF-8A2C-23D7-B50400C24F280C20}.Method_arg_12 (var_88)
loc_8F4233: Call {3014B1BF-8A2C-23D7-B50400C24F280C20}.Method_arg_16 (var_108)
loc_8F423D: If CBool(var_108) Then
loc_8F424D: Me.Global.Unload Me
loc_8F4258: Else
loc_8F425A: var_8A = &HFF
...
loc_8F43B0: End If
loc_8F43B3: Else
At the first sight var_108 seems a bool variable that is the one setting the debug window. Can I implicitly put in loc_8F423D: If CBool(false/true) Then to stop this window from launching?
Can anyone explain to me what are those Call {#######-####-####-################}.Method_arg_## from above?
PEiD detect compiler:
Microsoft Visual Basic 5.0 / 6.0 [Overlay]
Part 2:
It took me a long time to get the new idea - the right one, possibly. Let's take a look at the assembly code:
004F420C: 70 FStI2 var_8A <- loc_8F420C: var_8A = 0
Looks like loc_8F4219: If (Len(var_88) = &H30) Then
004F420F: 6C ILdRf var_88
004F4212: 4A FnLenStr Len()
004F4213: F5 LitI4: 48 (0x30)
Let's find the next code snippets:
004F4218: C7 EqI4 =
004F4219: 1C BranchF 004F43B3
Our Call methods looks like :
004F421C: 6C ILdRf var_88 < - (var_88) from Call
004F421F: 22 ImpAdLdPr
004F4222: 58 MemLdPr
004F4225: 0D VCallHresult var_88.vtable[12] <- Method_arg_12
004F422A: 04 FLdRfVar var_108 <- (var_108) possible CALL/BACK
004F422D: 22 ImpAdLdPr
004F4230: 58 MemLdPr
004F4233: 0D VCallHresult var_108.vtable[16] <- Method_arg_16
004F4238: 6C ILdRf var_108 <- (var_108) 70% sure is RESPONSE(true/false)
And now the most interesting parts of that annoying P-Code&Assembly, we find the if instance that verifies if the Debug Windows is needed. If we look at P-Code we can see that if has the form:
loc_8F423D: If CBool(var_108) Then
loc_8F424D: Me.Global.Unload Me
loc_8F4258: Else
loc_8F425A: var_8A = &HFF
And now look at the Address - if is true execute address 00F424D / 8F424D else jump outside to 004F4258
004F423B: FC52 CBoolI4
004F423D: 1C BranchF 004F4258
004F4240: 6C ILdRf param_8
004F4243: FD9C FStAdNoPop
004F4247: 05 ImpAdLdRf
004F424A: 24 NewIfNullPr GLOBAL
004F424D: 0D VCallHresult Global._Unload(object As IDispatch)
004F4252: 1A FFree1Ad var_90
004F4255: 1E Branch 004F43B0
004F4258: loc_004F423D
004F4258: F4 LitI2_Byte: 255 (True)
Possibly, if I change the 004F423D: 1C BranchF 004F4258 so that it points to another address 004F424D, logically that might do the trick.
004F423D: 1C BranchF 004F424D
Now I'm trying to find that address with OllyDbg - to test if that helps. If I succeed I will write part 3.
Does anyone have some other ideas?

Getting GCC to optimize hand assembly

In an attempt to make GCC not generate a load-modify-store operation every time I do |= or &=, I have defined the following macros:
#define bset(base, offset, mask) bmanip(set, base, offset, mask)
#define bclr(base, offset, mask) bmanip(clr, base, offset, mask)
#define bmanip(op, base, offset, mask) \
asm("pshx");\
asm("ldx " #base);\
asm("b" #op " " #offset ",x " #mask);\
asm("pulx")
And they work great; the disassembled binary is perfect.
The problem comes when I use more than one in sequence:
inline void spi_init()
{
bset(_io_ports, M6811_DDRD, 0x38);
bset(_io_ports, M6811_PORTD, 0x20);
bset(_io_ports, M6811_SPCR, (M6811_SPE | M6811_DWOM | M6811_MSTR));
}
This results in:
00002227 <spi_init>:
2227: 3c pshx
2228: fe 10 00 ldx 0x1000 <_io_ports>
222b: 1c 09 38 bset 0x9,x, #0x38
222e: 38 pulx
222f: 3c pshx
2230: fe 10 00 ldx 0x1000 <_io_ports>
2233: 1c 08 20 bset 0x8,x, #0x20
2236: 38 pulx
2237: 3c pshx
2238: fe 10 00 ldx 0x1000 <_io_ports>
223b: 1c 28 70 bset 0x28,x, #0x70
223e: 38 pulx
223f: 39 rts
Is there any way to get GCC (3.3.6-m68hc1x-20060122) to automatically optimize out the redundant stack operations?
gcc will always emit the assembly instructions you tell it to emit. So instead of explicitly writing code to load registers with the value you want to manipulate, you instead want to tell gcc to do this on your behalf. You can do this with register constraints.
Unfortunately the 6811 code generator doesn't seem to be a standard part of gcc --- I don't spot the documentation in the manual. So I can't point you at platform-specific bit of the docs. But the generic bit you need to read is here: http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Extended-Asm.html#Extended-Asm
The syntax is freaky, but the summary is:
asm("instructions" : outputs : inputs);
...where inputs and outputs are lists of constraints, which tell gcc what value to put where. The classic example is:
asm("fsinx %1,%0" : "=f" (result) : "f" (angle));
f indicates that the named value needs to go into a floating point register; = indicates it's an output; then the names of the registers are substituted into the instruction.
So, you'll probably want something like this:
asm("b" #op " " #offset ",%0 " #mask : "=Z" (i) : "0" (i));
...where i is a variable containing the value you want to modify. Z you'll need to look up in the 6811 gcc docs --- it's a constraint which represents a register which is valid for the asm instruction which is being generated. The 0 indicates that the input shares a register with output 0, and is used for read/write values.
Because you've told gcc what register you want i to be, it can integrate this knowledge into its register allocator and find the least-cost way to get i where you need it with the least amount of code. (Sometimes no additional code.)
gcc inline assembly is deeply contorted and weird, but pretty powerful. It's worth spending some time to thoroughly understand the constraint system to get the best use out of it.
(Incidentally, I don't know 6811 code, but have you forgotten to put the result of the op somewhere? I'd expect to see an stx to match the ldx.)
Update: Oh, I see what bset is doing now --- it's writing the result back to a memory location, right? That's still doable but it's a bit more painful. You need to tell gcc that you're modifying that memory location, so that it knows not to rely on any cached value. You'll need to have an output parameter with constraint m which represents that location. Check the docs.

VB6 RS232 commands not working

I have the following code:
MSCommProj.CommPort = 6
MSCommProj.RThreshold = 1
MSCommProj.Settings = "19200,N,8,1"
MSCommProj.InputLen = 0
MSCommProj.PortOpen = True
And it opens just fine and connects but when i try sending the command:
MSCommProj.Output = "21 8901 5057 31 0A" & Chr$(13)
and
MSCommProj.Output = "21 89 01 50 57 31 0A" & Chr$(13)
and
MSCommProj.Output = "3F 89 01 50 57 0A" & Chr$(13)
as instructed by the user manual, it does not come on.
Here is the pages in the manual that shows this. Maybe i am just doing it wrong?:
Are you sure that you're meant to be sending character data to the RS232 interface for that? Those look like binary sequences to me.
Rather than:
MSCommProj.Output = "3F 89 01 50 57 0A" & Chr$(13)
I'd be looking at transmitting the binary data thus:
MSCommProj.Output = chr$(63) & chr$(137) & chr$(1) & chr$(80) & chr$(87) & chr(10)
You'll note that there's no chr$(13) at the end, the spec doesn't call for that.
If you want to know what the conversions are for those hex values, start up the Windows calculator, change the view to scientific, switch to hex mode, enter the value, the switch to decimal mode.
Or you can download an ASCII table for this purpose. Or view one of my voluminous essays on the subject here.
You are required to send bytes given.
You instead send string representation of those.
Send actual bytes.
chr$(&h21) & chr$(&h89) & chr$(&h01) & chr$(&h50) etc.
It was because i did not use a cross-over cable... All the rs232 codes were correct. Blah.

Resources