scanstate* readmem_init(scanstate *ss, const char *data, size_t len) { scanstate_init(ss, data, len); ss->limit = ss->bufptr + ss->bufsiz; ss->read = readmem_read; return ss; }
compare_result compare(FILE *fp1, FILE *fp2, int brief) { // NOTE!! // This code is meant to be simple so I take shortcuts like // exiting without cleaning up. Sorry. char buf1[39], buf2[8]; // these sizes are totally arbitrary scanstate ssrec, *ss=&ssrec; int n, cont; scanstate_init(ss, buf1, sizeof(buf1)); readfp_attach(ss, fp1); compare_attach(ss); do { n = fread(buf2, 1, sizeof(buf2), fp2); if(n <= 0) { if(ferror(fp2)) { fprintf(stderr, "Error reading second file.\n"); exit(17); } if(feof(fp2)) { break; } } cont = compare_continue(ss, buf2, n); if(cont < 0) { fprintf(stderr, "Error reading first file.\n"); exit(17); } } while(cont == 0); return brief ? compare_check(ss) : compare_check_newlines(ss); }
static void test_analyze_results(struct test *test, int *stdo, int *stde) { scanstate scanner; char scanbuf[BUFSIZ]; *stdo = *stde = -1; if(was_aborted(test->status)) { test_failures++; return; } if(was_disabled(test->status)) { return; } if(test->status == test_has_failed) { test_failures++; return; } if(!was_started(test->status)) { test_failures++; return; } test->stdout_match = match_unknown; test->stderr_match = match_unknown; scanstate_init(&scanner, scanbuf, sizeof(scanbuf)); scan_sections(test, &test->testscanner, parse_section_compare, &scanner); assert(test->stdout_match != match_inprogress); assert(test->stderr_match != match_inprogress); if(test->stdout_match == match_unknown) { test->stdout_match = (fd_has_data(test, test->outfd) ? match_no : match_yes); } if(test->stderr_match == match_unknown) { test->stderr_match = (fd_has_data(test, test->errfd) ? match_no : match_yes); } *stdo = (test->stdout_match != match_yes); *stde = (test->stderr_match != match_yes); if(!*stdo && !*stde && !test->exitsignal) { test_successes++; } else { test_failures++; } }
int main(int argc, char **argv) { const char *filename; scanstate scanner, *ss = &scanner; char buffer[BUFSIZ]; int token; FILE *fp; filename = argv[1]; if(filename == NULL) { fprintf(stderr, "You must supply the file to open!\n"); exit(1); } fp = fopen(filename, "r"); if(!fp) { fprintf(stderr, "Could not open file %s\n", filename); exit(1); } // Create the scanner scanstate_init(ss, buffer, sizeof(buffer)); readfp_attach(ss, fp); // attach the readproc scanner_attach(ss); // attach the scanner do { token = scan_next_token(ss); if(token < 0) { printf("Scanner's readproc returned an error: %d\n", token); break; } process_token(filename, ss->line, token, scan_token_start(ss), scan_token_length(ss)); } while(token); // No need to deallocate the scanner because everything // was allocated on the stack. fclose(fp); return 0; }
scanstate* dynscan_create(size_t bufsiz) { scanstate *ss; char *bufptr; ss = malloc(sizeof(scanstate)); if(!ss) { return NULL; } if(bufsiz) { bufptr = malloc(bufsiz); if(!bufptr) { free(ss); return NULL; } } else { bufptr = 0; } scanstate_init(ss, bufptr, bufsiz); return ss; }
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); } }