std::pair<std::string, std::string> shade::formatter::get_next_token(const std::string& code) { std::string::size_type token_begin(code.find('<')); if (token_begin != 0) { if (token_begin == std::string::npos) return std::make_pair(code, std::string()); return std::make_pair(std::string(code, 0, token_begin), std::string(code, token_begin, std::string::npos)); } std::string::size_type token_end(code.find('>')); if (token_end == std::string::npos) { return std::make_pair(code, std::string()); } return std::make_pair(std::string(code, 0, token_end+1), std::string(code, token_end+1, std::string::npos)); }
void scan_status_file(struct test *test) { char lastfile[PATH_MAX]; int lastfile_good = 0; char buf[BUFSIZ]; scanstate ss; int tok; int state = 0; // first rewind the status file if(lseek(test->statusfd, 0, SEEK_SET) < 0) { test_abort(test, "read_file lseek on status file: %s\n", strerror(errno)); } // then create our scanner scanstate_init(&ss, buf, sizeof(buf)); readfd_attach(&ss, test->statusfd); stscan_attach(&ss); // now, if we see the token "CBRUNNING" in the token stream, // it means that we attempted to start the test. If not, // then the test bailed early. do { tok = scan_next_token(&ss); // look for errors... if(tok < 0) { test_abort(test, "Error %d pulling status tokens: %s\n", tok, strerror(errno)); } else if(tok == stGARBAGE) { fprintf(stderr, "Garbage on line %d in the status file: '%.*s'\n", ss.line, (int)token_length(&ss)-1, token_start(&ss)); } else { state = tok; } switch(tok) { case stSTART: // nothing to do break; case stCONFIG: if(test->status == test_pending) { test->num_config_files += 1; if(copy_status_arg(token_start(&ss), token_end(&ss), lastfile, sizeof(lastfile))) { lastfile_good = 1; } else { fprintf(stderr, "CONFIG needs arg on line %d of the status file: '%.*s'\n", ss.line, (int)token_length(&ss)-1, token_start(&ss)); } } else { fprintf(stderr, "CONFIG but status (%d) wasn't pending on line %d of the status file: '%.*s'\n", test->status, ss.line, (int)token_length(&ss)-1, token_start(&ss)); } break; case stPREPARE: // nothing to do break; case stRUNNING: if(test->status == test_pending) { test->status = test_was_started; if(strlen(test->testfile) < sizeof(lastfile)) { strcpy(lastfile, test->testfile); lastfile_good = 1; } else { fprintf(stderr, "RUNNING lastfile is not big enough for %s", test->testfile); } } else { fprintf(stderr, "RUNNING but status (%d) wasn't pending on line %d of the status file: '%.*s'\n", test->status, ss.line, (int)token_length(&ss)-1, token_start(&ss)); } break; case stDONE: if(test->status == test_was_started) { test->status = test_was_completed; } else { fprintf(stderr, "DONE but status (%d) wasn't RUNNING on line %d of the status file: '%.*s'\n", test->status, ss.line, (int)token_length(&ss)-1, token_start(&ss)); } break; case stABORTED: test->status = (test->status >= test_was_started ? test_was_aborted : config_was_aborted); test->status_reason = dup_status_arg(token_start(&ss), token_end(&ss)); break; case stDISABLED: test->status = (test->status >= test_was_started ? test_was_disabled : config_was_disabled); test->status_reason = dup_status_arg(token_start(&ss), token_end(&ss)); break; default: fprintf(stderr, "Unknown token (%d) on line %d of the status file: '%.*s'\n", tok, ss.line, (int)token_length(&ss)-1, token_start(&ss)); } } while(!scan_is_finished(&ss)); if(lastfile_good) { test->last_file_processed = strdup(lastfile); } }