### Eclipse Workspace Patch 1.0 #P p2j Index: src/com/goldencode/p2j/util/ObjectOps.java =================================================================== --- src/com/goldencode/p2j/util/ObjectOps.java (revision 2731) +++ src/com/goldencode/p2j/util/ObjectOps.java (working copy) @@ -47,6 +47,8 @@ ** CA 20210215 An INPUT parameter at the property SETTER must be registered as pending, so its reference ** can be tracked. ** CA 20210310 Performance improvement in hasDestructor - cache the result of this method. +** CA 20210322 asResource(LegacyEnum) will always return an ObjectResource instance (and a resource ID +** computed), so temp-table fields can refer enums. */ /* @@ -1434,7 +1436,14 @@ */ public static ObjectResource asResource(_BaseObject_ ref) { - return local.get().objects.get(ref); + if (ref instanceof LegacyEnum) + { + return new ObjectResource(ref); + } + else + { + return local.get().objects.get(ref); + } } /** Index: src/com/goldencode/p2j/util/ArrayAssigner.java =================================================================== --- src/com/goldencode/p2j/util/ArrayAssigner.java (revision 2731) +++ src/com/goldencode/p2j/util/ArrayAssigner.java (working copy) @@ -58,8 +58,9 @@ ** CA 20210203 Fixed registration of extent variables (defined in a procedure/function) and ** extent parameters - they need to be registered as 'pending' and registered when ** the top-level scope is processed. -** 007 CA 20210223 If a dynamic array parameter is resized by the top-level block code, then the +** CA 20210223 If a dynamic array parameter is resized by the top-level block code, then the ** reference in the parameter instance must be updated. +** CA 20210322 Fixed dynamic arrays used in persistent programs or OO instances. */ /* @@ -1823,6 +1824,15 @@ private Map[], Class> dynamicArrayType = new IdentityHashMap<>(); + /** Map of dynamic arrays created in a persistent program. */ + private Map> persistentProcDynArrays = new IdentityHashMap<>(); + + public WorkArea() + { + // add a scope for the 'global' block where all the persistent procedure arrays are kept + dynamicArrays.push(Collections.newSetFromMap(new IdentityHashMap<>())); + } + @Override public void scopeStart() { @@ -1860,22 +1870,46 @@ } dynamicUndoableArrays.remove(referent); + + Set refs = persistentProcDynArrays.remove(referent); + if (refs != null && !refs.isEmpty()) + { + // cleanup after this persistent program - remove them from the global block and other collections + dynamicArrays.getFirst().removeAll(refs); + dynamicArrayPrecisions.keySet().removeAll(refs); + dynamicArrayCaseSens.keySet().removeAll(refs); + dynamicArrayType.keySet().removeAll(refs); + } } @Override public void scopeFinished() { + Object referent = pm._thisProcedure(); + if (!dynamicArrays.isEmpty()) { // remove scope-registered arrays Set arrays = dynamicArrays.pop(); - - // remove precisions and output extent param registrations - // for the arrays being removed - for (BaseDataType[] array : arrays) + + if (!arrays.isEmpty()) { - dynamicArrayPrecisions.remove(array); - dynamicArrayCaseSens.remove(array); + if (ProcedureManager._isPersistent(referent) && tm.isExternalBlock()) + { + // all dynamic arrays in a persistent program must be saved in the global block + dynamicArrays.getFirst().addAll(arrays); + persistentProcDynArrays.put(referent, arrays); + } + else + { + // remove precisions and output extent param registrations for the arrays being removed + for (BaseDataType[] array : arrays) + { + dynamicArrayPrecisions.remove(array); + dynamicArrayCaseSens.remove(array); + dynamicArrayType.remove(array); + } + } } } @@ -1884,7 +1918,6 @@ extentParameters.pop(); } - Object referent = pm._thisProcedure(); Deque> undoableExtStack = dynamicUndoableArrays.get(referent); if (undoableExtStack != null && undoableExtStack.size() > 1) { Index: src/com/goldencode/p2j/util/TextOps.java =================================================================== --- src/com/goldencode/p2j/util/TextOps.java (revision 2731) +++ src/com/goldencode/p2j/util/TextOps.java (working copy) @@ -2,7 +2,7 @@ ** Module : TextOps.java ** Abstract : Progress 4GL compatible TextOps object ** -** Copyright (c) 2012-2020, Golden Code Development Corporation. +** Copyright (c) 2012-2021, Golden Code Development Corporation. ** ** -#- -I- --Date-- ---------------------------------------Description--------------------------------------- ** 001 AIL 20121206 Created initial version by moving static methods from the character class as @@ -38,7 +38,9 @@ ** ME 20201127 Use resource id for objects in substitute. ** OM 20201202 Fixed support for substitution of Java Boolean values. ** VVT 20210106 splitInt(): typo in javadoc fixed. -** ME 20210128 Avoid using java's trim to check if string is empty, 4GL only consider spaces to be empty (not tab, cr, lf). +** ME 20210128 Avoid using java's trim to check if string is empty, 4GL only consider spaces to be empty +** (not tab, cr, lf). +** CA 20210322 Fixed SUBSTITUTE when a legacy enum instance is used. */ /* @@ -104,6 +106,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import com.goldencode.p2j.oo.lang.*; + /** * A class that provides Progress 4GL compatible character and longchar * functions and operators. This class provides all functionality as statics @@ -6455,7 +6459,18 @@ else if (obj instanceof object) { object o = (object) obj; - sb.append(object.resourceId(o)); + if (o.isUnknown()) + { + sb.append("?"); + } + else if (o.ref instanceof LegacyEnum) + { + sb.append(((LegacyEnum) o.ref)._getValue()); + } + else + { + sb.append(object.resourceId(o)); + } } else if (obj instanceof BaseDataType) { Index: src/com/goldencode/p2j/oo/net/serverconnection/ClientSocketConnectionParameters.java =================================================================== --- src/com/goldencode/p2j/oo/net/serverconnection/ClientSocketConnectionParameters.java (revision 2731) +++ src/com/goldencode/p2j/oo/net/serverconnection/ClientSocketConnectionParameters.java (working copy) @@ -205,7 +205,7 @@ internalProcedure(ClientSocketConnectionParameters.class, this, "SslCiphers", new Block((Body) () -> { - assignMulti(sslCiphers, var); + sslCiphers = (character[]) assignMulti(sslCiphers, var); })); } @@ -288,7 +288,7 @@ internalProcedure(ClientSocketConnectionParameters.class, this, "SslProtocols", new Block((Body) () -> { - assignMulti(sslProtocols, var); + sslProtocols = (character[]) assignMulti(sslProtocols, var); })); }