home *** CD-ROM | disk | FTP | other *** search
- /* SKELETON.C -- THE PROTOTYPE APPLICATION FOR THE OXBOW FRAMEWORK
- COMPILE WITH GCC
-
- COPYRIGHT 1994 Norman D. Culver, Ft. Lauderdale, FL
-
- NOTE: 'main()' is at the end of the file.
- */
- #define SYMLINK(from,to) badsyms += oxlink_symlink(#from,#to)
-
- #define EARLY_PRINT 1 /* set to 1 if trace before linkup needed */
-
- #define BASE_CATEGORY 0
- #define MEMORY_BUG 0
- #define PRINT_RAWDATA 0
-
- #if 0
- #define DPRINTF lprintf
- #else
- #define DPRINTF(args...)
- #endif
-
- #if 0
- #define MPRINTF lprintf
- #else
- #define MPRINTF(args...)
- #endif
-
- #if EARLY_PRINT == 1
- #define TPRINTF lprintf
- #else
- #define TPRINTF VPRINTF
- #endif
-
- #include <go32.h>
-
- /* extracts from 'oxbow.h' */
- typedef unsigned long long KeyItem; /* type for a key's associated item */
-
- typedef union /* 2 BYTES */
- {
- unsigned short val;
- unsigned char b[2];
- } SVAL;
-
- typedef union /* 4 BYTES */
- {
- unsigned long a0;
- void *a1;
- struct
- {
- SVAL lo_word;
- SVAL hi_word;
- } a2;
- struct
- {
- unsigned int pad :28;
- unsigned int type :4;
- } a3;
- struct
- {
- unsigned char b[4];
- } a4;
- int a8;
- short a9;
- char a10;
- float a11;
- } ADDR;
-
- typedef union _stor /* 8 BYTES */
- {
- unsigned long a0;
- void *a1;
- KeyItem item;
- struct
- {
- unsigned short lo_word;
- unsigned short hi_word;
- unsigned int size :28; /* in bytes or nibbles */
- unsigned int type :4; /* describes the STOR type */
- } a2;
- struct
- {
- short s0;
- short s1;
- short s2;
- short s3;
- } a3;
- struct
- {
- unsigned long s0;
- unsigned long s1;
- } a4;
- struct
- {
- unsigned char b[8];
- } a5;
- struct
- {
- unsigned long long dupname :48;
- unsigned long long dupid :16;
- } a6;
- struct
- {
- unsigned int home : 30;
- unsigned int full : 2;
- } a7;
- int a8;
- short a9;
- char a10;
- float a11;
- double a12;
- } STOR, Item;
-
- typedef struct /* 12 BYTES */
- {
- STOR c0;
- ADDR c1;
- } CAT;
-
- #define OB_XFILE (0x00004000)
- #define OB_ROOTDIR (0x00000200)
- #define OB_TREEDIR (0x10000000)
- #define OB_HASHDIR (0x20000000)
- #define F_RDONLY (0x0001)
- #define F_STAT (0x20000) /* TRULY READONLY */
- #define O_RDONLY (0x0001)
- #define O_BINARY (0x8000)
- #define R_CLEAN (0x40000000)
- #undef NULL
- #define NULL ((void *)0)
- #define FOUND (1)
- #define NODUPS (0)
- #define S_SET (0)
- #define S_READBLK (1)
- #define S_WRITEBLK (2)
-
- #define _cat2_(a, b) a##b
- #define _cat_(a, b) _cat2_(a, b)
- #define _qt2_(x) #x
- #define _qt_(x) _qt2_(x)
-
- #define oxfunc(func, args...) ({ \
- typedef _fret = (appfunc()); \
- _fret (*dofunc)(); _fret _ret; \
- dofunc = oxlink_load_bare_symb(func,1); \
- if(dofunc) _ret = dofunc(## args) & 0x0fffffff; \
- else _ret = (_fret) -1; \
- _ret;})
-
- #define oxload(func) \
- oxlink_load_bare_symb(_qt_(_cat_(_, func)),1)
-
- #define oxunload(func) \
- oxlink_unload_symb(#func, 1)
-
- typedef int jmp_buf[32]; /* an adequate buffer for setjmp */
- int setjmp();
- void longjmp();
-
- /* end: extracts from 'oxbow.h' */
- /* ==================== A LIST OF PROBLEMS ======================= */
- /* external function prototypes needed initially,
- THESE NEED TO BE LOCALIZED */
- void *sbrk();
- int open();
- int creat();
- int close();
- int read();
- int write();
- int lseek();
- char *getenv();
- char *getwd();
-
- int strlen();
- char *strdup();
- char *strcat();
- char *strcpy();
- char *strchr();
- char *strrchr();
- char *strstr();
- int _strcpy();
- long strtol();
- int strcmp(const char *, const char *);
- int strncmp();
- void CF_Interactive_IO();
- int appfunc();
- void *malloc(unsigned);
- void *calloc(unsigned, unsigned);
- void free(void*);
- void *memcpy();
-
- /* external function prototypes needed by the portability modules
- THESE TOO NEED TO BE LOCALIZED (or something) */
- void exit();
- int ftruncate();
- void abort();
-
- /* internal function prototypes */
- static int lnulfunc();
- static void lhash(void *, int, CAT *);
- static int laccess(char *, int);
- static int lpagesize(void);
- static int lprintchar(int);
- static void lprintstr(char *);
- static void lcrash(char *, ...);
- void CF_InitIO(long arg, long long (*msgproc)());
-
- /* ======================== END LIST OF PROBLEMS ==================== */
-
- /* DYNAMIC LINKER FUNCTIONS */
- int oxlink_init (); /* initialize the routines */
- int oxlink_load_file (); /* dynamically link and load an object file */
- int oxlink_load_object (); /* link object file from libraries in list */
- void *oxlink_find_func (); /* return the address of the named function */
- void *oxlink_find_bare_func ();/* same as oxlink_find_func except that
- no underscore (_) is prepended (also faster). */
- void * oxlink_find_sym (); /* return the address of the named identifier */
- void *oxlink_find_bare_symb ();/* same as oxlink_find_symb except that
- no underscore (_) is prepended (also faster). */
- int oxlink_unload_file (); /* unlink a file */
- int oxlink_unload_symb (); /* unlink the module that defines the given symbol */
- int oxlink_unload_bare_symb (); /* unlink the module that defines the given symbol */
- char **oxlink_list_undefined_symb ();/* return an array of undefined symbols */
- char *cf_find_file ();/* return the full path name of the given file. */
- void *oxlink_load_symb(char *symb, int dynlink);
- void *oxlink_load_bare_symb(char *symb, int dynlink);
- int oxlink_export_symb();
- int oxlink_export_bare_symb();
- void oxlink_unexport_symb();
- void oxlink_unexport_bare_symb();
- int oxlink_symlink(); /* give new symbol same values as old symbol */
- void oxlink_demand_load(); /* define all undefined symbols with negative numbers */
- void oxlink_use_library(); /* add a filename for undefined symbol search */
- void oxlink_nouse_library(); /* remove a library from the search list */
- void *oxlink_resolve_symb(); /* resolve one of the demand loadable undefs */
- void oxlink_trace(); /* set the trace level */
- char *oxlink_symname(); /* return name of a demand loadable undef */
- void *oxlink_rename_symb(char *old,char *new);
- int oxlink_rename_file(char *old,char *new);
- void oxlink_lib_check(int dynlink); /* force search of library list */
- char *oxlink_file_of(char *symb);
- char *oxlink_file_of_bare(char *symb);
- int oxlink_scan_file(void *fhandle, void *thandle);
- void oxlink_set_libtype(int type);
- void oxlink_set_libnum(int libnum);
- void oxlink_load_thunk(int thunknum);
- int oxlink_prep_thunk(char *symb);
- void oxlink_clear_bss(char *filename);
- void *oxlink_get_entry_struct(char *filename);
- char *oxlink_errstr(void);
-
- /* virtual function pointers initially hard linked to the load module */
- /* needed in order to initialize and read a .o or .a file */
- int (*VCFREAD)() = read;
- int (*VCFWRITE)() = write;
- void *(*VCFOPEN)() = (void *)open;
- int (*VCFCLOSE)() = close;
- int (*VCFLSEEK)() = lseek;
- int (*VACCESS)() = laccess;
- void *(*VSBRK)() = sbrk;
- char *(*VGETENV)() = getenv;
- char *(*VGETCWD)() = getwd;
- int (*VOBTYPE)() = lnulfunc;
-
- void (*VHASH)() = lhash;
- int (*VGETPAGESIZE)() = lpagesize;
-
-
- #if EARLY_PRINT == 0
- int (*VVPRINTF)() = lnulfunc;
- int (*VSPRINTF)() = lnulfunc;
- int (*VPRINTF)() = lnulfunc;
- int (*BUGPRINTF)() = lnulfunc;
- #else
- static int lvprintf(char *, void *);
- static int lsprintf(char *, char *, ...);
- static int lprintf(char *, ...);
- int (*VVPRINTF)(char *, void*) = lvprintf;
- int (*VSPRINTF)(char *, char *, ...) = lsprintf;
- int (*VPRINTF)(char *, ...) = lprintf;
- int (*BUGPRINTF)(char *, ...) = lprintf;
- #endif
-
- /* function pointers needed by portability modules */
- void *(*VMALLOC)() = malloc;
- void *(*VCALLOC)() = calloc;
- void (*VFREE)() = free;
- void (*VEXIT)() = exit;
- int (*VREAD)() = read;
- int (*VOPEN)() = open;
- int (*VCLOSE)() = close;
- int (*VLSEEK)() = lseek;
- int (*VWRITE)() = write;
- void (*VABORT)() = abort;
- int (*VPRINTCHAR)() = lprintchar;
- void (*VPRINTSTR)() = lprintstr;
- void (*VCRASH)(char* fmt, ...) = lcrash;
- void (*VBITBLT)();
- int (*VSTAT)() = lnulfunc;
-
- /* function pointers used internally */
- int (*CFINIT)();
- void (*CFEXIT)();
- int (*COSINIT)();
- void (*THREADER)();
- void (*THREAD)();
- int *VINHIBIT_THREADER;
-
- /* cff function pointers used but not available until cff is loaded */
- int (*VPUSH_VALUE)();
- int (*VPUSH_DATA)();
- int (*VFIND)();
- int (*VGET)();
- void *(*VSUBOPEN)();
- int (*VPUT)();
- int (*VFILESIZE)();
- void *(*VOPEN_CHUNK)();
- void *(*VLOCALIZE)();
- int (*VRELEASE)();
- void **VMEMTEMP;
-
- /* function pointers used by the COS threader but not available until
- the message class is loaded */
- int (*VWASMSG)() = lnulfunc;
- int (*VDISPATCHMSG)() = lnulfunc;
-
-
- /* Global variables, here to suppress re-linking */
- long long (*VAPPMSG)();
- void *Application;
- int numTextModes;
- int numGraphicModes;
- void *TextModes;
- void *GraphicModes;
- int GuiEnabled;
- int _SCREENXMAX;
- int _SCREENYMAX;
- int _REMOTEFD;
- int _SCREENHEIGHT;
- int _EFFECTIVE_SCREENHEIGHT;
- int _SCREENWIDTH;
- int _EFFECTIVE_SCREENWIDTH;
- int _GLOBALWIDTH;
- int _GLOBALHEIGHT;
- int _CURCOLS;
- int _CURROWS;
- int _FONTWIDTH;
- int _FONTHEIGHT;
- int _CHARWIDTH;
- int _LINEHEIGHT;
- int _GRIDWIDTH;
- int _GRIDHEIGHT;
- int _GLOBALX;
- int _GLOBALY;
- int _MAXROWS;
- int _MAXCOLS;
- int _VIDEOMODE;
- int _LOOK;
- int _FEEL;
-
- /* variables needed by the cos threader */
- int _no_context_switch = 1;
- jmp_buf _t_start;
-
- /* application initializer word */
- long AppArg;
-
- /* flag used to force early symbols to be permanent */
- static int permanent_symbols;
- static char path_sep;
-
- /* ================ START OF INTERNAL SUPPORT FUNCTIONS ============ */
-
- /* ========================= MULTI HEAP MALLOC ========================== */
- /*
- NOTE: In a demand paged environment, this implementation of malloc
- (using skip_lists) can be ENORMOUSLY faster than buddy_block
- style mallocs.
- */
- void *mallocC(int category, unsigned amount);
- void *callocC(int category, unsigned nelems, unsigned elemsize);
- void *reallocC(int category, void* buf, unsigned newsize);
- void freeC(int category, void* buf);
- void freecat(int category);
- int memrangeC(int category, unsigned* minp, unsigned* maxp);
- int usedrangeC(int category, unsigned* minp, unsigned* maxp);
- void totrangeC(unsigned* minp,unsigned* maxp);
- void *heapcheckC(int category, void *start);
- void guardC(int category);
- void *memalignC(int category, unsigned alignment, unsigned req);
-
- #define PAGESIZE VGETPAGESIZE()
- #define ALIGNMENTM (sizeof(unsigned long))
- #define MAL_MAXLEVEL (12)
- #define ROUNDINGM(a) ((ALIGNMENTM-(a&(ALIGNMENTM-1)))&(ALIGNMENTM-1))
- #define ALLOCSIZE (4096)
- #define FRNTGUARD (0x544e5246UL)
- #define BACKGUARD (0x48434142UL)
- #define THEWELL do_sbrk
-
- #define NUMTYPES 3
- #define SIZEH 0
- #define FREEH 1
- #define USEDH 2
-
- #define SKIPVARS NodePM update[MAL_MAXLEVEL+1];NodePM node,prev;int level
-
- #define DELETENODE(TYPE) \
- {for(level=0;level<=bp->TYPE##level; level++)\
- {if(update[level]->fptr[level] == node)\
- update[level]->fptr[level] = node->fptr[level];else break;}\
- while(bp->TYPE##level>0 && bp->TYPE##header->fptr[bp->TYPE##level]==_NILLL)\
- bp->TYPE##level--;free_Mnode(bp,node,TYPE);}
-
- #define INSERT() \
- {while(level >= 0){\
- node->fptr[level] = update[level]->fptr[level];\
- update[level]->fptr[level] = node;level--;}}
-
- #define SETLEVEL(TYPE) \
- {level = getMlevel(bp, bp->TYPE##level);\
- while(bp->TYPE##level < level)update[++bp->TYPE##level]=bp->TYPE##header;}
-
- #define FINDKEY(TYPE, KEYVAL)\
- {node = bp->TYPE##header;\
- for(level = bp->TYPE##level; level >= 0; level--){\
- while(node->fptr[level]->key < KEYVAL)\
- node = node->fptr[level];\
- update[level] = node;}prev=node;node=node->fptr[0];}
-
- #define DETACH(SN)\
- {SN->bptr->fptr=SN->fptr;if(SN->fptr)SN->fptr->bptr=SN->bptr;}
-
- #define UNLINK(SN, N)\
- {if(!sp->fptr&&sp->bptr->bptr<=(AddrP)(MAL_MAXLEVEL+1))dsize[N]=sp->size;\
- DETACH(SN);free_addr(bp,SN);}
-
- #define CHECKGUARDS(MSG)\
- {if(bp->guarded){\
- unsigned *p2;\
- p2 = (void*)((char*)address+cursize-ALIGNMENTM);\
- if(*address != FRNTGUARD)\
- VCRASH(#MSG ":%d: corrupted at 0x%x\n", bp->bincat, addr);\
- if(*p2 != BACKGUARD)\
- VCRASH(#MSG ":%d: corrupted by 0x%x\n", bp->bincat, addr);}}
-
- #if MEMORY_BUG == 1
- #define HEAPCHECK \
- {void *lastaddr;\
- if(category > 0){\
- guardC(category);\
- if((lastaddr = heapcheckC(category, NULL))){\
- FINDKEY(USEDH, (unsigned)lastaddr-ALIGNMENTM)\
- BUGPRINTF("bad heap at %x c:%u size=%u\n", lastaddr, category, node->value);\
- (void)print_rawdata(lastaddr-ALIGNMENTM, node->value);\
- VABORT();}}}
- #else
- #define HEAPCHECK
- #endif
-
- struct _catlocs {
- void *addr;
- struct _catlocs *fptr;
- };
-
- typedef struct _nodeM
- {
- unsigned key;
- unsigned value;
- unsigned levels; /* must always be after value */
- struct _nodeM *fptr[1];
- } NodeM, *NodePM;
-
- typedef struct _addr
- {
- struct _addr *fptr;
- struct _addr *bptr;
- NodePM maddr;
- unsigned size;
- } *AddrP;
-
- struct _bins {
- unsigned bits;
- unsigned nbits;
- NodePM SIZEHheader;
- int SIZEHlevel;
- NodePM FREEHheader;
- int FREEHlevel;
- NodePM USEDHheader;
- int USEDHlevel;
-
- unsigned bincat;
- unsigned maxloc;
- unsigned minloc;
- struct _catlocs *catlocs;
- struct _bins *fptr;
- NodePM freenodes[NUMTYPES][MAL_MAXLEVEL+2];
- struct _addr *freeaddrlocs;
- char *chunkbase[NUMTYPES];
- int chunksize[NUMTYPES];
- int guarded;
- int addrbump;
- };
-
- static struct _bins zbp;
- static struct _bins *hmap[1009];
- static struct _nodeM _nilll = {0xffffffff,0,0,{0}};
- static struct _nodeM *_NILLL = &_nilll;
- static unsigned maxloc;
- static unsigned minloc;
- static struct _bins *freebinlocs;
- static struct _catlocs *freecatlocs;
- static char *binbase;
- static int binsize;
- static int chunksizes[] = {ALLOCSIZE,3*ALLOCSIZE,2*ALLOCSIZE};
-
-
- static long randtbl[32] = { 0L,
- 0x9a319039L, 0x32d9c024L, 0x9b663182L, 0x5da1f342L,
- 0xde3b81e0L, 0xdf0a6fb5L, 0xf103bc02L, 0x48f340fbL,
- 0x7449e56bL, 0xbeb1dbb0L, 0xab5c5918L, 0x946554fdL,
- 0x8c2e680fL, 0xeb3d799fL, 0xb11ee0b7L, 0x2d436b86L,
- 0xda672e2aL, 0x1588ca88L, 0xe369735dL, 0x904f35f7L,
- 0xd7158fd6L, 0x6fa6f051L, 0x616e6b96L, 0xac94efdcL,
- 0x36413f93L, 0xc622c298L, 0xf5a42ab8L, 0x8a88d77bL,
- 0xf5ad9d0eL, 0x8999220bL, 0x27fb47b9L
- };
-
- static long *fptr = &randtbl[4];
- static long *rptr = &randtbl[1];
-
-
- /* ================== THE CRASH FUNCTION IS FIRST IN .TEXT ================ */
- static void
- lcrash(char *msg, ...)
- {
- VVPRINTF(msg, &msg+1);
- /* CFEXIT();*/
- *((char *)0) = 0; /* force exception */
- }
- #if PRINT_RAWDATA == 1
- static char
- hexbyte(unsigned int c)
- {
- char x = c & 0xf;
-
- return x + ((x>9) ? 55 : 48);
- }
- static void
- print_rawdata(void *rawdata, long size)
- {
- unsigned long vaddr = 0;
- unsigned char *d = rawdata;
- int i,j;
- char addr[9];
- char hex1[24];
- char hex2[24];
- char side1[9];
- char side2[9];
-
- addr[8] = 0;
- hex1[23] = 0;
- hex2[23] = 0;
- side1[8] = 0;
- side2[8] = 0;
- while(size > 0)
- {
- unsigned long qaddr = vaddr;
- memset(addr, '0', 8);
- memset(hex1, ' ', 23);
- memset(hex2, ' ', 23);
- memset(side1, ' ', 8);
- memset(side2, ' ', 8);
- i = 7;
- while(qaddr)
- {
- addr[i--] = hexbyte(qaddr);
- qaddr >>= 4;
- }
- for(i=0,j=0; i < 8; ++i)
- {
- if(--size >= 0)
- {
- unsigned int c = *d++;
- if(isprint(c))
- side1[i] = c;
- else
- side1[i] = '.';
- hex1[j++] = hexbyte(c>>4);
- hex1[j++] = hexbyte(c);
- ++j;
- }
- else break;
- }
- for(i=0,j=0; i < 8; ++i)
- {
- if(--size >= 0)
- {
- unsigned int c = *d++;
- if(isprint(c))
- side2[i] = c;
- else
- side2[i] = '.';
- hex2[j++] = hexbyte(c>>4);
- hex2[j++] = hexbyte(c);
- ++j;
- }
- else break;
- }
- BUGPRINTF("%s %s%s%s %s%s%s\n",addr,hex1," | ",hex2,side1,"|",side2);
- vaddr += 16;
- }
- }
- #endif
-
- /*
- * Returns a really good 31-bit random number.
- */
- static long
- lrandom()
- {
- long i;
-
- *fptr += *rptr;
- i = (*fptr >> 1) & 0x7fffffffUL;
- if(++fptr > &randtbl[31])
- {
- fptr = &randtbl[1];
- ++rptr;
- }
- else
- {
- if(++rptr > &randtbl[31])
- rptr = &randtbl[1];
- }
- return( i );
- }
-
- static void *
- do_sbrk(unsigned amount)
- {
- void *address;
-
- address = VSBRK(amount); /* OR WHATEVER TO ACCESS THE OPERATING SYSTEM */
- if(address == (void*)-1)
- {
- VCRASH("\nskel: system out of memory, requested %u bytes\n", amount);
- }
- return address;
- }
- static struct _catlocs *
- new_catloc(void)
- {
- struct _catlocs *p;
- if((p=freecatlocs))
- {
- freecatlocs = p->fptr;
- return p;
- }
- if(binsize < sizeof(struct _catlocs))
- {
- binbase = THEWELL(4096);
- binsize = 4096;
- MPRINTF("NEWCATLOC at:%p size=4096\n", binbase);
- }
- binsize -= sizeof(struct _catlocs);
- p = (void*)binbase;
- binbase += sizeof(struct _catlocs);
- return p;
- }
- static void
- free_catloc(struct _catlocs *p)
- {
- p->fptr = freecatlocs;
- freecatlocs = p;
- }
- static void *
- new_chunk(struct _bins *bp, int size, int type)
- {
- char *p;
- if(bp->chunksize[type] < size)
- {
- if(bp->bincat == 0) {
- bp->chunkbase[type] = THEWELL(chunksizes[type]);
- bp->chunksize[type] = chunksizes[type];
- MPRINTF("NEWCHUNK0 at:%p size=%d\n", bp->chunkbase[type], bp->chunksize[type]);
- }
- else {
- struct _catlocs *cl;
- bp->chunkbase[type] = mallocC(0,chunksizes[type]-zbp.guarded);
- bp->chunksize[type] = chunksizes[type]-zbp.guarded;
- cl = new_catloc();
- cl->addr = bp->chunkbase[type];
- cl->fptr = bp->catlocs;
- bp->catlocs = cl;
- MPRINTF("NEWCHUNK%d at:%p size=%d\n", bp->bincat, bp->chunkbase[type], bp->chunksize[type]);
- }
- }
- bp->chunksize[type] -= size;
- p = bp->chunkbase[type];
- bp->chunkbase[type] += size;
- return p;
- }
- static void *
- new_Mnode(struct _bins *bp, int levels, int type)
- {
- int size;
- NodePM p;
-
- if((p=bp->freenodes[type][levels]))
- {
- bp->freenodes[type][levels] = p->fptr[0];
- p->value = 0;
- return p;
- }
- size = sizeof(struct _nodeM) + levels * sizeof(void*);
- p = new_chunk(bp, size, type);
- p->levels = levels;
- p->value = 0;
- return p;
- }
- static void
- free_Mnode(struct _bins *bp, NodePM p, int type)
- {
- p->fptr[0] = bp->freenodes[type][p->levels];
- bp->freenodes[type][p->levels] = p;
- }
- static struct _addr *
- new_addr(struct _bins *bp)
- {
- struct _addr *p;
- if((p=bp->freeaddrlocs))
- {
- bp->freeaddrlocs = p->fptr;
- return p;
- }
- return new_chunk(bp, sizeof(struct _addr), FREEH);
- }
- static void
- free_addr(struct _bins *bp, struct _addr *p)
- {
- p->fptr = bp->freeaddrlocs;
- bp->freeaddrlocs = p;
- }
- static struct _bins *
- new_bins(void)
- {
- struct _bins *p;
- if((p=freebinlocs))
- {
- freebinlocs = p->fptr;
- return p;
- }
- if(binsize < sizeof(struct _bins))
- {
- binbase = THEWELL(4096);
- binsize = 4096;
- MPRINTF("NEWBINS at:%p size=4096\n", binbase);
- }
- binsize -= sizeof(struct _bins);
- p = (struct _bins*)binbase;
- binbase += sizeof(struct _bins);
- return p;
- }
- static void
- free_bins(struct _bins *p)
- {
- p->fptr = freebinlocs;
- freebinlocs = p;
- }
- static int
- getMlevel (struct _bins *p, int binlevel)
- {
- int level = -1;
- int bits = 0;
-
- while(bits == 0)
- {
- if (p->nbits == 0)
- {
- p->bits = lrandom();
- p->nbits = 15;
- }
- bits = p->bits & 3;
- p->bits >>= 2;
- p->nbits--;
-
- if(++level > binlevel)
- break;
- }
- return (level > MAL_MAXLEVEL) ? MAL_MAXLEVEL : level;
- }
-
- static void
- init_bins(struct _bins *bp, int category)
- {
- int i;
- int binnum = category % 1009;
-
- bzero(bp, sizeof(struct _bins));
- bp->bincat = category;
- bp->minloc = 0xffffffff;
- bp->fptr = hmap[binnum];
- hmap[binnum] = bp;
- bp->SIZEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, SIZEH);
- bp->FREEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, FREEH);
- bp->USEDHheader = new_Mnode(bp, MAL_MAXLEVEL+1, USEDH);
-
- for(i = 0; i <= MAL_MAXLEVEL; ++i)
- {
- bp->SIZEHheader->fptr[i] = _NILLL;
- bp->FREEHheader->fptr[i] = _NILLL;
- bp->USEDHheader->fptr[i] = _NILLL;
- }
- }
-
- static struct _bins*
- getcat(int category)
- {
- struct _bins *hbp;
-
- hbp = hmap[category % 1009];
- while(hbp)
- {
- if(hbp->bincat == category)
- return hbp;
- hbp = hbp->fptr;
- }
- return 0;
- }
- static struct _bins *
- initcat(int category)
- {
- struct _bins *bp;
-
- if(category == 0)
- {
- bp = &zbp;
- if(zbp.SIZEHheader == 0)
- init_bins(bp, category);
- return bp;
- }
- /* do this to set zbp.guarded properly on startup */
- if(zbp.SIZEHheader == 0)
- initcat(0);
-
- if((bp = new_bins()))
- {
- init_bins(bp, category);
- return bp;
- }
- return 0;
- }
- static void *
- getspace(struct _bins *bp, unsigned size, unsigned *remainder)
- {
- unsigned desired;
- void *address;
-
- desired = ((size+ALLOCSIZE-1)/ALLOCSIZE)*ALLOCSIZE;
- if(bp->bincat == 0)
- {
- address = THEWELL(desired);
- *remainder = desired - size;
- MPRINTF("GETSPACE at:%p size=%d\n", address, desired);
- }
- else
- {
- struct _catlocs *cl;
-
- if((desired-size) > zbp.guarded)
- desired -= zbp.guarded;
-
- address = mallocC(0, desired);
- *remainder = desired - size;
-
- /* save the gross allocations for the category */
- cl = new_catloc();
- cl->addr = address;
- cl->fptr = bp->catlocs;
- bp->catlocs = cl;
- }
- /* maintain address range info */
- if((unsigned)address < bp->minloc)
- bp->minloc = (unsigned)address;
- if(((unsigned)address + desired) > bp->maxloc)
- bp->maxloc = (unsigned)address + desired;
- if(bp->minloc < minloc)
- minloc = bp->minloc;
- if(bp->maxloc > maxloc)
- maxloc = bp->maxloc;
- return address;
- }
- static void
- addto_sizelist(struct _bins *bp, AddrP ap)
- {
- SKIPVARS;
-
- /* INSERT IN SIZE LIST */
- FINDKEY(SIZEH, ap->size)
-
- if(node->key == ap->size)
- {/* size node exists */
- ap->fptr = (AddrP)node->value;
- ap->bptr = (AddrP)&node->value;
- if(ap->fptr) ap->fptr->bptr = ap;
- node->value = (unsigned)ap;
- }
- else
- {/* create new size node */
- SETLEVEL(SIZEH)
- node = new_Mnode(bp, level, SIZEH);
- node->key = ap->size;
- node->value = (unsigned)ap;
- ap->fptr = 0;
- ap->bptr = (AddrP)&node->value;
- INSERT()
- }
- }
- static void
- addto_freelist(struct _bins *bp, void *addr, unsigned size)
- {
- SKIPVARS;
- AddrP ap,sp;
- unsigned dsize[2];
-
- /* GET NEW ADDR STRUCT */
- ap = new_addr(bp);
- ap->size = size;
-
- dsize[1] = dsize[0] = 0; /* sizenode deletion markers */
-
- /* CHECK FREE LIST */
- FINDKEY(FREEH, (unsigned)addr)
-
- /* CHECK FOR MERGE OR INSERT */
- if(prev->value && prev->key+((AddrP)prev->value)->size == (unsigned)addr)
- {/* merge with previous block */
- ap->size += ((AddrP)prev->value)->size;
-
- if(prev->key + ap->size == node->key)
- {/* merge with previous and next block */
- sp = (AddrP) node->value;;
- ap->size += sp->size;
-
- /* delete size struct for next block */
- UNLINK(sp, 0)
-
- /* delete next block */
- DELETENODE(FREEH);
- }
- /* delete size struct for prev block */
- sp = (AddrP)prev->value;
- UNLINK(sp, 1)
-
- /* set new address struct */
- prev->value = (unsigned)ap;
- ap->maddr = prev;
- }
- else if(node->value && (char*)addr + size == (void*)node->key)
- {/* merge with next block */
- sp = (AddrP) node->value;;
- node->key = (unsigned)addr;
- ap->size += sp->size;
-
- /* unlink size struct for next block */
- UNLINK(sp,0)
-
- /* set new address struct */
- node->value = (unsigned)ap;
- ap->maddr = node;
- }
- else
- {/* insert in free list */
-
- SETLEVEL(FREEH)
- node = new_Mnode(bp, level, FREEH);
- node->key = (unsigned)addr;
- node->value = (unsigned)ap;
- ap->maddr = node;
- INSERT()
- }
- addto_sizelist(bp, ap);
-
- /* Remove sizenodes eliminated by merge */
- if(dsize[0])
- {
- FINDKEY(SIZEH, dsize[0])
- if(node->value == 0)
- DELETENODE(SIZEH)
- }
- if(dsize[1])
- {
- FINDKEY(SIZEH, dsize[1])
- if(node->value == 0)
- DELETENODE(SIZEH)
- }
- }
-
- void*
- memalignC(int category, unsigned alignment, unsigned req)
- {
- SKIPVARS;
- NodePM fnode;
- unsigned remainder;
- unsigned *address;
- struct _bins *bp;
- unsigned mask, size;
-
-
- if(!(bp = getcat(category)))
- if(!(bp = initcat(category)))
- return 0;
- HEAPCHECK
- if(req == 0)
- req = ALIGNMENTM;
- else
- req += ROUNDINGM(req);
- size = req += bp->guarded;
-
- if(alignment)
- {
- alignment += ROUNDINGM(alignment);
- if(alignment > ALIGNMENTM)
- {
- mask = alignment -1;
- size = req + alignment + bp->guarded;
- }
- else
- {
- alignment = 0;
- }
- }
-
- /* check sizelist for candidate */
- FINDKEY(SIZEH, size)
- fnode = node;
- trynext:
- if(node->key != 0xffffffff)
- {/* found an appropriately sized block */
- AddrP sp = (AddrP)node->value;
-
- if(!sp && node == fnode)
- {
- NodePM q;
- q = node->fptr[0];
- DELETENODE(SIZEH)
- node = q;
- goto trynext;
- }
- if(!sp)
- {/* no available space at this size */
- node = node->fptr[0];
- goto trynext;
- }
-
- /* extract some space from this block */
- remainder = node->key - size;
- address = (void*)sp->maddr->key;
- sp->maddr->key += size;
- DETACH(sp);
-
- if(node->value == 0)
- {/* no more blocks of this size, delete sizenode */
- if(node != fnode)
- FINDKEY(SIZEH, size)
- DELETENODE(SIZEH)
- }
-
- if(remainder == 0)
- {/* no remaining space,the node in freelist is exhausted, delete it */
- FINDKEY(FREEH, sp->maddr->key)
- DELETENODE(FREEH)
- free_addr(bp, sp);
- }
- else
- {/* space remains in block, move it to new size loc */
- sp->size = remainder;
- addto_sizelist(bp, sp);
- }
- }
- else
- {
- address = getspace(bp, size, &remainder);
- if(remainder)
- addto_freelist(bp, ((char*)address)+size, remainder);
- }
- if(alignment)
- {
- unsigned diff;
- if((diff = (unsigned)address & mask))
- {/* move address forward */
- char *naddress;
- unsigned lose;
- lose = alignment - diff;
- naddress = (char*)address + lose;
- addto_freelist(bp, address, lose);
- address = (unsigned*)naddress;
- }
- }
- if(bp->guarded)
- {
- *address = FRNTGUARD;
- *((unsigned*)(((char*)address)+req-ALIGNMENTM)) = BACKGUARD;
-
- }
-
- FINDKEY(USEDH, (unsigned)address)
-
- if(node->key == (unsigned)address) {
- VCRASH("allocC:%d: bookkeeping nodes are corrupted at:0x%x\n",
- category, address);
- }
- SETLEVEL(USEDH)
- node = new_Mnode(bp, level, USEDH);
- node->key = (unsigned)address;
- node->value = req;
- INSERT()
-
- return address+bp->addrbump;
- }
- void*
- callocC(int category, unsigned cnt, unsigned elem_size)
- {
- unsigned size = cnt * elem_size;
- void* buf;;
-
- if((buf = mallocC(category, size)))
- bzero(buf, size);
- return buf;
- };
- void
- freeC(int category, void* addr)
- {
- unsigned cursize;
- unsigned *address;
- struct _bins *bp;
- SKIPVARS;
- if(addr)
- {
- if(!(bp = getcat(category))) {
- VCRASH("freeC:%d: non-existant category at:0x%x\n",category,addr);
- }
- HEAPCHECK
- address = (void*) ((unsigned*)addr - bp->addrbump);
- FINDKEY(USEDH, (unsigned)address)
- if(node->key != (unsigned)address) {
- VCRASH("freeC:%d: bogus address=0x%x\n", category, addr);
- }
- cursize = node->value;
- CHECKGUARDS(freeC)
- DELETENODE(USEDH)
-
- addto_freelist(bp, address, cursize);
- }
- else VCRASH("freeC:%d: null pointer\n", category);
- }
- void*
- reallocC(int category, void* addr, unsigned newsize)
- {
- SKIPVARS;
- unsigned cursize;
- unsigned *address;
- struct _bins *bp;
- NodePM onode;
-
- if(addr == 0)
- return mallocC(category, newsize);
- else
- {
- if(!(bp = getcat(category))) {
- VCRASH("reallocC:%d: non-existant category at:%x\n",category,addr);
- }
- HEAPCHECK
- if(newsize == 0)
- newsize = ALIGNMENTM;
- else
- newsize += ROUNDINGM(newsize);
- newsize += bp->guarded;
-
- address = (void*)(((char*)addr)-(bp->guarded/2));
- FINDKEY(USEDH, (unsigned)address)
- if(node->key != (unsigned)address) {
- VCRASH("reallocC:%d: bogus address=0x%x\n", category, addr);
- }
- cursize = node->value;
- node->value = newsize;
- onode = node;
-
- CHECKGUARDS(reallocC)
-
- if(newsize == cursize)
- return addr;
- if(newsize > cursize)
- {/* check if block can be extended */
- void *taddr = ((char*)address) + cursize;
- unsigned extendsize = newsize-cursize;
-
- /* check freelist for an available block at the right address */
- FINDKEY(FREEH, (unsigned)taddr)
- if(node->key == (unsigned)taddr)
- {
- AddrP sp = (AddrP)node->value;
- if(sp->size >= extendsize)
- {/* BLOCK CAN BE EXTENDED INTERNALLY */
- node->key += extendsize;
- sp->size -= extendsize;
- DETACH(sp)
- if(sp->size == 0)
- {/* the extension block is used up, delete this node */
- free_addr(bp, sp);
- DELETENODE(FREEH)
- }
- else
- {/* shift the remainder in the sizelist */
- addto_sizelist(bp, sp);
- }
- /* SUCCESS */
- if(bp->guarded)
- {
- *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
- = BACKGUARD;
- }
- return addr;
- }
- }
- /* HERE WE COULD CHECK OTHER SOURCES OF SPACE */
-
- /* can't extend block, malloc some new space */
- if((taddr = mallocC(category,newsize-bp->guarded)))
- {
- memmove(taddr,addr,cursize-bp->guarded);
- onode->value = cursize;
- freeC(category, addr);
- }
- /* SUCCESS */
- return taddr;
- }
- else
- {/* shrink block */
- if(bp->guarded)
- {
- *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
- = BACKGUARD;
- }
- addto_freelist(bp, ((char*)address)+newsize, cursize-newsize);
- return addr;
- }
- }
- }
- void
- freecat(int category)
- {
- struct _bins *bp;
-
- if(category == 0)
- return;
-
- if((bp = getcat(category)))
- {
- struct _catlocs *cl = bp->catlocs;
- struct _bins *hbp;
- struct _bins *prev;
-
- while(cl)
- {/* Space allocated to the category is moved to category 0 */
- void *ql = cl->fptr;
-
- freeC(0, cl->addr);
- free_catloc(cl);
- cl = ql;
- }
- /* space for the _bins struct is placed on a free list */
- hbp = hmap[category % 1009];
- prev = 0;
- while(hbp)
- {
- if(hbp->bincat == category)
- {
- if(prev == 0)
- hmap[category % 1009] = hbp->fptr;
- else
- prev->fptr = hbp->fptr;
- free_bins(hbp);
- return;
- }
- prev = hbp;
- hbp = hbp->fptr;
- }
- }
- }
- int
- memrangeC(int category, unsigned *min, unsigned *max)
- {
- struct _bins *bp;
-
- if((bp = getcat(category)))
- {
- *min = bp->minloc;
- *max = bp->maxloc;
- return 1;
- }
- return 0;
- }
- int
- usedrangeC(int category, unsigned *min, unsigned *max)
- {
- struct _bins *bp;
- NodePM node;
- int level;
-
- if((bp = getcat(category)))
- {
- node = bp->USEDHheader;
- *min = node->fptr[0]->key;
- for(level = bp->USEDHlevel; level >= 0; level--)
- while(node->fptr[level]->key < 0xffffffff)
- node = node->fptr[level];
- *max = node->key;
- return 1;
- }
- return 0;
- }
- void
- totrangeC(unsigned *min, unsigned *max)
- {
- *min = minloc;
- *max = maxloc;
- }
- void
- guardC(int category)
- {
- struct _bins *bp;
-
- if(!(bp = getcat(category)))
- if(!(bp = initcat(category)))
- return;
-
- if(!bp->guarded)
- {
- bp->guarded = 2*ALIGNMENTM;
- bp->addrbump = 1;
- }
- }
- void*
- heapcheckC(int category, void *start)
- {
- struct _bins *bp;
- NodePM node,prev;
- unsigned *p1,*p2;
-
- if((bp = getcat(category)))
- {
- if(bp->guarded)
- {
- prev = 0;
- node = bp->USEDHheader;
- while( (node = node->fptr[0]) != (NodePM)0xffffffff
- && node->key != 0xffffffffUL)
- {
- if((void*)node->key > start)
- {
- p1 = (unsigned*)node->key;
- if(*p1 != FRNTGUARD)
- {
- if(prev)
- return (char*)prev->key+ALIGNMENTM;
- else
- return (void*)1;
- }
- p2 = (unsigned*)(((char*)p1)+node->value-ALIGNMENTM);
- if(*p2 != BACKGUARD)
- return (char*)node->key+ALIGNMENTM;
- }
- prev = node;
- }
- }
- }
- return 0;
- }
- void*
- mallocC(int category, unsigned size)
- {
- return memalignC(category, 0, size);
- }
-
- void*
- vallocC(int category, unsigned bytes)
- {
- return memalignC (category, PAGESIZE, bytes);
- }
- unsigned
- mallocsizeC(int category, void* addr)
- {
- struct _bins *bp;
- SKIPVARS;
-
- if(addr && (bp = getcat(category)))
- {
- unsigned address = (unsigned)((unsigned*)addr - bp->addrbump);
- FINDKEY(USEDH, address)
- if(node->key == address)
- return node->value - bp->guarded;
- }
- return 0;
- }
-
- int
- NewMallocCategory(void)
- {
- static unsigned int cat = BASE_CATEGORY;
- return ++cat;
- }
- /* ====================== END MULTI-HEAP MALLOC ============================ */
-
-
- /* These are here to prevent the system malloc from being linked */
- void *
- malloc(unsigned a)
- {
- void *result = mallocC(BASE_CATEGORY, a);
- MPRINTF("malloc %d bytes at %p caller=%x\n", a, result, ((unsigned *)&a)[-1]);
- return result;
- }
- void
- free(void *a)
- {
- MPRINTF("free at %p caller=%x\n", a, ((unsigned*)&a)[-1]);
- freeC(BASE_CATEGORY,a);
- }
- void *
- realloc(void *a, unsigned b)
- {
- void *result = reallocC(BASE_CATEGORY,a,b);
- MPRINTF("realloc %d bytes at %p old=%p caller=%x\n",
- b, result, a, ((unsigned*)&a)[-1]);
- return result;
- }
- void *
- calloc(unsigned a, unsigned b)
- {
- void *result = callocC(BASE_CATEGORY,a,b);
- MPRINTF("calloc %d bytes at %p caller=%x\n", a*b, result, ((unsigned*)&a)[-1]);
- return result;
- }
- void *
- valloc(unsigned a)
- {
- void *result = vallocC(BASE_CATEGORY,a);
- MPRINTF("valloc %d bytes at %p caller=%x\n", a, result, ((unsigned *)&a)[-1]);
- return result;
- }
- void *
- memalign(unsigned a, unsigned b)
- {
- void *result = memalignC(BASE_CATEGORY,a,b);
- MPRINTF("memalign(%u) %u bytes at %p caller=%x\n",
- a,b,result,((unsigned *)&a)[-1]);
- return result;
- }
- unsigned
- mallocsize(void *a)
- {
- return mallocsizeC(BASE_CATEGORY, a);
- }
-
- static int
- lnulfunc()
- {
- return 0;
- }
- static void
- lhash(void *keyptr, int cnt, CAT *cat)
- {/* THIS FUNCTION IS IDENTICAL TO 'key_hash' in CFF */
- STOR value;
- int i;
-
- cat->c0.item = 0;
-
- if(cnt <= 8)
- for (i = 0; i < cnt; ++i)
- cat->c0.a5.b[i] = *((unsigned char *)keyptr)++;
- else
- for (i = 0; i < cnt; ++i)
- cat->c0.a5.b[i&7] ^= *((unsigned char *)keyptr)++;
-
- /* THE CONSTANTS WERE CAREFULLY CHOSEN BY THEORY */
- /* value.item is a long long (use gcc only) */
-
- value.item = ((1103515245LL)*(cat->c0.a4.s0 ^ cat->c0.a4.s1))+453816693LL;
- if(value.a0 == 0) value.a0 = 1;
- value.a0 &= 0x0fffffff;
- if(cnt <= 8) value.a0 |= 0x80000000; /* exact key chunk */
- cat->c1.a0 = value.a0;
- }
- static int linkup_complete;
- static int
- laccess(char *a, int b)
- {/* suppress use of 'access', it links in too many other functions */
-
- if(linkup_complete)
- return ((VOBTYPE(a) & (OB_XFILE|OB_TREEDIR|OB_HASHDIR)) ? 0 : 1);
- else {
- int fd = VOPEN(a,O_RDONLY|O_BINARY);
- if(fd > 0)
- {
- VCLOSE(fd);
- return 0;
- }
- return 1;
- }
- }
- static int
- lpagesize()
- {
- return 4096;
- }
- static int
- lprintchar(int c)
- {
- return VWRITE(1,&c,1);
- }
- static void
- lprintstr(char *str)
- {
- while(*str)
- lprintchar(*str++);
- }
-
- #if EARLY_PRINT == 1
-
- struct parameters
- {
- int number_of_output_chars;
- int (*output_function)(void *, int);
- void *output_pointer;
- short minimum_field_width;
- short edited_string_length;
- short leading_zeros;
- char options;
- #define MINUS_SIGN 1
- #define RIGHT_JUSTIFY 2
- #define ZERO_PAD 4
- #define CAPITAL_HEX 8
- };
-
- static void output_and_count(struct parameters *p, int c)
- {
- if (p->number_of_output_chars >= 0)
- {
- int n = (*p->output_function)(p->output_pointer, c);
- if (n>=0) p->number_of_output_chars++;
- else p->number_of_output_chars = n;
- }
- }
-
- static void output_field(struct parameters *p, char *s)
- {
- short justification_length =
- p->minimum_field_width - p->leading_zeros - p->edited_string_length;
- if (p->options & MINUS_SIGN)
- {
- if (p->options & ZERO_PAD)
- output_and_count(p, '-');
- justification_length--;
- }
- if (p->options & RIGHT_JUSTIFY)
- while (--justification_length >= 0)
- output_and_count(p, p->options & ZERO_PAD ? '0' : ' ');
- if (p->options & MINUS_SIGN && !(p->options & ZERO_PAD))
- output_and_count(p, '-');
- while (--p->leading_zeros >= 0)
- output_and_count(p, '0');
- while (--p->edited_string_length >= 0)
- output_and_count(p, *s++);
- while (--justification_length >= 0)
- output_and_count(p, ' ');
- }
-
-
- static int
- gprintf(int (*output_function)(void *, int), void *output_pointer,
- char *control_string, int *argument_pointer)
- {
- struct parameters p;
- char control_char;
- p.number_of_output_chars = 0;
- p.output_function = output_function;
- p.output_pointer = output_pointer;
- control_char = *control_string++;
- while (control_char != '\0')
- {
- if (control_char == '%')
- {
- short precision = -1;
- short long_argument = 0;
- short base = 0;
- control_char = *control_string++;
- p.minimum_field_width = 0;
- p.leading_zeros = 0;
- p.options = RIGHT_JUSTIFY;
- if (control_char == '-')
- {
- p.options = 0;
- control_char = *control_string++;
- }
- if (control_char == '0')
- {
- p.options |= ZERO_PAD;
- control_char = *control_string++;
- }
- if (control_char == '*')
- {
- p.minimum_field_width = *argument_pointer++;
- control_char = *control_string++;
- }
- else
- {
- while ('0' <= control_char && control_char <= '9')
- {
- p.minimum_field_width =
- p.minimum_field_width * 10 + control_char - '0';
- control_char = *control_string++;
- }
- }
- if (control_char == '.')
- {
- control_char = *control_string++;
- if (control_char == '*')
- {
- precision = *argument_pointer++;
- control_char = *control_string++;
- }
- else
- {
- precision = 0;
- while ('0' <= control_char && control_char <= '9')
- {
- precision = precision * 10 + control_char - '0';
- control_char = *control_string++;
- }
- }
- }
- if (control_char == 'l')
- {
- long_argument = 1;
- control_char = *control_string++;
- }
- if (control_char == 'd')
- base = 10;
- else if (control_char == 'x' || control_char == 'p')
- base = 16;
- else if (control_char == 'X')
- {
- base = 16;
- p.options |= CAPITAL_HEX;
- }
- else if (control_char == 'u')
- base = 10;
- else if (control_char == 'o')
- base = 8;
- else if (control_char == 'b')
- base = 2;
- else if (control_char == 'c')
- {
- base = -1;
- p.options &= ~ZERO_PAD;
- }
- else if (control_char == 's')
- {
- base = -2;
- p.options &= ~ZERO_PAD;
- }
- if (base == 0) /* invalid conversion type */
- {
- if (control_char != '\0')
- {
- output_and_count(&p, control_char);
- control_char = *control_string++;
- }
- }
- else
- {
- if (base == -1) /* conversion type c */
- {
- char c = *argument_pointer++;
- p.edited_string_length = 1;
- output_field(&p, &c);
- }
- else if (base == -2) /* conversion type s */
- {
- char *string;
- p.edited_string_length = 0;
- string = * (char **) argument_pointer;
- argument_pointer += sizeof(char *) / sizeof(int);
- while (string[p.edited_string_length] != 0)
- p.edited_string_length++;
- if (precision >= 0 && p.edited_string_length > precision)
- p.edited_string_length = precision;
- output_field(&p, string);
- }
- else /* conversion type d, b, o or x */
- {
- unsigned long x;
- char buffer[64];
- p.edited_string_length = 0;
- if (long_argument)
- {
- x = * (unsigned long *) argument_pointer;
- argument_pointer += sizeof(unsigned long) / sizeof(int);
- }
- else if (control_char == 'd')
- x = (long) *argument_pointer++;
- else
- x = (unsigned) *argument_pointer++;
- if (control_char == 'd' && (long) x < 0)
- {
- p.options |= MINUS_SIGN;
- x = - (long) x;
- }
- do
- {
- int c;
- c = x % base + '0';
- if (c > '9')
- {
- if (p.options & CAPITAL_HEX)
- c += 'A'-'9'-1;
- else
- c += 'a'-'9'-1;
- }
- buffer[sizeof(buffer) - 1 - p.edited_string_length++] = c;
- }
- while ((x/=base) != 0);
- if (precision >= 0 && precision > p.edited_string_length)
- p.leading_zeros = precision - p.edited_string_length;
- output_field(&p, buffer + sizeof(buffer) - p.edited_string_length);
- }
- control_char = *control_string++;
- }
- }
- else
- {
- output_and_count(&p, control_char);
- control_char = *control_string++;
- }
- }
- return p.number_of_output_chars;
- }
- static int
- lputc(void *fd, int c)
- {
- return VWRITE((int)fd, &c, 1);
- }
- static int
- lprintf(char *fmt, ...)
- {
- return gprintf(lputc, (void*)1, fmt, (int*)(&fmt+1));
- }
- static int
- lvprintf(char *fmt, void *args)
- {
- return gprintf(lputc, (void*)1, fmt, args);
- }
- static int lfilc(void *p, int c)
- {
- *(*(char **)p)++ = c;
- return 0;
- }
- static int
- lsprintf(char *buf, char *fmt, ...)
- {
- int n;
- n = gprintf(lfilc, &buf, fmt, (int*)(&fmt+1));
- *buf = 0;
- return n;
- }
-
- #endif /* EARLY_PRINT == 1 */
-
- void
- _cleanup()
- {/* SUPPRESS PULLIN OF STDIO STUFF */
- }
- /* ================== END OF INTERNAL SUPPORT FUNCTIONS ================= */
-
- #include "oxlink.i"
-
- /* ================ END OF THE DYNAMIC LINKER ======================= */
-
- struct _linkups {
- void *dst;
- char *src;
- };
- static struct _linkups __linkups[] = {
- {&VPUSH_VALUE, "_cfpush_value"},
- {&VPUSH_DATA, "_cfpush_data"},
- {&VGET, "_cfgetx"},
- {&VFIND, "_cffindx"},
- {&VCFOPEN, "_cfopen"},
- {&VCFCLOSE, "_cfclose"},
- {&VCFREAD, "_cfrdwr_object"},
- {&VCFWRITE, "_cfrdwr_object"},
- {&VCFLSEEK, "_cfseek"},
- {&VSUBOPEN, "_cfsubopen"},
- {&VOBTYPE, "_cfobtype"},
- {&VPUT, "_cfputx"},
- {&VFILESIZE, "_cffilesize"},
- {&VOPEN_CHUNK, "_cfopen_chunk"},
- {&VLOCALIZE, "_cflocalize"},
- {&VRELEASE, "_cfrelease"},
- {&VMEMTEMP, "_MEMTEMP"},
- {&VVPRINTF, "_cfvprintf"},
- {&VSPRINTF, "_cfsprintf"},
- {&VPRINTF, "_cfprintf"},
- {&VSTAT, "_cfstat"},
- {&CFINIT, "_cfinit"},
- {&CFEXIT, "_cfexit"},
- {&COSINIT, "_InitCOS"},
- {&THREADER, "__start_threader"},
- {&THREAD, "__start_thread"},
- {&VINHIBIT_THREADER, "__no_context_switch"},
- {NULL}
- };
- static int badsyms;
- static void
- linkup()
- {
- struct _linkups *l = __linkups;
-
- while(l->dst)
- {
- *((long *)l->dst) = (long)oxlink_find_bare_symb(l->src);
- ++l;
- }
- /* REDIRECT USER CALLS TO OUR PREFERRED SUBROUTINES */
- SYMLINK(__filbuf, _cf_filbuf);
- SYMLINK(__flsbuf, _cf_flsbuf);
- SYMLINK(_fread, _cffread);
- SYMLINK(_fputc, _cffputc);
- SYMLINK(_fgetc, _cffgetc);
- SYMLINK(_fputs, _cffputs);
- SYMLINK(_fgets, _cffgets);
- SYMLINK(_puts, _cfputs);
- SYMLINK(_putw, _cfputw);
- SYMLINK(_gets, _cfgets);
- SYMLINK(_ftell, _cfftell);
- SYMLINK(_printf, _cfprintf);
- SYMLINK(_fprintf, _cffprintf);
- SYMLINK(_sprintf, _cfsprintf);
- SYMLINK(_vprintf, _cfvprintf);
- SYMLINK(_vfprintf, _cfvfprintf);
- SYMLINK(_fscanf, _cffscanf);
- SYMLINK(_fopen, _cffopen);
- SYMLINK(_freopen, _cffreopen);
- SYMLINK(_fseek, _cffseek);
- SYMLINK(_rewind, _cfrewind);
- SYMLINK(_fflush, _cffflush);
- SYMLINK(_fwrite, _cffwrite);
- SYMLINK(_unlink, _cfunlink);
- SYMLINK(_remove, _cfunlink);
- SYMLINK(_ungetc, _cfungetc);
- SYMLINK(_fclose, _cffclose);
- SYMLINK(_fdopen, _cffdopen);
- SYMLINK(_setmode, _cfsetmode);
- SYMLINK(_setbuf, _cfsetbuf);
- SYMLINK(_setvbuf, _cfsetvbuf);
- SYMLINK(_setlinebuf, _cfsetlinebuf);
- SYMLINK(_scanf, _cfscanf);
- SYMLINK(_sscanf, _cfsscanf);
- SYMLINK(_fscanf, _cffscanf);
- SYMLINK(_vscanf, _cfvscanf);
- SYMLINK(_vfscanf, _cfvfscanf);
- SYMLINK(_vsscanf, _cfvsscanf);
- SYMLINK(__iob, _cf_iob);
- SYMLINK(_stat, _TRAPSTAT);
- SYMLINK(_rename, _TRAPRENAME);
- SYMLINK(_fgetpos, _cffgetpos);
- SYMLINK(_fsetpos, _cffsetpos);
- SYMLINK(_tmpfile, _cftmpfile);
- SYMLINK(_tmpnam, _cftmpnam);
- SYMLINK(_tempnam, _cftempnam);
- SYMLINK(_itoa, _ltoa);
- }
- static char *
- appnameof(char *path)
- {
- char *aname;
- char *cp;
-
- if(path == NULL)
- return NULL;
-
- cp = concat("_", fileof(path, 0), "");
- aname = strdup(cp);
- _oxlink_free(cp); /* was not allocated with malloc */
- if((cp = strrchr(aname, '.')) != NULL)
- *cp = 0;
- cp = aname;
- while(*cp)
- {/* lower case app names only */
- if(*cp >= 'A' && *cp <= 'Z')
- *cp += 32;
- ++cp;
- }
- return aname;
- }
- static char *
- appfileof(char *aname)
- {
- char *fname;
- char *gname;
- int fcnt;
-
- if(aname == NULL)
- return NULL;
-
- fcnt = strlen(aname);
- fname = malloc(fcnt+6);
- if(aname[0] == '_')
- fcnt = _strcpy(fname, &aname[1]);
- else
- strcpy(fname, aname);
-
- strcpy(&fname[fcnt], ".o");
- if(!(gname = cf_find_file(fname, 0)))
- {
- #if 0
- strcpy(&fname[fcnt], ".byt");
- if(!(gname = cf_find_file(fname, 0)))
- #endif
- strcpy(&fname[fcnt], ".cff");
- gname = cf_find_file(fname, 0);
- }
- free(fname);
- return gname;
- }
- static char *
- cfffileof(char *aname)
- {
- char *fname;
- char *gname;
- int fcnt;
-
- if(aname == NULL)
- return NULL;
-
- fcnt = strlen(aname);
- fname = malloc(fcnt+6);
- if(aname[0] == '_')
- fcnt = _strcpy(fname, &aname[1]);
- else
- strcpy(fname, aname);
-
- strcpy(&fname[fcnt], ".cff");
- gname = cf_find_file(fname, 0);
- free(fname);
- return gname;
- }
- static void
- Usage()
- {
- lprintstr("\
- Usage: cfrun appname [-APP=][-LIB=][-PATH=][-TRACE=][-LBUFS=][appargs]\n\
- Switch -------- Meaning\n\
- -APP=filename Permanent object file/archive for the application.\n\
- -LIB=filename A library file.\n\
- -PATH=p1;p2;... Lookup path for files.\n\
- -LBUFS=n Allocate n kilobytes of database buffering.\n\
- -TRACE=n Set trace bits (hex,octal,decimal ok).\n\
- appargs Application args.\n\
- ");
- }
-
- /* ====================== THE MAIN FUNCTION ======================= */
- static int chainargc;
- static char *chainargv[30];
- static char *chainapp, *chainfile, *chaincff;
- static int chainapp_hasextension, chainfile_iscff;
- char **Envp;
- static char newmain[10];
-
- int
- main(int argc, char **argv, char **envp)
- {
- char *appath, *appname, *appfile, *ap, *dp;
- int lbufs, i;
- int appfile_iscff = 0;
- int appname_hasextension = 0;
- char *appcff = 0;
-
- char *
- check_for_arg(char *arg)
- {/* NESTED SUBROUTINE */
- int i;
- int arglen = strlen(arg);
-
- for(i = 1; i < argc; ++i)
- {
- if(argv[i][0] == '-' && !strncmp(arg, &argv[i][1], arglen))
- {
- int j;
- char *cp = &argv[i][arglen+1];
- for(j = i; j < argc; ++j)
- argv[j] = argv[j+1];
- --argc;
- return cp;
- }
- }
- return NULL;
- }
- /* main */
- path_sep = ';';
- _oxlink_openmode = O_RDONLY|O_BINARY;
- _oxlink_seekmode = 0;
- oxlink_errno = 0;
- Envp = envp;
-
- cf_set_search_path(check_for_arg("PATH="));
-
- if((ap = check_for_arg("TRACE=")) != NULL)
- _oxlink_trace = strtol(ap, NULL, 0);
-
- /* Get relevant info about this program name */
- appath = cf_find_file(argv[0], 0);
- appname = appnameof(appath);
-
- if(!strcmp(appname, "_cfrun"))
- {/* arg1 contains the real name of the application */
- int j;
- if(argc > 1)
- {
- appname = appnameof(argv[1]);
- if((dp = strchr(argv[1], '.')))
- {
- appfile = cf_find_file(argv[1], 0);
- appname_hasextension = 1;
- }
- else
- appfile = appfileof(appname);
-
- for(j = 1; j < argc; ++j)
- argv[j] = argv[j+1];
- --argc;
- }
- else
- {
- Usage();
- VEXIT(0);
- }
- }
- else appfile = appfileof(appname);
-
- if(appfile)
- {
- if((dp = strrchr(appfile, '.')))
- {
- if(!strcmp(dp, ".cff"))
- {
- appfile_iscff = 1;
- appcff = appfile;
- }
- else
- {
- appcff = cfffileof(appname);
- }
- }
- }
- /* Link in the base level code */
- permanent_symbols = 1;
- if(!oxlink_init(appath)) {
- oxlink_use_library("oxbow.a");
- if(!oxlink_load_object("dj12port.o")) {
- if(!oxlink_load_object("cffsys.o")) {
- if(!oxlink_load_object("cossys.o")) {
- oxlink_nouse_library("oxbow.a");
- linkup();
- }
- }
- }
- }
- permanent_symbols = 0;
-
- if(oxlink_errno) {
- lprintstr(oxlink_errstr());
- VEXIT(oxlink_errno);
- }
- /* CFF and COS are now linked */
- linkup_complete = 1;
- _oxlink_openmode = F_STAT;
- _oxlink_seekmode = S_SET;
-
- /* check for appfile override */
- if((ap = check_for_arg("APP=")) != NULL)
- appfile = strdup(ap);
-
- if((ap = check_for_arg("LBUFS=")) != NULL)
- lbufs = strtol(ap, NULL, 0);
- else lbufs = 100;
-
- /* Initialize CFF and COS */
- CFINIT(&appname[1], lbufs, appfile);
- COSINIT(&argc);
-
- /* Get rid of the symbol `_main' so it doesn't clash */
- strcpy(newmain, "_main$$$");
- oxlink_rename_symb("_main", newmain);
-
- /* Specify which libraries will provide code and data */
- oxlink_use_library("oxlib.cff");
-
- /* Pick up any additional libraries of interest */
- while((ap = check_for_arg("LIB=")) != NULL)
- oxlink_use_library(ap);
-
- /* Enable demand loading */
- oxlink_demand_load();
-
- if(_oxlink_trace)
- {/* Print the addresses of the early load modules */
- struct file_entry *entry = _oxlink_latest_entry;
- void print_file(struct file_entry *e)
- {/* NESTED SUBROUTINE */
- VPRINTF("%s\ntext:0x%x sz=%d data:0x%x sz=%d bss:0x%x sz=%d end=%x\n",
- e->local_sym_name,
- e->text_start_address, e->header.text_size,
- e->data_start_address, e->header.data_size,
- e->bss_start_address, e->header.bss_size,
- e->text_start_address+e->header.image_size
- );
- }
- while(entry)
- {
- if(entry->library_flag) {
- struct file_entry *subentry = entry->subfiles;
- while(subentry)
- {
- print_file(subentry);
- subentry = subentry->chain;
- }
- }
- entry = entry->chain;
- }
- }
- /* Start threads */
- THREADER(&argc);
- if(setjmp(_t_start)) {
- THREAD();
- }
-
- *VINHIBIT_THREADER += 1;
- {
- int ret;
- int run_argc;
- char **run_argv;
- run_argc = argc;
- run_argv = argv;
- chain:
- if(appcff)
- {
- oxlink_use_library(appcff); /* ignored if not a library */
- }
- run_argv[0] = &appname[1];
-
- if(appfile)
- {/* The file could be .o or .cff */
- char *filename;
- int (*funcptr)();
- int loaded = 0;
- if(appfile_iscff || !appname_hasextension)
- {/* look for a file inside a .cff file */
- /* FIRST TRY TO RUN THE APPNAME */
- if((ret = oxfunc(appname, run_argc, run_argv)) != -1)
- {
- oxlink_unload_bare_symb(appname, 0);
- loaded = -1;
- }
- else
- {/* try loading object from any defined libraries */
- dp = strrchr(appfile, '/')+1;
- filename = calloc(1, strlen(dp)+5);
- strcpy(filename, dp);
- strcpy(strchr(filename,'.'), ".o");
- if(!oxlink_load_object(filename))
- {
- loaded = 1;
- }
- }
- }
- if(!loaded)
- {/* try loading the file directly */
- filename = appfile;
- if(oxlink_load_file(filename))
- {
- VPRINTF("Can't start application `%s'\n", &appname[1]);
- VEXIT(1);
- }
- loaded = 1;
- }
- if(loaded > 0)
- {
- if((funcptr = oxlink_find_bare_func("_main")))
- {/* Get rid of the symbol `_main' so it doesn't clash */
- ++newmain[8];
- oxlink_rename_symb("_main", newmain);
- }
- else if(!(funcptr = oxlink_find_bare_func(appname)))
- {
- VPRINTF("Can't find `_main' or `%s' in file %s\n",
- appname, filename);
- VEXIT(1);
- }
- ret = funcptr(run_argc, run_argv);
- oxlink_unload_file(filename, 0);
- if(filename != appfile)
- free(filename);
- }
- }
- else
- {/* Just try to run the name from a library */
- if((ret = oxfunc(appname, run_argc, run_argv)) == -1)
- VPRINTF("Can't start application `%s'\n", &appname[1]);
- oxlink_unload_bare_symb(appname, 0);
- }
- free(appname);
- if(appcff)
- {
- oxlink_nouse_library(appcff);
- if(appcff != appfile)
- free(appcff);
- }
- if(appfile)
- free(appfile);
-
- if(chainapp)
- {/* The previous program chained to a new one */
- appname = chainapp;
- appfile = chainfile;
- appcff = chaincff;
- appfile_iscff = chainfile_iscff;
- appname_hasextension = chainapp_hasextension;
- chainapp = 0;
- if(run_argv != argv)
- {/* was chained previously, get rid of prev args */
- for(i = 1; i < run_argc; ++i)
- free(run_argv[i]);
- }
- run_argc = chainargc;
- run_argv = (char**)chainargv;
- goto chain;
- }
- CF_InitIO(-1, 0);
- VEXIT(ret);
- }
- }
- void
- CF_ChainFile(char *newname, int argc, char **argv)
- {/* CALLED FROM APPLICATION TO CHAIN TO ANOTHER PROGRAM */
- int i;
- char *dp;
- chaincff = 0;
- chainfile_iscff = 0;
- chainapp_hasextension = 0;
- chainapp = appnameof(newname);
-
- if((dp = strchr(newname, '.')))
- {
- chainfile = cf_find_file(newname, 0);
- chainapp_hasextension = 1;
- }
- else chainfile = appfileof(chainapp);
-
- if(chainfile)
- {
- if((dp = strrchr(chainfile, '.')))
- {
- if(!strcmp(dp, ".cff"))
- {
- chainfile_iscff = 1;
- chaincff = chainfile;
- }
- else
- {
- chaincff = cfffileof(chainapp);
- }
- }
- }
- chainargc = argc+1;
- for(i = 0; i < argc; ++i)
- chainargv[i+1] = copy_of(argv[i]);
- }
- void
- CF_InitIO(long arg, long long (*msgproc)())
- {/* THIS FUNCTION IS CALLED FROM THE APPLICATION */
- static void (*initio)() = NULL;
-
- if(arg >= 0)
- {
- AppArg = arg;
- initio = oxload(CF_Interactive_IO);
- initio(0, msgproc, &VAPPMSG);
- }
- else if(arg == -1)
- {/* deinit */
- if(initio)
- initio(-1, 0, 0);
- }
- else
- {/* re-init */
- if(initio)
- initio(arg, 0, 0);
- }
- }
- long long
- AppMsg(void *self, void *wnd, long long it)
- {
- return VAPPMSG(self, wnd, it);
- }
-