137 lines
3.1 KiB
Plaintext
137 lines
3.1 KiB
Plaintext
_GETTING A HANDLE ON VIRTUAL MEMORY_
|
||
by Walter Bright
|
||
|
||
|
||
[LISTING ONE]
|
||
|
||
/* Compile with: ZTC wc -ml */
|
||
/* (Use large model so strcmp() can handle far pointers.) */
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
#include <handle.h>
|
||
|
||
struct tree
|
||
{
|
||
char __handle *word;
|
||
int count;
|
||
struct tree __handle *left;
|
||
struct tree __handle *right;
|
||
};
|
||
int readword(char *w, int nbytes)
|
||
{
|
||
int c;
|
||
do {
|
||
c = getchar();
|
||
if (c == EOF)
|
||
return 0;
|
||
}
|
||
while (!isalpha(c));
|
||
do {
|
||
if (nbytes > 1)
|
||
{
|
||
*w++ = c;
|
||
nbytes--;
|
||
}
|
||
c = getchar();
|
||
}
|
||
while (isalnum(c));
|
||
*w = 0;
|
||
return 1;
|
||
}
|
||
void tree_insert(struct tree __handle * __handle *pt, char *w)
|
||
{
|
||
int cmp;
|
||
struct tree __handle *p;
|
||
while ((p = *pt) != NULL)
|
||
{
|
||
if ((cmp = strcmp(w,p->word)) == 0)
|
||
goto gotit;
|
||
pt = (cmp < 0) ? &p->left : &p->right;
|
||
}
|
||
p = (struct tree __handle *) handle_calloc(sizeof(struct tree));
|
||
if (!p || (p->word = handle_strdup(w)) == NULL)
|
||
{
|
||
printf("Out of memory\n");
|
||
exit(EXIT_FAILURE);
|
||
}
|
||
*pt = p;
|
||
gotit:
|
||
p->count++;
|
||
}
|
||
tree_print(struct tree __handle *p)
|
||
{
|
||
while (p)
|
||
{
|
||
tree_print(p->left);
|
||
printf("%5d %s\n",p->count,(char far *)p->word);
|
||
p = p->right;
|
||
}
|
||
}
|
||
tree_free(struct tree __handle *p)
|
||
{
|
||
struct tree __handle *pn;
|
||
while (p)
|
||
{
|
||
handle_free(p->word);
|
||
tree_free(p->left);
|
||
pn = p->right;
|
||
handle_free(p);
|
||
p = pn;
|
||
}
|
||
}
|
||
main()
|
||
{
|
||
struct tree __handle *root = NULL;
|
||
char word[32];
|
||
while (readword(word,sizeof(word)))
|
||
tree_insert(&root, word);
|
||
tree_print(root);
|
||
tree_free(root);
|
||
return EXIT_SUCCESS;
|
||
}
|
||
|
||
|
||
[Figure 1: Typical pointer types used in most PC implementations of C]
|
||
|
||
|
||
void *p; /* pointer type is default for the memory model */
|
||
char far *pc; /* far (segment and offset pair) pointer */
|
||
int near *p; /* near (offset only, segment is assumed) */
|
||
|
||
[Figure 2: Converting pointers from handle to far]
|
||
|
||
R 65,T 5
|
||
int __handle *h;
|
||
struct A __handle *h2;
|
||
int far *f;
|
||
int i;
|
||
extern void func(int far *pi);
|
||
|
||
f = h;
|
||
*h = i;
|
||
h[3] = *f;
|
||
i = *(h + 6);
|
||
h2->b = i;
|
||
func(h);
|
||
h = (int far *) h;
|
||
|
||
|
||
|
||
|
||
[Figure 3: Example showing that the optimizer is handle aware]
|
||
|
||
struct { int a,b; } __handle *h;
|
||
h->a = 1;
|
||
h->b = 2;
|
||
/* Converted code */
|
||
struct { int a,b; } __handle *h, far *p;
|
||
p = h;
|
||
p->a = 1;
|
||
p->b = 2;
|
||
|
||
|
||
|
||
|