Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

382 lines
11 KiB

/*
* Module: flist.h
* Author: Mark I. Himelstein, Himelsoft, Inc.
* Purpose: create lists: field list and arg list
*/
#include "conv.h"
typedef struct list_s {
type_s *type; /* type index and buffer pointer */
struct list_s *next; /* used to make stack */
long count; /* number of fields in field list */
pSYMR psym; /* points to stBlock start of field */
unsigned short *pcount;/* points to location for arg list count */
unsigned short *pproccount;/* points to location for proc arg count */
unsigned short cv_leaf_type; /* LF_FIELDLIST or LF_ARGLIST */
char emitted_tag; /* flag set to 1 if we have, else 0 */
} list_s;
/* we assume all usage of field lists occur after the field list is
* started. This is not true for forward defintions and is
* handled in btTypedef.
*/
list_s *list_stack; /* we can have nested strcuture definitions */
unsigned short *proc_arg_count_ptr; /* points to place to stuff count */
extern verbose;
extern data
list_start(
arg_s *parg, /* arg entry causing call */
callinfo_s *pinfo, /* info we need to pass around */
long *plength) /* for varying length fields */
{
/* take a type number and a buffer, and push them on the field list stack,
* emit field
*/
list_s *list; /* new list */
parg;
plength;
list = (list_s *)calloc(sizeof(list_s), 1);
if (list == 0) {
fatal("cannot allocate list structure\n");
} /* if */
list->type = type_create();
list->next = list_stack;
list->psym = pinfo->psym;
list_stack = list;
if (proc_arg_count_ptr) {
/* we had previously been asked to stuff an arg count in a
* LF_PROCEDURE, now we bind that request to this list.
*/
list->pproccount = proc_arg_count_ptr;
proc_arg_count_ptr = 0;
} /* if */
return type_get_index(list->type);
} /* list_start */
static void
emit_tag(list_s *list, unsigned short cv_leaf_type)
{
if (list->emitted_tag) {
return;
} /* if */
list->emitted_tag = 1;
list->cv_leaf_type = cv_leaf_type;
VERBOSE_PUSH_INDENT(TYPE_INDENT);
VERBOSE_PRINTF("\n");
VERBOSE_PRINTF("[0x%08x] %sLIST 0x%x tag = ", buffer_total(list->type->buf),
cv_leaf_type == LF_ARGLIST ? "ARG" :
"FIELD", type_get_index(list->type));
buffer_put_value(list->type->buf, cv_leaf_type, CV_LEAF_TAG_SIZE,
NO_VLENGTH);
if (cv_leaf_type == LF_ARGLIST) {
list->pcount = (unsigned short *)buffer_ptr(list->type->buf);
VERBOSE_PRINTF("[0x%08x] ARGLIST 0x%x count dummy = ",
buffer_total(list->type->buf), type_get_index(list->type));
buffer_put_value(list->type->buf, 0, CV_ARGLIST_COUNT_SIZE,NO_VLENGTH);
} /* if */
VERBOSE_POP_INDENT();
} /* emit tag */
extern void
list_end(
arg_s *parg, /* arg entry causing call */
callinfo_s *pinfo, /* info we need to pass around */
long *plength) /* for varying length fields */
{
pSYMR psymbegin;
list_s *list;
unsigned short *pcount;
unsigned short *ptype_index;
parg;
plength;
if (list_stack == 0) {
fatal("unexpected list end without list start\n");
} /* if */
list = list_stack;
VERBOSE_PUSH_INDENT(TYPE_INDENT);
/* no entries, emit tag*/
if (pinfo->psym->st != stEnd)
emit_tag(list, LF_ARGLIST);
else
emit_tag(list, LF_FIELDLIST);
if (pinfo->psym->st == stEnd) {
if (pinfo->psym->index == indexNil) {
fatal("list end doesn't point to list begin symbol (%d)\n",
pinfo->psym->index);
} /* if */
psymbegin = isym_to_psym(pinfo, pinfo->psym->index);
if (psymbegin != list->psym) {
fatal("list end doesn't point to list begin symbol (%d)\n",
pinfo->psym->index);
} /* if */
} /* if */
/* stash the count in stEnd iss field, and the type in stEnd value field */
if (pinfo->psym->sc == scForward) {
/* referenced the count and type information already and the pointers
* to where they go are in the respective fields we intend
* to stash them in.
*/
pcount = (unsigned short *)pinfo->psym->iss;
ptype_index = (unsigned short *)pinfo->psym->value;
*pcount = (unsigned short)list->count;
*ptype_index = (unsigned short)type_get_index(list->type);
VERBOSE_PRINTF("Fill forward ref count (%d) & type index (0x%x)\n",
*pcount, *ptype_index);
} /* if */
pinfo->psym->iss = list->count;
pinfo->psym->value = type_get_index(list->type);
pinfo->psym->sc = scProcessed; /* mark that we've done it */
if (list->cv_leaf_type == LF_ARGLIST) {
/* fix count field */
VERBOSE_PRINTF("Fix ARGLIST count field = %d\n", list->count);
*list->pcount = (unsigned short)list->count;
if (pinfo->psym->st == stEnd) {
/* prottype appears before typedef using prototype, so set
* st so we know it was a prototype.
*/
pinfo->psym->st = stProto;
} else if (pinfo->psym->st == stEndParam) {
if (list->pproccount) {
/* proc definition appears before arglist, so we need to back
* fill LF_PROCEDURE arg count
*/
VERBOSE_PRINTF("Fix LF_PROCEDURE count field = %d\n",
list->count);
*list->pproccount = (unsigned short)list->count;
} /* if */
} /* if */
} /* if */
/* pop the list stack and free list structure, types will dump buffer
* later.
*/
list_stack = list->next;
VERBOSE_PRINTF("LIST 0x%x count = %d\n", pinfo->psym->value, list->count);
VERBOSE_POP_INDENT();
free(list);
} /* list_end */
extern data
list_member(
arg_s *parg, /* arg entry causing call */
callinfo_s *pinfo, /* info we need to pass around */
long *plength) /* for varying length fields */
{
long is_arglist; /* set if we're building an arglist */
plength;
if (list_stack == 0) {
fatal("unexpected list end without list start\n");
} /* if */
is_arglist = pinfo->psym->st == stParam;
emit_tag(list_stack, (unsigned short)(is_arglist ? LF_ARGLIST:LF_FIELDLIST));
list_stack->count++;
VERBOSE_POP_INDENT();
VERBOSE_PUSH_INDENT(TYPE_INDENT);
VERBOSE_PRINTF("LIST 0x%x field %d:\n", type_get_index(list_stack->type),
list_stack->count);
VERBOSE_POP_INDENT();
VERBOSE_PUSH_INDENT(TYPE_INDENT);
pinfo->buf = list_stack->type->buf; /* subversion */
switch (parg->id) {
case MEMB:
return LF_MEMBER;
case ENUM:
return LF_ENUMERATE;
default:
return 0xbadbad;
} /* switch */
} /* list_member */
void
list_pop()
{
/* used to pop list stack because we didn't know it
* was a prototype block.
*/
if (list_stack == 0) {
fatal("tried to pop list stack when it was empty\n");
} /* if */
if (list_stack->emitted_tag) {
fatal("tried to pop list stack when it was active\n");
} /* if */
list_stack = list_stack->next;
} /* list_pop */
extern long
active_list_type()
{
if (list_stack == 0) {
return stNil;
} else {
return list_stack->psym->st;
} /* if */
} /* active_list_type */
extern long
list_active()
{
return (list_stack != 0);
} /* list_active */
extern data
get_field_count(
arg_s *parg, /* arg entry causing call */
callinfo_s *pinfo, /* info we need to pass around */
long *plength) /* for varying length fields */
{
/* called by types.c to retrieve a field count we put there before */
pSYMR psym;
parg;
plength;
if (pinfo->psym->st != stBlock) {
fatal("unexpected symbol type (%s) expected stBlock\n",
mc_st_to_ascii(pinfo->psym->st));
} /* if */
/* get end symbol where we stashed the flist type index */
psym = isym_to_psym(pinfo, pinfo->psym->index-1);
if (psym->sc == scForward) {
fatal("unexpected double process of scForward stEnd\n");
} /* if */
if (psym->sc == scInfo) {
/* this is a forward reference */
pinfo->psym->sc = scForward;
psym->sc = scForward;
psym->iss = (long)buffer_ptr(pinfo->buf);/* warning 64-bit issue */
return 0;
} /* if */
return psym->iss;
} /* get_field_count */
extern data
get_field_list(
arg_s *parg, /* arg entry causing call */
callinfo_s *pinfo, /* info we need to pass around */
long *plength) /* for varying length fields */
{
/* called by types.c to retrieve a list type index we put there before */
pSYMR psym;
parg;
plength;
if (pinfo->psym->st != stBlock) {
fatal("unexpected symbol type (%s) expected stBlock\n",
mc_st_to_ascii(pinfo->psym->st));
} /* if */
/* get stEnd symbol */
psym = isym_to_psym(pinfo, pinfo->psym->index-1);
if (psym->sc == scForward) {
/* forward ref */
psym->value = (long)buffer_ptr(pinfo->buf);/* warning 64-bit issue */
return 0;
} /* if */
if (psym->sc != scProcessed) {
fatal("unexpected unprocessed stEnd\n");
} /* if */
return psym->value;
} /* get_field_list */
extern data
get_field_pad(
arg_s *parg, /* arg entry causing call */
callinfo_s *pinfo, /* info we need to pass around */
long *plength) /* for varying length fields */
{
/* special LF_PAD things must be put out between field list
* members.
*/
unsigned long bytes;
unsigned long pad_size;
unsigned char pad;
#define PAD_CONSTANT 0xf0
parg;
pinfo;
plength;
if (list_stack == 0) {
fatal("tried to emit pad for list stack when it was empty\n");
} /* if */
bytes = buffer_total(list_stack->type->buf);
if (CALCULATE_PAD(pad_size, bytes, NATURAL_ALIGNMENT) != 0) {
pad = (unsigned char)(PAD_CONSTANT|pad_size);
VERBOSE_PRINTF("[0x%08x] LIST pad char = ",
buffer_total(list_stack->type->buf));
buffer_put_value(list_stack->type->buf, pad, CV_PAD_LEAF_SIZE,
NO_VLENGTH);
pad_size -= CV_PAD_LEAF_SIZE;
if (pad_size) {
VERBOSE_TOTAL(list_stack->type->buf);
VERBOSE_PRINTF("LIST pad (%d) = ", pad_size);
buffer_put_value(list_stack->type->buf, 0, pad_size,
NO_VLENGTH);
} /* if */
} /* if */
return 0;
} /* get_field_pad */
extern data
set_proc_arg_count_ptr(
struct buffer_s *buf) /* buffer we're going to stick it into */
{
/* the LF_PROCEDURE has an extra copy of the number of args in it
* which also appears in arglist. We need to stash a pointer so
* we can update it when the list is complete.
*/
proc_arg_count_ptr = (unsigned short *)buffer_ptr(buf);
return 0xdeaa; /* delay */
} /* set_proc_arg_count_ptr */