/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$XConsortium: UilSarComp.c /main/11 1995/07/14 09:36:46 drk $" #endif #endif /* * (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */ /* **++ ** FACILITY: ** ** User Interface Language Compiler (UIL) ** ** ABSTRACT: ** ** This module supports compound strings in UIL. It includes ** the basic operations for creating, copying, and concatenating ** strings. ** **-- **/ /* ** ** INCLUDE FILES ** **/ #include #ifdef DXM_V11 #include #endif #include "UilDefI.h" /* ** ** TABLE OF CONTENTS ** **/ /* ** ** DEFINE and MACRO DEFINITIONS ** **/ #define clear_class_mask (~(sym_m_private | sym_m_imported | sym_m_exported)) /* ** ** EXTERNAL VARIABLE DECLARATIONS ** **/ extern yystype yylval; /* ** ** GLOBAL VARIABLE DECLARATIONS ** **/ /* ** ** OWN VARIABLE DECLARATIONS ** **/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function creates a null compound string. ** ** FORMAL PARAMETERS: ** ** none ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** none ** ** SIDE EFFECTS: ** ** a copy of the primitive string may be made ** **-- **/ sym_value_entry_type *sem_create_cstr() { sym_value_entry_type *az_cstr_entry; az_cstr_entry = (sym_value_entry_type *) sem_allocate_node ( sym_k_value_entry, sym_k_value_entry_size + sizeof( char * ) ); az_cstr_entry->obj_header.b_flags = sym_m_builtin | sym_m_private; az_cstr_entry->b_type = sym_k_compound_string_value; az_cstr_entry->w_length = sizeof (char *); az_cstr_entry->b_direction = NOSTRING_DIRECTION; /* Fix for CN 16149 (DTS 10023) part 1 -- initialize charset info */ az_cstr_entry->b_charset = sym_k_error_charset; az_cstr_entry->az_charset_value = NULL; _sar_save_source_pos (&az_cstr_entry->header, &yylval); return az_cstr_entry; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function creates a null wide_character string. ** ** FORMAL PARAMETERS: ** ** none ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** none ** ** SIDE EFFECTS: ** ** a copy of the primitive string may be made ** **-- **/ sym_value_entry_type *sem_create_wchar_str() { sym_value_entry_type *az_wchar_str_entry; az_wchar_str_entry = (sym_value_entry_type *) sem_allocate_node ( sym_k_value_entry, sym_k_value_entry_size + sizeof( char * ) ); az_wchar_str_entry->obj_header.b_flags = sym_m_builtin | sym_m_private; az_wchar_str_entry->b_type = sym_k_wchar_string_value; az_wchar_str_entry->w_length = sizeof (char *); az_wchar_str_entry->b_direction = NOSTRING_DIRECTION; _sar_save_source_pos (&az_wchar_str_entry->header, &yylval); return az_wchar_str_entry; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function appends a primitive or a localized string to a ** compound string. ** ** FORMAL PARAMETERS: ** ** az_cstr_entry compound string ** az_str_entry primitive string or localized string ** op2_temporary true if op2 is not needed after operation ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** none ** ** SIDE EFFECTS: ** ** a copy of the primitive string may be made ** **-- **/ void sem_append_str_to_cstr(az_cstr_entry, az_str_entry, op2_temporary) sym_value_entry_type *az_cstr_entry; sym_value_entry_type *az_str_entry; boolean op2_temporary; { sym_value_entry_type *last_str_entry; sym_value_entry_type **ptr; sym_value_entry_type *new_str_entry; boolean merge; /* ** A couple of points: ** 1) if op2_temporary = FALSE - we must make a copy ** of it ** 2) if the last string of the compound string has the same attributes ** as the string being appended, the strings are merged into 1 */ /* find the last string of the compound string */ ptr = &(az_cstr_entry->az_first_table_value); last_str_entry = *ptr; merge = FALSE; if (last_str_entry != NULL) { for ( ; last_str_entry->az_next_table_value != NULL; ptr = (sym_value_entry_type * *) &(last_str_entry->az_next_table_value), last_str_entry = *ptr); if ((last_str_entry->b_charset == az_str_entry->b_charset) && ((last_str_entry->b_direction)== (az_str_entry->b_direction)) && ((last_str_entry->b_aux_flags & sym_m_separate) == 0 )) merge = TRUE; else ptr = (sym_value_entry_type * *) &(last_str_entry->az_next_table_value); } if (merge) { new_str_entry = sem_cat_str_to_str( last_str_entry, TRUE, az_str_entry, op2_temporary ); } else { /* ** Append a new segment to the compound string */ if( op2_temporary == FALSE ) { unsigned short old_size; /* must make a copy since user has access to string via name */ new_str_entry = (sym_value_entry_type *) sem_allocate_node( sym_k_value_entry, az_str_entry->header.w_node_size<<2 ); old_size = new_str_entry->header.w_node_size; _sym_copy_entry( new_str_entry, az_str_entry, az_str_entry->header.w_node_size ); new_str_entry->header.w_node_size = old_size; } else new_str_entry = az_str_entry; } /* link to the end of the compound string */ new_str_entry->b_aux_flags |= sym_m_table_entry; new_str_entry->obj_header.b_flags = sym_m_private | sym_m_builtin; new_str_entry->obj_header.az_name = NULL; new_str_entry->az_next_table_value = NULL; *ptr = new_str_entry; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function appends a compound string to a compound string. ** ** FORMAL PARAMETERS: ** ** az_cstr1_entry compound string ** az_cstr2_entry compound string ** op2_temporary true if op2 is not needed after operation ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** none ** ** SIDE EFFECTS: ** ** none ** **-- **/ void sem_append_cstr_to_cstr(az_cstr1_entry, az_cstr2_entry, op2_temporary) sym_value_entry_type *az_cstr1_entry; sym_value_entry_type *az_cstr2_entry; boolean op2_temporary; { sym_value_entry_type *last_str_entry; sym_value_entry_type **ptr; sym_value_entry_type *next_str_entry; /* ** A couple of points: ** 1) if op2_temporary = FALSE - we must make a copy of 2nd compound ** string ** 2) if the last string of 1st compound string has the same attributes ** as the 1st string of the 2nd compound string being appended, ** the strings are merged into 1 */ /* find the last string of the 1st compound string */ ptr = &(az_cstr1_entry->az_first_table_value); last_str_entry = *ptr; next_str_entry = az_cstr2_entry->az_first_table_value; if (op2_temporary) sem_free_node(( sym_entry_type *) az_cstr2_entry ); if (next_str_entry == NULL) return; if (last_str_entry != NULL) { for ( ; last_str_entry->az_next_table_value != NULL; ptr = (sym_value_entry_type * *) &(last_str_entry->az_next_table_value), last_str_entry = *ptr); if ((last_str_entry->b_charset == next_str_entry->b_charset) && ((last_str_entry->b_direction)== (next_str_entry->b_direction)) && ((last_str_entry->b_aux_flags & sym_m_separate) == 0 )) { last_str_entry = sem_cat_str_to_str( last_str_entry, TRUE, next_str_entry, op2_temporary ); last_str_entry->b_aux_flags |= sym_m_table_entry; *ptr = last_str_entry; next_str_entry = (sym_value_entry_type *) next_str_entry->az_next_table_value; } ptr = (sym_value_entry_type * *) &(last_str_entry->az_next_table_value); } if (op2_temporary) { *ptr = next_str_entry; return; } for ( ; next_str_entry != NULL; next_str_entry = (sym_value_entry_type *) next_str_entry->az_next_table_value ) { sym_value_entry_type *new_str_entry; unsigned short old_size; new_str_entry = (sym_value_entry_type *) sem_allocate_node( sym_k_value_entry, next_str_entry->header.w_node_size<<2 ); old_size = new_str_entry->header.w_node_size; _sym_copy_entry( new_str_entry, next_str_entry, next_str_entry->header.w_node_size ); new_str_entry->header.w_node_size = old_size; new_str_entry->obj_header.b_flags = sym_m_private | sym_m_builtin; new_str_entry->obj_header.az_name = NULL; new_str_entry->b_aux_flags |= sym_m_table_entry; /* link to the end of the compound string */ *ptr = new_str_entry; ptr = (sym_value_entry_type * *) &(new_str_entry->az_next_table_value); } *ptr = NULL; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function concatenates 2 primitive strings. ** ** FORMAL PARAMETERS: ** ** az_str1_entry primitive string ** op1_temporary op1 is a temporary string ** az_str2_entry primitive string ** op2_temporary op2 is a temporary string ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** ptr to the result string ** ** SIDE EFFECTS: ** ** none ** **-- **/ sym_value_entry_type *sem_cat_str_to_str (az_str1_entry, op1_temporary, az_str2_entry, op2_temporary) sym_value_entry_type *az_str1_entry; boolean op1_temporary; sym_value_entry_type *az_str2_entry; boolean op2_temporary; { sym_value_entry_type *new_str_entry; int l1, l2; /* ** Can only append two simple strings if they have the same direction and ** the first does not have the separate attribute. */ _assert(((az_str1_entry->b_charset == az_str2_entry->b_charset) && ((az_str1_entry->b_direction) == (az_str2_entry->b_direction)) ), "strings with different attrs concatenated" ); l1 = az_str1_entry->w_length; l2 = az_str2_entry->w_length; /* extra 1 is for terminating null */ new_str_entry = (sym_value_entry_type *) sem_allocate_node( sym_k_value_entry, sym_k_value_entry_size ); new_str_entry->value.c_value = XtCalloc(1, l1 + l2 + 1); new_str_entry->obj_header.b_flags = sym_m_builtin | sym_m_private; _sar_move_source_info_2 (&new_str_entry->header, &az_str1_entry->header); new_str_entry->b_charset = az_str1_entry->b_charset; new_str_entry->b_direction = az_str1_entry->b_direction; new_str_entry->b_aux_flags = (az_str1_entry->b_aux_flags & sym_m_separate); new_str_entry->b_type = sym_k_char_8_value; new_str_entry->w_length = l1 + l2; _move( new_str_entry->value.c_value, az_str1_entry->value.c_value, l1 ); _move( &new_str_entry->value.c_value[ l1 ], az_str2_entry->value.c_value, l2+1 ); /* ** if either of the operands is unnamed - free the node */ if (op1_temporary) { _free_memory( az_str1_entry->value.c_value ); sem_free_node(( sym_entry_type *) az_str1_entry ); } if (op2_temporary) { _free_memory( az_str2_entry->value.c_value ); sem_free_node(( sym_entry_type *) az_str2_entry ); } return new_str_entry; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function takes the charset sets understood by the parser ** and maps them to charsets understood by the symbol table and ** toolkit. ** ** FORMAL PARAMETERS: ** ** charset_as_subclass sym_k_..._charset literal naming charset ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** sym_k...charset name for charset ** ** SIDE EFFECTS: ** ** none ** **-- **/ int sem_map_subclass_to_charset(charset_as_subclass) int charset_as_subclass; { switch (charset_as_subclass) { case lex_k_fontlist_default_tag: case sym_k_fontlist_default_tag: return sym_k_fontlist_default_tag; case lex_k_default_charset: return uil_sym_default_charset; case lex_k_userdefined_charset: return sym_k_userdefined_charset; default: _assert (charset_as_subclass!=0, "charset code==0"); _assert (charset_as_subclass<=uil_max_charset, "unknown charset"); return charset_as_subclass; } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function verifies the character set indicated by the user. ** ** FORMAL PARAMETERS: ** ** current_frame current stack frame ** charset_frame stack frame of CHARSET token ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** none ** ** SIDE EFFECTS: ** ** none ** **-- **/ void sar_charset_verify ( charset_frame ) yystype *charset_frame; { key_keytable_entry_type *az_keyword_entry; _assert(((charset_frame->b_tag == sar_k_token_frame) || (charset_frame->b_tag == sar_k_value_frame)), "token or value frame missing" ); az_keyword_entry = charset_frame->value.az_keyword_entry; /* ** Store the current charset so it can be used by LEX to processes a ** string literal (if the CHARSET_NAME is used to prefix a string literal) */ Uil_lex_l_literal_charset = az_keyword_entry->b_subclass; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function converts a random NAME into a CHARSET_NAME ** with the default charset. ** ** FORMAL PARAMETERS: ** ** name_frame current stack frame containing NAME ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** modified name_frame ** ** FUNCTION VALUE: ** ** none ** ** SIDE EFFECTS: ** ** name_frame converted from NAME to CHARSET_NAME ** **-- **/ void sar_make_fallback_charset(name_frame) yystype *name_frame; { sym_name_entry_type *symbol_entry; static key_keytable_entry_type *az_keyword_entry = NULL; _assert(((name_frame->b_tag == sar_k_token_frame) || (name_frame->b_tag == sar_k_value_frame)), "token or value frame missing" ); /* Get symbol and check if already used as charset. */ symbol_entry = (sym_name_entry_type *)name_frame->value.az_symbol_entry; if ((symbol_entry->b_flags & sym_m_charset) == 0) { symbol_entry->b_flags |= sym_m_charset; diag_issue_diagnostic(d_default_charset, _sar_source_pos2(symbol_entry), symbol_entry->c_text, DEFAULT_TAG); } /* Get the default charset keyword entry. */ if (az_keyword_entry == NULL) az_keyword_entry = key_find_keyword(strlen(DEFAULT_TAG), DEFAULT_TAG); _assert((az_keyword_entry !=NULL), "default charset keyword missing"); /* Change NAME to CHARSET_NAME */ name_frame->value.az_keyword_entry = az_keyword_entry; name_frame ->b_type = az_keyword_entry->b_token; /* ** Store the current charset so it can be used by LEX to processes a ** string literal (if the NAME is used to prefix a string literal) */ Uil_lex_l_literal_charset = az_keyword_entry->b_subclass; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function checks the attributes of CHARACTER_SET function. ** ** FORMAL PARAMETERS: ** ** target_frame pointer to resultant token stack frame ** value_frame pointer to frame holding keyword and value ** prior_value_frame pointer to previous properties ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** void ** ** SIDE EFFECTS: ** ** attribute information is stuffed in target frame ** **-- **/ void sar_chk_charset_attr( target_frame, value_frame, prior_value_frame ) yystype *target_frame; yystype *value_frame; yystype *prior_value_frame; { /* ** Set up not specified values in the target frame. ** b_type will hold the sixteen_bit property */ switch (prior_value_frame->b_tag) { case sar_k_null_frame: /* ** no prior values */ target_frame->b_tag = sar_k_token_frame; target_frame->b_direction = NOSTRING_DIRECTION; target_frame->b_charset = uil_sym_default_charset; target_frame->b_type = 0; break; case sar_k_token_frame: case sar_k_value_frame: /* ** prior values - transfer them */ target_frame->b_tag = sar_k_token_frame; target_frame->b_direction = prior_value_frame->b_direction; target_frame->b_charset = prior_value_frame->b_charset; target_frame->b_type = prior_value_frame->b_type; break; default: _assert( FALSE, "prior value frame missing from stack" ); } /* ** Case on the keyword for the attribute given */ switch (value_frame->b_type) { case RIGHT_TO_LEFT: { sym_value_entry_type *value_entry; value_entry = (sym_value_entry_type *) value_frame->value.az_symbol_entry; /* ** If the value is a boolean, then just set the corresponding mask ** accordingly. */ if (value_entry->b_type == sym_k_bool_value) if (value_entry->value.l_integer == TRUE) target_frame->b_direction = XmSTRING_DIRECTION_R_TO_L; else target_frame->b_direction = XmSTRING_DIRECTION_L_TO_R; break; } case SIXTEEN_BIT: { sym_value_entry_type *value_entry; value_entry = (sym_value_entry_type *) value_frame->value.az_symbol_entry; /* ** If the value is a boolean, then just set the corresponding mask ** accordingly. */ if (value_entry->b_type == sym_k_bool_value) if (value_entry->value.l_integer == TRUE) target_frame->b_type |= sym_m_sixteen_bit; else target_frame->b_type &= ~sym_m_sixteen_bit; break; } default: _assert( FALSE, "keyword missing from stack" ); } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function makes a CHARACTER_SET and sets the properties ** of the string. ** ** FORMAL PARAMETERS: ** ** target_frame pointer to resultant token stack frame ** value_frame pointer to string value ** attr_frame pointer to strings attributes ** keyword_frame frame to use as locator for result ** ** IMPLICIT INPUTS: ** ** none ** ** IMPLICIT OUTPUTS: ** ** none ** ** FUNCTION VALUE: ** ** void ** ** SIDE EFFECTS: ** ** none ** **-- **/ void sar_make_charset (target_frame, value_frame, attr_frame, keyword_frame) yystype *target_frame; yystype *value_frame; yystype *attr_frame; yystype *keyword_frame; { sym_value_entry_type *value_entry; _assert( value_frame->b_tag == sar_k_value_frame, "value frame missing from stack" ); /* ** Set the character set information into the symbol table ** entry for the char_8 string that indentifies the name of this ** userdefined character set. */ value_entry = (sym_value_entry_type *) value_frame->value.az_symbol_entry; value_entry->b_charset = sym_k_userdefined_charset; /* BEGIN HaL fix CR 5547 */ sem_evaluate_value (value_entry); if (value_entry->b_type != sym_k_char_8_value) diag_issue_diagnostic (d_wrong_type, _sar_source_pos2( value_entry ), diag_value_text( value_entry->b_type ), "null-terminated string"); /* END HaL fix CR 5547 */ /* ** If the attr_frame is not null, it must be a value frame with contains ** a pointer to the attributes frame for this userdefined charset. */ if (attr_frame->b_tag == sar_k_token_frame) { /* ** Set the attributes of the string, as specified by the options ** to the CHARACTER_SET function, without disturbing any ** existing bits. */ value_entry->b_direction = attr_frame->b_direction; value_entry->b_aux_flags = (attr_frame->b_type & sym_m_sixteen_bit); } /* ** initialize the target frame */ _sar_move_source_info( target_frame, keyword_frame ); target_frame->b_tag = sar_k_value_frame; target_frame->b_type = sym_k_char_8_value; target_frame->b_flags = sym_m_private; target_frame->value.az_symbol_entry = value_frame->value.az_symbol_entry; /* ** Store the current charset so it can be used by LEX to processes a ** string literal (if the CHARACTER_SET function is used to prefix a ** string literal) */ Uil_lex_l_literal_charset = lex_k_userdefined_charset; Uil_lex_az_literal_charset = value_entry; }