The Relogix translation

Note: This is a translation exactly as produced by Relogix, with no human intervention to clean up the code after translation. Guided by the user, Relogix has automatically chosen the types of variables, detected the use of structures and pointers, created proper C function calls, and has placed the assembler comments in the translated source allowing for the re-arrangement of the code flow.

Note that MicroAPL currently offers Relogix/MF as a porting service. The output of the translator as shown here would be cleaned up by our engineers before delivery to the customer. Typical post-translation cleanup work includes removing EBCDIC and endian dependencies from the code, improving the choice of variable names and slight changes to improve code readability.



/************************************************************************
*                                                                       *
*       "Y2KDFMT.c" - Translated from file "Y2KDFMT.txt"                *
*                                                                       *
*-----------------------------------------------------------------------*
*                                                                       *
*       Relogix Code Translator Copyright (c) MicroAPL 1990-2017        *
*                   All Rights Reserved Worldwide                       *
*                                                                       *
*************************************************************************
*/

/*
**                                                                     *
**   yy   yy   222   kk   kk dddddd  fffffff m     mtttttttt           *
**   yy   yy  2   2  kk  kk  dd   dd ff      mm   mm   tt              *
**   yy   yy      2  kk kk   dd   dd ff      mmm mmm   tt              *
**    yy yy       2  kkkk    dd   dd fffff   mmmmmmm   tt              *
**     yyy     222   kkkk    dd   dd ff      mm m mm   tt              *
**     yy     2      kk kk   dd   dd ff      mm   mm   tt              *
**     yy     2      kk  kk  dd   dd ff      mm   mm   tt              *
**     yy     22222  kk   kk dddddd  ff      mm   mm   tt              *
**                                                                     *
** ******************************************************************* *
** ******************************************************************* *
**    this subroutine formats a given gregorian date (mmddyyyy) in     *
**    a large variety of formats                                       *
**                                                                     *
**    1.  valid input years for this routine are the years 1601        *
**        through 3399 a. d. (inclusive)                               *
**                                                                     *
**    2.  valid input month values for this routine are 01 through 12. *
**                                                                     *
**    3.  valid input day values for this routine are 01 through 31    *
**        with exceptions for the months listed:                       *
**             month          maximum day value                        *
**              04                    30                               *
**              06                    30                               *
**              09                    30                               *
**              11                    30                               *
**              02                    28                               *
**              02 during leap year   29                               *
**                                                                     *
**    4.  the date format must be mmddyyyy, where mm = the 2 digit     *
**        month value, dd = the 2 digit day value, and yyyy = the      *
**        4 digit year value.                                          *
**                                                                     *
**    5.  the major format code determines the overall output format   *
**        and the minor format code determines subtle variations of    *
**        the format:                                                  *
**          major                                  minor               *
**            1 = commercial (01051997)              1 = no insert     *
**            1 = commercial (01 05 1997)            2 = space         *
**            2 = european   (05/01/1997)            3 = slash         *
**            2 = european   (05-01-1997)            4 = hyphen        *
**            3 = f.i.p.s.   (yyyy.mm.dd)            5 = period        *
**          ---------------------------------------------------------  *
**            4 = text 1 (january 5, 1997)           1 = u.s.          *
**            4 = text 1 (5 january 1997)            2 = european      *
**            5 = text 2 (jan 5, 1997)               1 = u.s.          *
**            6 = text 3 (sunday, january 5, 1997)   1 = u.s.          *
**            7 = text 4 (sunday, 5 jan 1997)        2 = european      *
**            8 = text 5 (sun, january 5, 1997)      1 = u.s.          *
**            9 = text 6 (sun, 5 jan 1997)           2 = european      *
**                                                                     *
**    6.  six fields are passed as parameters to the routine:          *
**        1)  an 8 byte field containing the date (in zoned-           *
**            decimal format) to be formatted,                         *
**        2)  a 1 byte zoned-decimal major format code (see 5 above),  *
**        3)  a 1 byte zoned-decimal minor format code (see 5 above),  *
**        4)  a 1 byte zoned-decimal return code,                      *
**        5)  a 2 byte field which will contain the number of bytes    *
**            placed in the following field (in zoned decimal format), *
**        6)  an output field to receive the formatted date (note:     *
**            the size of this field depends upon the formatting       *
**            codes ... it is the caller's responsibility to pass a    *
**            field long enough to receive the requested format).      *
**        the routine will not alter the date or format code fields.   *
**                                                                     *
**        suggested calling syntax for alc callers:                    *
**                                                                     *
**                      call  y2kdfmt,(datein)                         *
**                         . . .                                       *
**             datein   ds    zl8'01051997'                            *
**             major    ds    cl1'1'                                   *
**             minor    ds    cl1'3'                                   *
**             rc       ds    zl1'0'                                   *
**             outsize  ds    zl2'00'                                  *
**             outdate  ds    cl29' '                                  *
**                                                                     *
**        suggested calling syntax for cobol callers:                  *
**                                                                     *
**             01  dfmt-parameters.                                    *
**                 02  datein  pic 9(8) value 01011997.                *
**                 02  major   pic 9(1) value 1.
**                 02  minor   pic 9(1) value 3.
**                 02  rc      pic 9(1) value 0.                       *
**                 02  outsize pic 9(2) value 0.                       *
**                 02  outdate pic x(29).                              *
**             call 'y2kdfmt' using dfmt-parameters.                   *
**                                                                     *
**    7.  the possible values for the return code field are:           *
**                                                                     *
**        0 indicates successful execution of the routine.             *
**                                                                     *
**        2 indicates invalid data was found in the date field.        *
**        invalid data are determined if the field's low order         *
**        byte's zone contains an invalid sign, (not one of            *
**        x'c', x'd' or x'f'), or if the preceding bytes' zones        *
**        are other than x'f', or if any byte's low order nibble       *
**        contains a value greater than x'9'.                          *
**                                                                     *
**        4 indicates the value of the year specified was not in       *
**        the range specified in 1 (above).                            *
**                                                                     *
**        6 indicates the value of the month specified was not in      *
**        the range specified in 2 (above).                            *
**                                                                     *
**        8 indicates the value of the day specified was not in        *
**        the range specified in 3 (above).                            *
**                                                                     *
**        3 indicates the value of the major format code specified     *
**        was not one of the acceptable values (see 5 above).          *
**                                                                     *
**        5 indicates the value of the minor format code specified     *
**        was not one of the acceptable values for the major format    *
**        code specified (see 5 above).                                *
**                                                                     *
**    8.  upon successful execution, the formatted date will be        *
**        placed in the 6th parameter field and the number of bytes    *
**        placed in the field will be placed in the 5th field.  if     *
**        the return code contains a non-zero value (unsuccessful      *
**        execution), the 6th field will not be modified by the        *
**        routine and the 5th field will contain zero.                 *
**                                                                     *
** ******************************************************************* *
** ******************************************************************* *
**         print nogen
*/


#include "rlx370.h"
#include "syscalls.h"
#include "y2kdemo.h"
#include "Y2KDFMT.h"
#include "Y2KDOWN.h"
#include "Y2KGTOA.h"

#define DO_DYNLEN            (sizeof(struct y2kdfmt_dynmem)) /* length of getmain'd area */

/* Prototypes for private routines translated to C */
static long mfmtsub (struct y2kdfmt_parms *parms_ptr);
static unsigned char * mdayn (unsigned char *output_address, struct y2kdfmt_dynmem *dynmem_ptr);
static unsigned char * mdaya (unsigned char *output_address, struct y2kdfmt_dynmem *dynmem_ptr);
static unsigned char * mmonthn (unsigned char *output_address, struct y2kdfmt_parms *parms_ptr, struct y2kdfmt_dynmem *dynmem_ptr);
static unsigned char * mmontha (unsigned char *output_address, struct y2kdfmt_parms *parms_ptr, struct y2kdfmt_dynmem *dynmem_ptr);
static void mday (unsigned char **ptr, struct y2kdfmt_parms *params);
static unsigned char * lday (long *size_day, struct y2kdfmt_dynmem *dynmem_ptr);
static unsigned char * lmonth (long *size_month, struct y2kdfmt_parms *parms_ptr, struct y2kdfmt_dynmem *dynmem_ptr);



/* Private file-scope variables */

/** ******************************************************************* *
* * **************************** constants **************************** *
* * ******************************************************************* *
* *
* *    day of week names, preceeded by length attribute
* */
static struct day_name dname [] = { 
    {   6,  { "MONDAY    " }  }, 
    {   7,  { "TUESDAY   " }  }, 
    {   9,  { "WEDNESDAY " }  }, 
    {   8,  { "THURSDAY  " }  }, 
    {   6,  { "FRIDAY    " }  }, 
    {   8,  { "SATURDAY  " }  }, 
    {   6,  { "SUNDAY    " }  }
};

/**    month names, preceeded by length attribute
* */
static struct month_name mname [] = { 
    {   7,  { "JANUARY   " }  }, 
    {   8,  { "FEBRUARY  " }  }, 
    {   5,  { "MARCH     " }  }, 
    {   5,  { "APRIL     " }  }, 
    {   3,  { "MAY       " }  }, 
    {   4,  { "JUNE      " }  }, 
    {   4,  { "JULY      " }  }, 
    {   6,  { "AUGUST    " }  }, 
    {   9,  { "SEPTEMBER " }  }, 
    {   7,  { "OCTOBER   " }  }, 
    {   8,  { "NOVEMBER  " }  }, 
    {   8,  { "DECEMBER  " }  }
};


/*
*************************************************************************
* y2kdfmt                                                               *
*************************************************************************
*
* Parameters:
*
*    struct y2kdfmt_parms *params                   [Originally in R1 param block at offset 0; In]
*
* Result:
*
*    int                                            [Originally in r15]
*/
int y2kdfmt (struct y2kdfmt_parms *params)
{
    struct y2kdfmt_dynmem *dynmem_ptr;           /* [Originally in r1] */
    long i;                                      /* [Originally in r2] */
    long j;                                      /* [Originally in r3] */
    unsigned char *output_address;               /* [Originally in r2] */
    unsigned char *ptr_poutdate;                 /* [Originally in r2] */

    getmain (DO_DYNLEN, GETMAIN_RU, (void **) &dynmem_ptr);
                                                 /* getmain dynamic workarea */

    /**    insert eyecatcher marks at begin/end of getmain'd area.
    * */
    memcpy (dynmem_ptr->topflag, "Y2KDFMT GETMAIN BEGINS->", sizeof(dynmem_ptr->topflag));
                                                 /* save a(memory)
                                                  * set a(my save area) */
    memcpy (dynmem_ptr->botflag, "<-Y2KDFMT GETMAIN ENDS", sizeof(dynmem_ptr->botflag));
    memset (&params->prc, '0', 3);               /* assume good return zero return size */

    /**    call y2kdown to verify date and return integral day number.
    * */
    _rlx_move_mem (dynmem_ptr->downparm.ddate, params->pdate, 8);
                                                 /* copy year to y2kdown parm */
    y2kdown ((struct y2kdown_parms *) &dynmem_ptr->downparm);
                                                 /* address of y2kdown parms
                                                  * store in dynamic area
                                                  * call routine */

    /**    see if date we received from caller passed edits in y2kdown.
    * *    this means we don't have to repeat the edit code here <g>!
    * */
    params->prc = dynmem_ptr->downparm.drc;      /* adopt received return code */

    /* was execution successful?
    *  if not, exit to caller */
    if (dynmem_ptr->downparm.drc != '0') {
        /**    restore registers, free storage, and return
        * */
        freemain (dynmem_ptr, DO_DYNLEN);        /* load address of getmained area
                                                  * load length of getmained area
                                                  * free getmained area */
        return 0;                                /* return to caller with rc=0 */
    }

    /**    test major format code for invalid value.
    * */
    i = '1';                                     /* lowest valid code */
    /* clear work register
    *  get major format code
    *  is format valid? */
    for (j = 9; j > 0; j--) {
        if ((long) params->pmajor == i)
            break;
        i++;                                     /* increment to next valid code
                                                  * and continue testing */
    }
    if (j == 0) {
        params->prc = '3';                       /* indicate invalid code */

        /**    restore registers, free storage, and return
        * */
        freemain (dynmem_ptr, DO_DYNLEN);        /* load address of getmained area
                                                  * load length of getmained area
                                                  * free getmained area */
        return 0;                                /* return to caller with rc=0 */
    }

    /**    test minor format code for invalid value.
    * *
    * is major less than 4? */
    j = (params->pmajor >= '4') ? 2 : 5;

    /* get minor format code
    *  is format valid? */
    for (i = '1'; i != (long) params->pminor; i++) {
        if (--j == 0) {
            params->prc = '5';                   /* indicate invalid code */

            /**    restore registers, free storage, and return
            * */
            freemain (dynmem_ptr, DO_DYNLEN);    /* load address of getmained area
                                                  * load length of getmained area
                                                  * free getmained area */
            return 0;                            /* return to caller with rc=0 */
        }
    }

    /**    branch to format routine based on major format code
    * *
    * clear work register
    * get format number
    * clear sign
    * decrement by 1 (zero based)
    * multiply by 4 (length of branch) */
    switch (params->pmajor & 15) {
    case 1:
        /**    major format code 1: commercial (mmddyyyy)
        * */
        j = mfmtsub (params);                    /* go get separator charactor */
        _rlx_move_mem (params->poutdate, params->pdate, 2);
                                                 /* load output area address
                                                  * move mm */
        ptr_poutdate = &params->poutdate [2];    /* bump output address */

        /* is there an insertion char? */
        if (j != 0)
            *ptr_poutdate++ = j;                 /* insert character */
        _rlx_move_mem (ptr_poutdate, &params->pdate [2], 2);
                                                 /* move dd */
        ptr_poutdate += 2;                       /* bump output address */

        /* is there an insertion char? */
        if (j != 0)
            *ptr_poutdate++ = j;                 /* insert character */
        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 2:
        /**    major format code 2: european (ddmmyyyy)
        * */
        j = mfmtsub (params);                    /* go get separator charactor */
        _rlx_move_mem (params->poutdate, &params->pdate [2], 2);
                                                 /* load output area address
                                                  * move dd */
        ptr_poutdate = &params->poutdate [2];    /* bump output address */

        /* is there an insertion char? */
        if (j != 0)
            *ptr_poutdate++ = j;                 /* insert character */
        _rlx_move_mem (ptr_poutdate, params->pdate, 2);
                                                 /* move mm */
        ptr_poutdate += 2;                       /* bump output address */

        /* is there an insertion char? */
        if (j != 0)
            *ptr_poutdate++ = j;                 /* insert character */
        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 3:
        /**    major format code 3: f.i.p.s. (yyyymmdd)
        * */
        j = mfmtsub (params);                    /* go get separator charactor */
        _rlx_move_mem (params->poutdate, &params->pdate [4], 4);
                                                 /* load output area address
                                                  * move yyyy */
        ptr_poutdate = &params->poutdate [4];    /* bump output address */

        /* is there an insertion char? */
        if (j != 0)
            *ptr_poutdate++ = j;                 /* insert character */
        _rlx_move_mem (ptr_poutdate, params->pdate, 2);
                                                 /* move mm */
        ptr_poutdate += 2;                       /* bump output address */

        /* is there an insertion char? */
        if (j != 0)
            *ptr_poutdate++ = j;                 /* insert character */
        _rlx_move_mem (ptr_poutdate, &params->pdate [2], 2);
                                                 /* move dd */
        ptr_poutdate += 2;                       /* bump output address
                                                  * set output field size */
        break;

    case 4:
        /**    major format code 4: text 1 (mmmmmmmmm d, yyyy)
        * */
        ptr_poutdate = params->poutdate;         /* load output area address */

        /* european? */
        if (params->pminor == '2') {
            mday (&ptr_poutdate, params);        /* move day of month */
            *ptr_poutdate = ' ';                 /* insert blank */
            ptr_poutdate = mmonthn (ptr_poutdate + 1, params, dynmem_ptr);
                                                 /* bump output address
                                                  * move month name */
        } else {
            ptr_poutdate = mmonthn (ptr_poutdate, params, dynmem_ptr);
                                                 /* move month name */
            mday (&ptr_poutdate, params);        /* move day of month */
            memcpy (ptr_poutdate, ", ", 2);      /* insert comma */
            ptr_poutdate += 2;                   /* bump output address
                                                  * continue */
        }

        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 5:
        /**    major format code 5: text 2 (mmm d, yyyy)
        * */
        ptr_poutdate = params->poutdate;         /* load output area address */

        /* european? */
        if (params->pminor == '2') {
            mday (&ptr_poutdate, params);        /* move day of month */
            *ptr_poutdate = ' ';                 /* insert blank */
            ptr_poutdate = mmontha (ptr_poutdate + 1, params, dynmem_ptr);
                                                 /* bump output address
                                                  * move month abbreviation */
        } else {
            ptr_poutdate = mmontha (ptr_poutdate, params, dynmem_ptr);
                                                 /* move month abbreviation */
            mday (&ptr_poutdate, params);        /* move day of month */
            memcpy (ptr_poutdate, ", ", 2);      /* insert comma */
            ptr_poutdate += 2;                   /* bump output address
                                                  * continue */
        }

        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 6:
        /**    major format code 6: text 3 (dayname, mmmmmmmmm d, yyyy)
        * */
        output_address = mdayn (params->poutdate, dynmem_ptr);
                                                 /* load output area address
                                                  * move day of week name */

        /* european? */
        if (params->pminor == '2') {
            mday (&output_address, params);      /* move day of month */
            output_address [0] = ' ';            /* insert blank */
            ptr_poutdate = mmonthn (&output_address [1], params, dynmem_ptr);
                                                 /* bump output address
                                                  * move month name */
        } else {
            ptr_poutdate = mmonthn (output_address, params, dynmem_ptr);
                                                 /* move month name */
            mday (&ptr_poutdate, params);        /* move day of month */
            memcpy (ptr_poutdate, ", ", 2);      /* insert comma */
            ptr_poutdate += 2;                   /* bump output address
                                                  * continue */
        }

        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 7:
        /**    major format code 7: text 4 (dayname, mmm d, yyyy)
        * */
        output_address = mdayn (params->poutdate, dynmem_ptr);
                                                 /* load output area address
                                                  * move day of week name */

        /* european? */
        if (params->pminor == '2') {
            mday (&output_address, params);      /* move day of month */
            output_address [0] = ' ';            /* insert blank */
            ptr_poutdate = mmontha (&output_address [1], params, dynmem_ptr);
                                                 /* bump output address
                                                  * move month abbreviation */
        } else {
            ptr_poutdate = mmontha (output_address, params, dynmem_ptr);
                                                 /* move month abbreviation */
            mday (&ptr_poutdate, params);        /* move day of month */
            memcpy (ptr_poutdate, ", ", 2);      /* insert comma */
            ptr_poutdate += 2;                   /* bump output address
                                                  * continue */
        }

        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 8:
        /**    major format code 8: text 5 (day, mmmmmmmmm d, yyyy)
        * */
        output_address = mdaya (params->poutdate, dynmem_ptr);
                                                 /* load output area address
                                                  * move day of week abbreviation */

        /* european? */
        if (params->pminor == '2') {
            mday (&output_address, params);      /* move day of month */
            output_address [0] = ' ';            /* insert blank */
            ptr_poutdate = mmonthn (&output_address [1], params, dynmem_ptr);
                                                 /* bump output address
                                                  * move month name */
        } else {
            ptr_poutdate = mmonthn (output_address, params, dynmem_ptr);
                                                 /* move month name */
            mday (&ptr_poutdate, params);        /* move day of month */
            memcpy (ptr_poutdate, ", ", 2);      /* insert comma */
            ptr_poutdate += 2;                   /* bump output address
                                                  * continue */
        }

        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    case 9:
        /**    major format code 9: text 6 (day, mmm d, yyyy)
        * */
        output_address = mdaya (params->poutdate, dynmem_ptr);
                                                 /* load output area address
                                                  * move day of week abbreviation */

        /* european? */
        if (params->pminor == '2') {
            mday (&output_address, params);      /* move day of month */
            output_address [0] = ' ';            /* insert blank */
            ptr_poutdate = mmontha (&output_address [1], params, dynmem_ptr);
                                                 /* bump output address
                                                  * move month abbreviation */
        } else {
            ptr_poutdate = mmontha (output_address, params, dynmem_ptr);
                                                 /* move month name */
            mday (&ptr_poutdate, params);        /* move day of abbreviation */
            memcpy (ptr_poutdate, ", ", 2);      /* insert comma */
            ptr_poutdate += 2;                   /* bump output address
                                                  * continue */
        }

        _rlx_move_mem (ptr_poutdate, &params->pdate [4], 4);
                                                 /* move yyyy */
        ptr_poutdate += 4;                       /* bump output address
                                                  * set output field size */
        break;

    default:
        _rlx_flow_error_trap();
                /* (Does not return) */
        break;
    }

    /**    return the size of the output field in bytes (common routine
    * *    branched to by all major format code routines above)
    * */
    _rlx_binary_to_packed (ptr_poutdate - params->poutdate, dynmem_ptr->dwork, 8);
                                                 /* get address of field start
                                                  * compute length of field
                                                  * convert to decimal */
    _rlx_packed_to_string (dynmem_ptr->dwork, 3, &dynmem_ptr->dwork [6], 2);
                                                 /* unpack size */
    _rlx_move_mem (params->psize, &dynmem_ptr->dwork [1], sizeof(params->psize));
                                                 /* move to output field */

    /**    restore registers, free storage, and return
    * */
    freemain (dynmem_ptr, DO_DYNLEN);            /* load address of getmained area
                                                  * load length of getmained area
                                                  * free getmained area */
    return 0;                                    /* return to caller with rc=0 */
}


/*
*************************************************************************
* mfmtsub                                                               *
*************************************************************************
*
*     this subroutine places the insertion character (if any) into
*     register 3 based upon minor code 1 through 5 (used by major
*     code routines 1 through 3 above.
*
*
* Parameters:
*
*    struct y2kdfmt_parms *parms_ptr                [Originally in r11; In]
*
* Result:
*
*    long                                           [Originally in r3]
*/
static long mfmtsub (struct y2kdfmt_parms *parms_ptr)
{
    long result;                                 /* [Originally in r3] */

    result = 0;                                  /* assume no separator */

    /* clear work register
    *  get minor format number
    *  clear sign
    *  decrement by 1 (zero based)
    *  multiply by 4 (length of branch) */
    switch (parms_ptr->pminor & 15) {
    case 1:
        break;
    case 2:
        result = ' ';                            /* space is insertion character */
        break;
    case 3:
        result = '/';                            /* space is insertion character */
        break;
    case 4:
        result = '-';                            /* space is insertion character */
        break;
    case 5:
        result = '.';                            /* space is insertion character */
        break;
    default:
        _rlx_flow_error_trap();
                /* (Does not return) */
        break;
    }

    return result;
}


/*
*************************************************************************
* mdayn                                                                 *
*************************************************************************
*
*     move weekday name to output area followed by ', ' (common
*     routine performed by major format code routines 6/7 above)
*
*
* Parameters:
*
*    unsigned char *output_address                  [Originally in r2; In]
*    struct y2kdfmt_dynmem *dynmem_ptr              [Originally in r13; In]
*
* Result:
*
*    unsigned char *                                [Originally in r2]
*/
static unsigned char * mdayn (unsigned char *output_address, struct y2kdfmt_dynmem *dynmem_ptr)
{
    long full_name_length;                       /* [Originally in r7] */
    unsigned char *p;                            /* [Originally in r6] */

    p = lday (&full_name_length, dynmem_ptr);    /* get address/length of dayname */
    full_name_length--;                          /* decrement length for ex */
    _rlx_move_mem (output_address, p, (unsigned char) full_name_length + 1);
                                                 /* move day name */
    output_address += full_name_length + 1;      /* restore full name length
                                                  * bump output address */
    memcpy (output_address, ", ", 2);            /* insert comma/blank after name */
    return output_address + 2;                   /* bump output address */
}


/*
*************************************************************************
* mdaya                                                                 *
*************************************************************************
*
*     move weekday abbr to output area followed by ', ' (common
*     routine performed by major format code routines 7/8 above)
*
*
* Parameters:
*
*    unsigned char *output_address                  [Originally in r2; In]
*    struct y2kdfmt_dynmem *dynmem_ptr              [Originally in r13; In]
*
* Result:
*
*    unsigned char *                                [Originally in r2]
*/
static unsigned char * mdaya (unsigned char *output_address, struct y2kdfmt_dynmem *dynmem_ptr)
{
    unsigned char *p;                            /* [Originally in r6] */
    long v;                                      /* [Originally in r7] */

    p = lday (&v, dynmem_ptr);                   /* get address/length of dayname */
    _rlx_move_mem (output_address, p, 3);        /* abbr length minus 1 for ex
                                                  * move day name */
    output_address += 3;                         /* restore full move length
                                                  * bump output address */
    memcpy (output_address, ", ", 2);            /* insert comma/blank after name */
    return output_address + 2;                   /* bump output address */
}


/*
*************************************************************************
* mmonthn                                                               *
*************************************************************************
*
*     move month name to output area followed by a blank (common
*     routine performed by major format code                above)
*
*
* Parameters:
*
*    unsigned char *output_address                  [Originally in r2; In]
*    struct y2kdfmt_parms *parms_ptr                [Originally in r11; In]
*    struct y2kdfmt_dynmem *dynmem_ptr              [Originally in r13; In]
*
* Result:
*
*    unsigned char *                                [Originally in r2]
*/
static unsigned char * mmonthn (unsigned char *output_address, struct y2kdfmt_parms *parms_ptr, struct y2kdfmt_dynmem *dynmem_ptr)
{
    long full_name_length;                       /* [Originally in r7] */
    unsigned char *p;                            /* [Originally in r6] */

    p = lmonth (&full_name_length, parms_ptr, dynmem_ptr);
                                                 /* get address/length of month */
    full_name_length--;                          /* decrement length for ex */
    _rlx_move_mem (output_address, p, (unsigned char) full_name_length + 1);
                                                 /* move month name */
    output_address += full_name_length + 1;      /* restore full name length
                                                  * bump output address */
    *output_address = ' ';                       /* insert blank after name */
    return output_address + 1;                   /* bump output address */
}


/*
*************************************************************************
* mmontha                                                               *
*************************************************************************
*
*     move month abbr to output area followed by a blank (common
*     routine performed by major format code                above)
*
*
* Parameters:
*
*    unsigned char *output_address                  [Originally in r2; In]
*    struct y2kdfmt_parms *parms_ptr                [Originally in r11; In]
*    struct y2kdfmt_dynmem *dynmem_ptr              [Originally in r13; In]
*
* Result:
*
*    unsigned char *                                [Originally in r2]
*/
static unsigned char * mmontha (unsigned char *output_address, struct y2kdfmt_parms *parms_ptr, struct y2kdfmt_dynmem *dynmem_ptr)
{
    unsigned char *p;                            /* [Originally in r6] */
    long v;                                      /* [Originally in r7] */

    p = lmonth (&v, parms_ptr, dynmem_ptr);      /* get address/length of month */
    _rlx_move_mem (output_address, p, 3);        /* abbr length minus 1 for ex
                                                  * move month name */
    output_address += 3;                         /* restore full move length
                                                  * bump output address */
    *output_address = ' ';                       /* insert blank after name */
    return output_address + 1;                   /* bump output address */
}


/*
*************************************************************************
* mday                                                                  *
*************************************************************************
*
*     move day of month to output area (common routine performed from
*     major format code routines 4 through 9 above)
*
*
* Parameters:
*
*    unsigned char **ptr                            [Originally in r2; InOut]
*    struct y2kdfmt_parms *params                   [Originally in r11; In]
*/
static void mday (unsigned char **ptr, struct y2kdfmt_parms *params)
{
    /* is first digit zero? */
    if (params->pdate [2] == '0')
        *(*ptr)++ = params->pdate [3];           /* move only right digit */
    else {
        _rlx_move_mem (*ptr, &params->pdate [2], 2);
                                                 /* move both digits */
        *ptr += 2;                               /* bump output address */
    }
}


/*
*************************************************************************
* lday                                                                  *
*************************************************************************
*
*     load address of day name in r6, length in r7 (common routine
*     performed from mdayn and mdaya above)
*
*
* Parameters:
*
*    long *size_day                                 [Originally in r7; Out]
*    struct y2kdfmt_dynmem *dynmem_ptr              [Originally in r13; In]
*
* Result:
*
*    unsigned char *                                [Originally in r6]
*/
static unsigned char * lday (long *size_day, struct y2kdfmt_dynmem *dynmem_ptr)
{
    struct day_name *item;                       /* [Originally in r7] */

    _rlx_zoned_to_packed (dynmem_ptr->dwork, 1, &dynmem_ptr->downparm.ddow, 1);
                                                 /* pack day integral number */
    _rlx_move_packed (dynmem_ptr->dwork, 8, dynmem_ptr->dwork, 1);
                                                 /* expand to doubleword */
    item = &dname [_rlx_packed_to_binary (dynmem_ptr->dwork, 8)];
                                                 /* convert to binary
                                                  * multiply by 12 (length of entry)
                                                  * load address of name's size */
    *size_day = item->name_length;               /* load size of day's name */
    return (unsigned char *) item + 2;           /* load address of day's name */
}


/*
*************************************************************************
* lmonth                                                                *
*************************************************************************
*
*     load address of month name in r6, length in r7 (common routine
*     performed from mmonthn and mmontha above)
*
*
* Parameters:
*
*    long *size_month                               [Originally in r7; Out]
*    struct y2kdfmt_parms *parms_ptr                [Originally in r11; In]
*    struct y2kdfmt_dynmem *dynmem_ptr              [Originally in r13; In]
*
* Result:
*
*    unsigned char *                                [Originally in r6]
*/
static unsigned char * lmonth (long *size_month, struct y2kdfmt_parms *parms_ptr, struct y2kdfmt_dynmem *dynmem_ptr)
{
    struct month_name *item;                     /* [Originally in r7] */

    _rlx_zoned_to_packed (dynmem_ptr->dwork, 2, parms_ptr->pdate, 2);
                                                 /* pack month integral number */
    _rlx_move_packed (dynmem_ptr->dwork, 8, dynmem_ptr->dwork, 2);
                                                 /* expand to doubleword */
    item = &mname [_rlx_packed_to_binary (dynmem_ptr->dwork, 8) - 1];
                                                 /* convert to binary
                                                  * decrement by 1 (zero based)
                                                  * multiply by 12 (length of entry)
                                                  * load address of name's size */
    *size_month = item->name_length;             /* load size of month's name */
    return (unsigned char *) item + 2;           /* load address of month's name */
}