diff --git a/doc/environment_variables.md b/doc/environment_variables.md index a19c7fae6..2da990b6b 100644 --- a/doc/environment_variables.md +++ b/doc/environment_variables.md @@ -446,13 +446,22 @@ $ OC_EXTEND_CREATES=yes java ocextcreates FILE STATUS: 00 ``` -#### COB_FILE_SEQ_WRITE_BUFFER_SIZE +#### COB_FILE_SEQ_BUFFER_SIZE -Specifies the write buffer size for sequential files. +Specifies the buffer size for sequential file I/O (both read and write). + +- **Value**: Integer >= 0 (default: 10). The value represents a multiplier for the record size. +- **Example**: `COB_FILE_SEQ_BUFFER_SIZE=100` +- **Purpose**: Adjusts read and write performance for SEQUENTIAL and LINE SEQUENTIAL files. The actual buffer size is calculated as `COB_FILE_SEQ_BUFFER_SIZE * record_max` bytes. Setting to 0 disables buffering. + +#### COB_FILE_SEQ_WRITE_BUFFER_SIZE (Deprecated) + +Deprecated. Use `COB_FILE_SEQ_BUFFER_SIZE` instead. + +This environment variable is retained for backward compatibility. When `COB_FILE_SEQ_BUFFER_SIZE` is not set, this variable is used as a fallback with the same effect. - **Value**: Integer >= 0 (default: 10) - **Example**: `COB_FILE_SEQ_WRITE_BUFFER_SIZE=100` -- **Purpose**: Adjusts write performance. #### COB_IO_ASSUME_REWRITE diff --git a/doc/environment_variables_JP.md b/doc/environment_variables_JP.md index aed991ef8..129472677 100644 --- a/doc/environment_variables_JP.md +++ b/doc/environment_variables_JP.md @@ -446,13 +446,22 @@ $ OC_EXTEND_CREATES=yes java ocextcreates FILE STATUS: 00 ``` -#### COB_FILE_SEQ_WRITE_BUFFER_SIZE +#### COB_FILE_SEQ_BUFFER_SIZE -順編成ファイルの書き込みバッファサイズを指定します。 +順編成ファイルの読み書きバッファサイズを指定します。 + +- **値**: 0以上の整数(デフォルト: 10)。レコードサイズに対する倍率を指定します。 +- **例**: `COB_FILE_SEQ_BUFFER_SIZE=100` +- **用途**: SEQUENTIALおよびLINE SEQUENTIALファイルの読み書きパフォーマンスを調整できます。実際のバッファサイズは `COB_FILE_SEQ_BUFFER_SIZE * record_max` バイトとなります。0を指定するとバッファリングが無効になります。 + +#### COB_FILE_SEQ_WRITE_BUFFER_SIZE(非推奨) + +非推奨です。代わりに `COB_FILE_SEQ_BUFFER_SIZE` を使用してください。 + +後方互換性のために残されています。`COB_FILE_SEQ_BUFFER_SIZE` が設定されていない場合にフォールバックとして同じ効果で使用されます。 - **値**: 0以上の整数(デフォルト: 10) - **例**: `COB_FILE_SEQ_WRITE_BUFFER_SIZE=100` -- **用途**: 書き込みパフォーマンスを調整できます。 #### COB_IO_ASSUME_REWRITE diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolUtil.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolUtil.java index 0e0dd923a..a244ba361 100755 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolUtil.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolUtil.java @@ -69,8 +69,8 @@ public class CobolUtil { /** TDOD: 準備中 */ public static Calendar cal; - /** TDOD: 準備中 */ - public static int fileSeqWriteBufferSize = 10; + /** 順編成ファイルの読み書きバッファサイズ(レコード数単位) */ + public static int fileSeqBufferSize = 10; /** DISPLAY/ACCEPT文によるデータ出力時のエンコーディング */ public static CobolEncoding terminalEncoding = CobolEncoding.SHIFT_JIS; @@ -345,11 +345,18 @@ public static void cob_init(String[] argv, boolean cobInitialized) { CobolUtil.nibbleCForUnsigned = true; } - s = System.getenv("COB_FILE_SEQ_WRITE_BUFFER_SIZE"); + s = CobolUtil.getEnv("COB_FILE_SEQ_BUFFER_SIZE"); + if (s == null) { + s = CobolUtil.getEnv("COB_FILE_SEQ_WRITE_BUFFER_SIZE"); + } if (s != null) { - int size = Integer.parseInt(s); - if (size >= 0) { - CobolUtil.fileSeqWriteBufferSize = size; + try { + int size = Integer.parseInt(s); + if (size >= 0) { + CobolUtil.fileSeqBufferSize = size; + } + } catch (NumberFormatException ignored) { + // ignore invalid value } } diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFile.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFile.java index f3747fcfe..de53105c4 100755 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFile.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFile.java @@ -1243,9 +1243,8 @@ public int open_(String filename, int mode, int sharing) throws IOException { } if ((this.organization == COB_ORG_SEQUENTIAL || this.organization == COB_ORG_LINE_SEQUENTIAL) - && (mode == COB_OPEN_OUTPUT || mode == COB_OPEN_EXTEND) - && CobolUtil.fileSeqWriteBufferSize > 0) { - this.file.prepareWriteBuffer(CobolUtil.fileSeqWriteBufferSize * this.record_max); + && CobolUtil.fileSeqBufferSize > 0) { + this.file.prepareBuffer(CobolUtil.fileSeqBufferSize * this.record_max); } return 0; } diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/FileIO.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/FileIO.java index b3634358e..1c9b2354c 100644 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/FileIO.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/FileIO.java @@ -38,24 +38,18 @@ class FileIO { private boolean useStdIn = true; private boolean atEnd = false; - private static final boolean USE_READ_BUFFER = false; - private static final int READ_BUFFER_SIZE = 1024; - private int readBufferIndex; - private byte[] readBuffer; - private int readBufferEndIndex; - - private int writeBufferSize = 0; - private int writeBufferEndIndex = 0; - private byte[] writeBuffer; + private int bufferSize = 0; + private byte[] buffer; + private int bufferPos = 0; + private int bufferValidEnd = 0; + private long bufferFileOffset = 0; + private boolean bufferDirty = false; + private boolean bufferActive = false; /** TODO: 準備中 */ FileIO() { this.useStdOut = true; this.useStdIn = true; - - this.readBufferIndex = READ_BUFFER_SIZE; - this.readBuffer = new byte[READ_BUFFER_SIZE]; - this.readBufferEndIndex = READ_BUFFER_SIZE; } /** @@ -116,19 +110,72 @@ void setIn(InputStream in) { * * @param bufferSize TODO: 準備中 */ - void prepareWriteBuffer(int bufferSize) { + void prepareBuffer(int bufferSize) { if (bufferSize > 0) { - this.writeBufferSize = bufferSize; - this.writeBufferEndIndex = 0; - if (this.writeBuffer == null || this.writeBuffer.length < bufferSize) { - this.writeBuffer = new byte[bufferSize]; + this.bufferSize = bufferSize; + this.bufferActive = false; + this.bufferDirty = false; + this.bufferPos = 0; + this.bufferValidEnd = 0; + this.bufferFileOffset = 0; + if (this.buffer == null || this.buffer.length < bufferSize) { + this.buffer = new byte[bufferSize]; + } + } + } + + private long logicalPosition() throws IOException { + if (bufferActive) { + return bufferFileOffset + bufferPos; + } + return fc.position(); + } + + private void deactivateBuffer() { + this.bufferActive = false; + this.bufferDirty = false; + this.bufferPos = 0; + this.bufferValidEnd = 0; + this.bufferFileOffset = 0; + } + + private boolean flushBuffer() { + if (bufferDirty && bufferValidEnd > 0) { + try { + fc.position(bufferFileOffset); + } catch (IOException e) { + return false; } + ByteBuffer bb = ByteBuffer.wrap(buffer, 0, bufferValidEnd); + if (!writeByteBuffer(bb)) { + return false; + } + bufferDirty = false; } + return true; } - private void destroyWriteBuffer() { - this.writeBufferSize = 0; - this.writeBufferEndIndex = 0; + private int fillReadBuffer() throws IOException { + long filePos = logicalPosition(); + bufferActive = false; + bufferFileOffset = filePos; + bufferPos = 0; + bufferValidEnd = 0; + fc.position(filePos); + ByteBuffer bb = ByteBuffer.wrap(buffer, 0, bufferSize); + int readBytes; + try { + readBytes = this.fc.read(bb); + } catch (NonReadableChannelException e) { + return -1; + } + if (readBytes <= 0) { + return -1; + } + bufferValidEnd = readBytes; + bufferActive = true; + bufferDirty = false; + return readBytes; } /** @@ -144,6 +191,41 @@ int read(byte[] bytes, int size) { System.err.println("read stdin not implmented"); return 0; } else { + if (bufferSize > 0) { + try { + int offset = 0; + int remaining = size; + while (remaining > 0) { + if (bufferActive) { + int available = bufferValidEnd - bufferPos; + if (available > 0) { + int toCopy = Math.min(remaining, available); + System.arraycopy(buffer, bufferPos, bytes, offset, toCopy); + bufferPos += toCopy; + offset += toCopy; + remaining -= toCopy; + continue; + } + } + if (bufferDirty) { + if (!flushBuffer()) { + return 0; + } + } + if (fillReadBuffer() < 0) { + this.atEnd = true; + if (offset == 0) { + return 0; + } + return 1; + } + } + } catch (IOException e) { + return 0; + } + return 1; + } + int readSize; ByteBuffer data = ByteBuffer.wrap(bytes); try { @@ -175,6 +257,35 @@ int read(CobolDataStorage storage, int size) throws IOException { if (this.fc == null) { throw new IOException(); } + if (bufferSize > 0) { + int offset = 0; + int remaining = size; + while (remaining > 0) { + if (bufferActive) { + int available = bufferValidEnd - bufferPos; + if (available > 0) { + int toCopy = Math.min(remaining, available); + for (int i = 0; i < toCopy; ++i) { + storage.setByte(offset + i, buffer[bufferPos + i]); + } + bufferPos += toCopy; + offset += toCopy; + remaining -= toCopy; + continue; + } + } + if (bufferDirty) { + if (!flushBuffer()) { + return offset; + } + } + if (fillReadBuffer() < 0) { + return offset; + } + } + return size; + } + int i = 0; try { for (i = 0; i < size; ++i) { @@ -201,15 +312,12 @@ private boolean writeByteBuffer(ByteBuffer bb) { return true; } - private boolean outputWriteBuffer() { - if (writeBufferEndIndex > 0 && writeBufferSize > 0) { - ByteBuffer bb = ByteBuffer.wrap(writeBuffer, 0, writeBufferEndIndex); - if (!writeByteBuffer(bb)) { - return false; - } - writeBufferEndIndex = 0; - } - return true; + private void startNewBuffer(long filePos) { + bufferFileOffset = filePos; + bufferPos = 0; + bufferValidEnd = 0; + bufferActive = true; + bufferDirty = false; } /** @@ -223,18 +331,47 @@ boolean write(byte[] bytes, int size) { if (this.fc == null) { return false; } - if (writeBufferSize > 0 && size <= writeBufferSize - writeBufferEndIndex) { - System.arraycopy(bytes, 0, writeBuffer, writeBufferEndIndex, size); - writeBufferEndIndex += size; - return true; - } - if (!outputWriteBuffer()) { - return false; - } - if (writeBufferSize > 0 && size <= writeBufferSize - writeBufferEndIndex) { - System.arraycopy(bytes, 0, writeBuffer, writeBufferEndIndex, size); - writeBufferEndIndex += size; - return true; + if (bufferSize > 0) { + try { + if (bufferActive) { + if (bufferPos + size <= bufferSize) { + System.arraycopy(bytes, 0, buffer, bufferPos, size); + bufferPos += size; + bufferValidEnd = Math.max(bufferValidEnd, bufferPos); + bufferDirty = true; + return true; + } + if (!flushBuffer()) { + return false; + } + long filePos = bufferFileOffset + bufferPos; + fc.position(filePos); + startNewBuffer(filePos); + if (size <= bufferSize) { + System.arraycopy(bytes, 0, buffer, 0, size); + bufferPos = size; + bufferValidEnd = size; + bufferDirty = true; + return true; + } + deactivateBuffer(); + ByteBuffer bb = ByteBuffer.wrap(bytes, 0, size); + return writeByteBuffer(bb); + } + startNewBuffer(fc.position()); + if (size <= bufferSize) { + System.arraycopy(bytes, 0, buffer, 0, size); + bufferPos = size; + bufferValidEnd = size; + bufferDirty = true; + return true; + } + deactivateBuffer(); + } catch (IOException e) { + return false; + } + ByteBuffer bb = ByteBuffer.wrap(bytes, 0, size); + return writeByteBuffer(bb); } ByteBuffer bb = ByteBuffer.wrap(bytes, 0, size); return writeByteBuffer(bb); @@ -251,22 +388,53 @@ boolean write(CobolDataStorage storage, int size) { if (this.fc == null) { return false; } - if (writeBufferSize > 0 && size <= writeBufferSize - writeBufferEndIndex) { - for (int i = 0; i < size; ++i) { - writeBuffer[writeBufferEndIndex + i] = storage.getByte(i); - } - writeBufferEndIndex += size; - return true; - } - if (!outputWriteBuffer()) { - return false; - } - if (writeBufferSize > 0 && size <= writeBufferSize - writeBufferEndIndex) { - for (int i = 0; i < size; ++i) { - writeBuffer[writeBufferEndIndex + i] = storage.getByte(i); + if (bufferSize > 0) { + try { + if (bufferActive) { + if (bufferPos + size <= bufferSize) { + for (int i = 0; i < size; ++i) { + buffer[bufferPos + i] = storage.getByte(i); + } + bufferPos += size; + bufferValidEnd = Math.max(bufferValidEnd, bufferPos); + bufferDirty = true; + return true; + } + if (!flushBuffer()) { + return false; + } + long filePos = bufferFileOffset + bufferPos; + fc.position(filePos); + startNewBuffer(filePos); + if (size <= bufferSize) { + for (int i = 0; i < size; ++i) { + buffer[i] = storage.getByte(i); + } + bufferPos = size; + bufferValidEnd = size; + bufferDirty = true; + return true; + } + deactivateBuffer(); + ByteBuffer bb = storage.getByteBuffer(size); + return writeByteBuffer(bb); + } + startNewBuffer(fc.position()); + if (size <= bufferSize) { + for (int i = 0; i < size; ++i) { + buffer[i] = storage.getByte(i); + } + bufferPos = size; + bufferValidEnd = size; + bufferDirty = true; + return true; + } + deactivateBuffer(); + } catch (IOException e) { + return false; } - writeBufferEndIndex += size; - return true; + ByteBuffer bb = storage.getByteBuffer(size); + return writeByteBuffer(bb); } ByteBuffer bb = storage.getByteBuffer(size); return writeByteBuffer(bb); @@ -282,16 +450,36 @@ byte putc(byte val) { if (this.fc == null) { return 0; } - if (writeBufferSize > 0 && 1 <= writeBufferSize - writeBufferEndIndex) { - writeBuffer[writeBufferEndIndex++] = val; - return val; - } - if (!outputWriteBuffer()) { - return -1; - } - if (writeBufferSize > 0 && 1 <= writeBufferSize - writeBufferEndIndex) { - writeBuffer[writeBufferEndIndex++] = val; - return val; + if (bufferSize > 0) { + try { + if (bufferActive) { + if (bufferPos < bufferSize) { + buffer[bufferPos++] = val; + bufferValidEnd = Math.max(bufferValidEnd, bufferPos); + bufferDirty = true; + return val; + } + if (!flushBuffer()) { + return -1; + } + long filePos = bufferFileOffset + bufferPos; + fc.position(filePos); + startNewBuffer(filePos); + buffer[0] = val; + bufferPos = 1; + bufferValidEnd = 1; + bufferDirty = true; + return val; + } + startNewBuffer(fc.position()); + buffer[0] = val; + bufferPos = 1; + bufferValidEnd = 1; + bufferDirty = true; + return val; + } catch (IOException e) { + return -1; + } } byte[] arr = {val}; if (writeByteBuffer(ByteBuffer.wrap(arr))) { @@ -310,40 +498,34 @@ int getc() { if (this.fc == null) { return 0; } - if (USE_READ_BUFFER) { - if (readBufferIndex >= READ_BUFFER_SIZE) { - this.readBufferIndex = 0; - try { - ByteBuffer bb = ByteBuffer.wrap(readBuffer); - int readBytes = this.fc.read(bb); - if (readBytes <= 0) { - this.readBufferEndIndex = -1; - } else { - this.readBufferEndIndex = readBytes; + if (bufferSize > 0) { + try { + if (bufferActive && bufferPos < bufferValidEnd) { + return buffer[bufferPos++] & 0xFF; + } + if (bufferDirty) { + if (!flushBuffer()) { + return -1; } - } catch (IOException | NonReadableChannelException e) { + } + if (fillReadBuffer() < 0) { return -1; } - } - - if (this.readBufferIndex >= this.readBufferEndIndex) { + return buffer[bufferPos++] & 0xFF; + } catch (IOException e) { return -1; } - - return readBuffer[readBufferIndex++]; - - } else { - try { - byte[] b = new byte[1]; - ByteBuffer bb = ByteBuffer.wrap(b); - if (this.fc.read(bb) == 1) { - return b[0]; - } else { - return -1; - } - } catch (IOException | NonReadableChannelException e) { + } + try { + byte[] b = new byte[1]; + ByteBuffer bb = ByteBuffer.wrap(b); + if (this.fc.read(bb) == 1) { + return b[0] & 0xFF; + } else { return -1; } + } catch (IOException | NonReadableChannelException e) { + return -1; } } @@ -351,8 +533,9 @@ int getc() { void close() { if (!useStdOut && !useStdIn && this.fc != null) { try { - outputWriteBuffer(); - destroyWriteBuffer(); + flushBuffer(); + deactivateBuffer(); + this.bufferSize = 0; this.fc.close(); } catch (IOException e) { return; @@ -364,7 +547,7 @@ void close() { void flush() { if (!useStdOut) { try { - outputWriteBuffer(); + flushBuffer(); this.fc.force(false); } catch (IOException e) { return; @@ -388,16 +571,31 @@ void flush() { boolean seek(long offset, int origin) { if (!useStdOut && !useStdIn) { try { + long targetPos; switch (origin) { case FileIO.SEEK_SET: - this.fc.position(offset); + targetPos = offset; break; case FileIO.SEEK_CUR: - this.fc.position(this.fc.position() + offset); + targetPos = logicalPosition() + offset; break; default: return false; } + + if (bufferActive) { + long relativePos = targetPos - bufferFileOffset; + if (relativePos >= 0 && relativePos <= bufferValidEnd) { + bufferPos = (int) relativePos; + return true; + } + if (!flushBuffer()) { + return false; + } + deactivateBuffer(); + } + + this.fc.position(targetPos); } catch (IOException e) { return false; } @@ -411,11 +609,7 @@ void seekInit() {} /** TODO: 準備中 */ void rewind() { if (!useStdOut && !useStdIn) { - try { - this.fc.position(0L); - } catch (IOException e) { - return; - } + seek(0, SEEK_SET); } } diff --git a/tests/Makefile.am b/tests/Makefile.am index a14a525ca..bc20ada38 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -268,6 +268,7 @@ misc_DEPENDENCIES = \ misc.src/display-inspect-sign.at \ misc.src/comp1-comp2.at \ misc.src/variable-length-file.at \ + misc.src/seq-buffer.at \ misc.src/convert-string-concat.at \ misc.src/complex-odo.at diff --git a/tests/Makefile.in b/tests/Makefile.in index 6ae0a4324..bfdb571d3 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -817,6 +817,7 @@ misc_DEPENDENCIES = \ misc.src/display-inspect-sign.at \ misc.src/comp1-comp2.at \ misc.src/variable-length-file.at \ + misc.src/seq-buffer.at \ misc.src/convert-string-concat.at \ misc.src/complex-odo.at diff --git a/tests/misc.at b/tests/misc.at index 606706449..3aa7d0052 100644 --- a/tests/misc.at +++ b/tests/misc.at @@ -59,3 +59,4 @@ m4_include([comp1-comp2.at]) m4_include([variable-length-file.at]) m4_include([convert-string-concat.at]) m4_include([complex-odo.at]) +m4_include([seq-buffer.at]) diff --git a/tests/misc.src/seq-buffer.at b/tests/misc.src/seq-buffer.at new file mode 100644 index 000000000..d3a169397 --- /dev/null +++ b/tests/misc.src/seq-buffer.at @@ -0,0 +1,672 @@ +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL read]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTSEQ" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AAAA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BBBB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CCCC" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=10 ${RUN_MODULE} prog], [0], +[AAAA +BBBB +CCCC +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL read with buffer size 1]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTSEQ" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AAAA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BBBB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CCCC" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=1 ${RUN_MODULE} prog], [0], +[AAAA +BBBB +CCCC +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL read with buffer disabled]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTSEQ" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AAAA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BBBB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CCCC" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=0 ${RUN_MODULE} prog], [0], +[AAAA +BBBB +CCCC +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: LINE SEQUENTIAL read via getc]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTLSEQ" + ORGANIZATION LINE SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(8). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "LINE0001" TO TEST-REC. + WRITE TEST-REC. + MOVE "LINE0002" TO TEST-REC. + WRITE TEST-REC. + MOVE "LINE0003" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=10 ${RUN_MODULE} prog], [0], +[LINE0001 +LINE0002 +LINE0003 +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL I-O rewrite]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTREWR" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AAAA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BBBB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CCCC" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN I-O TEST-FILE. + READ TEST-FILE. + READ TEST-FILE. + MOVE "XXXX" TO TEST-REC. + REWRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=10 ${RUN_MODULE} prog], [0], +[AAAA +XXXX +CCCC +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL I-O interleaved read and rewrite]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTREWR" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "REC1" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC2" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC3" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC4" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC5" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC6" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC7" TO TEST-REC. + WRITE TEST-REC. + MOVE "REC8" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN I-O TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "UPD1" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "UPD3" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "UPD4" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "UPD6" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=2 ${RUN_MODULE} prog], [0], +[REC1 +REC2 +REC3 +REC4 +REC5 +REC6 +REC7 +REC8 +UPD1 +REC2 +UPD3 +UPD4 +REC5 +UPD6 +REC7 +REC8 +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL many records]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTMANY" + ORGANIZATION SEQUENTIAL + FILE STATUS F-STATUS. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(10). + WORKING-STORAGE SECTION. + 01 CTR PIC 9(4) VALUE 0. + 01 READ-CTR PIC 9(4) VALUE 0. + 01 F-STATUS PIC X(2). + 01 EOF-FLAG PIC 9 VALUE 0. + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + PERFORM 100 TIMES + ADD 1 TO CTR + MOVE CTR TO TEST-REC + WRITE TEST-REC + END-PERFORM. + CLOSE TEST-FILE. + + MOVE 0 TO READ-CTR. + MOVE 0 TO EOF-FLAG. + OPEN INPUT TEST-FILE. + PERFORM UNTIL EOF-FLAG = 1 + READ TEST-FILE + AT END + MOVE 1 TO EOF-FLAG + NOT AT END + ADD 1 TO READ-CTR + END-READ + END-PERFORM. + CLOSE TEST-FILE. + DISPLAY READ-CTR. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=3 ${RUN_MODULE} prog], [0], +[0100 +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: LINE SEQUENTIAL many records]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTLMNY" + ORGANIZATION LINE SEQUENTIAL + FILE STATUS F-STATUS. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(10). + WORKING-STORAGE SECTION. + 01 CTR PIC 9(4) VALUE 0. + 01 READ-CTR PIC 9(4) VALUE 0. + 01 F-STATUS PIC X(2). + 01 EOF-FLAG PIC 9 VALUE 0. + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + PERFORM 100 TIMES + ADD 1 TO CTR + MOVE CTR TO TEST-REC + WRITE TEST-REC + END-PERFORM. + CLOSE TEST-FILE. + + MOVE 0 TO READ-CTR. + MOVE 0 TO EOF-FLAG. + OPEN INPUT TEST-FILE. + PERFORM UNTIL EOF-FLAG = 1 + READ TEST-FILE + AT END + MOVE 1 TO EOF-FLAG + NOT AT END + ADD 1 TO READ-CTR + END-READ + END-PERFORM. + CLOSE TEST-FILE. + DISPLAY READ-CTR. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=3 ${RUN_MODULE} prog], [0], +[0100 +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_WRITE_BUFFER_SIZE: deprecated fallback]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTDEP" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AAAA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BBBB" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_WRITE_BUFFER_SIZE=10 ${RUN_MODULE} prog], [0], +[AAAA +BBBB +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL read then write in I-O mode]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTRW" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(4). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AAAA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BBBB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CCCC" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN I-O TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "ZZZZ" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=10 ${RUN_MODULE} prog], [0], +[AAAA +BBBB +CCCC +ZZZZ +BBBB +CCCC +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: SEQUENTIAL I-O repeated mode transitions]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTRW" + ORGANIZATION SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(2). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AA" TO TEST-REC. + WRITE TEST-REC. + MOVE "BB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CC" TO TEST-REC. + WRITE TEST-REC. + MOVE "DD" TO TEST-REC. + WRITE TEST-REC. + MOVE "EE" TO TEST-REC. + WRITE TEST-REC. + MOVE "FF" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN I-O TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "XX" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "YY" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + MOVE "ZZ" TO TEST-REC. + REWRITE TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + READ TEST-FILE. + DISPLAY TEST-REC. + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=1 ${RUN_MODULE} prog], [0], +[AA +BB +CC +DD +EE +FF +XX +YY +CC +DD +ZZ +FF +]) + +AT_CLEANUP + + +AT_SETUP([COB_FILE_SEQ_BUFFER_SIZE: LINE SEQUENTIAL read with short records]) + +AT_DATA([prog.cbl], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT TEST-FILE ASSIGN "TESTSHRT" + ORGANIZATION LINE SEQUENTIAL. + DATA DIVISION. + FILE SECTION. + FD TEST-FILE. + 01 TEST-REC PIC X(20). + PROCEDURE DIVISION. + OPEN OUTPUT TEST-FILE. + MOVE "AB" TO TEST-REC. + WRITE TEST-REC. + MOVE "CDEFGHIJ" TO TEST-REC. + WRITE TEST-REC. + MOVE "K" TO TEST-REC. + WRITE TEST-REC. + CLOSE TEST-FILE. + + OPEN INPUT TEST-FILE. + READ TEST-FILE. + DISPLAY ">" TEST-REC "<". + READ TEST-FILE. + DISPLAY ">" TEST-REC "<". + READ TEST-FILE. + DISPLAY ">" TEST-REC "<". + CLOSE TEST-FILE. + STOP RUN. +]) + +AT_CHECK([${COMPILE} prog.cbl]) +AT_CHECK([COB_FILE_SEQ_BUFFER_SIZE=2 ${RUN_MODULE} prog], [0], +[>AB < +>CDEFGHIJ < +>K < +]) + +AT_CLEANUP diff --git a/tests/package.m4 b/tests/package.m4 index 78d404454..4ce0d7d3d 100644 --- a/tests/package.m4 +++ b/tests/package.m4 @@ -1,6 +1,6 @@ # Signature of the current package. m4_define([AT_PACKAGE_NAME], [opensource COBOL 4J]) -m4_define([AT_PACKAGE_TARNAME], [opensource-cobol-4j-1.1.17]) -m4_define([AT_PACKAGE_VERSION], [1.1.17]) -m4_define([AT_PACKAGE_STRING], [opensource COBOL 4J 1.1.17]) +m4_define([AT_PACKAGE_TARNAME], [opensource-cobol-4j-1.1.18]) +m4_define([AT_PACKAGE_VERSION], [1.1.18]) +m4_define([AT_PACKAGE_STRING], [opensource COBOL 4J 1.1.18]) m4_define([AT_PACKAGE_BUGREPORT], [ws-opensource-cobol-contact@osscons.jp])