[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::vaxc

Title:VAX C Notes
Notice:READ 1.* BEFORE WRITING; USE KEYWORDS TO FIND EXISTING NOTES
Moderator:DECC::VMCCUTCHEON
Created:Sat Jan 25 1986
Last Modified:Mon Jun 02 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:5611
Total number of notes:27963

5611.0. "Problem on Axp with DOUBLE datas." by PADKOA::COSTEUX (France: pays d'assist�s...) Mon Jun 02 1997 11:39

    When running the following program the result is that the first
    variable named 'mt' is incorrectly displayed. ALl other
    variables (including mt2 which is also declared as DOUBLE like is
    defined mt) are correctly displayed. This same program works fine on Vax. 
    The problem ocurs only on Axp.
    Any help is greatly welcome ...
    
    Thanks in advance.
    
    Jean-Pierre
    
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    ***> - main program:

/* paye *****************************************************************
 *         menu general de la paye					*
 ************************************************************************/

/*
# include "appli.h"
# include "fenetre.h"
exec sql include sqlca.h;
*/
#define S_NORMAL 0

main()

{


	char	ch[81];
	short	fen, ish;
	long	lsh;
	double	mt2, mt;

	mt = 13456.45;
	mt2 = 22222.55;
	ish = 345;
	lsh = 123456L;
	s_pr( fen, 4, 5, S_NORMAL, "Montant    : %9.02lf  mt2:%8.02lf", 
						mt, mt2);
	s_pr( fen, 10, 5, S_NORMAL, "Chaine: %s _ %s", 
		"chaine1", "chaine2");
	s_pr( fen, 12, 5, S_NORMAL, "Short: %d _ %d",  23, 44);
	s_pr( fen, 14, 5, S_NORMAL, "Long : %ld _ %ld",  123456L, 4567890L);

/*	getchar(); */
}

    ***> - function called:
/*s_pr************************************************************************
 * affichage dans une fenetre d'un ecran virtuel                             *
 *****************************************************************************/
# include "fenetre.h"

s_pr(num,lig,col,type,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)

char	*cmd;
int	num, lig, col, type;

{           

	char	ch1[80], data[80];
	int	i, j;
	$DESCRIPTOR (dat,data);

	printf("\nDEBUT S_PR");
	printf("\nS_PR _ DATA:%s", data);

	sprintf(data,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);

	printf("\nS_PR _ CMD :%s", cmd);
	printf("\nS_PR _ DATA:%s", data);

	dat.dsc$w_length = strlen(data);

/**
	i = SMG$PUT_CHARS(&fenetre[num].num_fenetre,&dat,&lig,&col,0,&type); 
	
**/
	/*else s_erreur(i);*/
}


    ***> - procedure to create the .EXE:
$ cc/stand=VAXC/deb/noop/float=d_float/member titi
$ cc/stand=VAXC/deb/noop/float=d_float/member s_pr
$ link/deb titi,s_pr,sys$library:vaxcrtld/lib
$ del/log/noconf *.obj;*
$ pu
$ exit
    ***> - appli.h:

# define	OUI		1
# define	NON		2

# define	OK		1
# define	NOK		0

# define	AUTRE		0
# define	RESEAU		1
# define	BATCH		2
# define	INTERACTIF	3

# define	DIRECTE		1
# define	DIFFERE		2

# define	NORMAL		1
# define	NOR_VIDEO	1
# define	INVERSE	 	2
# define	INV_VIDEO       2
# define	CLIGNOTE	3
# define	SOULIGNE	4
# define	INTENSE		5
# define	SLSH		6
# define	DLSH		7
# define	DLDH		8

# define	PHYSIQUE	1
# define	VIRTUEL		2

# define	J     		0 /* JOUR pour stdrt */
# define	M     		1 /* MOIS pour strdt */
# define	A     		2 /* AN   pour strdt */

# define	JJMMAA		1
# define	JJMM		2
# define	MMAA		3
# define	SRT		4
# define	SHORT		5
# define	LONG		6
# define	CODE		7
# define	JJMMAAAA	8

# define	BS		127
# define	VALIDER		270
# define	RETN		13
# define	HOME		7
# define	KEY_RIGHT	277
# define	KEY_LEFT	276
# define	KEY_UP		274
# define	KEY_DOWN	275
# define	NEXT_PAGE	316
# define	PREV_PAGE	315
# define	INSRT_CHAR	11
# define	DEL_CHAR	12
# define	INSRT_LINE	13
# define	DEL_LINE	14
# define	RECH		311
# define	SELECTION	314
# define	DEL		127
# define	BELL		'\007'

# define	F1		291
# define	F2		292
# define	F3		293
# define	F4		294
# define	F5		295
# define	F6		296
# define	F7		297
# define	F8		298
# define	F9		299
# define	F10		300
# define	PF1		256
# define	PF2		257
# define	PF3		258
# define	PF4		259


    ***> - fenetre.h:

/*fenetre*********************************************************************
 * header du gestionnaire d'ecran C-VMS (SMG$)                               *
 *****************************************************************************/

# include <stdio.h>

/*
# include <car.h>
*/

# include descrip
# include smgdef

# define S_MAX_FENETRE	300

# define NETWORK	1
# define BATCH		2
# define INTERACTIF	3

# define OK		1
# define NOK		0

# define S_OUI		1
# define S_NON		2

# define S_VISIBLE	1
# define S_INVISIBLE	2

# define S_HORI		1
# define S_VERT		2

# define S_NORMAL 	0
# define S_INVERSE	SMG$M_REVERSE
# define S_SOULIGNE 	SMG$M_UNDERLINE
# define S_INTENSE 	SMG$M_BOLD
# define S_CLIGNOTE	SMG$M_BLINK

# define S_DOWN		SMG$M_DOWN
# define S_UP  		SMG$M_UP
# define S_RIGHT	SMG$M_RIGHT
# define S_LEFT		SMG$M_LEFT

# define S_LIGNE	1
# define S_PAGE		2
# define S_DEMIPAGE     3
# define S_PAGE_1	4


# define REMPLACEMENT	1
# define INSERTION	2

# define SAI_STR	1
# define SAI_NBR	2
# define SAI_DEC	3
# define SAI_HR		4
# define SAI_JMA	5
# define SAI_JMAA	6

char	s_user[30];
char	s_application[30];
int	s_num_pid;
int	s_num_clavier;
int	s_num_ecran_physique;

struct fenetre {
	short	etat;
	int	num_fenetre;
	short	lig;
	short	col;
} fenetre[S_MAX_FENETRE];

# define	MAX_NIVEAU	5
# define	MAX_CHOIX	20

struct menu0 {
	char	lib_sup[30];
	char	lib_inf[30];
	short	col;
	short	lg;
	short	action;
} menu0[9];	    

struct ss_menu {
	short	max_menu;
	struct menu {    
		int    	num_fenetre;
		short	max_lib;
		short	max_lg;
		char   	lib[MAX_CHOIX+1][70];
		short  	type[MAX_CHOIX+1];
		short  	action[MAX_CHOIX+1];
	} menu[100];
} ss_menu[MAX_NIVEAU+1];

struct param_menu {
	short	premier_passage;
	short	nb_menu0;
	int	num_menu0;
	int	num_pied;
	short	menu0_val;
	short	menu_val[MAX_NIVEAU+1];
	short	menu_lig[MAX_NIVEAU+1];
	short	niveau;
};

struct param_menu param_menu = {S_OUI,0,0,0,0};

struct	def_sai_code {
	char	choix[300][60];
	short	nb;
} def_sai_code;


struct	param_saisie {
	short	mode;
        short	num_pied;
	short	lg;
	char	ch_initiale[256];
	double	bmin;
	double	bmax;
} param_saisie;

    
    
    
    *****************************************************************************
    ... Here is a Debugger Log file:
    
g
!break at routine TITI\main
!    23:         mt = 13456.45;
Step
!stepped to TITI\main\%LINE 24
!    24:         mt2 = 22222.55;
Step
!stepped to TITI\main\%LINE 25
!    25:         ish = 345;
Step
!stepped to TITI\main\%LINE 26
!    26:         lsh = 123456L;
Step
!stepped to TITI\main\%LINE 27
!    27:         s_pr( fen, 4, 5, S_NORMAL, "Montant    : %9.02lf  mt2:%8.02lf", 
exa/d_float mt
!TITI\main\mt:   13456.4500000000
exa/d_float mt2
!TITI\main\mt2:  22222.5500000000
step/into
!%DEBUG-I-DYNMODSET, setting module S_PR
!stepped to S_PR\s_pr\%LINE 4316
!  4316:         $DESCRIPTOR (dat,data);
Step
!stepped to S_PR\s_pr\%LINE 4318
!  4318:         printf("\nDEBUT S_PR");
exa/d_float arg0
!S_PR\s_pr\arg0: -0.173211716118183E+35  <***************** problem  ****
exa/d_float arg1
!S_PR\s_pr\arg1: 22222.5500000000
Step
!stepped to S_PR\s_pr\%LINE 4319
!  4319:         printf("\nS_PR _ DATA:%s", data);
Step
!stepped to S_PR\s_pr\%LINE 4321
!  4321:         sprintf(data,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
Step
!stepped to S_PR\s_pr\%LINE 4323
!  4323:         printf("\nS_PR _ CMD :%s", cmd);
exa cmd
!S_PR\s_pr\cmd:  131088
exa data
!S_PR\s_pr\data[0:79]
!    [0]:        77
!    [1]:        111
!    [2]:        110
!    [3]:        116
!    [4]:        97
!    [5]:        110
!    [6]:        116
!    [7]:        32
!    [8]:        32
!    [9]:        32
!    [10]:       32
!    [11]:       58
!    [12]:       32
!    [13]:       45
!    [14]:       49
!    [15]:       55
!    [16]:       51
!    [17]:       50
!    [18]:       49
!    [19]:       49
!    [20]:       55
!    [21]:       49
!    [22]:       54
!    [23]:       49
!    [24]:       49
!    [25]:       56
!    [26]:       49
!    [27]:       56
!    [28]:       51
!    [29]:       51
!    [30]:       48
!    [31]:       49
!    [32]:       48
!    [33]:       48
!    [34]:       48
!    [35]:       48
!    [36]:       48
!    [37]:       48
!    [38]:       48
!    [39]:       48
!    [40]:       48
!    [41]:       48
!    [42]:       48
!    [43]:       48
!    [44]:       48
!    [45]:       48
!    [46]:       48
!    [47]:       48
!    [48]:       48
!    [49]:       46
!    [50]:       48
!    [51]:       48
!    [52]:       32
!    [53]:       32
!    [54]:       109
!    [55]:       116
!    [56]:       50
!    [57]:       58
!    [58]:       50
!    [59]:       50
!    [60]:       50
!    [61]:       50
!    [62]:       50
!    [63]:       46
!    [64]:       53
!    [65]:       53
!    [66]:       0
!    [67]:       0
!    [68]:       0
!    [69]:       0
!    [70]:       0
!    [71]:       0
!    [72]:       108
!    [73]:       54
!    [74]:       81
!    [75]:       0
!    [76]:       0
!    [77]:       0
!    [78]:       0
!    [79]:       0
Step
!stepped to S_PR\s_pr\%LINE 4324
!  4324:         printf("\nS_PR _ DATA:%s", data);
Step
!stepped to S_PR\s_pr\%LINE 4326
!  4326:         dat.dsc$w_length = strlen(data);
exa/d_float arg0
!S_PR\s_pr\arg0: -0.173211716118183E+35		<******* problem *******
go
!%DEBUG-I-EXITSTATUS, is '%SYSTEM-S-NORMAL, normal successful completion'
exit
    
T.RTitleUserPersonal
Name
DateLines
5611.1DECC versions used for my tests.PADKOA::COSTEUXFrance: pays d&#039;assist�s...Mon Jun 02 1997 11:453
    Forgot to mention that I get the same behavior on Axp using either
    DECC-V5.3-006 or DECC-V5.5-003
    
5611.2SPECXN::DERAMODan D&#039;EramoMon Jun 02 1997 12:2742
            <<< CLT::DISK$CLT_LIBRARY3:[NOTES$LIBRARY]SMG.NOTE;1 >>>
                       -< Screen ManaGement Discussions >-
================================================================================
Note 1567.4               SMG$PUT_CHARS problem on AXP.                   4 of 4
SPECXN::DERAMO "Dan D'Eramo"                         36 lines   2-JUN-1997 11:22
--------------------------------------------------------------------------------
	You just can't do this...it isn't legal C.  It doesn't work.
        
>	s_pr( fen, 4, 5, S_NORMAL, "Montant    : %9.02lf  mt2:%8.02lf", 
>						mt, mt2);
        
>s_pr(num,lig,col,type,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)
>
>char	*cmd;
>int	num, lig, col, type;
>
>{           
[...]
>	sprintf(data,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
        
        The only way to write s_pr is to prototype it with the "..."
        before calling it and then define it using <stdarg.h>.
        
        Dan
        
#include <stdarg.h>
void s_pr(int num, int lig, int col, int type, const char *cmd, ...);
        
/* Now that the above prototype has been seen it is okay to call s_pr. */
        
/* Here's how the definition calls sprintf... */
void s_pr(int num, int lig, int col, int type, const char *cmd, ...)
{
    va_list ap;
    char data[80];
        
    va_start(ap, cmd);
    vsprintf(data, cmd, ap);
    va_end(ap);
        
    /* ... */
}
5611.3OK. But why a pb. only for the first variable? PADKOA::COSTEUXFrance: pays d&#039;assist�s...Mon Jun 02 1997 12:495
    I don' t understand as there is no problem with other variables to
    print but the variable mt only ..
    I'm not a C expert so it's difficult to understand...
    
    Jean-Pierre
5611.4Use Correct Syntax...XDELTA::HOFFMANSteve, OpenVMS EngineeringMon Jun 02 1997 13:5316
   The variable-argument-list functions look at the argument list to
   determine how many arguments are passed -- there is either an
   explicit number of arguments passed via the argument list (this
   can be explicitly passed as an argument on either platform, or it
   can be read via the call list on VAX), or via implicit mechanisms
   such as the printf control string or the pattern of arguments.
   From this, the routine can determine the number of arguments...

   As for why this works -- C has a calling standard waiver around
   passing quadword-sized arguments (doubles) by value on VAX -- these
   take up two longword argument positions in the call stack.  I'd
   suspect this difference was involved here.

   Bottom line: fix the code.

5611.5You lied about the types, and got caughtWIBBIN::NOYCEPulling weeds, pickin&#039; stonesMon Jun 02 1997 17:1145
>s_pr(num,lig,col,type,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)
>
>char	*cmd;
>int	num, lig, col, type;
>
>{           

This declaration says that arg0, arg1, ..., arg9 all have type "int".
When you pass an argument of a different type, things may go wrong.

On Alpha, the first 6 arguments are passed in registers -- integer
arguments in integer registers, and floating arguments in floating
registers.  Thus, num, lig, col, type, cmd, and arg0 are expected to
arrive in the 6 integer argument registers, while arg1, arg2, ..., arg9
are expected to arrive in memory.

>	s_pr( fen, 4, 5, S_NORMAL, "Montant    : %9.02lf  mt2:%8.02lf", 
>						mt, mt2);

This call passes fen, 4, 5, S_NORMAL, and the string pointer in the first 5
integer argument registers.  It passes mt in the 6th floating argument
register, and it passes mt2 in memory.

When s_pr copies arg0 for the call to sprintf, it gets an uninitialized
value out of the 6th integer argument register, and places it in the 3rd
integer argument register (after data and cmd).  That's why you see garbage
printed.

(Why does mt2 work?  s_pr gets the right data -- or at least the low longword
of the right data, so you get 7 significant digits -- out of memory, and puts
it into the 4th integer argument register.  But sprintf ought to expect a
floating argument for a "%ld" item.  This works, approximately, because of magic
flags passed in the "Argument Information" register (R25) that tell sprintf (and
other stdargs routines) where their arguments were actually passed.  The "AI"
register isn't used on Digital UNIX or Windows NT, so this wouldn't work there.
Also, those systems only support IEEE floating types, where the most significant
part of a double is in the higher-addressed half, not the lower-addressed half as
for the VAX types.)

The proper solution is to recode s_pr to use the stdarg mechanism.  If that
turns out to be really difficult, you could hack around it by passing an extra
parameter to s_pr, so that arg0 is pushed out to the 7th position, and gets
passed in memory instead of in a register.  If you declare arg0 thru arg9 as
__int64 on Alpha, you won't even lose precision   But this is really a hack --
you should use the stdarg mechanism.
5611.6SPECXN::DERAMODan D&#039;EramoMon Jun 02 1997 18:3331
        In comparison to .-1, here is why you "got away with it"
        on OpenVMS VAX.  The call
        
>	s_pr( fen, 4, 5, S_NORMAL, "Montant    : %9.02lf  mt2:%8.02lf", 
>						mt, mt2);
        
        created an arglist with longword count 9 followed by longwords
        fen, 4, 5, S_NORMAL, "Montant...", mt (lo), mt (hi), mt2 (lo), mt2 (hi)
        
        The declaration
        
>s_pr(num,lig,col,type,cmd,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)
>
>char	*cmd;
>int	num, lig, col, type;
        
        caused s_pr to pick up these 9 longwords into arguments
        num,lig,col,type,cmd,arg0,arg1,arg2,arg3.  The call to sprintf
        in s_pr built up sprintf's argument list in exactly the same
        way sprintf would have seen it if you had passed the format
        string and mt and mt2 to sprintf directly.
        
        Lots of older C compilers passed arguments in consecutive
        memory locations like that, and the code would probably have
        appeared to work fine using any of them.  But once it was
        ported to a system where arguments were passed in registers
        the underlying nonportability was revealed.  That's why
        <stdarg.h> was standardized, any ANSI C vendor has to make it
        work no matter how the compiler passes arguments.
        
        Dan