Thread overview
Union bug??
May 16, 2001
Mark Evans
May 16, 2001
Mark Evans
May 16, 2001
Mark Evans
May 17, 2001
Walter
May 17, 2001
Mark Evans
May 17, 2001
Mark Evans
May 17, 2001
Walter
May 17, 2001
Mark Evans
May 17, 2001
Mark Evans
May 17, 2001
Walter
May 16, 2001

It's possible that I've uncovered a bug in the C compiler.

The complicated structure below includes a union of subsidiary structure types. Given two of these ParseBlock structures, I want to copy one of the unionized subsidiaries from one ParseBlock to the other.

It is turning out to be surprisingly close to impossible, and I don't understand
why.  This should be a simple memory operation.  The structures are declared
as __far in my 16-bit Windows 3.1 app.  The union is a union of structures
which are defined in a vendor header file.  These are identified as SPM_XXX
structs.

The only code that works copies the entire ParseBlock, including
the internal union.  (Here outpb and inpb are far pointers to ParseBlock.)

	*outpb = *inpb;

The following similar code does not work (but should):

	*((SPM_APPROACH_PARAMS __far *) &(outpb->structs.pb_SPM_APPROACH_PARAMS)) =
	*((SPM_APPROACH_PARAMS __far *) &(inpb->structs.pb_SPM_APPROACH_PARAMS));

The more natural and expected fmemcpy() also fails:

	_fmemcpy(&(outpb->structs.pb_SPM_APPROACH_PARAMS),
		&(inpb->structs.pb_SPM_APPROACH_PARAMS),
		sizeof(SPM_APPROACH_PARAMS));

Does anyone have a clue what is going on?

Mark



typedef struct
{
    // locking flag and stack to indicate how it was
    // populated

    BOOL                    locked;

    // general atomic parameter storage
    unsigned long int       U32[k_PARSE_PARAM_ARRAY_SZ];
    unsigned short int      U16[k_PARSE_PARAM_ARRAY_SZ];
    signed long int         I32[k_PARSE_PARAM_ARRAY_SZ];
    signed short int        I16[k_PARSE_PARAM_ARRAY_SZ];
    float                   SGL[k_PARSE_PARAM_ARRAY_SZ];
    double                  DBL[k_PARSE_PARAM_ARRAY_SZ];
    char                    BLC[k_PARSE_PARAM_ARRAY_SZ];
    HSPM                    spmHandles[k_PARSE_PARAM_ARRAY_SMALL_SZ];
    SPMERROR                spmErrs[k_PARSE_PARAM_ARRAY_SMALL_SZ];
    HWND                    window[k_PARSE_PARAM_ARRAY_SMALL_SZ];
    char __far              STR[k_PARSE_PARAM_ARRAY_SMALL_SZ][k_PARSE_STRING_SZ];

    // next-free (also population count)
    signed long int         U32_slot,U16_slot,I32_slot,I16_slot,
                            SGL_slot,DBL_slot,spmHandles_slot,spmErrs_slot,
                            window_slot,BLC_slot,STR_slot;

    // output counters
    signed long int         U32_outcnt,U16_outcnt,I32_outcnt,I16_outcnt,
                            SGL_outcnt,DBL_outcnt,spmHandles_outcnt,spmErrs_outcnt,
                            window_outcnt,BLC_outcnt,STR_outcnt;
    // Arrays
    // Can be any dimension, data is contiguous, row-major order (C order)

    long int                arrayDimensionality;    // 1D, 2D, 3D, ...
    unsigned long int       arrayDims;              // the actual array sizes

    TypeCode arrayType;
    union arrays
    {
        unsigned long int   __huge *    U32Ptr;
        unsigned short int  __huge *    U16Ptr;
        signed long int     __huge *    I32Ptr;
        signed short int    __huge *    I16Ptr;
        float               __huge *    SGLPtr;
        double              __huge *    DBLPtr;
    };

    // storage for pointers to structs for recursion
    TypeCode                recursionStack[k_PARSE_PARAM_ARRAY_SZ];
    unsigned long int       recursion;

    // Every struct type in spm.h, the Park API
    TypeCode structType;
    union
    {
        SPM_PARAMS                  pb_SPM_PARAMS;
        SPM_STATUS_ITEM             pb_SPM_STATUS_ITEM;
        SPM_CALIBRATE_PROGRESS      pb_SPM_CALIBRATE_PROGRESS;
        SPM_ERROR_SIGNAL            pb_SPM_ERROR_SIGNAL;
        SPM_SCANNER_Z               pb_SPM_SCANNER_Z;
        SPM_SCANNER_XY              pb_SPM_SCANNER_XY;
        SPM_SCANNER_Z_SLOPE         pb_SPM_SCANNER_Z_SLOPE;
        SPM_BIAS                    pb_SPM_BIAS;
        SPM_DATA_FILTER_PARAMS      pb_SPM_DATA_FILTER_PARAMS;
        SPM_STEP_PIECE              pb_SPM_STEP_PIECE;
        SPM_WAVE_PIECE              pb_SPM_WAVE_PIECE;
        SPM_WAVE_ACQ                pb_SPM_WAVE_ACQ;
        SPM_SCANNING_PARAMS         pb_SPM_SCANNING_PARAMS;
        SPM_SCAN_RATE_PARAMS        pb_SPM_SCAN_RATE_PARAMS;
        SPM_APPROACH_PARAMS         pb_SPM_APPROACH_PARAMS;
        SPM_APPROACH_PARAMS_LOW     pb_SPM_APPROACH_PARAMS_LOW;
        SPM_MOVE_STEPPER_PARAMS     pb_SPM_MOVE_STEPPER_PARAMS;
        SPM_STEPPER_PARAMS          pb_SPM_STEPPER_PARAMS;
        SPM_MOVE_IMOTOR_PARAMS      pb_SPM_MOVE_IMOTOR_PARAMS;
        SPM_MOVE_PC38_PARAMS        pb_SPM_MOVE_PC38_PARAMS;
        SPM_NCM_SWEEP_LOW_TYPE      pb_SPM_NCM_SWEEP_LOW_TYPE;
        SPM_NCM_PHOP_TYPE           pb_SPM_NCM_PHOP_TYPE;
        SPM_NCM_RESPONSE_LUT        pb_SPM_NCM_RESPONSE_LUT;
        SPM_VOLTAGE_PROBE_PARAMS    pb_SPM_VOLTAGE_PROBE_PARAMS;
        SPM_NCM_SWEEP_PARAMS        pb_SPM_NCM_SWEEP_PARAMS;
        SPM_NCM_SWEEP_POINT         pb_SPM_NCM_SWEEP_POINT;

    } structs;

} ParseBlock,  __far * ParseBlockPtr;



May 16, 2001
I may have discovered the problem.

ParseBlock __far		inpb_block, outpb_block;

declares one of the structs as far, the other near.  This was a mistake.

Mark


May 16, 2001
Still I would like to understand why the assignment *outpb = *inpb works when one block is declared near, the other far.  And what is the doctor-recommended method for copying between near and far data segments.  And how would I assign two far objects to the same data segment.  I did not find a pragma for this purpose.

I tried chaning both to __far and some other code broke mysteriously.  Oh how I love 16-bit code.

Mark



On Wed, 16 May 2001 21:26:39 GMT, Mark Evans <mevans@zyvex.com> wrote:
> I may have discovered the problem.
> 
> ParseBlock __far		inpb_block, outpb_block;
> 
> declares one of the structs as far, the other near.  This was a mistake.
> 
> Mark
> 
> 


May 17, 2001
It all depends on your memory model. I'd use _fmemcpy() if in a near data
model, and memcpy() in a far data model.


"Mark Evans" <mevans@zyvex.com> wrote in message news:1106_990055289@evans...
>
> Still I would like to understand why the assignment *outpb = *inpb works
when one block is declared near, the other far.  And what is the doctor-recommended method for copying between
> near and far data segments.  And how would I assign two far objects to the
same data segment.  I did not find a pragma for this purpose.
>
> I tried chaning both to __far and some other code broke mysteriously.  Oh
how I love 16-bit code.
>
> Mark
>
>
>
> On Wed, 16 May 2001 21:26:39 GMT, Mark Evans <mevans@zyvex.com> wrote:
> > I may have discovered the problem.
> >
> > ParseBlock __far inpb_block, outpb_block;
> >
> > declares one of the structs as far, the other near.  This was a mistake.
> >
> > Mark
> >
> >
>
>


May 17, 2001
Walter,

I've tried both actually, and both fail.

This is very mysterious to me why a deref assignment works and the runtime calls don't.

Mark


On Wed, 16 May 2001 17:29:59 -0700, "Walter" <walter@digitalmars.com> wrote:
> It all depends on your memory model. I'd use _fmemcpy() if in a near data
> model, and memcpy() in a far data model.
> 
> 
> "Mark Evans" <mevans@zyvex.com> wrote in message news:1106_990055289@evans...
> >
> > Still I would like to understand why the assignment *outpb = *inpb works
> when one block is declared near, the other far.  And what is the doctor-recommended method for copying between
> > near and far data segments.  And how would I assign two far objects to the
> same data segment.  I did not find a pragma for this purpose.
> >
> > I tried chaning both to __far and some other code broke mysteriously.  Oh
> how I love 16-bit code.
> >
> > Mark
> >
> >
> >
> > On Wed, 16 May 2001 21:26:39 GMT, Mark Evans <mevans@zyvex.com> wrote:
> > > I may have discovered the problem.
> > >
> > > ParseBlock __far inpb_block, outpb_block;
> > >
> > > declares one of the structs as far, the other near.  This was a mistake.
> > >
> > > Mark
> > >
> > >
> >
> >
> 
> 


May 17, 2001
Walter,

I still suspect something is wrong with putting structures inside a union. Referring to the previous post, this failure is interesting:


SPM_APPROACH_PARAMS __far * src;
SPM_APPROACH_PARAMS __far * dest;

src = &((inpb->structs).pb_SPM_APPROACH_PARAMS);
dest = &((outpb->structs).pb_SPM_APPROACH_PARAMS);

*dest = *src; // fails


/*Approach Params from a header file*/
    typedef struct
    {
        BOOL bQuery;
        BOOL bLift;
        BOOL bAutoLift;
        BOOL bScannerXY;
        BOOL bReNull;
        BOOL bApproach;
        BOOL bSanityChecks;
        long nRetry;
        BOOL bSelectStyle;
        BOOL bCrash;
        BOOL bSelectMotor;
        BOOL bFineMotor;
        long nZMotorOptions;
        float fLiftMicrons;
        float fRetryMicrons;
        float fLiftSpeed;
        float fCrashSpeed;
        BOOL bOvershootMicrons;
        float fOvershootMicrons;
        BOOL bScannerZThreshold;
        float fScannerZThreshold;
        short nScannerZUnit;
        float fTimeoutSeconds;
        float fScannerMicronsX;
        float fScannerMicronsY;
        BOOL bESigCal;
        float fESigCalFactor;
    } SPM_APPROACH_PARAMS;


May 17, 2001
Are you using C or C++? It makes a difference.

"Mark Evans" <mevans@zyvex.com> wrote in message news:1108_990060635@evans...
> Walter,
>
> I still suspect something is wrong with putting structures inside a union. Referring to the previous post, this failure is interesting:
>
>
> SPM_APPROACH_PARAMS __far * src;
> SPM_APPROACH_PARAMS __far * dest;
>
> src = &((inpb->structs).pb_SPM_APPROACH_PARAMS);
> dest = &((outpb->structs).pb_SPM_APPROACH_PARAMS);
>
> *dest = *src; // fails
>
>
> /*Approach Params from a header file*/
>     typedef struct
>     {
>         BOOL bQuery;
>         BOOL bLift;
>         BOOL bAutoLift;
>         BOOL bScannerXY;
>         BOOL bReNull;
>         BOOL bApproach;
>         BOOL bSanityChecks;
>         long nRetry;
>         BOOL bSelectStyle;
>         BOOL bCrash;
>         BOOL bSelectMotor;
>         BOOL bFineMotor;
>         long nZMotorOptions;
>         float fLiftMicrons;
>         float fRetryMicrons;
>         float fLiftSpeed;
>         float fCrashSpeed;
>         BOOL bOvershootMicrons;
>         float fOvershootMicrons;
>         BOOL bScannerZThreshold;
>         float fScannerZThreshold;
>         short nScannerZUnit;
>         float fTimeoutSeconds;
>         float fScannerMicronsX;
>         float fScannerMicronsY;
>         BOOL bESigCal;
>         float fESigCalFactor;
>     } SPM_APPROACH_PARAMS;
>
>


May 17, 2001
Plain vanilla C with no trace of C++.  My build flags are

SCFLAGS = -D_WINIO=1 -D_parkplug -mluw -Jm -p -r -WA -S -5 -a2 -IC:\DigMars\dm\include\;C:\DigMars\dm\include\win16;..\Snippets

and all files end in .c or .h.

The syntax below is legitimate C that should work.  All I can figure is that some kind of segmentation issue is interfering with this simple memory copy.

Mark


On Wed, 16 May 2001 19:07:40 -0700, "Walter" <walter@digitalmars.com> wrote:
> Are you using C or C++? It makes a difference.
> 
> "Mark Evans" <mevans@zyvex.com> wrote in message news:1108_990060635@evans...
> > Walter,
> >
> > I still suspect something is wrong with putting structures inside a union. Referring to the previous post, this failure is interesting:
> >
> >
> > SPM_APPROACH_PARAMS __far * src;
> > SPM_APPROACH_PARAMS __far * dest;
> >
> > src = &((inpb->structs).pb_SPM_APPROACH_PARAMS);
> > dest = &((outpb->structs).pb_SPM_APPROACH_PARAMS);
> >
> > *dest = *src; // fails
> >
> >
> > /*Approach Params from a header file*/
> >     typedef struct
> >     {
> >         BOOL bQuery;
> >         BOOL bLift;
> >         BOOL bAutoLift;
> >         BOOL bScannerXY;
> >         BOOL bReNull;
> >         BOOL bApproach;
> >         BOOL bSanityChecks;
> >         long nRetry;
> >         BOOL bSelectStyle;
> >         BOOL bCrash;
> >         BOOL bSelectMotor;
> >         BOOL bFineMotor;
> >         long nZMotorOptions;
> >         float fLiftMicrons;
> >         float fRetryMicrons;
> >         float fLiftSpeed;
> >         float fCrashSpeed;
> >         BOOL bOvershootMicrons;
> >         float fOvershootMicrons;
> >         BOOL bScannerZThreshold;
> >         float fScannerZThreshold;
> >         short nScannerZUnit;
> >         float fTimeoutSeconds;
> >         float fScannerMicronsX;
> >         float fScannerMicronsY;
> >         BOOL bESigCal;
> >         float fESigCalFactor;
> >     } SPM_APPROACH_PARAMS;
> >
> >
> 
> 


May 17, 2001
Walter,

Think I found my bug.  I did a simple test to validate memory copying with * and it works.

I had been assuming correct operation of another module which was incomplete and because of that, not referencing the actual data copied.

Mark


May 17, 2001
I'm glad you found the problem and are able to proceed. -Walter


"Mark Evans" <mevans@zyvex.com> wrote in message news:1104_990119091@evans...
> Walter,
>
> Think I found my bug.  I did a simple test to validate memory copying with
* and it works.
>
> I had been assuming correct operation of another module which was
incomplete and because of that, not referencing the actual data copied.
>
> Mark
>
>