/******************************************************************* * get_temp_ibm reads temperatures from /proc/acpi/ibm/thermal and * returns the highest one found. *******************************************************************/ int get_temp_ibm() { int i=0, res, retval=0, ibm_temp, *tmp; ssize_t r; char *input; input = rbuf; if (unlikely(((ibm_temp = open(IBM_TEMP, O_RDONLY)) < 0) || ((r = read(ibm_temp, rbuf, 128)) < 14) || (close(ibm_temp) < 0))) { report(LOG_ERR, LOG_ERR, IBM_TEMP ": %s", strerror(errno)); errcnt++; return ERR_T_GET; } rbuf[r] = 0; skip_space(&input); if (likely(parse_keyword(&input, temperatures) != NULL)) { for (i = 0; ((tmp = parse_int(&input)) && (i < 16)); i++) { res = *tmp + config->sensors->bias[i]; if (res > retval) retval = res; free(tmp); } if (unlikely(i < 2)) { report(LOG_ERR, LOG_ERR, MSG_ERR_T_GET); errcnt++; retval = ERR_T_GET; } } else { report(LOG_ERR, LOG_ERR, MSG_ERR_T_PARSE(rbuf)); errcnt++; retval = ERR_T_GET; } return retval; }
static void ExecClass(const char *param) { char *temp = strmalloc(param); parse_keyword(temp, 1); free(temp); }
static void parse_nondirective(char *s) { char *base = s; char *t; const char *attr0 = Ident_attr; const char *attr1 = Ident2_attr; char *attr2 = Literal_attr; if (FltOptions('c')) { t = skip_ident(s = base); if (t != s) { int save = *t; /* this parses one of * "name" * "name:class" * "name:color" */ parse_keyword(s, 0); *t = 0; attr0 = actual_color(s, abbr_len(s), 0); *t = (char) save; } if (skip_eqls_ch(&t)) { s = skip_ident(t); if (s != t) { attr1 = actual_color(t, (int) (s - t), 1); } } } t = skip_ident(s = base); flt_puts(s, (int) (t - s), attr0); if (parse_eqls_ch(&t)) { s = skip_ident(t); if (s != t) { int save = *s; *s = 0; if (!FltOptions('c')) { if (*(attr1 = color_of(t, 0)) == '\0') attr1 = Action_attr; } flt_puts(t, (int) strlen(t), attr1); *s = (char) save; } if (parse_eqls_ch(&s)) { flt_puts(s, (int) strlen(s), attr2); } else if (*s) { flt_puts(s, (int) strlen(s), Error_attr); } } else if (*t) { flt_puts(t, (int) strlen(t), Error_attr); } }
static C_RESULT parse_I(FILE* f) { char keyword[KW_MAX_LEN]; while( SUCCEED(fetch_char(f)) && is_separator(next_c) ); while( !is_eol(next_c) ) { keyword_t kw; parse_string( f, keyword, KW_MAX_LEN ); if( SUCCEED( match_keyword( keyword, &kw ) ) ) { parse_keyword( f, kw ); } } return C_OK; }
/* * Each line contains a sequence of keywords. */ static int parse_line(struct archive_read *a, struct archive_entry *entry, struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws) { struct mtree_option *iter; int r = ARCHIVE_OK, r1; for (iter = mp->options; iter != NULL; iter = iter->next) { r1 = parse_keyword(a, mtree, entry, iter, parsed_kws); if (r1 < r) r = r1; } if (r == ARCHIVE_OK && (*parsed_kws & MTREE_HAS_TYPE) == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Missing type keyword in mtree specification"); return (ARCHIVE_WARN); } return (r); }
/** Read FILE match content */ static void read_file_content(FILE* in, int* lineno, struct replay_moment* mom) { char line[MAX_LINE_LEN]; char* remain = line; struct config_strlist** last = &mom->file_content; line[MAX_LINE_LEN-1]=0; if(!fgets(line, MAX_LINE_LEN-1, in)) fatal_exit("FILE_BEGIN expected at line %d", *lineno); if(!parse_keyword(&remain, "FILE_BEGIN")) fatal_exit("FILE_BEGIN expected at line %d", *lineno); while(fgets(line, MAX_LINE_LEN-1, in)) { (*lineno)++; if(strncmp(line, "FILE_END", 8) == 0) { return; } if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ if(!cfg_strlist_insert(last, strdup(line))) fatal_exit("malloc failure"); last = &( (*last)->next ); } fatal_exit("no FILE_END in input file"); }
static void ExecClass(char *param) { char *t = strmalloc(param); char *s; const char *attr = ""; parse_keyword(t, 1); free(t); t = flt_put_blanks(param); s = skip_ident(t); if (FltOptions('c')) { attr = actual_color(param, (int) (s - param), 1); } else { attr = Ident2_attr; } flt_puts(param, (int) (s - param), attr); if (parse_eqls_ch(&s)) { t = s; s = skip_ident(t); if (FltOptions('c')) { attr = actual_color(t, (int) (s - t), 1); } else { if (*(attr = color_of(t, 0)) == '\0') attr = Action_attr; } flt_puts(t, (int) (s - t), attr); if (parse_eqls_ch(&s)) { flt_puts(s, (int) strlen(s), Literal_attr); } else if (*s) { flt_puts(s, (int) strlen(s), Error_attr); } } else if (*s) { flt_puts(s, (int) strlen(s), Error_attr); } }
struct replay_scenario* replay_scenario_read(FILE* in, const char* name, int* lineno) { char line[MAX_LINE_LEN]; char *parse; struct replay_scenario* scen = NULL; uint32_t ttl = 3600; ldns_rdf* or = NULL; ldns_rdf* prev = NULL; line[MAX_LINE_LEN-1]=0; while(fgets(line, MAX_LINE_LEN-1, in)) { parse=line; (*lineno)++; while(isspace((int)*parse)) parse++; if(!*parse) continue; /* empty line */ if(parse_keyword(&parse, ";")) continue; /* comment */ if(parse_keyword(&parse, "SCENARIO_BEGIN")) { scen = make_scenario(parse); if(!scen) fatal_exit("%d: could not make scen", *lineno); continue; } if(!scen) fatal_exit("%d: expected SCENARIO", *lineno); if(parse_keyword(&parse, "RANGE_BEGIN")) { struct replay_range* newr = replay_range_read(parse, in, name, lineno, line, &ttl, &or, &prev); if(!newr) fatal_exit("%d: bad range", *lineno); newr->next_range = scen->range_list; scen->range_list = newr; } else if(parse_keyword(&parse, "STEP")) { struct replay_moment* mom = replay_moment_read(parse, in, name, lineno, &ttl, &or, &prev); if(!mom) fatal_exit("%d: bad moment", *lineno); if(scen->mom_last && scen->mom_last->time_step >= mom->time_step) fatal_exit("%d: time goes backwards", *lineno); if(scen->mom_last) scen->mom_last->mom_next = mom; else scen->mom_first = mom; scen->mom_last = mom; } else if(parse_keyword(&parse, "SCENARIO_END")) { struct replay_moment *p = scen->mom_first; int num = 0; while(p) { num++; p = p->mom_next; } log_info("Scenario has %d steps", num); ldns_rdf_deep_free(or); ldns_rdf_deep_free(prev); return scen; } } ldns_rdf_deep_free(or); ldns_rdf_deep_free(prev); replay_scenario_delete(scen); return NULL; }
/** * Read a replay moment 'STEP' from file. * @param remain: Rest of line (after STEP keyword). * @param in: file to read from. * @param name: name to print in errors. * @param lineno: incremented as lines are read. * @param ttl: for readentry * @param or: for readentry * @param prev: for readentry * @return: range object to add to list, or NULL on error. */ static struct replay_moment* replay_moment_read(char* remain, FILE* in, const char* name, int* lineno, uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev) { struct replay_moment* mom = (struct replay_moment*)malloc( sizeof(struct replay_moment)); int skip = 0; int readentry = 0; if(!mom) return NULL; memset(mom, 0, sizeof(*mom)); if(sscanf(remain, " %d%n", &mom->time_step, &skip) != 1) { log_err("%d: cannot read number: %s", *lineno, remain); free(mom); return NULL; } remain += skip; while(isspace((int)*remain)) remain++; if(parse_keyword(&remain, "NOTHING")) { mom->evt_type = repevt_nothing; } else if(parse_keyword(&remain, "QUERY")) { mom->evt_type = repevt_front_query; readentry = 1; if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen)) fatal_exit("internal error"); } else if(parse_keyword(&remain, "CHECK_ANSWER")) { mom->evt_type = repevt_front_reply; readentry = 1; } else if(parse_keyword(&remain, "CHECK_OUT_QUERY")) { mom->evt_type = repevt_back_query; readentry = 1; } else if(parse_keyword(&remain, "REPLY")) { mom->evt_type = repevt_back_reply; readentry = 1; } else if(parse_keyword(&remain, "TIMEOUT")) { mom->evt_type = repevt_timeout; } else if(parse_keyword(&remain, "TIME_PASSES")) { mom->evt_type = repevt_time_passes; while(isspace((int)*remain)) remain++; if(parse_keyword(&remain, "EVAL")) { while(isspace((int)*remain)) remain++; mom->string = strdup(remain); if(!mom->string) fatal_exit("out of memory"); if(strlen(mom->string)>0) mom->string[strlen(mom->string)-1]=0; remain += strlen(mom->string); } } else if(parse_keyword(&remain, "CHECK_AUTOTRUST")) { mom->evt_type = repevt_autotrust_check; while(isspace((int)*remain)) remain++; if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n') remain[strlen(remain)-1] = 0; mom->autotrust_id = strdup(remain); if(!mom->autotrust_id) fatal_exit("out of memory"); read_file_content(in, lineno, mom); } else if(parse_keyword(&remain, "ERROR")) { mom->evt_type = repevt_error; } else if(parse_keyword(&remain, "TRAFFIC")) { mom->evt_type = repevt_traffic; } else if(parse_keyword(&remain, "ASSIGN")) { mom->evt_type = repevt_assign; read_assign_step(remain, mom); } else if(parse_keyword(&remain, "INFRA_RTT")) { char *s, *m; mom->evt_type = repevt_infra_rtt; while(isspace((int)*remain)) remain++; s = remain; remain = strchr(s, ' '); if(!remain) fatal_exit("expected three args for INFRA_RTT"); remain[0] = 0; remain++; while(isspace((int)*remain)) remain++; m = strchr(remain, ' '); if(!m) fatal_exit("expected three args for INFRA_RTT"); m[0] = 0; m++; while(isspace((int)*m)) m++; if(!extstrtoaddr(s, &mom->addr, &mom->addrlen)) fatal_exit("bad infra_rtt address %s", s); if(strlen(m)>0 && m[strlen(m)-1]=='\n') m[strlen(m)-1] = 0; mom->variable = strdup(remain); mom->string = strdup(m); if(!mom->string) fatal_exit("out of memory"); if(!mom->variable) fatal_exit("out of memory"); } else { log_err("%d: unknown event type %s", *lineno, remain); free(mom); return NULL; } while(isspace((int)*remain)) remain++; if(parse_keyword(&remain, "ADDRESS")) { while(isspace((int)*remain)) remain++; if(strlen(remain) > 0) /* remove \n */ remain[strlen(remain)-1] = 0; if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) { log_err("line %d: could not parse ADDRESS: %s", *lineno, remain); free(mom); return NULL; } } if(parse_keyword(&remain, "ELAPSE")) { double sec; errno = 0; sec = strtod(remain, &remain); if(sec == 0. && errno != 0) { log_err("line %d: could not parse ELAPSE: %s (%s)", *lineno, remain, strerror(errno)); free(mom); return NULL; } #ifndef S_SPLINT_S mom->elapse.tv_sec = (int)sec; mom->elapse.tv_usec = (int)((sec - (double)mom->elapse.tv_sec) *1000000. + 0.5); #endif } if(readentry) { mom->match = read_entry(in, name, lineno, ttl, or, prev, 1); if(!mom->match) { free(mom); return NULL; } } return mom; }
string r_language_rep::get_color (tree t, int start, int end) { static bool setup_done= false; if (!setup_done) { r_color_setup_constants (colored); r_color_setup_keywords (colored); r_color_setup_otherlexeme (colored); setup_done= true; } static string none= ""; if (start >= end) return none; string s= t->label; string r1=s(0,start) ; int pos=0;int opos; bool backquote= false; bool after_backquote; bool postfix= false; bool possible_function= true; bool possible_type= false; bool possible_class= false; bool possible_future_type= false; bool possible_future_function= true; bool possible_future_class= false; string type; bool is_markup; #if 0 // There isn't much point to the following, because its only effet is pos and type, and both are reset below. do { do { opos=pos; parse_string (s, pos); if (opos<pos) break; parse_comment_single_line (s, pos); if (opos < pos) { type= "comment"; break; } pos++; } while(false); } while( pos<N(s) ); #endif pos=0; do { type= none; do { after_backquote= backquote; possible_function= possible_future_function; possible_type= possible_future_type; possible_class= possible_future_class; opos= pos; parse_blanks (s, pos); if (opos<pos) break; parse_string (s, pos); if (opos<pos) { type= "string"; backquote= false; postfix= false; possible_future_function= false; possible_future_type= false; possible_future_class= false; possible_type= false; break; } parse_number (s, pos); if (opos<pos) { type= "number"; backquote= false; postfix= false; possible_future_function= false; possible_future_class= false; break; } parse_comment_single_line (s, pos); if (opos<pos) { type= "comment"; backquote= false; postfix= false; possible_future_type= false; possible_type= false; break; } parse_modifier (colored, s, pos); if (opos<pos) { type="keyword"; backquote= false; postfix= false; possible_future_type= false; possible_type= false; possible_function= false; break; } parse_postfix (colored, s, pos); if (opos<pos) { type="keyword"; backquote= false; postfix= true; possible_future_type= false; possible_future_class= false; possible_type= false; possible_function= false; possible_future_class= false; break; } parse_class (colored, s, pos); if (opos<pos) { type= "keyword"; backquote=false; postfix=false; possible_future_type= false; possible_type= false; possible_future_class=true; possible_future_function= false; break; } parse_keyword (colored, s, pos); if (opos<pos) { type= "keyword"; backquote= false; postfix= false; possible_future_type= false; possible_type= false; possible_function= false; possible_future_function= false; possible_future_class= false; break; } parse_other_op_assign (colored, s, pos); //not left parenthesis if (opos<pos) { type= "other_lexeme";// was type = "op assign" ; backquote= false; postfix= false; possible_function= false; possible_future_function= true; possible_future_type= false; possible_future_class= false; possible_type= false; break; } parse_other_op_index (colored, s, pos); //not left parenthesis if (opos<pos) { type= "other_lexeme";// was type = "op index" ; backquote= false; postfix= false; possible_function= false; possible_future_function= true; possible_future_type= false; possible_future_class= false; possible_type= false; break; } parse_other_lexeme (colored, s, pos); //not left parenthesis if (opos<pos) { type= "other_lexeme";// was type = "operator" ; backquote= false; postfix= false; possible_function= false; possible_future_function= true; possible_future_type= false; possible_future_class= false; possible_type= false; break; } parse_constant (colored, s, pos); if (opos<pos) { type= "constant"; backquote= false; postfix= false; possible_future_function= false; possible_future_class= false; break; } parse_backquote (s, pos); if (opos<pos) { backquote= true; postfix= false; possible_future_function= false; possible_future_class= false; break; } parse_identifier_or_markup (colored, s, pos, postfix, is_markup); if (opos<pos) { if (is_markup) {type= "identifier_markup";} else type= "identifier"; backquote= false; postfix= false; possible_future_function=false; possible_future_class= false; break; } parse_parenthesized (s, pos); // stops after well parenthesized ) or before // or /{ or " or /" if (opos<pos && pos<=start) { type="left_parenthesis"; backquote= false; postfix= false; possible_function= false; possible_future_function= true; possible_future_class= false; break; } if (opos<pos && possible_type==true) return "dark green"; if (opos<pos && after_backquote) return none; backquote= false; postfix= false; pos= opos; pos++; } while (false); // This while() is so that we can easily escape with break. } while (pos<=start); if (possible_type) return "dark green"; if (type=="string") return "#a06040"; if (type=="operator") return "red"; if (type=="op assign") return "dark green"; if (type=="op index") return "dark blue"; if (type=="comment") return "brown"; if (type=="keyword" && !after_backquote) return "#8020c0"; if (type=="other_lexeme") return none; if (type=="constant") return "#2060c0"; if (type=="number") return "#2060c0"; if (type=="left_parenthesis") return none; if (type=="identifier" && !possible_function && !possible_class ) return none; if (type=="identifier_markup" && !possible_function && !possible_class ) return COLOR_MARKUP; if ( (type=="identifier" || type=="identifier_markup") && possible_function) { possible_function= false; do { do { opos=pos; parse_blanks (s, pos); if (opos<pos) break; parse_identifier (colored, s, pos,false); if (opos<pos) { possible_function= true; break; } parse_number (s, pos); if (opos<pos) { possible_function= true; break; } parse_constant (colored, s, pos); if (opos<pos) { possible_function= true; break; } parse_comment_single_line (s, pos); if (opos<pos) break; parse_parenthesized (s, pos); if (opos<pos) { possible_function= true; break; } } while (false); } while (opos != pos); if (!possible_function) { if (type=="identifier") {return none;} else return COLOR_MARKUP; // type=="identifier_markup" } else do { do { opos=pos; parse_blanks (s, pos); if (opos<pos) break; parse_identifier (colored, s, pos,false); if (opos<pos) break; parse_number(s,pos); if (opos<pos) break; parse_constant (colored, s, pos); if (opos<pos) break; parse_comment_single_line(s,pos); if (opos<pos) break; parse_parenthesized (s, pos); if (opos<pos) break; if (type=="identifier") {return none;} else return COLOR_MARKUP; } while (false); } while (pos<N(s)); } // type==identifier || type==identifier_markup && possible function if ( (type=="identifier" || type=="identifier_markup") && possible_class) { do { do { opos=pos; parse_blanks (s, pos); if (opos<pos) break; parse_identifier (colored, s, pos,false); if (opos<pos) break; parse_number(s,pos); if (opos<pos) break; parse_constant (colored, s, pos); if (opos<pos) break; parse_comment_single_line(s,pos); if (opos<pos) break; parse_parenthesized (s, pos); if (opos<pos) break; if (type=="identifier") {return none;} else return COLOR_MARKUP; } while (false); } while (pos<N(s)); } if (type=="identifier_markup") {return COLOR_MARKUP;} else return none; }
void m3umod_help_prompt_summary(char * command) { Select_t option = parse_keyword(command); switch (option) { case help: puts("KEYWORD\n" "\thelp\tdisplays help text; displays keyword information.\n\n" "ARGUMENTS\n" "\tThe 'help' command takes optional arguments. The argument is any\n" "\tvalid keyword.\n\n" "KEYWORD DICTIONARY\n" "\thelp\tversion\tcreate\tdelete\n" "\tparse\tmodify\tprint\tid3v2\n" "\tclear\ttouch\tpwd\tcd\n" "\tls\tquit\n\n" "USAGE\n" "\t> help [keyword]\n" ); break; case version: puts("KEYWORD\n" "\tversion\tdisplays version information.\n\n" "ARGUMENTS\n" "\tThe 'version' command takes no arguments.\n\n" "USAGE\n" "\t> version\n" ); break; case create: puts("KEYWORD\n" "\tcreate\tinitializes a m3u playlist file.\n\n" "ARGUMENTS\n" "\tThe 'create' command requires a argument.\n\n" "USAGE\n" "\t> create [filename].m3u\n" ); break; case del: puts("KEYWORD\n" "\tdelete\tdeletes the given file.\n\n" "ARGUMENTS\n" "\tThe 'delete' command requires at least one argument.\n\n" "USAGE\n" "\t> delete [filename]...\n" ); break; case parse: puts("KEYWORD\n" "\tparse\tparses a m3u playlist file.\n\n" "ARGUMENTS\n" "\tThe 'parse' command requires a argument.\n\n" "USAGE\n" "\t> parse [filename].m3u\n" ); break; case modify: puts("KEYWORD\n" "\tmodify\tmodifies mp3 filepaths in m3u playlist file\n\n" "ARGUMENTS\n" "\tThe 'modify' command requires three arguments.\n" "\tRequires a filename, source pattern, and target pattern.\n\n" "\tfilename\t\tthe file to be modified.\n" "\tsource pattern\t\tthe file path used in the given file.\n" "\ttarget pattern\t\tthe new path to replace the source pattern.\n\n" "USAGE\n" "\t> modify [filename].m3u [source pattern] [target pattern]\n" ); break; case cat: puts("KEYWORD\n" "\tcat\tconcatenates files to stdout.\n\n" "ARGUMENTS\n" "\tThe 'cat' command requires a argument.\n\n" "USAGE\n" "\t> cat [filename]...\n" ); break; case id3v2: puts("KEYWORD\n" "\tid3v2\tdisplays and modifies mp3 tags\n\n" "ARGUMENTS\n" "\tThe 'id3v2' command requires a subset of commands.\n" "\tRequires a mp3 filename, command, tag, and string.\n" "\tOnly one command, with its argument, is given at a time.\n\n" "id3v2 COMMANDS\n" "\tset\tsets the id3 tag\n" "\tload\tloads the id3 tag\n" "\tedit\tedits the id3 tag\n" "\tdelete\tdeletes the id3 tag\n\n" "id3v2 TAGS\n" "\ttitle\n" "\talbum\n" "\tartist\n" "\talbumartist\n" "\tcomment\n" "\tyear\n" "\ttrack\n" "\talbumnumber\n" "\talbumcover\n\n" "id3v2 STRINGS\n" "\tthe text based information to be stored within the tag.\n\n" "USAGE\n" "\t> id3v2 [filename].mp3 [command] [tag] [string]\n" ); break; case clear: puts("KEYWORD\n" "\tclear\tclears the screen.\n\n" "ARGUMENTS\n" "\tThe 'clear' command takes no arguments.\n\n" "USAGE\n" "\t> clear\n" ); break; case touch: puts("KEYWORD\n" "\ttouch\tcreates a empty file.\n\n" "ARGUMENTS\n" "\tThe 'touch' command requires at least one argument.\n\n" "USAGE\n" "\t> touch [filename]...\n" ); break; case pwd: puts("KEYWORD\n" "\tpwd\tprints the working directory to stdout.\n\n" "ARGUMENTS\n" "\tThe 'pwd' command takes no arguments.\n\n" "USAGE\n" "\t> pwd\n" ); break; case cd: puts("KEYWORD\n" "\tcd\tchanges the working directory.\n\n" "ARGUMENTS\n" "\tThe 'cd' command takes an optional argument.\n\n" "USAGE\n" "\t> cd [filepath]\n" ); break; case ls: puts("KEYWORD\n" "\tls\tlists the directories contents.\n\n" "ARGUMENTS\n" "\tThe 'ls' command takes optional arguments.\n\n" "USAGE\n" "\t> ls [filepath]...\n" ); break; case quit: puts("KEYWORD\n" "\tquit\tcloses this program.\n\n" "ARGUMENTS\n" "\tThe 'quit' command takes no arguments.\n\n" "USAGE\n" "\t> quit\n" ); break; default: fprintf(stderr, "Error: '%s' is not a valid help option.\n", command); break; } }
static inline #endif PsycParseIndexRC psyc_parse_index (PsycParseIndexState *state, PsycString *idx) { ParseRC ret; if (state->cursor >= state->buffer.length) return PSYC_PARSE_INDEX_END; state->startc = state->cursor; switch (state->part) { case PSYC_INDEX_PART_START: case PSYC_INDEX_PART_TYPE: idx->length = 0; idx->data = NULL; switch (state->buffer.data[state->cursor]) { case '#': state->part = PSYC_INDEX_PART_LIST; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); goto PSYC_INDEX_PART_LIST; case '.': state->part = PSYC_INDEX_PART_DICT; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); goto PSYC_INDEX_PART_STRUCT; case '{': state->part = PSYC_INDEX_PART_DICT; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); goto PSYC_INDEX_PART_DICT_LENGTH; default: return PSYC_PARSE_INDEX_ERROR_TYPE; } case PSYC_INDEX_PART_LIST: PSYC_INDEX_PART_LIST: switch (parse_length((ParseState*)state, &idx->length)) { case PARSE_SUCCESS: // list index is complete state->part = PSYC_INDEX_PART_TYPE; return PSYC_PARSE_INDEX_LIST; case PARSE_INSUFFICIENT: // list index at the end of buffer return PSYC_PARSE_INDEX_LIST_LAST; case PARSE_ERROR: // no index return PSYC_PARSE_INDEX_ERROR_LIST; default: // should not be reached return PSYC_PARSE_INDEX_ERROR; } case PSYC_INDEX_PART_STRUCT: PSYC_INDEX_PART_STRUCT: switch (parse_keyword((ParseState*)state, idx)) { case PARSE_SUCCESS: // end of keyword state->part = PSYC_INDEX_PART_TYPE; return PSYC_PARSE_INDEX_STRUCT; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_INDEX_STRUCT_LAST; case PARSE_ERROR: // no keyword return PSYC_PARSE_INDEX_ERROR_STRUCT; default: // should not be reached return PSYC_PARSE_INDEX_ERROR; } case PSYC_INDEX_PART_DICT_LENGTH: PSYC_INDEX_PART_DICT_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; idx->length = state->elemlen; idx->data = NULL; if (state->buffer.data[state->cursor] != ' ') return PSYC_PARSE_INDEX_ERROR_DICT_LENGTH; state->part = PSYC_INDEX_PART_DICT; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); break; case PARSE_INSUFFICIENT: // length is incomplete return PSYC_PARSE_DICT_INSUFFICIENT; case PARSE_ERROR: // no length state->part = PSYC_INDEX_PART_DICT; break; default: // should not be reached return PSYC_PARSE_INDEX_ERROR; } // fall thru case PSYC_INDEX_PART_DICT: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, idx, &state->elem_parsed)) { case PARSE_SUCCESS: if (idx->length == state->elem_parsed) ret = PSYC_PARSE_INDEX_DICT; else ret = PSYC_PARSE_INDEX_DICT_END; break; case PARSE_INCOMPLETE: if (idx->length == state->elem_parsed) ret = PSYC_PARSE_INDEX_DICT_START; else ret = PSYC_PARSE_INDEX_DICT_CONT; break; default: // should not be reached return PSYC_PARSE_INDEX_ERROR_DICT; } } else { switch (parse_until((ParseState*)state, '}', idx)) { case PARSE_SUCCESS: ret = PSYC_PARSE_INDEX_DICT; break; case PARSE_INSUFFICIENT: return PSYC_PARSE_INDEX_INSUFFICIENT; default: // should not be reached return PSYC_PARSE_INDEX_ERROR_DICT; } } state->part = PSYC_INDEX_PART_TYPE; state->cursor++; return ret; } return PSYC_PARSE_INDEX_ERROR; // should not be reached }
static inline #endif PsycParseUpdateRC psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value) { PsycParseIndexRC ret; if (state->cursor >= state->buffer.length) return PSYC_PARSE_UPDATE_END; state->startc = state->cursor; switch (state->part) { case PSYC_UPDATE_PART_START: value->length = 0; value->data = NULL; // fall thru case PSYC_INDEX_PART_TYPE: case PSYC_INDEX_PART_LIST: case PSYC_INDEX_PART_STRUCT: case PSYC_INDEX_PART_DICT_LENGTH: case PSYC_INDEX_PART_DICT: ret = psyc_parse_index((PsycParseIndexState*)state, value); switch (ret) { case PSYC_PARSE_INDEX_INSUFFICIENT: case PSYC_PARSE_INDEX_LIST_LAST: case PSYC_PARSE_INDEX_STRUCT_LAST: case PSYC_PARSE_INDEX_END: return PSYC_PARSE_UPDATE_INSUFFICIENT; case PSYC_PARSE_INDEX_ERROR_TYPE: if (state->buffer.data[state->cursor] != ' ') return ret; state->part = PSYC_PARSE_UPDATE_TYPE; value->length = 0; value->data = NULL; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_UPDATE_INSUFFICIENT); break; default: return ret; } case PSYC_UPDATE_PART_TYPE: if (!psyc_is_oper(state->buffer.data[state->cursor])) return PSYC_PARSE_UPDATE_ERROR_OPER; *oper = state->buffer.data[state->cursor]; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_UPDATE_END); switch (parse_keyword((ParseState*)state, value)) { case PARSE_SUCCESS: // end of keyword case PARSE_ERROR: // no keyword switch (state->buffer.data[state->cursor]) { case ':': state->part = PSYC_UPDATE_PART_LENGTH; break; case ' ': state->part = PSYC_UPDATE_PART_VALUE; break; default: return PSYC_PARSE_UPDATE_ERROR_TYPE; } state->cursor++; return PSYC_PARSE_UPDATE_TYPE; break; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_UPDATE_TYPE_END; default: // should not be reached return PSYC_PARSE_UPDATE_ERROR; } break; case PSYC_UPDATE_PART_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; value->length = state->elemlen; value->data = NULL; if (state->buffer.data[state->cursor] != ' ') return PSYC_PARSE_UPDATE_ERROR_LENGTH; state->part = PSYC_UPDATE_PART_VALUE; if (value->length == 0) return PSYC_PARSE_UPDATE_END; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_UPDATE_INSUFFICIENT); break; case PARSE_INSUFFICIENT: // length is incomplete if (value->length == 0) return PSYC_PARSE_UPDATE_END; return PSYC_PARSE_UPDATE_INSUFFICIENT; case PARSE_ERROR: // no length after : return PSYC_PARSE_UPDATE_ERROR_LENGTH; default: // should not be reached return PSYC_PARSE_UPDATE_ERROR; } // fall thru case PSYC_UPDATE_PART_VALUE: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, value, &state->elem_parsed)) { case PARSE_SUCCESS: if (value->length == state->elem_parsed) ret = PSYC_PARSE_UPDATE_VALUE; else ret = PSYC_PARSE_UPDATE_VALUE_END; break; case PARSE_INCOMPLETE: if (value->length == state->elem_parsed) ret = PSYC_PARSE_UPDATE_VALUE_START; else ret = PSYC_PARSE_UPDATE_VALUE_CONT; break; default: // should not be reached return PSYC_PARSE_UPDATE_ERROR_VALUE; } } else { value->data = state->buffer.data + state->cursor; value->length = state->buffer.length - state->cursor; ret = PSYC_PARSE_UPDATE_VALUE; } state->part = PSYC_INDEX_PART_TYPE; state->cursor++; return ret; } return PSYC_PARSE_INDEX_ERROR; // should not be reached }
/** * Parse dictionary. * * dict = [ type ] *dict-item * dict-item = "{" ( dict-key / length SP OCTET) "}" * ( type [ SP dict-value ] / [ length ] [ ":" type ] [ SP *OCTET ] ) * dict-key = %x00-7C / %x7E-FF ; any byte except "{" * dict-value = %x00-7A / %x7C-FF ; any byte except "}" */ PsycParseDictRC psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem) { ParseRC ret; if (state->cursor >= state->buffer.length) return PSYC_PARSE_DICT_END; state->startc = state->cursor; switch (state->part) { case PSYC_DICT_PART_START: type->length = elem->length = 0; type->data = elem->data = NULL; state->part = PSYC_DICT_PART_TYPE; // fall thru case PSYC_DICT_PART_TYPE: switch (parse_keyword((ParseState*)state, type)) { case PARSE_SUCCESS: // end of keyword state->part = PSYC_DICT_PART_KEY_START; return PSYC_PARSE_DICT_TYPE; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_DICT_END; case PARSE_ERROR: // no keyword state->part = PSYC_DICT_PART_KEY_START; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } // fall thru case PSYC_DICT_PART_KEY_START: if (state->buffer.data[state->cursor] != '{') return PSYC_PARSE_DICT_ERROR_KEY_START; type->length = elem->length = 0; type->data = elem->data = NULL; state->elem_parsed = 0; state->elemlen_found = 0; state->part = PSYC_DICT_PART_KEY_LENGTH; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_INSUFFICIENT); // fall thru case PSYC_DICT_PART_KEY_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; elem->length = state->elemlen; elem->data = NULL; if (state->buffer.data[state->cursor] != ' ') return PSYC_PARSE_DICT_ERROR_KEY_LENGTH; state->part = PSYC_DICT_PART_KEY; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); break; case PARSE_INSUFFICIENT: // length is incomplete return PSYC_PARSE_DICT_INSUFFICIENT; case PARSE_ERROR: // no length state->part = PSYC_DICT_PART_KEY; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } // fall thru case PSYC_DICT_PART_KEY: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, elem, &state->elem_parsed)) { case PARSE_SUCCESS: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_KEY; else ret = PSYC_PARSE_DICT_KEY_END; break; case PARSE_INCOMPLETE: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_KEY_START; else ret = PSYC_PARSE_DICT_KEY_CONT; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } else { switch (parse_until((ParseState*)state, '}', elem)) { case PARSE_SUCCESS: ret = PSYC_PARSE_DICT_KEY; break; case PARSE_INSUFFICIENT: return PSYC_PARSE_DICT_INSUFFICIENT; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } state->part = PSYC_DICT_PART_VALUE_START; state->startc = state->cursor; return ret; case PSYC_DICT_PART_VALUE_START: switch (state->buffer.data[state->cursor] != '}') return PSYC_PARSE_DICT_ERROR_VALUE_START; type->length = elem->length = 0; type->data = elem->data = NULL; state->elem_parsed = 0; state->elemlen_found = 0; state->part = PSYC_DICT_PART_VALUE_TYPE; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); // fall thru case PSYC_DICT_PART_VALUE_TYPE: if (state->buffer.data[state->cursor] == '=') { ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); switch (parse_keyword((ParseState*)state, type)) { case PARSE_SUCCESS: switch (state->buffer.data[state->cursor]) { case ':': state->part = PSYC_DICT_PART_VALUE_LENGTH; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); break; case ' ': state->part = PSYC_DICT_PART_VALUE; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); goto PSYC_DICT_PART_VALUE; case '{': state->part = PSYC_DICT_PART_KEY_START; return PSYC_PARSE_DICT_VALUE; break; default: return PSYC_PARSE_DICT_ERROR_VALUE_TYPE; } break; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_DICT_VALUE_LAST; case PARSE_ERROR: return PSYC_PARSE_DICT_ERROR_VALUE_TYPE; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } // fall thru case PSYC_DICT_PART_VALUE_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; elem->length = state->elemlen; elem->data = NULL; break; case PARSE_INSUFFICIENT: // length is incomplete return PSYC_PARSE_DICT_INSUFFICIENT; case PARSE_ERROR: // no length break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } switch (state->buffer.data[state->cursor]) { case ' ': state->part = PSYC_DICT_PART_VALUE; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); break; case '{': state->part = PSYC_DICT_PART_KEY_START; return PSYC_PARSE_DICT_VALUE; default: return PSYC_PARSE_DICT_ERROR_VALUE_LENGTH; } // fall thru case PSYC_DICT_PART_VALUE: PSYC_DICT_PART_VALUE: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, elem, &state->elem_parsed)) { case PARSE_SUCCESS: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_VALUE; else ret = PSYC_PARSE_DICT_VALUE_END; break; case PARSE_INCOMPLETE: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_VALUE_START; else ret = PSYC_PARSE_DICT_VALUE_CONT; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } else { switch (parse_until((ParseState*)state, '{', elem)) { case PARSE_SUCCESS: ret = PSYC_PARSE_DICT_VALUE; break; case PARSE_INSUFFICIENT: return PSYC_PARSE_DICT_VALUE_LAST; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } state->part = PSYC_DICT_PART_KEY_START; return ret; } return PSYC_PARSE_DICT_ERROR; // should not be reached }
static inline #endif PsycParseRC psyc_parse (PsycParseState *state, char *oper, PsycString *name, PsycString *value) { #ifdef DEBUG if (state->flags & PSYC_PARSE_ROUTING_ONLY && state->flags & PSYC_PARSE_START_AT_CONTENT) PP(("Invalid flag combination")); #endif ParseRC ret; // a return value size_t pos = state->cursor; // a cursor position // Start position of the current line in the buffer // in case we return insufficent, we rewind to this position. state->startc = state->cursor; if (state->flags & PSYC_PARSE_START_AT_CONTENT && (state->buffer.length == 0 || state->cursor >= state->buffer.length - 1)) return PSYC_PARSE_COMPLETE; // First we test if we can access the first char. if (state->cursor >= state->buffer.length) // Cursor is not inside the length. return PSYC_PARSE_INSUFFICIENT; switch (state->part) { case PSYC_PART_RESET: // New packet starts here, reset state. state->value_parsed = 0; state->valuelen = 0; state->valuelen_found = 0; state->routinglen = 0; state->content_parsed = 0; state->contentlen = 0; state->contentlen_found = 0; state->part = PSYC_PART_ROUTING; // fall thru case PSYC_PART_ROUTING: if (state->routinglen > 0) { if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_MOD_NL; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } // Each line of the header starts with a glyph, // i.e. :_name, -_name +_name etc, // so just test if the first char is a glyph. if (psyc_is_oper(state->buffer.data[state->cursor])) { // it is a glyph, so a variable starts here ret = psyc_parse_modifier(state, oper, name, value); state->routinglen += state->cursor - pos; return ret == PARSE_SUCCESS ? PSYC_PARSE_ROUTING : ret; } else { // not a glyph state->part = PSYC_PART_LENGTH; state->startc = state->cursor; // fall thru } case PSYC_PART_LENGTH: // End of header, content starts with an optional length then a NL if (psyc_is_numeric(state->buffer.data[state->cursor])) { state->contentlen_found = 1; state->contentlen = 0; do { state->contentlen = 10 * state->contentlen + state->buffer.data[state->cursor] - '0'; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } while (psyc_is_numeric(state->buffer.data[state->cursor])); } if (state->buffer.data[state->cursor] == '\n') { // start of content // If we need to parse the header only and we know the content length, // then skip content parsing. if (state->flags & PSYC_PARSE_ROUTING_ONLY) { state->part = PSYC_PART_DATA; if (++(state->cursor) >= state->buffer.length) return PSYC_PARSE_INSUFFICIENT; goto PSYC_PART_DATA; } else state->part = PSYC_PART_CONTENT; } else { // Not start of content, this must be the end. // If we have a length then it should've been followed by a \n if (state->contentlen_found) return PSYC_PARSE_ERROR_LENGTH; state->part = PSYC_PART_END; goto PSYC_PART_END; } state->startc = state->cursor + 1; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); // fall thru case PSYC_PART_CONTENT: // In case of an incomplete binary variable resume parsing it. if (state->value_parsed < state->valuelen) { ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed); state->content_parsed += value->length; if (ret == PARSE_INCOMPLETE) return PSYC_PARSE_ENTITY_CONT; return PSYC_PARSE_ENTITY_END; } pos = state->cursor; if (state->content_parsed > 0) { if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_MOD_NL; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } // Each line of the header starts with a glyph, // i.e. :_name, -_name +_name etc. // So just test if the first char is a glyph. // In the body, the same applies, only that the // method does not start with a glyph. if (psyc_is_oper(state->buffer.data[state->cursor])) { if (state->content_parsed == 0) { ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); if (state->buffer.data[state->cursor] == '\n') { *oper = *(state->buffer.data + state->cursor - 1); switch (*oper) { case PSYC_STATE_RESYNC: state->content_parsed++; return PSYC_PARSE_STATE_RESYNC; case PSYC_STATE_RESET: state->content_parsed++; return PSYC_PARSE_STATE_RESET; default: return PSYC_PARSE_ERROR_MOD_NAME; } } state->cursor--; } ret = psyc_parse_modifier(state, oper, name, value); state->content_parsed += state->cursor - pos; if (ret == PARSE_INCOMPLETE) return PSYC_PARSE_ENTITY_START; else if (ret == PARSE_SUCCESS) return PSYC_PARSE_ENTITY; return ret; } else { state->content_parsed += state->cursor - pos; state->startc = state->cursor; state->part = PSYC_PART_METHOD; // fall thru } case PSYC_PART_METHOD: pos = state->cursor; ret = parse_keyword((ParseState*)state, name); if (ret == PARSE_INSUFFICIENT) return ret; else if (ret == PARSE_SUCCESS) { // The method ends with a \n then the data follows. if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_METHOD; state->valuelen_found = 0; state->value_parsed = 0; state->valuelen = 0; if (state->contentlen_found) { // len found, set start position to the beginning of data. state->cursor++; state->startc = state->cursor; state->content_parsed += state->cursor - pos; state->part = PSYC_PART_DATA; } else { // Otherwise keep it at the beginning of method. ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } } else { // No method, which means the packet should end now. state->part = PSYC_PART_END; state->startc = state->cursor; goto PSYC_PART_END; } // fall thru case PSYC_PART_DATA: PSYC_PART_DATA: value->data = state->buffer.data + state->cursor; value->length = 0; if (state->contentlen_found) { // We know the length of the packet. if (!state->valuelen_found) { // start of data state->valuelen_found = 1; state->valuelen = state->contentlen - state->content_parsed; if (state->valuelen && !(state->flags & PSYC_PARSE_ROUTING_ONLY)) state->valuelen--; // \n at the end is not part of data } if (state->value_parsed < state->valuelen) { ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed); state->content_parsed += value->length; if (ret == PARSE_INCOMPLETE) return state->value_parsed == value->length ? PSYC_PARSE_BODY_START : PSYC_PARSE_BODY_CONT; } state->part = PSYC_PART_END; return state->valuelen == value->length ? PSYC_PARSE_BODY : PSYC_PARSE_BODY_END; } else { // Search for the terminator. size_t datac = state->cursor; // start of data if (state->flags & PSYC_PARSE_ROUTING_ONLY) // in routing-only mode restart state->startc = datac; // from the start of data while (1) { uint8_t nl = state->buffer.data[state->cursor] == '\n'; // check for |\n if we're at the start of data or we have found a \n if (state->cursor == datac || nl) { // incremented cursor inside length? if (state->cursor + 1 + nl >= state->buffer.length) { state->cursor = state->startc; return PSYC_PARSE_INSUFFICIENT; } if (state->buffer.data[state->cursor + nl] == '|' && state->buffer.data[state->cursor + 1 + nl] == '\n') { // packet ends here if (state->flags & PSYC_PARSE_ROUTING_ONLY) value->length++; state->content_parsed += state->cursor - pos; state->cursor += nl; state->part = PSYC_PART_END; return PSYC_PARSE_BODY; } } value->length++; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } } case PSYC_PART_END: PSYC_PART_END: // if data was not empty next is the \n at the end of data if (state->contentlen_found && state->valuelen_found && state->valuelen && !(state->flags & PSYC_PARSE_ROUTING_ONLY)) { state->valuelen = 0; state->valuelen_found = 0; if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_END; state->content_parsed++; state->cursor++; } // End of packet, at this point we have already passed a \n // and the cursor should point to | if (state->cursor + 1 >= state->buffer.length) return PSYC_PARSE_INSUFFICIENT; if (state->buffer.data[state->cursor] == '|' && state->buffer.data[state->cursor + 1] == '\n') { // Packet ends here. state->cursor += 2; state->part = PSYC_PART_RESET; return PSYC_PARSE_COMPLETE; } else { // Packet should've ended here, return error. state->part = PSYC_PART_RESET; return PSYC_PARSE_ERROR_END; } } return PSYC_PARSE_ERROR; // should not be reached }
/** * Parse simple or binary variable. * @return PARSE_ERROR or PARSE_SUCCESS */ static inline ParseRC psyc_parse_modifier (PsycParseState *state, char *oper, PsycString *name, PsycString *value) { *oper = *(state->buffer.data + state->cursor); ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); ParseRC ret = parse_keyword((ParseState*)state, name); if (ret == PARSE_ERROR) return PSYC_PARSE_ERROR_MOD_NAME; else if (ret != PARSE_SUCCESS) return ret; size_t length = 0; value->length = 0; state->valuelen = 0; state->valuelen_found = 0; state->value_parsed = 0; // Parse the value. // If we're in the content part check if it's a binary var. if (state->part == PSYC_PART_CONTENT && state->buffer.data[state->cursor] == ' ') { // binary arg // After SP the length follows. ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); if (psyc_is_numeric(state->buffer.data[state->cursor])) { state->valuelen_found = 1; do { length = 10 * length + state->buffer.data[state->cursor] - '0'; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } while (psyc_is_numeric(state->buffer.data[state->cursor])); state->valuelen = length; } else return PSYC_PARSE_ERROR_MOD_LEN; // After the length a TAB follows. if (state->buffer.data[state->cursor] != '\t') return PSYC_PARSE_ERROR_MOD_TAB; if (++(state->cursor) >= state->buffer.length) return length ? PARSE_INCOMPLETE : PARSE_SUCCESS; // if length=0 we're done ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed); if (ret == PARSE_INCOMPLETE) return ret; return PARSE_SUCCESS; } else if (state->buffer.data[state->cursor] == '\t') { // simple arg ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); value->data = state->buffer.data + state->cursor; while (state->buffer.data[state->cursor] != '\n') { value->length++; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } return PARSE_SUCCESS; } else return PSYC_PARSE_ERROR_MOD_TAB; }
struct replay_scenario* replay_scenario_read(FILE* in, const char* name, int* lineno) { char line[MAX_LINE_LEN]; char *parse; struct replay_scenario* scen = NULL; struct sldns_file_parse_state pstate; line[MAX_LINE_LEN-1]=0; memset(&pstate, 0, sizeof(pstate)); pstate.default_ttl = 3600; pstate.lineno = *lineno; while(fgets(line, MAX_LINE_LEN-1, in)) { parse=line; pstate.lineno++; (*lineno)++; while(isspace((unsigned char)*parse)) parse++; if(!*parse) continue; /* empty line */ if(parse_keyword(&parse, ";")) continue; /* comment */ if(parse_keyword(&parse, "SCENARIO_BEGIN")) { scen = make_scenario(parse); if(!scen) fatal_exit("%d: could not make scen", *lineno); continue; } if(!scen) fatal_exit("%d: expected SCENARIO", *lineno); if(parse_keyword(&parse, "RANGE_BEGIN")) { struct replay_range* newr = replay_range_read(parse, in, name, &pstate, line); if(!newr) fatal_exit("%d: bad range", pstate.lineno); *lineno = pstate.lineno; newr->next_range = scen->range_list; scen->range_list = newr; } else if(parse_keyword(&parse, "STEP")) { struct replay_moment* mom = replay_moment_read(parse, in, name, &pstate); if(!mom) fatal_exit("%d: bad moment", pstate.lineno); *lineno = pstate.lineno; if(scen->mom_last && scen->mom_last->time_step >= mom->time_step) fatal_exit("%d: time goes backwards", *lineno); if(scen->mom_last) scen->mom_last->mom_next = mom; else scen->mom_first = mom; scen->mom_last = mom; } else if(parse_keyword(&parse, "SCENARIO_END")) { struct replay_moment *p = scen->mom_first; int num = 0; while(p) { num++; p = p->mom_next; } log_info("Scenario has %d steps", num); return scen; } } replay_scenario_delete(scen); return NULL; }
/** * Parse the various attributes of an XML-styled config file entry */ LOCAL char* parseAttributes( tOptions* pOpts, char* pzText, tOptionLoadMode* pMode, tOptionValue* pType ) { size_t len; do { if (! IS_WHITESPACE_CHAR(*pzText)) switch (*pzText) { case '/': pType->valType = OPARG_TYPE_NONE; case '>': return pzText; default: case NUL: return NULL; } while (IS_WHITESPACE_CHAR(*++pzText)) ; len = 0; while (IS_LOWER_CASE_CHAR(pzText[len])) len++; switch (find_xat_attribute_id(pzText, len)) { case XAT_KWD_TYPE: pzText = parse_value(pzText+len, pType); break; case XAT_KWD_WORDS: pzText = parse_keyword(pOpts, pzText+len, pType); break; case XAT_KWD_MEMBERS: pzText = parse_set_mem(pOpts, pzText+len, pType); break; case XAT_KWD_COOKED: pzText += len; if (! IS_END_XML_TOKEN_CHAR(*pzText)) goto invalid_kwd; *pMode = OPTION_LOAD_COOKED; break; case XAT_KWD_UNCOOKED: pzText += len; if (! IS_END_XML_TOKEN_CHAR(*pzText)) goto invalid_kwd; *pMode = OPTION_LOAD_UNCOOKED; break; case XAT_KWD_KEEP: pzText += len; if (! IS_END_XML_TOKEN_CHAR(*pzText)) goto invalid_kwd; *pMode = OPTION_LOAD_KEEP; break; default: case XAT_KWD_INVALID: invalid_kwd: pType->valType = OPARG_TYPE_NONE; return skip_unkn(pzText); } } while (pzText != NULL); return pzText; }
/** * Parse the various attributes of an XML-styled config file entry * * @returns NULL on failure, otherwise the scan point */ LOCAL char const * parse_attrs(tOptions * opts, char const * txt, tOptionLoadMode * pMode, tOptionValue * pType) { size_t len = 0; for (;;) { len = (size_t)(SPN_LOWER_CASE_CHARS(txt) - txt); /* * The enumeration used in this switch is derived from this switch * statement itself. The "find_option_xat_attribute_cmd" function * will return XAT_CMD_MEMBERS for the "txt" string value * "members", etc. */ switch (find_option_xat_attribute_cmd(txt, len)) { case XAT_CMD_TYPE: txt = parse_value(txt+len, pType); break; case XAT_CMD_WORDS: txt = parse_keyword(opts, txt+len, pType); break; case XAT_CMD_MEMBERS: txt = parse_set_mem(opts, txt+len, pType); break; case XAT_CMD_COOKED: txt += len; if (! IS_END_XML_TOKEN_CHAR(*txt)) goto invalid_kwd; *pMode = OPTION_LOAD_COOKED; break; case XAT_CMD_UNCOOKED: txt += len; if (! IS_END_XML_TOKEN_CHAR(*txt)) goto invalid_kwd; *pMode = OPTION_LOAD_UNCOOKED; break; case XAT_CMD_KEEP: txt += len; if (! IS_END_XML_TOKEN_CHAR(*txt)) goto invalid_kwd; *pMode = OPTION_LOAD_KEEP; break; default: case XAT_INVALID_CMD: invalid_kwd: pType->valType = OPARG_TYPE_NONE; return skip_unkn(txt); } if (txt == NULL) return NULL; txt = SPN_WHITESPACE_CHARS(txt); switch (*txt) { case '/': pType->valType = OPARG_TYPE_NONE; /* FALLTHROUGH */ case '>': return txt; } if (! IS_LOWER_CASE_CHAR(*txt)) return NULL; } }
/** * Read a range from file. * @param remain: Rest of line (after RANGE keyword). * @param in: file to read from. * @param name: name to print in errors. * @param lineno: incremented as lines are read. * @param line: line buffer. * @param ttl: for readentry * @param or: for readentry * @param prev: for readentry * @return: range object to add to list, or NULL on error. */ static struct replay_range* replay_range_read(char* remain, FILE* in, const char* name, int* lineno, char* line, uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev) { struct replay_range* rng = (struct replay_range*)malloc( sizeof(struct replay_range)); off_t pos; char *parse; struct entry* entry, *last = NULL; if(!rng) return NULL; memset(rng, 0, sizeof(*rng)); /* read time range */ if(sscanf(remain, " %d %d", &rng->start_step, &rng->end_step)!=2) { log_err("Could not read time range: %s", line); free(rng); return NULL; } /* read entries */ pos = ftello(in); while(fgets(line, MAX_LINE_LEN-1, in)) { (*lineno)++; parse = line; while(isspace((int)*parse)) parse++; if(!*parse || *parse == ';') { pos = ftello(in); continue; } if(parse_keyword(&parse, "ADDRESS")) { while(isspace((int)*parse)) parse++; strip_end_white(parse); if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) { log_err("Line %d: could not read ADDRESS: %s", *lineno, parse); free(rng); return NULL; } pos = ftello(in); continue; } if(parse_keyword(&parse, "RANGE_END")) { return rng; } /* set position before line; read entry */ (*lineno)--; fseeko(in, pos, SEEK_SET); entry = read_entry(in, name, lineno, ttl, or, prev, 1); if(!entry) fatal_exit("%d: bad entry", *lineno); entry->next = NULL; if(last) last->next = entry; else rng->match = entry; last = entry; pos = ftello(in); } replay_range_delete(rng); return NULL; }