📄 asn_tabulate.c
字号:
/*****************************************************************************
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 + -