Xref: utzoo comp.lang.c:15806 comp.sys.ibm.pc:23796 Path: utzoo!attcan!uunet!smsdpg!seg From: seg@smsdpg.uu.net (Scott Garfinkle) Newsgroups: comp.lang.c,comp.sys.ibm.pc Subject: Re: Microsoft C 5.1 question Message-ID: <189@smsdpg.uu.net> Date: 26 Jan 89 19:11:44 GMT References: <617@uceng.UC.EDU> Organization: SMS Data Products Group, Reston VA Lines: 79 From article <617@uceng.UC.EDU>, by mfinegan@uceng.UC.EDU (michael k finegan): > What I am trying to do is put an address into a far data pointer > (unsigned char far * ptr), which works okay at first, but when the global > pointer gets accessed in a subroutine, low and behold - it is different! It > appears that the high order word is zeroed out ... My question: has anyone out > there in net land put addresses into far pointers in medium model with success? > Is there a trick? No. I've done it. It works. It's just a real pain. Following code to set an arbitrary string in the DOS environment works in all models: Scott E. Garfinkle SMS Data Products Group, Inc. uunet!smsdpg!seg (seg@smsdpg.uu.net) ---------- /* Demo of how to set a string in parent environment. * By Scott E. Garfinkle -- No rights reserved, no responsibility assumed. * * This program can be very unhealthy for your environment. In particular, * it does not do the following: * 1. Check for theoretically illegal characters, like '=' in the * environment. * 2. Remove old definitions that you're redefining. * 3. Check to see if you've hit the limit of the environment size. * 4. Force the new variable into uppercase. * Some of the above aren't bugs, depending on your point of view. If you * don't like something, change it. */ #include extern unsigned _psp; /* set to segment of our psp by MSC init routines */ /* from dos.h */ #define FP_SEG(fp) (*((unsigned *)&(fp) + 1)) #define FP_OFF(fp) (*((unsigned *)&(fp))) main(int argc, char **argv) { char far *env_ptr; int count; unsigned far *psp_ptr; extern char *getenv(const char *); if(argc != 3) { fprintf(stderr,"Usage: %s \n", *argv); exit(1); } psp_ptr = (unsigned far *) (((long) _psp << 16 ) + 0x16L); /* now psp_ptr points to DOS PSP segment */ psp_ptr = (unsigned far *) (((long) *psp_ptr << 16 ) + 0x2cL); /* now psp_ptr points to DOS environ segment */ env_ptr = (char far *) ((long) *psp_ptr << 16 ); /* now env_ptr points to DOS environ */ while(*env_ptr) /* skip past the current strings */ env_ptr += strlen(env_ptr)+1; /* usually, sprintf returns number of characters written, excluding * the null. This is true, e.g. for msc. */ #ifndef SPRINTF_RETURNS_CHAR { int count; char buffer[512]; /* arbitrary */ count = sprintf(buffer,"%s=%s",argv[1],argv[2]); movedata( /* of course microsoft does this backwards */ (unsigned) (( (long) (char far *) buffer) >> 16), /* yech */ (unsigned) buffer, FP_SEG(env_ptr), FP_OFF(env_ptr), ++count ); env_ptr[count] = '\0'; } #else (void) sprintf(env_ptr,"%s=%s",argv[1],argv[2]); env_ptr[strlen(env_ptr)+1] = '\0'; /* need two nulls to terminate env */ #endif exit(0); }