Re: win64

"Frediano Ziglio" <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <[email protected]>
2009/1/17 James K. Lowden <[email protected]>:
> Sometimes work guides The Work.  I built FreeTDS for 64-bit Windows this
> week with VS 2005.  I modified libtds to emit fewer warnings -- I left
> some that are pretty egregious -- and added a .sln and .vcproj files to
> the src directories.
>

good.. I would have put in win32 directory but it's ok.

> As far as I know, I'm the first one to do this.  There was barely any
> support for it.  For example, the winsock stuff was defined only for
> WIN32.  It's a big patch.
>

???
are you sure ?? Do you know WIN32 is defined even for win64 ??

> What follows are some notes on what I did in case it helps anyone else.
>
> Win64 is an LLP64 architecture, whereas Linux uses LP64.  The major
> difference is that a Win64 long integer is still 32 bits while a Linux
> long is 64 bits  (cf.
> http://www.ibm.com/developerworks/library/l-port64.html and
> http://www.unix.org/version2/whatsnew/lp64_wp.html).  size_t can hold the
> maximum difference between two pointers.  In Linux, size_t is the same as
> an unsigned long.  In Win64 there's no standard type equivalent to size_t.
>

intptr_t perhaps or something like that. There is also TDS_INTPTR !

>
> There's an inherent tension in the C standard library between integers and
> sizes.  For example, strlen(3) returns size_t and sprintf(3) returns int.
> To be meaninful, the values being compared have to fit within both
> datatype's domains (which typically they do, but the compiler can't know
> that and the handling of the atypical case will likely hurt). .
>
> To squelch the warnings, we add a cast.  To be safe, that cast really
> should be inside a conversion function that uses assert(3) to verify the
> size_t values fits in 31 bits.  I didn't do that, but it would be IMO a
> worthwhile exercise.
>
> Simlilarly, libtds plays fast and loose with int and unsigned int.  Most
> of the time it's really OK: how often will a column name length need more
> than 2^31 bits?  I find myself wondering if we shouldn't have a function
> strleni() that returns an int after checking the size.  .
>
> Another way to handle this would be to make widespread use of a union,
>
>        typedef union tds_length {
>                unsigned long  ulong;
>                size_t  size;
>                int     len;
>        } TDS_LENGTH;
>
> and use checking functions (or macros)
>
>        size_t
>        as_size( TDS_LENGTH L )
>        {
>                assert(L.len > 0);
>                return L.size;
>        }
>
>        int
>        as_int( TDS_LENGTH L )
>        {
>                assert(L.size <= INT_MAX);
>                return L.len;
>        }
>
>        unsigned long
>        as_ulong( TDS_LENGTH L )
>        {
>                assert(L.len > 0);
>                return L.ulong;
>        }
>
> to write such code as
>
>        TDS_LENGTH a;
>        a.len = sprintf(...);
>        if( as_size(a) != strlen(...) )
>                return FAIL;
>

it can't work !!! Think about endianess !!!

> That would constrain TDS_LENGTH to use values <= 2^31 is most cases.  The
> functions *assume* you're using the structure for type-punning.  Short of
> C++'s operator overloading, there's no easy way to check.
>
> There are many places in libtds particularly where int is used where
> size_t would have been more in keeping with the standard library.  (I'm as
> guilty as anyone else; old habits are hard to break.)  Often, the type is
> chosen to match a corresponding part of the TDS data strea, e.g.
> TDSRESULTINFO::row_size is TDS_INT because that's how column widths are
> defined in the TDS_ROWFMT2 packet.  (But it's not used that way in
> practice.  tds_alloc_row() defines its local row_size as TDS_UINT,
> accumulates the sizes of the columns, and assigns the sum to
> TDSRESULTINFO::row_size.  It would have been better to use size_t after
> all.)
>

Ok, size_t is correct, however see how packet is readed from network
and how row is allocated. Column number is a 16 bit so there can be at
maximun 2^16 = 65536 columns so each column can contains up to 2^31 /
2^16 = 2^15. Considering that BLOBs occupy just few bytes and variable
columns occupy at maximun 8000 bytes... there is no limit... 31 bits
are sufficient for every rowset.

> I think it would be better to use standard C types within the library and
> as much as possible reserve casts to deal with TDS packets or API calls.
> I wonder what others have done.  It's not an easy question to research.
>

Personally I think this patch it too big and contains a lot of changes
grouped in a single one:
- new defines for sybdb.h just to make some windows programs happy...
nothing related to win64
- use of newer _fseeki64 which break compatibility with old VS and even mingw
- changed inclusion styles. Are you sure that client programs works as
expected ??
- a lot of warning removed just adding casts
- added a log and a strange string copy in tds_put_login_string (with
a possible buffer overflow... I'll check it)
- winsocket initialization (why in mem.c and not in net.c ??)
- other minor styles changes

freddy77
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.