/******************************************************************** * FUNCTION write_yin_contents * * Go through the token chain and write all the * YIN elements according to algoritm in sec. 11 * * 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 * * RETURNS: * status *********************************************************************/ static status_t write_yin_contents (yang_pcb_t *pcb, const yangdump_cvtparms_t *cp, ses_cb_t *scb) { status_t res; boolean done; int i; tk_reset_chain(pcb->tkc); res = NO_ERR; /* need to skip the first 3 tokens because the * [sub]module name { tokens have already been * handled as a special case */ for (i = 0; i < 4; i++) { res = advance_token(pcb); if (res != NO_ERR) { return res; } } done = FALSE; while (!done && res == NO_ERR) { res = write_yin_stmt(pcb, cp, scb, cp->indent, &done); } return res; } /* write_yin_contents */
struct Token* c_get_tokens(struct Grammar* grammar, char* text, int indent, struct cTokenError* error) { struct Token* start = NULL; struct Token* current = NULL; struct Token* tmp = NULL; struct TokenState state; state.at = 0; state.ln = strlen(text); // state.text = text; state.lineno = 1; state.charno = 1; state.indents = (int*)malloc(sizeof(int)*100); state.indents[0] = 0; state.max_indents = 100; state.num_indents = 1; struct PToken ptoken; int ID_t = grammar->tokens.num; int DD_t = grammar->tokens.num+1; int res = 0; int dirty; // printf("with text:: %s\n\n", text); while (state.at < state.ln) { int i; dirty = 0; for (i=0;i<grammar->tokens.num;i++) { // printf("looking for token: %d\n", i); ptoken = grammar->tokens.tokens[i]; switch (ptoken.type) { case CTOKEN: res = check_ctoken(ptoken.value.tid, state.at, text, state.ln, grammar->idchars); break; case CHARTOKEN: res = check_chartoken(ptoken.value.chars, ptoken.num, state.at, text, state.ln); break; case STRTOKEN: res = check_stringtoken(ptoken.value.strings, ptoken.num, state.at, text, state.ln); break; case IDTOKEN: res = check_idtoken(ptoken.value.strings, ptoken.num, state.at, text, state.ln, grammar->idchars); break; case IIDTOKEN: res = check_iidtoken(ptoken.value.strings, ptoken.num, state.at, text, state.ln, grammar->idchars); break; default: res = 0; } if (res > 0) { tmp = (struct Token*)malloc(sizeof(struct Token)); tmp->value = (char*)malloc(sizeof(char)*(res+1)); strncpy(tmp->value, text + state.at, res); tmp->value[res] = '\0'; // printf("got token! %d (%s)\n", res, tmp->value); tmp->which = ptoken.which; tmp->next = NULL; tmp->lineno = state.lineno; tmp->charno = state.charno; if (start == NULL) { start = tmp; } else { current->next = tmp; } current = tmp; current = advance_token(res, current, indent, &state, text, ID_t, DD_t, error); if (current == NULL) { return NULL; } state.at += res; dirty = 1; break; } } if (!dirty) { error->text = "no valid token found"; error->lineno = state.lineno; error->charno = state.charno; return NULL; } } return start; }
/******************************************************************** * 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 */