xddgen

xddgen

xddgen is used to generate XDD files directly from COBOL source code. Because xddgen must analyze the program to create the XDD, it needs a full COBOL program as input.

Usage

xddgen [options] file...

Options:

  • --help Display this message
  • --version, -V Display compiler version
  • -std=<dialect> Compile using a config file (config/<dialect>.conf) for a specific dialect (see xddgen Configuration File):

acu ACUCOBOL-GT

acu-Ds ACUCOBOL-GT using the -Ds switch

cobol2002 COBOL 2002

cobol85 COBOL 85

ibm IBM Compatible

mvs MVS Compatible

bs2000 BS2000 Compatible

mf Micro Focus Compatible

default When not specified

  • When -std is not specified, config/default.conf is used.
  • -free Use free source format
  • -fixed Use fixed source format (default)
  • -o <directory> Place the output into <directory>
  • -I <directory> Add <directory> to copy/include search path
  • -conf=<file> User defined dialect configuration. See -std=
  • --list-reserved Display reserved words
  • --list-intrinsics Display intrinsic functions
  • --list-mnemonics Display mnemonic names
  • -save-temps(=<dir>) Save intermediate files (default current directory)

Some elements of COBOL FD statements require special consideration when generating the XDD. In particular:

Redefines

Fields contained in a redefining item occupy the same positions as the fields being redefined.

The XDD generator needs to select just one of the field definitions; by default it takes the fields in the item being redefined.

Multiple record definition

The same rule applies to multiple record definitions which are redefinitions of the entire record area, so again this leads to multiple definitions for the same data area. In this case the XDD generator picks the first definition.

Group items

By default never included in an XDD as they result in multiple names for the same data items.

FILLER Data Items

In a COBOL FD, FILLER data items are placeholders however they take space on the record area. FILLER items are not uniquely named, so when generating the XDD they get renamed to have a unique name and by default are marked as “hidden fields”.

Occurs

An OCCURS clause requires special handling because there must be a unique name to each database column. The XDD generator accomplishes this by expanding the OCCURS items and appending sequential index numbers to the items named in the OCCURS.

Primary Key

The xddgen utility (as well as ctutil -xfd2xdd) mark the first index as the primary in the XDD definition so that this key becomes the primary key for SQL.

 

XDD Directives

Directives are comments that can be placed into an FD in your COBOL source code. You can add directives to your COBOL source to override default mapping behaviors or map a field to a different name. Directives apply to the next field and up to 4 directives per field can be specified.

For compatibility with existing ACUCOBOL-GT source code, xddgen accepts the following $xfd and *>>XFD directives:

DATE, HIDDEN, NAME, USE GROUP, WHEN, ALPHA, BINARY, COMMENT

Syntax

*>>directive_name parameters

Note: For fixed syntax, the directive must start at column 8.

Supported Directives

XDD ALPHA

This option forces the resulting field to be ALPHANUMERIC. An index can then be created via SQL that provides expected range sorting on the value.

Syntax

*>>XDD ALPHA

XDD HIDDEN

Use the HIDDEN directive to hide the subsequent field in the SQL structure.

Syntax

*>>XDD HIDDEN 

XDD NAME

Use the NAME directive to assign a database field name to the subsequent field.

Syntax

*>>XDD NAME = field

XDD USE GROUP

Use the USE GROUP directive to enter a group item into the database as a single field, instead of using the elements contained in the group. It implies that the resulting field is alphanumeric.

Syntax

*>>XDD USE GROUP

XDD DATE

Use the DATE directive to expose the subsequent field in SQL as a time/date/timestamp field in SQL. The date_format is mandatory and represents the description of the desired date format for the XDD file.

Syntax

*>>XDD DATE = date_format

where

  • date_format - A description of the desired date format. The date format is composed of characters from the following list:

M - Month (01–12)
Y - Year (two or four digits)
D - Day of month (01–31)
J - Julian day (00000000–99999999)
E - Day of year (001–366)
H - Hour (00–23)
N - Minute
S - Second

XDD WHEN

Use the WHEN directive when you want to include multiple record definitions or REDEFINES in the XDD. The WHEN directive is used to force certain columns of data to be available that wouldn't be available otherwise. Use the WHEN directive if you want a user to be able to access all the data in the COBOL file in a way that is understandable.

WHEN declares that the field (or subordinate fields, if it is a group item) immediately following the directive must appear as a column (or columns) in the indexed file database table when the condition is satisfied.

Syntax

*>>XDD WHEN field operator value

or

*>>XDD WHEN field operator value TABLENAME = tablename

where

  • field - Specifies the name of a data item that corresponds to a field.

operator - Specifies the operator to use for comparison between the field value and the literal value.

Supported operators:

= equal

!= not equal

> greater than

< less than

>= greater or equal than

<= less or equal than

  • value - An alphanumeric literal specifying the value to compare with or OTHER which requires the = (equal) operator and matches when no other condition matches.
  • tablename - The name of the table exposing the fields.

The WHEN directive supports complex expressions containing multiple AND and OR operations and parentheses to group sub-expressions for proper order of evaluation.

The maximum length of the expression is 1024 characters (no need to split the line). For example:

*>>XDD WHEN (fld1 = "abac" or fld1 = "default") and (fld2 < 15 or fld2 > 123) and fld4 != "12"

If you have need for an existing $XFD WHEN directive in place and would like a different WHEN directive in effect (for example, complex directives were not supported with old ACUCOBOL-GT versions) a *>>WHEN directive immediately following a $XFD WHEN directive overrides it. This is a useful method to have an original $XFD WHEN in place for other file systems and *>>WHEN directives for c-tree specific usage.

Multiple schemas can be defined with the same definition but different records and mapping to different SQL tables by specifying multiple WHEN directives having different tablename settings on the same field.

For example, your application may use a single table containing customers and suppliers with a TYPE field indicating if an entry is for a customer or for a supplier. It may be desirable to map this table into two SQL tables; one for suppliers and one for customers. In such a case it is possible to have two WHEN directives on the same level 01 field (in this example) with the proper condition and two different table names.

Nested WHEN directives are not explicitly supported.

XDD WHENFULL - redefined key fields

Use the WHENFULL directive in the FD or COBOL source when you want to include multiple record definitions or REDEFINES that also redefine the indexed fields. This directive is very similar to the WHEN directive.

The WHENFULL directive can only be used before an 01 level definition and the 01 level entry must contain the whole record definition (including indexed fields). WHENFULL is applicable only for 01 level definitions that redefine the entire record.

It is possible to nest WHEN directives within a WHENFULL directive.

XDD FILLER

This directive forces the following field to be considered to be a FILLER.

Syntax

*>>XDD FILLER 

 

Handling DATE Fields in Your XFD

Micro Focus and ACUCOBOL support DATE directives in the XFD. Using the DATE directive, a COBOL field can be mapped to the desired time and date format. This directive applies to a numeric XFD field. The syntax is as follows:

*>>XDD DATE=date-format-string

If the date-format-string is not supplied, 6-digit fields are interpreted as YYMMDD and 8-digit fields are interpreted as YYYYMMDD.

If a different date format is required, the date-format-string can be used to specify the format using these characters:

  • M - Month (01–12)
  • Y - Year (two or four digits)
  • D - Day of month (01–31)
  • J - Julian day (00000000–99999999)
  • E - Day of year (001–366)
  • H - Hour (00–23)
  • N - Minute
  • S - Second
  • T - Hundredths of a second

All other characters are invalid and will cause an error.

Example 1

This example creates "date-hired" column with type DATE based on an 8-digit field with the default format of YYYYMMDD:

*>>XDD date
      03  date-hired    pic 9(8).
      03  pay-scale     pic x(3).

Example 2

This example shows a different way to produce a column named "date-hired" with type DATE based on an 8-digit field with a format of YYYYMMDD:

*>>XDD DATE
*>>XDD USE GROUP
      03  date-hired.
          05  yyyy      pic 9(4).
          05  mm        pic 9(2).
          05  dd        pic 9(2).

Example 3

This example produces a column named "date-sold" with type DATE. The date is based on a 7-digit field that contains the day of the year (e.g., February 1st is 032), followed by the four-digit year (e.g., 2018).

*>>XDD DATE=EEEYYYY
      03  date-sold      pic 9(7).
      03  sales-rep      pic x(30).

 

Syntax for WITH DUPLICATES on RECORD KEY

In most COBOL compilers it is possible to specify WITH DUPLICATES on the RECORD KEY, but xddgen did not allow this (it failed with a syntax error). The xddgen syntax has been expanded to support duplicates on the record key in addition to the support for duplicates on alternate keys. A record key that allows duplicates cannot be marked as primary key in SQL.

 

Suppress Dash or Replace with Underscore

A boolean xddgen configuration behavior allows suppressing the dash character ("-") when it is present instead of substituting it with an underscore ("_"). The default is no, which preserves the past behavior in which a dash is substituted with an underscore.

suppress-dash-in-field-names
  • no (default) - Dashes are substituted with underscores.
  • yes - Dashes are eliminated from the file name rather than being substituted.

Example:

You can create a new configuration file and set this feature as desired. When you run xddgen, the ‑std= switch can be used to point to the new configuration file:

  1. Copy the configuration file specified by the xddgen ‑std=<dialect> configuration switch. For example, if ‑std=mf, make a copy of the configuration file mf.conf found in the conf directory.
  2. Rename the configuration file copied in step 1.
  3. Add (or change) for setting for suppress-dash-in-field-names: yes
  4. Run xddgen -std=<new_name> replacing <new_name> with the new configuration file name assigned in step 2.

 

xddgen Configuration File

The -std=<dialect> parameter for xddgen determines which configuration file controls the conversion. The conf directory contains one configuration file for each value of <dialect> (e.g., for ACUCOBOL, specify ‑std=acu when running xddgen acu.conf is used). The file default.conf is used if ‑std= is not specified.

You can make customized copies of these files and give them new names. Use those names when running xddgen. For example, you could make a copy of acu.conf and call it myacu.conf. Use xddgen -std=myacu to use this file.

Configuration Options

  • comp-1-16bit-signed-binary - When set to yes, COMP-1 and COMP-2 are mapped as per the ACUCOBOL definition.

When using xddgen to create an XDD file for an FD containing a COMP‑1 field, the correct mapping depends on the COBOL compiler being used. It should be mapped into a Float for most compilers. However, the ACUCOBOL compiler defines COMP‑1 as a 16-bit signed integer, so it should be mapped to BinarySigned. To achieve this, use the following configuration property:

comp-1-16bit-signed-binary: yes 
  • sign-trailing-separate - The ACUCOBOL -Ds compiler switch causes numbers to have separate leading sign by default (when no COMP specification is in place). This option defaults to no (0). Setting it to yes invokes TRAILING SEPARATE. The configuration file named acu‑Ds.conf enables this flag (use ‑std=acu-Ds).
  • binary-size - Defines the allocated bytes according to PIC:
Value:         signed  unsigned  bytes
               ------  --------  -----
'2-4-8'        1 -  4                2
               5 -  9                4
              10 - 18                8
'1-2-4-8'      1 -  2                1
               3 -  4                2
               5 -  9                4
              10 - 18                8
'1--8'         1 -  2    1 -  2      1
               3 -  4    3 -  4      2
               5 -  6    5 -  7      3
               7 -  9    8 -  9      4
              10 - 11   10 - 12      5
              12 - 14   13 - 14      6
              15 - 16   15 - 16      7
              17 - 18   17 - 18      8
  • binary-byteorder - Determines the byte-order. Can be set to native (to use the byte-order of the original) or big-endian (to force big-endian byte order).
  • suppress-dash-in-field-names - When set to yes, dashes are eliminated from the file name rather than being substituted. The default, no, causes dashes to be substituted with underscores. See Suppress dash or replace with underscore.

Handling Names Larger Than 31 Characters

The xddgen utility is able to generate the XDD if a field name is larger than 31 characters to allow more flexibility in generating the XDD. Two configuration entries accommodate this situation:

  1. user-defined-names-len (defaults to 31) - Can be any number between 31 and 64. It determines the number of significant chars in fields and table names.
  2. check-redefinition (defaults to yes) - If yes, check for field names redefinitions that would cause having multiple SQL fields with the same name and if so, error out.

The behavior when names larger than user-defined-names-len is encountered has been changed so that, instead of generating an error, it produces a warning and truncates the name to the maximum allowed length.

More xddgen enhancements

Several enhancements have been made to the latest version of xddgen:

Generate an XDD for EXTERNAL files

Support was added xddgen to generate an XDD for files defined as EXTERNAL. By default, xddgen does not generate XDD files for external files, but it is now possible to change the xddgen configuration file follows to instruct xddgen to generate XDD files for EXTERNAL files:

# If yes, generates xdd file also for "external files"
# Value: 'yes', 'no'
consider-external-file: yes
 

Now when an external file is ignored, xddgen generates a warning message to inform about it.

Key based on a redefine

The xddgen utility used to return an error if a key was based on a redefine of a field or, in case of split keys, if one of the specified fields was a redefine. Now the logic has been changed to allow these conditions and produce a warning indicating the situation.

It is possible to change the behavior from the default of generating a warning to the old behavior of getting an error (or even to allow it without any warning) by changing the xddgen configuration entry:

# behaviour when a key is based on a redefine of a field.
# Value: 'ok', 'error', 'warning'
key-on-redefines: warning
 

Rationalized xddgen behavior on error

If an error occurs while generating an XDD, the XDD will not be generated (although other XDDs may be generated). The xddgen utility will always return a value different than 0 on the occurrence of an error. This implies it is sufficient to check the return code to see if something failed during xddgen execution.

 

Configuration Files Directory

The xddgen configuration files can be loaded from the config directory under the xddgen executable directory. This allows calling xddgen from any directory without worrying about copying the config sub-directory.

A number of xddgen behaviors are controlled by configuration files. The default configuration file, default.conf, can be modified using either the ‑std or the ‑conf command-line switches:

  • When ‑std=AAA is used, the configuration file name is AAA.conf.
  • When ‑conf is used, the configuration file name is the exact name passed in with no changes. If no path or a relative path is specified, it will be based on the current working directory.

When ‑conf is not used, the file is loaded from a directory using the following criteria:

  1. If the environment variable COB_CONFIG_DIR is specified, that is the only directory that will be considered.
    1. else
  2. The search for the configuration file will include the config directory under the current working directory (i.e. the directory where xddgen is launched).
  3. If #2 fails, the search for the configuration file will include the config directory under the xddgen invocation path (i.e., the directory from which xddgen was executed).

The above criteria are also used to locate "included" configuration files (one configuration file can include another and overwrite some of the values specified).

 

xddgen - New Configuration Option max-fixed-record-len

When RM/COBOL is configured to use Btrieve as the file handler, the creation of a fixed-length file with record size over 4082 actually creates a variable-length file with a minimum record length of 4082 and maximum record length of whatever is the record size. This can cause a problem when an XDD is generated and the file is SQLized or the XDD is used to re-create the file.

Because RM/COBOL does not have a way of generating a "schema" that can be translated into an XDD, xddgen is the only way to produce an XDD.

Given the FD and the SL with a record size greater than 4082, xddgen produces a XDD containing minRecLen equal to maxRecLen. When this XDD is used to sqlize the file created by RM/COBOL, the SQL callback fails because the definition is not correct (the file is variable with a fixed-length of 4082). When used to generate a file (ctutil -make), the RM/COBOL runtime fails with error 39.09 because the definition does not match.

xddgen has no way to know about this limit on the minRecLen unless instructed so. Therefore, a new configuration parameter has been added:

max-fixed-record-len

The default is 0, meaning no limit. When set to a value other than 0, it is used to limit the minRecLen value when generating the XDD.

To use this keyword, create your own xddgen configuration file with content similar to:

include "default.conf"
max-fixed-record-len: 4082

 

xddgen - New Record Size Checks and Warnings

When the FD does not explicitly define a record size (using COBOL-specific syntax), xddgen determines the minimum and maximum record length by looking at the minimum and maximum record size of the various records layouts (level 01).

When COBOL does not specify a record length, the record is always fixed-length, but the records layout may have different sizes and so the generated XDD have different minimum and maximum lengths, which then (depending on how these are set) fail the check against the physical file record length causing a 4110 error (CALLBACK_2).

The logic has been changed so that, if the record length is not specified, it considers the record as fixed-length and uses the first record definition length as the "base length." It then checks each record size against the specified or calculated record minimum and maximum lengths and prints a warning if its size is outside of the expected range.

The XDD will be generated using the minimum and the maximum record lengths found in the various record definitions (schemas) as it always was.

If the XDD is going to generate information with different minimum and maximum record lengths (thus implying a vlen file) but the COBOL source did not specify the record as variable length, a warning message is printed. It is recommended to modify the COBOL source to resolve these warnings.

It was also identified that the size of COMP-4 for default AcuCobol configuration was not correct. The "binary-size" has been updated to the proper setting of "2-4-8" in acu.conf and acu-Ds.conf.