int read_definition( int parent) { /** Function: General function to read a definition and fill in the appropriate global variables Inputs: file descriptor for input file Outputs: Sets flags in option and in flags. Fills in tag, type, min, max, and subclass Sets state as follows: IF definition is an upper bound, GLOBAL ELSE IF '{' OR '\n' is found, IN_DEFINITION Returns: IF end of file is reached, -1 ELSE 0 Procedure: 1. DO IF token is CHOICE, set type of ASN_CHOICE ELSE IF token is DEFINED, do the defined thing to fill in defined_by ELSE IF token is EMPTY, do nothing ELSE IF token is EXPLICIT, set temporary explicit flag ELSE IF token is IMPLICIT, clear temporary explicit flag ELSE IF token is OF, set OF bit in options and get the subclass name ELSE IF token is SIZE, get sizes ELSE IF token is TABLE, set table bit in flags and note file position ELSE IF token is '[', get tag ELSE IF token is '(', get min-max ELSE IF token is ',' AND not at a real definition, reset type ELSE IF token is numeric Clear any line end Set state to GLOBAL ELSE IF token is a known type name IF type is ENUMERATED, set enumerated flag IF no type so far, use this one ELSE IF OF flag set, set subtype to this type ELSE 'Or' the constructed bit into the present type ELSE IF (token begins with a capital letter OR *) AND type is not -1, set subclass & options IF no next token, return -1 WHILE state is IN_DEFINITION AND token is not '{' NOR '\n' Return 0 **/ long tmp; do { if (!strcmp(token, choice_w)) type = ASN_CHOICE; else if (!strcmp(token, defined_w)) { do_defined(); if (type >= ASN_CHOICE) subtype = type; else subtype = ASN_CHOICE; } else if (!strcmp(token, empty_w)); else if (!strcmp(token, explicit_w)) explicit1 |= 1; else if (!strcmp(token, implicit_w)) explicit1 &= ~1; else if (!strcmp(token, in_w)) { if (!*definer) syntax(token); if (!get_token(0, inclass)) syntax(definer); } else if (!strcmp(token, of_w)) { option |= ASN_OF_FLAG; if (!get_token(0, token)) syntax(of_w); if ((tmp = find_type(token)) != ASN_NOTYPE) get_expected(0, (subtype = (short)tmp), token); else if ((*token < 'A' || *token > 'Z') && *token != '*') syntax(token); else if (*subclass) syntax(subclass); /* misspelled SEQ/SET */ else option |= set_name_option(subclass, token); } else if (!strcmp(token, size_w)) get_size(token, &min, &max, parent); else if (!strcmp(token, table_w)) { flags |= ASN_TABLE_FLAG; tablepos = tell_pos(streams.str); table_start_line = curr_line - 1; /* adjust for extra \n */ } else if (*token == '[') tag = get_tag(token); else if (*token == '(') get_paren(token, &min, &max, parent); else if (*token == ',' && (*classname & 0x20)) type = -1; else if (*token >= '0' && *token <= '9') { while (get_token(0, token) && *token != '\n'); state = GLOBAL; return 0; } else if ((tmp = find_type(token)) != ASN_NOTYPE) { get_expected(0, tmp, token); if (tmp == ASN_ENUMERATED) flags |= ASN_ENUM_FLAG; if (type < 0) type = tmp; else if ((option & ASN_OF_FLAG)) subtype = (short)tmp; else if (tmp > 0) type |= (tmp & ASN_CONSTRUCTED); } else if (((*token >= 'A' && *token <= 'Z') || *token == '*') && type == -1) option |= set_name_option(subclass, token); if (!get_token(0, token)) return -1; } while (state == IN_DEFINITION && *token != '{' && *token != '\n'); return 0; }
int read_item( int parent, void (*func)(void)) { /** Function: General function to read an item and fill in appropriate global variables Input: File descriptor for input Outputs: Sets option flags Fills in tag, type, min, max, itemname, subclass, subtype, defaultname and numstring Procedure: 1. WHILE token is neither ',' NOR '}' IF token is '[', get tag ELSE IF token is '(' IF enumerated flag set, get material for tag or sub_val ELSE Get min-max ELSE IF token is CHOICE, set constructed bit in type ELSE IF token is COMPONENTS, do components stuff ELSE IF token is DEFAULT, make defaultname and set default flag ELSE IF token is DEFINED, do the defined thing to fill in defined_by ELSE IF token is EMPTY, do nothing ELSE IF token is EXPLICIT, set temporary explicit flag ELSE IF token is FUNCTION Set type Get all tokens up to comma or right brace ELSE IF token is IMPLICIT, clear temporary explicit flag ELSE IF token is OF, error ELSE IF token is OPTIONAL, set OPTIONAL flag in options ELSE IF token is SIZE, get min-max ELSE IF token is TABLE Get table name to skip it Set table variable ELSE IF token is TAGS OR UNIQUE, swallow it ELSE IF token is a defined type IF this is a table AND (there's a type OR a subclass already) append token to alt_subclasses ELSE IF have a subclass already, syntax error ELSE IF have no type yet, use that ELSE IF explicit tagging, set subtype ELSE 'Or' the constructed bit into type Get expected sequel to token, if any ELSE IF token begins with a number IF TABLE bit is set, convert number ELSE IF enumerated flag is set Put token into itemname prefixed with e Set enumerated flag ELSE IF in a table AND (token is TRUE OR FALSE) Make type boolean Put token in subclass ELSE IF name begins with a capital letter IF this is a table item AND (there is already a subclass OR a type) Append this to the alt_subclasses ELSE IF there is already a subclass OR a type, syntax error ELSE set the subclass and option from the token ELSE IF name begins with a lower-case letter IF this is a table item, increment the array count IF no itemname so far, set token in itemname with options IF no next token, return -1 2. IF token is '}' Peek at the next token IF it's '(', set the constrained flag Return 0 **/ char *c; long tmp; struct name_table *ntbp; struct id_table *idp = (struct id_table *)0; int parens; struct alt_subclass *altscp = (struct alt_subclass *)0; while (*token != ',' && *token != '}') { if (*token == '[') { tmp = get_tag(token); if (tag >= 0) tag |= tmp; else tag = tmp; } else if (*token == '(') { if ((flags & ASN_ENUM_FLAG)) { if (!get_token(0, token)) syntax(itemname); if (*(c = token) == '_') c++; if (find_name(classname)->type == ASN_OBJ_ID) { if (*c > '2') { if (!(idp = find_id(c))) syntax(c); strcpy(c, idp->val); idp = (struct id_table *)0; } sub_val = (char *)calloc(1, strlen(c) + 1); strcpy(sub_val, c); } else if (*c >= '0' && *c <= '9') { for (integer_val = 0; *c; integer_val = (integer_val * 10) + *c++ - '0'); if (*token == '_') integer_val = -integer_val; } else { integer_val = find_ub(token); add_child(token, parent, 0, (ulong) - 1, 0); } if (!get_known(0, token, ")")) syntax(itemname); } else get_paren(token, &min, &max, parent); } else if (!strcmp(token, choice_w)) { if (tag >= 0) tag |= ASN_CONSTRUCTED; else if (type >= 0) type |= ASN_CONSTRUCTED; else type = ASN_CONSTRUCTED; } else if (!strcmp(token, components_w)) do_components(func); else if (!strcmp(token, default_w)) { option |= (ASN_OPTIONAL_FLAG | ASN_DEFAULT_FLAG); get_token(0, token); c = defaultname; if (*token >= '0' && *token <= '9') *c++ = '0'; else if (!strcmp(token, empty_w) || !strcmp(token, null_w) || (*token == '"' && token[1] == '"')) cat(token, "{"); strcpy(c, token); } else if (!strcmp(token, defined_w)) { do_defined(); } else if (!strcmp(token, empty_w)); else if (!strcmp(token, explicit_w)) explicit1 |= 1; else if (!strcmp(token, function_w)) { type = ASN_FUNCTION; for (c = itemname, parens = 0; get_must(0, token) && (parens || (*token != ',' && *token != '}'));) { if (*token == '(') parens++; else if (*token == ')') parens--; c = cat(cat(c, token), " "); } break; } else if (!strcmp(token, implicit_w)) { explicit1 &= ~1; if (*subclass && tag < ASN_APPL_SPEC && (ntbp = find_name(subclass)) && ntbp->name) { if (type < 0) type = ntbp->type; else if (ntbp->type != -1) type |= (ntbp->type & ASN_CONSTRUCTED); } } else if (!strcmp(token, in_w)) { if (!*definer) syntax(token); if (!get_token(0, inclass)) syntax(definer); } else if (!strcmp(token, of_w)) syntax(token); else if (!strcmp(token, optional_w)) { option |= ASN_OPTIONAL_FLAG; if (altscp) { altscp->options = option; option &= ~(ASN_OPTIONAL_FLAG); } } else if (!strcmp(token, size_w)) { get_size(token, &min, &max, parent); // if (type == ASN_UTCTIME || type == ASN_GENTIME) min = max = 0; } else if (!strcmp(token, table_w)) { if (!get_token(0, tablename)) syntax(table_w); if (*tablename < 'A' || *tablename > 'Z') syntax(tablename); option |= ASN_TABLE_FLAG; } else if (!strcmp(token, tags_w) || !strcmp(token, unique_w)); else if ((tmp = (int)find_type(token)) != ASN_NOTYPE) { if ((flags & ASN_TABLE_FLAG) && (*subclass || type >= 0)) altscp = append_subclasses(token); else if (*subclass) syntax(token); if (type < 0) type = (ulong) tmp; else if ((explicit1 & 1)) subtype = (short)tmp; else if (tmp > 0) type |= (tmp & ASN_CONSTRUCTED); get_expected(0, tmp, token); } else if ((*token >= '0' && *token <= '9') || (*itemname && (idp = find_id(token))) || is_ub(token)) { if (*token > '9') { if (idp) cat(token, idp->val); else { add_name(token, -1, 0); /* keep it off the 'Defined * but not used' list */ sprintf(token, "%ld", find_ub(token)); } } if ((flags & ASN_TABLE_FLAG)) { if (*token >= '0' && *token <= '9') cvt_number(numstring, token); } else if ((flags & ASN_ENUM_FLAG)) { if (!*itemname) cat(cat(itemname, "e"), token); else { if (*(c = token) == '_') c++; for (integer_val = 0; *c; integer_val = (integer_val * 10) + *c++ - '0'); if (*token == '_') integer_val = -integer_val; } } idp = (struct id_table *)0; } else if ((flags & ASN_TABLE_FLAG) && (!strcmp(token, false_w) || !strcmp(token, true_w) || !strcmp(token, either_w))) { type = ASN_BOOLEAN; cat(subclass, token); } else if ((*token >= 'A' && *token <= 'Z') || *token == '*') { if ((flags & ASN_TABLE_FLAG)) { if (!strcmp(token, "NONE")) cat(token, "AsnNone"); if (*subclass || type > 0) altscp = append_subclasses(token); else option |= set_name_option(subclass, token); } else if ((type > 0 && type < ASN_CHOICE) || *subclass) syntax(token); else option |= set_name_option(subclass, token); } else if (*token >= 'a' && *token <= 'z') { if ((flags & ASN_TABLE_FLAG)) array++; if (*itemname) warn(MSG_SYNTAX_ERR, token); else cat(itemname, token); } if (!get_token(0, token)) return -1; } if (*definer && !*inclass) cat(inclass, classname); if (*token == '}' && *peek_token(0) == '(') { get_known(0, &token[2], "("); get_def_paren(&token[2]); } return 0; }
/************************************************************************ ** can_expand: tries to expand the macro passed to it - returns ** true if it succeeded in expanding it. It will only return FALSE ** if a macro name was found, a paren was expected, and a paren was ** not the next non white character. ************************************************************************/ int can_expand(pdefn_t pdef) { UCHAR c; int n_formals; int return_value = FALSE; Tiny_lexer_nesting = 0; Save_Exp_ptr = Exp_ptr; /* not necessarily EXP_BUFFER */ Macro_line = Linenumber; expand_name: P_actuals = Act_ptr; N_actuals = 0; n_formals = DEFN_NFORMALS(pdef); if( PRE_DEFINED(pdef) ) { push_macro(pdef); DEFN_EXPANDING(CURRENT_MACRO)++; if(rescan_expansion()) { return(TRUE); /* could expand macro */ } } else if( n_formals == 0 ) { return_value = TRUE; if(DEFN_TEXT(pdef)) { push_macro(pdef); expand_definition(); } else { /* ** Macro expands to nothing (no definition). Since it ** didn't have any actuals, Act_ptr is already correct. ** Exp_ptr must be changed however to delete the ** identifier from the expanded text. */ Exp_ptr = Save_Exp_ptr; } } else { if( n_formals == -1 ) { n_formals = 0; } name_comment_paren: if( can_get_non_white()) { if(CHARMAP(CHECKCH()) == LX_SLASH) { SKIPCH(); if(skip_comment()) { goto name_comment_paren; } else { UNGETCH(); } } if(CHARMAP(CHECKCH())==LX_OPAREN) { SKIPCH(); return_value = TRUE; get_actuals(pdef, n_formals); } else { /* ** #define xx(a) a ** xx bar(); ** don't lose white space between "xx" and "bar" */ ptext_t p = Exp_ptr; push_macro(pdef); DEFN_EXPANDING(CURRENT_MACRO)++; Exp_ptr = p; if( rescan_expansion() ) { return(FALSE); } } } else { } } /* ** makes sure a macro is being worked on. At this point, there will ** be a macro to expand, unless the macro expand_the_named_macro was ** passed had no definition text. If it had no defintion text, ** Tiny_lexer_nesting was not incremented. */ while(Tiny_lexer_nesting != 0) { if(Exp_ptr >= ELIMIT) { fatal_in_macro(10056); } switch(CHARMAP(c = GETCH())) { case LX_ID: case LX_MACFORMAL: Save_Exp_ptr = Exp_ptr; if(tl_getid(c) && ((pdef = get_defined())!= 0)) { if(DEFN_EXPANDING(pdef)) { /* ** the macro is already being expanded, so just ** write the do not expand marker and the ** identifier to the expand area. The do not ** expand marker is necessary so this macro ** doesn't get expanded on the rescan */ int len = Reuse_1_length - 1; *Exp_ptr++ = LX_NOEXPANDMARK; *Exp_ptr++ = ((UCHAR)len); } else { /* ** a legal identifier was read, it is defined, and ** it is not currently being expanded. This means ** there is reason to believe it can be expanded. */ goto expand_name; } } if(InIf &&(memcmp(Reuse_1, "defined", 8) ==0)) { do_defined(Reuse_1); } continue; break; case LX_NUMBER: /* getnum with Prep on to keep leading 0x on number */ { int Save_prep = Prep; Prep = TRUE; getnum(c); Prep = Save_prep; } continue; break; case LX_DOT: *Exp_ptr++ = '.'; dot_switch: switch(CHARMAP(c = GETCH())) { case LX_EOS: if(handle_eos() != BACKSLASH_EOS) { if(Tiny_lexer_nesting > 0) { goto dot_switch; } continue; } break; case LX_DOT: *Exp_ptr++ = '.'; if( ! checkop('.')) { break; /* error will be caught on rescan */ } *Exp_ptr++ = '.'; continue; break; case LX_NUMBER: *Exp_ptr++ = c; get_real(Exp_ptr); continue; } UNGETCH(); continue; case LX_CHARFORMAL: move_to_exp_esc('\'', do_strformal()); continue; break; case LX_STRFORMAL: move_to_exp_esc('"', do_strformal()); continue; break; case LX_DQUOTE: case LX_SQUOTE: /* ** gather_chars is called even though the error reported ** on overflow may need to be changed. */ Exp_ptr = gather_chars(Exp_ptr, c); continue; break; case LX_WHITE: while(LXC_IS_WHITE(GETCH())) { ; } UNGETCH(); c = ' '; break; case LX_EOS: if(handle_eos() == BACKSLASH_EOS) { *Exp_ptr++ = c; c = GETCH(); break; } continue; break; } *Exp_ptr++ = c; } return(return_value); }