diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 80027df6..4f67db52 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -17,18 +17,23 @@ jobs: container: image: ${{ matrix.os }} steps: - + + - uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + - name: Install dependencies on Ubuntu 22.04 if: matrix.os == 'ubuntu:22.04' run: | apt update -y - apt install -y default-jdk build-essential bison flex gettext texinfo automake autoconf + apt install -y build-essential bison flex gettext texinfo automake autoconf - name: Install dependencies on AlmaLinux 9 if: matrix.os == 'almalinux:9' run: | dnf -y update - dnf install -y java-17-openjdk-devel gcc make bison flex automake autoconf diffutils gettext + dnf install -y gcc make bison flex automake autoconf diffutils gettext - name: Checkout opensource COBOL 4J uses: actions/checkout@v3 @@ -90,7 +95,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '17' + java-version: '11' - name: Install static analysis tools run: | diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index 0d190792..00000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Make a coverate report - -on: - workflow_dispatch: - -env: - CLASSPATH: ":/usr/lib/opensourcecobol4j/libcobj.jar" - -jobs: - run-tests: - runs-on: ubuntu-latest - steps: - - - name: Install dependencies on Ubuntu 22.04 - run: | - sudo apt update -y - sudo apt install -y default-jdk build-essential bison flex gettext texinfo automake autoconf gcovr - - - name: Checkout opensource COBOL 4J - uses: actions/checkout@v3 - - - name: Install opensource COBOL 4J - run: | - ./configure CFLAGS='-fprofile-arcs -ftest-coverage' --prefix=/usr/ - make - sudo make install - - #- name: Run tests "command-line-options" - # run: | - # cd tests/ - # ./command-line-options - - #- name: Run tests "misc" - # run: | - # cd tests/ - # ./misc - - #- name: Run tests "data-rep" - # run: | - # cd tests/ - # ./data-rep - - #- name: Run tests "i18n_sjis" - # run: | - # cd tests/ - # ./i18n_sjis - - #- name: Run tests "jp-compat" - # run: | - # cd tests/ - # ./jp-compat - - #- name: Run tests "run" - # run: | - # cd tests/ - # ./run - - #- name: Run tests "syntax" - # run: | - # cd tests/ - # ./syntax - - #- name: Run NIST test - # run: | - # cd tests/cobol85 - # make test - - #- name: Run Extra NIST test - # run: | - # cd tests/cobol85 - # make test-extra - - # #- name: Run tests "i18n_utf8" - # # run: | - # # ./configure --prefix=/usr/ --with-vbisam --enable-utf8 - # # make - # # make install - # # ./i18n_utf8 || true - # # cd ../ - - #- name: Make a coverage report - # run: | - # cd cobj - # gcov -l *.gcda - # gcovr -r . --html -o report.html - # mkdir coverage-report - # cp *.gcno *.gcda *.gcov report.html coverage-report - - #- name: Archive a coverage report - # uses: actions/upload-artifact@v3 - # with: - # name: code-coverage-report - # path: cobj/coverage-report/ \ No newline at end of file diff --git a/.github/workflows/test-nist.yml b/.github/workflows/test-nist.yml index 511950df..e40e96fd 100644 --- a/.github/workflows/test-nist.yml +++ b/.github/workflows/test-nist.yml @@ -29,17 +29,22 @@ jobs: with: name: opensourcecobol4j-${{ env.ARTIFACT_NAME }} + - uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + - name: Install dependencies on Ubuntu 22.04 if: matrix.os == 'ubuntu:22.04' run: | apt update -y - apt install -y default-jdk build-essential + apt install -y build-essential - name: Install dependencies on AlmaLinux 9 if: matrix.os == 'almalinux:9' run: | dnf -y update - dnf install -y java-17-openjdk-devel gcc make perl + dnf install -y gcc make perl - name: Install opensource COBOL 4J run: | diff --git a/.github/workflows/test-other.yml b/.github/workflows/test-other.yml index 97bbb64b..55a632c5 100644 --- a/.github/workflows/test-other.yml +++ b/.github/workflows/test-other.yml @@ -26,17 +26,22 @@ jobs: with: name: opensourcecobol4j-${{ env.ARTIFACT_NAME }} + - uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + - name: Install dependencies on Ubuntu 22.04 if: matrix.os == 'ubuntu:22.04' run: | apt update -y - apt install -y default-jdk build-essential + apt install -y build-essential - name: Install dependencies on AlmaLinux 9 if: matrix.os == 'almalinux:9' run: | dnf -y update - dnf install -y java-17-openjdk-devel gcc make diffutils + dnf install -y gcc make diffutils - name: Install opensource COBOL 4J run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index d74357a5..6f279540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## [1.0.17] - 2023-11-28 +### Added +* Implement sorting a table (#251) +* Implement functions SUBSTITUTE and SUBSTITUTE-CASE (#246) +### Changed +* Support JDK 11 (#249) + * Older versions are tested with JDK 17 and 1.0.17 is tested with JDK 11. + * Plan to support JDK 8 in the future. ## [1.0.16] - 2023-10-31 -## Added +### Added * Publish libcobj.jar in GitHub Packages * Implement intrinsic functions * ORD-MAX (#228) @@ -13,7 +22,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * SIGN (#231) * STORED-CHAR-LENGTH (#231) * TRIM (#244) -## Fixed +## [1.0.16] - 2023-10-31 +### Added +* Publish libcobj.jar in GitHub Packages +* Implement intrinsic functions + * ORD-MAX (#228) + * ORD-MIN (#228) + * SECONDS-FROM-FORMATTED-TIME (#231) + * SIGN (#231) + * STORED-CHAR-LENGTH (#231) + * TRIM (#244) +### Fixed * Fix `DECIMAL POINT IS COMMA` in `SPECIAL NAMES` clause. (#233) ## [1.0.15] - 2023-09-29 ### Added diff --git a/ChangeLog b/ChangeLog index a921016f..1ebcce6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2023-11-28 OSS Consortium + + * opensource COBOL 4J v1.0.17 released. + 2023-10-31 OSS Consortium * opensource COBOL 4J v1.0.16 released. diff --git a/NEWS b/NEWS index a3a2c709..c987bf24 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,18 @@ NEWS - user visible changes -*- outline -*- ----------------------------------------------------------------------- +* opensource COBOL 4J 1.0.17 + +** New Features + (1) Implement sorting a table + (2) Implement functions SUBSTITUTE and SUBSTITUTE-CASE +** Miscellaneous + (1) Support JDK 11 + (a) Older versions are tested with JDK 17 and 1.0.17 is tested with JDK 11. + (b) Plan to support JDK 8 in the future. + +----------------------------------------------------------------------- + * opensource COBOL 4J 1.0.16 ** New Features diff --git a/configure b/configure index 01754c72..c901c406 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for opensource COBOL 4J 1.0.16. +# Generated by GNU Autoconf 2.71 for opensource COBOL 4J 1.0.17. # # Report bugs to . # @@ -620,9 +620,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='opensource COBOL 4J' -PACKAGE_TARNAME='opensource-cobol-4j-1.0.16' -PACKAGE_VERSION='1.0.16' -PACKAGE_STRING='opensource COBOL 4J 1.0.16' +PACKAGE_TARNAME='opensource-cobol-4j-1.0.17' +PACKAGE_VERSION='1.0.17' +PACKAGE_STRING='opensource COBOL 4J 1.0.17' PACKAGE_BUGREPORT='ws-opensource-cobol-contact@osscons.jp' PACKAGE_URL='' @@ -1414,7 +1414,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures opensource COBOL 4J 1.0.16 to adapt to many kinds of systems. +\`configure' configures opensource COBOL 4J 1.0.17 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1464,7 +1464,7 @@ Fine tuning of the installation directories: --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root - [DATAROOTDIR/doc/opensource-cobol-4j-1.0.16] + [DATAROOTDIR/doc/opensource-cobol-4j-1.0.17] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] @@ -1486,7 +1486,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of opensource COBOL 4J 1.0.16:";; + short | recursive ) echo "Configuration of opensource COBOL 4J 1.0.17:";; esac cat <<\_ACEOF @@ -1617,7 +1617,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -opensource COBOL 4J configure 1.0.16 +opensource COBOL 4J configure 1.0.17 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2105,7 +2105,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by opensource COBOL 4J $as_me 1.0.16, which was +It was created by opensource COBOL 4J $as_me 1.0.17, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3403,8 +3403,8 @@ fi # Define the identity of the package. - PACKAGE='opensource-cobol-4j-1.0.16' - VERSION='1.0.16' + PACKAGE='opensource-cobol-4j-1.0.17' + VERSION='1.0.17' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -25367,7 +25367,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by opensource COBOL 4J $as_me 1.0.16, which was +This file was extended by opensource COBOL 4J $as_me 1.0.17, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25435,7 +25435,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -opensource COBOL 4J config.status 1.0.16 +opensource COBOL 4J config.status 1.0.17 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index d6c7c17e..ac319d5b 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.59) -AC_INIT([opensource COBOL 4J],[1.0.16],[ws-opensource-cobol-contact@osscons.jp],[opensource-cobol-4j-1.0.16]) +AC_INIT([opensource COBOL 4J],[1.0.17],[ws-opensource-cobol-contact@osscons.jp],[opensource-cobol-4j-1.0.17]) AC_CONFIG_SRCDIR([libcobj.h]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_TESTDIR([tests]) diff --git a/libcobj/app/build.gradle.kts b/libcobj/app/build.gradle.kts index 2393508c..d35d3018 100644 --- a/libcobj/app/build.gradle.kts +++ b/libcobj/app/build.gradle.kts @@ -14,6 +14,18 @@ repositories { mavenCentral() } +tasks { + javadoc { + options.encoding = "UTF-8" + } + compileJava { + options.encoding = "UTF-8" + } + compileTestJava { + options.encoding = "UTF-8" + } +} + dependencies { implementation("com.google.guava:guava:31.1-jre") implementation("org.xerial:sqlite-jdbc:3.30.1") @@ -22,7 +34,7 @@ dependencies { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(11)) + languageVersion.set(JavaLanguageVersion.of(8)) } } @@ -47,7 +59,7 @@ publishing { register("gpr") { groupId = "jp.osscons.opensourcecobol" artifactId = "libcobj" - version = "1.0.16" + version = "1.0.17" from(components["java"]) } } diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolIntrinsic.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolIntrinsic.java index 25fbeb23..3a1404b3 100644 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolIntrinsic.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/common/CobolIntrinsic.java @@ -2185,6 +2185,116 @@ public static AbstractCobolField funcStoredCharLength(AbstractCobolField srcfiel return currField; } + public static AbstractCobolField funcSubstitute( + int offset, int length, int params, AbstractCobolField... fields) { + int i, j, k; + int numreps = params / 2; + AbstractCobolField[] f1 = new AbstractCobolField[numreps]; + AbstractCobolField[] f2 = new AbstractCobolField[numreps]; + CobolDataStorage src = fields[0].getDataStorage(); + CobolDataStorage fData1; + int srcSize = fields[0].getSize(); + int fSize1; + StringBuilder rtn = new StringBuilder(); + + for (i = 0; i < params - 1; i++) { + if ((i % 2) == 0) { + f1[i / 2] = fields[i + 1]; + } else { + f2[i / 2] = fields[i + 1]; + } + } + + for (i = 0; i < srcSize; ) { + for (j = 0; j < numreps; j++) { + fData1 = f1[j].getDataStorage(); + fSize1 = f1[j].getSize(); + for (k = fSize1 - 1; k >= 0; k--) { + if (i + k >= srcSize || src.getByte(i + k) != fData1.getByte(k)) { + break; + } + } + if (k < 0) { + rtn.append(f2[j].getString()); + i += fSize1; + break; + } + } + if (j == numreps) { + rtn.append((char) src.getByte(i)); + i++; + } + } + + CobolFieldAttribute attr = + new CobolFieldAttribute(CobolFieldAttribute.COB_TYPE_ALPHANUMERIC, 0, 0, 0, null); + AbstractCobolField field = + CobolFieldFactory.makeCobolField(rtn.length(), (CobolDataStorage) null, attr); + makeFieldEntry(field); + currField.setDataStorage(new CobolDataStorage(rtn.toString())); + + if (offset > 0) { + calcRefMod(currField, offset, length); + } + return currField; + } + + public static AbstractCobolField funcSubstituteCase( + int offset, int length, int params, AbstractCobolField... fields) { + int i, j, k; + int numreps = params / 2; + AbstractCobolField[] f1 = new AbstractCobolField[numreps]; + AbstractCobolField[] f2 = new AbstractCobolField[numreps]; + CobolDataStorage src = fields[0].getDataStorage(); + CobolDataStorage fData1; + int srcSize = fields[0].getSize(); + int fSize1; + StringBuilder rtn = new StringBuilder(); + + for (i = 0; i < params - 1; i++) { + if (i % 2 == 0) { + f1[i / 2] = fields[i + 1]; + } else { + f2[i / 2] = fields[i + 1]; + } + } + + for (i = 0; i < srcSize; ) { + for (j = 0; j < numreps; j++) { + fData1 = f1[j].getDataStorage(); + fSize1 = f1[j].getSize(); + for (k = fSize1 - 1; k >= 0; k--) { + if (i + k >= srcSize + || Character.toLowerCase((char) fData1.getByte(k)) + != Character.toLowerCase((char) src.getByte(i + k))) { + break; + } + } + if (k < 0) { + rtn.append(f2[j].getString()); + i += fSize1; + break; + } + } + if (j == numreps) { + rtn.append((char) src.getByte(i)); + i++; + } + } + + CobolFieldAttribute attr = + new CobolFieldAttribute(CobolFieldAttribute.COB_TYPE_ALPHANUMERIC, 0, 0, 0, null); + AbstractCobolField field = + CobolFieldFactory.makeCobolField(rtn.length(), (CobolDataStorage) null, attr); + makeFieldEntry(field); + + currField.setDataStorage(new CobolDataStorage(rtn.toString())); + if (offset > 0) { + calcRefMod(currField, offset, length); + } + return currField; + } + /** Equivalent to cob_intr_trim */ public static AbstractCobolField funcTrim( int offset, int length, AbstractCobolField srcField, int direction) { diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/data/CobolDataStorage.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/data/CobolDataStorage.java index 9eee80b5..b8855fb0 100644 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/data/CobolDataStorage.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/data/CobolDataStorage.java @@ -71,10 +71,19 @@ public CobolDataStorage() { this.data = null; } + public void setDataRefAndIndex(CobolDataStorage data, int index) { + this.data = data.data; + this.index = index; + } + public int getIndex() { return this.index; } + public void setIndex(int index) { + this.index = index; + } + public byte[] getRefOfData() { return this.data; } @@ -158,13 +167,6 @@ public byte[] getByteArray(int index, int length) { return result; } - public byte[] getByteArray() { - int length = this.data.length; - byte[] result = new byte[length]; - System.arraycopy(this.data, this.index, result, 0, length); - return result; - } - /** * C言語のmemcpy * diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFileSort.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFileSort.java index 854f1bf0..5a8629c1 100644 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFileSort.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolFileSort.java @@ -31,6 +31,7 @@ import jp.osscons.opensourcecobol.libcobj.common.CobolUtil; import jp.osscons.opensourcecobol.libcobj.data.AbstractCobolField; import jp.osscons.opensourcecobol.libcobj.data.CobolDataStorage; +import jp.osscons.opensourcecobol.libcobj.data.CobolFieldAttribute; import jp.osscons.opensourcecobol.libcobj.data.CobolFieldFactory; import jp.osscons.opensourcecobol.libcobj.exceptions.CobolStopRunException; @@ -903,4 +904,177 @@ public static void performReturn(CobolFile f) { return; } } + + /* Table sort */ + private static int sortNKeys; + private static CobolFileKey[] sortKeys; + private static CobolDataStorage sortCollate; + private static CobolDataStorage pivotStorage = new CobolDataStorage(); + private static CobolDataStorage leftStorage = new CobolDataStorage(); + private static CobolDataStorage rightStorage = new CobolDataStorage(); + private static CobolDataStorage cmpStorage1 = new CobolDataStorage(); + private static CobolDataStorage cmpStorage2 = new CobolDataStorage(); + private static CobolDataStorage copyBuffer = null; + private static CobolDataStorage tmpRecord = new CobolDataStorage(); + private static int copyBufferSizeMax = 0; + private static int[] sortBuffer = null; + private static AbstractCobolField cmpField1 = + CobolFieldFactory.makeCobolField( + 0, + cmpStorage1, + new CobolFieldAttribute(CobolFieldAttribute.COB_TYPE_ALPHANUMERIC, 0, 0, 0, null)); + private static AbstractCobolField cmpField2 = + CobolFieldFactory.makeCobolField( + 0, + cmpStorage2, + new CobolFieldAttribute(CobolFieldAttribute.COB_TYPE_ALPHANUMERIC, 0, 0, 0, null)); + + public static void sortTableInit(int nkeys, int collatingSequence) { + sortTableInit(nkeys, null); + } + + public static void sortTableInit(int nkeys, CobolDataStorage collatingSequence) { + sortNKeys = 0; + if (sortKeys == null || sortKeys.length < nkeys) { + sortKeys = new CobolFileKey[nkeys]; + } + if (collatingSequence != null) { + sortCollate = collatingSequence; + } else { + sortCollate = CobolModule.getCurrentModule().collating_sequence; + } + } + + public static void sortTableInitKey(int flag, AbstractCobolField field, int offset) { + if (sortKeys[sortNKeys] == null) { + sortKeys[sortNKeys] = new CobolFileKey(); + } + sortKeys[sortNKeys].setFlag(flag); + sortKeys[sortNKeys].setField( + CobolFieldFactory.makeCobolField( + field.getSize(), (CobolDataStorage) null, field.getAttribute())); + sortKeys[sortNKeys].setOffset(offset); + sortNKeys++; + } + + public static void sortTable(AbstractCobolField f, int n) { + int recordSize = f.getSize(); + if (sortBuffer == null || sortBuffer.length < n) { + sortBuffer = new int[n]; + } + for (int i = 0; i < n; ++i) { + sortBuffer[i] = i; + } + CobolDataStorage baseStorage = f.getDataStorage(); + int baseStorageBaseIndex = baseStorage.getIndex(); + indexQuickSort(f.getDataStorage(), 0, n, recordSize); + + int copyBufferSize = n * f.getSize(); + if (copyBuffer == null || copyBufferSizeMax < copyBufferSize) { + copyBuffer = new CobolDataStorage(copyBufferSize); + copyBufferSizeMax = copyBufferSize; + } + + for (int i = 0; i < n; ++i, copyBuffer.addIndex(recordSize)) { + tmpRecord.setDataRefAndIndex(baseStorage, baseStorageBaseIndex + recordSize * sortBuffer[i]); + copyBuffer.memcpy(tmpRecord, recordSize); + } + copyBuffer.setIndex(0); + baseStorage.memcpy(copyBuffer, copyBufferSize); + } + + private static void indexQuickSort( + CobolDataStorage base, int mostLeft, int mostRight, int recordSize) { + + if (mostRight - mostLeft <= 1) { + return; + } + + int pivot = (mostRight + mostLeft) / 2; + int left = mostLeft, right = mostRight - 1; + + while (true) { + pivotStorage.setDataRefAndIndex(base, base.getIndex() + sortBuffer[pivot] * recordSize); + boolean elementBiggerThanPivot = false; + for (; left < pivot; ++left) { + leftStorage.setDataRefAndIndex(base, base.getIndex() + sortBuffer[left] * recordSize); + if (compareStorageForSort(leftStorage, pivotStorage) > 0) { + elementBiggerThanPivot = true; + break; + } + } + boolean elementSmallerThanPivot = false; + for (; right > pivot; --right) { + rightStorage.setDataRefAndIndex(base, base.getIndex() + sortBuffer[right] * recordSize); + if (compareStorageForSort(pivotStorage, rightStorage) > 0) { + elementSmallerThanPivot = true; + break; + } + } + if (elementBiggerThanPivot && elementSmallerThanPivot) { + swap2Indecies(left, right); + ++left; + --right; + } else if (elementBiggerThanPivot && !elementSmallerThanPivot) { + if (left + 1 == pivot) { + swap2Indecies(left, pivot); + } else { + rotate3Indecies(pivot, pivot - 1, left); + } + --pivot; + } else if (!elementBiggerThanPivot && elementSmallerThanPivot) { + if (right - 1 == pivot) { + swap2Indecies(pivot, right); + } else { + rotate3Indecies(pivot, pivot + 1, right); + } + ++pivot; + } else { + break; + } + } + indexQuickSort(base, mostLeft, pivot, recordSize); + indexQuickSort(base, pivot + 1, mostRight, recordSize); + } + + private static int compareStorageForSort(CobolDataStorage s1, CobolDataStorage s2) { + for (int i = 0; i < sortNKeys; ++i) { + int keySize = sortKeys[i].getField().getSize(); + cmpField1.setSize(keySize); + cmpField2.setSize(keySize); + + CobolFieldAttribute attr = sortKeys[i].getField().getAttribute(); + cmpField1.setAttribute(attr); + cmpField2.setAttribute(attr); + + cmpStorage1.setDataRefAndIndex(s1, s1.getIndex() + sortKeys[i].getOffset()); + cmpStorage2.setDataRefAndIndex(s2, s2.getIndex() + sortKeys[i].getOffset()); + + int cmp; + if (attr.isTypeNumeric()) { + cmp = cmpField1.numericCompareTo(cmpField2); + } else if (attr.isTypeNational()) { + cmp = CobolUtil.nationalCmps(s1, s2, keySize, sortCollate); + } else { + cmp = cmpField1.cmpAlnum(cmpField2); + } + if (cmp != 0) { + return (sortKeys[i].getFlag() == COB_ASCENDING) ? cmp : -cmp; + } + } + return 0; + } + + private static void swap2Indecies(int a, int b) { + int tmp = sortBuffer[a]; + sortBuffer[a] = sortBuffer[b]; + sortBuffer[b] = tmp; + } + + private static void rotate3Indecies(int a, int b, int c) { + int tmp = sortBuffer[c]; + sortBuffer[c] = sortBuffer[b]; + sortBuffer[b] = sortBuffer[a]; + sortBuffer[a] = tmp; + } } diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolIndexedFile.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolIndexedFile.java index abce08d2..03373a50 100644 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolIndexedFile.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/CobolIndexedFile.java @@ -256,7 +256,7 @@ public int indexed_start_internal( boolean isDuplicate = this.keys[p.key_index].getFlag() != 0; this.cursor = IndexedCursor.createCursor(p.connection, p.key, p.key_index, isDuplicate, cond); - if (this.cursor.isEmpty()) { + if (!this.cursor.isPresent()) { return COB_STATUS_30_PERMANENT_ERROR; } @@ -316,25 +316,25 @@ public int readNext(int readOpts) { if (this.indexedFirstRead || this.flag_begin_of_file) { this.cursor = IndexedCursor.createCursor(p.connection, p.key, p.key_index, isDuplicate, COB_GE); - if (this.cursor.isEmpty()) { + if (!this.cursor.isPresent()) { return COB_STATUS_10_END_OF_FILE; } this.cursor.get().moveToFirst(); } else if (this.flag_end_of_file) { this.cursor = IndexedCursor.createCursor(p.connection, p.key, p.key_index, isDuplicate, COB_LE); - if (this.cursor.isEmpty()) { + if (!this.cursor.isPresent()) { return COB_STATUS_30_PERMANENT_ERROR; } this.cursor.get().moveToLast(); } else if (this.updateWhileReading) { this.updateWhileReading = false; - if (this.cursor.isEmpty()) { + if (!this.cursor.isPresent()) { return COB_STATUS_30_PERMANENT_ERROR; } IndexedCursor oldCursor = this.cursor.get(); Optional newCursor = oldCursor.reloadCursor(); - if (newCursor.isEmpty()) { + if (!newCursor.isPresent()) { this.cursor = Optional.of(oldCursor); } else { oldCursor.close(); @@ -342,7 +342,7 @@ public int readNext(int readOpts) { } } - if (this.cursor.isEmpty()) { + if (!this.cursor.isPresent()) { return COB_STATUS_30_PERMANENT_ERROR; } @@ -361,7 +361,7 @@ public int readNext(int readOpts) { this.indexedFirstRead = false; - if (optionalResult.isEmpty()) { + if (!optionalResult.isPresent()) { return COB_STATUS_10_END_OF_FILE; } else { FetchResult result = optionalResult.get(); diff --git a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/IndexedCursor.java b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/IndexedCursor.java index d919bae0..98d95054 100644 --- a/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/IndexedCursor.java +++ b/libcobj/app/src/main/java/jp/osscons/opensourcecobol/libcobj/file/IndexedCursor.java @@ -128,7 +128,7 @@ public static Optional createCursor( IndexedCursor cursor = new IndexedCursor(conn, key, tableIndex, isDuplicate, comparator); cursor.forwardCursor = getCursor(conn, key, tableIndex, isDuplicate, comparator, true); cursor.backwardCursor = getCursor(conn, key, tableIndex, isDuplicate, comparator, false); - if (cursor.forwardCursor.isEmpty() || cursor.backwardCursor.isEmpty()) { + if (!cursor.forwardCursor.isPresent() || !cursor.backwardCursor.isPresent()) { return Optional.empty(); } else { return Optional.of(cursor); @@ -178,14 +178,14 @@ public Optional reloadCursor() { Optional reFetchResult = reFetch(this.conn, this.tableIndex, this.isDuplicate, result); - if (!reFetchResult.isEmpty()) { + if (reFetchResult.isPresent()) { FetchResult r = reFetchResult.get(); newCursor.forwardBuffer.add(r); newCursor.cursorIndex = 0; newCursor.firstFetch = false; } - if (newCursor.forwardCursor.isEmpty() || newCursor.backwardCursor.isEmpty()) { + if (!newCursor.forwardCursor.isPresent() || !newCursor.backwardCursor.isPresent()) { return Optional.empty(); } else { return Optional.of(newCursor); @@ -409,7 +409,7 @@ private Optional fetchPrev(ResultSet cursor) { * return Optional.empty() */ public Optional next() { - if (this.forwardCursor.isEmpty()) { + if (!this.forwardCursor.isPresent()) { return Optional.empty(); } ResultSet cursor = this.forwardCursor.get(); @@ -458,7 +458,7 @@ public Optional next() { * return Optional.empty() */ public Optional prev() { - if (this.backwardCursor.isEmpty()) { + if (!this.backwardCursor.isPresent()) { return Optional.empty(); } ResultSet cursor = this.backwardCursor.get(); @@ -524,7 +524,7 @@ private static Optional getCursor( boolean forward) { final Optional optionalCompOperator = getCompOperator(comparator, forward); - if (optionalCompOperator.isEmpty()) { + if (!optionalCompOperator.isPresent()) { return Optional.empty(); } @@ -617,7 +617,7 @@ private Optional getCursorForFirstLast( public boolean moveToFirst() { Optional cursor = getCursorForFirstLast(this.tableIndex, this.isDuplicate, CursorReadOption.FIRST); - if (cursor.isEmpty()) { + if (!cursor.isPresent()) { return false; } this.forwardCursor = cursor; @@ -630,7 +630,7 @@ public boolean moveToFirst() { public boolean moveToLast() { Optional cursor = getCursorForFirstLast(this.tableIndex, this.isDuplicate, CursorReadOption.LAST); - if (cursor.isEmpty()) { + if (!cursor.isPresent()) { return false; } this.backwardCursor = cursor; diff --git a/tests/run.src/functions.at b/tests/run.src/functions.at index 420c0010..c3788b92 100755 --- a/tests/run.src/functions.at +++ b/tests/run.src/functions.at @@ -1625,7 +1625,6 @@ AT_CHECK([java prog], [0], AT_CLEANUP AT_SETUP([FUNCTION SUBSTITUTE]) -AT_CHECK([${SKIP_TEST}]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -1637,18 +1636,27 @@ AT_DATA([prog.cob], [ MOVE "abc111444555defxxabc" TO Y. DISPLAY FUNCTION SUBSTITUTE ( Y "abc" "zz" "55" "666" ) END-DISPLAY. + MOVE "abc111444555defxxabc" TO Y. + DISPLAY FUNCTION SUBSTITUTE + ( Y "abc" "55" "55" "666" ) + END-DISPLAY. + MOVE "abc111444555defxxabc" TO Y. + DISPLAY FUNCTION SUBSTITUTE + ( Y "abc1" "666" "abc" "zz" ) + END-DISPLAY. STOP RUN. ]) AT_CHECK([${COMPILE} prog.cob]) AT_CHECK([java prog], [0], [zz1114446665defxxzz +551114446665defxx55 +66611444555defxxzz ]) AT_CLEANUP AT_SETUP([FUNCTION SUBSTITUTE with reference modding]) -AT_CHECK([${SKIP_TEST}]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -1672,7 +1680,6 @@ AT_CHECK([java prog], [0], AT_CLEANUP AT_SETUP([FUNCTION SUBSTITUTE-CASE]) -AT_CHECK([${SKIP_TEST}]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -1684,18 +1691,28 @@ AT_DATA([prog.cob], [ MOVE "ABC111444555defxxabc" TO Y. DISPLAY FUNCTION SUBSTITUTE-CASE (Y "abc" "zz" "55" "666") END-DISPLAY. + MOVE "abc111444555defxxABC" TO Y. + DISPLAY FUNCTION SUBSTITUTE-CASE + ( Y "abc" "55" "55" "666" ) + END-DISPLAY. + + MOVE "abc111444555defxxABC" TO Y. + DISPLAY FUNCTION SUBSTITUTE-CASE + ( Y "abc1" "666" "abc" "zz" ) + END-DISPLAY. STOP RUN. ]) AT_CHECK([${COMPILE} prog.cob]) AT_CHECK([java prog], [0], [zz1114446665defxxzz +551114446665defxx55 +66611444555defxxzz ]) AT_CLEANUP AT_SETUP([FUNCTION SUBSTITUTE-CASE with reference mod]) -AT_CHECK([${SKIP_TEST}]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -1704,7 +1721,7 @@ AT_DATA([prog.cob], [ WORKING-STORAGE SECTION. 01 Y PIC X(20). PROCEDURE DIVISION. - MOVE "abc111444555defxxabc" TO Y. + MOVE "abc111444555defxxABC" TO Y. DISPLAY FUNCTION SUBSTITUTE-CASE ( Y "ABC" "zz" "55" "666" ) (2 : 9) END-DISPLAY. diff --git a/tests/run.src/miscellaneous.at b/tests/run.src/miscellaneous.at index ae1d7c27..8ca8c3e5 100644 --- a/tests/run.src/miscellaneous.at +++ b/tests/run.src/miscellaneous.at @@ -1366,7 +1366,6 @@ AT_CLEANUP AT_SETUP([SORT: table sort]) -AT_CHECK([${SKIP_TEST}]) AT_DATA([prog.cob], [ IDENTIFICATION DIVISION. @@ -1374,22 +1373,43 @@ AT_DATA([prog.cob], [ DATA DIVISION. WORKING-STORAGE SECTION. 01 G VALUE "d4b2e1a3c5". - 02 TBL OCCURS 5. + 02 TBL-G OCCURS 5. 03 X PIC X. 03 Y PIC 9. - PROCEDURE DIVISION. - SORT TBL ASCENDING KEY X. - DISPLAY G - END-DISPLAY. - SORT TBL DESCENDING KEY Y. - DISPLAY G - END-DISPLAY. - SORT TBL ASCENDING KEY TBL. - DISPLAY G - END-DISPLAY. - SORT TBL DESCENDING KEY. - DISPLAY G - END-DISPLAY. + 01 H VALUE "d4Db2Be3Ea5Ac6Cf1F". + 02 TBL-H OCCURS 6. + 03 A PIC X. + 03 B PIC 9. + 03 C PIC X. + PROCEDURE DIVISION. + SORT TBL-G ASCENDING KEY X. + DISPLAY G. + SORT TBL-G DESCENDING KEY Y. + DISPLAY G. + SORT TBL-G ASCENDING KEY TBL-G. + DISPLAY G. + SORT TBL-G DESCENDING KEY. + DISPLAY G. + + SORT TBL-H ASCENDING KEY A. + DISPLAY H. + SORT TBL-H DESCENDING KEY B. + DISPLAY H. + SORT TBL-H DESCENDING KEY C. + DISPLAY H. + SORT TBL-H ASCENDING KEY TBL-H. + DISPLAY H. + SORT TBL-H DESCENDING KEY. + DISPLAY H. + + SORT TBL-G ASCENDING KEY X. + DISPLAY G. + SORT TBL-G DESCENDING KEY Y. + DISPLAY G. + SORT TBL-G ASCENDING KEY TBL-G. + DISPLAY G. + SORT TBL-G DESCENDING KEY. + DISPLAY G. STOP RUN. ]) @@ -1399,6 +1419,15 @@ AT_CHECK([java prog], [0], c5d4a3b2e1 a3b2c5d4e1 e1d4c5b2a3 +a5Ab2Bc6Cd4De3Ef1F +c6Ca5Ad4De3Eb2Bf1F +f1Fe3Ed4Dc6Cb2Ba5A +a5Ab2Bc6Cd4De3Ef1F +f1Fe3Ed4Dc6Cb2Ba5A +a3b2c5d4e1 +c5d4a3b2e1 +a3b2c5d4e1 +e1d4c5b2a3 ]) AT_CLEANUP diff --git a/texi/open-cobol.info b/texi/open-cobol.info index 7b4fe514..b886fbec 100644 --- a/texi/open-cobol.info +++ b/texi/open-cobol.info @@ -1,4 +1,4 @@ -This is open-cobol.info, produced by makeinfo version 6.7 from +This is open-cobol.info, produced by makeinfo version 6.8 from open-cobol.texi. INFO-DIR-SECTION COBOL