/******************************************************************** * FUNCTION parse_val * * Parse, and fill one val_value_t struct during * processing of a text config file * * Error messages are printed by this function!! * Do not duplicate error messages upon error return * * The value name is the current token. * Based on the value typdef, the res of the tokens * comprising the value statement will be processed * * INPUTS: * tkc == token chain * obj == the object template struct to use for filling in 'val' * val == initialized value struct, without any value, * which will be filled in by this function * nsid == namespace ID to use for this value * valname == name of the value struct * * RETURNS: * status of the operation *********************************************************************/ static status_t parse_val (tk_chain_t *tkc, obj_template_t *obj, val_value_t *val) { obj_template_t *chobj; val_value_t *chval; const xmlChar *valname, *useval; typ_def_t *typdef; status_t res; ncx_btype_t btyp; boolean done; xmlns_id_t nsid; btyp = obj_get_basetype(obj); nsid = obj_get_nsid(obj); valname = obj_get_name(obj); typdef = obj_get_typdef(obj); /* check if there is an index clause expected */ if (typ_has_index(btyp)) { res = parse_index(tkc, obj, val, nsid); if (res != NO_ERR) { return res; } } /* get next token, NEWLINE is significant at this point */ res = adv_tk(tkc); if (res != NO_ERR) { return res; } /* the current token should be the value for a leaf * or a left brace for the start of a complex type * A NEWLINE is treated as if the user entered a * zero-length string for the value. (Unless the * base type is NCX_BT_EMPTY, in which case the NEWLINE * is the expected token */ if (typ_is_simple(btyp)) { /* form for a leaf is: foo [value] NEWLINE */ if (TK_CUR_TYP(tkc)==TK_TT_NEWLINE) { useval = NULL; } else { useval = TK_CUR_VAL(tkc); } res = val_set_simval(val, typdef, nsid, valname, useval); if (res != NO_ERR) { log_error("\nError: '%s' cannot be set to '%s'", valname, (TK_CUR_VAL(tkc)) ? TK_CUR_VAL(tkc) : EMPTY_STRING); if (btyp == NCX_BT_EMPTY) { ncx_conf_exp_err(tkc, res, "empty"); } else { ncx_conf_exp_err(tkc, res, "simple value string"); } return res; } /* get a NEWLINE unless current token is already a NEWLINE */ if (TK_CUR_TYP(tkc) != TK_TT_NEWLINE) { res = adv_tk(tkc); if (res != NO_ERR) { return res; } if (TK_CUR_TYP(tkc) != TK_TT_NEWLINE) { res = ERR_NCX_WRONG_TKTYPE; ncx_conf_exp_err(tkc, res, "\\n"); } } } else { /* complex type is foo { ... } or * foo index1 index2 { ... } * If there is an index, it was already parsed */ res = consume_tk(tkc, TK_TT_LBRACE); if (res != NO_ERR) { ncx_conf_exp_err(tkc, res, "left brace"); return res; } /* get all the child nodes specified for this complex type */ res = NO_ERR; done = FALSE; while (!done && res==NO_ERR) { /* start out looking for a child node name or a * right brace to end the sub-section */ if (tk_next_typ(tkc)==TK_TT_NEWLINE) { /* skip the NEWLINE token */ (void)adv_tk(tkc); } else if (tk_next_typ(tkc)==TK_TT_RBRACE) { /* found end of sub-section */ done = TRUE; } else { /* get the next token */ res = adv_tk(tkc); if (res != NO_ERR) { continue; } /* make sure cur token is an identifier string * if so, find the child node and call this function * recursively to fill it in and add it to * the parent 'val' */ if (TK_CUR_ID(tkc)) { /* parent 'typdef' must have a child with a name * that matches the current token vale */ chobj = obj_find_child(obj, TK_CUR_MOD(tkc), TK_CUR_VAL(tkc)); if (chobj) { chval = val_new_value(); if (!chval) { res = ERR_INTERNAL_MEM; ncx_print_errormsg(tkc, NULL, res); } else { val_init_from_template(chval, chobj); res = parse_val(tkc, chobj, chval); if (res == NO_ERR) { val_add_child(chval, val); } else { val_free_value(chval); } } } else { /* string is not a child name in this typdef */ res = ERR_NCX_DEF_NOT_FOUND; ncx_conf_exp_err(tkc, res, "identifier string"); } } else { /* token is not an identifier string */ res = ERR_NCX_WRONG_TKTYPE; ncx_conf_exp_err(tkc, res, "identifier string"); } } } /* end loop through all the child nodes */ /* expecting a right brace to finish the complex value */ if (res == NO_ERR) { res = consume_tk(tkc, TK_TT_RBRACE); if (res != NO_ERR) { ncx_conf_exp_err(tkc, res, "right brace"); return res; } } } return res; } /* parse_val */
/******************************************************************** * FUNCTION dump_typdef_data * * Dump some contents from a typ_def_t struct for help text * * INPUTS: * obj == obj_template_t to dump help for * mode == requested help mode * indent == start indent count *********************************************************************/ static void dump_typdef_data (obj_template_t *obj, help_mode_t mode, uint32 indent) { if (mode == HELP_MODE_BRIEF) { return; } typ_def_t *typdef = obj_get_typdef(obj); if (!typdef) { return; } typ_def_t *basetypdef = typ_get_base_typdef(typdef); ncx_btype_t btyp = typ_get_basetype(typdef); const xmlChar *datastr = typ_get_rangestr(typdef); if (datastr) { if (typ_is_string(btyp)) { help_write_lines((const xmlChar *)"length: ", indent, TRUE); } else { help_write_lines((const xmlChar *)"range: ", indent, TRUE); } help_write_lines(datastr, 0, FALSE); } typ_def_t *testdef = typdef; while (testdef) { typ_pattern_t *pattern; for (pattern = typ_get_first_pattern(testdef); pattern != NULL; pattern = typ_get_next_pattern(pattern)) { help_write_lines((const xmlChar *)"pattern: ", indent, TRUE); help_write_lines(pattern->pat_str, 0, FALSE); } testdef = typ_get_parent_typdef(testdef); } typ_enum_t *tenum = NULL; switch (btyp) { case NCX_BT_ENUM: case NCX_BT_BITS: if (btyp == NCX_BT_ENUM) { help_write_lines((const xmlChar *)"enum values:", indent, TRUE); } else { help_write_lines((const xmlChar *)"bit values:", indent, TRUE); } for (tenum = typ_first_enumdef(basetypdef); tenum != NULL; tenum = typ_next_enumdef(tenum)) { if (mode == HELP_MODE_NORMAL) { help_write_lines((const xmlChar *)" ", 0, FALSE); help_write_lines(tenum->name, 0, FALSE); } else { help_write_lines(tenum->name, indent+NCX_DEF_INDENT, TRUE); /* !!! removed since not allowed in syntax; * !!! position or value is meta-data usually set-by-default * help_write_lines((const xmlChar *)" (", 0, FALSE); help_write_lines(numlabel, 0, FALSE); help_write_lines((const xmlChar *)": ", 0, FALSE); xmlChar numbuff[NCX_MAX_NUMLEN]; if (btyp == NCX_BT_ENUM) { snprintf((char *)numbuff, sizeof(numbuff), "%d", tenum->val); } else { snprintf((char *)numbuff, sizeof(numbuff), "%u", tenum->pos); } help_write_lines(numbuff, 0, FALSE); help_write_lines((const xmlChar *)")", 0, FALSE); */ if (tenum->descr) { help_write_lines(tenum->descr, indent+(2*NCX_DEF_INDENT), TRUE); } if (tenum->ref) { help_write_lines(tenum->ref, indent+(2*NCX_DEF_INDENT), TRUE); } } } break; case NCX_BT_LEAFREF: datastr = typ_get_leafref_path(basetypdef); if (datastr) { help_write_lines((const xmlChar *)"leafref path:", indent, TRUE); help_write_lines(datastr, indent+NCX_DEF_INDENT, TRUE); } break; default: ; } } /* dump_typdef_data */