Ejemplo n.º 1
0
/********************************************************************
* FUNCTION write_cur_token
* 
* Write the full value of the current token to the session
*
* INPUTS:
*    scb == session control block
*    pcb == YANG parser control block
*    elem == TRUE if this is element content; FALSE if attribute
*********************************************************************/
static void
    write_cur_token (ses_cb_t *scb,
                     yang_pcb_t *pcb,
                     boolean elem)
{
    const xmlChar   *prefix, *value;

    prefix = TK_CUR_MOD(pcb->tkc);
    if (prefix != NULL) {
        if (elem) {
            ses_putcstr(scb, prefix, -1);
        } else {
            ses_putastr(scb, prefix, -1);
        }
        ses_putchar(scb, ':');
    }

    value = TK_CUR_VAL(pcb->tkc);
    if (value != NULL) {
        if (elem) {
            ses_putcstr(scb, value, -1);
        } else {
            ses_putastr(scb, value, -1);
        }
    }

}  /* write_cur_token */
Ejemplo n.º 2
0
/********************************************************************
* FUNCTION parse_index
* 
* Parse, and fill the indexQ for 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 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
*
* OUTPUTS:
*   indexQ filled in as tokens representing the index components
*   are parsed.  NEWLINE tokens are skipped as needed
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    parse_index (tk_chain_t  *tkc,
                 obj_template_t *obj,
                 val_value_t *val,
                 xmlns_id_t  nsid)
{
    obj_key_t     *indef, *infirst;
    val_value_t   *inval;
    status_t       res;

    infirst = obj_first_key(obj);

    /* first make value nodes for all the index values */
    for (indef = infirst; 
         indef != NULL; 
         indef = obj_next_key(indef)) {

        /* advance to the next non-NEWLINE token */
        res = get_tk(tkc);
        if (res != NO_ERR) {
            ncx_conf_exp_err(tkc, res, "index value");
            return res;
        }

        /* check if a valid token is given for the index value */
        if (TK_CUR_TEXT(tkc)) {
            inval = val_make_simval_obj(indef->keyobj,
                                        TK_CUR_VAL(tkc), 
                                        &res);
            if (!inval) {
                ncx_conf_exp_err(tkc, res, "index value");
                return res;
            } else {
                val_change_nsid(inval, nsid);
                val_add_child(inval, val);
            }
        } else {
            res = ERR_NCX_WRONG_TKTYPE;
            ncx_conf_exp_err(tkc, res, "index value");
            return res;
        }
    }

    /* generate the index chain in the indexQ */
    res = val_gen_index_chain(obj, val);
    if (res != NO_ERR) {
        ncx_print_errormsg(tkc, NULL, res);
    }

    return res;
        
} /* parse_index */
Ejemplo n.º 3
0
/********************************************************************
* FUNCTION match_name
* 
* Get the next token which must be a string which matches name
*
* INPUTS:
*   tkc == token chain
*   name  == name to match
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    match_name (tk_chain_t  *tkc,
                const xmlChar *name)
{
    status_t res;

    /* get the next token */
    res = consume_tk(tkc, TK_TT_TSTRING);
    if (res == NO_ERR) {
        if (xml_strcmp(TK_CUR_VAL(tkc), name)) {
            res = ERR_NCX_WRONG_VAL;
        }
    }
    return res;

} /* match_name */
Ejemplo n.º 4
0
/********************************************************************
* FUNCTION write_yin_stmt
*  
* Go through the token chain and write YIN stmts
* recursively if needed, until 1 YANG stmt is handled
*
* INPUTS:
*   pcb == parser control block of module to convert
*          This is returned from ncxmod_load_module_ex
*   cp == conversion parms to use
*   scb == session control block for writing output
*   startindent == start indent count
*   done == address of done return var to use
*
* RETURNS:
*   status
*********************************************************************/
static status_t
    write_yin_stmt (yang_pcb_t *pcb,
                    const yangdump_cvtparms_t *cp,
                    ses_cb_t *scb,
                    int32 startindent,
                    boolean *done)
{
    const yin_mapping_t  *mapping;
    ncx_import_t         *import;
    ext_template_t       *extension;
    const xmlChar        *prefix, *modprefix;
    status_t              res;
    boolean               loopdone;

    res = NO_ERR;
    *done = FALSE;

    /* expecting a keyword [string] stmt-end sequence
     * or the very last closing right brace
     */
    if (TK_CUR_TYP(pcb->tkc) == TK_TT_RBRACE) {
        if (tk_next_typ(pcb->tkc) == TK_TT_NONE) {
            *done = TRUE;
            return NO_ERR;
        } else {
            return ERR_NCX_WRONG_TKTYPE;
        }
    } else if (!TK_CUR_ID(pcb->tkc)) {
        return ERR_NCX_WRONG_TKTYPE;
    }

    /* check the keyword type */
    switch (TK_CUR_TYP(pcb->tkc)) {
    case TK_TT_TSTRING:
        /* YANG keyword */
        mapping = yin_find_mapping(TK_CUR_VAL(pcb->tkc));
        if (mapping == NULL) {
            return ERR_NCX_DEF_NOT_FOUND;
        }

        /* output keyword part */
        start_yin_elem(scb, mapping->keyword, startindent);

        /* output [string] part if expected */
        if (mapping->argname == NULL) {
            if (tk_next_typ(pcb->tkc) == TK_TT_LBRACE) {
                ses_putchar(scb, '>');
            }
        } else {
            /* move token pointer to the argument string */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }

            /* write the string part 
             * do not add any extra whiespace to the XML string
             */
            if (mapping->elem) {
                ses_putchar(scb, '>');

                /* encode argname,value as an element */
                start_yin_elem(scb, 
                               mapping->argname,
                               startindent + cp->indent);
                ses_putchar(scb, '>');
                write_cur_token(scb, pcb, TRUE);
                end_yin_elem(scb, mapping->argname, -1);
            } else {
                /* encode argname,value as an attribute */
                ses_putchar(scb, ' ');
                ses_putstr(scb, mapping->argname);
                ses_putchar(scb, '=');
                ses_putchar(scb, '"');
                write_cur_token(scb, pcb, FALSE);
                ses_putchar(scb, '"');
                if (tk_next_typ(pcb->tkc) != TK_TT_SEMICOL) {
                    ses_putchar(scb, '>');
                } /* else end with empty element */
            }
        }

        /* move token pointer to the stmt-end char */
        res = advance_token(pcb);
        if (res != NO_ERR) {
            return res;
        }

        switch (TK_CUR_TYP(pcb->tkc)) {
        case TK_TT_SEMICOL:
            /* advance to next stmt, this one is done */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }
            if (mapping->elem) {
                /* end the complex element */
                end_yin_elem(scb, mapping->keyword, startindent);
            } else {
                /* end the empty element */
                ses_putstr(scb, (const xmlChar *)" />");
            }
            break;
        case TK_TT_LBRACE:
            /* advance to next sub-stmt, this one has child nodes */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }

            /* write the nested sub-stmts as child nodes */
            if (TK_CUR_TYP(pcb->tkc) != TK_TT_RBRACE) {
                loopdone = FALSE;
                while (!loopdone) {
                    res = write_yin_stmt(pcb,
                                         cp,
                                         scb,
                                         startindent + cp->indent,
                                         done);
                    if (res != NO_ERR) {
                        return res;
                    }
                    if (TK_CUR_TYP(pcb->tkc) == TK_TT_RBRACE) {
                        loopdone = TRUE;
                    }
                }
            }

            /* move to next stmt, this one is done */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }

            /* end the complex element */
            end_yin_elem(scb, mapping->keyword, startindent);
            break;
        default:
            return SET_ERROR(ERR_INTERNAL_VAL);
        }
        break;
    case TK_TT_MSTRING:
        /* extension keyword */
        prefix = TK_CUR_MOD(pcb->tkc);
        modprefix = ncx_get_mod_prefix(pcb->top);
        if (modprefix != NULL && !xml_strcmp(prefix, modprefix)) {
            /* local module */
            extension = ext_find_extension(pcb->top, 
                                           TK_CUR_VAL(pcb->tkc));
        } else {
            import = ncx_find_pre_import(pcb->top, prefix);
            if (import == NULL || import->mod == NULL) {
                return ERR_NCX_IMP_NOT_FOUND;
            }
            extension = ext_find_extension(import->mod, 
                                           TK_CUR_VAL(pcb->tkc));
        }
        if (extension == NULL) {
            return ERR_NCX_DEF_NOT_FOUND;
        }

        /* got the extension for this external keyword
         * output keyword part 
         */
        start_ext_elem(scb, 
                       prefix,
                       TK_CUR_VAL(pcb->tkc), 
                       startindent);

        /* output [string] part if expected */
        if (extension->arg == NULL) {
            if (tk_next_typ(pcb->tkc) == TK_TT_LBRACE) {
                ses_putchar(scb, '>');
            }
        } else {
            /* move token pointer to the argument string */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }

            /* write the string part
             * do not add any extra whiespace chars to the string
             */
            if (extension->argel) {
                ses_putchar(scb, '>');

                /* encode argname,value as an element */
                start_ext_elem(scb, 
                               prefix,
                               extension->arg,
                               startindent + cp->indent);
                ses_putchar(scb, '>');
                write_cur_token(scb, pcb, TRUE);
                end_ext_elem(scb, prefix, extension->arg, -1);
            } else {
                /* encode argname,value as an attribute */
                ses_putchar(scb, ' ');
                ses_putstr(scb, extension->arg);
                ses_putchar(scb, '=');
                ses_putchar(scb, '"');
                write_cur_token(scb, pcb, FALSE);
                ses_putchar(scb, '"');
                if (tk_next_typ(pcb->tkc) != TK_TT_SEMICOL) {
                    ses_putchar(scb, '>');
                } /* else end with empty element */
            }
        }

        /* move token pointer to the stmt-end char */
        res = advance_token(pcb);
        if (res != NO_ERR) {
            return res;
        }

        switch (TK_CUR_TYP(pcb->tkc)) {
        case TK_TT_SEMICOL:
            /* advance to next stmt, this one is done */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }
            if (extension->arg != NULL && extension->argel) {
                /* end the complex element */
                end_ext_elem(scb, 
                             prefix,
                             extension->name, 
                             startindent);
            } else {
                /* end the empty element */
                ses_putstr(scb, (const xmlChar *)" />");
            }
            break;
        case TK_TT_LBRACE:
            /* advance to next sub-stmt, this one has child nodes */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }

            /* write the nested sub-stmts as child nodes */
            if (TK_CUR_TYP(pcb->tkc) != TK_TT_RBRACE) {
                loopdone = FALSE;
                while (!loopdone) {
                    res = write_yin_stmt(pcb,
                                         cp,
                                         scb,
                                         startindent + cp->indent,
                                         done);
                    if (res != NO_ERR) {
                        return res;
                    }
                    if (TK_CUR_TYP(pcb->tkc) == TK_TT_RBRACE) {
                        loopdone = TRUE;
                    }
                }
            }

            /* move to next stmt, this one is done */
            res = advance_token(pcb);
            if (res != NO_ERR) {
                return res;
            }

            /* end the complex element */
            end_ext_elem(scb, 
                         prefix,
                         extension->name,
                         startindent);
            break;
        default:
            return SET_ERROR(ERR_INTERNAL_VAL);
        }
        break;
    default:
        return SET_ERROR(ERR_INTERNAL_VAL);
    }
    

    return res;

}   /* write_yin_stmt */
Ejemplo n.º 5
0
/********************************************************************
* FUNCTION parse_parm
* 
* Parse, and fill one val_value_t struct during
* processing of a parmset
*
* Error messages are printed by this function!!
* Do not duplicate error messages upon error return
*
*
* INPUTS:
*   tkc == token chain
*   val == container val to fill in
*   keepvals == TRUE to save existing parms in 'ps', as needed
*               FALSE to overwrite old parms in 'ps', as needed
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    parse_parm (tk_chain_t  *tkc,
                val_value_t *val,
                boolean keepvals)
{
    obj_template_t         *obj;
    const xmlChar          *modname;
    val_value_t            *curparm, *newparm;
    status_t                res;
    ncx_iqual_t             iqual;
    boolean                 match, usewarning, isdefault;

    
    /* get the next token, which must be a TSTRING
     * representing the parameter name 
     */
    if (TK_CUR_TYP(tkc) != TK_TT_TSTRING) {
        res = ERR_NCX_WRONG_TKTYPE;
        ncx_conf_exp_err(tkc, res, "parameter name");
        return res;
    }

    curparm = NULL;
    usewarning = ncx_warning_enabled(ERR_NCX_CONF_PARM_EXISTS);

    /* check if this TSTRING is a parameter in this parmset
     * make sure to always check for prefix:identifier
     * This is automatically processed in tk.c
     */
    if (TK_CUR_MOD(tkc)) {
        modname = xmlns_get_module
            (xmlns_find_ns_by_prefix(TK_CUR_MOD(tkc)));
        if (modname) {
            curparm = val_find_child(val, 
                                     modname,
                                     TK_CUR_VAL(tkc));
        }
    }  else {
        curparm = val_find_child(val, 
                                 val_get_mod_name(val),
                                 TK_CUR_VAL(tkc));
    }
        
    if (curparm) {
        obj = curparm->obj;
    } else {
        obj = obj_find_child(val->obj, 
                             TK_CUR_MOD(tkc),
                             TK_CUR_VAL(tkc));
    }
    if (!obj) {
        res = ERR_NCX_UNKNOWN_PARM;
        if (TK_CUR_MOD(tkc)) {
            log_error("\nError: parameter '%s:%s' not found",
                      TK_CUR_MOD(tkc),
                      TK_CUR_VAL(tkc));
        } else {
            log_error("\nError: parameter '%s' not found",
                      TK_CUR_VAL(tkc));
        }
        ncx_conf_exp_err(tkc, res, "parameter name");
        return res;
    }

    /* got a valid parameter name, now create a new parm
     * even if it may not be kept.  There are corner-cases
     * that require the new value be parsed before knowing
     * if a parm value is a duplicate or not
     */
    newparm = val_new_value();
    if (!newparm) {
        res = ERR_INTERNAL_MEM;
        ncx_print_errormsg(tkc, NULL, res);
        return res;
    }
    val_init_from_template(newparm, obj);

    /* parse the parameter value */
    res = parse_val(tkc, obj, newparm);
    if (res != NO_ERR) {
        val_free_value(newparm);
        return res;
    }

    /* check if a potential current value exists, or just
     * add the newparm to the parmset
     */
    if (curparm) {
        isdefault = val_set_by_default(curparm);
        iqual = obj_get_iqualval(obj);
        if (iqual == NCX_IQUAL_ONE || iqual == NCX_IQUAL_OPT) {
            /* only one allowed, check really a match */
            match = TRUE;
            if (val_has_index(curparm) &&
                !val_index_match(newparm, curparm)) {
                match = FALSE;
            }

            if (!match) {
                val_add_child(newparm, val);
            } else if (isdefault) {
                dlq_remove(curparm);
                val_free_value(curparm);
                val_add_child(newparm, val);
            } else if (keepvals) {
                if (usewarning) {
                    /* keep current value and toss new value */
                    log_warn("\nWarning: Parameter '%s' already exists. "
                             "Not using new value\n", 
                             curparm->name);
                    if (LOGDEBUG2) {
                        val_dump_value(newparm, NCX_DEF_INDENT);
                        log_debug2("\n");
                    }
                }
                val_free_value(newparm);
            } else {
                if (usewarning) {
                    /* replace current value and warn old value tossed */
                    log_warn("\nconf: Parameter '%s' already exists. "
                             "Overwriting with new value\n",
                             curparm->name);
                    if (LOGDEBUG2) {
                        val_dump_value(newparm, NCX_DEF_INDENT);
                        log_debug2("\n");
                    }
                }
                dlq_remove(curparm);
                val_free_value(curparm);
                val_add_child(newparm, val);
            }
        } else {
            /* mutliple instances allowed */
            val_add_child(newparm, val);
        }
    } else {
        val_add_child(newparm, val);
    }

    return NO_ERR;

}  /* parse_parm */
Ejemplo n.º 6
0
/********************************************************************
* 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 */
Ejemplo n.º 7
0
/********************************************************************
* FUNCTION yang_ext_consume_extension
* 
* Parse the next N tokens as an extension-stmt
* Create an ext_template_t struct and add it to the specified Q
*
* Error messages are printed by this function!!
* Do not duplicate error messages upon error return
*
* Current token is the 'extension' keyword
*
* INPUTS:
*   tkc == token chain
*   mod == module in progress
*
* RETURNS:
*   status of the operation
*********************************************************************/
status_t 
    yang_ext_consume_extension (tk_chain_t *tkc,
                                ncx_module_t  *mod)
{
    ext_template_t  *ext, *testext;
    const xmlChar   *val;
    const char      *expstr;
    yang_stmt_t     *stmt;
    tk_type_t        tktyp;
    boolean          done, arg, stat, desc, ref;
    status_t         res, retres;

#ifdef DEBUG
    if (!tkc || !mod) {
        return SET_ERROR(ERR_INTERNAL_PTR);
    }
#endif

    val = NULL;
    expstr = "keyword";
    done = FALSE;
    arg = FALSE;
    stat = FALSE;
    desc = FALSE;
    ref = FALSE;
    res = NO_ERR;
    retres = NO_ERR;

    /* Get a new ext_template_t to fill in */
    ext = ext_new_template();
    if (!ext) {
        res = ERR_INTERNAL_MEM;
        ncx_print_errormsg(tkc, mod, res);
        return res;
    }

    ncx_set_error(&ext->tkerr,
                  mod,
                  TK_CUR_LNUM(tkc),
                  TK_CUR_LPOS(tkc));

    /* Get the mandatory extension name */
    res = yang_consume_id_string(tkc, mod, &ext->name);
    CHK_EXT_EXIT;

    /* Get the starting left brace for the sub-clauses
     * or a semi-colon to end the extension-stmt
     */
    res = TK_ADV(tkc);
    if (res != NO_ERR) {
        ncx_print_errormsg(tkc, mod, res);
        ext_free_template(ext);
        return res;
    }
    switch (TK_CUR_TYP(tkc)) {
    case TK_TT_SEMICOL:
        done = TRUE;
        break;
    case TK_TT_LBRACE:
        break;
    default:
        retres = ERR_NCX_WRONG_TKTYPE;
        expstr = "semi-colon or left brace";
        ncx_mod_exp_err(tkc, mod, retres, expstr);
        done = TRUE;
    }

    /* get the extension statements and any appinfo extensions */
    while (!done) {
        /* get the next token */
        res = TK_ADV(tkc);
        if (res != NO_ERR) {
            ncx_print_errormsg(tkc, mod, res);
            ext_free_template(ext);
            return res;
        }

        tktyp = TK_CUR_TYP(tkc);
        val = TK_CUR_VAL(tkc);

        /* check the current token type */
        switch (tktyp) {
        case TK_TT_NONE:
            res = ERR_NCX_EOF;
            ncx_print_errormsg(tkc, mod, res);
            ext_free_template(ext);
            return res;
        case TK_TT_MSTRING:
            /* vendor-specific clause found instead */
            res = ncx_consume_appinfo(tkc, mod, &ext->appinfoQ);
            CHK_EXT_EXIT;
            continue;
        case TK_TT_RBRACE:
            done = TRUE;
            continue;
        case TK_TT_TSTRING:
            break;  /* YANG clause assumed */
        default:
            retres = ERR_NCX_WRONG_TKTYPE;
            ncx_mod_exp_err(tkc, mod, retres, expstr);
            continue;
        }

        /* Got a token string so check the value */
        if (!xml_strcmp(val, YANG_K_ARGUMENT)) {
            res = consume_yang_arg(tkc, mod, ext, &arg);
        } else if (!xml_strcmp(val, YANG_K_STATUS)) {
            res = yang_consume_status(tkc, 
                                      mod, 
                                      &ext->status,
                                      &stat, 
                                      &ext->appinfoQ);
        } else if (!xml_strcmp(val, YANG_K_DESCRIPTION)) {
            res = yang_consume_descr(tkc, 
                                     mod, 
                                     &ext->descr,
                                     &desc, 
                                     &ext->appinfoQ);
        } else if (!xml_strcmp(val, YANG_K_REFERENCE)) {
            res = yang_consume_descr(tkc, 
                                     mod, 
                                     &ext->ref,
                                     &ref, 
                                     &ext->appinfoQ);
        } else {
            res = ERR_NCX_WRONG_TKVAL;
            ncx_mod_exp_err(tkc, mod, res, expstr);
        }
        CHK_EXT_EXIT;
    }

    /* save or delete the ext_template_t struct */
    if (ext->name && ncx_valid_name2(ext->name)) {
        testext = ext_find_extension_all(mod, ext->name);
        if (testext) {
            log_error("\nError: extension '%s' already defined "
                      "in '%s' at line %u",
                      ext->name, 
                      testext->tkerr.mod->name,
                      testext->tkerr.linenum);
            retres = ERR_NCX_DUP_ENTRY;
            ncx_print_errormsg(tkc, mod, retres);
            ext_free_template(ext);
        } else {
            dlq_enque(ext, &mod->extensionQ);  /* may have some errors */
            if (mod->stmtmode) {
                stmt = yang_new_ext_stmt(ext);
                if (stmt) {
                    dlq_enque(stmt, &mod->stmtQ);
                } else {
                    log_error("\nError: malloc failure for ext_stmt");
                    retres = ERR_INTERNAL_MEM;
                    ncx_print_errormsg(tkc, mod, retres);
                }
            }
        }
    } else {
        ext_free_template(ext);
    }

    return retres;

}  /* yang_ext_consume_extension */
Ejemplo n.º 8
0
/********************************************************************
* FUNCTION consume_yang_arg
* 
* Parse the next N tokens as an argument-stmt
* Fill in the arg anf argel fields in the ext_template_t struct
*
* Error messages are printed by this function!!
* Do not duplicate error messages upon error return
*
* Current token is the 'argument' keyword
*
* INPUTS:
*   tkc == token chain
*   mod == module in progress
*   ext == extension template in progress
*   argdone == address of duplicate entry error flag
*
* OUTPUTS:
*   *argdone == TRUE upon exit
*
* RETURNS:
*   status of the operation
*********************************************************************/
static status_t 
    consume_yang_arg (tk_chain_t *tkc,
                      ncx_module_t  *mod,
                      ext_template_t *ext,
                      boolean *argdone)
{
    const xmlChar   *val;
    const char      *expstr;
    xmlChar         *errstr;
    dlq_hdr_t        errQ;
    tk_type_t        tktyp;
    boolean          done, yinel, save, errsave;
    status_t         res, retres;

#ifdef DEBUG
    if (!tkc || !mod) {
        return SET_ERROR(ERR_INTERNAL_PTR);
    }
#endif

    val = NULL;
    expstr = NULL;
    done = FALSE;
    yinel = FALSE;
    save = TRUE;
    res = NO_ERR;
    retres = NO_ERR;
    dlq_createSQue(&errQ);

    /* check duplicate entry error first */
    if (*argdone) {
        retres = ERR_NCX_ENTRY_EXISTS;
        ncx_print_errormsg(tkc, mod, retres);
        save = FALSE;
    } else {
        *argdone = TRUE;
    }

    /* Get the mandatory argument name */
    if (save) {
        res = yang_consume_id_string(tkc, mod, &ext->arg);
    } else {
        errstr = NULL;
        res = yang_consume_id_string(tkc, mod, &errstr);
        if (errstr) {
            m__free(errstr);
        }
    }
    CHK_EXIT(res, retres);

    /* Get the starting left brace for the sub-clauses
     * or a semi-colon to end the extension-stmt
     */
    res = TK_ADV(tkc);
    if (res != NO_ERR) {
        ncx_print_errormsg(tkc, mod, res);
        return res;
    }
    switch (TK_CUR_TYP(tkc)) {
    case TK_TT_SEMICOL:
        done = TRUE;
        break;
    case TK_TT_LBRACE:
        break;
    default:
        retres = ERR_NCX_WRONG_TKTYPE;
        expstr = "semi-colon or left brace";
        ncx_mod_exp_err(tkc, mod, retres, expstr);
        done = TRUE;
    }

    /* get the extension statements and any appinfo extensions */
    while (!done) {
        /* get the next token */
        res = TK_ADV(tkc);
        if (res != NO_ERR) {
            ncx_print_errormsg(tkc, mod, res);
            return res;
        }

        tktyp = TK_CUR_TYP(tkc);
        val = TK_CUR_VAL(tkc);

        /* check the current token type */
        switch (tktyp) {
        case TK_TT_NONE:
            res = ERR_NCX_EOF;
            ncx_print_errormsg(tkc, mod, res);
            return res;
        case TK_TT_MSTRING:
            /* vendor-specific clause found instead */
            if (save) {
                res = ncx_consume_appinfo(tkc, mod, &ext->appinfoQ);
            } else {
                res = ncx_consume_appinfo(tkc, mod, &errQ);
                ncx_clean_appinfoQ(&errQ);
            }
            CHK_EXIT(res, retres);
            continue;
        case TK_TT_RBRACE:
            done = TRUE;
            continue;
        case TK_TT_TSTRING:
            break;  /* YANG clause assumed */
        default:
            retres = ERR_NCX_WRONG_TKTYPE;
            ncx_mod_exp_err(tkc, mod, retres, expstr);
            continue;
        }

        /* Got a token string so check the value */
        if (!xml_strcmp(val, YANG_K_YIN_ELEMENT)) {
            if (save) {
                res = yang_consume_boolean(tkc, 
                                           mod, 
                                           &ext->argel,
                                           &yinel, 
                                           &ext->appinfoQ);
            } else {
                res = yang_consume_boolean(tkc, 
                                           mod, 
                                           &errsave,
                                           NULL, 
                                           NULL);
            }
        } else {
            res = ERR_NCX_WRONG_TKVAL;
            ncx_mod_exp_err(tkc, mod, res, expstr);
        }
        CHK_EXIT(res, retres);
    }

    return retres;

}  /* consume_yang_arg */
Ejemplo n.º 9
0
/********************************************************************
 * FUNCTION parse_node
 * (config mode input received)
 *  Parse the next word using the comstate and session_cb state
 *  Expecting this word to represent a datastore node, not a key or value
 *
 * e.g.,
 *  interface eth0 mtu 1500
 *      ^      ^    ^    ^
 *    node    key node  value
 *
 * INPUTS:
 *    tkc == token chain in progress
 *    session_cb == session control block to use
 *    done == address of return done flag
 *    gotexit == address of return gotexit flag
 *    gotapply == address of return gotapply flag
 *    gotdo == address of return do command flag
 *
 * OUTPUTS:
 *    *done == TRUE if parsing done; no more tokens;
 *             ignore unless return NO_ERR
 *    *gotexit == TRUE if got 'exit' command
 *             ignore unless return NO_ERR and *done == TRUE
 *    *gotapply == TRUE if got 'apply' command
 *             ignore unless return NO_ERR and *done == TRUE
 *    *gotdo == TRUE if got 'do' command
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    parse_node (tk_chain_t *tkc,
                session_cb_t *session_cb,
                boolean *done,
                boolean *gotexit,
                boolean *gotapply,
                boolean *gotdo)
{
    *done = FALSE;
    *gotexit = FALSE;
    *gotapply = FALSE;
    *gotdo = FALSE;

    /* get the next token to use */
    status_t res = TK_ADV(tkc);
    if (res != NO_ERR) {
        if (res == ERR_NCX_EOF) {
            *done = TRUE;
            return NO_ERR;
        } else {
            log_error("\nError: Expecting node identifier\n");
            return res;
        }
    }

    boolean first = tk_cur_is_first(tkc);

    /* check if the 'do' form of command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_DO) &&
        tk_next_typ(tkc) != TK_TT_NONE) {

        *gotdo = TRUE;
        *done = TRUE;
        return NO_ERR;
    }

    /* check if the 'no' form of command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_NO) &&
        tk_next_typ(tkc) != TK_TT_NONE) {

        /* get the next token to use as the first identifier */
        res = TK_ADV(tkc);
        if (res != NO_ERR) {
            log_error("\nError: Expecting identifier token after "
                      "'no' keyword\n");
            return res;
        }
        first = FALSE;
        session_cb->config_no_active = TRUE;
    }

    /* check if the current token is an identifier */
    if (!TK_CUR_ID(tkc)) {
        log_error("\nError: expecting a node identifier\n");
        res = ERR_NCX_WRONG_TKTYPE;
        return res;
    }

    /* check if the exit command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_EXIT) &&
        tk_next_typ(tkc) == TK_TT_NONE) {
        *done = TRUE;
        *gotexit = TRUE;
        return NO_ERR;
    }

    /* check if the apply command was given */
    if (first && TK_CUR_TYP(tkc) == TK_TT_TSTRING &&
        !xml_strcmp(TK_CUR_VAL(tkc), NCX_EL_APPLY) &&
        tk_next_typ(tkc) == TK_TT_NONE) {
        *done = TRUE;
        *gotapply = TRUE;
        return NO_ERR;
    }

    obj_template_t *startobj = session_cb->config_curobj;
    obj_template_t *topobj = NULL;

    if (startobj == NULL) {
        /* getting top-level config object */
        topobj = find_top_obj(session_cb, TK_CUR_VAL(tkc));
        if (topobj && !(obj_is_data_db(topobj) && obj_is_config(topobj))) {
            topobj = NULL;
        }
    } else {
        /* getting child node config object */
        topobj = find_child_obj(session_cb, startobj, TK_CUR_VAL(tkc));
        if (topobj && !obj_is_config(topobj)) {
            topobj = NULL;
        }
    }
    
    if (topobj == NULL) {
        log_error("\nError: No config object found matching '%s'\n",
                  TK_CUR_VAL(tkc));
        return ERR_NCX_UNKNOWN_OBJECT;
    }

    /* got a top object (relative to the current context) */
    session_cb->config_curobj = topobj;

    /* make a template object for the edit operation for non-terminals */
    val_value_t *newval = NULL;
    if (!obj_is_leafy(topobj)) {
        newval = val_new_value();
        if (newval == NULL) {
            log_error("\nError: malloc failed for new value\n");
            return ERR_INTERNAL_MEM;
        }
        val_init_from_template(newval, topobj);
        add_enode(session_cb, newval);
    } else if (session_cb->config_no_active && obj_is_leaf(topobj)) {
        /* no ... foo-leaf */
        newval = xml_val_new_flag(obj_get_name(topobj), obj_get_nsid(topobj));
        if (newval == NULL) {
            log_error("\nError: malloc failed for new value\n");
            return ERR_INTERNAL_MEM;
        }
        add_enode(session_cb, newval);
    }

    if (obj_is_list(topobj)) {
        boolean anykeys = FALSE;
        obj_key_t *newkey = obj_first_key(topobj);
        while (newkey) {
            anykeys = TRUE;

            /* get the next token to use as the key value */
            res = TK_ADV(tkc);
            if (res != NO_ERR) {
                log_error("\nError: Expecting value for '%s' key leaf\n",
                          obj_get_name(newkey->keyobj));
                return res;
            }

            /* parse the value as a key value */
            /*** do something different if TK_CUR_MOD(tkc) is not NULL ***/
            val_value_t *keyval =
                val_make_simval_obj(newkey->keyobj, TK_CUR_VAL(tkc), &res);
            if (res != NO_ERR) {
                log_error("\nError: Invalid value for '%s' key leaf\n",
                          obj_get_name(newkey->keyobj));
                val_free_value(keyval);
                return res;
            }

            /* save keyval */
            if (newval) {
                val_add_child(keyval, newval);
            } else {
                val_free_value(keyval);
            }

            /* set up the next key in the list */
            newkey = obj_next_key(newkey);
        }
        if (anykeys) {
            res = val_gen_index_chain(topobj, newval);
        }
    }

    if (res == NO_ERR && obj_is_leafy(topobj)) {
        /* expecting a value node to follow or done if 'no' command */
        *done = TRUE;
    }

    return res;

}  /* parse_node */
Ejemplo n.º 10
0
/********************************************************************
 * FUNCTION parse_value
 * (config mode input received)
 *  Parse the next word using the comstate and session_cb state
 *  Expecting this word to represent a leaf or leaf-list value
 *
 * e.g.,
 *  interface eth0 mtu 1500
 *      ^      ^    ^    ^
 *    node    key node  value
 *
 * INPUTS:
 *    session_cb == session control block to use
 *    tkc == token chain in progress
 *
 * RETURNS:
 *   status
 *********************************************************************/
static status_t
    parse_value (session_cb_t *session_cb,
                 tk_chain_t *tkc)
{
    obj_template_t *obj = session_cb->config_curobj;
    if (obj == NULL) {
        return SET_ERROR(ERR_INTERNAL_VAL);
    }

    const xmlChar *usestr = NULL;
    status_t res = NO_ERR;
    boolean isleaf = obj_is_leaf(obj);
    boolean isempty =
        (obj_is_leafy(obj) && obj_get_basetype(obj) == NCX_BT_EMPTY);

    if (!session_cb->config_no_active && isempty) {
        /* do not get the next token; treat next token as a sibling
         * of this empty leaf or leaf-list           */
        usestr = EMPTY_STRING;
    } else {
        /* get the next token to use */
        res = TK_ADV(tkc);

        if (session_cb->config_no_active) {
            /* got no [command] */
            if (isleaf || isempty) {
                if (res == NO_ERR) {
                    log_error("\nError: Not expecting value string for '%s' "
                              "in 'no' command\n", obj_get_name(obj));
                    return ERR_NCX_EXTRA_NODE;
                }
                if (isleaf) {
                    // node already added in parse_node
                    return NO_ERR;
                }
            } else if (res != NO_ERR) {
                log_error("\nError: Expecting value string for node '%s'\n",
                          obj_get_name(obj));
                return res;
            }
        } else if (res != NO_ERR) {
            log_error("\nError: Expecting value string for node '%s'\n",
                      obj_get_name(obj));
            return res;
        } else {
            usestr = TK_CUR_VAL(tkc);
        }
    }

    /* parse the value as a leaf value */
    /*** do something different if TK_CUR_MOD(tkc) is not NULL ***/
    val_value_t *leafval = val_make_simval_obj(obj, usestr, &res);
    if (res != NO_ERR) {
        log_error("\nError: Invalid value for '%s' leaf%s\n",
                  obj_get_name(obj),
                  obj_is_leaf(obj) ? EMPTY_STRING : (const xmlChar *)"-list");
        val_free_value(leafval);
        return res;
    }

    add_enode(session_cb, leafval);

    return NO_ERR;

}  /* parse_value */