int read_global( ) { /** Function: Reads file in global state Inputs: File descriptor Returns: IF reaches end of file, -1 ELSE 0 Procedure: 1. DO IF token is '::=' Return IN_DEFINITION ELSE IF token is DEFINITIONS WHILE next token is not '::=' IF token is IMPLICIT, clear implicit flag for file ELSE IF token is EXPLICIT, set explicit flag for file ELSE IF token is not TAGS, error ELSE IF token is EXPORTS OR IMPORTS, throw away everything up to ';' ELSE IF haven't a classname, copy token into classname 2. WHILE have another token Return -1 **/ do { if (*token == ':') { get_known(0, &token[1], colon_ch); get_known(0, &token[2], equal_ch); token[3] = 0; max = min = 0; state = IN_DEFINITION; return 0; } else if (!strcmp(token, definitions_w)) { while (get_token(0, token) && *token != ':') { if (!strcmp(token, implicit_w)) explicit1 = 0; else if (!strcmp(token, explicit_w)) explicit1 = 3; else if (strcmp(token, tags_w)) syntax(token); } get_known(0, &token[1], ":"); get_known(0, &token[2], "="); token[3] = 0; } else if (!strcmp(token, exports_w) || !strcmp(token, imports_w)) while (*token != ';') get_must(0, token); else if (!*classname && *token >= 'A') strcpy(classname, token); } while (get_token(0, token)); return -1; }
void initialize_in_object(O& object, Context* context) const override { PluralAssociationBase<O, HasMany<A>>::initialize_in_object(object, context); // This is sinful (and undefined behaviour, and probably slow: // The aim is to be able to go from pointer to HasMany<A> to pointer to O. size_t offset = member_offset(object); this->get(object)->get_id_of_owner_ = [=](const HasMany<A>& anchor) -> PrimaryKey { const O* obj = reinterpret_cast<const O*>(reinterpret_cast<const char*>(&anchor) - offset); auto t = get_type<O>()->primary_key(); auto p = dynamic_cast<const PropertyOfBase<O, PrimaryKey>*>(t); if (p == nullptr) { throw AssociationError{"Owner of HasMany association has a primary key that isn't a PrimaryKey property."}; } return p->get_known(*obj); }; }
static long get_tag( char *token) { /** Procedure: 1. IF no next token, exit with fatal message IF token is APPLICATION OR PRIVATE OR UNIVERSAL Set tag to application specific IF no next token, exit with fatal message ELSE set tag to content specific IF token is an upper bound, get its value IF token is an ID, translate it ELSE IF token is an ID, copy that into token Get number in token 2. Convert number to true tag Return tag **/ long ttag, tmp; char *c; struct id_table *idp; struct ub_table *ubp; get_must(0, token); /* step 1 */ if (!strcmp(token, application_w) || !strcmp(token, private_w) || !strcmp(token, universal_w)) { if (*token == 'A') ttag = ASN_APPL_SPEC; else if (*token == 'P') ttag = ASN_PRIV_SPEC; else ttag = 0; get_must(0, token); } else ttag = ASN_CONT_SPEC; if (token[0] == '0' && (token[1] | 0x20) == 'x') { /* special stuff for inexpressible tags */ for (c = &token[2], tmp = 0; *c >= '0' && *c <= 'f'; c++) { tmp <<= 4; if (*c > 'F') *c -= 0x20; if (*c > '9') *c -= 7; tmp |= (*c - '0'); } } else { if ((ubp = is_ub(token))) { sprintf(token, "%ld", ubp->val); for (c = token; *c >= '0' && *c <= '9'; c++); *c = 0; } else if ((idp = find_id(token))) strcpy(token, idp->val); for (c = token, tmp = 0; *c >= '0' && *c <= '9'; tmp = (tmp * 10) + *c++ - '0'); } if (*c++) syntax(token); get_known(0, c, "]"); if (token[1] > '9') { /* more for inexpressible tags */ ttag |= tmp >> 8; ttag |= (tmp & 0xFF) << 8; }
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; }