// host = IP-literal / IPv4address / reg-name // IP-literal = "[" ( IPv6address / IPvFuture ) "]" // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet // reg-name = *( unreserved / pct-encoded / sub-delims ) static IteratorT parse_host_character(IteratorT begin, IteratorT end) { IteratorT next = begin; next = parse_predicate(is_unreserved, next, end); next = parse_string(parse_percent_encoded, next, end); next = parse_predicate(is_sub_delimiter, next, end); return next; }
static IteratorT parse_path_character(IteratorT begin, IteratorT end) { // We coalesce the parsing into one step and parse as much as possible each time. // This isn't strictly following the standard, but it shouldn't be any different in practice. IteratorT next = begin; next = parse_predicate(is_unreserved, next, end); next = parse_string(parse_percent_encoded, next, end); next = parse_predicate(is_sub_delimiter, next, end); next = parse_predicate(is_path_character, next, end); return next; }
static IteratorT parse_scheme(IteratorT begin, IteratorT end) { IteratorT next = parse_predicate(is_alpha, begin, end); if (next == begin) { return begin; } next = parse_predicate(is_scheme_character, next, end); IteratorT scheme_end = parse_constant(":", next, end); if (scheme_end == next) { return begin; } else { return scheme_end; } }
static IteratorT parse_meta_character(IteratorT begin, IteratorT end) { IteratorT next = begin; next = parse_path_character(next, end); next = parse_predicate(is_meta_character, next, end); return next; }
// authority = [ userinfo "@" ] host [ ":" port ] // port = *DIGIT static IteratorT parse_authority(IteratorT begin, IteratorT end, Authority & authority) { IteratorT user_info_begin = begin; IteratorT user_info_end = parse_string(parse_user_info_character, begin, end); IteratorT host_begin = parse_constant("@", user_info_end, end); // Can we parse the "@" symbol? if (host_begin != user_info_end) { // Valid user info was found: authority.user_info_begin = user_info_begin; authority.user_info_end = user_info_end; } else { host_begin = begin; } IteratorT host_end = parse_host(host_begin, end); if (host_end == host_begin) { // We can't continue as host is required. return host_end; } authority.host_begin = host_begin; authority.host_end = host_end; IteratorT port_begin = parse_constant(":", host_end, end); if (port_begin != host_end) { IteratorT port_end = parse_predicate(is_numeric, port_begin, end); authority.port_begin = port_begin; authority.port_end = port_end; return port_end; } else { return host_end; } }
int parse_config(bool_node **tree) { int sts; FILE *file = NULL; char *fname; struct stat stat_buf; long size; char *ptr; if ((sts = parse_predicate(tree)) != 0) { (void)fprintf(stderr, "%s: Failed to parse configuration file\n", pmProgname); return sts; } /* --- dump to tmp file & read to buffer --- */ if ((fname = tmpnam(NULL)) == NULL || (file = fopen(fname, "w+")) == NULL) { sts = -oserror(); fprintf(stderr, "%s: parse_config: failed to create \"%s\": %s\n", pmProgname, fname, strerror(-sts)); goto error; } if (unlink(fname) == -1) { sts = -oserror(); fprintf(stderr, "%s: parse_config: failed to unlink \"%s\": %s\n", pmProgname, fname, strerror(-sts)); goto error; } dump_predicate(file, *tree); fflush(file); if (fstat(fileno(file), &stat_buf) < 0) { sts = -oserror(); fprintf(stderr, "%s: parse_config: failed to stat \"%s\": %s\n", pmProgname, fname, strerror(-sts)); goto error; } size = (long)stat_buf.st_size; ptr = malloc(size+1); if (ptr == NULL) { sts = -oserror(); fprintf(stderr, "%s: parse_config: failed to malloc: %s\n", pmProgname, strerror(-sts)); goto error; } rewind(file); if (fread(ptr, size, 1, file) != 1) { clearerr(file); fprintf(stderr, "%s: parse_config: failed to fread \"%s\"\n", pmProgname, fname); sts = -1; goto error; } (void)fclose(file); if (pred_buffer != NULL) free(pred_buffer); pred_buffer = ptr; pred_buffer[size] = '\0'; return 0; error: if (file != NULL) (void)fclose(file); return sts; }