⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn_tabulate.c

📁 ASN.1语法解析代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
File:     asn_tabulate.c
Contents: functions to create the name table as part of the ASN_GEN program.
System:   ASN development.
Created:
Author:   Charles W. Gardiner <gardiner@bbn.com>

Remarks:

COPYRIGHT 1995 BBN Systems and Technologies, A Division of Bolt Beranek and
    Newman Inc.
150 CambridgePark Drive
Cambridge, Ma. 02140
617-873-4000
*****************************************************************************/

const char asn_tabulate_rcsid[]="$Header: /nfs/sub-rosa/u2/IOS_Project/ASN/Dev/rcs/cmd/asn_gen/asn_tabulate.c,v 1.13 1995/09/01 18:12:05 gardiner Exp $";
char asn_tabulate_id[] = "@(#)asn_tabulate.c 272P";

#include "includes.h"
#include "asn_obj.h"
#include "asn_gen.h"

static void massage_table(struct name_table *),
    mk_table_child(int, int, int, int),
    set_false(struct name_table *, struct name_table *),
    sort_defineds(struct name_table *),
    tab_def(int, struct name_table *),
    tab_item(int, int);

void tabulate(int fd)
{
/*
Function: Fills name_tab with info about the input file

Inputs: fd is file descriptor for ASN.1 file
	str is the stream descriptor for the output
Outputs: Name_tab filled in
Procedure:
   WHILE there's a next token
     Switch on state
1.   Case GLOBAL
        IF read_global returns < 0, break
	IF token is '::='
	    Add object name to name_table
            IF position not yet set, set it to current position
	    Save index as current parent
	    Clear 'name'
	    Go to IN_DEFINITION state
2.   Case IN_DEFINITION
	Read the definition
	IF not in GLOBAL state, tabulate the definition
	IF in GLOBAL state clear classname
3.   Case IN_ITEM
	IF token is '::=' OR '{', exit with fatal message
	IF read_item returns -1, return
	IF token is '}' OR ',' (indicating the end of an item)
	    Tabulate the item
   Default: Exit with fatal message
*/
int parent;
struct name_table *ptbp;
option = 0;
if (state != SUB_ITEM) end_definition();
else end_item();
while (get_token(fd, token, (char)0))
    {
    switch (state)
    	{
							    /* step 1 */
    case GLOBAL:
	if (read_global(fd) < 0) break;
	parent = add_name(classname, (ulong)-1, 0);
        ptbp = &((struct name_table *)name_area.area)[parent];
	if ((ptbp->flags & ASN_FILLED_FLAG)) warn(17, classname);
	else ptbp->flags |= ASN_FILLED_FLAG;
	if (!fd && ptbp->pos == -1) ptbp->pos = lseek(fd, 0L, 1);
	classcount++;
	break;
							    /* step 2 */
    case IN_DEFINITION:                                     /* got ::= */
	if (read_definition(fd, parent) < 0) return;
        if (state != GLOBAL) tab_def(parent, ptbp);
        if (state == GLOBAL) end_definition();
	else end_item();
	break;
							    /* step 3 */
    case IN_ITEM:                                     /* got '{' */
	if (!strcmp(token, equals) || *token == '{') syntax(classname);
	if (read_item(fd, parent, 0) < 0) return;
	if (*token == ',' || *token == '}')        /* end of item */
	    tab_item(fd, parent);
	break;

    default:
	fatal(4, (char *)state);
	}
    }
if (!fd) massage_table((ptbp = (struct name_table *)name_area.area));
}

static void tab_def(int parent, struct name_table *ptbp)
{
/**
1. IF have a tag,
        IF type is constructed, put constructed bit in tag
        Put tag in name table
   ELSE set tag to type
2. Set max and min
   IF have a child (i.e. subclass) name
	IF no type yet AND not a pointer, mark parent false
        Add child to object table with
            current parent, path of zero, type and option
   ELSE IF no type nor table nor choice, error
   ELSE IF have a primitive universal subtype, set parent subtype
3. IF item is subdefined AND type is BIT STRING OR INTEGER OR
        ENUMERATED, set enumerated flag and option
   IF in explicit area, set EXPLICIT flag
   Add object name to table with type and option
4. IF at line end, set to GLOBAL state
   IF table flag is set, set it in object table
   Clear assorted variables
   Set state to IN_ITEM
**/
int did;
if (tag >= 0)
    {
    if (type > 0) tag |= (type & ASN_CONSTRUCTED);
    ptbp->tag = tag;
    }
else tag = ptbp->type = type;
					        /* step 2 */
    /* in case name table moved! */
ptbp = &((struct name_table *)name_area.area)[parent];
if ((ptbp->max = max)) ptbp->min = min;
if (*subclass)
    {
    if (type < 0)
        add_name(classname, (long)-1, ASN_FALSE_FLAG);
    if (ptbp->pos < real_start && ptbp->type == 0xFFFFFFFF)
        ptbp->type = 0; /* so imported passthru won't be undefined */
    add_child(subclass, parent, 0, (ulong)-1, 0);
    }
else if (type < 0 && type != ASN_CHOICE &&
    !(flags & ASN_TABLE_FLAG)) syntax(subclass);
else if (subtype >= 0 && subtype < ASN_CONSTRUCTED)
    ptbp->subtype = subtype;
					        /* step 3 */
if (*token == '{' && (type == ASN_BITSTRING || type == ASN_INTEGER ||
    type == ASN_ENUMERATED) && !(option & ASN_OF_FLAG))
    {
    flags |= ASN_ENUM_FLAG;  /* for read_item */
    option |= ASN_ENUM_FLAG;  /* for add_name just below */
    }
if (explicit) option |= ASN_EXPLICIT_FLAG;
did = add_name(classname, type, (option & ASN_OF_FLAG)?
    (option &= ~(ASN_POINTER_FLAG)): option);
					        /* step 4 */
if ((option & ASN_TABLE_FLAG)) ptbp->flags |= ASN_TABLE_FLAG;
did = 0;
if (*token == '\n') state = GLOBAL;
else state = IN_ITEM;
}

static void tab_item(int fd, int parent)
{
/**
1. IF it's a DEFINED BY, make a table entry
2. IF it's not a universal type, add name to object table with
        current	parent and path of 'did'
   IF there's a table name, i.e. this is a definer
	Make a dummy name of itemnameIntablename
	Add that to object table with current parent, definer flag and path
        of 'did'
	Make a dummy name of tablenameIntablename
	Add that to table as child of current item with table flag and path of
            zero
	Add table name to table as child of that item with table flag and path
            of zero
   IF no itemname AND no type AND no subclass AND not imported
	Print warning
3. IF it's a comma, increment the item count ('did')
   ELSE
     	IF have a stream for a subordinate item
	    Copy all its contents to main stream
	    Mark new stream emptied
        Go to GLOBAL state
**/
int child, tmp;
static int did;
char *c;
struct alt_subclass *altscp;
if (*defined_by)
    {
    mk_table_child(fd, parent, did, option);
    *defined_by = 0;
    }
					        /* step 2 */
if (type < 0 && *subclass)
    child = add_child(subclass, parent, did, (ulong)-1,
        (option & ~(ASN_TABLE_FLAG)));
else child = parent;
for (altscp = alt_subclassp; altscp; altscp = altscp->next)
    {
    if (*altscp->name && find_type(altscp->name) == ASN_NOTYPE)
        add_child(altscp->name, child, did, (ulong)-1, 0);
    }
if (*tablename)
    {
    mk_in_name(itemname, itemname, classname);
    child = add_child(itemname, parent, did,
        ((child == parent)? type:
        ((struct name_table *)name_area.area)[child].type),
        ASN_DEFINER_FLAG);
    if (!(c = (char *)calloc(strlen(tablename) + strlen(classname) + 4, 1)))
	fatal(7, (char *)0);
    mk_in_name(c, tablename, classname);
    tmp = add_child(c, child, 0, (ulong)-1, ASN_TABLE_FLAG);
    tmp = add_child(tablename, tmp, 0, (ulong)-1, ASN_TABLE_FLAG);
    free(c);
    *tablename = 0;
    }
if (!*itemname && type < 0 && !*subclass &&
    lseek(fd, 0L, 1) >= real_start) warn(20, "item name");
					        /* step 3 */
if (*token == ',')
    {
    did++;
    end_item();
    }
else                      /* last */
    {
    did = 0;
    end_definition();
    }
}

static struct name_table *find_definer(int fd, char *definername, int parent)
{
/**
Function: Finds the item in the table which is the definer, based on the
definername, which may be segmented.  On the way, it makes table entries for any
missing items.  It may call itself for later segments in definer name
Inputs:
    File descriptor for file being read
    Pointer to (segmented?) definer name
Also uses inclass, an array containing the name of the class containing the
    item which is the first segment of definer
Outputs:
    Entries in name table for any intermediate items not yet in table
Returns: Pointer to table entry for the definer
Procedure:
1. Mark off first segment
   Look for segmentIninclass in the table
   IF the name is found OR there's no more to the definer, return the pointer
2. Save the current classname, itemname and file position
   IF there's already a definition of inclass
        Go back to the definition of the inclass
        Read until the segment is found
        Add segmentIninclass as a child of the inclass
        Make the subclass the new inclass
3.      Call this function with remaining definer name
   ELSE Add segmentInclass as child of the inclass with unknown offset
   Restore saved items
   Return the name table pointer
**/
long oldpos, oldtype;
int numitems, oldstate, oldoption;
struct name_table *ntbp;
char *c, *testname, *oldclass, *olditem, *oldsubclass, *oldtoken, segment[128];
							    /* step 1 */
for (c = segment; *definername && *definername != '.'; *c++ = *definername++);
*c = 0;
if (*definername) definername++;
if (!(testname = (char *)calloc(BSIZE + (2 * strlen(classname)) +
    strlen(itemname) + strlen(subclass) + strlen(token) + 8, 1)))
    fatal(7, (char *)0);
mk_in_name(testname, segment, inclass);
ntbp = find_name(testname);
if (!ntbp->name)
    {
							    /* step 2 */
    for (c = testname; *c; c++);
    c = cat((oldclass = &c[1]), classname);
    c = cat((olditem = &c[1]), itemname);
    c = cat((oldsubclass = &c[1]), subclass);
    c = cat((oldtoken = &c[1]), token);
    oldpos = lseek(fd, 0L, 1);
    oldstate = state;
    oldoption = option;
    oldtype = type;
    if ((ntbp = find_name(inclass))->name && ntbp->pos >= 0)
    	{
        lseek(fd, ntbp->pos, 0);
    	cat(classname, inclass);
    	for (numitems = 0 ; get_token(fd, token, '(') && *token != '}' &&
    	    strcmp(token, segment); )
	    {
	    if (*token == ',') numitems++;
	    }
    	if (!strcmp(token, segment))
    	    {
    	    cat(itemname, token);
    	    *itemname = 0;
    	    parent = ntbp - (struct name_table *)name_area.area;
    	    read_item(fd, parent, 0);
    	    ntbp = &((struct name_table *)name_area.area)
                [add_child(testname, parent, numitems, -1, 0)];
	    ntbp->pos = lseek(fd, 0L, 1);
    	    if (*subclass) cat(inclass, subclass);
    	    else cat(inclass, find_class(type));
							    /* step 3 */
    	    if (*definername) ntbp = find_definer(fd, definername, parent);
    	    lseek(fd, oldpos, 0);
	    }
	}
    else if (ntbp->name) ntbp = &((struct name_table *)name_area.area)
        [add_child(testname, (ntbp - (struct name_table *)name_area.area),
        -1, -1, 0)];
    cat(classname, oldclass);
    cat(itemname, olditem);
    cat(subclass, oldsubclass);
    cat(token, oldtoken);
    state = oldstate;
    option = oldoption;
    type = oldtype;
    }
free(testname);
return ntbp;
}

static struct name_table *last_false(struct name_table *table,
    struct name_table *ptbp)
{
/**
Function: Finds lowest generation 'false' child of ptbp, which must be false
Returns: IF there's a false child, pointer to its lowest false child
	 ELSE what a call of this function for the child returns
Procedure:
1. Find the sole child of this parent
   IF it's not false, return the parent pointer
   Return what this functions calls for the child
**/
struct name_table *ctbp;
struct parent *cparentp;
int curr_parent = ptbp - table;
for(ctbp = table; ctbp->name; ctbp++)
    {
    for(cparentp = &ctbp->parent; cparentp; cparentp = cparentp->next)
	{
	if (cparentp->index == curr_parent) break;
	}
    if (!cparentp) continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -