T.R | Title | User | Personal Name | Date | Lines |
---|
5602.1 | Cockpit error? | CADSYS::GROSS | The bug stops here | Mon Feb 10 1997 08:47 | 7 |
| My C Reference Manual (Steele) says that %2d will accept a minimum of ZERO
digits (and a maximum of 2 digits). Therefore, VAXC is behaving correctly
according to the manual. Maybe you could reverse the order of the two scans.
The scan for 6 fields will fail if there are 7 fields present because the first
digit of "vers" will not match the "." in the scan string.
Dave
|
5602.2 | cannot reproduce the problem | TAVENG::BORIS | Boris Gubenko, ISE | Mon Feb 10 1997 10:24 | 82 |
|
Your code seems to be correct (while leading zeros in the field width are
unnecessary, this is not a bug).
I was unable to reproduce the problem on OpenVMS VAX V6.1 and V6.2.
Could you check the scope of the the 'vers' variable ?
Boris
X.C
===
#include <stdio.h>
main()
{
char *name = "1997020716590588.";
int year, month, date, hours, mins, secs, vers;
int sts, sts1;
if ((sts=sscanf(name, "%04d%02d%02d%02d%02d%02d%2d.", &year, &month, &date,
&hours, &mins, &secs, &vers)) != 7)
sts1=sscanf(name, "%04d%02d%02d%02d%02d%2d.", &year, &month,&date,
&hours, &mins, &vers);
printf("sts=%d, sts1=%d\n",sts,sts1);
printf("year =%d, mins=%d, secs=%d, vers=%d",year,mins,secs,vers);
}
result on OpenVMS VAX V6.1 with VAXC
====================================
Image Identification Information
image name: "VAXCRTL"
image file identification: "V06-007"
link date/time: 9-MAR-1994 01:37:39.79
$ say f$getsyi("version")
V6.1
$ say f$getsyi("hw_name")
VAXstation 4000-VLC
$ cc/vaxc x
$ lin x, sys$input:/opt
sys$share:vaxcrtl/share
$ run x
sts=7, sts1=2146017341
year =1997, mins=59, secs=5, vers=88
result on OpenVMS VAX V6.2 with VAXC
====================================
Image Identification Information
image name: "VAXCRTL"
image file identification: "V06-007"
link date/time: 22-APR-1995 00:15:52.76
$ say f$getsyi("version")
V6.2
$ say f$getsyi("hw_name")
VAX 6000-540
$ cc/vaxc x
$ lin x, sys$input:/opt
sys$share:vaxcrtl/share
$ run x
sts=7, sts1=2144683069
year =1997, mins=59, secs=5, vers=88
result on OpenVMS V6.2 Alpha (with DECC)
========================================
$ say f$getsyi("version")
V6.2-1H1
$ say f$getsyi("hw_name")
AlphaServer 2100 4/275
$ cc x
$ lin x, sys$input:/opt
sys$share:decc$shr/share
$ run x
sts=7, sts1=17
year =1997, mins=59, secs=5, vers=88
|
5602.3 | This is a reply to .1: clash happens | FORTY2::BOYES | My karma ran over my dogma | Mon Feb 10 1997 10:41 | 20 |
| Thanks for your input, but reversing the order of the 'if' produces a match on
six fields when there are seven...
if ((sts1=sscanf(name, "%04d%02d%02d%02d%02d%2d.", &year, &month, &date,
&hours, &mins, &vers)) != 6)
Produces sts1=6
1997020716270188.
produces
year =1997, mins=27, secs=0, vers=1
(Hang on: does "." need escaping to be interpreted correctly?)
+Mark+
|
5602.4 | | FORTY2::BOYES | My karma ran over my dogma | Mon Feb 10 1997 12:22 | 24 |
| I ran the test program in .2 successfully.
Vers is a local variable to the routine. Worryingly one of the output variables
to the relevant routine is called version, and a module level comment in the
code I am modifying says...
** Use stack copy of version in check_file to avoid stack
** trampling problems.
After the scanf calls,
*version = (uint8)vers;
where uint8 is a typedef for unsigned char.
Could it be an aliasing problem? I've tried renaming vers to 'perverse',
and declaring it as 'volatile int' to no effect. Would it be better to declare
year,month...secs,vers as pointers?
+Mark+
|
5602.5 | Reply to .4 | TAVENG::BORIS | Boris Gubenko, ISE | Mon Feb 10 1997 13:02 | 13 |
| >
> I ran the test program in .2 successfully.
>
So, this is not a [s]scanf() problem. I'm almost sure, that locale variable
'vers' contains the right value after sscanf() call.
Casting 'vers' to unsigned char should not hurt (as long as the value is
not truncated); declaring year,month... etc as pointers does not seem to fix
any problem.
Without seeing the code, it is difficult to say what is wrong.
Boris
|
5602.6 | | FORTY2::BOYES | My karma ran over my dogma | Mon Feb 10 1997 15:13 | 133 |
|
Here is the whole routine: m_irr_dbg is an unexciting trace macro.
The code is supposed to work on multiple patforms: the VMS macro *is*
set on VMS (logging info in the ifdef is displayed int the trace file).
I'm not expecting anyone to write my project for me, but if anyone
can confrim that this is valid (if currently very straggly due to all
the debug code) then something context dependednt is happening. Which
is probably a valid point for this conference.
+Mark+
extern boolean ir__def_msg_check_file ( name, length, version, time_check )
uint8 *name;
uint32 length;
uint8 *version;
boolean time_check;
/*
** FUNCTIONAL DESCRIPTION:
**
** This routine is called to see if the given filename of a deferred
** message indicates that the message has timed-out, and therefore needs
** bringing into the MTA.
**
** The deferred-until time is in the filename followed by 84 or 88
** indicating the protocol used by the client.
**
** If the time_check flag is NOT set, then only the name is checked for
** validity, and not whether its timed-out yet.
**
** edit 28: Expand the filename to include seconds: that way if two
** messages are deferred to the same time, they do not have to be faked
** to have filenames (and hence submission times) one minute apart to
** ensure unique filenames. Watch out for old format messages, though.
*/
{ volatile int perverse;
int c,
year=0,
month=0,
date=0,
hours=0,
mins=0,
secs=0,
sts,sts1;
time_t now, deftim;
uint8 tmputc[20];
perverse=0;
m_irr_dbg(printf("Start of bad code\n"));
m_irr_dbg(printf("1.perverse %x=%x\n",&perverse,perverse));
#if defined (unix) || defined (_WIN32)
if (sscanf(name, "%04d%02d%02d%02d%02d%02d%02d", &year, &month, &date,
&hours, &mins, &secs, &perverse) != 7)
if (sscanf(name, "%04d%02d%02d%02d%02d%02d", &year, &month, &date,
&hours, &mins, &perverse) != 6)
return FALSE;
if (length != 16)
if (length !=14)
return FALSE;
#endif
#ifdef vms
if ((sts=sscanf(name, "%04d%02d%02d%02d%02d%02d%2d.", &year, &month, &date,
&hours, &mins, &secs, &perverse)) != 7)
if ((sts1=sscanf(name, "%04d%02d%02d%02d%02d%2d.", &year, &month, &date,
&hours, &mins, &perverse)) != 6)
return FALSE;
m_irr_dbg(printf("2.perverse %x=%x\n",&perverse,perverse));
m_irr_dbg(printf("sts=%d, sts1=%d\n",sts,sts1));
if (length != 17)
if (length !=15)
return FALSE;
m_irr_dbg(printf("Cp1 name is **%s**\n",name));
m_irr_dbg(printf("year =%d, mins=%d, secs=%d, vers=%d\n",year,mins,secs,perverse));
#endif
m_irr_dbg(printf("3.perverse %x=%x\n",&perverse,perverse));
if ((perverse != 84) && (perverse != 88))
return FALSE;
m_irr_dbg(printf("Cp2\n"));
*version = (uint8)perverse;
if (length > 15) /* i.e. new format, on either platform, so do not have to
pretend that the seconds are zero */
{
strncpy(tmputc, name+2,12);
tmputc[12]=0;
strcat(tmputc,"Z");
}
else
{
strncpy (tmputc, name+2, 10);
tmputc[10] = 0;
strcat (tmputc, "00Z");
}
if (!ok(mta_cnv_utc_to_secs (strlen(tmputc), tmputc, &deftim)))
return FALSE;
m_irr_dbg(printf("CP3\n"));
if (!time_check)
return TRUE;
now = mta_time((long*)0);
if (deftim > now)
return FALSE;
m_irr_dbg(printf("CP4\n"));
return TRUE;
}
|
5602.7 | | FORTY2::BOYES | My karma ran over my dogma | Wed Feb 12 1997 05:54 | 6 |
| FYI the problem was finally fixed by copying the first 10 bytes to another
string, using sscanf on that string, and then parsing byte by byte through the
remainder of 'name'. It works, but whatever was breaking sscanf may still be
hanging around waiting to break my new code it in a certain context...
+Mark+
|
5602.8 | uint8 is a char | TAVENG::BORIS | Boris Gubenko, ISE | Thu Feb 13 1997 06:34 | 107 |
| > FYI the problem was finally fixed by copying the first 10 bytes to another
> string, using sscanf on that string, and then parsing byte by byte through the
> remainder of 'name'. It works, but whatever was breaking sscanf may still be
> hanging around waiting to break my new code it in a certain context...
In the code example in .6 you failed to show the calling routine.
If in the calling routine the 'version' variable, whose address is passed
to the ir__def_msg_check_file() routine, is declared as int (or short), the
following assignment
*version = (uint8)perverse;
leaves untouched three (for int) or 1 (for short) high order byte(s) of the
variable.
printf() for the "%d" conversion specifier fetches the whole int, so you
can see a garbage value of the 'version' variable after the call to
ir__def_msg_check_file() routine.
Attached example, based on your code, which illustrates this behaviour.
Boris
X.C
===
#include <ints.h>
#include <stdio.h>
#include <string.h>
typedef int boolean;
#define m_irr_dbg(X) X
static boolean func ( name, length, version, time_check )
uint8 *name;
uint32 length;
uint8 *version;
boolean time_check;
{ volatile int perverse;
int c,
year=0,
month=0,
date=0,
hours=0,
mins=0,
secs=0,
sts,sts1;
perverse=0;
m_irr_dbg(printf("Start of bad code\n"));
m_irr_dbg(printf("1.perverse %x=%x\n",&perverse,perverse));
if ((sts=sscanf(name, "%04d%02d%02d%02d%02d%02d%2d.", &year, &month, &date,
&hours, &mins, &secs, &perverse)) != 7)
if ((sts1=sscanf(name, "%04d%02d%02d%02d%02d%2d.", &year, &month, &date,
&hours, &mins, &perverse)) != 6)
return FALSE;
m_irr_dbg(printf("2.perverse %x=%x\n",&perverse,perverse));
m_irr_dbg(printf("sts=%d, sts1=%d\n",sts,sts1));
if (length != 17)
if (length !=15)
return FALSE;
m_irr_dbg(printf("Cp1 name is **%s**\n",name));
m_irr_dbg(printf("year =%d, mins=%d, secs=%d, vers=%d\n",year,mins,secs,perverse));
m_irr_dbg(printf("3.perverse %x=%x\n",&perverse,perverse));
if ((perverse != 84) && (perverse != 88))
return FALSE;
*version = (uint8)perverse;
printf("in func() version = %08x\n", *version);
return TRUE;
}
main()
{
char *name = "1997020716590588.";
int version;
func ( (uint8 *)name, strlen(name), &version, TRUE );
printf("in main() version = %08x\n", version);
}
Result
======
$ cc/ver/noobj _nl0:
DEC C V5.0-003 on OpenVMS Alpha V6.2-1H1
$ cc/stand=vax x.c
$ lin x
$ run x
Start of bad code
1.perverse 7edf7a18=0
2.perverse 7edf7a18=58
sts=7, sts1=2147076576
Cp1 name is **1997020716590588.**
year =1997, mins=59, secs=5, vers=88
3.perverse 7edf7a18=58
in func() version = 00000058
in main() version = 00030058
^^^^^^
garbage
|