Article View: comp.windows.ms.programmer
Article #1583About strings in windows (long, with some code)
From: Risto Lankinen
Date: Fri, 08 Mar 1991 08:55
Date: Fri, 08 Mar 1991 08:55
231 lines
10119 bytes
10119 bytes
poffen@sj.ate.slb.com (Russ Poffenberger) writes:
>In article <1991Mar3.194444.26873@javelin.es.com> lwallace@javelin.es.com (Lynn Wallace) writes:
>>I've found that many of the string functions~ don't work in Windows, ...
>There are windows specific versions of most of those types of functions. ...
Hi!
There's a limited subset of C run-time functions, which don't need any static
variables or initialized data in program's DGROUP . With just a few except-
ions, the string & memory manipulation functions fall into this category.
There's also a way to make these functions into a 'C run-time DLL' by compil-
ing the following:
(Note: Microsoft C 6.00 & Seg.Exec. Linker 5.10 are essential!)
*** CCALLS.MAK ***
CCALLS.OBJ: CCALLS.C
CL -c -ASw -Gcsw -Ocegilswz -Zcelp CCALLS.C
CCALLS.DLL: CCALLS.DEF CCALLS.OBJ
LINK/A:16/NOD/NOE CCALLS LIBENTRY,CCALLS.DLL,NUL,LDLLCAW LIBW,CCALLS;
RC CCALLS.DLL
CCALLS.LIB: CCALLS.DLL
IMPLIB CCALLS.LIB CCALLS.DLL
*** CCALLS.C ***
#include <windows.h>
int FAR PASCAL LibMain( HANDLE hInst,HANDLE hDSeg,WORD nHeapSz,LPSTR lpCmdLn )
{ return TRUE; }
BOOL FAR PASCAL WEP( WORD wParam )
{ return TRUE; }
*** CCALLS.H ***
// Declarations for intrinsic versions of C runtime functions:
#pragma intrinsic( abs,labs )
#pragma intrinsic( _disable,_enable )
#pragma intrinsic( inp,inpw,outp,outpw )
#pragma intrinsic( _lrotl,_lrotr,_rotl,_rotr )
#pragma intrinsic( memcmp,memcpy,memset )
#pragma intrinsic( strcat,strcmp,strcpy,strlen,strset )
// Declarations for DLL'ed C run-time functions:
typedef struct { int quot; int rem; } div_t;
int FAR _cdecl atoi( LPSTR );
long FAR _cdecl atol( LPSTR );
int FAR _cdecl bdos( int,WORD,WORD );
LPSTR FAR _cdecl bsearch( LPSTR,LPSTR,WORD,WORD,\
int(FAR _cdecl *)(LPSTR,LPSTR) );
div_t FAR _cdecl div( int,int );
int FAR _cdecl getpid( void );
LPSTR FAR _cdecl itoa( int,LPSTR,int );
LPSTR FAR _cdecl lfind( LPSTR,LPSTR,WORD,WORD,\
int(FAR _cdecl *)(LPSTR,LPSTR) );
LPSTR FAR _cdecl lsearch( LPSTR,LPSTR,WORD,WORD,\
int(FAR _cdecl *)(LPSTR,LPSTR) );
LPSTR FAR _cdecl ltoa( long,LPSTR,int );
LPSTR FAR _cdecl memccpy( LPSTR,LPSTR,int,WORD );
LPSTR FAR _cdecl memchr( LPSTR,WORD,WORD );
int FAR _cdecl memicmp( LPSTR,LPSTR,WORD );
LPSTR FAR _cdecl memmove( LPSTR,LPSTR,WORD );
void FAR _cdecl movedata( WORD,WORD,WORD,WORD,WORD );
LPSTR FAR _cdecl strchr( LPSTR,int );
int FAR _cdecl strcoll( LPSTR,LPSTR );
WORD FAR _cdecl strcspn( LPSTR,LPSTR );
int FAR _cdecl strcmpi( LPSTR,LPSTR );
int FAR _cdecl stricmp( LPSTR,LPSTR );
LPSTR FAR _cdecl strlwr( LPSTR );
LPSTR FAR _cdecl strncat( LPSTR,LPSTR,WORD );
int FAR _cdecl strncmp( LPSTR,LPSTR,WORD );
LPSTR FAR _cdecl strncpy( LPSTR,LPSTR,WORD );
int FAR _cdecl strnicmp( LPSTR,LPSTR,WORD );
LPSTR FAR _cdecl strnset( LPSTR,int,WORD );
LPSTR FAR _cdecl strpbrk( LPSTR,LPSTR );
LPSTR FAR _cdecl strrchr( LPSTR,int );
LPSTR FAR _cdecl strrev( LPSTR );
WORD FAR _cdecl strspn( LPSTR,LPSTR );
LPSTR FAR _cdecl strstr( LPSTR LPSTR );
LPSTR FAR _cdecl strupr( LPSTR );
WORD FAR _cdecl strxfrm( LPSTR,LPSTR,WORD );
void FAR _cdecl swab( LPSTR,LPSTR,int );
LPSTR FAR _cdecl ultoa( DWORD,LPSTR,int );
LPSTR FAR _cdecl _strdate( LPSTR );
LPSTR FAR _cdecl _strtime( LPSTR );
*** CCALLS.DEF ***
LIBRARY CCALLS
DESCRIPTION 'Partial C run-time function DLL for Windows.'
EXETYPE WINDOWS
CODE PRELOAD MOVEABLE DISCARDABLE SHARED EXECUTEREAD
DATA PRELOAD MOVEABLE SINGLE READWRITE
EXPORTS WEP @1 RESIDENTNAME
_atoi @10 NODATA
_atol @11 NODATA
_bdos @12 NODATA
_bsearch @13 NODATA
_div @14 NODATA
_getpid @15 NODATA
_itoa @16 NODATA
_lfind @17 NODATA
_lsearch @18 NODATA
_ltoa @19 NODATA
_memccpy @20 NODATA
_memchr @21 NODATA
_memicmp @22 NODATA
_memmove @23 NODATA
_movedata @24 NODATA
_strchr @25 NODATA
_strcoll @26 NODATA
_strcspn @27 NODATA
_strcmpi @28 NODATA
_stricmp @29 NODATA
_strlwr @30 NODATA
_strncat @31 NODATA
_strncmp @32 NODATA
_strncpy @33 NODATA
_strnicmp @34 NODATA
_strnset @35 NODATA
_strpbrk @36 NODATA
_strrchr @37 NODATA
_strrev @38 NODATA
_strspn @39 NODATA
_strstr @40 NODATA
_strupr @41 NODATA
_strxfrm @42 NODATA
_swab @43 NODATA
_ultoa @44 NODATA
__strdate @45 NODATA
__strtime @46 NODATA
*** End of CCALLS files ***
When you run the 'MAKE CCALLS.MAK', you'll get two files: CCALLS.DLL and
CCALLS.LIB . Subsequently, you will use '#include <ccalls.h>' in your
application program and at least 'CL -Oi' with the C-compiler (to enable
the intrinsic functions). Finally, at the linking phase, you *MUST* use
libraries 'xNOCRT LIBW CCALLS' (optionally followed with 'xLIBCyW', if
your program makes use of any of the '*','/' or '%' with at least one
DWORD operand). In any other sense, you should be able to use the calls
as you would from any ordinary C program (making sure the CCALLS.DLL is
located in a dictionary pointed to by the 'PATH=').
Failing to use 'xNOCRT' (and using 'xLIBCyW') may make the additionally
used C run-time functions refer to the FAR calls in DLL, when they actually
expect to see a memory-model dependend version, resulting an UAE.
*** EXAMPLE.C ***
#include <windows.h>
#define _WINDOWS
#include <ccalls.h>
...
char strBuffer[256]; int iNumber;
// Simulate nonexistent 'WriteProfileInt()':
WriteProfileString( ... ,itoa(iNumber,strBuffer,10), ... );
*** EXAMPLE.MAK ***
...
CL -c -AS -Gsw -Ois -Zp ...
LINK/A:16/NOD/NOE, ... ,SNOCRT LIBW CCALLS, ...
*** End of example ***
A few words of explanation may be justified:
As told above, these functions don't access their (nonexistent) 'default'
data segment. Instead, they only use the data areas pointed to by their
arguments, or use their arguments as values. In either case, they only
need to access the stack.
The DLLs in Windows are using the caller's stack, but their own data seg.
Now, if a DLL function doesn't use any static data, it can be defined with
'NODATA' attribute. To Windows, this means that there's no need to protect
any data segment from memory movement, and therefore there's no need for
the Windows' entry & exit code in procedures (there's no protection for code
segment, either, and therefore such a function must not call other Windows'
functions itself - but C run-time functions fortunately don't).
See also, that the DLL entry routine CCALLS.C is compiled with -ASw, but
it is linked to LLIBCyW (large model). This, together with the proper
declarations in CCALLS.H, provide the run-time functions an access to
the segment where the actual argument(s) is (are) in. Otherwise, they'd
use whatever segment the DS points to at the time of call, which would
work often, but not nearly always (moving to GlobalAlloc()ed memory, for
instance). Another reason to use the large model library is, that Windows
requires any DLL function being called as FAR . Their _cdecl nature does
not change, however, which is taken into account in the declarations.
I've gone thru all the functions that don't use their default DGROUP, but
some of the functions *may* require a special initialization call, which
this DLL doesn't execute. In particular, I think it would be safest not
to use the function _bdos() even though it's been included. Also, the
_getpid() makes use of Windows' GetCurrentTask(), which is a bit risky,
because the control is at Windows, but the DLL code segment has not been
protected against moving.
One more word of recommendation: A number of the functions have a Windows
counterpart, so basically you should use them. However, the strcpy() for
instance has an even more optimal form of an intrinsic function, which you
may prefer instead. The intrinsic functions can even be used by themselves
without accessing the CCALLS.DLL at all (ie. using only the #pragma:s of the
definition file - the C compiler 'knows' their declarations internally).
***
Disclaimer: Problems arising from actually making use of the information
in this article is assumed to be entirely at the user's own risk.
***
Terveisin: Risto Lankinen
--
Risto Lankinen / product specialist ***************************************
Nokia Data Systems, Technology Dept * 2 2 *
THIS SPACE INTENTIONALLY LEFT BLANK * 2 -1 is PRIME! Now working on 2 +1 *
replies: risto@yj.data.nokia.fi ***************************************
Technical Details
Message-ID:
<1057@tuura.UUCP>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!uwm.edu!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!yale!cmcl2!uupsi!sunic!news.funet.fi!fuug!tuura!ristoReferences:
<1991Mar3.194444.26873@javelin.es.com> <1991Mar6.004213.2305@sj.ate.slb.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!uwm.edu!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!yale!cmcl2!uupsi!sunic!news.funet.fi!fuug!tuura!risto From: risto@tuura.UUCP (Risto Lankinen) Newsgroups: comp.windows.ms.programmer Subject: About strings in windows (long, with some code) Message-ID: <1057@tuura.UUCP> Date: 8 Mar 91 08:55:55 GMT References: <1991Mar3.194444.26873@javelin.es.com> <1991Mar6.004213.2305@sj.ate.slb.com> Organization: Nokia Data Systems Oy Lines: 231