Programming an Oracle Tuxedo ATMI Application Using FML

     Previous  Next    Open TOC in new window  Open Index in new window  View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Field Manipulation Functions

This topic includes the following sections:

 


About This Section

This section describes all FML and VIEWS functions except the run-time mapping functions described in Defining and Using Fields.

FML functions are not directly available for COBOL programs. A procedure called FINIT is available to initialize a record for receiving FML data, and the FVSTOF and FVFTOS procedures are available to convert a COBOL record into an FML buffer, and vice-versa. For detailed descriptions of these procedures, see Programming an Oracle Tuxedo ATMI Application Using COBOL. The COBOL interface is not described further here.

 


FML and VIEWS: 16-bit and 32-bit Interfaces

There are two variants of FML. The original FML interface is based on 16-bit values for the length of fields and contains information identifying fields (hence FML16). FML16 is limited to 8191 unique fields, individual field lengths of up to 64K bytes, and a total fielded buffer size of 64K. The definitions, types, and function prototypes for this interface are in fml.h which must be included in an application program using the FML16 interface; and functions live in -lfml.

A second interface, FML32, uses 32-bit values for the field lengths and identifiers. It allows for about 30 million fields, and field and buffer lengths of about 2 billion bytes. The definitions, types, and function prototypes for FML32 are in fml32.h; functions reside in -lfml32. All definitions, types, and function names for FML32 have a “32” suffix (for example, MAXFBLEN32, FBFR32, FLDID32, FLDLEN32, F_OVHD32, Fchg32, and error code Ferror32). Also the environment variables are suffixed with “32” (for example, FLDTBLDIR32, FIELDTBLS32, VIEWFILES32, and VIEWDIR32). For FML32, a fielded buffer pointer is of type “FBFR32 *”, a field length has the type FLDLEN32, and the number of occurrences of a field has the type FLDOCC32. The default required alignment for FML32 buffers is 4-byte alignment.

FML16 applications that are written correctly can easily be changed to use the FML32 interface. All variables used in the calls to the FML functions must use the proper typedefs (FLDID, FLDLEN, and FLDOCC). Any call to tpalloc(3c) for an FML typed buffer should use the FMLTYPE definition instead of “FML”. The application source code can be changed to use the 32-bit functions simply by changing the include of fml.h to inclusion of fml32.h followed by fml1632.h. The fml1632.h contains macros that convert all of the 16-bit type definitions to 32-bit type definitions, and 16-bit functions and macros to 32-bit functions and macros.

Functions are also provided to convert an FML32 fielded buffer into an FML16 fielded buffer, and vice-versa:

#include “fml.h”
#include “fml32.h”
int
F32to16(FBFR *dest, FBFR32 *src)
int
F16to32(FBFR32 *dest, FBFR *src)

F32to16 converts a 32-bit FML buffer to a 16-bit FML buffer. It does this by converting the buffer on a field-by-field basis and then creating the index for the fielded buffer. A field is converted by generating a FLDID from a FLDID32, and copying the field value (and field length for string and carray fields).

dest and src are pointers to the destination and source fielded buffers, respectively. The source buffer is not changed.

These functions can fail for lack of space; they can be re-issued after enough additional space to complete the operation has been allocated. F16to32 converts a 16-bit FML buffer to a 32-bit FML buffer. It lives in the fml32 library or shared object and sets Ferror32 on error. F32to16 lives in the fml library or shared object and sets Ferror on error. Note that both fml.h and fml32.h must be included to use these functions; fml1632.h may not be included in the same file.

The field types for embedded buffers (FLD_PTR, FLD_FML32, and FLD_VIEW32) are supported only for FML32. Buffers containing FLD_PTR, FLD_FML32, FLD_MBSTRING, or FLD_VIEW32 fields cause F32to16 to fail with an FBADFLD error. There is no impact when F16to32 is called for these functions.

Note: For the remainder of this section, we describe only the 16-bit functions, without specifying the equivalent FML32 and VIEW32 functions.

 


Definitions of the FML Function Parameters

To simplify the specification of parameters for FML functions, a convention has been adopted for the sequence of those parameters. FML parameters appear in the following sequence.

  1. For functions that require a pointer to a fielded buffer (FBFR), this parameter is first. If a function takes two-fielded buffer pointers (such as the transfer functions), the destination buffer comes first, followed by the source buffer. A fielded buffer pointer must point to an area that is aligned on a short boundary (or an error is returned with Ferror set to FALIGNERR) and the area must be a fielded buffer (or an error is returned with Ferror set to FNOTFLD).
  2. For I/O functions, a pointer to a stream follows the fielded buffer pointer.
  3. For functions that need one, a field identifier (type FLDID) appears next (in the case of Fnext, it is a pointer to a field identifier).
  4. For functions that need a field occurrence (type FLDOCC), this parameter comes next. (For Fnext, it is a pointer to an occurrence number.)
  5. In functions in which a field value is passed to or from the function, a pointer to the beginning of the field value is given next. (It is defined as a character pointer but may be cast from any other pointer type.)
  6. When a field value is passed to a function that contains a character array (carray, mbstring) field, you must specify its length as the next parameter (type FLDLEN). For functions that retrieve a field value, a pointer to the length of the retrieval buffer must be passed to the function and this length parameter is set to the length of the value retrieved.
  7. A few functions require special parameters and differ from the preceding conventions. These special parameters appear after the above parameters. They are discussed in the descriptions of individual functions.
  8. The following NULL values are defined for the various field types:
    • 0 for short and long
    • 0.0 for float and double
    • \0 for string (1 byte in length)
    • A zero-length string for carray or mbstring

 


Field Identifier Mapping Functions

Several functions allow a programmer to query field tables or field identifiers for information about fields during program execution.

Fldid

Fldid returns the field identifier for a given valid field name and loads the field name/field ID mapping tables from the field table files, if they do not already exist.

FLDID
Fldid(char *name)

Here name is a valid field name.

The space used by the mapping tables in memory can be freed using the Fnmid_unload, Fnmid_unload32(3fml) function. Note that these tables are separate from the tables loaded and used by the Fname function.

For more information, refer to Fldid, Fldid32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fname

Fname returns the field name for a given valid field identifier and loads the field ID/name mapping tables from the field table files, if they do not already exist.

char *
Fname(FLDID fieldid)

Here fieldid is a valid field identifier.

The space used by the mapping tables in memory can be freed using the Fnmid_unload, Fnmid_unload32(3fml) function. Note that these tables are separate from the tables loaded and used by the Fldid function. (Refer to the Oracle Tuxedo ATMI FML Function Reference for more information.)

For more information, refer to Fname, Fname32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fldno

Fldno extracts the field number from a given field identifier.

FLDOCC
Fldno(FLDID fieldid)

Here fieldid is a valid field identifier.

For more information, refer to Fldno, Fldno32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fldtype

Fldtype extracts the field type (an integer, as defined in fml.h) from a given field identifier.

int
Fldtype(FLDID fieldid)

Here fieldid is a valid field identifier.

The following table shows the possible values returned by Fldtype and their meanings.

Table 5-1 Field Types Returned by Fldtype  
Return Value
Meaning
Field Type Name in fml.h/ fml32.h
0
Short integer
FLD_SHORT
1
Long integer
FLD_LONG
2
Character
FLD_CHAR
3
Single-precision float
FLD_FLOAT
4
Double-precision float
FLD_DOUBLE
5
Null-terminated string
FLD_STRING
6
Character array
FLD_CARRAY
9
Pointer
FLD_PTR
10
Embedded FML32 buffer
FLD_FML32
11
Embedded VIEW32 buffer
FLD_VIEW32
12
Multibyte character array
FLD_MBSTRING

For more information, refer to Fldtype, Fldtype32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Ftype

Ftype returns a pointer to a string containing the name of the type of a field given a field identifier.

char *
Ftype(FLDID fieldid)

Here fieldid is a valid field identifier. For example, the following code returns a pointer to one of the following strings: short, long, char, float, double, string, carray, mbstring, FLD_PTR, FLD_FML32, or FLD_VIEW32.

char *typename
. . .
typename = Ftype(fieldid);

For more information, refer to Ftype, Ftype32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fmkfldid

As part of an application generator, or to reconstruct a field identifier, it might be useful to make a field identifier from a type specification and an available field number. Fmkfldid provides this functionality.

FLDID
Fmkfldid(int type, FLDID num)

Here:

For more information, refer to Fmkfldid, Fmkfldid32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Buffer Allocation and Initialization

The functions described in this section are provided for writing stand-alone FML programs. If you are using the Oracle Tuxedo ATMI functions, keep in mind that for tasks such as allocating and freeing message buffers, you must call ATMI functions such as tpalloc(3c), tprealloc(3c), and tpfree(3c), instead of FML functions such as Falloc, Falloc32(3fml), Frealloc, Frealloc32(3fml), and Ffree, Ffree32(3fml).

Most FML functions require a pointer to a fielded buffer as an argument. The typedef FBFR is available for declaring such pointers, as shown in the following example:

FBFR *fbfr;

In this section, the variable fbfr refers to a pointer to a fielded buffer. Never attempt to declare fielded buffers themselves; declare only pointers to fielded buffers.

When a server receives a request that contains an FML buffer, it allocates space for that FML buffer and for any embedded views or buffers referenced by FLD_PTR fields. A pointer to the new FML buffer is passed to the user-written code. Once the server processing is complete, all buffers allocated when the message was received must be destroyed. The Oracle Tuxedo system checks the FML buffer and all subsidiary buffers, and deletes any buffers to which it finds references. As a programmer writing server code, you should be aware of the following situations:

The functions used to reserve space for fielded buffers are explained in the following text, but first we describe a function that can be used to determine whether a given buffer is, in fact, a fielded buffer.

Fielded

Fielded (or Fielded32) is used to test whether the specified buffer is fielded.

int
Fielded(FBFR *fbfr)

Fielded32 is used with 32-bit FML.

Fielded returns true (1) if the buffer is fielded. It returns false (0) if the buffer is not fielded but does not set Ferror.

For more information, refer to Fielded, Fielded32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fneeded

The amount of memory to allocate for a fielded buffer depends on the maximum number of fields the buffer will contain and the total amount of space needed for all the field values. The function Fneeded can be used to determine the amount of space (in bytes) needed for a fielded buffer; it takes the number of fields and the space needed for all field values (in bytes) as arguments.

long
Fneeded(FLDOCC F, FLDLEN V)

Here:

The space needed for field values is computed by estimating the amount of space that is required by each field value if stored in standard structures (for example, a long is stored as a long and needs four bytes). For variable length fields, estimate the average amount of space needed for the field. The space calculated by Fneeded includes a fixed overhead for each field; it adds that to the space needed for the field values.

Once you obtain the estimate of space from Fneeded, you can allocate the desired number of bytes using malloc(3) and set up a pointer to the allocated memory space. For example, the following code allocates space for a fielded buffer large enough to contain 25 fields and 300 bytes of values.

#define NF 25
#define NV 300
extern char *malloc;
. . .
if((fbfr = (FBFR *)malloc(Fneeded(NF, NV))) == NULL)
F_error("pgm_name"); /* no space to allocate buffer */

However, this allocated memory space is not yet a fielded buffer. Finit must be used to initialize it.

For more information, refer to Fneeded, Fneeded32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvneeded

The Fvneeded function determines the amount of space (in bytes) needed for a VIEW buffer. The function takes a pointer to the name of the VIEW as an argument.

long
Fvneeded(char *subtype)

The Fvneeded function returns the size of the VIEW in number of bytes.

For more information, refer to Fvneeded, Fvneeded32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Finit

The Finit function initializes an allocated memory space as a fielded buffer.

int
Finit(FBFR *fbfr, FLDLEN buflen)

Here:

A call to Finit to initialize the memory space allocated in the previous example looks like the following code:

Finit(fbfr, Fneeded(NF, NV));

Now fbfr points to an initialized, empty fielded buffer. Up to Fneeded(NF, NV) bytes minus a small amount (F_OVHD as defined in fml.h) are available in the buffer to hold fields.

Note: The numbers used in the malloc(3) call (as described in the previous section) and Finit call must be the same.

For more information, refer to Finit, Finit32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Falloc

Calls to Fneeded, malloc(3) and Finit may be replaced by a single call to Falloc, which allocates the desired amount of space and initializes the buffer.

FBFR *
Falloc(FLDOCC
F, FLDLEN V)

Here:

A call to Falloc that provides the same functionality created by the calls to Fneeded, malloc(), and Finit described in the previous three sections, must be written as follows:

extern FBFR *Falloc;
. . .
if((fbfr = Falloc(NF, NV)) == NULL)
F_error(“pgm_name”); /* couldn't allocate buffer */

Storage allocated with Falloc (or Fneeded, malloc(3), and Finit) should be freed with Ffree. (See Ffree, Ffree32(3fml) in the Oracle Tuxedo ATMI FML Function Reference.)

For more information, refer to Falloc, Falloc32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Ffree

Ffree is used to free memory space allocated as a fielded buffer. Ffree32 does not free the memory area referenced by a pointer in a FLD_PTR field.

int
Ffree(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. Consider the following example:

#include  <fml.h>
. . .
if(Ffree(fbfr) < 0)
F_error("pgm_name"); /* not fielded buffer */

Ffree is preferable to free(3), because Ffree invalidates a fielded buffer, whereas free(3) does not. It is necessary to invalidate fielded buffers because malloc(3) re-uses memory that has been freed without clearing it. Thus, if free(3) is used, malloc can return a piece of memory that looks like a valid fielded buffer, but is not.

Space for a fielded buffer may also be reserved directly. The buffer must begin on a short boundary. You must allocate at least F_OVHD bytes (defined in fml.h) for the buffer; if you do not, Finit returns an error.

The following code is analogous to the preceding example but Fneeded cannot be used to size the static buffer because it is not a macro:

/* the first line aligns the buffer */
static short buffer[500/sizeof(short)];
FBFR *fbfr=(FBFR *)buffer;
. . .
Finit(fbfr, 500);

Be careful not to enter code such as the following:

FBFR badfbfr;
. . .
Finit(&badfbfr, Fneeded(NF, NV));

This code is wrong: the structure for FBFR is not defined in the user header files. As a result, a compilation error will be produced.

For more information, refer to Ffree, Ffree32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fsizeof

Fsizeof returns the size of a fielded buffer in bytes.

long
Fsizeof(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. In the following code, for example, Fsizeof returns the same number that Fneeded returned when the fielded buffer was originally allocated:

long bytes;
. . .
bytes = Fsizeof(fbfr);

For more information, refer to Fsizeof, Fsizeof32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Funused

Funused may be used to determine how much space is available in a fielded buffer for additional data.

long
Funused(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. Consider the following example:

long unused;
. . .
unused = Funused(fbfr);

Note that Funused does not indicate the location, in the buffer, of the unused bytes; only the number of unused bytes is specified.

For more information, refer to Funused, Funused32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fused

Fused may be used to determine how much space is used in a fielded buffer for data and overhead.

long
Fused(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. Consider the following example:

long used;
. . .
used = Fused(fbfr);

Note that Fused does not indicate the location, in the buffer, of the used bytes; only the number of used bytes is specified.

For more information, refer to Fused, Fused32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Frealloc

This function enables you to change the size of a buffer for which you have allocated space by calling Falloc.

If you have allocated space with tpalloc(3c), you must call tprealloc(3c) to reallocate that space. Being able to resize the buffer can be useful if, for example, a buffer runs out of space while a new field value is being added. Simply by calling Frealloc you can increase the size of the buffer. In other situations you may want to call Frealloc to decrease the size of the buffer.

FBFR *
Frealloc(FBFR *fbfr, FLDOCC nf, FLDLEN nv)

Here:

Consider the following example:

FBFR *newfbfr;
. . .
if((newfbfr = Frealloc(fbfr, NF+5, NV+300)) == NULL)
F_error(“pgm_name”); /* couldn't re-allocate space */
else
fbfr = newfbfr; /* assign new pointer to old */

In this case, the application needed to remember the number of fields and the number of value space bytes previously allocated. Note that the arguments to Frealloc (as with its counterpart realloc(3)) are absolute values, not increments. This example does not work if it is necessary to re-allocate space several times.

The following example shows a second way of incrementing the allocated space:

/* define the increment size when buffer out of space */
#define INCR 400
FBFR *newfbfr;
. . .
if((newfbfr = Frealloc(fbfr, 0, Fsizeof(fbfr)+INCR)) == NULL)
F_error(“pgm_name”); /* couldn't re-allocate space */
else
fbfr = newfbfr; /* assign new pointer to old */

You do not need to know the number of fields or the value space size with which the buffer was last initialized. Thus, the easiest way to increase the size is to use the current size plus the increment as the value space. The previous example can be executed as many times as needed without remembering past executions or values. You do not need to call Finit after calling Frealloc.

If the amount of additional space requested in the call to Frealloc is contiguous to the old buffer, newfbfr and fbfr in the previous examples are the same. However, defensive programming dictates that you should declare newfbfr as a safeguard in case either a new value or NULL is returned. If Frealloc fails, do not use fbfr again.

Note: The buffer size can be decreased only to the number of bytes currently being used in the buffer.

For more information, refer to Frealloc, Frealloc32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Functions for Moving Fielded Buffers

The only restriction on the location of fielded buffers is that they must be aligned on a short boundary. Otherwise, fielded buffers are position-independent and may be moved around freely in memory.

Fmove

If src points to a fielded buffer and dest points to an area of storage big enough to hold it, then the following code might be used to move the fielded buffer:

FBFR *src;
char *dest;
. . .
memcpy(dest, src, Fsizeof(src));

The function memcpy, one of the C run-time memory management functions, moves the number of bytes indicated by its third argument from the area pointed to by its second argument to the area pointed to by its first argument.

While memcpy may be used to copy a fielded buffer, the destination copy of the buffer looks just like the source copy. In particular, for example, the destination copy has the same number of unused bytes as the source buffer.

Fmove acts like memcpy, but does not need an explicit length (which is computed).

int
Fmove(char *dest, FBFR *src)

Here:

In the following code, for example, Fmove checks that the source buffer is indeed a fielded buffer, but does not modify the source buffer in any way.

FBFR *src;
char *dest;
. . .
if(Fmove(dest,src) < 0)
F_error("pgm_name");

The destination buffer need not be a fielded buffer (that is, it need not have been allocated using Falloc), but it must be aligned on a short boundary (4-byte alignment for FML32). Thus, Fmove provides an alternative to Fcpy when you want to copy a fielded buffer to a non-fielded buffer. Fmove does not, however, check to make sure there is enough room in the destination buffer to receive the source buffer.

For values of type FLD_PTR, Fmove32 transfers the buffer pointer. The application programmer must manage the reallocation and freeing of buffers when the associated pointer is moved. The buffer pointed to by a FLD_PTR field must be allocated using the tpalloc(3c) call.

For more information, refer to Fmove, Fmove32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fcpy

Fcpy is used to overwrite one fielded buffer with another.

int
Fcpy(FBFR *dest, FBFR *src)

Here:

Fcpy preserves the overall buffer length of the overwritten fielded buffer and therefore is useful for expanding or reducing the size of a fielded buffer. Consider the following example:

FBFR *src, *dest;
. . .
if(Fcpy(dest, src) < 0)
F_error(“pgm_name”);

Unlike Fmove, where dest could point to an uninitialized area, Fcpy expects dest to point to an initialized fielded buffer (allocated using Falloc). Fcpy also verifies that dest is big enough to accommodate the data from the source buffer.

Note: You cannot reduce the size of a fielded buffer below the amount of space needed for currently held data.

As with Fmove, the source buffer is not modified by Fcpy.

For values of type FLD_PTR, Fcpy32 copies the buffer pointer. The application programmer must manage the reallocation and freeing of buffers when the associated pointer is copied. The buffer pointed to by a FLD_PTR field must be allocated using the tpalloc(3c) call.

For more information, refer to Fcpy, Fcpy32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Field Access and Modification Functions

This section discusses how to update and access fielded buffers using the field types of the fields without doing any conversions. For a list of the functions that allow you to convert data from one type to another upon transfer to or from a fielded buffer, see Conversion Functions.

Fadd

The Fadd function adds a new field value to the fielded buffer.

int
Fadd(FBFR *fbfr, FLDID fieldid, char *value, FLDLEN len)

Here:

If no occurrence of the field exists in the buffer, then the field is added. If one or more occurrences of the field already exist, then the value is added as a new occurrence of the field, and is assigned an occurrence number 1 greater than the current highest occurrence. (To add a specific occurrence, Fchg must be used.)

Fadd, like all other functions that take or return a field value, expects a pointer to a field value, never the value itself.

If the field type is such that the field length is fixed (short, long, char, float, or double) or can be determined (string), the field length need not be given (it is ignored). If the field type is a character array (FLD_CARRAY or FLD_MBSTRING), the length must be specified; the length is defined as type FLDLEN. The following code, for example, gets the field identifier for the desired field and adds the field value to the buffer.

FLDID fieldid, Fldid;
FBFR *fbfr;
. . .
fieldid = Fldid("fieldname");
if(Fadd(fbfr, fieldid, "new value", (FLDLEN)9) < 0)
F_error("pgm_name");

It is assumed (by default) that the native type of the field is a character array so that the length of the value must be passed to the function. If the value being added is not a character array, the type of value must reflect the type of the value to which it points. The following code, for example, adds a long field value.

long lval;
. . .
lval = 123456789;
if(Fadd(fbfr, fieldid, &lval, (FLDLEN)0) < 0)
F_error("pgm_name");

For character array fields, null fields may be indicated by a length of 0. For string fields, the null string may be stored since the NULL terminating byte is actually stored as part of the field value: a string consisting of only the NULL terminating byte is considered to have a length of 1. For all other types (fixed length types), you may choose some special value that is interpreted by the application as a NULL, but the size of the value is taken from its field type (for example, a length of 4 for a long), regardless of what value is actually passed. Passing a NULL value address results in an error (FEINVAL).

For pointer fields, Fadd32 stores the pointer value. The buffer pointed to by a FLD_PTR field must be allocated using the tpalloc(3c) call. For embedded FML32 buffers, Fadd32 stores the entire FLD_FML32 field value, except for the index.

For embedded VIEW32 buffers, Fadd32 stores a pointer to a structure of type FVIEWFLD, which contains vflags (a flags field, currently unused and set to 0), vname (a character array containing the view name), and data (a pointer to the view data stored as a C structure). The application provides the vname and data to Fadd32. The FVIEWFLD structure is as follows:

typedef struct { 
TM32U vflags; /* flags - currently unused */
char vname[FVIEWNAMESIZE+1]; /* name of view */
char *data; /* pointer to view structure */
} FVIEWFLD;

For more information, refer to Fadd, Fadd32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fappend

The Fappend function appends a new field value to the fielded buffer.

int
Fappend(FBFR *fbfr, FLDID fieldid, char *value, FLDLEN len)

Here:

Fappend appends a new occurrence of the field fieldid with a value located at value to the fielded buffer and puts the buffer into append mode. Append mode provides optimized buffer construction for large buffers constructed of many rows of a common set of fields.

A buffer that is in append mode is restricted as to what operations may be performed on the buffer. Only calls to the following FML routines are allowed in append mode: Fappend, Findex, Funindex, Ffree, Fused, Funused and Fsizeof. Calls to Findex or Funindex end append mode.

The following example shows the construction, using Fappend, of a 500-row buffer with 5 fields per row:

for (i=0; i 500 ;i++) {
if ((Fappend(fbfr, LONGFLD1, &lval1[i], (FLDLEN)0) < 0) ||
(Fappend(fbfr, LONGFLD2, &lval2[i], (FLDLEN)0) < 0) ||
(Fappend(fbfr, STRFLD1, &str1[i], (FLDLEN)0) < 0) ||
(Fappend(fbfr, STRFLD2, &str2[i], (FLDLEN)0) < 0) ||
(Fappend(fbfr, LONGFLD3, &lval3[i], (FLDLEN)0) < 0)) {
F_error("pgm_name");
break;
}
}
Findex(fbfr, 0);

Fappend, like all other functions that take or return a field value, expects a pointer to a field value, never the value itself.

If the field type is such that the field length is fixed (short, long, char, float, or double) or can be determined (string), the field length need not be given (it is ignored). If the field type is a character array (FLD_CARRAY or FLD_MBSTRING), the length must be specified; the length is defined as type FLDLEN.

It is assumed (by default) that the native type of the field is a character array so that the length of the value must be passed to the function. If the value being appended is not a character array, the type of value must reflect the type of the value it points to.

For character array fields, null fields may be indicated by a length of 0. For string fields, the null string may be stored since the NULL terminating byte is actually stored as part of the field value: a string consisting of only the NULL terminating byte is considered to have a length of 1. For all other types (fixed-length types), you may choose some special value that is interpreted by the application as a NULL, but the size of the value is taken from its field type (for example, the length of 4 for a long), regardless of what value is actually passed. Passing a NULL value address results in an error (FEINVAL).

For more information, refer to Fappend, Fappend32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fchg

Fchg changes the value of a field in the buffer.

int
Fchg(FBFR *fbfr, FLDID fieldid, FLDOCC oc, char *value, FLDLEN len)

Here:

For example, the following code changes a field of type carray to a new value stored in value:

FBFR *fbfr;
FLDID fieldid;
FLDOCC oc;
FLDLEN len;
char value[50];
. . .
strcpy(value, "new value");
flen = strlen(value);
if(Fchg(fbfr, fieldid, oc, value, len) < 0)
F_error("pgm_name");

If oc is -1, then the field value is added as a new occurrence to the buffer. If oc is 0 or greater and the field is found, then the field value is modified to the new value specified. If oc is 0 or greater and the field is not found, then NULL occurrences are added to the buffer until the value can be added as the specified occurrence. For example, changing field occurrence 3 for a field that does not exist on a buffer causes three NULL occurrences to be added (occurrences 0, 1 and 2), followed by occurrence 3 with the specified field value. Null values consist of the NULL string “\0” (1 byte in length) for string and character values, 0 for long and short fields, 0.0 for float and double values, and a zero-length string for a character array.

The new or modified value is contained in value. If it is a character array (FLD_CARRAY or FLD_MBSTRING), its length is given in len (len is ignored for other field types). If the value pointer is NULL and the field is found, then the field is deleted. If the field occurrence to be deleted is not found, it is considered an error (FNOTPRES).

For pointer fields, Fchg32 stores the pointer value. The buffer pointed to by a FLD_PTR field must be allocated using the tpalloc(3c) call. For embedded FML32 buffers, Fchg32 stores the entire FLD_FML32 field value, except the index.

For embedded VIEW32 buffers, Fchg32 stores a pointer to a structure of type FVIEWFLD, which contains vflags (a flags field, currently unused and set to 0), vname (a character array containing the view name), and data (a pointer to the view data stored as a C structure). The application provides the vname and data to Fchg32. The FVIEWFLD structure is as follows:

typedef struct { 
TM32U vflags; /* flags - currently unused */
char vname[FVIEWNAMESIZE+1]; /* name of view */
char *data; /* pointer to view structure */
} FVIEWFLD;

The buffer must have enough room to contain the modified or added field value, or an error is returned (FNOSPACE).

For more information, refer to Fchg, Fchg32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fcmp

Fcmp compares the field identifiers and field values of two fielded buffers.

int
Fcmp(FBFR *fbfr1, FBFR *fbfr2)

Here fbfr1 and fbfr2 are pointers to fielded buffers.

The function returns a 0 if the buffers are identical; it returns a -1 on any of the following conditions:

The following criteria are used to determine whether pointers and embedded buffers are equal:

Fcmp returns a 1 if the opposite of any of these conditions is true. For example, Fcmp returns 1 if the field ID of a fbfr2 field is less than the field ID of the corresponding field of fbfr1.

For more information, refer to Fcmp, Fcmp32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fdel

The Fdel function deletes the specified field occurrence.

int
Fdel(FBFR *fbfr, FLDID fieldid, FLDOCC oc)

Here:

For example, the following code deletes the first occurrence of the field indicated by the specified field identifier:

FLDOCC occurrence;
. . .
occurrence=0;
if(Fdel(fbfr, fieldid, occurrence) < 0)
F_error("pgm_name");

If the specified field does not exist, the function returns -1 and Ferror is set to FNOTPRES.

For pointer fields, Fdel32 deletes the FLD_PTR field occurrence without changing the referenced buffer or freeing the pointer. The data buffer is treated as an opaque pointer.

For more information, refer to Fdel, Fdel32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fdelall

Fdelall deletes all occurrences of the specified field from the buffer.

int
Fdelall(FBFR *fbfr, FLDID fieldid)

Here:

Consider the following example:

if(Fdelall(fbfr, fieldid) < 0)
F_error("pgm_name"); /* field not present */

If the field is not found, the function returns -1 and Ferror is set to FNOTPRES.

For pointer fields, Fdelall32 deletes the FLD_PTR field occurrence without changing the referenced buffer or freeing the pointer. The data buffer is treated as an opaque pointer.

For more information, refer to Fdelall, Fdelall32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fdelete

Fdelete deletes all occurrences of all fields listed in the array of field identifiers, fieldid[].

int
Fdelete(FBFR *fbfr, FLDID *fieldid)

Here:

The update is done directly to the fielded buffer. The array of field identifiers does not need to be in any specific order, but the last entry in the array must be field identifier 0 (BADFLDID). Consider the following example:

#include "fldtbl.h"
FBFR *dest;
FLDID fieldid[20];
. . .
fieldid[0] = A; /* field id for field A */
fieldid[1] = D; /* field id for field D */
fieldid[2] = BADFLDID; /* sentinel value */
if(Fdelete(dest, fieldid) < 0)
F_error("pgm_name");

If the destination buffer has fields A, B, C, and D, this example results in a buffer that contains only occurrences of fields B and C.

Fdelete provides a more efficient way of deleting several fields from a buffer than using several Fdelall calls.

For pointer fields, Fdelete deletes the FLD_PTR field occurrence without changing the referenced buffer or freeing the pointer. The data buffer is treated as an opaque pointer.

For more information, refer to Fdelete, Fdelete32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Ffind

Ffind finds the value of the specified field occurrence in the buffer.

char *
Ffind(FBFR *fbfr, FLDID fieldid, FLDOCC oc, FLDLEN *len)

Here:

In the previous declaration the return value to Ffind is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

The following code provides an example of how this function is used:

#include "fldtbl.h"
FBFR *fbfr;
FLDLEN len;
char* Ffind, *value;
. . .
if((value=Ffind(fbfr,ZIP,0, &len)) == NULL)
F_error("pgm_name");

If the field is found, its length is returned in len (if len is NULL, the length is not returned), and its location is returned as the value of the function. If the field is not found, NULL is returned, and Ferror is set to FNOTPRES.

Ffind is useful for gaining “read-only” access to a field. The value returned by Ffind should not be used to modify the buffer. Field values should be modified only by the Fadd or Fchg function. This function does not check for occurrences of the specified field in embedded buffers.

The value returned by Ffind is valid only so long as the buffer remains unmodified. The value is guaranteed to be aligned on a short boundary but may not be aligned on a long or double boundary, even if the field is of that type. (See the conversion functions described later in this document for aligned values.) On processors that require proper alignment of variables, referencing the value when not aligned properly causes a system error, as shown in the following example:

long *l1,l2;
FLDLEN length;
char *Ffind;
. . .
if((l1=(long *)Ffind(fbfr, ZIP, 0, &length)) == NULL)
F_error("pgm_name");
else
l2 = *l1;

This code should be re-written as follows:

if((l1==(long *)Ffind(fbfr, ZIP, 0, &length)) == NULL)
F_error("pgm_name");
else
memcpy(&l2,l1,sizeof(long));

For more information, refer to Ffind, Ffind32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Ffindlast

This function finds the last occurrence of a field in a fielded buffer and returns a pointer to the field, as well as the occurrence number and length of the field occurrence.

char *
Ffindlast(FBFR *fbfr, FLDID fieldid, FLDOCC *oc, FLDLEN *len)

Here:

In the previous declaration the return value to Ffindlast is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

Ffindlast acts like Ffind, except that you do not specify a field occurrence. Instead, both the occurrence number and the value of the last field occurrence are returned. However, if you specify NULL as the value of the occurrence when calling the function, the occurrence number is not returned. This function does not check for occurrences of the specified field in embedded buffers.

The value returned by Ffindlast is valid only as long as the buffer remains unchanged.

For more information, refer to Ffindlast, Ffindlast32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Ffindocc

Ffindocc looks at occurrences of the specified field on the buffer and returns the occurrence number of the first field occurrence that matches the user-specified field value.

FLDOCC
Ffindocc(FBFR *fbfr, FLDID fieldid, char *value, FLDLEN len;)

Here:

For example, the following code sets oc to the occurrence for the specified zip code:

#include "fldtbl.h"
FBFR *fbfr;
FLDOCC oc;
long zipvalue;
. . .
zipvalue = 123456;
if((oc=Ffindocc(fbfr,ZIP,&zipvalue, 0)) < 0)
F_error("pgm_name");

Regular expressions are supported for string fields. For example, the following code sets oc to the occurrence of NAME that starts with “J”:

#include "fldtbl.h"
FBFR *fbfr;
FLDOCC oc;
char *name;
. . .
name = "J.*"
if ((oc = Ffindocc(fbfr, NAME, name, 1)) < 0)
F_error("pgm_name");
Note: To enable pattern matching on strings, the fourth argument to Ffindocc must be non-zero. If it is zero, a simple string compare is performed. If the field value is not found, -1 is returned.

For upward compatibility, a circumflex (^) prefix and dollar sign ($) suffix are implicitly added to the regular expression. Thus the previous example is actually interpreted as “^(J.*)$”. The regular expression must match the entire string value in the field.

For more information, refer to Ffindocc, Ffindocc32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fget

Use Fget to retrieve a field from a fielded buffer when the value is to be modified.

int
Fget(FBFR *fbfr, FLDID fieldid, FLDOCC oc, char *loc, FLDLEN *maxlen)

Here:

The caller provides Fget with a pointer to a private buffer, as well as the length of the buffer. If maxlen is specified as NULL, then it is assumed that the destination buffer is large enough to accommodate the field value, and its length is not returned.

Fget returns an error if the desired field is not in the buffer (FNOTPRES), or if the destination buffer is too small (FNOSPACE). For example, the following code gets the zip code, assuming it is stored as a character array or string:

FLDLEN len;
char value[100];
. . .
len=sizeof(value);
if(Fget(fbfr, ZIP, 0, value, &len) < 0)
F_error("pgm_name");

If the zip code is stored as a long, it can be retrieved by the following code:

FLDLEN len;
long value;
. . .
len = sizeof(value);
if(Fget(fbfr, ZIP, 0, value, &len) < 0)
F_error("pgm_name");

For more information, refer to Fget, Fget32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fgetalloc

Like Fget, Fgetalloc finds and makes a copy of a buffer field, but it acquires space for the field via a call to malloc(3).

char *
Fgetalloc(FBFR *fbfr, FLDID fieldid, FLDOCC oc, FLDLEN *extralen)

Here:

In the declaration above the return value to Fgetalloc is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

On success, Fgetalloc returns a valid pointer to the copy of the properly aligned buffer field; on error it returns NULL. If malloc(3) fails, Fgetalloc returns an error and Ferror is set to FMALLOC.

The last parameter to Fgetalloc specifies an extra amount of space to be acquired if, for instance, the value obtained is to be expanded before re-insertion into the fielded buffer. On success, the length of the allocated buffer is returned in extralen. Consider the following example:

FLDLEN extralen;
FBFR *fieldbfr
char *Fgetalloc;
. . .
extralen = 0;
if (fieldbfr = (FBFR *)Fgetalloc(fbfr, ZIP, 0, &extralen) == NULL)
F_error("pgm_name");

It is the responsibility of the caller to free space acquired by Fgetalloc.

For more information, refer to Fgetalloc, Fgetalloc32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fgetlast

Fgetlast is used to retrieve the last occurrence of a field from a fielded buffer when the value is to be modified.

int
Fgetlast(FBFR *fbfr, FLDID fieldid, FLDOCC *oc, char *loc, FLDLEN *maxlen)

Here:

The caller provides Fgetlast with a pointer to a private buffer, as well as the length of the buffer. Fgetlast acts like Fget, except that you do not specify a field occurrence. Instead, both the occurrence number and the value of the last field occurrence are returned. However, if you specify NULL for occ on calling the function, the occurrence number is not returned.

For more information, refer to Fgetlast, Fgetlast32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fnext

Fnext finds the next field in the buffer after the specified field occurrence.

int
Fnext(FBFR *fbfr, FLDID *fieldid, FLDOCC *oc, char *value, FLDLEN *len)

Here:

A fieldid of FIRSTFLDID should be specified to get the first field in a buffer; the field identifier and occurrence number of the first field occurrence are returned in the corresponding parameters. If the field is not NULL, its value is copied into the memory location addressed by the value pointer.

The len parameter is used to determine whether value has enough space allocated to contain the field value. If the amount of space is insufficient, Ferror is set to FNOSPACE. The length of the value is returned in the len parameter. If the value of the field is non-null, then the len parameter is also assumed to contain the length of the currently allocated space for value.

When the field to be retrieved is an embedded VIEW32 buffer, the value parameter points to an FVIEWFLD structure. The Fnext function populates the vname and data fields in the structure. The FVIEWFLD structure is as follows:

typedef struct { 
TM32U vflags; /* flags - currently unused */
char vname[FVIEWNAMESIZE+1]; /* name of view */
char *data; /* pointer to view structure */
} FVIEWFLD;

If the field value is NULL, then the value and length parameters are not changed.

If no more fields are found, Fnext returns 0 (end of buffer) and fieldid, occurrence, and value are left unchanged.

If the value parameter is not NULL, the length parameter is also assumed to be non-NULL.

The following example reads all field occurrences in the buffer:

FLDID fieldid;
FLDOCC occurrence;
char *value[100];
FLDLEN len;
. . .
for(fieldid=FIRSTFLDID,len=sizeof(value);
Fnext(fbfr,&fieldid,&occurrence,value,&len) > 0;
len=sizeof(value)) {
/* code for each field occurrence */
}

For more information, refer to Fnext, Fnext32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fnum

Fnum returns the number of fields contained in the specified buffer, or -1 on error.

FLDOCC
Fnum(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. The following code, for example, prints the number of fields in the specified buffer:

if((cnt=Fnum(fbfr)) < 0)
F_error("pgm_name");
else
fprintf(stdout,"%d fields in buffer\n",cnt);

Each FLD_FML32 and FLD_VIEW32 field is counted as a single field, regardless of the number of fields it contains.

For more information, refer to Fnum, Fnum32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Foccur

Foccur returns the number of occurrences for the specified field in the buffer:

FLDOCC
Foccur(FBFR *fbfr, FLDID fieldid)

Here:

Occurrences of a field within an embedded FML32 buffer are not counted.

Zero is returned if the field does not occur in the buffer and -1 is returned on error. For example, the following code prints the number of occurrences of the field ZIP in the specified buffer:

FLDOCC cnt;
. . .
if((cnt=Foccur(fbfr,ZIP)) < 0)
F_error("pgm_name");
else
fprintf(stdout,"Field ZIP occurs %d times in buffer\n",cnt);

For more information, refer to Foccur, Foccur32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fpres

Fpres returns true (1) if the specified field occurrence exists. Otherwise, it returns false (0).

int
Fpres(FBFR *fbfr, FLDID fieldid, FLDOCC oc)

Here:

For example, the following code returns true if the field ZIP exists in the fielded buffer referenced by fbfr:

Fpres(fbfr,ZIP,0)

Fpres does not check for occurrences of the specified field within an embedded buffer.

For more information, refer to Fpres, Fpres32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvals and Fvall

Fvals works like Ffind for string values but guarantees that a pointer to a value is returned. Fvall works like Ffind for long and short values, but returns the actual value of the field as a long, instead of as a pointer to the value.

char* 
Fvals(FBFR *fbfr,FLDID fieldid,FLDOCC oc)
char*
Fvall(FBFR *fbfr,FLDID fieldid,FLDOCC oc)

In both functions:

For Fvals, if the specified field occurrence is not found, the NULL string, \0, is returned. This function is useful for passing the value of a field to another function without checking the return value. This function is valid only for fields of type string; the NULL string is automatically returned for other field types (that is, no conversion is done).

For Fvall, if the specified field occurrence is not found, then 0 is returned. This function is useful for passing the value of a field to another function without checking the return value. This function is valid only for fields of type long and short; 0 is automatically returned for other field types (that is, no conversion is done).

For more information, refer to Fvals, Fvals32(3fml) and Fvall, Fvall32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Buffer Update Functions

The functions listed in this section access and update entire fielded buffers, rather than individual fields in the buffers. These functions use, at most, three parameters:

Fconcat

Fconcat adds fields from the source buffer to the fields that already exist in the destination buffer.

int
Fconcat(FBFR *dest, FBFR *src)

Occurrences in the destination buffer are maintained (that is, they are retained and not modified) and new occurrences from the source buffer are added with greater occurrence numbers than any existing occurrences for each field. The fields are maintained in field identifier order.

Consider the following example:

FBFR *src, *dest;
. . .
if(Fconcat(dest,src) < 0)
F_error("pgm_name");

If dest has fields A, B, and two occurrences of C, and src has fields A, C, and D, the resulting dest has two occurrences of field A (destination field A and source field A), field B, three occurrences of field C (two from dest and the third from src), and field D.

This operation fails if there is not enough space for the new fields (FNOSPACE); in this case, the destination buffer remains unchanged.

For more information, refer to Fconcat, Fconcat32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fjoin

Fjoin is used to join two fielded buffers based on matching field ID/occurrence.

int
Fjoin(FBFR *dest, FBFR *src)

For fields that match on field ID/occurrence, the field value is updated in the destination buffer with the value from the source buffer. Fields in the destination buffer that have no corresponding field ID/occurrence in the source buffer are deleted. Fields in the source buffer that have no corresponding field ID/occurrence in the destination buffer are not added to the destination buffer. Thus

if(Fjoin(dest,src) < 0)
F_error("pgm_name");

Using the input buffers in the previous example results in a destination buffer that has source field value A and source field value C. This function may fail due to lack of space if the new values are larger than the old (FNOSPACE); in this case, the destination buffer will have been modified. However, if this happens, the destination buffer may be reallocated using Frealloc and the Fjoin function repeated (even if the destination buffer has been partially updated, repeating the function gives the correct results).

If joining buffers results in the removal of a pointer field (FLD_PTR), the memory area referenced by the pointer is not modified or freed.

For more information, refer to Fjoin, Fjoin32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fojoin

Fojoin is similar to Fjoin, but it does not delete fields from the destination buffer that have no corresponding field ID/occurrence in the source buffer.

int
Fojoin(FBFR *dest, FBFR *src)

Note that fields in the source buffer for which there are no corresponding field ID/occurrence pairs in the destination buffer are not added to the destination buffer. Consider the following example:

if(Fojoin(dest,src) < 0)
F_error("pgm_name");

Using the input buffers from the previous example, dest contains the source field value A, the destination field value B, the source field value C, and the second destination field value C. As with Fjoin, this function can fail for lack of space (FNOSPACE) and can be reissued again after more space has been allocated to complete the operation.

If joining buffers results in the removal of a pointer field (FLD_PTR), the memory area referenced by the pointer is not modified or freed.

For more information, refer to Fojoin, Fojoin32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fproj

Fproj is used to update a buffer in place so that only the desired fields are kept. (The result, in other words, is a projection on specified fields.) If updating buffers results in the removal of a pointer field (FLD_PTR), the memory area referenced by the pointer is not modified or freed.

int
Fproj(FBFR *fbfr, FLDID *fieldid)

These fields are specified in an array of field identifiers passed to the function. The update is performed directly in the fielded buffer. Consider the following example:

#include "fldtbl.h"
FBFR *fbfr;
FLDID fieldid[20];
. . .
fieldid[0] = A; /* field id for field A */
fieldid[1] = D; /* field id for field D */
fieldid[2] = BADFLDID; /* sentinel value */
if(Fproj(fbfr, fieldid) < 0)
F_error("pgm_name");

If the buffer has fields A, B, C, and D, the example results in a buffer that contains only occurrences of fields A and D. Note that the entries in the array of field identifiers do not need to be in any specific order, but the last value in the array of field identifiers must be field identifier 0 (BADFLDID).

For more information, refer to Fproj, Fproj32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fprojcpy

Fprojcpy is similar to Fproj but the desired fields are placed in a destination buffer. If updating buffers results in the removal of a pointer field (FLD_PTR), the memory area referenced by the pointer is not modified or freed.

int
Fprojcpy(FBFR *dest, FBFR *src, FLDID *fieldid)

Any fields in the destination buffer are first deleted and the results of the projection on the source buffer are copied into the destination buffer. Using the above example, the following code places the results of the projection in the destination buffer:

if(Fprojcpy(dest, src, fieldid) < 0)
F_error("pgm_name");

The entries in the array of field identifiers may be rearranged; if the entries are not in numeric order, the field identifier array is sorted.

For more information, refer to Fprojcpy, Fprojcpy32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fupdate

Fupdate updates the destination buffer with the field values in the source buffer.

int
Fupdate(FBFR *dest, FBFR *src)

For fields that match on field ID/occurrence, the field value is updated in the destination buffer with the value in the source buffer (like Fjoin). Fields on the destination buffer that have no corresponding field on the source buffer are left untouched (like Fojoin). Fields on the source buffer that have no corresponding field on the destination buffer are added to the destination buffer (like Fconcat). Consider the following example:

if(Fupdate(dest,src) < 0)
F_error("pgm_name");

If the src buffer has fields A, C, and D, and the dest buffer has fields A, B, and two occurrences of C, the updated destination buffer contains: the source field value A, the destination field value B, the source field value C, the second destination field value C, and the source field value D.

For pointers, Fupdate32 stores the pointer value. The buffer pointed to by a FLD_PTR field must be allocated using the tpalloc(3c) call. For embedded FML32 buffers, Fupdate32 stores the entire FLD_FML32 field value, except the index.

For embedded VIEW32 buffers, Fupdate32 stores a pointer to a structure of type FVIEWFLD, which contains vflags (a flags field, currently unused and set to 0), vname (a character array containing the view name), and data (a pointer to the view data stored as a C structure). The application provides the vname and data to Fupdate32. The FVIEWFLD structure is as follows:

typedef struct { 
TM32U vflags; /* flags - currently unused */
char vname[FVIEWNAMESIZE+1]; /* name of view */
char *data; /* pointer to view structure */
} FVIEWFLD;

For more information, refer to Fupdate, Fupdate32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


VIEWS Functions

Fvftos

This function transfers data from a fielded buffer to a C structure using a specified view description.

int
Fvftos(FBFR *fbfr, char *cstruct, char *view)

Here:

If the named view is not found, Fvftos returns -1, and Ferror is set to FBADVIEW.

When data is being transferred from a fielded buffer to a C structure, the following rules apply:

For example, the following code puts string1 into cust.action[0] and abc into cust.bug[0]. All other members in the cust structure should contain null values.

#include <stdio.h>
#include "fml.h"
#include "custdb.flds.h"
#include "custdb.h"
struct custdb cust;
FBFR *fbfr;
. . .
fbfr = Falloc(800,1000);
Fvinit((char *)&cust,"custdb"); /* initialize cust */
str = "string1";
Fadd(fbfr,ACTION,str,(FLDLEN)8);
str = "abc";
Fadd(fbfr,BUG_CURS,str,(FLDLEN)4);
Fvftos(fbfr,(char *)&cust,"custdb");
. . .

View custdb is defined in VIEWS Examples.

For more information, refer to Fvftos, Fvftos32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvstof

This function transfers data from a C structure to a fielded buffer using a specified view description.

int
Fvstof(FBFR *fbfr, char *cstruct, int mode, char *view)

Here:

The transfer process obeys the rules listed under the FML function corresponding to the mode parameter: Fupdate, Fjoin, Fojoin, or Fconcat.

If the named view is not found, Fvstof returns -1, and Ferror is set to FBADVIEW.

Note: Null values are not transferred from a structure member to a fielded buffer. That is, during a structure-to-field transfer, if a structure member contains the (default or user-specified) null value defined for that member, the member is ignored.

For more information, refer to Fvftos, Fvftos32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvnull

Fvnull is used to determine whether an occurrence in a C structure contains the null value for that field.

int
Fvnull(char *cstruct, char *cname, FLDOCC oc, char *view)

Here:

Fvnull returns:

For more information, refer to Fvnull, Fvnull32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvsinit

This function initializes all elements in a C structure to their appropriate null value.

int
Fvsinit(char *cstruct, char *view)

Here:

For more information, refer to Fvsinit, Fvsinit32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvopt

This function allows users to change flag options at run time.

int
Fvopt(char *cname, int option, char *view)

Here:

The following list describes possible values for the option parameter.

F_FTOS

Allows one-way mapping from fielded buffers to C structures. Similar to the S option in view descriptions.

F_STOF

Allows one-way mapping from C structures to fielded buffers. Similar to the F option in view descriptions.

F_BOTH

Allows two-way mapping between C structures and fielded buffers.

F_OFF

Turns off mapping of the specified member. Similar to the N option in view descriptions.

Note that changes to view descriptions are not permanent. They are guaranteed only until another view description is accessed.

For more information, refer to Fvopt, Fvopt32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fvselinit

This function initializes an individual member of a C structure to its appropriate null value. It sets the ACM of the element to 0, if the C flag is used in the view file; it sets the ALMs to the length of the associated null value, if the L flag is used in the view file.

int
Fvselinit(char *cstruct, char *cname, char *view)

Here:

For more information, refer to Fvselinit, Fvselinit32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Conversion Functions

FML provides a set of routines that perform data conversion upon reading or writing a fielded buffer.

Generally, the functions behave like their non-conversion counterparts, except that they provide conversion from a user type to the native field type when writing to a buffer, and from the native type to a user type when reading from a buffer.

The native type of a field is the type specified for it in its field table entry and encoded in its field identifier. (The only exception to this rule is CFfindocc, which, although it is a read operation, converts from the user-specified type to the native type before calling Ffindocc.) The function names are the same as their non-conversion FML counterparts except that they include a “C” prefix.

The following field types are not supported for conversion functions: pointers (FLD_PTR), embedded FML32 buffers (FLD_FML32), and embedded VIEW32 buffers (FLD_VIEW32). If one of these field types is encountered during the execution of an FML32 conversion function, Ferror is set to FEBADOP.

CFadd

The CFadd function adds a user-supplied item to a buffer creating a new field occurrence within the buffer.

int
CFadd(FBFR *fbfr, FLDID fieldid, char *value, FLDLEN len, int type)

Here:

Before the field addition, the data item is converted from a user-supplied type to the type specified in the field table as the fielded buffer storage type of the field. If the source type is FLD_CARRAY (character array), the length argument should be set to the length of the array. Consider the following example:

if(CFadd(fbfr,ZIP,"12345",(FLDLEN)0,FLD_STRING) < 0)
F_error("pgm_name");

If the ZIP (zip code) field were stored in a fielded buffer as a long integer, the function would convert “12345” to a long integer representation, before adding it to the fielded buffer pointed to by fbfr (note that the field value length is given as 0 since the function can determine it; the length is needed only for type FLD_CARRAY). The following code puts the same value into the fielded buffer, but does so by presenting it as a long, instead of as a string:

long zipval;
. . .
zipval = 12345;
if(CFadd(fbfr,ZIP,&zipval,(FLDLEN)0,FLD_LONG) < 0)
F_error("pgm_name");

Note that the value must first be put into a variable, since C does not permit the construct &12345L. CFadd returns 1 on success, and -1 on error, in which case Ferror is set appropriately.

For more information, refer to CFadd, CFadd32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

CFchg

The function CFchg acts like CFadd, except that it changes the value of a field (after conversion of the supplied value).

int
CFchg(FBFR *fbfr, FLDID fieldid, FLDOCC oc, char *value, FLDLEN len, int type)

Here:

For example, the following code changes the first occurrence (occurrence 0) of field ZIP to the specified value, doing any needed conversion:

FLDOCC occurrence;
long zipval;
. . .
zipval = 12345;
occurrence = 0;
if(CFchg(fbfr,ZIP,occurrence,&zipval,(FLDLEN)0,FLD_LONG) < 0)
F_error("pgm_name");

If the specified occurrence is not found, then null occurrences are added to pad the buffer with multiple occurrences until the value can be added as the specified occurrence.

For more information, refer to CFchg, CFchg32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

CFget

CFget is the conversion analog of Fget. The difference is that it copies a converted value to the user-supplied buffer.

int
CFget(FBFR *fbfr, FLDID fieldid, FLDOCC oc, char *buf, FLDLEN *len, int type)

Here:

Using the previous example, the following code gets the value that was just stored in the buffer (regardless of which format is being used) and converts it back to a long integer:

FLDLEN len;
. . .
len=sizeof(zipval);
if(CFget(fbfr,ZIP,occurrence,&zipval,&len,FLD_LONG) < 0)
F_error("pgm_name");

If the length pointer is NULL, then the length of the value retrieved and converted is not returned.

For more information, refer to CFget, CFget32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

CFgetalloc

CFgetalloc is like Fgetalloc; you are responsible for freeing the space allocated with malloc for the returned (converted) value with free.

char *
CFgetalloc(FBFR *fbfr, FLDID fieldid, FLDOCC oc, int type, FLDLEN *extralen)

Here:

In the declaration above, the return value to CFgetalloc is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

The previously stored value can be retrieved into space allocated automatically for you by the following code:

char *value;
FLDLEN extra;
. . .
extra = 25;
if((value=CFgetalloc(fbfr,ZIP,0,FLD_LONG,&extra)) == NULL)
F_error("pgm_name");

The value extra in the function call indicates that the function should allocate an extra 25 bytes over the amount of space sufficient for the retrieved value. The total amount of space allocated is returned in this variable.

For more information, refer to CFgetalloc, CFgetalloc32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

CFfind

CFfind returns a pointer to a converted value of the desired field.

char *
CFfind(FBFR *fbfr, FLDID fieldid, FLDOCC oc, FLDLEN len, int type)

Here:

In the previous declaration the return value to CFfind is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

Like Ffind, this pointer should be considered “readonly.” For example, the following code returns a pointer to a long containing the value of the first occurrence of the ZIP field:

char *CFfind;
FLDLEN len;
long *value;
. . .
if((value=(long *)CFfind(fbfr,ZIP,occurrence,&len,FLD_LONG))== NULL)
F_error("pgm_name");

If the length pointer is NULL, then the length of the value found is not returned. Unlike Ffind, the value returned is guaranteed to be properly aligned for the corresponding user-specified type.

Note: The duration of the validity of the pointer returned by CFfind is guaranteed only until the next buffer operation, even if it is non-destructive, since the converted value is retained in a single private buffer. This differs from the value returned by Ffind, which is guaranteed until the next modification of the buffer.

For more information, refer to CFfind, CFfind32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

CFfindocc

CFfindocc looks at occurrences of the specified field on the buffer and returns the occurrence number of the first field occurrence that matches the user-specified field value after it has been converted to the type of the field identifier.

FLDOCC
CFfindocc(FBFR *fbfr, FLDID fieldid, char *value, FLDLEN len, int type)

Here:

For example, the following code converts the string to the type of fieldid ZIP (possibly a long) and sets oc to the occurrence for the specified zip code:

#include "fldtbl.h"
FBFR *fbfr;
FLDOCC oc;
char zipvalue[20];
. . .
strcpy(zipvalue,"123456");
if((oc=CFfindocc(fbfr,ZIP,zipvalue,0,FLD_STRING)) < 0)
F_error("pgm_name");

If the field value is not found, -1 is returned.

Note: Because CFfindocc converts the user-specified value to the native field type before examining the field values, regular expressions work only when the user-specified type and the native field type are both FLD_STRING. Thus, CFfindocc has no utility with regular expressions.

For more information, refer to CFf indocc, CFfindocc32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Converting Strings

The following set of functions is provided to handle the case of conversion to and from a user type of FLD_STRING:

These functions call their non-string-function counterparts, providing a type of FLD_STRING, and a len of 0. Note that the duration of the validity of the pointer returned by Ffinds is the same as that described for CFfind.

For descriptions of these functions, see Oracle Tuxedo ATMI FML Function Reference.

Ftypcvt

The functions CFadd, CFchg, CFget, CFgetalloc, and CFfind use the function Ftypcvt to perform the appropriate data conversion. The Ftypcvt32 function fails for the FLD_PTR, FLD_FML32, and FLD_VIEW32 field types. The synopsis of Ftypcvt usage is as follows (it does not follow the parameter order conventions).

char *
Ftypcvt(FLDLEN *tolen, int totype, char *fromval, int fromtype, FLDLEN fromlen)

Here:

Ftypcvt converts from the value *fromval, which has type fromtype, and length fromlen if fromtype is type FLD_CARRAY (otherwise fromlen is inferred from fromtype), to a value of type totype. Ftypcvt returns a pointer to the converted value, and sets *tolen to the converted length, upon success. Upon failure, Ftypcvt returns NULL. Consider the following example, in which the CFchg function is used:

CFchg(fbfr,fieldid,oc,value,len,type)
FBFR *fbfr; /* fielded buffer */
FLDID fieldid; /* field to be changed */
FLDOCC oc; /* occurrence of field to be changed */
char *value; /* location of new value */
FLDLEN len; /* length of new value */
int type; /* type of new value */
{
char *convloc; /* location of post-conversion value */
FLDLEN convlen; /* length of post-conversion value */
extern char *Ftypcvt;

/* convert value to fielded buffer type */
if((convloc = Ftypcvt(&convlen,FLDTYPE(fieldid),value,type,len)) == NULL)
return(-1);

if(Fchg(fbfr,fieldid,oc,convloc,convlen) < 0)
return(-1);
return(1);
}

The user may call Ftypcvt directly to do field value conversion without adding or modifying a fielded buffer.

For more information, refer to Ftypcvt, Ftypcvt32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Conversion Rules

In the following list of conversion rules, oldval represents a pointer to the data item being converted, and newval, a pointer to the post-conversion value.

The following table summarizes the conversion rules presented in this section.

Table 5-2 Summary of Conversion Rules
src type
dest type
-
char
short
long
float
double
string
carray
dec_t
char
-
cast
cast
cast
cast
st[0]=c
array[0]=c
d
short
cast
-
cast
cast
cast
sprintf
sprintf
d
long
cast
cast
-
cast
cast
sprintf
sprintf
d
float
cast
cast
cast
-
cast
sprintf
sprintf
d
double
cast
cast
cast
cast
-
sprintf
sprintf
d
string
c=st[0]
atoi
atol
atof
atof
-
drop 0
d
carray
c=array[0]
atoi
atol
atof
atof
add 0
-
d
dec_t
d
d
d
d
d
d
d
-

The following table defines the entries listed in the previous table.

Table 5-3 Meanings of Entries in the Summary of Conversion Rules
Entry
Meaning
-
src and dest are the same type; no conversion required
cast
Conversion done using C assignment with type casting
sprintf
Conversion done using sprintf function
atoi
Conversion done using atoi function
atof
Conversion done using atof function
atol
Conversion done using atol function
add 0
Conversion done by concatenating NULL byte
drop 0
Conversion done by dropping terminating NULL byte
c=array[0]
Character set to first byte of array
array[0]=c
First byte of array is set to character
c=st[0]
Character set to first byte of string
st[0]=c
First byte of string set to c
d
decimal(3c) conversion function

 


Converting FLD_MBSTRING Fields

The following set of functions is provided to handle code-set encoding conversion of data in user type of FLD_MBSTRING:

These functions prepare the encoding name and multibyte data information for an FLD_MBSTRING field, extract the encoding name and multibyte data information from an FLD_MBSTRING field, and convert the multibyte characters in an FLD_MBSTRING field to a named target encoding. The following figure shows through example how encoding conversion works.

Figure 5-1 Encoding Conversion Using FML32 Buffers—Example

Encoding Conversion Using FML32 Buffers—Example

As indicated in the example, the FLD_MBSTRING field is capable of carrying information identifying the code-set character encoding, or simply encoding, of its user data. In the example, the client-request FLD_MBSTRING field holds Japanese user data represented by the Shift-JIS (SJIS) encoding, while the server-reply FLD_MBSTRING field holds Japanese user data represented by the Extended UNIX Code (EUC) encoding. The multibyte character encoding feature reads environment variables TPMBENC and TPMBACONV to determine the source encoding, the target encoding, and the state (on or off) of automatic encoding conversion.

As shown in the following figure, the FML32 typed buffer, itself, is capable of carrying information identifying the character encoding of its user data.

Figure 5-2 Using Global Encoding

Using Global Encoding

For an FML32 typed buffer holding many FLD_MBSTRING fields, using global encoding is a more efficient way to transport multibyte user data via FML32 buffers than adding a character encoding name to each FLD_MBSTRING field. Using the Fmbpack32() function, application developers can choose global encoding or individual encoding for each FLD_MBSTRING field created via Fmbpack32(). Only one global encoding name is allowed per FML32 buffer.

The encoding conversion capability enables the underlying Tuxedo system software to convert the encoding representation of an incoming FLD_MBSTRING field to an encoding representation supported by the machine on which the receiving process is running. The conversion is neither a conversion between character code sets nor a translation between languages, but rather a conversion between different character encodings for the same language.

Fmbpack32

This function prepares the encoding name and multibyte data information for an FLD_MBSTRING field input to an FML32 typed buffer. Fmbpack32() is used before the FLD_MBSTRING field is added to an FML32 buffer via FML32 APIs.

For more information about this function, refer to the Fmbpack32(3fml) function in Oracle Tuxedo ATMI FML Function Reference.

Fmbunpack32

This function extracts the encoding name and multibyte data information from an FLD_MBSTRING field in an FML32 typed buffer. Fmbunpack32() is used after the FLD_MBSTRING field is extracted from an FML32 buffer via FML32 APIs (Ffind32(), Fget32(), ...).

For more information about this function, refer to the Fmbunpack32(3fml) function in Oracle Tuxedo ATMI FML Function Reference.

tpconvfmb32

This function converts the multibyte characters in an FLD_MBSTRING field in an FML32 typed buffer to a named target encoding. Specifically, tpconvfmb32() compares the source encoding name specified for the FLD_MBSTRING field with the target encoding name defined in target_encoding; if the encoding names are different, tpconvfmb32() converts the FLD_MBSTRING field data to the target encoding.

For more information about this function, refer to the tpconvfmb32(3fml) function in Oracle Tuxedo ATMI FML Function Reference.

tpconvvmb32

This function converts the multibyte characters in an MBSTRING field in a VIEW32 typed buffer to a named target encoding. Specifically, tpconvvmb32() compares the source encoding name specified for the MBSTRING field with the target encoding name defined in target_encoding; if the encoding names are different, tpconvvmb32() converts the MBSTRING field data to the target encoding.

For more information about this function, refer to the tpconvvmb32(3fml) function in Oracle Tuxedo ATMI FML Function Reference.

 


Indexing Functions

When a fielded buffer is initialized by Finit or Falloc, an index is automatically set up. This index is used to expedite fielded buffer accesses and is transparent to you. As fields are added to or deleted from the fielded buffer, the index is automatically updated.

However, when storing a fielded buffer on a long-term storage device, or when transferring it between cooperating processes, it may be desirable to save space by eliminating its index and regenerating it upon receipt. The functions described in this section may be used to perform such index manipulations.

Fidxused

This function returns the amount of space used by the index of a buffer.

long
Fidxused(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer.

You can use this function to determine the size of the index of a buffer, and whether significant time or space can be saved by deleting the index.

For more information, refer to Fidxused, Fidxused32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Findex

The function Findex may be used at any time to index an unindexed fielded buffer.

int
Findex(FBFR *fbfr. FLDOCC intvl)

Here:

The second argument to Findex specifies the indexing interval for the buffer. If 0 is specified, the value FSTDXINT (defined in fml.h) is used. The user may ensure that all fields are indexed by specifying an interval of 1.

Note that more space may be made available in an existing buffer for user data by increasing the indexing interval, and reindexing the buffer. This represents a space/time trade-off, however, since reducing the number of index elements (by increasing the index interval), means, in general, that searches for fields will take longer. Most operations attempt to drop the entire index if they run out of space before returning a “no space” error.

For more information, refer to Findex, Findex32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Frstrindex

This function can be used instead of Findex for cases in which the fielded buffer has not been altered since its index was removed.

int
Frstrindex(FBFR *fbfr, FLDOCC numidx)

Here:

For more information, refer to Frstrindex, Frstrindex32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Funindex

Funindex discards the index of a fielded buffer and returns the number of index entries the buffer had before the index was stripped.

FLDOCC
Funindex(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer.

For more information, refer to Funindex, Funindex32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Example of Sending a Fielded Buffer Without an Index

To transmit a fielded buffer without its index, complete a procedure such as the following:

  1. Remove the index:
  2. save = Funindex(fbfr);
  3. Get the number of bytes to send (that is, the number of significant bytes from the beginning of the buffer):
  4. num_to_send = Fused(fbfr);
  5. Send the buffer without the index:
  6. transmit(fbfr,num_to_send);
  7. Restore the index to the buffer:
  8. Frstrindex(fbfr,save);

The index may be regenerated on the receiving side by the following statement:

Findex(fbfr);

Note that the receiving process cannot call Frstrindex because it did not remove the index itself, and the index was not sent with the file.

Note: The space used in memory by the index is not freed by calling Funindex. The Funindex function only saves space on disk or when sending a buffer to another process. Of course, you are always free to send a fielded buffer and its index to another process and avoid using these functions.

 


Input/Output Functions

The functions described in this section support input and output of fielded buffers to standard I/O or to file streams.

Fread and Fwrite

The I/O functions Fread and Fwrite work with the standard I/O library:

int Fread(FBFR *fbfr, FILE *iop)
int Fwrite(FBFR *fbfr, FILE *iop)

The stream to which—or from which—I/O is directed is determined by a FILE pointer argument. This argument must be set up using the normal standard I/O library functions.

A fielded buffer may be written into a standard I/O stream with the function Fwrite, as follows:

if (Fwrite(fbfr, iop) < 0)
F_error("pgm_name");

A buffer written with Fwrite may be read with Fread, as follows.

if(Fread(fbfr, iop) < 0)
F_error("pgm_name");

Although the contents of the fielded buffer pointed to by fbfr are replaced by the fielded buffer read in, the capacity of the fielded buffer (that is, the size of the buffer) remains unchanged.

Fwrite discards the buffer index, writing only as much of the fielded buffer as has been used (as returned by Fused).

Fread restores the index of a buffer by calling Findex. The buffer is indexed with the same indexing interval with which it was written by Fwrite. Fread32 ignores the FLD_PTR field type.

For more information, refer to Fread, Fread32(3fml) and Fwrite, Fwrite32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fchksum

A checksum may be calculated for verifying I/O, as follows:

long chk;
. . .
chk = Fchksum(fbfr);

The user is responsible for calling Fchksum, writing the checksum value out, along with the fielded buffer, and checking it on input. Fwrite does not write the checksum automatically. For pointer fields (FLD_PTR), the name of the pointer field in the checksum calculation (rather than the pointer or the data referenced by the pointer) is included.

For more information, refer to Fchksum, Fchksum32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fprint and Ffprint

The Fprint function prints a fielded buffer on the standard output in text format.

Fprint(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer.

Ffprint is similar to Fprint, except that it sends text to a specified output stream, as in the following line:

Ffprint(FBFR *fbfr, FILE *iop)

Here:

Each of these print functions prints, for each field occurrence, the field name and the field value, separated by a tab and followed by a new line. Fname is used to determine the field name. If the field name cannot be determined, then the field identifier is printed. Non-printable characters in the field values for strings and character arrays are represented by a backslash followed by their two-character hexadecimal value. Backslashes occurring in the text are escaped with an extra backslash. A blank line is printed following the output of the printed buffer.

For values of type FLD_PTR, Fprint32 prints the field name or field identifier and the pointer value in hexadecimal. Although this function prints pointer information, the Fextread32 function ignores the FLD_PTR field type. For values of type FLD_FML32, Fprint32 recursively prints the FML32 buffer, with leading tabs added for each level of nesting. For values of type FLD_VIEW32, this function prints the VIEW32 field name and structure member name/value pairs.

For more information, refer to Fprint, Fprint32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fextread

Fextread may be used to construct a fielded buffer from its printed format, that is, from the output of Fprint (hexadecimal values output by Fprint are interpreted properly).

int
Fextread(FBFR *fbfr, FILE *iop)

Fextread accepts an optional flag preceding the field name/field identifier specification in the output of Fprint, as shown in the following table.

If no flag is specified, the default action is to Fadd the field to the buffer.

Field values may be extended across lines by beginning each overflow line with a tab (which is later discarded). A single blank line signals the end of the buffer; successive blank lines yield a null buffer. For embedded buffers FLD_FML32 and FLD_VIEW32, Fextread generates nested FML32 buffers and VIEW32 fields, respectively. Fextread32 ignores the FLD_PTR field type.

If an error has occurred, -1 is returned, and Ferror is set accordingly. If the end of the file is reached before a blank line, Ferror is set to FSYNTAX.

For more information, refer to Fextread, Fextread32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


Boolean Expressions of Fielded Buffers

This topic includes the following sections:

This section describes the functions available for evaluating Boolean expressions in which the “variables” are the values of fields in a fielded buffer or a VIEW. Functions described in this section allow you to:

A function is provided that compiles the expression into a compact form suitable for efficient evaluation. A second function evaluates the compiled form against a fielded buffer to produce a true or false answer.

 


Definitions of Boolean Expressions

This section describes, in detail, the expressions accepted by the Boolean compilation function, and explains how each expression is evaluated.

The following standard C language operators are not supported:

The following table shows the Backus-Naur Form definitions of the accepted Boolean expressions.

Table 5-5 BNF Boolean Expression Definitions  
Expression
Definition
<boolean>
<boolean> || <logical and> | <logical and>
<logical and>
<logical and> && <xor expr> | <xor expr>
<xor expr>
<xor expr> ^ <equality expr> | <equality expr>
<equality expr>
<equality expr> <eq op> <relational expr> | <relational expr>
<eq op>
== | != | %% | !%
<relational expr>
<relational expr> <rel op> <additive expr> | <additive expr>
<rel op>
< | <= | >= | > |
<additive expr>
<additive expr> <add op> <multiplicative expr> | <multiplicative expr>
<add op>
+ | -
<multiplicative expr>
<multiplicative expr> <mult op> <unary expr> | <unary expr>
<mult op>
* | / | %
<unary expr>
<unary op> <primary expr> | <primary expr>
<unary op>
+ | - | ~ | !
<primary expr>
( <boolean> ) | <unsigned constant> | <field ref>
<unsigned constant>
<unsigned number> | <string>
<unsigned number>
<unsigned float> | <unsigned int>
<string>
' <character> {<character>. . .} '
<field ref>
<field name> | <field name>[<field occurrence>]
<field occurrence>
<unsigned int> | <meta>
<meta>
?

The following sections describe Boolean expressions in greater detail.

 


Field Names and Types

The only variables allowed in Boolean expressions are field references. There are several restrictions on field names. Names are made up of letters and digits; the first character must be a letter. The underscore ( _ ) counts as a letter; it is useful for improving the readability of long variable names. Up to 30 characters are significant. There are no reserved words.

For a fielded buffer evaluation, any field that is referenced in a Boolean expression must exist in a field table. This implies that the FLDTBLDIR and FIELDTBLS environment variables are set, as described in Setting Up Your Environment for FML and VIEWS before using the Boolean compilation function. The field types used in Booleans are those allowed for FML fields: short, long, float, double, char, string, and carray. Along with the field name, the field type is kept in the field table. Thus, the field type can always be determined.

For a VIEW evaluation, any field that is referenced in a Boolean expression must exist as a C structure element name, not the associated fielded buffer name, in the VIEW. This implies that the VIEWDIR and VIEWFILES environment variables are set, as described in Setting Up Your Environment for FML and VIEWS before using the Boolean compilation function. The field types used in Booleans are those allowed for FML VIEWS: short, long, float, double, char, string, carray, plus int and dec_t. Along with the field name, the field type is kept in the view definition. Thus, the field type can always be determined.

Strings

A string is a group of characters within single quotes. The ASCII code for a character may be substituted for the character via an escape sequence. An escape sequence takes the form of a backslash followed by exactly two hexadecimal digits. This convention differs from the C language convention of using a hexadecimal escape sequence that starts with \x.

As an example, consider ‘hello’ and ‘hell\\6f’. They are equivalent strings because the hexadecimal code for an ‘o’ is 6f.

Octal escape sequences and escape sequences such as \n are not supported.

Constants

Numeric integer and floating point constants are accepted, as in C. (Octal and hexadecimal constants are not recognized.) Integer constants are treated as longs and floating point constants are treated as doubles. (Decimal constants for the dec_t type are not supported.)

 


How a Boolean Expression Is Converted for Evaluation

To evaluate a Boolean expression, the Boolean compiler performs the following conversions:

 


Description of Boolean Primary Expressions

Boolean expressions are built from primary expressions, which can be any of the following:

A field name or a field name followed by a subscript is a primary expression. The subscript indicates which occurrence of the field is being referenced. The subscript may be either an integer constant, or ? indicating any occurrence; the subscript cannot be an expression. If the field name is not subscripted, field occurrence 0 is assumed.

If a field name reference appears without an arithmetic, unary, equality, or relational operator, then its value is the long integer value 1 if the field exists and 0 if the field does not exist. This may be used to test the existence of a field in the fielded buffer regardless of field type. (Note that there is no * indirection operator.)

A constant is a primary expression. Its type may be long, double, or carray, as discussed in the conversion section.

A parenthesized expression is a primary expression for which the type and value are identical to those of the unadorned expression. Parentheses may be used to change the precedence of operators, which is discussed in the next section.

Description of Boolean Expression Operators

The following table lists the Boolean expression operators in descending order of precedence.

Table 5-6 Boolean Expression Operators
Type
Operators
Unary
+, -, !, ~
Multiplicative
*, /, %
Additive
+, -
Relational
< , >, <=, >=, ==, !=
Equality and matching
==, !=, %%, !%
Exclusive OR
^
Logical AND
&&
Logical OR
||

The operators classified as the same operator type have equal precedence. The following sections discuss each operator type in detail. As in C, you can override the precedence of operators by using parentheses.

Unary Operators Used in Boolean Expressions

The following unary operators are recognized:

Expressions in which unary operators are used group right-to-left:

+ expression
- expression
~ expression
! expression

The unary plus operator has no effect on the operand; it is recognized and ignored. The result of the unary minus operator is the negative of its operand. The usual arithmetic conversions are performed. Unsigned entities do not exist in FML and thus cause no problems with this operator.

The result of the logical negation operator is 1 if the value of its operand is 0, and 0 if the value of its operand is non-zero. The type of the result is long.

The result of the one’s complement operator is the one’s complement of its operand. The type of the result is long.

Multiplicative Operators Used in Boolean Expressions

The multiplicative operators—*, /, and %—group left-to-right. The usual arithmetic conversions are performed:

expression * expression
expression
/ expression
expression
% expression

The binary * operator indicates multiplication. The * operator is associative and expressions with several multiplications at the same level may be rearranged by the compiler.

The binary / operator indicates division. When positive integers are divided, truncation is toward 0, but the form of truncation is machine-dependent if either operand is negative.

The binary % operator yields the remainder from the division of the first expression by the second. The usual arithmetic conversions are performed. The operands must not be float or double.

Additive Operators Used in Boolean Expressions

The additive operators + and - group left-to-right. The usual arithmetic conversions are performed:

expression + expression
expression
- expression

The result of the + operator is the sum of the operands. The + operator is associative and expressions with several additions at the same level may be rearranged by the compiler. The operands must not both be strings; if one is a string, it is converted to the arithmetic type of the other.

The result of the - operator is the difference of the operands. The usual arithmetic conversions are performed. The operands must not both be strings; if one is a string, it is converted to the arithmetic type of the other.

Equality and Match Operators Used in Boolean Expressions

These operators group left-to-right:

expression == expression
expression
!= expression
expression
%% expression
expression
!% expression

The == (equal to) and the != (not equal to) operators yield 0 if the specified relation is false and 1 if it is true. The type of the result is long. The usual arithmetic conversions are performed.

The %% operator takes, as its second expression, a regular expression against which it matches its first expression. The second expression (the regular expression) must be a quoted string. The first expression may be an FML field name or a quoted string. This operator yields a 1 if the first expression is fully matched by the second expression (the regular expression). The operator yields a 0 in all other cases.

The !% operator is the not regular expression match operator. It takes exactly the same operands as the %% operator, but yields exactly the opposite results. The relationship between %% and !% is analogous to the relationship between == and !=.

The regular expressions allowed are described on the tpsubscribe(3c) reference page in the Oracle Tuxedo ATMI C Function Reference.

Relational Operators Used in Boolean Expressions

These operators group left-to-right:

expression < expression
expression
> expression
expression
<= expression
expression
>= expression

The operators < (less than), > (greater than), <= (less than or equal to) and >= (greater than or equal to) all yield 0 if the specified relation is false and 1 if it is true. The type of the result is long. The usual arithmetic conversions are performed.

Exclusive OR Operator Used in Boolean Expressions

The ^ operator groups left-to-right:

expression ^ expression

It returns the bitwise exclusive OR function of the operands. The result is always a long.

Logical AND Operator Used in Boolean Expressions

expression && expression

The && operator groups left-to-right. It returns 1 if both its operands are non-zero; otherwise, it returns 0. The && operator guarantees left-to-right evaluation. However, it is not guaranteed that the second operand is not evaluated if the first operand is 0; this is different from the C language. The operands need not have the same type. The result is always a long.

Logical OR Operator Used in Boolean Expressions

The || operator groups left-to-right:

expression || expression

It returns 1 if either of its operands is non-zero; otherwise, it returns 0. The || operator guarantees left-to-right evaluation. However, it is not guaranteed that the second operand is not evaluated if the first operand is non-zero; this is different from the C language. The operands need not have the same type, and the result is always a long.

Sample Boolean Expressions

The following field table defines the fields used for the sample Boolean expressions:

EMPID    200    carray
SEX 201 char
AGE 202 short
DEPT 203 long
SALARY 204 float
NAME 205 string

Boolean expressions always evaluate to either true or false. The following example is true if both of the following conditions are true:

This example uses a constant integer as a subscript to EMPID. In the following example, the ? subscript is used, instead:

"PETS[?] == 'dog'"

This expression is true if PETS exists and any occurrence of it contains the characters “dog”.

 


Boolean Functions

The following sections describe the various functions that take Boolean expressions as arguments.

Fboolco and Fvboolco

Fboolco compiles a Boolean expression for FML and returns a pointer to an evaluation tree:

char *
Fboolco(char *expression)

Here *expression is a pointer to an expression to be compiled. This function fails if any of the following field types is used: FLD_PTR, FLD_FML32, or FLD_VIEW32. If one of these field types is encountered, Ferror is set to FEBADOP.

Fvboolco compiles a Boolean expression for a VIEW and returns a pointer to an evaluation tree:

char *
Fvboolco(char *expression, char *viewname)

Here *expression is a pointer to an expression to be compiled, and *viewname is a pointer to the view name for which the fields are evaluated.

Space is allocated using malloc(3) to hold the evaluation tree. For example, the following code compiles a Boolean expression that checks whether the FIRSTNAME field is in the buffer, whether it begins with ‘J’ and ends with ‘n’ (such as “John” or “Joan”), and whether the SEX field is equal to ‘M’.

#include "<stdio.h>"
#include "fml.h"
extern char *Fboolco;
char *tree;
. . .
if((tree=Fboolco("FIRSTNAME %% 'J.*n' && SEX == 'M'")) == NULL)
F_error("pgm_name");

The first and second characters of the tree array form the least significant byte and the most significant byte, respectively, of an unsigned 16-bit quantity that gives the length, in bytes, of the entire array. This value is useful for copying or otherwise manipulating the array.

Because the evaluation tree produced by Fboolco is used by the Boolean functions described in the following sections, it is not necessary to recompile the expression constantly.

Use the free(3) function to free the space allocated to an evaluation tree when the Boolean expression will no longer be used. Compiling many Boolean expressions without freeing the evaluation tree when it is no longer needed may cause a program to run out of data space.

For more information, refer to Fboolco, Fboolco32, Fvboolco, Fvboolco32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fboolpr and Fvboolpr

Fboolpr prints a compiled expression to the specified file stream. The expression is fully parenthesized, as it was parsed (as indicated by the evaluation tree).

void
Fboolpr(char *tree, FILE *iop)

Here:

Fvboolpr prints a compiled expression to the specified file stream.

void
Fvboolpr(char *tree, FILE *iop, char *viewname)

Here:

This function is useful for debugging.

Executing Fboolpr on the expression compiled above produces the following results:

(((FIRSTNAME[0]) %% ('J.*n')) && ((SEX[0]) == ('M')))

For more information, refer to Fboolpr, Fboolpr32, Fvboolpr, Fvboolpr32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

Fboolev and Ffloatev, Fvboolev and Fvfloatev

These functions evaluate a fielded buffer against a Boolean expression.

int Fboolev(FBFR *fbfr,char *tree)
double Ffloatev(FBFR *
fbfr,char *tree)

Here:

The VIEW equivalents are as follows:

int
Fvboolev(FBFR *fbfr,char *tree,char *viewname)
double
Fvfloatev(FBFR *fbfr,char *tree,char *viewname)

Fboolev returns true (1) if the fielded buffer matches the Boolean conditions specified in the evaluation tree. This function does not change either the fielded buffer or the evaluation tree. Using the evaluation tree compiled above, the following code prints “Buffer selected”:

#include <stdio.h>
#include "fml.h"
#include "fldtbl.h"
FBFR *fbfr;
. . .
Fchg(fbfr,FIRSTNAME,0,"John",0);
Fchg(fbfr,SEX,0,"M",0);
if(Fboolev(fbfr,tree) > 0)
fprintf(stderr,"Buffer selected\n");
else
fprintf(stderr,"Buffer not selected\n");

Ffloatev and Ffloatev32 are similar to Fboolev, but return the value of the expression as a double. For example, the following code prints “6.6”:

#include <stdio.h>
#include "fml.h"
FBFR *fbfr;
. . .
main() {
char *Fboolco;
char *tree;
double Ffloatev;
if (tree=Fboolco("3.3+3.3")) {
printf("%lf",Ffloatev(fbfr,tree));
}
}

If Fboolev is used instead of Ffloatev in the previous example, a 1 is printed.

For more information, refer to Fboolev, Fboolev32, Fvboolev, Fvboolev32(3fml) and Ffloatev, Ffloatev32, Fvfloatev, Fvfloatev32(3fml) in Oracle Tuxedo ATMI FML Function Reference.

 


VIEW Conversion to and from Target Format

A VIEW can be converted to and from a target record format. The default target format is that of IBM System/370 COBOL records.

Fvstot, Fvftos and Fcodeset

The following functions convert targets:

long
Fvstot(char *cstruct, char *trecord, long treclen, char *viewname)
long
Fvttos(char *cstruct, char *trecord, char *viewname)
int 
Fcodeset(char *translation_table)

The Fvstot function transfers data from a C structure to a target record type. The Fvttos function transfers data from a target record to a C structure. trecord is a pointer to the target record. cstruct is a pointer to a C structure. viewname is a pointer to the name of a compiled view description. The VIEWDIR and VIEWFILES environment variables are used to find the directory and file containing the compiled view description.

To convert an FML buffer to a target record, complete the following procedure.

  1. Call Fvftos to convert the FML buffer to a C structure.
  2. Call Fvstot to convert to a target record.

To convert a target record to an FML buffer, complete the following procedure.

  1. Call Fvttos to convert to a C structure.
  2. Call Fvstof to convert the structure to an FML buffer.

The default target is that of IBM/370 COBOL records. The default data conversion is done as shown in the following table.

No filler bytes are provided between fields in an IBM/370 record. The COBOL SYNC clause should not be specified for any data items that are a part of the structure corresponding to the view. An integer field is converted to either a four-byte or two-byte integer, depending on the size of integers on the machine on which the conversion is done. A string field in the view must be terminated with a null when converting to and from the IBM/370 format. The data in a carray field is passed unchanged; no data translation is performed.

Packed decimals exist in the IBM/370 environment as two decimal digits packed into one byte with the low-order half byte used to store the sign. The length of a packed decimal may be 1 to 16 bytes with storage available for 1 to 31 digits and a sign. Packed decimals are supported in C structures using the dec_t field type. The dec_t field has a defined size consisting of two numbers separated by a comma. The number to the left of the comma is the total number of bytes occupied by the decimal. The number to the right is the number of digits to the right of the decimal point. The following formula is used for conversion:

dec_t(m, n) <=> S9(2*m-(n+1))V9(n)COMP-3

Decimal values may be converted to and from other data types (such as int, long, string, double, and float) using the functions described in decimal(3c).

See the Fvstof, Fvstof32(3fml) for a description of the default character conversion of ASCII to EBCDIC, and vice-versa.

An alternate character translation table can be used at run time by calling Fcodeset. The translation_table must point to 512 bytes of binary data. The first 256 bytes of data are interpreted as the ASCII-to-EBCDIC translation table. The second 256 bytes of data are interpreted as the EBCDIC-to-ASCII table. Any data after the 512th byte is ignored. If the pointer is NULL, the default translation is used.

For more information, refer to Fvstot, Fvttos(3fml) in Oracle Tuxedo ATMI FML Function Reference.


  Back to Top       Previous  Next