/* Parse the options strings in ARGC & ARGV according to the argp in ARGP. FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the index in ARGV of the first unparsed option is returned in it. If an unknown option is present, EINVAL is returned; if some parser routine returned a non-zero value, it is returned; otherwise 0 is returned. */ error_t __argp_parse(const struct argp *argp, int argc, char **argv, unsigned flags, int *end_index, void *input) { error_t err; struct parser parser; /* If true, then err == EBADKEY is a result of a non-option argument * failing to be parsed (which in some cases is actually a non-error): */ int arg_ebadkey = 0; if (! (flags & ARGP_NO_HELP)) { /* Add our own options: */ struct argp_child *child; struct argp *top_argp; child = (struct argp_child *)alloca(4 * sizeof(struct argp_child)); top_argp = (struct argp *)alloca(sizeof(struct argp)); /* TOP_ARGP has no options, it just serves to group the user & default * argps: */ memset(top_argp, 0, sizeof(*top_argp)); top_argp->children = child; memset(child, 0, (4 * sizeof(struct argp_child))); if (argp) (child++)->argp = argp; (child++)->argp = &argp_default_argp; if (argp_program_version || argp_program_version_hook) (child++)->argp = &argp_version_argp; child->argp = 0; argp = top_argp; } /* Construct a parser for these arguments: */ err = parser_init(&parser, argp, argc, argv, (int)flags, input); if (! err) { /* Parse! */ while (! err) { err = parser_parse_next(&parser, &arg_ebadkey); } err = parser_finalize(&parser, err, arg_ebadkey, end_index); } return err; }
int server_config_parse_string(const struct config_parser *parser, const char *file, uint32_t length, const uint8_t *data, void *input) { struct config_tokenizer tokenizer; struct parser_state state; int err; config_tokenizer_init(&tokenizer, file, length, data); err = parser_init(&state, parser, input); if (err) return err; while (!err) { enum config_token_type type = config_tokenizer_next(&tokenizer); switch (type) { default: err = EINVAL; break; case TOK_STRING: err = parser_parse_option(&state, &tokenizer); break; case TOK_EOF: goto done; } /* FIXME: Require newline or separator between options? */ } done: parser_finalize(&state); return err; }
/** * Helper, called whenever a full response line is collected. */ static void parser_handle_line(struct at_parser *parser) { /* Skip empty lines. */ if (parser->buf_used == parser->buf_current) return; /* NULL-terminate the response .*/ parser->buf[parser->buf_used] = '\0'; /* Extract line address & length for later use. */ const char *line = parser->buf + parser->buf_current; size_t len = parser->buf_used - parser->buf_current; /* Log the received line. */ printf("< '%.*s'\n", (int) len, line); /* Determine response type. */ enum at_response_type type = AT_RESPONSE_UNKNOWN; if (parser->cbs->scan_line) type = parser->cbs->scan_line(line, len, parser->priv); if (!type) type = generic_line_scanner(line, len, parser); /* Expected URCs and all unexpected lines are sent to URC handler. */ if (type == AT_RESPONSE_URC || parser->state == STATE_IDLE) { /* Fire the callback on the URC line. */ parser->cbs->handle_urc(parser->buf + parser->buf_current, parser->buf_used - parser->buf_current, parser->priv); /* Discard the URC line from the buffer. */ parser_discard_line(parser); return; } /* Accumulate everything that's not a final OK. */ if (type != AT_RESPONSE_FINAL_OK) { /* Include the line in the buffer. */ parser_include_line(parser); } else { /* Discard the line from the buffer. */ parser_discard_line(parser); } /* Act on the response type. */ switch (type & _AT_RESPONSE_TYPE_MASK) { case AT_RESPONSE_FINAL_OK: case AT_RESPONSE_FINAL: { /* Fire the response callback. */ parser_finalize(parser); parser->cbs->handle_response(parser->buf, parser->buf_used, parser->priv); /* Go back to idle state. */ at_parser_reset(parser); } break; case _AT_RESPONSE_RAWDATA_FOLLOWS: { /* Switch parser state to rawdata mode. */ parser->data_left = (int)type >> 8; parser->state = STATE_RAWDATA; } break; case _AT_RESPONSE_HEXDATA_FOLLOWS: { /* Switch parser state to hexdata mode. */ parser->data_left = (int)type >> 8; parser->nibble = -1; parser->state = STATE_HEXDATA; } break; default: { /* Keep calm and carry on. */ } break; } }
int server_config_parse_example(const struct config_parser *parser, void *input) { struct parser_state state; struct group *group; int err; err = parser_init(&state, parser, input); if (err) return err; for (group = state.egroup - 1; group >= state.groups; group--) { const struct config_parser *parser= group->parser; const struct config_option *option; for (option = parser->options; option->type != CONFIG_TYPE_NONE; option++) if (option->example) { uint32_t value = 0; const uint8_t *data = NULL; unsigned length = strlen(option->example); switch (option->type) { default: fatal("Internal error.\n"); case CONFIG_TYPE_LIST: { struct config_tokenizer tokenizer; uint8_t *list; config_tokenizer_init(&tokenizer, "example fragment", length, option->example); err = parse_value_list(&value, &list, &tokenizer); data = list; break; } case CONFIG_TYPE_BOOL: err = parse_value_bool(&value, length, option->example); break; case CONFIG_TYPE_NUMBER: err = parse_value_unsigned(&value, length, option->example); break; case CONFIG_TYPE_STRING: value = length; data = option->example; break; } if (err) fatal("Bad example value for configuration option `%z'\n", option->name); else err = group->parser->handler(option->key, value, data, &group->state); } } parser_finalize(&state); return err; }