This chapter describes all of the FML and FML VIEWS functions, with the exception of the run-time mapping functions described in Chapter 4, "Field Definition and Use." In this chapter you will learn:
Introduction
For COBOL programs, the FML functions are not directly available. A procedure called 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 Existing 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 ( Functions are also provided to convert an FML32 fielded buffer to an FML16 fielded buffer and vice versa.
For the remainder of this chapter, rather than continuing to give both the FML and FML32 names, and VIEW and VIEW32 names, the 16-bit functions will be described.
To make it easier to remember the parameters for the FML functions, a convention has been adopted for the sequence of function parameters. FML parameters appear in the following sequence:
FINIT
is available to initialize a record for receiving FML data, and FVSTOF
and FVFTOS
are available to convert from a COBOL record to an FML buffer and back. These are described in detail in the BEA TUXEDO COBOL Guide. The COBOL interface will not be described further in this chapter.
FML/FML32 and VIEW/VIEW32
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
; and functions live 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
. Also note that the default required alignment for FML32 buffers is 4-byte alignment.
FLDID
, FLDLEN
, and FLDOCC
). Any call to tpalloc
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.
#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 allocating enough additional space to complete the operation. 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.
FML Parameters
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
).
Several functions allow the programmer to query field tables or field identifiers for information about fields during program execution.
Fldid
returns the field identifier for a given valid field name and loads the field name/fieldid mapping tables from the field table files, if they do not already exist:
FLDID
Fldid(char *name
)
where name
is a valid field name.
The space used by the mapping tables in memory can be freed using the Fnmid_unload
or Fnmid_unload32
function. Note that these tables are separate from the tables loaded and used by the Fname
function.
Fname
returns the field name for a given valid field identifier and loads the fieldid/name mapping tables from the field table files, if they do not already exist:
char *
Fname(FLDIDfieldid
)
where fieldid
is a valid field identifier.
The space used by the mapping tables in memory can be freed using the Fidnm_unload
or Fidnm_unload32
function. Note that these tables are separate from the tables loaded and used by the Fldid
function.
Fldno
extracts the field number from a given field identifier:
FLDOCC
Fldno(FLDIDfieldid
)
where fieldid
is a valid field identifier.
Fldtype
extracts the field type (an integer, as defined in fml.h
) from a given field identifier.
int
Fldtype(FLDIDfieldid
)
where fieldid
is a valid field identifier.
Table 5-1 shows the possible values returned by Fldtype
and their meanings.
Return Value | Meaning |
---|---|
0 |
short integer |
1 |
long integer |
2 |
character |
3 |
single-precision float |
4 |
double-precision float |
5 |
null-terminated string |
6 |
character array |
where For example:
returns a pointer to one of the following strings: As part of an application generator, or to reconstruct a field identifier, it might be useful to be able to make a field identifier from a type specification and an available field number. where
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
)fieldid
is a valid field identifier.
char *typename
. . .
typename = Ftype(fieldid);short
, long
, char
, float
, double
, string
, or carray
.
Fmkfldid
Fmkfldid
provides this functionality:
FLDID
Fmkfldid(int type
, FLDID num
)
type
is a valid type (an integer; see Fldtype
, above)
num
is a field number (it should be an unused field number, to avoid confusion with existing fields)
Most FML functions require a pointer to a fielded buffer as an argument. The typedef In this chapter, the variable Never attempt to declare fielded buffers themselves, only pointers to them. The functions used to reserve space for fielded buffers are explained in the following pages, but first we will describe a function that can be used to determine whether a given buffer is in fact a fielded buffer.
The amount of memory to allocate for a fielded buffer depends on the maximum number of fields it will contain and the total amount of space needed for all the field values. The function where
Buffer Allocation and Initialization
FBFR
is available for declaring such pointers, as in this example:
FBFR *
fbfr
;fbfr
will be used to mean a pointer to 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 and does not set Ferror
in this case.
Fneeded
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
)
F
is the number of fields
The space needed for field values is computed by estimating the amount of space that would be required by each field value if stored in standard structures (e.g., a long is stored as a long and needs four bytes, etc.). For variable length fields, you should estimate the average amount of space needed for the field. The space calculated by Once you obtain the estimate of space from However, this allocated memory space is not yet a fielded buffer. The where
Fneeded
includes a fixed overhead for each field; it adds that to the space needed for the field values.
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 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 */Finit
must be used to initialize it.
Finit
Finit
function initializes an allocated memory space as a fielded buffer.
int
Finit(FBFR *fbfr
, FLDLEN buflen
)
fbfr
is a pointer to an uninitialized fielded buffer
A call to Now
Note:
The numbers used in the Calls to where
Finit
to initialize the memory space allocated in the previous example above would look like the following:
Finit(fbfr, Fneeded(NF, NV));
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.
malloc
(3) (from the previous section) and Finit
calls must be the same.
Falloc
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
)
F
is the number of fields
A call to Storage allocated with Remember that when using the BEA TUXEDO system, the ATMI functions where
Falloc
that would replace the examples above would look like the following:
extern FBFR *Falloc;
. . .
if((fbfr = Falloc(NF, NV)) == NULL)
F_error("pgm_name"); /* couldn't allocate buffer */Falloc
(or Fneeded
, malloc
(3) and Finit
) should be freed with Ffree
.
tpalloc
, tprealloc
, and tpfree
must be used to allocate and free message buffers, rather than the FML functions Falloc
, Frealloc
, and Free
.
Ffree
Ffree
is used to free memory space allocated as a fielded buffer.
int
Ffree(FBFR *fbfr
)
fbfr
is a pointer to a fielded buffer
For example:
Space for a fielded buffer may also be reserved directly. The buffer must begin on a The following code is analogous to the preceding example but It should be emphasized that the following code is quite wrong:
The structure for FBFR is not defined in the user header files so this will result in a compilation error.
where
#include <fml.h>
. . .
if(Ffree(fbfr) < 0)
F_error("pgm_name"); /* not fielded buffer */Ffree
is recommended as opposed to free
(3), because Ffree
will invalidate a fielded buffer whereas free
(3) will 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) were used, it would be possible for malloc
to return a piece of memory that looks like a valid fielded buffer, but is not.
short
boundary. The user must allocate at least F_OVHD
bytes (defined in fml.h
) for the buffer or an error will be returned from Finit
.
Fneeded
cannot be used to size the static buffer since it is not a macro.
/* the first line aligns the buffer */
static short buffer[500/sizeof(short)];
FBFR *fbfr=(FBFR *)buffer;
. . .
Finit(fbfr, 500);FBFR badfbfr;
. . .
Finit(&badfbfr, Fneeded(NF, NV)); Fsizeof
Fsizeof
returns the size of a fielded buffer in bytes:
long
Fsizeof(FBFR *fbfr
)
fbfr
is a pointer to a fielded buffer
For example:
where
long bytes;
. . .
bytes = Fsizeof(fbfr);Fsizeof
returns the same number that Fneeded
returned when the fielded buffer was originally allocated.
Funused
Funused
may be used to determine how much space is available in a fielded buffer for additional data:
long
Funused(FBFR *fbfr
)
fbfr
is a pointer to a fielded buffer
For example:
Note that where
long unused;
. . .
unused = Funused(fbfr);Funused
does not indicate where in the buffer the unused bytes are, only the number of unused bytes.
Fused
Fused
may be used to determine how much space is used in a fielded buffer for data and overhead:
long
Fused(FBFR *fbfr
)
fbfr
is a pointer to a fielded buffer
For example:
Note that At some point, the buffer may run out of space, such as during the addition of a new field value. where
long used;
. . .
used = Fused(fbfr);Fused
does not indicate where in the buffer the used bytes are, only the number of used bytes.
Frealloc
Frealloc
can be used to increase (or decrease) the size of the buffer:
FBFR *
Frealloc(FBFR *fbfr
, FLDOCC nf
, FLDLEN nv
)
fbfr
is a pointer to a fielded buffer
For example:
In this case, the application needed to remember the number of fields and number of value space bytes previously allocated. Note that the arguments to The following example shows a second way of incrementing the allocated space:
Note that 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 above example could be executed as many times as needed without remembering past executions or values. The user need not call If the amount of additional space requested in the call to
Note:
The buffer size can only be decreased to the number of bytes currently being used in the buffer.
The only restriction on the location of fielded buffers is that they must be aligned on a If The function While where
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 */Frealloc
(as with its counterpart realloc
(3)) are absolute values, not increments. This example will not work if space needs to be re-allocated several times.
/* 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 */Finit
after calling Frealloc
.
Frealloc
is contiguous to the old buffer, newfbfr
and fbfr
in the examples above will be the same. However, defensive programming dictates that the user should declare newfbfr
as a safeguard against the case where either a new value or NULL is returned. If Frealloc
fails, do not use fbfr
again.
Functions for Moving Fielded Buffers
short
boundary. Otherwise, fielded buffers are position-independent and may be moved freely around in memory.
Fmove
src
points to a fielded buffer and dest
points to an area of storage big enough to hold it, then the following might be used to move the fielded buffer:
FBFR *
src
;
char *dest
;
. . .
memcpy(dest, src, Fsizeof(src));memcpy
, part of the C runtime 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.
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 (it is computed):
int
Fmove(char *dest
, FBFR *src
)
dest
is a pointer to the destination buffer
For example:
The destination buffer need not be a fielded buffer (that is, it need not have been allocated using where
FBFR *src;
char *dest;
. . .
if(Fmove(dest,src) < 0)
F_error("pgm_name");Fmove
checks that the source buffer is indeed a fielded buffer, but does not modify the source buffer in any way.
Falloc
), but it must be aligned on a short
boundary (4-byte alignment for FML32). Thus, Fmove
provides an alternative to Fcpy
(see below) when it is desired to copy a fielded buffer to a non-fielded buffer, but Fmove
does not check to make sure there is enough room in the destination buffer to receive the source buffer.
Fcpy
Fcpy
is used to overwrite one fielded buffer with another:
int
Fcpy(FBFR *dest
, FBFR *src
)
dest
is a pointer to the destination fielded buffer
Unlike
Note:
You cannot reduce the size of a fielded buffer below the amount of space needed for currently held data.
As with This section discusses how to update and access fielded buffers using the field types of the fields without doing any conversions. The functions that allow you to convert data from one type to another upon transfer to/from a fielded buffer are listed under "Conversion Functions" later in this chapter.
The where
Fcpy
preserves the overall buffer length of the overwritten fielded buffer; thus, Fcpy
is useful for expanding or reducing the size of a fielded buffer. For example:
FBFR *src, *dest;
. . .
if(Fcpy(dest, src) < 0)
F_error("pgm_name");Fmove
, where dest
could point to an uninitialized area, Fcpy
expects dest
to point to an initialized fielded buffer (allocated using Falloc
) and also checks to see that it is big enough to accommodate the data from the source buffer.
Fmove
, the source buffer is not modified by Fcpy
.
Field Access and Modification Functions
Fadd
Fadd
function adds a new field value to the fielded buffer.
int
Fadd(FBFR *fbfr
, FLDID fieldid
, char *value
, FLDLEN len
)
fbfr
is a pointer to a fielded buffer
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, 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, the length must be specified; the length is defined as type gets the field identifier for the desired field and adds the field value to the buffer.
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 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 will be taken from its field type (e.g., length of four for a long) regardless of what value is actually passed. Passing a NULL value address will result in an error ( The where
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.
FLDLEN
. For example:
FLDID fieldid, Fldid;
FBFR *fbfr;
. . .
fieldid = Fldid("fieldname");
if(Fadd(fbfr, fieldid, "new value", (FLDLEN)9) < 0)
F_error("pgm_name");value
must reflect the type of the value it points to; for instance, the following example adds a long field value:
long lval;
. . .
lval = 123456789;
if(Fadd(fbfr, fieldid, &lval, (FLDLEN)0) < 0)
F_error("pgm_name");FEINVAL
).
Fappend
Fappend
function appends a new field value to the fielded buffer.
int
Fappend(FBFR *fbfr
, FLDID fieldid
, char *value
, FLDLEN len
)
fbfr
is a pointer to a fielded buffer
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, the length must be specified; the length is defined as type 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 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 will be taken from its field type (e.g., length of four for a long) regardless of what value is actually passed. Passing a NULL value address will result in an error ( where
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
will end append mode. The following example shows the construction of a 500 row buffer with 5 fields per row using Fappend
.
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.
FLDLEN
.
value
must reflect the type of the value it points to.
FEINVAL
).
Fchg
Fchg
changes the value of a field in the buffer.
int
Fchg(FBFR *fbfr
, FLDID fieldid
, FLDOCC oc
, char *value
, FLDLEN len
)
fbfr
is a pointer to a fielded buffer
For example, to change a field of type If The new or modified value is contained in The buffer must have enough room to contain the modified or added field value, or an error is returned ( where
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");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 will cause 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.
value
. If it is a character array, 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
).
FNOSPACE
).
Fcmp
Fcmp
compares the field identifiers and field values of two fielded buffers.
int
Fcmp(FBFR *fbfr1
, FBFR *fbfr2
)
fbfr1
and fbfr2
are pointers to fielded buffers
fieldid
of a fbfr1
field is less than the field id of the corresponding field of fbfr2
fbfr1
field is less than the value of the corresponding field of fbfr2
The where
Fcmp
returns a 1 if any of the reverse set of the above conditions is true (for example, if the field id of a fbfr2
field is less than the field id of the corresponding field of fbfr1
, etc.).
Fdel
Fdel
function deletes the specified field occurrence.
int
Fdel(FBFR *fbfr
, FLDID fieldid
, FLDOCC oc
)
fbfr
is a pointer to a fielded buffer
For example,
deletes the first occurrence of the field indicated by the specified field identifier. If it does not exist, the function returns where
FLDOCC occurrence;
. . .
occurrence=0;
if(Fdel(fbfr, fieldid, occurrence) < 0)
F_error("pgm_name");-1
(Ferror
is set to FNOTPRES
).
Fdelall
Fdelall
deletes all occurrences of the specified field from the buffer:
int
Fdelall(FBFR *fbfr
, FLDID fieldid
)
fbfr
is a pointer to a fielded buffer
For example:
If the field is not found, the function returns where
if(Fdelall(fbfr, fieldid) < 0)
F_error("pgm_name"); /* field not present */-1
(Ferror
is set to FNOTPRES
).
Fdelete
Fdelete
deletes all occurrences of all fields listed in the array of field identifiers, fieldid[]
:
int
Fdelete(FBFR *fbfr
, FLDID *fieldid
)
fbfr
is a pointer to a fielded buffer
fieldid
is a pointer to the list of field identifiers to be deleted
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 ( If the destination buffer has fields A, B, C, and D, this example will result in a buffer that contains only occurrences of fields B and C.
where
BADFLDID
). For 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");Fdelete
is a more efficient way of deleting several fields from a buffer than using several Fdelall
calls.
Ffind
Ffind
finds the value of the specified field occurrence in the buffer:
char *
Ffind(FBFR *fbfr
, FLDID fieldid
, FLDOCC oc
, FLDLEN *len
)
fbfr
is a pointer to a fielded buffer
In the declaration above the return value to An example of the use of the function is:
If the field is found, its length is returned in The value returned by and should be re-written as:
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:
where
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 it points to.
#include "fldtbl.h"
FBFR *fbfr;
FLDLEN len;
char* Ffind, *value;
. . .
if((value=Ffind(fbfr,ZIP,0, &len)) == NULL)
F_error("pgm_name");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 value modification should only be done by the functions Fadd
or Fchg
.
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 will cause a system error, as 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;if((l1==(long *)Ffind(fbfr, ZIP, 0, &length)) == NULL)
F_error("pgm_name");
else
memcpy(&l2,l1,sizeof(long)); Ffindlast
char *
Ffindlast(FBFR *fbfr
, FLDID fieldid
, FLDOCC *oc
, FLDLEN *len
)
fbfr
is a pointer to a fielded buffer
oc
is a pointer to the occurrence number of the last field occurrence found
In the declaration above the return value to The value returned by where
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 it points to.
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 for occurrence on calling the function, the occurrence number will not be returned.
Ffindlast
is valid only as long as the buffer remains unchanged.
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
;)
fbfr
is a pointer to a fielded buffer
For example,
would set Regular expressions are supported for string fields. For example,
would set
Note:
To enable pattern matching on strings, the fourth argument to For upward compatibility, a circumflex (^) and dollar sign ($) are implied to surround the regular expression; thus, the above example is actually interpreted as "^(J.*)$". This means that the regular expression must match the entire string value in the field.
where
#include "fldtbl.h"
FBFR *fbfr;
FLDOCC oc;
long zipvalue;
. . .
zipvalue = 123456;
if((oc=Ffindocc(fbfr,ZIP,&zipvalue, 0)) < 0)
F_error("pgm_name");oc
to the occurrence for the specified zip code.
#include "fldtbl.h"
FBFR *fbfr;
FLDOCC oc;
char *name;
. . .
name = "J.*"
if ((oc = Ffindocc(fbfr, NAME, name, 1)) < 0)
F_error("pgm_name");oc
to the occurrence of NAME that starts with "J".
Ffindocc
must be nonzero. If zero, simple string compare is performed. If the field value is not found, -1
is returned.
Fget
Fget
should be used 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)
fbfr
is a pointer to a fielded buffer
The caller provides gets the zip code assuming it is stored as a character array or string. If it is stored as a long, then it would be retrieved by:
Like where
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,
FLDLEN len;
char value[100];
. . .
len=sizeof(value);
if(Fget(fbfr, ZIP, 0, value, &len) < 0)
F_error("pgm_name");FLDLEN len;
long value;
. . .
len = sizeof(value);
if(Fget(fbfr, ZIP, 0, value, &len) < 0)
F_error("pgm_name"); Fgetalloc
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
)
fbfr
is a pointer to a fielded buffer
In the declaration above the return value to Fgetalloc is shown as a character pointer data type ( On success, The last parameter to It is the responsibility of the caller to where
char*
in C). The actual type of the pointer returned is the same as the type of the value it points to.
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 (Ferror
is set to FMALLOC
).
Fgetalloc
specifies an extra amount of space to be acquired if, for instance, the gotten value is to be expanded before re-insertion into the fielded buffer. On success, the length of the allocated buffer is returned in extralen
. For example:
FLDLEN extralen;
FBFR *fieldbfr
char *Fgetalloc;
. . .
extralen = 0;
if (fieldbfr = (FBFR *)Fgetalloc(fbfr, ZIP, 0, &extralen) == NULL)
F_error("pgm_name");free
space acquired by Fgetalloc
.
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
)
fbfr
is a pointer to a fielded buffer
oc
is a pointer to the occurrence number of the last field occurrence
The caller provides where
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 will not be returned.
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
)
fbfr
is a pointer to a fielded buffer
fieldid
is a pointer to a field identifier
oc
is a pointer to the occurrence number
value
is a pointer of the same type as the value contained in the next field
A If the field value is NULL, then the If no more fields are found, If the The following example reads all field occurrences in the buffer:
where
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 if value
has enough space allocated to contain the field value (Ferror
is set to FNOSPACE
if it does not); and, the length of the value is returned in the len
parameter. Note that 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
.
value
and length
parameters are not changed.
Fnext
returns 0
(end of buffer) and fieldid
, occurrence
, and value
are left unchanged.
value
parameter is not NULL, the length
parameter is also assumed to be non-NULL.
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 */
} Fnum
Fnum
returns the number of fields contained in the specified buffer, or -1
on error:
FLDOCC
Fnum(FBFR *fbfr
)
fbfr is a
pointer to a fielded buffer
For example:
would print the number of fields in the specified buffer.
where
if((cnt=Fnum(fbfr)) < 0)
F_error("pgm_name");
else
fprintf(stdout,"%d fields in buffer\n",cnt); Foccur
Foccur
returns the number of occurrences for the specified field in the buffer:
FLDOCC
Foccur(FBFR *fbfr
, FLDID fieldid
)
fbfr
is a pointer to a fielded buffer
Zero is returned if the field does not occur in the buffer and would print the number of occurrences of the field where
-1
is returned on error. For example:
FLDOCC cnt;
. . .
if((cnt=Foccur(fbfr,ZIP)) < 0)
F_error("pgm_name");
else
fprintf(stdout,"Field ZIP occurs %d times in buffer\n",cnt);ZIP
in the specified buffer.
Fpres
Fpres
returns true (1) if the specified field occurrence exists and false (0) otherwise:
int
Fpres(FBFR *fbfr
, FLDID fieldid
, FLDOCC oc
)
fbfr
is a pointer to a fielded buffer
For example:
would return true if the field where in both functions
Fpres(fbfr,ZIP,0)
ZIP
exists in the fielded buffer pointed to by fbfr
.
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 a pointer to the value.
char
* Fvals(FBFR *
fbfr
,FLDID
fieldid
,FLDOCC
oc)
char*
Fvall(FBFR *
fbfr
,FLDID
fieldid
,FLDOCC
oc)
fbfr
is a pointer to a fielded buffer
For For 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, 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 (i.e., no conversion is done).
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 (i.e., no conversion is done).
Buffer Update Functions
dest
,
src,
and fieldid
, where
dest
is a pointer to a destination fielded buffer
src
is a pointer to a source fielded buffer
fieldid
is a field identifier or an array of field identifiers
Occurrences in the destination buffer are maintained (i.e., 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).
In the following example:
if This operation will fail if there is not enough space to contain the new fields ( For fields that match on fieldid/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 fieldid/occurrence in the source buffer are deleted. Fields in the source buffer that have no corresponding fieldid/occurrence in the destination buffer are not added to the destination buffer. Thus,
Using the input buffers in the previous example will result 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 ( Note that fields that exist in the source buffer that have no corresponding fieldid/occurrence in the destination buffer are not added to the destination buffer. For example:
Using the input buffers from the previous example, These fields are specified in an array of field identifiers passed to the function. The update is performed directly in the fielded buffer. For example:
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 ( 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,
will place the results of the projection in the destination buffer. The entries in the array of field identifiers may be re-arranged; the field identifier array is sorted if they are not in numeric order.
For fields that match on fieldid/occurrence, the field value is updated in the destination buffer with the value in the source buffer (like If the This function transfers data from a fielded buffer to a C structure using a specified view description.
where
Fconcat
Fconcat
adds fields from the source buffer to the fields that already exist in the destination buffer.
int
Fconcat(FBFR *dest
, FBFR *src
)FBFR *src, *dest;
. . .
if(Fconcat(dest,src) < 0)
F_error("pgm_name");dest
has fields A, B, and two occurrences of C, and src
has fields A, C, and D, the resultant dest
will have 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.
FNOSPACE
); in this case, the destination buffer remains unchanged.
Fjoin
Fjoin
is used to join two fielded buffers based on matching fieldid/occurrence.
int
Fjoin(FBFR *dest
, FBFR *src
)if(Fjoin(dest,src) < 0)
F_error("pgm_name");FNOSPACE
); in this case, the destination buffer will have been modified. However, if this happens, the destination buffer may be re-allocated using Frealloc
and the Fjoin
function repeated (even if the destination buffer has been partially updated, repeating the function will give the correct results).
Fojoin
Fojoin
is similar to Fjoin
, but it does not delete fields from the destination buffer that have no corresponding fieldid/occurrence in the source buffer.
int
Fojoin(FBFR *dest
, FBFR *src
)if(Fojoin(dest,src) < 0)
F_error("pgm_name");dest
will contain 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 re-issued again after allocating more space to complete the operation.
Fproj
Fproj
is used to update a buffer in place so that only the desired fields are kept (in other words, the result is a projection on specified fields).
int
Fproj(FBFR *fbfr
, FLDID *fieldid
)#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");BADFLDID
).
Fprojcpy
Fprojcpy
is similar to Fproj
but the projection is done into a destination buffer.
int
Fprojcpy(FBFR *dest
, FBFR *src
, FLDID *fieldid
)if(Fprojcpy(dest, src, fieldid) < 0)
F_error("pgm_name"); Fupdate
Fupdate
updates the destination buffer with the field values in the source buffer.
int
Fupdate(FBFR *dest
, FBFR *src
)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
). For example:
if(Fupdate(dest,src) < 0)
F_error("pgm_name");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 will contain: 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.
VIEWS Functions
Fvftos
int
Fvftos(FBFR *fbfr
, char *cstruct
, char *view
)
fbfr
is a pointer to a fielded buffer
If the named view is not found, When transferring data from a fielded buffer to a C structure, the following rules apply:
Fvftos
returns -1, and Ferror
is set to FBADVIEW
.
For example,
would put "string1" into View This function transfers data from a C structure to a fielded buffer using a specified view description.
where
#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");
. . .cust.action[0]
and "abc" into cust.bug[0]
. All other members in the cust
structure should contain null values.
custdb
is defined in "VIEWS Examples" in Chapter 6.
Fvstof
int
Fvstof(FBFR *fbfr
, char *cstruct
, int mode
, char *view
)
fbfr
is a pointer to a fielded buffer
cstruct
is a pointer to a structure
mode
is one of the following: FUPDATE
, FJOIN
, FOJOIN
, FCONCAT
The transfer process obeys the rules listed under the FML function corresponding to the If the named view is not found,
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.
where
mode
parameter (Fupdate, Fjoin, Fojoin
, and Fconcat
, described in this chapter).
Fvstof
returns -1
, and Ferror
is set to FBADVIEW
.
Fvnull
Fvnull
is used to determine if an occurrence in a C structure contains the null value for that field.
int
Fvnull(char *cstruct
, char *cname
, FLDOCC oc
, char *view
)
cstruct
is a pointer to a structure
cname
is a pointer to the name of a structure member
This function initializes all elements in a C structure to their appropriate null value.
where
Fvnull
returns:
1 if an occurrence is null
0 if an occurrence is not null
-1 if an error occurred Fvsinit
int
Fvsinit(char *cstruct
, char *view
)
cstruct
is a pointer to a structure
This function allows users to change flag options at run time.
where
Fvopt
int
Fvopt(char *cname,
int option,
char *view
)
cname
is the name of a structure member
Possible values for the option
parameter are:
F_FTOS
F_STOF
F_BOTH
F_OFF
N
option in view descriptions.
Note that changes to view descriptions are not permanent. They are guaranteed only until another view description is accessed.
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
)
where
cstruct
is a pointer to a structure
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 The where
Conversion Functions
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 they have a "C" prefix.
CFadd
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
)
fbfr
is a pointer to a fielded buffer
fieldid
is the field identifier of the field to be added
value
is a pointer to the value to be added
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 If the puts the same value into the fielded buffer, but does so by presenting it as a long, instead of as a string. Note that the value must first be put into a variable, since C does not permit the construct &12345L. CFadd returns The function where
FLD_CARRAY
(character array), the length argument should be set to the length of the array. For example,
if(CFadd(fbfr,ZIP,"12345",(FLDLEN)0,FLD_STRING) < 0)
F_error("pgm_name");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 fragment:
long zipval;
. . .
zipval = 12345;
if(CFadd(fbfr,ZIP,&zipval,(FLDLEN)0,FLD_LONG) < 0)
F_error("pgm_name");1
on success, and -1
on error, in which case Ferror
is set appropriately.
CFchg
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
)
fbfr
is a pointer to a fielded buffer
fieldid
is the field identifier of the field to be changed
oc
is the occurrence number of the field to be changed
value
is a pointer to the value to be added
For example,
would change the first occurrence (occurrence 0) of field 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.
where
FLDOCC occurrence;
long zipval;
. . .
zipval = 12345;
occurrence = 0;
if(CFchg(fbfr,ZIP,occurrence,&zipval,(FLDLEN)0,FLD_LONG) < 0)
F_error("pgm_name");ZIP
to the specified value, doing any needed conversion.
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
)
fbfr
is a pointer to a fielded buffer
fieldid
is the field identifier of the field to be retrieved
oc
is the occurrence number of the field
buf
is a pointer to the post-conversion buffer
Using the previous example,
would get the value that was just stored in the buffer, no matter what format, and convert it back to a long integer. If the length pointer is NULL, then the length of the value retrieved and converted is not returned.
where
FLDLEN len;
. . .
len=sizeof(zipval);
if(CFget(fbfr,ZIP,occurrence,&zipval,&len,FLD_LONG) < 0)
F_error("pgm_name"); CFgetalloc
CFgetalloc
is like Fgetalloc
; you are responsible for freeing the malloc
'd space for the returned (converted) value with free
:
char *
CFgetalloc(FBFR *fbfr
, FLDID fieldid
, FLDOCC oc
, int type
, FLDLEN *extralen
)
fbfr
is a pointer to a fielded buffer
fieldid
is the field identifier of the field to be converted
oc
is the occurrence number of the field
In the declaration above the return value to The previously stored value could be retrieved into space allocated automatically for you by the following code:
The value where
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 it points to.
char *value;
FLDLEN extra;
. . .
extra = 25;
if((value=CFgetalloc(fbfr,ZIP,0,FLD_LONG,&extra)) == NULL)
F_error("pgm_name");extra
in the function call indicates that the function should not only allocate enough space for the retrieved value but an additional 25 bytes and the total amount of space allocated will be returned in this variable.
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
)
fbfr
is a pointer to a fielded buffer
fieldid
is the field identifier of the field to be retrieved
oc
is the occurrence number of the field
In the declaration above the return value to Like would return a pointer to a long containing the value of the first occurrence of the ZIP field. If the length pointer is NULL, then the length of the value found is not returned. Unlike
Note:
The duration of the validity of the pointer returned by where
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 it points to.
Ffind
, this pointer should be considered read only. For example:
char *CFfind;
FLDLEN len;
long *value;
. . .
if((value=(long *)CFfind(fbfr,ZIP,occurrence,&len,FLD_LONG))== NULL)
F_error("pgm_name");Ffind
, the value returned is guaranteed to be properly aligned for the corresponding user-specified type.
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.
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 (it is converted to the type of the field identifier).
FLDOCC
CFfindocc(FBFR *fbfr
, FLDID fieldid
, char *value
, FLDLEN len
, int type
)
fbfr
is a pointer to a fielded buffer
fieldid
is the field identifier of the field to be retrieved
value
is a pointer to the unconverted matching value
For example,
would convert the string to the type of
Note:
Since A set of functions ( See Section 3fml of the BEA TUXEDO Reference Manual for descriptions of these functions.
The functions where
#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");fieldid
ZIP
(possibly a long) and set oc
to the occurrence for the specified zip code. If the field value is not found, -1
is returned.
CFfindocc
converts the user-specified value to the native field type before examining the field values, regular expressions will only work when the user-specified type and the native field type are both FLD_STRING
. Thus, CFfindocc
has no utility with regular expressions.
Converting Strings
Fadds
(3fml), Fchgs
(3fml), Fgets
(3fml), Fgetsa
(3fml) and Ffinds
(3fml) and their FML32 counterparts) has been provided to handle the case of conversion to/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
.
Ftypcvt
CFadd
, CFchg
, CFget
, CFgetalloc
, and CFfind
use the function Ftypcvt
to perform the appropriate data conversion. 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
)
tolen
is a pointer to the length of the converted value
totype
is the type to which to convert
fromval
is a pointer to the value from which to convert
fromtype
is the type from which to convert
fromlen
is the length of the from value if the from type is FLD_CARRAY
The user may call A description of conversion rules is now presented. In this description, 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. As an example of its usage, the function CFchg
is presented:
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);
} Ftypcvt
directly to do field value conversion without adding or modifying a fielded buffer.
Conversion Rules
oldval
represents a pointer to the data item being converted, and newval
a pointer to the post-conversion value:
*newval
is identical to *oldval
.
*((float *)newval) = *((short *) oldval)
sprintf
is used. For example, converting a short to a string is done by:
sprintf(newval,"%d",*((short *)oldval))
atof
, atol
) is used, with the result assigned to a typecasted receiving location, for example:
*((float *)newval) = atof(oldval)
char
to any numeric type, or from a numeric type to a char
, the char is considered to be a "shorter short." For example,
is the method used to convert a is used to convert a short to a *((float *)newval) = *((char *)oldval)
char
to a float. Similarly,
*((char *)newval) = *((short *)oldval)
char
.
char
is converted to a string by appending a NULL character. In this regard, a char
is not a "shorter short." If it were, assignment would be done by converting it to a short, and then converting the short to a string via sprintf
. In the same sense, a string is converted to a char
by assigning the first character of the string to the character.
carray
is converted to a string by appending the NULL byte to the carray
. In this sense, a carray
could be used to store a string, less the overhead of the trailing NULL (note that this does not always save space, since fields are aligned on short boundaries within a fielded buffer). A string is converted to a carray
by removing its terminating NULL byte.
Note that a carray
of length 1 and a char
have the following differences:
char
has only the overhead of its associated fieldid
, while a carray
contains a length code, in addition to the associated fieldid
.
dec_t
type, the associated conversion function as described in decimal
(3) is used (_gp_deccvasc
, _gp_deccvdbl
, _gp_deccvflt
, _gp_deccvint
, _gp_deccvlong
, _gp_dectoasc
, _gp_dectodbl
, _gp_dectoflt
, _gp_dectoint
, and _gp_dectolong
).
Table 5-2 summarizes the conversion rules presented in this section.
When a fielded buffer is initialized by 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.
This function returns the amount of space used by the index of a buffer:
where
Indexing Functions
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.
Fidxused
long
Fidxused(FBFR *fbfr
)
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 would be saved by deleting the index.
The function where
Findex
Findex
may be used at any time to index an unindexed fielded buffer:
int
Findex(FBFR *fbfr
. FLDOCC intvl
)
fbfr
is a pointer to a fielded buffer
The second argument to Note that more space may be made available in an existing buffer for user data by increasing the indexing interval, and re-indexing 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 will attempt to drop the entire index if they run out of space before returning a "no space" error.
This function can be used instead of where
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.
Frstrindex
Findex
in cases where the fielded buffer has not been altered since its index was removed:
int
Frstrindex(FBFR *fbfr
, FLDOCC numidx
)
fbfr
is a pointer to a fielded buffer
where
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
)
fbfr
is a pointer to a fielded buffer
To transmit a fielded buffer without its index, something similar to the following should be done:
Example
save = Funindex(fbfr);
num_to_send = Fused(fbfr);
transmit(fbfr,num_to_send);
On the receiving side, the index could be regenerated with 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
; this 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.
The functions described in this section provide for input and output of fielded buffers to standard I/O or to file streams.
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 or from which the 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
, like this:
if (Fwrite(fbfr, iop) < 0)
F_error("pgm_name");
A buffer written with Fwrite
may be read with Fread
, as in:
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 (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
.
A checksum may be calculated for verifying I/O:
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.
The function Fprint
prints a fielded buffer on the standard output in ASCII format:
Fprint(FBFR *fbfr)
where
fbfr
is a pointer to a fielded buffer
where
Ffprint
is similar to Fprint
, except the text is printed to a specified output stream:
Ffprint(FBFR *
fbfr
, FILE *iop
)
fbfr
is a pointer to a fielded buffer
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.
Fextread
Fextread
may be used to construct a fielded buffer from its printed format, i.e. 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 Table 5-4.
flag | indicates |
---|---|
+ |
field should be changed in the buffer |
- |
field should be deleted from the buffer |
= |
one field should be assigned to another |
# |
comment line - ignored |
If no flag is given, the default action is to Field values may be extended across lines by having the overflow lines begin with a tab (the tab is discarded). A single blank line signals end of buffer; successive blank lines yield a null buffer.
If an error has occurred, The functions in this section deal with the evaluation of boolean expressions where the "variables" of the expression are the values of fields in a fielded buffer or a VIEW. Functions described in this section allow you to:
Fadd
the field to the buffer.
-1
is returned, and Ferror
is set accordingly. If end of file is reached before a blank line, Ferror
is set to FSYNTAX
.
Boolean Expressions of Fielded Buffers
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.
This section describes, in detail, the expressions accepted by the boolean compilation function and how the expression is evaluated. Table 5-5 shows the Backus-Naur Form definitions of the accepted boolean expressions.
Standard C language operators not supported include the shift operators (<< and >>), the bitwise "or" and "and" operators ( Boolean Expressions
||
and &&), the conditional operator (?), the prefix and postfix incrementation and decrementation operators (++ and --), the address and indirection operators (& and *), the assignment operator (=), and the comma operator (,). The following sections describe boolean expressions in greater detail.
The only variables allowed in the 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 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 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. NOTE THAT THIS IS NOT AS IT IS IN C where a hexadecimal escape sequence 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.
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 To evaluate a boolean expression, the following conversions are performed by the boolean compiler:
Field Names and Types
FLDTBLDIR
and FIELDTBLS
environment variables are set, as described in Chapter 3, "Setup," before using the boolean compilation function. The field types used in booleans are those allowed for FML fields; namely, 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.
VIEWDIR
and VIEWFILES
environment variables are set, as described in Chapter 3, "Setup," before using the boolean compilation function. The field types used in booleans are those allowed for FML VIEWS; namely, 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
Constants
dec_t
type are not supported).
Conversion
Boolean expressions are built from primary expressions, which can be any of the following:
Primary Expressions
field name
-a field name
field name[constant
-a field name and a constant subscript
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 whose 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.
Table 5-6 lists the precedence of expression operators, with the operators having the highest precedence at the top of the list.
Expression Operators
Within each operator type, the operators have the same precedence. The following sections discuss each operator type in detail. As in C, you can override the precedence of operators by using parentheses.
The unary operators recognized are the unary plus operator (+), the unary minus operator (-), the one's complement operator (~), and the logical not operator (!). Expressions with unary operators group right-to-left:
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.
The multiplicative operators *, /, and % group left-to-right. The usual arithmetic conversions are performed.
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.
The additive operators + and - group left-to-right. The usual arithmetic conversions are performed.
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.
These operators group left-to-right.
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 These operators group left-to-right.
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.
The It returns the bitwise exclusive OR function of the operands. The result is always a long.
The && operator groups left-to-right. It returns 1 if both its operands are non-zero, 0 otherwise. 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.
The It returns 1 if either of its operands is non-zero, and 0 otherwise. The The following field table defines the fields used for the sample boolean expressions:
Recall that boolean expressions always evaluate to either true or false. The following example:
would be true if field occurrence 2 of This expression would be true if The following sections describe the various functions that take boolean expressions as arguments.
where where Space is allocated using would compile a boolean expression that checks whether the 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.
The evaluation tree produced by where
Unary Operators
+ expression
- expression
~ expression
! expression Multiplicative Operators
expression * expression
expression / expression
expression % expression Additive Operators
expression + expression
expression - expression Equality and Match Operators
expression == expression
expression != expression
expression %% expression
expression !% expressionrecomp
(3c) manual page.
Relational Operators
expression < expression
expression > expression
expression <= expression
expression >= expression Exclusive OR Operator
^
operator groups left-to-right.
expression ^ expression
Logical AND Operator
expression && expression
Logical OR Operator
||
operator groups left-to-right.
expression || expression
||
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
EMPID 200 carray
SEX 201 char
AGE 202 short
DEPT 203 long
SALARY 204 float
NAME 205 string"EMPID[2] %% '123.*' && AGE < 32"
EMPID
exists and begins with the characters "123" and the age field (occurrence 0) appears and is less than 32. This example uses a constant integer as a subscript to EMPID
. The ? subscript is used in the following example:
"PETS[?] == 'dog'"
PETS
exists and any occurrence of it contained the characters "dog".
Boolean Functions
Fboolco and Fvboolco
Fboolco
compiles a boolean expression for FML and returns a pointer to an evaluation tree:
char *
Fboolco(char *expression)*expression
is a pointer to an expression to be compiled.
Fvboolco
compiles a boolean expression for a VIEW and returns a pointer to an evaluation tree:
char *
Fvboolco(char *expression, char *viewname)*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.
malloc
(3) to hold the evaluation tree. For example,
#include "<stdio.h>"
#include "fml.h"
extern char *Fboolco;
char *tree;
. . .
if((tree=Fboolco("FIRSTNAME %% 'J.*n' && SEX == 'M'")) == NULL)
F_error("pgm_name");FIRSTNAME
field is in the buffer, begins with `J' and ends with `n' (e.g., John, Joan, etc.), and whether the SEX
field is equal to `M
'.
Fboolco
is used by the other boolean functions listed below; this avoids having to constantly re-compile the expression.
free
(3) should be used 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 no longer needed may cause a program to run out of data space.
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)
*tree
is a pointer to a Boolean tree previously compiled by Fboolco
where
Fvboolpr
prints a compiled expression to the specified file stream.
void
Fvboolpr(char *tree, FILE *iop, char *viewname)
*tree
is a pointer to a Boolean tree previously compiled by Fvboolco
This function is useful for debugging.
Executing Fboolpr on the expression compiled above would yield
These functions evaluate a fielded buffer against a boolean expression.
where
(((FIRSTNAME[0]) %% ('J.*n')) && ((SEX[0]) == ('M')))
Fboolev and Ffloatev, Fvboolev and Fvfloatev
int Fboolev(FBFR *
fbfr
,char *
tree
)
double Ffloatev(FBFR *fbfr
,char *
tree
)
fbfr
is the fielded buffer referenced by an evaluation tree produced by Fboolco
tree
is a pointer to an evaluation tree that references the fielded buffer pointed to by fbfr
The VIEW equivalents are as follows.
would print "Buffer selected".
would print 6.6. If A VIEW can be converted to and from a target record format. The default target format is IBM System/370 COBOL records.
The three functions that provide target conversion are as follows.
The To convert from an FML buffer to a target record, first call The default target is IBM/370 COBOL records. The default data conversion is done as shown in Table 5-7.
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:
#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
or Ffloatev32
is similar to Fboolev,
but returns the value of the expression as a double. For example,
#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));
}
}Fboolev
were used in place of Ffloatev
in the above example, a 1 would be printed.
VIEW Conversion to and from Target Format
Fvstot, Fvttos and Fcodeset
long
Fvstot(char *cstruct, char *trecord, long treclen, char *viewname)long
Fvttos(char *cstruct, char *trecord, char *viewname)int
Fcodeset(char *translation_table)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.
Fvftos
to convert the FML buffer to a C structure, and call Fvstot
to convert to a target record. To convert from a target record to an FML buffer, first call Fvttos
to convert to a C structure and then call Fvstof
to convert the structure to an FML buffer.
No filler bytes are provided between fields in the 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 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/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 Decimal values may be converted to and from other data types (e.g., int, long, string, double, and float) using the functions described in See the An alternate character translation table can be used at run-time by calling 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 that the decimal occupies. The number to the right is the number of digits to the right of the decimal point. The formula for conversion is:
dec_t(m, n) <=> S9(2*m-(n+1))V9(n)COMP-3
decimal
(3c).
Fvstof
(3fml) reference page for the default character conversion of ASCII to/from EBCDIC.
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.