How to iterate through temp-table that is being accessed using buffer? - progress-4gl

I have found an article, about accessing temp-table that is declared inside the class, from outside the class.
I'm trying to use 2nd solution(using handles and buffer). And while it works(i can get 1st or last element from it), i can't find a way to iterate through full temp-table.
Thank you.

You could do it by creating a dynamic query and attaching it to the buffer handle:
Class2.cls looks exactly the same, if added it below for reference.
Test2.p is changed:
DEF VAR c-class2 AS Class2.
DEF VAR local-ttbuf-hdl AS HANDLE.
DEF VAR tt-def-buff AS HANDLE.
c-class2 = NEW Class2().
local-ttbuf-hdl = c-class2:GetTempTableHandle().
tt-def-buff = local-ttbuf-hdl:DEFAULT-BUFFER-HANDLE.
/*
/* Find last is commented out */
tt-def-buff:FIND-LAST().
MESSAGE tt-def-buff:BUFFER-FIELD(1):buffer-value SKIP
tt-def-buff:BUFFER-FIELD(2):buffer-value
VIEW-AS ALERT-BOX.
*/
/**** New code here ****/
/* Define and create a dynamic query */
DEFINE VARIABLE hQuery AS HANDLE NO-UNDO.
CREATE QUERY hQuery.
/* Set the buffer */
hQuery:SET-BUFFERS(tt-def-buff).
/* Create a query-string */
hQuery:QUERY-PREPARE("FOR EACH " + tt-def-buff:NAME).
/* Open the query */
hQuery:QUERY-OPEN.
REPEAT :
/* Get the next record, for the first run it will be the first record */
hQuery:GET-NEXT().
/* Leave the repeat if there are no more records */
IF hQuery:QUERY-OFF-END THEN LEAVE.
/* Display */
MESSAGE tt-def-buff:BUFFER-FIELD(1):buffer-value SKIP
tt-def-buff:BUFFER-FIELD(2):buffer-value
VIEW-AS ALERT-BOX.
END.
/* All created objects should be deleted */
DELETE OBJECT hQuery.
Class2.cls:
CLASS class2:
DEF VAR i AS INTEGER.
DEF TEMP-TABLE tt
FIELD i1 AS INTEGER
FIELD c1 AS CHARACTER.
CONSTRUCTOR class2():
DO i = 1 TO 10:
CREATE tt.
ASSIGN
tt.i1 = i
tt.c1 = STRING(i).
END.
END CONSTRUCTOR.
METHOD PUBLIC HANDLE GetTempTableHandle():
RETURN TEMP-TABLE tt:HANDLE.
END.
END CLASS.

Related

Get the actual structure size before alignment

So it turns out that both dt struct and ?? sizeof struct return the total size the struct occupies in memory after alignment.
Is there a way to get the actual size of the struct before alignment?
I need this functionality for a function that returns the actual size of a field within a struct. For example:
__declspec(align(64)) struct ALIGNED_STRUCT {
char field;
}
running ?? sizeof(ALIGNED_STRUCT) one should get 0x40 which makes it hard to deduce the actual size of the internal field.
edit:
command outputs:
2:001> dt -v ALIGNED_STRUCT
test!ALIGNED_STRUCT
struct ALIGNED_STRUCT, 1 elements, 0x40 bytes
+0x000 field : Char
3:001> ?? sizeof(ALIGNED_STRUCT)
0x40
No -- there isn't a way to return the structure size "before alignment". That's not really meaningful in any case. The compiler is always using the aligned size. The symbols have the aligned size. That's the size of the type.
If you are looking for things like the "size of an internal field", there are numerous ways to accomplish this. As mentioned in comments, you can do the quick dirty EE sizeof thing:
dx sizeof(((ALIGNED_STRUCT *)0)->field)
You can also get full access to the underlying type system via the data model APIs (in either a C/C++ extension or in JavaScript) which will allow you to find out pretty much whatever you want about the types: their fields, sizes, offsets, function parameter types, template arguments, etc...
From C/C++, you can:
QI for IDebugHostSymbols (https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/dbgmodel/nn-dbgmodel-idebughostsymbols)
Get an IDebugHostModule (https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/dbgmodel/nn-dbgmodel-idebughostmodule) for the module containing your structure by calling the FindModuleByName method.
Get an IDebugHostType (https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/dbgmodel/nn-dbgmodel-idebughosttype) for the type you want to inquire about (e.g.: ALIGNED_STRUCT) by calling FindTypeByName
Enumerate its fields with EnumerateChildren, getting an IDebugHostField (https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/dbgmodel/nn-dbgmodel-idebughostfield) for each
Get the offset of such field by calling GetOffset
Get the type of each field by calling GetType, getting you back to another IDebugHostType
Get the size of the field by calling GetSize
That might look something like this:
ComPtr<IDebugHostSymbols> spHostSymbols; /* QI this off IDebugClient, etc... */
ComPtr<IDebugHostModule> spMyModule;
if (FAILED(spHostSymbols->FindModuleByName(USE_CURRENT_HOST_CONTEXT, L"myModule", &spMyModule)))
{
return ...;
}
ComPtr<IDebugHostType> spType;
if (FAILED(spMyModule->FindTypeByName(L"ALIGNED_STRUCT", &spType)))
{
return ...;
}
ComPtr<IDebugHostType> spType; /* get the type of an object */
//
// Enumerate every field of this type. Note thiat this *WILL NOT* enumerate
// fields of base classes!
//
ComPtr<IDebugHostSymbolEnumerator> spEnum;
if (SUCCEEDED(spType->EnumerateChildren(SymbolField, nullptr, &spEnum)))
{
ComPtr<IDebugHostSymbol> spFieldSymbol;
HRESULT hr = S_OK;
while (SUCCEEDED(hr))
{
hr = spEnum->GetNext(&spFieldSymbol);
if (SUCCEEDED(hr))
{
ComPtr<IDebugHostField> spField;
if (SUCCEEDED(spFieldSymbol.As(&spField))) /* should always succeed */
{
// spField is each field of the type in turn
}
ULONG64 fieldOffset;
if (SUCCEEDED(spField->GetOffset(&fieldOffset)) /* won't succeed on static fields */
{
// fieldOffset is the offset of the field within the type
}
ComPtr<IDebugHostType> spFieldType;
if (SUCCEEDED(spField->GetType(&spFieldType))
{
ULONG64 fieldSize;
if (SUCCEEDED(spFieldType->GetSize(&fieldSize)))
{
// fieldSize contains the size (aligned) of the field's type
}
}
}
}
// hr == E_BOUNDS : we hit the end of the enumerator
// hr == E_ABORT : user requested interruption, propagate upwards immediately
}
For C++, this can be made significantly easier by using the C++17 helper library on GitHub (https://github.com/microsoft/WinDbg-Libraries/blob/master/DbgModelCppLib/DbgModelClientEx.h)
That might look something like:
Module myModule(HostContext::DeferredCurrent(), L"myModule");
Type alignedStruct(myModule, L"ALIGNED_STRUCT");
//
// The below will *NOT* enumerate fields of base classes. You must explicitly
// recurse if you want such.
//
for(Field f : alignedStruct.Fields())
{
//
// Get the offset and size of each field.
//
ULONG64 fieldOffset = f.GetOffset();
ULONG64 fieldSize = f.Type().Size();
}
In JavaScript (see https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/native-objects-in-javascript-extensions-type-objects), this would look like:
Call host.getModuleType to get a type object for the structure (e.g.: ALIGNED_STRUCT)
Get access to the field in question by accessing the named property of fields on the type (e.g.: myType.fields.field_name)
Get the offset of of such field by accessing the offset property
Get the type of each field by accessing the type property
Get the size of the field by accessing the size property of its type
That might look something like:
var myType = host.getModuleType("myModule", "ALIGNED_STRUCT");
var fields = myType.fields;
//
// In JavaScript, fields has properties named according to each field. If
// you want to enumerate, get the property names and access those keys.
//
var fieldNames = Object.getOwnPropertyNames(fields);
for (var fieldName of fieldNames)
{
var field = fields[fieldName];
//
// Get the offset and size of each field...
//
var fieldOffset = field.offset;
var fieldSize = field.type.size;
}
In either of these cases, you would need to manually recurse base classes if you're looking at C++ objects where fields are contained in base classes.
Hope that helps...
William has provided a comprehensive answer this answer is just a practical example of that
0:000> dx #$stru
#$stru : Pcb _KPROCESS (+ 0x0)
name : Pcb
type : _KPROCESS
locationKind : member
offset : 0x0
0:000> dx #$stru.type.fields.Header.type.size
#$stru.type.fields.Header.type.size : 0x18
0:000>

Writing #value in javadoc brackets remove - Eclipse

I would like to write javadoc in Eclipse.
I have this piece of code:
private int variable;
When I want to add #value parametar in Eclipse above line I get {#value} instead of #value. When I want to add #author, I get output without {} brackets, as I want. How can I get #value without brackets?
Since the #value tag appears in running text, it should be in braces. It is not a tag like #author, which occurs at the end and basically considers the text up to the next (braceless) tag as its parameters.
So Eclipse's suggestion is correct. Why do you want to use that tag without braces?
The Javadoc tool will replace #value tags with the value of the constant it documents (if no parameter is given) or with the value of the constant mentioned in the parameter. For example:
/** The value {#value}. */
public static int aConstant = 1;
/**
* Does something.
* #param aValue should be {#value #aConstant}.
* #return 42
*/
public int aMethod(int aValue) {
...
}

How to pass parameters to a Progress program using database field dynamic-based rules?

I have in my database a set of records that concentrates information about my .W's, e.g. window name, parent directory, file name, procedure type (for internal treatments purposes), used to build my main menu. With this data I'm developing a new start procedure for the ERP that I maintain and using the opportunity in order to rewrite some really outdated functions and programs and implement new functionalities. Until now, I hadn't any problems but when I started to develop the .P procedure which will check the database register of a program that was called from the menu of this new start procedure - to check if it needs to receive fixed parameters to be run and its data types - I found a problem that I can't figure out a solution.
In this table, I have stored in one of the fields the parameters needed by the program, each with his correspondent data type. The problem is on how to pass different data types to procedures based only on the stored data. I tried to pre-convert data using a CASE clause and an include to check the parameter field for correct parameter sending but the include doesn't work as I've expected.
My database field is stored as this:
Description | DATATYPE | Content
I've declared some variables and converted properly the stored data into their correct datatype vars.
DEF VAR c-param-exec AS CHAR NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-param-exec AS INT NO-UNDO EXTENT 9 INIT ?.
DEF VAR de-param-exec AS DEC NO-UNDO EXTENT 9 INIT ?.
DEF VAR da-param-exec AS DATE NO-UNDO EXTENT 9 INIT ?.
DEF VAR l-param-exec AS LOG NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-count AS INT NO-UNDO.
blk-count:
DO i-count = 0 TO 8:
IF TRIM(programa.parametro[i-count]) = '' THEN
LEAVE blk-count.
i-count = i-count + 1.
CASE ENTRY(2,programa.parametro[i-count],CHR(1)):
WHEN 'CHARACTER' THEN
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
WHEN 'INTEGER' THEN
i-param-exec[i-count] = INT(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DECIMAL' THEN
de-param-exec[i-count] = DEC(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DATE' THEN
da-param-exec[i-count] = DATE(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'LOGICAL' THEN
l-param-exec[i-count] = (ENTRY(3,programa.parametro[i-count],CHR(1)) = 'yes').
OTHERWISE
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
END CASE.
END.
Then I tried to run the program using an include to pass parameters (in this example, the program have 3 INPUT parameters).
RUN VALUE(c-prog-exec) ({util\abrePrograma.i 1},
{util\abrePrograma.i 2},
{util\abrePrograma.i 3}).
Here is my abrePrograma.i
/* abrePrograma.i */
(IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'CHARACTER' THEN c-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'INTEGER' THEN i-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DECIMAL' THEN de-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DATE' THEN da-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'LOGICAL' THEN l-param-exec[{1}] ELSE
c-param-exec[{1}])
If I suppress the 2nd, 3rd, 4th and 5th IF's from the include or use only one data type in all IF's (e.g. only CHAR, only DATE, etc.) the program works properly and executes like a charm but I need to call some old programs, which expects different datatypes in its INPUT parameters and using the programs as described OpenEdge doesn't compile the caller, triggering the error number 223.
---------------------------
Erro (Press HELP to view stack trace)
---------------------------
** Tipos de dados imcompativeis em expressao ou atribuicao. (223)
** Nao entendi a linha 86. (196)
---------------------------
OK Ajuda
---------------------------
Can anyone help me with this ?
Thanks in advance.
Looks as if you're trying to use variable parameter definitions.
Have a look at the "create call" statement in the ABL reference.
http://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref/call-object-handle.html#wwconnect_header
Sample from the documentation
DEFINE VARIABLE hCall AS HANDLE NO-UNDO.
CREATE CALL hCall.
/* Invoke hello.p non-persistently */
hCall:CALL-NAME = "hello.p".
/* Sets CALL-TYPE to the default */
hCall:CALL-TYPE = PROCEDURE-CALL-TYPE
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.
/* Clean up */
DELETE OBJECT hCall.
The best way to get to the bottom of those kind of preprocessor related issues is to do a compile with preprocess listing followed by a syntax check on the preprocessed file. Once you know where the error is in the resulting preprocessed file you have to find out which include / define caused the code that won't compile .
In procedure editor
compile source.w preprocess source.pp.
Open source.pp in the procedure editor and do syntax check
look at original source to find include or preprocessor construct that resulted in the code that does not compile.
Okay, I am getting a little bit lost (often happens to me with lots of preprocessors) but am I missing that on the way in and out of the database fields you are storing values as characters, right? So when storing a parameter in the database you have to convert it to Char and on the way out of the database you have convert it back to its correct data-type. To not do it one way or the other would cause a type mismatch.
Also, just thinking out loud (without thinking it all the way through) wonder if using OOABL (Object Oriented ABL) depending on if you Release has it available wouldn't make it easier by defining signatures for the different datatypes and then depending on which type of input or output parameter you call it with, it will use the correct signature and correct conversion method.
Something like:
METHOD PUBLIC VOID storeParam(input cParam as char ):
dbfield = cParam.
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input iParam as int ):
dbfield = string(iParam).
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input dParam as date ):
dbfield = string(dParam).
RETURN.
END METHOD.
just a thought.

Display all enums from an EMF model in a CheckBoxTable ?

I am trying to display a CheckBoxTable in an Eclipse page which enables the user to select any one of a number of items - the items that are available come from an EMF model and are enums.
I've got the content provider and the label provider set up correctly (I think) but I can't figure what to use to set the input in order to display the full list of enums.
So say my model has an enum called MyEnum which has values of ONE, TWO and THREE - I want to be able to display all three of those enums to the user as check boxes.
I need to call setInput(...) on the viewer but what do I pass into it to get those enums?
Although I've never done it for a CheckboxTableViewer, I have set an EEnum as the source of values for other StructuredViewer classes like ComboViewer. What I did was create a custom IStructuredContentProvider that is a subclass of ArrayList and takes the EEnum as a constructor argument (call this class EEnumContentProvider). In the constructor, I iterate over the EEnum's getELiterals() and call add() on each of their getInstance() values. Like this:
public EEnumContentProvider(EEnum source) {
List<EEnumLiteral> literals = source.getELiterals();
for (EEnumLiteral aLiteral : literals) {
add(aLiteral.getInstance());
}
}
You can easily implement IStructuredContentProvider.getElements(Object) by using returning the result of toArray() and you don't care about IContentProvider.setInput() because the contents aren't based on the input, they're static.
Then you can set an instance of EEnumContentProvider as the content provider for the viewer.
Simply you need to get the literals and add them to the control as follows:
/* Populate the Combo Box with the Literals */
EEnum cFEnum = Package.Literals.LITERAL_ENUMERATION;
/*
* Add an EMPTY item value so that the user can disable the specific
* feature
*/
this.cmbNames.add( EMPTY_STRING );
/*
* Add the Enumeration Literals to the
* appropriate SWT Combo widget.
*/
for (int i=0; i<cFEnum.getELiterals().size(); i++){
this.cmbNames.add( cFEnum.getEEnumLiteral( i ).toString() );
}
cFEnum = null;
String[] sortedTypes = this.cmbNames.getItems();
Arrays.sort( sortedTypes );
this.cmbNames.setItems( sortedTypes );

Difference between param[out] and return in doxygen?

What is the difference between \param[out] and \return in Doxygen? They both seem to document the output / return of a function. Is the difference due to void functions which don't have a return value and only param[out] would be valid?
Out parameters are different from return values. Take this example in C:
/**
* \param[in] val Value calculations are based off.
* \param[out] variable Function output is written to this variable.
*
* \return Nothing
*/
void modify_value(int val, int *variable)
{
val *= 5;
int working = val % 44;
*variable = working;
}
The function returns nothing, but the value to which variable points is changed, hence we call it an output parameter. It represents an 'output' of the function in that we expect it to be modified somehow by the function. val, on the other hand, is an 'input' parameter because it is not modified (and, indeed, cannot be modified from the perspective of the function's caller, since it is passed as a value).
Here's a slightly more useful and realistic example:
typedef struct data {
int i;
int j;
...
} data;
/**
* \param[in] val Initialising parameter for data.
* \param[out] dat Data pointer where the new object should be stored.
*
* \return True if the object was created, false if not
* (i.e., we're out of memory)
*/
bool create_data(int val, data **dat)
{
data *newdata;
newdata = (data*)malloc(sizeof(data));
if(newdata == NULL)
{
*dat = NULL;
return false;
}
newdata->i = val;
*dat = newdata;
return true;
}
In this case, we construct some complex object inside the function. We return a simple status flag that lets the user know the object creation was successful. But we pass out the newly-created object using an out parameter.
(Although, of course, this function could easily just return a pointer. Some functions are more complex!)
As a simpler answer, [out] parameters are only for results returned via parameters not the return value. It is quite reasonable to have a function which has a return value and also has optional return data, eg: one I'm just writing has the signature:
/**
Determine UTF type of a file.
Unless a UTF8 file has a BOM, it is regarded as unknown.
#param [in] path Path to file suitable for ifstream
#param [out] bomWasFound optional return flag to indicate a BOM was found, really only useful for UTF8
#return an enum indicating type, default utf_unknown
*/
UtfType CheckFileType(const std::string& path, bool* bomWasFound=0);