Critical Design Review (CDR) Document


1996 SPRING BDESYM TEAM

Bob Connell

Bob Costello

April 24, 1996 - Version 1.1


1.0 Integration of 94 Fall BDESYM Revisions.

The 94 Spring BDESYM Team revised the CHGEN program to support additional "iskey" values to denote text fields that referenced symbol reference [YR Table] or text block [XB Table] foreign keys. The 94 Spring team suggested revision of the native CHGEN pr_get/set_str macros to utilizize the TT and TA metadata tables to determine the appropriate text access routine at execution time.

The 96 Spring BDESYM Team expanded upon this approach and developed the polymorphic string field access macros described in this document. The macros minimize searches of the TT and TA metadata tables by checking the current position in these tables prior to initiaing table searches.

1.1 pr_get_str macro.

/* ====================================================================

pr_get_str macro.

Preconditions.

o A properly initialized database environment must exist. The pr_get_str macro uses the TT and TA metadata tables to determine the characteristics of the requested field at execution time.

o A pointer to hcg_key type [created by pr_create()] for the table containing the requested field should be supplied as the first parameter to the macro. The specified table must exist in the database schema.

o The table field name must be supplied as the second macro parameter.

The specified field must exist in specified table.

o The specified field must be defined in the database schema as a

character or text field.

o The table's schema "is_key" fields for text fields stored as

XB or YR references must be coded with the values 'x' or 'y'

as described in the 94 Fall BDESYM Project Report.

o The parameters supplied to the macro must be the names of null

delimited character strings.

o When pr_get_str is used as the source of a C language assignment

statement, the target field should be defined as a C character

string. The defined length of the target field should be .ge.

the length of the source field in the database schema.

Postconditions.

o The requested value of the requested character field is returned.

o In the event that an invalid or non-existent table identifier is

supplied as the first macro parameter, the program will halt on

an assertion.

o In the event that an invalid or non-existent field name is supplied

as the second macro parameter, the program will halt on an

assertion.

Alters.

o The value of TTcurr and TAcurr may be altered.

Programmer Notes.

o The required CHGEN generated header file and the C library header

files string.h and assert.h must be included in the compilation

unit.

o The signal processing routine generated bt CHGEN will catch an

abort signal generated by an assertion. A bdeabort.dat file will

be created by the signal processing routine prior to exit.

==================================================================== */

#define pr_get_str(pkval,fld) \

/* hcg_key *pkval */ \

/* char *fld */ \

do { \

char decoded_tbl_abbr[ARR_SIZE+1]; /* required for get_abbr() */ \

get_abbr(pkval,decoded_tbl_abbr); \

assert(decoded_tbl_abbr[0] != '\0'); \

/* \

search TT table for the requested table \

look at the TTcurr pointer before initiating the TT table search \

*/ \

if ((TTcurr == NULL) || \

(strcmp(TTcurr->TTabbr,decoded_tbl_abbr) != 0)) \

find_str_loop("94sbdeview",TT,TTabbr,decoded_tbl_abbr) ; \

assert(strcmp(TTcurr->TTabbr,decoded_tbl_abbr) == 0); \

/* \

search TA table for the requested field \

look at the TAcurr pointer before initiating the search \

*/ \

if ((TAcurr == NULL) || \

(strcmp(TAcurr->TAname),"fld") != 0)) \

child_loop(TT,TA,TAid,TTid) \

{ \

if (strcmp(TAcurr->TAname,fld) == 0) \

break ; \

} \

assert(strcmp(TAcurr->TAname,"fld") == 0); \

if (TAcurr->is_key == (int) 'x') \

pr_get_tokset(pkval,fld) ; \

else \

if (TAcurr->is_key == (int) 'y') \

pr_get_sym(pkval,fld) ; \

else \

(pkval)->fld; \

} while(0)

1.2 pr_set_str macro.

/*=====================================================================

pr_set_str macro.

Preconditions.

o A properly initialized database environment must exist. The

pr_set_str macro uses the TT and TA metadata tables to determine

the characteristics of the requested field at execution time.

o A pointer to hcg_key type [created by pr_create()] for the table

containing the requested field should be supplied as the first

parameter to the macro. The specified table must exist in the

database schema.

o The table field name must be supplied as the second macro parameter.

The specified field must exist in specified table.

o The specified field must be defined in the database schema as a

character or text field.

o The table's schema "is_key" fields for text fields stored as

XB or YR references must be coded with the values 'x' or 'y'

as described in the 94 Fall BDESYM Project Report.

o The parameters supplied to the macro must be the names of null

delimited character strings.

o When pr_set_str is used as the source of a C language assignment

statement, the target field should be defined as a C character

string. The defined length of the target field should be .ge.

the length of the source field in the database schema.

Postconditions.

o The field in the requested table is set to the supplied value.

o In the event that an invalid or non-existent table identifier is

supplied as the first macro parameter, the program will halt on

an assertion.

o In the event that an invalid or non-existent field name is supplied

as the second macro parameter, the program will halt on an

assertion.

o If the size of the value field exceeds the size specified in the

database schema, a warning message is issued to STDERR and the

field is truncated.

Alters.

o The value of TTcurr and TAcurr may be altered.

Programmer Notes.

o The required CHGEN generated header file and the C library header

files string.h and assert.h must be included in the compilation

unit.

o The signal processing routine generated bt CHGEN will catch an

abort signal generated by an assertion. A bdeabort.dat file will

be created by the signal processing routine prior to exit.

==================================================================== */

#define pr_set_str(pkval,fld,value) \

/* hcg_key *pkval */ \

/* char *fld */ \

/* vhar *value */ \

do { \

char decoded_tbl_abbr[ARR_SIZE+1]; /* required for get_abbr() */ \

get_abbr(pkval,decoded_tbl_abbr); \

assert(decoded_tbl_abbr[0] != '\0'); \

/* \

search TT table for the requested table \

look at the TTcurr pointer before initiating the TT table search \

*/ \

if ((TTcurr == NULL) || \

(strcmp(TTcurr->TTabbr,decoded_tbl_abbr) != 0)) \

find_str_loop("94sbdeview",TT,TTabbr,decoded_tbl_abbr) ; \

assert(strcmp(TTcurr->TTabbr,decoded_tbl_abbr) == 0); \

/* \

search TA table for the requested field \

look at the TAcurr pointer before initiating the search \

*/ \

if ((TAcurr == NULL) || \

(strcmp(TAcurr->TAname),"fld") != 0)) \

child_loop(TT,TA,TAid,TTid) \

{ \

if (strcmp(TAcurr->TAname,fld) == 0) \

break ; \

} \

assert(strcmp(TAcurr->TAname,"fld") == 0); \

if (TAcurr->is_key == (int) 'x') \

pr_set_tokset(pkval,fld,value) ; \

else \

if (TAcurr->is_key == (int) 'y') \

pr_set_sym(pfval,fld,value) ; \

else \

{ \

if (strlen(value) >= sizeof((pkval)->fld)) \

fprintf(stderr,"Warning:field %s in table %s is too long-truncated\n", \

#fld, decoded_tbl_abbr) ; \

strncpy( (pkval)->fld, (value), sizeof((pkval)->fld)-1); \

} \

} while(0)

1.3 Other String Manipulation Macros.

To insure correct functionality of other CHGEN string access macros, direct references to fields were replaced with pr_get_str macro calls.

/*

find_str_loop_all -- revised to use polymorphic pr_get_str

*/

#define find_str_loop_all(tbl,field,value) \

for (tbl##curr = tbl; tbl##curr != NULL; \

tbl##curr=tbl##curr->next_ptr) \

if (strcmp(pr_get_str(tbl##curr,field),value) == 0)

/*

find_str_loop -- revised to use polymorphic pr_get_str

*/

#define find_str_loop(viewname,tbl,field,value) \

if (find_view_idx(viewname)) \

for (tbl##curr = tbl; tbl##curr != NULL; \

tbl##curr=tbl##curr->next_ptr) \

if ((meets_view(tbl##_idx,hcg_view_idx,tbl##curr->tbl##id)) && \

(strcmp(pr_get_str(tbl##curr,field),value) == 0))

/*

var_find_str_loop_all -- revised to use polymorphic pr_set_str

*/

#define var_find_str_loop_all(tbl,tblvar,field,value) \

for (tblvar = tbl; tblvar != NULL; tblvar=tblvar->next_ptr) \

if (strcmp(pr_get_str(tblvar,field),value) == 0)

/*

var_find_str_loop -- revised to use polymorphic pr_get_str

*/

#define var_find_str_loop(viewname,tbl,tblvar,field,value) \

if (find_view_idx(viewname)) \

for (tblvar = tbl; tblvar != NULL; tblvar=tblvar->next_ptr) \

if ((meets_view(tbl##_idx,hcg_view_idx,tblvar->tbl##id)) && \

(strcmp(pr_get_str(tblvar,field),value) == 0))

2.0 pr_load row encode/decode routines.

The key encoding approach outlined in the 96 Spring BDESYM PDR requires that key values be externally represented as hexadecimal character strings. To support this requirement, two pr_load routines [row_decode and row_encode] must be revised to support hexadecimal encoding of key values. The changes to the impacted routines are detailed below.

2.1 row_decode routine.

/*******************************************************************

int row_decode(const hcg_key* input_key,

char* decoded_row)

Description:

Decode the row portion of the passed hcd_key type field and return

decoded row as a hexadecimal character string.

Called By:

row_decode is called by the decode function in the pr_load.c routine

generated by chgen

Revisions.

96 Spring BDESYM rcostell Revised routine to return row value as a

hexadecimal character string, renamed formal parameters, revised

sprintf format specification to support hexadecimal strings, altered

indenting

Preconditions.

o A pointer to a valid hcg_key type field should be passed as the

first argument to the row_decode function.

o A pointer to a character type field should be passed as the second

argument to the row_decode function. The size of the field should be

sufficent to support the decoded row field. If the database schema is

defined with eight character keys, the decoded row field is four

characters [OLD_ROW_LEN]. If the database schema is defined with

twelve character keys, the decoded row field is a five characters

[NEW_ROW_LEN]. The key_len global static variable is used to determine

the key size chosen at schema generation time. The rwshift and rwmask

global variables are used to isolate the row portion of the hcg_key

type field passed as the first argument.

Postconditions.

o The row number of the hcg_key type field passed to the routine is

returned in character format at the location passed as the second

argument to the routine. Successful decoding is indicated by a return

value of 1.

o With the 96 Spring BDESYM project changes, the row number is

returned as a character format hexadecimal string.

o If the key_len global static variable contains a value unknown to

row_decode, the routine returns -1 and does not alter the character

type field passed as the second argument.

Alters.

o None

*******************************************************************/

int row_decode( input_key,

decoded_row )

hcg_key* input_key; /* input const hcg_key* */

char* decoded_row; /* output char* */

{

int rwi;

rwi = (int) ((*(unsigned long*)input_key >> rwshift) & rwmask);

if( key_len == OLD_KEY_LEN )

{

sprintf(decoded_row, "%04X", rwi);

}

else if( key_len == NEW_KEY_LEN )

{

sprintf(decoded_row, "%05X", rwi);

}

else

{

return -1;

}

return 1;

}

2.2 row_encode routine

/*******************************************************************

int row_encode( hcg_key* output_key,

const char* input_row)

Description:

Encode the row_number provided into the passed hcg_key type field.

Validate the row_number passed using the global constant max_row.

Called By.

row_encode is called by the encode function in the pr_load.c routine

generated by chgen

Revisions.

96 Spring BDESYM rcostell Revised routine to accept row value as a

hexadecimal character string, renamed formal parameters, revised sprintf

format specification to support hexadecimal strings, altered indenting

Preconditions.

o A pointer to a valid hcg_key type field should be passed as the first

argument to the row_encode function.

o A pointer to a null delimited C character string should be passed

as the second argument to the row_decode function. The character

string should be a hexadecimally encoded table row number.

[NEW_ROW_LEN].

o The max_row global static variable is used in determining the validity of the row number passed to the routine. The rwmask global variable is used in building the row portion of the hcg_key type field passed as the first argument.

Postconditions.

o The row number portion of the hcg_key type field passed to the routine as the first argument is populated with an encoding of the row_number passed as the second argument to the routine. Successful encoding is indicated by a return value of 1.

o If the row number passed as the second argument can not be successfully encoded, the routine returns -1 and does not alter the hcg_key* type field passed as the first argument. In this event, a diagnostic message is written to stdout.

Alters.

o None

*******************************************************************/

int row_encode( output_key,

input_row )

hcg_key* output_key; /* output hcg_key* */

char* input_row; /* input const char* */

{

unsigned long rw;

char* unconv_suff = NULL;

if( (rw = strtoul(input_row, &unconv_suff, 16)) > max_row )

{

printf("ERROR: failure to encode row value:");

printf(" %s; MAX allowed row: %d\n", input_row, max_row);

return -1;

}

else

{

*(unsigned long*)output_key |= (rw & rwmask);

return 1;

}

}

3.0 Changes to the schema

As documented in the PDR short tokens (3 characters or less) are now captured in the token table (TK) and repeated character strings will be encoded in the SY foreign key (SYid). Therefore there is no longer a need for the tktyp field in the TK table. Many of the functions that previously used the tktyp field has been improved.

Secondly, a space character is typically a default character which used to be represented by a row in the TK Table using the tktyp field. Part of the improvement is to remove the requirement of placing a separate row in the TK table for a space and making it the default. In the case of a multiple space before a symbol the field space has been added to the TK table. The field space is of type integer and is added to define how many spaces to place before the token is printed.

Changes to the TK table include :

token TK /* token descriptor */

{

TKid tokenid c8 1 /* pkey of the token */

XBid textblockdesid c8 1 /* fkey of text block des. */

SYid symbolid c8 1 /* fkey of symbol */

space prefixspace i4 0 /* spacing before token */

}

4.0 Changes to SYMTXT source code

Modification of the TK table in the schema results in several required changes to the SYMTXT code located in the /text directory. Included in these source changes include the way spaces are handled and encoding of the repeat literal string in the SY foreign key.

Each module which requires a change is presented below. Included in this review is a description of the change, the function header description(s) and the proposed code changes.

4.1 sym_pj_mgr.c

The module sym_pj_mgr.c contains the function XB_restore_text(). The main purpose of this function is to obtain the text that is contained in within the TK table for the XB key passed in. This function XB_restore_text() needs to be modified to reflect the changes that were made in the TK table. All references to the tktyp field of the TK table shall be removed. This function also checks to see if a repeated literal string is encoded in the SY foreign key (SYid) by checking to see if the 5th character is set to "F". If the 5th character is encoded with an "F" then this function attempts to extract the literal token stored in character positions 7 & 8. Once the token is decoded the repeat count is obtained from the 6th character position and the character is placed into the buffer that many times. The prefix spacing has been added to this function. The number of spaces added is determined by the space field in the TK table.

/*

** FUNCTION NAME: XB_restore_text()

**

** FUNCTIONAL DESCRIPTION: This function restores the text specified by the XBid,

**

** RETURN VALUE: pointer to a character array (*text).

**

** Preconditions:

** o The value of xb_pkey is of type hcg_key for a row in the XB

** table and is passed in as the first parameter

**

** Postconditions:

** o The token encoded in the SY foreign key or located in the symbol

** table and is returned as a character pointer.

**
** Alters:

** o If xb_pkey is NULL a warning message is printed out and NULL is

** returned.

*/

char *XB_restore_text(xb_pkey)

hcg_key xb_pkey; /* hcg_key value for a row in XB table. */

{

/*

**

*/

int i; /* Scratch... loop variable */

int j;

char literal_value; /* Character value of the decoded literal */

char word [ SYMBOL_NAME_SIZE + 1]; /* word string copied from the schema structure */

hcg_key xbkey;/* key of a DS structure */

char *buffer; /* Buffer where extracted items are placed */

int spacing; /* Used to help count spaces of each TK token extracted */

char syid_string[13];/* A decoded SYid into a character string */

buffer = (char *)malloc(128* sizeof(char));

pr_find(XB,XBid, xb_pkey);

if ( XBcurr == NULL )

{

printf("\n\nSYMTXT-E-INVDS, invalid or non-existent XBid\n\n\n");

return NULL;

}

child_loop(XB,TK,TKid,XBid)

{

:

/* Add the prefix spaces to the buffer

* prior to getting the token.

*/

spacing = TKcurr->space;

while(spacing > 0)

{

strcat(buffer, " ");

spacing--;

}

/* Decode the SY foreign key id into a character string in order for processing */

pr_set_key(TK_elt, SYid, sy_key);

decode(syid_string, &sy_key);

/*

* If the 5th field in the SY foreign key field is not set to "F" then attempt to

* retrieve the symbol from the symbol table SY, otherwise decode the

* literal value from the SY foreign key.

*/

if (syid_string[4] != "F")
{

pr_find(SY,SYid,TKcurr->SYid);

strcpy((char *) &word[ 0 ], (char *) &SYcurr->symnam[0] );

i = 0;

while( word[ i ] != ' ' )

i++;

word[ i ] = '\0';

strcat(buffer, &word[0]);

}

else

{

/*

** The syid_string has been encoded with a literal token.

** This sections extracts the literal token out of the 7th and 8th

** field of the SYid.

*/

if (syid_string [ 6 ] >= 'a' )

{

literal_value = (syid_string [6] - 'a' + 10 ) * 16;

if (syid_string [ 7 ] >= 'a' )

literal_value += syid_string [ 7 ] - 'a' + 10;

else

literal_value += syid_string [ 7 ] - '0';

}

else {

literal_value = (syid_string [ 6 ] - '0' ) * 16;

if (syid_string [ 7 ] >= 'a' )

literal_value += syid_string [ 7 ] - 'a' + 10;

else

literal_value += syid_string [ 7 ] - '0';

}

/*

** Extract the repeat count from the 6th field and go

** through the for loop printing the individual literal value.

*/

for ( i = 1; i <= (syid_string[ 5 ] - 33 ); i++ ) {

word[0] = literal_value;

word[1] = '\0';

strcat(buffer, &word[0]);

}

break;

}

} /* end child_loop */

return (buffer);

}

4.2 sym_tk_mgr.c

This module contains three functions which require change due to the TK table changes in the schema. There are also two functions within this module that are duplicated in symtxt.c and should be removed.

4.2.1 TK_generator()

The function TK_generator() is called to process a token when a token is matched according to the pattern specified by the lex rules. This function needs to be updated first to remove the references to the tktyp field of the TK table. The section of code which encodes a short word in the tktyp field of the TK table is removed. The section which places "0000" and "XXXX" in the tktyp table is removed also.

/*

** FUNCTION NAME: TK_generator()

**

** FUNCTIONAL DESCRIPTION: This function is responsible for processing of the

** tokens initially received from the lexical analyzer.

** It then builds a TK structure based on the sym_schema

** and updates the SYid keys.

**

** RETURN VALUE: None.

**

** CALLING SEQUENCE: TK_generator(unsigned int, char *, int, hcg_key )

**

** Preconditions:

** o The curr_view_name parameter is defined with the current view

** o The lex_token_type variable contains an unsigned integer

** describing the type of token processed by the lexical analyzer

** o The lex_symbol variable contains a valid character pointer to

** the symbol name

** o The lex_symbol name variable contains the string length of the

** symbol name

** o The previous_lexical variable is either set to "\0" or some

** other literal value

**

** Postconditions:

** For LITERALS :

** o If the previous_lexical[0] variable is the same as the lex

** symbol passed in then the lexical_cnt variable is incremented

** by 1.

** o The previous_lexical[0] variable contains the value of lex

** symbol passed in.

** o The lexical_cnt variable is set to one if the lex_symbol being

** processed is not the same as the previous lex symbol.

** For WORDS :

** o The lexical symbol length is a valid integer from 1-MAXLEN and

** is the sting length of the symbol

**

** Alters:

**

*/

int TK_generator(lex_token_type, lex_symbol, lex_symbol_len ,xb_pkey)

unsigned int lex_token_type; /* an unsigned integer describing the type of token processed by the lexical analyzer. */

unsigned char *lex_symbol;/* a char pointer of the symbol name */

int lex_symbol_len; /* string length of the symbol name */

hcg_key xb_pkey;

{

/*

** DECLARATIONS

*/

char *encoded_token; /* Encoded value of literal or word token */

char syid_string[ 13 ]; /* A decoded SYid into a char string */

char word_str[ SYMBOL_NAME_SIZE + 1 ]; /* Max size of word token allowed by schema */

hcg_key tmp_key; /* temp SY key used for updating tktyp */

struct TK *TK_elt; /* chgen TK structure taken from sym_schema.h */

word_str[ 0 ] = '\0';

switch( lex_token_type )

{

case LITERAL_TOKEN :

/*

**Match the current literal with the previous one. If they are the

** same, determine if the literals are '\n' characters. If so, and

** the lexical_cnt is a multiple of 2, create a XB row in the

** network database. If the previous literal is not a '\n' and the

** previous literal is equal to the current one, just increment

** the lexical cnt. When the previous literal is different from

** the current one, encode it along with the repeat count

** "lexical_cnt" in the network database.

*/

switch( previous_lexical[ 0 ] )

{

case '\0' :

previous_lexical[ 0 ] = *lex_symbol;

lexical_cnt = 1;

break;

default :

if ( previous_lexical[ 0 ] == *lex_symbol )

{

lexical_cnt++;

if(( previous_lexical[ 0 ] == '\n' ) && ( lexical_cnt % 2 == 0 ))

{

/************* start ******************* added by 94ssym BDESYM Group ***********/

/*

XB_elt = pr_create( XB );

pr_add(curr_view_name, XB, XB_elt);

*/

/************ end ******************* added by 94ssym BDESYM Group **************/

}

break;

} else {

TK_save_previous_literals(xb_pkey);

previous_lexical[ 0 ] = *lex_symbol;

lexical_cnt = 1;

break;

}

}

break;

case WORD_TOKEN :

/*

** Process the word token received from the lexical analyzer. First,

** save any previous literals that were not saved.

*/

TK_save_previous_literals(xb_pkey);

/*

** Update the TK database with the regular word.

** Update the word normally, unless the size of the

** is greater then SYMBOL_NAME_SIZE, which corresponds to the symbolname

** size. If that's the case, break up the word into chunks not to

** exceed SYMBOL_NAME_SIZE in size, and update them in the database

*/

TK_elt = pr_create(TK);

pr_set_key(TK_elt, XBid, xb_pkey);

if ( lex_symbol_len > SYMBOL_NAME_SIZE )

{

strncpy((char *) &word_str[ 0 ], lex_symbol, SYMBOL_NAME_SIZE );

word_str[ SYMBOL_NAME_SIZE + 1 ] = '\0';

} else {

strcpy((char *) &word_str[ 0 ], lex_symbol);

word_str[ lex_symbol_len + 1 ] = '\0';

}

sy_key = SY_manager( (char *) &word_str[ 0 ] );

pr_set_key(TK_elt, SYid, sy_key );

pr_add(curr_view_name, TK, TK_elt);

decode(syid_string, &sy_key);

if ( syid_string[ 4 ] > 'E' )

{

printf("SYMTXT-W-TKCNT, exceeded SYid count\n");

} else

lex_symbol_len = 0;

}

break;

}

return;

}

4.2.2 TK_encode_token()

The function TK_encode_token() will be modified to prepare the literal token to be encoded in the SY foreign key (SYid). This function is not called for regular words (including short words). Regular words are encoded in the SY table when the function SY_manager() is called. When given a literal token this function will encode the literal into the SY foreign key (SYid) and return a pointer to the string. The hexadecimal value for the literal passed in is computed and encoded into the 7th and 8th character fields. This was previously encoded in the 3rd and 4th field of the tktyp field (e.g. SY00F221 - which represents 3 instances of !). Existing code segments used to encode a short word in the tktyp field of the TK table will be removed.

Another change includes the removal of two function arguments. The encoding_type argument use to specify whether the token passed in was a WORD type or a LITERAL type. Since short words are no longer encoded in the TK table and all other non-literal words are encoded in the SY table there is no need to have this encoded in any row of the TK table. Only LITERAL token types are encoded into the TK table. The token_length argument will be removed since it is currently not used in the function. The only calling function that will need to be adjusted to these arguments changes is TK_save_previous literals().

Code for encoding a word type in the tktyp field will be removed from this function. The code for encoding a repeated literal string in the tktyp field is modified slightly.

/*

** FUNCTION NAME: TK_encode_token().

**

** FUNCTIONAL DESCRIPTION: This functions encodes a given literal

** into the SY foreign key

**

** RETURN VALUE: coded_str - pointer to the encoded character string.

**

** CALLING SEQUENCE: TK_encode_token().

**

** IMPLICIT INPUT PARAMETERS: None

**

** IMPLICIT OUTPUT PARAMETERS: None

**

** Preconditions:

** o The token field contains a valid 1 character literal returned ** by the lex analyzer

** o The repeat count variable is a valid integer from 1 to 16

**

** Postconditions:

** o The token is encoded in a 8 character string. A pointer to is ** returned to the calling function

**

** Alters:

** o The function will encode the value no matter if it is of type

** literal or not.

**

*/

char *TK_encode_token(, token, , repeat_count )

char *token; /* char ptr to the token string */

unsigned int repeat_count; /* repeat count for the literal character */

{

/*

** DECLARATIONS

*/

static char coded_string[ TOKENTYPE_LEN ]; /* The encoded value returned by this function. */

unsigned char tmp_char; /*Scratch character used for manipulations */

/*

** Encode a single literal character that is repeated

** many times.

** e.g. white spaces, '...', '!!!', or other literal

** types. This encoding

** is done as follows:

** -- place LITERAL_TYPE (i.e. SY00F) in char

** position 0-4 to indicate the

** type of token.

**

** -- Convert the repeat count to a printable character,

** i.e. ASCII codes (33 through 126), by adding 33.

** Copy this repeat character to position 5

**

** -- Lastly convert the ASCII value of the literal to

** a string, with char position [6] having the half

** byte hex value, and char position [7] having the low

** half byte hex

** value. The result indicates the ASCII hex value of

** the literal,

** in string format from positions 6 and 7.

*/

coded_string[ 0 ] = LITERAL_TYPE;

coded_string[ 5 ] = (char ) ( repeat_count + 33 );

tmp_char = (*token & 0xf0) >> 4;

if ( tmp_char >= 10 )

tmp_char = tmp_char - 10 + 'a';

else

tmp_char = tmp_char + '0';

coded_string[ 6 ] = tmp_char;

tmp_char = *token & 0x0f;

if ( tmp_char >= 10 )

tmp_char = tmp_char - 10 + 'a';

else

tmp_char = tmp_char + '0';

coded_string[ 7 ] = tmp_char;

coded_string[ 8 ] = '\0';

return &coded_string[ 0 ];

break;

}

4.2.3 TK_save_previous_literals()

Changes to this function include the re-adjusting the function call to TK_encode_token() to account for its change in parameters. The first parameter to be removed is the global LITERAL_TYPE which is simply states that the token passed in is a literal. This is no longer needed since the only tokens that TK_encode_token() processes now is literals. The second paramter passed is "1" and this is the default.

The second change, involves changing the repeat count value of a repeated literal string from 93 to 16. The define statement #define REPCOUNT 16 will be created in order to allow for easier code changes in the future.

Sections that previously placed the encoded token in the tktyp field has been reworked to encode it in the SY foreign key (SYid) field.

/*

** FUNCTION NAME: TK_save_previous_literals()

**

** FUNCTIONAL DESCRIPTION: This functions saves any literal that was

** not previously saved. It's called before a new token is processed.

** This is necessary, when a single literal is repeated many times,

** followed by a normal non literal token.

**

** RETURN VALUE: None

**

** CALLING SEQUENCE: TK_save_previous_literals().

**

** PRECONDITONS:

** o A valid xb_pkey is passed in.

** o The lexical_cnt value is a valid integer value of 0-16

**

** Postconditions:

** o The lexical_cnt value is returned with the value 0.

** o The previous_lexical variable is set to "\0".

** o The encoded token is encoded in the SY foreign key (SYid)

** o New row(s) are added to the TK table with the current XB pointer

** with a maximum repeat count of 16.

**

** Alters:

** o Results are un-predictable if the lexical_cnt is not within the

** 0-16 value.

*/

int TK_save_previous_literals(xb_pkey)

hcg_key xb_pkey;

{

/*

** DECLARATIONS

*/

unsigned int temp_cnt; /* A counter of the number of processed */

/* literal tokens */

char *encoded_token; /* Encoded value of literal or word token */

struct TK *TK_elt; /* chgen TK structure taken from */

/*

** Check to make sure that previous literal exist. If they don't, just return.

** There is no need to perform additional checking.

*/

if ( lexical_cnt != 0 )

{

/*

** Save any literals which occurred which were not processed. 16 is the

** magic number because if the repeat cnt exceeds 16, then it enters the

** realm of non printable characters and cannot be viewed directly. If

** the repeat count is greater than 16, create a new TK_elt which represents

** a literal that is repeated 16 of fewer times. Continue this until the

** literal and its repeat count is fully represented via TKid's.

*/

if( lexical_cnt <= REPCOUNT )

{

encoded_token = TK_encode_token(

&previous_lexical[ 0 ],

lexical_cnt );

TK_elt = pr_create(TK);

encode(encode_token, &sy_hcg_key);

pr_set_key(TK_elt, SYid, sy_hcg_key);

pr_set_key(TK_elt, XBid, xb_pkey);

pr_add(curr_view_name, TK, TK_elt);

previous_lexical[ 0 ] = '\0';

lexical_cnt = 0;

} else {

temp_cnt = REPCOUNT;

while( lexical_cnt != 0 )

{

encoded_token = TK_encode_token(,

&previous_lexical[ 0 ],

temp_cnt );

TK_elt = pr_create(TK);

encode(encode_token, &sy_hcg_key);

pr_set_key(TK_elt, SYid, sy_hcg_key);

pr_set_key(TK_elt, XBid, xb_pkey);

pr_add(curr_view_name, TK, TK_elt);

lexical_cnt = lexical_cnt - temp_cnt;

if ( lexical_cnt > REPCOUNT )

temp_cnt = REPCOUNT;

else temp_cnt = lexical_cnt;

}

}

previous_lexical[ 0 ] = '\0';

}

}

4.2.4 Functions to remove form sym_tk_mgr.c

get_tokset()

This function is repeated in symtxt.c and should be removed in this function.

get_sym()

This function is repeated in symtxt.c and should be removed in this function.

4.3 sym_sy_mgr.c

Removal of the tktyp field in the TK table does not affect this module.

4.4 symtxt.c

This module contains the functions get_sym() and get_tokset(). Neither function contains documentation. The following documentation is recommended to be added.

/*

FUNCTION: get_sym()

FUNCTION DESCRIPTION: Used to retrieve the text value for a

field of type "symref"

RETURN VALUE:

Preconditions:

o The tbl_idx is a valid integer that contains the value 1, 2, or 6

Postconditions:

o A charcater pointer to a symbol id is returned

Alters:

o Results are un-predictable if the tbl_idx is not a valid integer that contains the value 1,2, or 6

*/

/*

FUNCTION: get_tokset()

FUNCTION DESCRIPTION: Reconstructs a multi-word text from all the

tokens that belongs to a particular XBid, which belongs to a

particular table.

RETURN VALUE : Character string from the XB table

Preconditions:

o The tbl_idx is a valid integer that contains the value 1, 2, or 3

Postconditions:

o A pointer to an array of characters from the XB table is returned

Alters:

o Results are unpredictable if the tbl_idx is not between 1-3.

*/

4.5 Functions to be deleted

The following function found in the /text directory under specified unit (described below) is no longer used. This function should be removed from the module or at least provided with comments to describe that it is not part of BDESYM functions.


Function                 Unit                      

sy_add_symbol_name()     sym_sy_mgr.c              



4.6 Functions that don't require change


Function                 Unit                      

sy_manager()             sym_sy_mgr.c              

sy_get_sym_ptr()         sym_sy_mgr.c              



5.0 BDE Source Code Changes

5.1 "SY000000" references

All references in the code to "SY000000" should be removed. These SY foreign key (SYid) was set to this to signal the code that either a short word is stored in the tktyp field or that a literal token is stored in the tktyp field. Since the tktyp field will be removed it is necessary to remove and correct all references to this special key.

The files edit.cc and textops.cc reference the SY foreign key "SY000000" which in the old design represented that either an in-line token was encoded in the tktyp field or that a repeated character string was encoded in the tktyp field. This will need to be corrected.

6.0 Test Approaches

6.1 Creation of Graph 1

The first test case shall prove that a completely new graph can be created using the BDESYM functions. The graph in Figure 3 shall be created and given a name. Three nodes shall be created. Each of the nodes will be given a name of node <number>. Links between nodes shall be created and each of the links will be given a name of link <number>. The graph header will contain two literal tokens and extra spaces between the tokens. After the graph has been created it will be saved and a bdesym.dat file should be created in the lib directory.

To prove that the modified SYMTXT code works correctly with BDE the bdesym.dat file will be printed and inspected. There should be several block fields. The space field should be set to the correct value. The data file should not have any references to a TK tktyp field. The two literals added to the graph header shall be encoded in the SY foreign key (SYid).

6.2 Editing Graph 1

This second test case shall prove that the graph previously created in test case shall be able to be successfully modified by BDESYM functions. The graph will be selected and opened. The text string within node 1 will be modified from "node one" to "node uno". The text string attached to link 2 will be modified from "link two" to "link #2". A second graph header file will be added. After the modifications have been completed the graph will be printed and saved. BDE will be exited.

To prove that the modified SYMTXT works correctly with BDE the bdesym.dat file will be printed and inspected by comparing the results with the previous data file store. The text block (XB) for node 2, node 3, and link 1 and 3 should be the same as in the previous bdesym.dat file. The text block (XB) for node 1 should be changed. A new symbol entry should be placed in the SY table for the string "uno". A new symbol entry should be present in the SY table for the string "2". This row should have a prefix-space count of 0 since there are no spaces between # and 2. The literal "#" should be encoded into the SY foreign key. This row should also have prefix space count of 4.


[BDESYM Home] [PDR] [Final Report]