home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / oxcc1433.zip / SRC / SKELETON.C < prev    next >
C/C++ Source or Header  |  1995-11-06  |  54KB  |  2,319 lines

  1. /* SKELETON.C -- THE PROTOTYPE APPLICATION FOR THE OXBOW FRAMEWORK
  2.     COMPILE WITH GCC
  3.  
  4.    COPYRIGHT 1994 Norman D. Culver, Ft. Lauderdale, FL
  5.  
  6. NOTE: 'main()' is at the end of the file.
  7. */
  8. #define SYMLINK(from,to) badsyms += oxlink_symlink(#from,#to)
  9.  
  10. #define EARLY_PRINT 1    /* set to 1 if trace before linkup needed */
  11.  
  12. #define BASE_CATEGORY 0
  13. #define MEMORY_BUG 0
  14. #define PRINT_RAWDATA 0
  15.  
  16. #if 0
  17. #define DPRINTF lprintf
  18. #else
  19. #define DPRINTF(args...)
  20. #endif
  21.  
  22. #if 0
  23. #define MPRINTF lprintf
  24. #else
  25. #define MPRINTF(args...)
  26. #endif
  27.  
  28. #if EARLY_PRINT == 1
  29. #define TPRINTF lprintf
  30. #else
  31. #define TPRINTF VPRINTF
  32. #endif
  33.  
  34. #include <go32.h>
  35.  
  36. /* extracts from 'oxbow.h' */
  37. typedef unsigned long long  KeyItem;   /* type for a key's associated item */
  38.  
  39. typedef union             /* 2 BYTES */
  40.     {
  41.         unsigned short val;
  42.         unsigned char b[2];
  43. } SVAL;
  44.  
  45. typedef union            /* 4 BYTES */
  46.     {
  47.     unsigned long a0;
  48.     void *a1;
  49.     struct
  50.         {
  51.         SVAL    lo_word;
  52.         SVAL    hi_word;
  53.         } a2;
  54.     struct
  55.         {
  56.             unsigned int pad :28;
  57.             unsigned int type :4;
  58.         } a3;
  59.     struct
  60.         {
  61.             unsigned char b[4];
  62.         } a4;
  63.     int a8;
  64.     short a9;
  65.     char a10;
  66.     float a11;
  67. } ADDR;
  68.  
  69. typedef union _stor    /* 8 BYTES */
  70.     {
  71.     unsigned long    a0;
  72.     void *a1;
  73.     KeyItem item;
  74.     struct
  75.         {
  76.         unsigned short    lo_word;
  77.         unsigned short    hi_word;
  78.         unsigned int size :28;        /* in bytes or nibbles */
  79.         unsigned int type :4;        /* describes the STOR type */
  80.         } a2;
  81.     struct
  82.         {
  83.             short s0;
  84.             short s1;
  85.             short s2;
  86.             short s3;
  87.         } a3;
  88.     struct
  89.         {
  90.             unsigned long    s0;
  91.             unsigned long    s1;
  92.         } a4;
  93.     struct
  94.         {
  95.             unsigned char    b[8];
  96.         } a5;
  97.     struct
  98.         {
  99.             unsigned long long dupname :48;
  100.             unsigned long long dupid :16;
  101.         } a6;
  102.     struct
  103.         {
  104.             unsigned int home : 30;
  105.             unsigned int full : 2;
  106.         } a7;
  107.     int a8;
  108.     short a9;
  109.     char a10;
  110.     float a11;
  111.     double a12;
  112. } STOR, Item;
  113.  
  114. typedef struct            /* 12 BYTES */
  115.     {
  116.         STOR c0;
  117.         ADDR c1;
  118. } CAT;
  119.  
  120. #define OB_XFILE    (0x00004000)
  121. #define OB_ROOTDIR    (0x00000200)
  122. #define OB_TREEDIR    (0x10000000)
  123. #define OB_HASHDIR    (0x20000000)
  124. #define F_RDONLY    (0x0001)
  125. #define F_STAT        (0x20000)    /* TRULY READONLY */
  126. #define O_RDONLY    (0x0001)
  127. #define O_BINARY    (0x8000)
  128. #define R_CLEAN        (0x40000000)
  129. #undef NULL
  130. #define NULL        ((void *)0)
  131. #define FOUND        (1)
  132. #define NODUPS        (0)
  133. #define S_SET        (0)
  134. #define S_READBLK    (1)
  135. #define S_WRITEBLK    (2)
  136.  
  137. #define    _cat2_(a, b)    a##b
  138. #define _cat_(a, b)    _cat2_(a, b)
  139. #define _qt2_(x) #x
  140. #define _qt_(x) _qt2_(x)
  141.  
  142. #define oxfunc(func, args...) ({ \
  143. typedef _fret = (appfunc()); \
  144. _fret (*dofunc)(); _fret _ret; \
  145. dofunc = oxlink_load_bare_symb(func,1); \
  146. if(dofunc) _ret = dofunc(## args) & 0x0fffffff; \
  147. else _ret = (_fret) -1; \
  148. _ret;})
  149.  
  150. #define oxload(func) \
  151. oxlink_load_bare_symb(_qt_(_cat_(_, func)),1)
  152.  
  153. #define oxunload(func) \
  154. oxlink_unload_symb(#func, 1)
  155.  
  156. typedef int jmp_buf[32];               /* an adequate buffer for setjmp */
  157. int setjmp();
  158. void longjmp();
  159.  
  160. /* end: extracts from 'oxbow.h' */
  161. /* ==================== A LIST OF PROBLEMS ======================= */
  162. /* external function prototypes needed initially,
  163.     THESE NEED TO BE LOCALIZED */
  164. void *sbrk();
  165. int open();
  166. int creat();
  167. int close();
  168. int read();
  169. int write();
  170. int lseek();
  171. char *getenv();
  172. char *getwd();
  173.  
  174. int strlen();
  175. char *strdup();
  176. char *strcat();
  177. char *strcpy();
  178. char *strchr();
  179. char *strrchr();
  180. char *strstr();
  181. int _strcpy();
  182. long strtol();
  183. int strcmp(const char *, const char *);
  184. int strncmp();
  185. void CF_Interactive_IO();
  186. int appfunc();
  187. void *malloc(unsigned);
  188. void *calloc(unsigned, unsigned);
  189. void free(void*);
  190. void *memcpy();
  191.  
  192. /* external function prototypes needed by the portability modules
  193.     THESE TOO NEED TO BE LOCALIZED (or something) */
  194. void exit();
  195. int ftruncate();
  196. void abort();
  197.  
  198. /* internal function prototypes */
  199. static int lnulfunc();
  200. static void lhash(void *, int, CAT *);
  201. static int laccess(char *, int);
  202. static int lpagesize(void);
  203. static int lprintchar(int);
  204. static void lprintstr(char *);
  205. static void lcrash(char *, ...);
  206. void CF_InitIO(long arg, long long (*msgproc)());
  207.  
  208. /* ======================== END LIST OF PROBLEMS ==================== */
  209.  
  210. /* DYNAMIC LINKER FUNCTIONS */
  211. int oxlink_init ();            /* initialize the routines */
  212. int oxlink_load_file ();    /* dynamically link and load an object file */
  213. int oxlink_load_object ();    /* link object file from libraries in list */
  214. void *oxlink_find_func ();    /* return the address of the named function */
  215. void *oxlink_find_bare_func ();/* same as oxlink_find_func except that
  216.                                no underscore (_) is prepended (also faster). */
  217. void * oxlink_find_sym ();    /* return the address of the named identifier  */
  218. void *oxlink_find_bare_symb ();/* same as oxlink_find_symb except that
  219.                                no underscore (_) is prepended (also faster). */
  220. int oxlink_unload_file ();   /* unlink a file */
  221. int oxlink_unload_symb (); /* unlink the module that defines the given symbol */
  222. int oxlink_unload_bare_symb (); /* unlink the module that defines the given symbol */
  223. char **oxlink_list_undefined_symb ();/* return an array of undefined symbols */
  224. char *cf_find_file ();/* return the full path name of the given file. */
  225. void *oxlink_load_symb(char *symb, int dynlink);
  226. void *oxlink_load_bare_symb(char *symb, int dynlink);
  227. int oxlink_export_symb();
  228. int oxlink_export_bare_symb();
  229. void oxlink_unexport_symb();
  230. void oxlink_unexport_bare_symb();
  231. int oxlink_symlink();            /* give new symbol same values as old symbol */
  232. void oxlink_demand_load();    /* define all undefined symbols with negative numbers */
  233. void oxlink_use_library();    /* add a filename for undefined symbol search */
  234. void oxlink_nouse_library();    /* remove a library from the search list */
  235. void  *oxlink_resolve_symb();    /* resolve one of the demand loadable undefs */
  236. void oxlink_trace();        /* set the trace level */
  237. char *oxlink_symname();        /* return name of a demand loadable undef */
  238. void *oxlink_rename_symb(char *old,char *new);
  239. int oxlink_rename_file(char *old,char *new);
  240. void oxlink_lib_check(int dynlink);    /* force search of library list */
  241. char *oxlink_file_of(char *symb);
  242. char *oxlink_file_of_bare(char *symb);
  243. int oxlink_scan_file(void *fhandle, void *thandle);
  244. void oxlink_set_libtype(int type);
  245. void oxlink_set_libnum(int libnum);
  246. void oxlink_load_thunk(int thunknum);
  247. int oxlink_prep_thunk(char *symb);
  248. void oxlink_clear_bss(char *filename);
  249. void *oxlink_get_entry_struct(char *filename);
  250. char *oxlink_errstr(void);
  251.  
  252. /* virtual function pointers initially hard linked to the load module */
  253. /* needed in order to initialize and read a .o or .a file */
  254. int (*VCFREAD)() = read;
  255. int (*VCFWRITE)() = write;
  256. void *(*VCFOPEN)() = (void *)open;
  257. int (*VCFCLOSE)() = close;
  258. int (*VCFLSEEK)() = lseek;
  259. int (*VACCESS)() = laccess;
  260. void *(*VSBRK)() = sbrk;
  261. char *(*VGETENV)() = getenv;
  262. char *(*VGETCWD)() = getwd;
  263. int (*VOBTYPE)() = lnulfunc;
  264.  
  265. void (*VHASH)() = lhash;
  266. int (*VGETPAGESIZE)() = lpagesize;
  267.  
  268.  
  269. #if EARLY_PRINT == 0
  270. int (*VVPRINTF)() = lnulfunc;
  271. int (*VSPRINTF)() = lnulfunc;
  272. int (*VPRINTF)() = lnulfunc;
  273. int (*BUGPRINTF)() = lnulfunc;
  274. #else
  275. static int lvprintf(char *, void *);
  276. static int lsprintf(char *, char *, ...);
  277. static int lprintf(char *, ...);
  278. int (*VVPRINTF)(char *, void*) = lvprintf;
  279. int (*VSPRINTF)(char *, char *, ...) = lsprintf;
  280. int (*VPRINTF)(char *, ...) = lprintf;
  281. int (*BUGPRINTF)(char *, ...) = lprintf;
  282. #endif
  283.  
  284. /* function pointers needed by portability modules */
  285. void *(*VMALLOC)() = malloc;
  286. void *(*VCALLOC)() = calloc;
  287. void (*VFREE)() = free;
  288. void (*VEXIT)() = exit;
  289. int (*VREAD)() = read;
  290. int (*VOPEN)() = open;
  291. int (*VCLOSE)() = close;
  292. int (*VLSEEK)() = lseek;
  293. int (*VWRITE)() = write;
  294. void (*VABORT)() = abort;
  295. int (*VPRINTCHAR)() = lprintchar;
  296. void (*VPRINTSTR)() = lprintstr;
  297. void (*VCRASH)(char* fmt, ...) = lcrash;
  298. void (*VBITBLT)();
  299. int (*VSTAT)() = lnulfunc;
  300.  
  301. /* function pointers used internally */
  302. int (*CFINIT)();
  303. void (*CFEXIT)();
  304. int (*COSINIT)();
  305. void (*THREADER)();
  306. void (*THREAD)();
  307. int *VINHIBIT_THREADER;
  308.  
  309. /* cff function pointers used but not available until cff is loaded */
  310. int (*VPUSH_VALUE)();
  311. int (*VPUSH_DATA)();
  312. int (*VFIND)();
  313. int (*VGET)();
  314. void *(*VSUBOPEN)();
  315. int (*VPUT)();
  316. int (*VFILESIZE)();
  317. void *(*VOPEN_CHUNK)();
  318. void *(*VLOCALIZE)();
  319. int (*VRELEASE)();
  320. void **VMEMTEMP;
  321.  
  322. /* function pointers used by the COS threader but not available until
  323.     the message class is loaded */
  324. int (*VWASMSG)() = lnulfunc;
  325. int (*VDISPATCHMSG)() = lnulfunc;
  326.  
  327.  
  328. /* Global variables, here to suppress re-linking */
  329. long long (*VAPPMSG)();
  330. void *Application;
  331. int numTextModes;
  332. int numGraphicModes;
  333. void *TextModes;
  334. void *GraphicModes;
  335. int GuiEnabled;
  336. int _SCREENXMAX;
  337. int _SCREENYMAX;
  338. int _REMOTEFD;
  339. int _SCREENHEIGHT;
  340. int _EFFECTIVE_SCREENHEIGHT;
  341. int _SCREENWIDTH;
  342. int _EFFECTIVE_SCREENWIDTH;
  343. int _GLOBALWIDTH;
  344. int _GLOBALHEIGHT;
  345. int _CURCOLS;
  346. int _CURROWS;
  347. int _FONTWIDTH;
  348. int _FONTHEIGHT;
  349. int _CHARWIDTH;
  350. int _LINEHEIGHT;
  351. int _GRIDWIDTH;
  352. int _GRIDHEIGHT;
  353. int _GLOBALX;
  354. int _GLOBALY;
  355. int _MAXROWS;
  356. int _MAXCOLS;
  357. int _VIDEOMODE;
  358. int _LOOK;
  359. int _FEEL;
  360.  
  361. /* variables needed by the cos threader */
  362. int _no_context_switch = 1;
  363. jmp_buf _t_start;
  364.  
  365. /* application initializer word */
  366. long AppArg;
  367.  
  368. /* flag used to force early symbols to be permanent */
  369. static int permanent_symbols;
  370. static char path_sep;
  371.  
  372. /* ================ START OF INTERNAL SUPPORT FUNCTIONS ============ */
  373.  
  374. /* ========================= MULTI HEAP MALLOC ========================== */
  375. /*
  376.    NOTE: In a demand paged environment, this implementation of malloc
  377.          (using skip_lists) can be ENORMOUSLY faster than buddy_block
  378.          style mallocs.
  379. */
  380. void *mallocC(int category, unsigned amount);
  381. void *callocC(int category, unsigned nelems, unsigned elemsize);
  382. void *reallocC(int category, void* buf, unsigned newsize);
  383. void freeC(int category, void* buf);
  384. void freecat(int category);
  385. int memrangeC(int category, unsigned* minp, unsigned* maxp);
  386. int usedrangeC(int category, unsigned* minp, unsigned* maxp);
  387. void totrangeC(unsigned* minp,unsigned* maxp);
  388. void *heapcheckC(int category, void *start);
  389. void guardC(int category);
  390. void *memalignC(int category, unsigned alignment, unsigned req);
  391.  
  392. #define PAGESIZE VGETPAGESIZE()
  393. #define ALIGNMENTM (sizeof(unsigned long))
  394. #define MAL_MAXLEVEL (12)
  395. #define ROUNDINGM(a) ((ALIGNMENTM-(a&(ALIGNMENTM-1)))&(ALIGNMENTM-1))
  396. #define ALLOCSIZE (4096)
  397. #define FRNTGUARD (0x544e5246UL)
  398. #define BACKGUARD (0x48434142UL)
  399. #define THEWELL do_sbrk
  400.  
  401. #define NUMTYPES 3
  402. #define SIZEH 0
  403. #define FREEH 1
  404. #define USEDH 2
  405.  
  406. #define SKIPVARS NodePM update[MAL_MAXLEVEL+1];NodePM node,prev;int level
  407.  
  408. #define DELETENODE(TYPE) \
  409. {for(level=0;level<=bp->TYPE##level; level++)\
  410. {if(update[level]->fptr[level] == node)\
  411. update[level]->fptr[level] = node->fptr[level];else break;}\
  412. while(bp->TYPE##level>0 && bp->TYPE##header->fptr[bp->TYPE##level]==_NILLL)\
  413. bp->TYPE##level--;free_Mnode(bp,node,TYPE);}
  414.  
  415. #define INSERT() \
  416. {while(level >= 0){\
  417. node->fptr[level] = update[level]->fptr[level];\
  418. update[level]->fptr[level] = node;level--;}}
  419.  
  420. #define SETLEVEL(TYPE) \
  421. {level = getMlevel(bp, bp->TYPE##level);\
  422. while(bp->TYPE##level < level)update[++bp->TYPE##level]=bp->TYPE##header;}
  423.  
  424. #define FINDKEY(TYPE, KEYVAL)\
  425. {node = bp->TYPE##header;\
  426. for(level = bp->TYPE##level; level >= 0; level--){\
  427. while(node->fptr[level]->key < KEYVAL)\
  428. node = node->fptr[level];\
  429. update[level] = node;}prev=node;node=node->fptr[0];}
  430.  
  431. #define DETACH(SN)\
  432. {SN->bptr->fptr=SN->fptr;if(SN->fptr)SN->fptr->bptr=SN->bptr;}
  433.  
  434. #define UNLINK(SN, N)\
  435. {if(!sp->fptr&&sp->bptr->bptr<=(AddrP)(MAL_MAXLEVEL+1))dsize[N]=sp->size;\
  436. DETACH(SN);free_addr(bp,SN);}
  437.  
  438. #define CHECKGUARDS(MSG)\
  439. {if(bp->guarded){\
  440. unsigned *p2;\
  441. p2 = (void*)((char*)address+cursize-ALIGNMENTM);\
  442. if(*address != FRNTGUARD)\
  443. VCRASH(#MSG ":%d: corrupted at 0x%x\n", bp->bincat, addr);\
  444. if(*p2 != BACKGUARD)\
  445. VCRASH(#MSG ":%d: corrupted by 0x%x\n", bp->bincat, addr);}}
  446.  
  447. #if MEMORY_BUG == 1
  448. #define HEAPCHECK \
  449. {void *lastaddr;\
  450. if(category > 0){\
  451. guardC(category);\
  452. if((lastaddr = heapcheckC(category, NULL))){\
  453. FINDKEY(USEDH, (unsigned)lastaddr-ALIGNMENTM)\
  454. BUGPRINTF("bad heap at %x c:%u size=%u\n", lastaddr, category, node->value);\
  455. (void)print_rawdata(lastaddr-ALIGNMENTM, node->value);\
  456. VABORT();}}}
  457. #else
  458. #define HEAPCHECK
  459. #endif
  460.  
  461. struct _catlocs {
  462.     void *addr;
  463.     struct _catlocs *fptr;
  464. };
  465.  
  466. typedef struct _nodeM
  467. {
  468.     unsigned key;
  469.     unsigned value;
  470.     unsigned levels;    /* must always be after value */
  471.     struct _nodeM *fptr[1];
  472. } NodeM, *NodePM;
  473.  
  474. typedef struct _addr
  475. {
  476.     struct _addr *fptr;
  477.     struct _addr *bptr;
  478.     NodePM maddr;
  479.     unsigned size;
  480. } *AddrP;
  481.  
  482. struct _bins {
  483.     unsigned bits;
  484.     unsigned nbits;
  485.     NodePM SIZEHheader;
  486.     int SIZEHlevel;
  487.     NodePM FREEHheader;
  488.     int FREEHlevel; 
  489.     NodePM USEDHheader;
  490.     int USEDHlevel;
  491.  
  492.     unsigned bincat;
  493.     unsigned maxloc;
  494.     unsigned minloc;
  495.     struct _catlocs *catlocs;
  496.     struct _bins *fptr;
  497.     NodePM freenodes[NUMTYPES][MAL_MAXLEVEL+2];
  498.     struct _addr *freeaddrlocs;
  499.     char *chunkbase[NUMTYPES];
  500.     int chunksize[NUMTYPES];
  501.     int guarded;
  502.     int addrbump;
  503. };
  504.  
  505. static struct _bins zbp;
  506. static struct _bins *hmap[1009];
  507. static struct _nodeM _nilll = {0xffffffff,0,0,{0}};
  508. static struct _nodeM *_NILLL = &_nilll;
  509. static unsigned maxloc;
  510. static unsigned minloc;
  511. static struct _bins *freebinlocs;
  512. static struct _catlocs *freecatlocs;
  513. static char *binbase;
  514. static int binsize;
  515. static int chunksizes[] = {ALLOCSIZE,3*ALLOCSIZE,2*ALLOCSIZE};
  516.  
  517.  
  518. static long randtbl[32]    = { 0L,
  519.     0x9a319039L, 0x32d9c024L, 0x9b663182L, 0x5da1f342L, 
  520.     0xde3b81e0L, 0xdf0a6fb5L, 0xf103bc02L, 0x48f340fbL, 
  521.     0x7449e56bL, 0xbeb1dbb0L, 0xab5c5918L, 0x946554fdL, 
  522.     0x8c2e680fL, 0xeb3d799fL, 0xb11ee0b7L, 0x2d436b86L, 
  523.     0xda672e2aL, 0x1588ca88L, 0xe369735dL, 0x904f35f7L, 
  524.     0xd7158fd6L, 0x6fa6f051L, 0x616e6b96L, 0xac94efdcL, 
  525.     0x36413f93L, 0xc622c298L, 0xf5a42ab8L, 0x8a88d77bL, 
  526.     0xf5ad9d0eL, 0x8999220bL, 0x27fb47b9L
  527. };
  528.  
  529. static  long *fptr    = &randtbl[4];
  530. static  long *rptr    = &randtbl[1];
  531.  
  532.  
  533. /* ================== THE CRASH FUNCTION IS FIRST IN .TEXT ================ */
  534. static void
  535. lcrash(char *msg, ...)
  536. {
  537.     VVPRINTF(msg, &msg+1);
  538. /*    CFEXIT();*/
  539.     *((char *)0) = 0;    /* force exception */
  540. }
  541. #if PRINT_RAWDATA == 1
  542. static char
  543. hexbyte(unsigned int c)
  544. {
  545. char x = c & 0xf;
  546.  
  547.     return x + ((x>9) ? 55 : 48);
  548. }
  549. static void
  550. print_rawdata(void *rawdata, long size)
  551. {
  552. unsigned long vaddr = 0;
  553. unsigned char *d = rawdata;
  554. int i,j;
  555. char addr[9];
  556. char hex1[24];
  557. char hex2[24];
  558. char side1[9];
  559. char side2[9];
  560.  
  561.     addr[8] = 0;
  562.     hex1[23] = 0;
  563.     hex2[23] = 0;
  564.     side1[8] = 0;
  565.     side2[8] = 0;
  566.     while(size > 0)
  567.     {
  568.     unsigned long qaddr = vaddr;
  569.         memset(addr, '0', 8);
  570.         memset(hex1, ' ', 23);
  571.         memset(hex2, ' ', 23);
  572.         memset(side1, ' ', 8);
  573.         memset(side2, ' ', 8);
  574.         i = 7;
  575.         while(qaddr)
  576.         {
  577.             addr[i--] = hexbyte(qaddr);
  578.             qaddr >>= 4;
  579.         }
  580.         for(i=0,j=0; i < 8; ++i)
  581.         {
  582.             if(--size >= 0)
  583.             {
  584.             unsigned int c = *d++;
  585.                 if(isprint(c))
  586.                     side1[i] = c;
  587.                 else
  588.                     side1[i] = '.';
  589.                 hex1[j++] = hexbyte(c>>4);
  590.                 hex1[j++] = hexbyte(c);
  591.                     ++j;
  592.             }
  593.             else break;
  594.         }
  595.         for(i=0,j=0; i < 8; ++i)
  596.         {
  597.             if(--size >= 0)
  598.             {
  599.             unsigned int c = *d++;
  600.                 if(isprint(c))
  601.                     side2[i] = c;                    
  602.                 else
  603.                     side2[i] = '.';
  604.                 hex2[j++] = hexbyte(c>>4);
  605.                 hex2[j++] = hexbyte(c);
  606.                 ++j;
  607.             }
  608.             else break;
  609.         }
  610.         BUGPRINTF("%s  %s%s%s  %s%s%s\n",addr,hex1," | ",hex2,side1,"|",side2);
  611.         vaddr += 16;
  612.     }
  613. }
  614. #endif
  615.  
  616. /*
  617.  * Returns a really good 31-bit random number.
  618.  */
  619. static long
  620. lrandom()
  621. {
  622. long i;
  623.     
  624.     *fptr += *rptr;
  625.     i = (*fptr >> 1) & 0x7fffffffUL;
  626.     if(++fptr > &randtbl[31])
  627.     {
  628.         fptr = &randtbl[1];
  629.         ++rptr;
  630.     }
  631.     else
  632.     {
  633.         if(++rptr > &randtbl[31])  
  634.             rptr = &randtbl[1];
  635.     }
  636.     return( i );
  637. }
  638.  
  639. static void *
  640. do_sbrk(unsigned amount)
  641. {
  642. void *address;
  643.  
  644.     address = VSBRK(amount);    /* OR WHATEVER TO ACCESS THE OPERATING SYSTEM */
  645.     if(address == (void*)-1)
  646.     {
  647.         VCRASH("\nskel: system out of memory, requested %u bytes\n", amount);
  648.     }
  649.     return address;
  650. }
  651. static struct _catlocs *
  652. new_catloc(void)
  653. {
  654. struct _catlocs *p;
  655.     if((p=freecatlocs))
  656.     {
  657.         freecatlocs = p->fptr;
  658.         return p;
  659.     }
  660.     if(binsize < sizeof(struct _catlocs))
  661.     {
  662.         binbase = THEWELL(4096);
  663.         binsize = 4096;
  664. MPRINTF("NEWCATLOC at:%p size=4096\n", binbase);
  665.     }
  666.     binsize -= sizeof(struct _catlocs);
  667.     p = (void*)binbase;
  668.     binbase += sizeof(struct _catlocs);
  669.     return p;
  670. }
  671. static void
  672. free_catloc(struct _catlocs *p)
  673. {
  674.     p->fptr = freecatlocs;
  675.     freecatlocs = p;
  676. }
  677. static void *
  678. new_chunk(struct _bins *bp, int size, int type)
  679. {
  680. char *p;
  681.      if(bp->chunksize[type] < size)
  682.     {
  683.         if(bp->bincat == 0) {
  684.             bp->chunkbase[type] = THEWELL(chunksizes[type]);
  685.             bp->chunksize[type] = chunksizes[type];
  686. MPRINTF("NEWCHUNK0 at:%p size=%d\n", bp->chunkbase[type], bp->chunksize[type]);
  687.         }
  688.         else {
  689.         struct _catlocs *cl;
  690.             bp->chunkbase[type] = mallocC(0,chunksizes[type]-zbp.guarded);
  691.             bp->chunksize[type] = chunksizes[type]-zbp.guarded;
  692.             cl = new_catloc();
  693.             cl->addr = bp->chunkbase[type];
  694.             cl->fptr = bp->catlocs;
  695.             bp->catlocs = cl;
  696. MPRINTF("NEWCHUNK%d at:%p size=%d\n", bp->bincat, bp->chunkbase[type], bp->chunksize[type]);
  697.         }
  698.     }
  699.     bp->chunksize[type] -= size;
  700.     p = bp->chunkbase[type];
  701.     bp->chunkbase[type] += size;
  702.     return p;
  703. }
  704. static void *
  705. new_Mnode(struct _bins *bp, int levels, int type)
  706. {
  707. int size;
  708. NodePM p;
  709.  
  710.     if((p=bp->freenodes[type][levels]))
  711.     {
  712.         bp->freenodes[type][levels] = p->fptr[0];
  713.         p->value = 0;
  714.         return p;
  715.     }
  716.      size = sizeof(struct _nodeM) + levels * sizeof(void*);
  717.     p = new_chunk(bp, size, type);
  718.     p->levels = levels;
  719.     p->value = 0;
  720.     return p;    
  721. }
  722. static void
  723. free_Mnode(struct _bins *bp, NodePM p, int type)
  724. {
  725.     p->fptr[0] = bp->freenodes[type][p->levels];
  726.     bp->freenodes[type][p->levels] = p;
  727. }
  728. static struct _addr *
  729. new_addr(struct _bins *bp)
  730. {
  731. struct _addr *p;
  732.     if((p=bp->freeaddrlocs))
  733.     {
  734.         bp->freeaddrlocs = p->fptr;
  735.         return p;
  736.     }
  737.     return new_chunk(bp, sizeof(struct _addr), FREEH);
  738. }
  739. static void
  740. free_addr(struct _bins *bp, struct _addr *p)
  741. {
  742.     p->fptr = bp->freeaddrlocs;
  743.     bp->freeaddrlocs = p;
  744. }
  745. static struct _bins *
  746. new_bins(void)
  747. {
  748. struct _bins *p;
  749.     if((p=freebinlocs))
  750.     {
  751.         freebinlocs = p->fptr;
  752.         return p;
  753.     }
  754.      if(binsize < sizeof(struct _bins))
  755.     {
  756.         binbase = THEWELL(4096);
  757.         binsize = 4096;
  758. MPRINTF("NEWBINS at:%p size=4096\n", binbase);
  759.     }
  760.     binsize -= sizeof(struct _bins);
  761.     p = (struct _bins*)binbase;
  762.     binbase += sizeof(struct _bins);
  763.     return p;
  764. }
  765. static void
  766. free_bins(struct _bins *p)
  767. {
  768.     p->fptr = freebinlocs;
  769.     freebinlocs = p;
  770. }
  771. static int
  772. getMlevel (struct _bins *p, int binlevel)
  773. {
  774. int level = -1;
  775. int bits = 0;
  776.  
  777.     while(bits == 0)
  778.     {
  779.         if (p->nbits == 0)
  780.         {
  781.             p->bits = lrandom();
  782.             p->nbits = 15;
  783.         }
  784.         bits = p->bits & 3;
  785.         p->bits >>= 2;
  786.         p->nbits--;
  787.  
  788.         if(++level > binlevel)
  789.             break;
  790.     }
  791.     return (level > MAL_MAXLEVEL) ? MAL_MAXLEVEL : level;
  792. }
  793.  
  794. static void
  795. init_bins(struct _bins *bp, int category)
  796. {
  797. int i;
  798. int binnum = category % 1009;
  799.  
  800.     bzero(bp, sizeof(struct _bins));
  801.     bp->bincat = category;
  802.     bp->minloc = 0xffffffff;
  803.     bp->fptr = hmap[binnum];
  804.     hmap[binnum] = bp;
  805.     bp->SIZEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, SIZEH);
  806.     bp->FREEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, FREEH);
  807.     bp->USEDHheader = new_Mnode(bp, MAL_MAXLEVEL+1, USEDH);
  808.  
  809.     for(i = 0; i <= MAL_MAXLEVEL; ++i)
  810.     {
  811.         bp->SIZEHheader->fptr[i] = _NILLL;
  812.         bp->FREEHheader->fptr[i] = _NILLL;
  813.         bp->USEDHheader->fptr[i] = _NILLL;
  814.     }
  815. }
  816.  
  817. static struct _bins*
  818. getcat(int category)
  819. {
  820. struct _bins *hbp;
  821.  
  822.     hbp = hmap[category % 1009];
  823.     while(hbp)
  824.     {
  825.         if(hbp->bincat == category)
  826.             return hbp;
  827.         hbp = hbp->fptr;
  828.     }
  829.     return 0;
  830. }
  831. static struct _bins *
  832. initcat(int category)
  833. {
  834. struct _bins *bp;
  835.  
  836.     if(category == 0)
  837.     {
  838.         bp = &zbp;
  839.         if(zbp.SIZEHheader == 0)
  840.             init_bins(bp, category);
  841.         return bp;
  842.     }
  843.     /* do this to set zbp.guarded properly on startup */
  844.     if(zbp.SIZEHheader == 0)
  845.         initcat(0);
  846.  
  847.     if((bp = new_bins()))
  848.     {
  849.         init_bins(bp, category);
  850.         return bp;
  851.     }
  852.     return 0;
  853. }
  854. static void *
  855. getspace(struct _bins *bp, unsigned size, unsigned *remainder)
  856. {
  857. unsigned desired;
  858. void *address;
  859.   
  860.     desired = ((size+ALLOCSIZE-1)/ALLOCSIZE)*ALLOCSIZE;
  861.     if(bp->bincat == 0)
  862.     {
  863.         address = THEWELL(desired);
  864.         *remainder = desired - size;
  865. MPRINTF("GETSPACE at:%p size=%d\n", address, desired);
  866.     }
  867.     else
  868.     {
  869.     struct _catlocs *cl;
  870.  
  871.         if((desired-size) > zbp.guarded)
  872.             desired -= zbp.guarded;
  873.         
  874.         address = mallocC(0, desired);
  875.         *remainder = desired - size;
  876.  
  877.         /* save the gross allocations for the category */
  878.         cl = new_catloc();
  879.         cl->addr = address;
  880.         cl->fptr = bp->catlocs;
  881.         bp->catlocs = cl;
  882.     }
  883.     /* maintain address range info */
  884.     if((unsigned)address < bp->minloc)
  885.         bp->minloc = (unsigned)address;
  886.     if(((unsigned)address + desired) > bp->maxloc)
  887.         bp->maxloc = (unsigned)address + desired;
  888.      if(bp->minloc < minloc)
  889.          minloc = bp->minloc;
  890.      if(bp->maxloc > maxloc)
  891.          maxloc = bp->maxloc;
  892.     return address;
  893. }
  894. static void
  895. addto_sizelist(struct _bins *bp, AddrP ap)
  896. {
  897. SKIPVARS;
  898.  
  899.     /* INSERT IN SIZE LIST */
  900.     FINDKEY(SIZEH, ap->size)
  901.  
  902.     if(node->key == ap->size)
  903.     {/* size node exists */
  904.         ap->fptr = (AddrP)node->value;
  905.         ap->bptr = (AddrP)&node->value;
  906.         if(ap->fptr) ap->fptr->bptr = ap;
  907.         node->value = (unsigned)ap;
  908.     }
  909.     else
  910.     {/* create new size node */
  911.         SETLEVEL(SIZEH)
  912.         node = new_Mnode(bp, level, SIZEH);
  913.         node->key = ap->size;
  914.         node->value = (unsigned)ap;
  915.         ap->fptr = 0;
  916.         ap->bptr = (AddrP)&node->value;
  917.         INSERT()
  918.     }
  919. }
  920. static void
  921. addto_freelist(struct _bins *bp, void *addr, unsigned size)
  922. {
  923. SKIPVARS;
  924. AddrP ap,sp;
  925. unsigned dsize[2];
  926.  
  927.     /* GET NEW ADDR STRUCT */
  928.     ap = new_addr(bp);
  929.     ap->size = size;
  930.  
  931.     dsize[1] = dsize[0] = 0; /* sizenode deletion markers */
  932.  
  933.     /* CHECK FREE LIST */
  934.     FINDKEY(FREEH, (unsigned)addr)
  935.  
  936.     /* CHECK FOR MERGE OR INSERT */
  937.     if(prev->value && prev->key+((AddrP)prev->value)->size == (unsigned)addr)
  938.     {/* merge with previous block */
  939.         ap->size += ((AddrP)prev->value)->size;
  940.  
  941.         if(prev->key + ap->size == node->key)
  942.         {/* merge with previous and next block */
  943.             sp = (AddrP) node->value;;
  944.             ap->size += sp->size;
  945.  
  946.             /* delete size struct for next block */
  947.             UNLINK(sp, 0)
  948.  
  949.             /* delete next block */
  950.             DELETENODE(FREEH);
  951.         }
  952.         /* delete size struct for prev block */
  953.         sp = (AddrP)prev->value;
  954.         UNLINK(sp, 1)
  955.  
  956.         /* set new address struct */
  957.         prev->value = (unsigned)ap;
  958.         ap->maddr = prev;
  959.     }
  960.     else if(node->value && (char*)addr + size == (void*)node->key)
  961.     {/* merge with next block */
  962.         sp = (AddrP) node->value;;
  963.         node->key = (unsigned)addr;
  964.         ap->size += sp->size;
  965.  
  966.         /* unlink size struct for next block */
  967.         UNLINK(sp,0)
  968.  
  969.         /* set new address struct */
  970.         node->value = (unsigned)ap;
  971.         ap->maddr = node;
  972.     }
  973.     else
  974.     {/* insert in free list */
  975.  
  976.         SETLEVEL(FREEH)
  977.         node = new_Mnode(bp, level, FREEH);
  978.         node->key = (unsigned)addr;
  979.         node->value = (unsigned)ap;
  980.         ap->maddr = node;
  981.         INSERT()
  982.     }
  983.     addto_sizelist(bp, ap);
  984.  
  985.     /* Remove sizenodes eliminated by merge */
  986.     if(dsize[0])
  987.     {
  988.         FINDKEY(SIZEH, dsize[0])
  989.         if(node->value == 0)
  990.           DELETENODE(SIZEH)
  991.     }
  992.     if(dsize[1])
  993.     {
  994.         FINDKEY(SIZEH, dsize[1])
  995.         if(node->value == 0)
  996.           DELETENODE(SIZEH)
  997.     }
  998. }
  999.  
  1000. void* 
  1001. memalignC(int category, unsigned alignment, unsigned req)
  1002. {
  1003. SKIPVARS;
  1004. NodePM fnode;
  1005. unsigned remainder;
  1006. unsigned *address;
  1007. struct _bins *bp;
  1008. unsigned mask, size;
  1009.  
  1010.  
  1011.     if(!(bp = getcat(category)))
  1012.       if(!(bp = initcat(category)))
  1013.         return 0;
  1014. HEAPCHECK
  1015.     if(req == 0)
  1016.         req = ALIGNMENTM;
  1017.     else
  1018.         req += ROUNDINGM(req);
  1019.     size = req += bp->guarded;
  1020.  
  1021.     if(alignment)
  1022.     {
  1023.         alignment += ROUNDINGM(alignment);
  1024.         if(alignment > ALIGNMENTM)
  1025.         {
  1026.             mask = alignment -1;
  1027.             size = req + alignment + bp->guarded;
  1028.         }
  1029.         else
  1030.         {
  1031.             alignment = 0;
  1032.         }
  1033.     }
  1034.  
  1035.     /* check sizelist for candidate */
  1036.     FINDKEY(SIZEH, size)
  1037.     fnode = node;
  1038. trynext:
  1039.     if(node->key != 0xffffffff)
  1040.     {/* found an appropriately sized block */
  1041.     AddrP sp = (AddrP)node->value;
  1042.  
  1043.         if(!sp && node == fnode)
  1044.         {
  1045.         NodePM q;
  1046.             q = node->fptr[0];
  1047.             DELETENODE(SIZEH)
  1048.             node = q;
  1049.             goto trynext;
  1050.         }
  1051.         if(!sp)
  1052.         {/* no available space at this size */
  1053.             node = node->fptr[0];
  1054.             goto trynext;
  1055.         }
  1056.  
  1057.         /* extract some space from this block */
  1058.         remainder = node->key - size;
  1059.         address = (void*)sp->maddr->key;
  1060.         sp->maddr->key += size;
  1061.         DETACH(sp);
  1062.  
  1063.         if(node->value == 0)
  1064.         {/* no more blocks of this size, delete sizenode */
  1065.             if(node != fnode)
  1066.               FINDKEY(SIZEH, size)
  1067.             DELETENODE(SIZEH)
  1068.         }
  1069.  
  1070.         if(remainder == 0)
  1071.         {/* no remaining space,the node in freelist is exhausted, delete it */
  1072.             FINDKEY(FREEH, sp->maddr->key)
  1073.             DELETENODE(FREEH)
  1074.             free_addr(bp, sp);
  1075.         }
  1076.         else
  1077.         {/* space remains in block, move it to new size loc */
  1078.             sp->size = remainder;
  1079.             addto_sizelist(bp, sp);
  1080.         }
  1081.     }
  1082.     else
  1083.     {
  1084.         address = getspace(bp, size, &remainder);
  1085.         if(remainder)
  1086.           addto_freelist(bp, ((char*)address)+size, remainder);
  1087.     }
  1088.     if(alignment)
  1089.     {
  1090.     unsigned diff;
  1091.         if((diff = (unsigned)address & mask))
  1092.         {/* move address forward */
  1093.         char *naddress;
  1094.         unsigned lose;
  1095.             lose = alignment - diff;
  1096.             naddress = (char*)address + lose;
  1097.             addto_freelist(bp, address, lose);
  1098.             address = (unsigned*)naddress;
  1099.         }
  1100.     }
  1101.     if(bp->guarded)
  1102.     {
  1103.       *address = FRNTGUARD;
  1104.       *((unsigned*)(((char*)address)+req-ALIGNMENTM)) = BACKGUARD;
  1105.  
  1106.     }
  1107.  
  1108.     FINDKEY(USEDH, (unsigned)address)
  1109.  
  1110.     if(node->key == (unsigned)address) {
  1111.       VCRASH("allocC:%d: bookkeeping nodes are corrupted at:0x%x\n",
  1112.           category, address);
  1113.     }
  1114.     SETLEVEL(USEDH)
  1115.     node = new_Mnode(bp, level, USEDH);
  1116.     node->key = (unsigned)address;
  1117.     node->value = req;
  1118.     INSERT()    
  1119.  
  1120.     return address+bp->addrbump;
  1121. }
  1122. void*
  1123. callocC(int category, unsigned cnt, unsigned elem_size)
  1124. {
  1125. unsigned size = cnt * elem_size;
  1126. void* buf;;
  1127.  
  1128.   if((buf = mallocC(category, size)))
  1129.       bzero(buf, size);
  1130.   return buf;
  1131. };
  1132. void
  1133. freeC(int category, void* addr)
  1134. {
  1135. unsigned cursize;
  1136. unsigned *address;
  1137. struct _bins *bp;
  1138. SKIPVARS;
  1139.     if(addr)
  1140.     {
  1141.         if(!(bp = getcat(category))) {
  1142.             VCRASH("freeC:%d: non-existant category at:0x%x\n",category,addr);
  1143.         }
  1144. HEAPCHECK
  1145.         address = (void*) ((unsigned*)addr - bp->addrbump);
  1146.         FINDKEY(USEDH, (unsigned)address)
  1147.         if(node->key != (unsigned)address) {
  1148.           VCRASH("freeC:%d: bogus address=0x%x\n", category, addr);
  1149.         }
  1150.         cursize = node->value;
  1151.         CHECKGUARDS(freeC)
  1152.         DELETENODE(USEDH)
  1153.  
  1154.         addto_freelist(bp, address, cursize);
  1155.     }
  1156.     else VCRASH("freeC:%d: null pointer\n", category);
  1157. }
  1158. void* 
  1159. reallocC(int category, void* addr, unsigned newsize)
  1160. {
  1161. SKIPVARS;
  1162. unsigned cursize;
  1163. unsigned *address;
  1164. struct _bins *bp;
  1165. NodePM onode;
  1166.  
  1167.     if(addr == 0) 
  1168.         return mallocC(category, newsize);
  1169.     else
  1170.     {
  1171.         if(!(bp = getcat(category))) {
  1172.            VCRASH("reallocC:%d: non-existant category at:%x\n",category,addr);
  1173.         }
  1174. HEAPCHECK 
  1175.         if(newsize == 0)
  1176.             newsize = ALIGNMENTM;
  1177.         else
  1178.             newsize += ROUNDINGM(newsize);
  1179.         newsize += bp->guarded;
  1180.  
  1181.         address = (void*)(((char*)addr)-(bp->guarded/2));
  1182.         FINDKEY(USEDH, (unsigned)address)
  1183.         if(node->key != (unsigned)address) {
  1184.           VCRASH("reallocC:%d: bogus address=0x%x\n", category, addr);
  1185.         }
  1186.         cursize = node->value;
  1187.         node->value = newsize;
  1188.         onode = node;
  1189.  
  1190.         CHECKGUARDS(reallocC)
  1191.  
  1192.         if(newsize == cursize)
  1193.             return addr;
  1194.         if(newsize > cursize)
  1195.         {/* check if block can be extended */
  1196.         void *taddr = ((char*)address) + cursize;
  1197.         unsigned extendsize = newsize-cursize;
  1198.  
  1199.             /* check freelist for an available block at the right address */
  1200.             FINDKEY(FREEH, (unsigned)taddr)
  1201.             if(node->key == (unsigned)taddr)
  1202.             {
  1203.             AddrP sp = (AddrP)node->value;
  1204.                 if(sp->size >= extendsize)
  1205.                 {/* BLOCK CAN BE EXTENDED INTERNALLY */
  1206.                     node->key += extendsize;
  1207.                     sp->size -= extendsize;
  1208.                     DETACH(sp)
  1209.                     if(sp->size == 0)
  1210.                     {/* the extension block is used up, delete this node */
  1211.                         free_addr(bp, sp);
  1212.                         DELETENODE(FREEH)
  1213.                     }
  1214.                     else
  1215.                     {/* shift the remainder in the sizelist */
  1216.                         addto_sizelist(bp, sp);
  1217.                     }
  1218.                     /* SUCCESS */
  1219.                     if(bp->guarded)
  1220.                     {
  1221.                         *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
  1222.                             = BACKGUARD;
  1223.                     }
  1224.                     return addr;
  1225.                 }
  1226.             }
  1227.             /* HERE WE COULD CHECK OTHER SOURCES OF SPACE */
  1228.  
  1229.             /* can't extend block, malloc some new space */
  1230.             if((taddr = mallocC(category,newsize-bp->guarded)))
  1231.             {
  1232.                 memmove(taddr,addr,cursize-bp->guarded);
  1233.                 onode->value = cursize;
  1234.                 freeC(category, addr);
  1235.             }
  1236.             /* SUCCESS */
  1237.             return taddr;
  1238.         }
  1239.         else
  1240.         {/* shrink block */
  1241.             if(bp->guarded)
  1242.             {
  1243.                 *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
  1244.                     = BACKGUARD;
  1245.             }
  1246.             addto_freelist(bp, ((char*)address)+newsize, cursize-newsize); 
  1247.             return addr;
  1248.         }
  1249.       }
  1250. }
  1251. void
  1252. freecat(int category)
  1253. {
  1254. struct _bins *bp;
  1255.  
  1256.     if(category == 0)
  1257.         return;
  1258.  
  1259.     if((bp = getcat(category)))
  1260.     {
  1261.     struct _catlocs *cl = bp->catlocs;
  1262.     struct _bins *hbp;
  1263.     struct _bins *prev;
  1264.  
  1265.         while(cl)
  1266.         {/* Space allocated to the category is moved to category 0 */
  1267.         void *ql = cl->fptr;
  1268.  
  1269.             freeC(0, cl->addr);
  1270.             free_catloc(cl);
  1271.             cl = ql;
  1272.         }
  1273.         /* space for the _bins struct is placed on a free list */
  1274.         hbp = hmap[category % 1009];
  1275.         prev = 0;
  1276.         while(hbp)
  1277.         {
  1278.             if(hbp->bincat == category)
  1279.             {
  1280.                 if(prev == 0)
  1281.                     hmap[category % 1009] = hbp->fptr;
  1282.                 else
  1283.                     prev->fptr = hbp->fptr;
  1284.                 free_bins(hbp);
  1285.                 return;
  1286.             }
  1287.             prev = hbp;
  1288.             hbp = hbp->fptr;
  1289.         }
  1290.     }
  1291. }
  1292. int
  1293. memrangeC(int category, unsigned *min, unsigned *max)
  1294. {
  1295. struct _bins *bp;
  1296.  
  1297.     if((bp = getcat(category)))
  1298.     {
  1299.         *min = bp->minloc;
  1300.         *max = bp->maxloc;
  1301.         return 1;
  1302.     }
  1303.     return 0;
  1304. }
  1305. int
  1306. usedrangeC(int category, unsigned *min, unsigned *max)
  1307. {
  1308. struct _bins *bp;
  1309. NodePM node;
  1310. int level;
  1311.  
  1312.     if((bp = getcat(category)))
  1313.     {
  1314.         node = bp->USEDHheader;
  1315.         *min = node->fptr[0]->key;
  1316.         for(level = bp->USEDHlevel; level >= 0; level--)
  1317.           while(node->fptr[level]->key < 0xffffffff)
  1318.             node = node->fptr[level];
  1319.         *max = node->key;
  1320.         return 1;
  1321.     }
  1322.     return 0;
  1323. }
  1324. void
  1325. totrangeC(unsigned *min, unsigned *max)
  1326. {
  1327.     *min = minloc;
  1328.     *max = maxloc;
  1329. }
  1330. void
  1331. guardC(int category)
  1332. {
  1333. struct _bins *bp;
  1334.  
  1335.     if(!(bp = getcat(category)))
  1336.       if(!(bp = initcat(category)))
  1337.           return;
  1338.  
  1339.     if(!bp->guarded)
  1340.     {
  1341.         bp->guarded = 2*ALIGNMENTM;
  1342.         bp->addrbump = 1;
  1343.     }
  1344. }
  1345. void*
  1346. heapcheckC(int category, void *start)
  1347. {
  1348. struct _bins *bp;
  1349. NodePM node,prev;
  1350. unsigned *p1,*p2;
  1351.  
  1352.     if((bp = getcat(category)))
  1353.     {
  1354.         if(bp->guarded)
  1355.         {
  1356.             prev = 0;
  1357.             node = bp->USEDHheader;
  1358.             while(        (node = node->fptr[0]) != (NodePM)0xffffffff
  1359.                     &&    node->key != 0xffffffffUL)
  1360.             {
  1361.                 if((void*)node->key > start)
  1362.                 {
  1363.                     p1 = (unsigned*)node->key;
  1364.                     if(*p1 != FRNTGUARD)
  1365.                     {
  1366.                         if(prev)
  1367.                             return (char*)prev->key+ALIGNMENTM;
  1368.                         else
  1369.                             return (void*)1;
  1370.                     }
  1371.                     p2 = (unsigned*)(((char*)p1)+node->value-ALIGNMENTM);
  1372.                     if(*p2 != BACKGUARD)
  1373.                         return (char*)node->key+ALIGNMENTM;
  1374.                 }
  1375.                 prev = node;
  1376.             }
  1377.         }
  1378.     }
  1379.     return 0;
  1380. }
  1381. void* 
  1382. mallocC(int category, unsigned size)
  1383. {
  1384.     return memalignC(category, 0, size);
  1385. }
  1386.  
  1387. void* 
  1388. vallocC(int category, unsigned bytes)
  1389. {
  1390.   return memalignC (category, PAGESIZE, bytes);
  1391. }
  1392. unsigned
  1393. mallocsizeC(int category, void* addr)
  1394. {
  1395. struct _bins *bp;
  1396. SKIPVARS;
  1397.  
  1398.     if(addr && (bp = getcat(category)))
  1399.     {
  1400.     unsigned address = (unsigned)((unsigned*)addr - bp->addrbump);
  1401.         FINDKEY(USEDH, address)
  1402.         if(node->key == address)
  1403.             return node->value - bp->guarded;
  1404.     }
  1405.     return 0;
  1406. }
  1407.  
  1408. int
  1409. NewMallocCategory(void)
  1410. {
  1411. static unsigned int cat = BASE_CATEGORY;
  1412.     return ++cat;
  1413. }
  1414. /* ====================== END MULTI-HEAP MALLOC ============================ */
  1415.  
  1416.  
  1417. /* These are here to prevent the system malloc from being linked */
  1418. void *
  1419. malloc(unsigned a)
  1420. {
  1421. void *result = mallocC(BASE_CATEGORY, a);
  1422. MPRINTF("malloc %d bytes at %p caller=%x\n", a, result, ((unsigned *)&a)[-1]);
  1423.     return result;
  1424. }
  1425. void
  1426. free(void *a)
  1427. {
  1428. MPRINTF("free at %p caller=%x\n", a, ((unsigned*)&a)[-1]);
  1429.     freeC(BASE_CATEGORY,a);
  1430. }
  1431. void *
  1432. realloc(void *a, unsigned b)
  1433. {
  1434. void *result = reallocC(BASE_CATEGORY,a,b);
  1435. MPRINTF("realloc %d bytes at %p old=%p caller=%x\n",
  1436.     b, result, a, ((unsigned*)&a)[-1]);
  1437.     return result;
  1438. }
  1439. void *
  1440. calloc(unsigned a, unsigned b)
  1441. {
  1442. void *result = callocC(BASE_CATEGORY,a,b);
  1443. MPRINTF("calloc %d bytes at %p caller=%x\n", a*b, result, ((unsigned*)&a)[-1]);
  1444.     return result;
  1445. }
  1446. void *
  1447. valloc(unsigned a)
  1448. {
  1449. void *result = vallocC(BASE_CATEGORY,a);
  1450. MPRINTF("valloc %d bytes at %p caller=%x\n", a, result, ((unsigned *)&a)[-1]);
  1451.     return result;
  1452. }
  1453. void *
  1454. memalign(unsigned a, unsigned b)
  1455. {
  1456. void *result = memalignC(BASE_CATEGORY,a,b);
  1457. MPRINTF("memalign(%u) %u bytes at %p caller=%x\n",
  1458.     a,b,result,((unsigned *)&a)[-1]);
  1459.     return result;
  1460. }
  1461. unsigned
  1462. mallocsize(void *a)
  1463. {
  1464.     return mallocsizeC(BASE_CATEGORY, a);
  1465. }
  1466.  
  1467. static int 
  1468. lnulfunc()
  1469. {
  1470.     return 0;
  1471. }
  1472. static void 
  1473. lhash(void *keyptr, int cnt, CAT *cat)
  1474. {/* THIS FUNCTION IS IDENTICAL TO 'key_hash' in CFF */
  1475. STOR  value;
  1476. int  i;
  1477.  
  1478.     cat->c0.item = 0;
  1479.  
  1480.     if(cnt <= 8)
  1481.         for (i = 0; i < cnt; ++i)
  1482.             cat->c0.a5.b[i] = *((unsigned char *)keyptr)++;
  1483.     else
  1484.         for (i = 0; i < cnt; ++i)
  1485.             cat->c0.a5.b[i&7] ^= *((unsigned char *)keyptr)++;
  1486.  
  1487.     /* THE CONSTANTS WERE CAREFULLY CHOSEN BY THEORY */
  1488.     /* value.item is a long long (use gcc only) */
  1489.  
  1490.     value.item = ((1103515245LL)*(cat->c0.a4.s0 ^ cat->c0.a4.s1))+453816693LL;
  1491.     if(value.a0 == 0) value.a0 = 1;
  1492.     value.a0 &= 0x0fffffff;
  1493.     if(cnt <= 8) value.a0 |= 0x80000000;    /* exact key chunk */
  1494.     cat->c1.a0 = value.a0;
  1495. }
  1496. static int linkup_complete;
  1497. static int
  1498. laccess(char *a, int b)
  1499. {/* suppress use of 'access', it links in too many other functions */
  1500.  
  1501.     if(linkup_complete)
  1502.         return ((VOBTYPE(a) & (OB_XFILE|OB_TREEDIR|OB_HASHDIR)) ? 0 : 1);
  1503.     else {
  1504.     int fd = VOPEN(a,O_RDONLY|O_BINARY);
  1505.         if(fd > 0)
  1506.         {
  1507.             VCLOSE(fd);
  1508.             return 0;
  1509.         }
  1510.         return 1;
  1511.     }
  1512. }
  1513. static int
  1514. lpagesize()
  1515. {
  1516.     return 4096;
  1517. }
  1518. static int
  1519. lprintchar(int c)
  1520. {
  1521.     return VWRITE(1,&c,1);
  1522. }
  1523. static void
  1524. lprintstr(char *str)
  1525. {
  1526.     while(*str)
  1527.         lprintchar(*str++);
  1528. }
  1529.  
  1530. #if EARLY_PRINT == 1
  1531.  
  1532. struct parameters
  1533. {
  1534.   int number_of_output_chars;
  1535.   int (*output_function)(void *, int);
  1536.   void *output_pointer;
  1537.   short minimum_field_width;
  1538.   short edited_string_length;
  1539.   short leading_zeros;
  1540.   char options;
  1541.     #define MINUS_SIGN    1
  1542.     #define RIGHT_JUSTIFY 2
  1543.     #define ZERO_PAD      4
  1544.     #define CAPITAL_HEX   8
  1545. };
  1546.  
  1547. static void output_and_count(struct parameters *p, int c)
  1548. {
  1549.   if (p->number_of_output_chars >= 0)
  1550.   {
  1551.     int n = (*p->output_function)(p->output_pointer, c);
  1552.     if (n>=0) p->number_of_output_chars++;
  1553.     else p->number_of_output_chars = n;
  1554.   }
  1555. }
  1556.  
  1557. static void output_field(struct parameters *p, char *s)
  1558. {
  1559.   short justification_length =
  1560.     p->minimum_field_width - p->leading_zeros - p->edited_string_length;
  1561.   if (p->options & MINUS_SIGN)
  1562.   {
  1563.     if (p->options & ZERO_PAD)
  1564.       output_and_count(p, '-');
  1565.     justification_length--;
  1566.   }
  1567.   if (p->options & RIGHT_JUSTIFY)
  1568.     while (--justification_length >= 0)
  1569.       output_and_count(p, p->options & ZERO_PAD ? '0' : ' ');
  1570.   if (p->options & MINUS_SIGN && !(p->options & ZERO_PAD))
  1571.     output_and_count(p, '-');
  1572.   while (--p->leading_zeros >= 0)
  1573.     output_and_count(p, '0');
  1574.   while (--p->edited_string_length >= 0)
  1575.     output_and_count(p, *s++);
  1576.   while (--justification_length >= 0)
  1577.     output_and_count(p, ' ');
  1578. }
  1579.     
  1580.  
  1581. static int 
  1582. gprintf(int (*output_function)(void *, int), void *output_pointer,
  1583.   char *control_string, int *argument_pointer)
  1584. {
  1585.   struct parameters p;
  1586.   char control_char;
  1587.   p.number_of_output_chars = 0;
  1588.   p.output_function = output_function;
  1589.   p.output_pointer = output_pointer;
  1590.   control_char = *control_string++;
  1591.   while (control_char != '\0')
  1592.   {
  1593.     if (control_char == '%')
  1594.     {
  1595.       short precision = -1;
  1596.       short long_argument = 0;
  1597.       short base = 0;
  1598.       control_char = *control_string++;
  1599.       p.minimum_field_width = 0;
  1600.       p.leading_zeros = 0;
  1601.       p.options = RIGHT_JUSTIFY;
  1602.       if (control_char == '-')
  1603.       {
  1604.         p.options = 0;
  1605.         control_char = *control_string++;
  1606.       }
  1607.       if (control_char == '0')
  1608.       {
  1609.         p.options |= ZERO_PAD;
  1610.         control_char = *control_string++;
  1611.       }
  1612.       if (control_char == '*')
  1613.       {
  1614.         p.minimum_field_width = *argument_pointer++;
  1615.         control_char = *control_string++;
  1616.       }
  1617.       else
  1618.       {
  1619.         while ('0' <= control_char && control_char <= '9')
  1620.         {
  1621.           p.minimum_field_width =
  1622.             p.minimum_field_width * 10 + control_char - '0';
  1623.           control_char = *control_string++;
  1624.         }
  1625.       }
  1626.       if (control_char == '.')
  1627.       {
  1628.         control_char = *control_string++;
  1629.         if (control_char == '*')
  1630.         {
  1631.           precision = *argument_pointer++;
  1632.           control_char = *control_string++;
  1633.         }
  1634.         else
  1635.         {
  1636.           precision = 0;
  1637.           while ('0' <= control_char && control_char <= '9')
  1638.           {
  1639.             precision = precision * 10 + control_char - '0';
  1640.             control_char = *control_string++;
  1641.           }
  1642.         }
  1643.       }
  1644.       if (control_char == 'l')
  1645.       {
  1646.         long_argument = 1;
  1647.         control_char = *control_string++;
  1648.       }
  1649.       if (control_char == 'd')
  1650.         base = 10;
  1651.       else if (control_char == 'x' || control_char == 'p')
  1652.         base = 16;
  1653.       else if (control_char == 'X')
  1654.       {
  1655.         base = 16;
  1656.         p.options |= CAPITAL_HEX;
  1657.       }
  1658.       else if (control_char == 'u')
  1659.         base = 10;
  1660.       else if (control_char == 'o')
  1661.         base = 8;
  1662.       else if (control_char == 'b')
  1663.         base = 2;
  1664.       else if (control_char == 'c')
  1665.       {
  1666.         base = -1;
  1667.         p.options &= ~ZERO_PAD;
  1668.       }
  1669.       else if (control_char == 's')
  1670.       {
  1671.         base = -2;
  1672.         p.options &= ~ZERO_PAD;
  1673.       }
  1674.       if (base == 0)  /* invalid conversion type */
  1675.       {
  1676.         if (control_char != '\0')
  1677.         {
  1678.           output_and_count(&p, control_char);
  1679.           control_char = *control_string++;
  1680.         }
  1681.       }
  1682.       else
  1683.       {
  1684.         if (base == -1)  /* conversion type c */
  1685.         {
  1686.           char c = *argument_pointer++;
  1687.           p.edited_string_length = 1;
  1688.           output_field(&p, &c);
  1689.         }
  1690.         else if (base == -2)  /* conversion type s */
  1691.         {
  1692.           char *string;
  1693.           p.edited_string_length = 0;
  1694.           string = * (char **) argument_pointer;
  1695.           argument_pointer += sizeof(char *) / sizeof(int);
  1696.           while (string[p.edited_string_length] != 0)
  1697.             p.edited_string_length++;
  1698.           if (precision >= 0 && p.edited_string_length > precision)
  1699.             p.edited_string_length = precision;
  1700.           output_field(&p, string);
  1701.         }
  1702.         else  /* conversion type d, b, o or x */
  1703.         {
  1704.           unsigned long x;
  1705.           char buffer[64];
  1706.           p.edited_string_length = 0;
  1707.           if (long_argument) 
  1708.           {
  1709.             x = * (unsigned long *) argument_pointer;
  1710.             argument_pointer += sizeof(unsigned long) / sizeof(int);
  1711.           }
  1712.           else if (control_char == 'd')
  1713.             x = (long) *argument_pointer++;
  1714.           else
  1715.             x = (unsigned) *argument_pointer++;
  1716.           if (control_char == 'd' && (long) x < 0)
  1717.           {
  1718.             p.options |= MINUS_SIGN;
  1719.             x = - (long) x;
  1720.           }
  1721.           do 
  1722.           {
  1723.             int c;
  1724.             c = x % base + '0';
  1725.             if (c > '9')
  1726.             {
  1727.               if (p.options & CAPITAL_HEX)
  1728.                 c += 'A'-'9'-1;
  1729.               else
  1730.                 c += 'a'-'9'-1;
  1731.             }
  1732.             buffer[sizeof(buffer) - 1 - p.edited_string_length++] = c;
  1733.           }
  1734.           while ((x/=base) != 0);
  1735.           if (precision >= 0 && precision > p.edited_string_length)
  1736.             p.leading_zeros = precision - p.edited_string_length;
  1737.           output_field(&p, buffer + sizeof(buffer) - p.edited_string_length);
  1738.         }
  1739.         control_char = *control_string++;
  1740.       }
  1741.     }
  1742.     else
  1743.     {
  1744.       output_and_count(&p, control_char);
  1745.       control_char = *control_string++;
  1746.     }
  1747.   }
  1748.   return p.number_of_output_chars;
  1749. }
  1750. static int
  1751. lputc(void *fd, int c)
  1752. {
  1753.     return VWRITE((int)fd, &c, 1);
  1754. }
  1755. static int
  1756. lprintf(char *fmt, ...)
  1757. {
  1758.     return gprintf(lputc, (void*)1, fmt, (int*)(&fmt+1));
  1759. }
  1760. static int
  1761. lvprintf(char *fmt, void *args)
  1762. {
  1763.     return gprintf(lputc, (void*)1, fmt, args);
  1764. }
  1765. static int lfilc(void *p, int c)
  1766. {
  1767.     *(*(char **)p)++ = c;
  1768.     return 0;
  1769. }
  1770. static int
  1771. lsprintf(char *buf, char *fmt, ...)
  1772. {
  1773. int n;
  1774.     n = gprintf(lfilc, &buf, fmt, (int*)(&fmt+1));
  1775.     *buf = 0;
  1776.     return n;
  1777. }
  1778.  
  1779. #endif /* EARLY_PRINT == 1 */
  1780.  
  1781. void
  1782. _cleanup()
  1783. {/* SUPPRESS PULLIN OF STDIO STUFF */
  1784. }
  1785. /* ================== END OF INTERNAL SUPPORT FUNCTIONS ================= */
  1786.  
  1787. #include "oxlink.i"
  1788.  
  1789. /* ================ END OF THE DYNAMIC LINKER ======================= */
  1790.  
  1791. struct _linkups {
  1792.     void *dst;
  1793.     char *src;
  1794. };
  1795. static struct _linkups __linkups[] = {
  1796.     {&VPUSH_VALUE,    "_cfpush_value"},    
  1797.     {&VPUSH_DATA,     "_cfpush_data"},
  1798.     {&VGET,            "_cfgetx"},
  1799.     {&VFIND,        "_cffindx"},
  1800.     {&VCFOPEN,        "_cfopen"},
  1801.     {&VCFCLOSE,        "_cfclose"},
  1802.     {&VCFREAD,        "_cfrdwr_object"},
  1803.     {&VCFWRITE,        "_cfrdwr_object"},
  1804.     {&VCFLSEEK,        "_cfseek"},
  1805.     {&VSUBOPEN,        "_cfsubopen"},
  1806.     {&VOBTYPE,        "_cfobtype"},
  1807.     {&VPUT,            "_cfputx"},
  1808.     {&VFILESIZE,    "_cffilesize"},
  1809.     {&VOPEN_CHUNK,    "_cfopen_chunk"},
  1810.     {&VLOCALIZE,    "_cflocalize"},
  1811.     {&VRELEASE,        "_cfrelease"},
  1812.     {&VMEMTEMP,        "_MEMTEMP"},
  1813.     {&VVPRINTF,        "_cfvprintf"},
  1814.     {&VSPRINTF,        "_cfsprintf"},
  1815.     {&VPRINTF,        "_cfprintf"},
  1816.     {&VSTAT,        "_cfstat"},
  1817.     {&CFINIT,        "_cfinit"},
  1818.     {&CFEXIT,        "_cfexit"},
  1819.     {&COSINIT,        "_InitCOS"},
  1820.     {&THREADER,        "__start_threader"},
  1821.     {&THREAD,        "__start_thread"},
  1822.     {&VINHIBIT_THREADER, "__no_context_switch"},
  1823.     {NULL}
  1824. };
  1825. static int badsyms;
  1826. static void
  1827. linkup()
  1828. {
  1829. struct _linkups *l = __linkups;
  1830.  
  1831.     while(l->dst)
  1832.     {
  1833.         *((long *)l->dst) = (long)oxlink_find_bare_symb(l->src);
  1834.         ++l;
  1835.     }
  1836.     /* REDIRECT USER CALLS TO OUR PREFERRED SUBROUTINES */
  1837.     SYMLINK(__filbuf, _cf_filbuf);
  1838.     SYMLINK(__flsbuf, _cf_flsbuf);
  1839.     SYMLINK(_fread, _cffread);
  1840.     SYMLINK(_fputc, _cffputc);
  1841.     SYMLINK(_fgetc, _cffgetc);
  1842.     SYMLINK(_fputs, _cffputs);
  1843.     SYMLINK(_fgets, _cffgets);
  1844.     SYMLINK(_puts, _cfputs);
  1845.     SYMLINK(_putw, _cfputw);
  1846.     SYMLINK(_gets, _cfgets);
  1847.     SYMLINK(_ftell, _cfftell);
  1848.     SYMLINK(_printf, _cfprintf);
  1849.     SYMLINK(_fprintf, _cffprintf);
  1850.     SYMLINK(_sprintf, _cfsprintf);
  1851.     SYMLINK(_vprintf, _cfvprintf);
  1852.     SYMLINK(_vfprintf, _cfvfprintf);
  1853.     SYMLINK(_fscanf, _cffscanf);
  1854.     SYMLINK(_fopen, _cffopen);
  1855.     SYMLINK(_freopen, _cffreopen);
  1856.     SYMLINK(_fseek, _cffseek);
  1857.     SYMLINK(_rewind, _cfrewind);
  1858.     SYMLINK(_fflush, _cffflush);
  1859.     SYMLINK(_fwrite, _cffwrite);
  1860.     SYMLINK(_unlink, _cfunlink);
  1861.     SYMLINK(_remove, _cfunlink);
  1862.     SYMLINK(_ungetc, _cfungetc);
  1863.     SYMLINK(_fclose, _cffclose);
  1864.     SYMLINK(_fdopen, _cffdopen);
  1865.     SYMLINK(_setmode, _cfsetmode);
  1866.     SYMLINK(_setbuf, _cfsetbuf);
  1867.     SYMLINK(_setvbuf, _cfsetvbuf);
  1868.     SYMLINK(_setlinebuf, _cfsetlinebuf);
  1869.     SYMLINK(_scanf, _cfscanf);
  1870.     SYMLINK(_sscanf, _cfsscanf);
  1871.     SYMLINK(_fscanf, _cffscanf);
  1872.     SYMLINK(_vscanf, _cfvscanf);
  1873.     SYMLINK(_vfscanf, _cfvfscanf);
  1874.     SYMLINK(_vsscanf, _cfvsscanf);
  1875.     SYMLINK(__iob, _cf_iob);
  1876.     SYMLINK(_stat, _TRAPSTAT);
  1877.     SYMLINK(_rename, _TRAPRENAME);
  1878.     SYMLINK(_fgetpos, _cffgetpos);
  1879.     SYMLINK(_fsetpos, _cffsetpos);
  1880.     SYMLINK(_tmpfile, _cftmpfile);
  1881.     SYMLINK(_tmpnam, _cftmpnam);
  1882.     SYMLINK(_tempnam, _cftempnam);
  1883.     SYMLINK(_itoa, _ltoa);
  1884. }
  1885. static char *
  1886. appnameof(char *path)
  1887. {
  1888. char *aname;
  1889. char *cp;
  1890.  
  1891.     if(path == NULL)
  1892.         return NULL;
  1893.  
  1894.     cp = concat("_", fileof(path, 0), "");
  1895.     aname = strdup(cp);
  1896.     _oxlink_free(cp);    /* was not allocated with malloc */
  1897.     if((cp = strrchr(aname, '.')) != NULL)
  1898.         *cp = 0;    
  1899.     cp = aname;
  1900.     while(*cp)
  1901.     {/* lower case app names only */
  1902.         if(*cp >= 'A' && *cp <= 'Z')
  1903.             *cp += 32;
  1904.         ++cp;
  1905.     }
  1906.     return aname;
  1907. }
  1908. static char *
  1909. appfileof(char *aname)
  1910. {
  1911. char *fname;
  1912. char *gname;
  1913. int fcnt;
  1914.  
  1915.     if(aname == NULL)
  1916.         return NULL;
  1917.  
  1918.     fcnt = strlen(aname);
  1919.     fname = malloc(fcnt+6);
  1920.     if(aname[0] == '_')
  1921.         fcnt = _strcpy(fname, &aname[1]);
  1922.     else
  1923.         strcpy(fname, aname);
  1924.  
  1925.     strcpy(&fname[fcnt], ".o");
  1926.     if(!(gname = cf_find_file(fname, 0)))
  1927.     {
  1928. #if 0
  1929.       strcpy(&fname[fcnt], ".byt");
  1930.       if(!(gname = cf_find_file(fname, 0)))
  1931. #endif
  1932.         strcpy(&fname[fcnt], ".cff");
  1933.           gname = cf_find_file(fname, 0);
  1934.     }
  1935.     free(fname);
  1936.     return gname;
  1937. }
  1938. static char *
  1939. cfffileof(char *aname)
  1940. {
  1941. char *fname;
  1942. char *gname;
  1943. int fcnt;
  1944.  
  1945.     if(aname == NULL)
  1946.         return NULL;
  1947.  
  1948.     fcnt = strlen(aname);
  1949.     fname = malloc(fcnt+6);
  1950.     if(aname[0] == '_')
  1951.         fcnt = _strcpy(fname, &aname[1]);
  1952.     else
  1953.         strcpy(fname, aname);
  1954.  
  1955.     strcpy(&fname[fcnt], ".cff");
  1956.     gname = cf_find_file(fname, 0);
  1957.     free(fname);
  1958.     return gname;
  1959. }
  1960. static void
  1961. Usage()
  1962. {
  1963. lprintstr("\
  1964. Usage: cfrun appname [-APP=][-LIB=][-PATH=][-TRACE=][-LBUFS=][appargs]\n\
  1965.    Switch -------- Meaning\n\
  1966.    -APP=filename   Permanent object file/archive for the application.\n\
  1967.    -LIB=filename   A library file.\n\
  1968.    -PATH=p1;p2;... Lookup path for files.\n\
  1969.    -LBUFS=n        Allocate n kilobytes of database buffering.\n\
  1970.    -TRACE=n        Set trace bits (hex,octal,decimal ok).\n\
  1971.    appargs         Application args.\n\
  1972. ");
  1973. }
  1974.  
  1975. /* ====================== THE MAIN FUNCTION ======================= */
  1976. static int chainargc;
  1977. static char *chainargv[30];
  1978. static char *chainapp, *chainfile, *chaincff;
  1979. static int chainapp_hasextension, chainfile_iscff;
  1980. char **Envp;
  1981. static char newmain[10];
  1982.  
  1983. int
  1984. main(int argc, char **argv, char **envp)
  1985. {
  1986. char *appath, *appname, *appfile, *ap, *dp;
  1987. int lbufs, i;
  1988. int appfile_iscff = 0;
  1989. int appname_hasextension = 0;
  1990. char *appcff = 0;
  1991.  
  1992. char *
  1993. check_for_arg(char *arg)
  1994. {/* NESTED SUBROUTINE */
  1995. int i;
  1996. int arglen = strlen(arg);
  1997.  
  1998.     for(i = 1; i < argc; ++i)
  1999.     {
  2000.         if(argv[i][0] == '-' && !strncmp(arg, &argv[i][1], arglen))
  2001.         {
  2002.         int j;
  2003.         char *cp = &argv[i][arglen+1];
  2004.             for(j = i; j < argc; ++j)
  2005.                 argv[j] = argv[j+1];
  2006.             --argc;
  2007.             return cp;
  2008.         }
  2009.     }
  2010.     return NULL;
  2011. }
  2012. /* main */
  2013.     path_sep = ';';
  2014.     _oxlink_openmode = O_RDONLY|O_BINARY;
  2015.     _oxlink_seekmode = 0;
  2016.     oxlink_errno = 0;
  2017.     Envp = envp;
  2018.  
  2019.     cf_set_search_path(check_for_arg("PATH="));
  2020.  
  2021.     if((ap = check_for_arg("TRACE=")) != NULL)
  2022.         _oxlink_trace = strtol(ap, NULL, 0);
  2023.  
  2024.     /* Get relevant info about this program name */
  2025.     appath = cf_find_file(argv[0], 0);
  2026.     appname = appnameof(appath);
  2027.  
  2028.     if(!strcmp(appname, "_cfrun"))
  2029.     {/* arg1 contains the real name of the application */
  2030.     int j;
  2031.         if(argc > 1)
  2032.         {
  2033.             appname = appnameof(argv[1]);
  2034.             if((dp = strchr(argv[1], '.')))
  2035.             {
  2036.                 appfile = cf_find_file(argv[1], 0);
  2037.                 appname_hasextension = 1;
  2038.             }
  2039.             else
  2040.                 appfile = appfileof(appname);
  2041.  
  2042.             for(j = 1; j < argc; ++j)
  2043.                 argv[j] = argv[j+1];
  2044.             --argc;
  2045.         }
  2046.         else
  2047.         {
  2048.             Usage();
  2049.             VEXIT(0);
  2050.         }
  2051.     }
  2052.     else appfile = appfileof(appname);
  2053.  
  2054.     if(appfile)
  2055.     {
  2056.         if((dp = strrchr(appfile, '.')))
  2057.         {
  2058.             if(!strcmp(dp, ".cff"))
  2059.             {
  2060.                 appfile_iscff = 1;
  2061.                 appcff = appfile;
  2062.             }
  2063.             else
  2064.             {
  2065.                 appcff = cfffileof(appname);
  2066.             }
  2067.         }
  2068.     }
  2069.     /* Link in the base level code */
  2070.     permanent_symbols = 1;
  2071.     if(!oxlink_init(appath)) {
  2072.       oxlink_use_library("oxbow.a");
  2073.       if(!oxlink_load_object("dj12port.o")) {
  2074.         if(!oxlink_load_object("cffsys.o")) {
  2075.           if(!oxlink_load_object("cossys.o")) {
  2076.             oxlink_nouse_library("oxbow.a");
  2077.             linkup();
  2078.           }
  2079.         }
  2080.       }
  2081.     }
  2082.     permanent_symbols = 0;
  2083.  
  2084.     if(oxlink_errno) {
  2085.          lprintstr(oxlink_errstr());
  2086.          VEXIT(oxlink_errno);
  2087.     }
  2088.     /* CFF and COS are now linked */
  2089.     linkup_complete = 1;
  2090.     _oxlink_openmode = F_STAT;
  2091.     _oxlink_seekmode = S_SET;
  2092.  
  2093.     /* check for appfile override */
  2094.     if((ap = check_for_arg("APP=")) != NULL)
  2095.         appfile = strdup(ap);
  2096.  
  2097.     if((ap = check_for_arg("LBUFS=")) != NULL)
  2098.          lbufs = strtol(ap, NULL, 0);
  2099.     else lbufs = 100;
  2100.  
  2101.     /* Initialize CFF and COS */
  2102.     CFINIT(&appname[1], lbufs, appfile);
  2103.     COSINIT(&argc);
  2104.  
  2105.     /* Get rid of the symbol `_main' so it doesn't clash */
  2106.     strcpy(newmain, "_main$$$");
  2107.     oxlink_rename_symb("_main", newmain);
  2108.     
  2109.     /* Specify which libraries will provide code and data */
  2110.     oxlink_use_library("oxlib.cff");
  2111.  
  2112.     /* Pick up any additional libraries of interest */
  2113.     while((ap = check_for_arg("LIB=")) != NULL)
  2114.         oxlink_use_library(ap);
  2115.  
  2116.     /* Enable demand loading */
  2117.      oxlink_demand_load();
  2118.  
  2119.     if(_oxlink_trace)
  2120.     {/* Print the addresses of the early load modules */
  2121.     struct file_entry *entry = _oxlink_latest_entry;
  2122.         void print_file(struct file_entry *e)
  2123.         {/* NESTED SUBROUTINE */
  2124.             VPRINTF("%s\ntext:0x%x sz=%d data:0x%x sz=%d bss:0x%x sz=%d end=%x\n",
  2125.                 e->local_sym_name,
  2126.                 e->text_start_address, e->header.text_size,
  2127.                 e->data_start_address, e->header.data_size,
  2128.                 e->bss_start_address, e->header.bss_size,
  2129.                 e->text_start_address+e->header.image_size
  2130.                 );
  2131.         }
  2132.         while(entry)
  2133.         {
  2134.             if(entry->library_flag) {
  2135.             struct file_entry *subentry = entry->subfiles;
  2136.                 while(subentry)
  2137.                 {
  2138.                     print_file(subentry);
  2139.                     subentry = subentry->chain;
  2140.                 }
  2141.             }
  2142.             entry = entry->chain;
  2143.         }
  2144.     }
  2145.     /* Start threads */
  2146.     THREADER(&argc);
  2147.     if(setjmp(_t_start)) {
  2148.         THREAD();
  2149.     }
  2150.  
  2151.     *VINHIBIT_THREADER += 1;
  2152.     {
  2153.     int ret;
  2154.     int run_argc;
  2155.     char **run_argv;
  2156.         run_argc = argc;
  2157.         run_argv = argv;
  2158. chain:
  2159.         if(appcff)
  2160.         {
  2161.             oxlink_use_library(appcff); /* ignored if not a library */
  2162.         }
  2163.         run_argv[0] = &appname[1];
  2164.  
  2165.         if(appfile)
  2166.         {/* The file could be .o or .cff */
  2167.         char *filename;
  2168.         int (*funcptr)();
  2169.         int loaded = 0;
  2170.             if(appfile_iscff || !appname_hasextension)
  2171.             {/* look for a file inside a .cff file */
  2172.               /* FIRST TRY TO RUN THE APPNAME */
  2173.               if((ret = oxfunc(appname, run_argc, run_argv)) != -1)
  2174.               {
  2175.                   oxlink_unload_bare_symb(appname, 0);
  2176.                   loaded = -1;
  2177.               }
  2178.               else
  2179.               {/* try loading object from any defined libraries */
  2180.                 dp = strrchr(appfile, '/')+1;
  2181.                 filename = calloc(1, strlen(dp)+5);
  2182.                 strcpy(filename, dp);
  2183.                 strcpy(strchr(filename,'.'), ".o");
  2184.                 if(!oxlink_load_object(filename))
  2185.                 {
  2186.                     loaded = 1;
  2187.                 }
  2188.               }
  2189.             }
  2190.             if(!loaded)
  2191.             {/* try loading the file directly */
  2192.               filename = appfile;
  2193.               if(oxlink_load_file(filename))
  2194.               {
  2195.                 VPRINTF("Can't start application `%s'\n", &appname[1]);
  2196.                 VEXIT(1);
  2197.               }
  2198.               loaded = 1;
  2199.             }
  2200.             if(loaded > 0)
  2201.             {
  2202.               if((funcptr = oxlink_find_bare_func("_main")))
  2203.               {/* Get rid of the symbol `_main' so it doesn't clash */
  2204.                 ++newmain[8];
  2205.                 oxlink_rename_symb("_main", newmain);
  2206.               }
  2207.               else if(!(funcptr = oxlink_find_bare_func(appname)))
  2208.               {
  2209.                 VPRINTF("Can't find `_main' or `%s' in file %s\n",
  2210.                     appname, filename);
  2211.                 VEXIT(1);
  2212.               }
  2213.               ret = funcptr(run_argc, run_argv);
  2214.               oxlink_unload_file(filename, 0);
  2215.               if(filename != appfile)
  2216.                 free(filename);
  2217.             }
  2218.         }
  2219.         else
  2220.         {/* Just try to run the name from a library */
  2221.             if((ret = oxfunc(appname, run_argc, run_argv)) == -1)
  2222.                 VPRINTF("Can't start application `%s'\n", &appname[1]);
  2223.             oxlink_unload_bare_symb(appname, 0);
  2224.         }
  2225.         free(appname);
  2226.         if(appcff)
  2227.         {
  2228.             oxlink_nouse_library(appcff);
  2229.             if(appcff != appfile)
  2230.                 free(appcff);
  2231.         }
  2232.         if(appfile)
  2233.             free(appfile);
  2234.  
  2235.         if(chainapp)
  2236.         {/* The previous program chained to a new one */
  2237.             appname = chainapp;
  2238.             appfile = chainfile;
  2239.             appcff = chaincff;
  2240.             appfile_iscff = chainfile_iscff;
  2241.             appname_hasextension = chainapp_hasextension;
  2242.             chainapp = 0;
  2243.             if(run_argv != argv)
  2244.             {/* was chained previously, get rid of prev args */
  2245.                 for(i = 1; i < run_argc; ++i)
  2246.                     free(run_argv[i]);
  2247.             }
  2248.             run_argc = chainargc;
  2249.             run_argv = (char**)chainargv;
  2250.             goto chain;
  2251.         }
  2252.         CF_InitIO(-1, 0);
  2253.         VEXIT(ret);
  2254.     }
  2255. }
  2256. void
  2257. CF_ChainFile(char *newname, int argc, char **argv)
  2258. {/* CALLED FROM APPLICATION TO CHAIN TO ANOTHER PROGRAM */
  2259. int i;
  2260. char *dp;
  2261.     chaincff = 0;
  2262.     chainfile_iscff = 0;
  2263.     chainapp_hasextension = 0;
  2264.     chainapp = appnameof(newname);
  2265.  
  2266.     if((dp = strchr(newname, '.')))
  2267.     {
  2268.          chainfile = cf_find_file(newname, 0);
  2269.          chainapp_hasextension = 1;
  2270.     }
  2271.     else chainfile = appfileof(chainapp);
  2272.  
  2273.     if(chainfile)
  2274.     {
  2275.         if((dp = strrchr(chainfile, '.')))
  2276.         {
  2277.             if(!strcmp(dp, ".cff"))
  2278.             {
  2279.                 chainfile_iscff = 1;
  2280.                 chaincff = chainfile;
  2281.             }
  2282.             else
  2283.             {
  2284.                 chaincff = cfffileof(chainapp);
  2285.             }
  2286.         }
  2287.     }
  2288.     chainargc = argc+1;
  2289.     for(i = 0; i < argc; ++i)
  2290.         chainargv[i+1] = copy_of(argv[i]);
  2291. }
  2292. void
  2293. CF_InitIO(long arg, long long (*msgproc)())
  2294. {/* THIS FUNCTION IS CALLED FROM THE APPLICATION */
  2295. static void (*initio)() = NULL;
  2296.  
  2297.     if(arg >= 0)
  2298.     {
  2299.         AppArg = arg;
  2300.         initio = oxload(CF_Interactive_IO);
  2301.         initio(0, msgproc, &VAPPMSG);
  2302.     }
  2303.     else if(arg == -1)
  2304.     {/* deinit */
  2305.         if(initio)
  2306.             initio(-1, 0, 0);
  2307.     }
  2308.     else
  2309.     {/* re-init */
  2310.         if(initio)
  2311.             initio(arg, 0, 0);
  2312.     }
  2313. }    
  2314. long long
  2315. AppMsg(void *self, void *wnd, long long it)
  2316. {
  2317.     return VAPPMSG(self, wnd, it);
  2318. }
  2319.