bool Reader::has_next() { if (buff_written == 0) { return buffer_next() > 0; } return buff_written > 0; }
int Reader::skip_next() { int skipped = 0; if (buff_written == 0) { skipped = buffer_next(); if (skipped == -1) { return -1; } } else { skipped = buff_written; } //cerr << "SKIP " << buff << endl; buffer_clear(); return skipped; }
int main(int argc, char** argv) { // read all used flags while (1) { static struct option long_options[] = { {"invert-match", no_argument, 0, 'v'}, {"line-regexp", no_argument, 0, 'x'}, {"count", no_argument, 0, 'c'}, {"help", no_argument, &display_help, 1}, {"version", no_argument, 0, 'V'}, {"cache-limit", required_argument, 0, OPTION_CACHE_LIMIT}, {0, 0, 0, 0} }; int option_index = 0; int c = getopt_long(argc, argv, "vxcV", long_options, &option_index); if (c == -1) break; switch (c) { case 'v': invert_match = true; break; case 'x': whole_lines = true; break; case 'c': count_matches = true; break; case OPTION_CACHE_LIMIT: cache_mem_limit = parse_size_in_kb(optarg); if (cache_mem_limit == -1U) { print_usage(argv[0]); return 2; } break; case 'V': display_version = true; break; case 0: break; default: print_usage(argv[0]); return 2; } } if (display_help) { printf(help_message, argv[0]); return 0; } if (display_version) { printf(version_message); return 0; } // check if there is exactly one regular expression if (optind != argc-1) { print_usage(argv[0]); return 2; } char* regex = argv[optind]; // parse the regular expression to abstract syntax tree struct syntree* tree; tree = parse(regex, strlen(regex)); // build nfa for the regular expression struct nfa* nfa; nfa = build_nfa(tree, whole_lines); free_tree(tree); // initialize simulation state sim_init(&state, nfa, invert_match, cache_mem_limit); // initialize buffer uintptr_t buffer_size = 65536; buffer_init(&buffer, STDIN_FILENO, STDOUT_FILENO, buffer_size); // main matching loop uintmax_t match_count = 0; bool new_line = true; bool some_match = false; intptr_t res = buffer_next(&buffer); if (!count_matches) buffer_mark(&buffer); while (res == 1) { // save next input byte to ch uint_fast8_t ch = buffer_get(&buffer); if (ch == '\n') { // handle the end of line here new_line = true; // simulate the special line end character if (!state.dfa_state->accept) sim_step(&state, CHAR_INPUT_END); if (sim_is_match(&state)) { // the last line matched, either print it or count it some_match = true; if (count_matches) { ++match_count; } else { int_fast8_t res = buffer_print(&buffer, true); if (res != 1) die(2, (res == -1) ? errno : 0, "Error writing to stdout"); } } // reset simulation state state.dfa_state = state.after_begin; // read next character from input res = buffer_next(&buffer); if (!count_matches) buffer_mark(&buffer); } else { new_line = false; // simulate only if there was no match on the current line if (!state.dfa_state->accept) { // if the character is not valid ASCII, no transitions will take place if (ch > MAX_CHAR) state.dfa_state = state.before_begin; // otherwise do the simulation else sim_step(&state, ch); } // read next character from input res = buffer_next(&buffer); } } if (res == -1) die(2, errno, "Error reading from stdin"); // check if there is no \n at the end of the input // if it is the case, behave as if it was there if (!new_line) { if (!state.dfa_state->accept) sim_step(&state, CHAR_INPUT_END); if (sim_is_match(&state)) { some_match = true; if (count_matches) { ++match_count; } else { int_fast8_t res = buffer_print(&buffer, false); puts(""); if (res != 1) die(2, (res == -1) ? errno : 0, "Error writing to stdout"); } } } // if -c is used, print the count of matches if (count_matches) { printf("%" PRIuMAX "\n", match_count); } // clean up buffer_cleanup(&buffer); sim_cleanup(&state); free_nfa(nfa); // return status is based on whether there was a match or not return some_match ? 0 : 1; }
void cmd_exit (char *cp) { const char *bn, *fn, *ynanswer; Buffer *buffer; int prompt, saveflag, ynflag; String *ynstring; /* Check for -save qualifier - it inhibits deleting the journal file */ saveflag = 0; if ((strncasecmp (cp, "-save", 5) == 0) && (cp[5] <= ' ')) { if ((journal_name == NULL) || (journal_name[0] == 0)) { outerr (0, "there is no journal file to save\n"); return; } saveflag = 1; cp = skipspaces (cp + 5); } /* Maybe use a different name for main buffer */ if (*cp != 0) buffer_setfile (main_buffer, cp); /* Don't bother if recovery mode, we want them to be able to do more. They can re-type exit command */ if (recover_file != NULL) { outerr (0, "EXIT command ignored in recovery mode\n"); return; } /* Check for buffers that have filename of "" (opened -readonly) but were modified */ prompt = 0; for (buffer = NULL; (buffer = buffer_next (buffer)) != NULL;) { fn = buffer_filename (buffer); if (fn == NULL) continue; if (fn[0] != 0) continue; if (buffer_dirty (buffer, -1)) { bn = buffer_name (buffer); if (!prompt) outerr (0, "\n"); outerr (strlen (bn), "buffer %s was modified but has no output file\n", bn); prompt = 1; } } if (prompt) { do { ynstring = jnl_readprompt ("\r\n do you still want to exit (yes or no)? "); if (ynstring == NULL) return; ynflag = -1; ynanswer = string_getval (ynstring); if (strcasecmp (ynanswer, "no") == 0) ynflag = 0; if (strcasecmp (ynanswer, "yes") == 0) ynflag = 1; string_delete (ynstring); } while (ynflag < 0); if (!ynflag) return; } /* Write the entire contents of all the buffers that have files and that have been modified to their respective files */ for (buffer = NULL; (buffer = buffer_next (buffer)) != NULL;) { fn = buffer_filename (buffer); /* get output filename */ if (fn == NULL) continue; /* if none, don't try to write */ bn = buffer_name (buffer); /* ok, write it out */ if (!buffer_dirty (buffer, -1)) { outerr (strlen (fn) + strlen (bn), "not writing %s from =%s because it is unmodified\n", fn, bn); continue; } outerr (strlen (fn) + strlen (bn), "writing %s from =%s: ", fn, bn); if (!write_file (fn, buffer_first_line (buffer), buffer_last_line (buffer))) { outerr (strlen (fn), "output file %s not written, not exiting\n", fn); /* if error, don't exit */ return; } buffer_dirty (buffer, 0); } /* Write successful, maybe delete journal file and terminate process */ jnl_close (!saveflag); output (); exit (0); }
void cmd_show (char *cp) { char c, curbf, dirty, *p; const char *fname, *name; int l, rf; Buffer *buffer; uLong lines; if (*cp == 0) goto usage; do { p = uptospace (cp); /* Show buffer info */ if (strncasecmp ("buffers", cp, p - cp) == 0) { outfmt (0, "\nBuffers:\n"); l = 0; for (buffer = NULL; (buffer = buffer_next (buffer)) != NULL;) { name = buffer_name (buffer); if (strlen (name) > l) l = strlen (name); } for (buffer = NULL; (buffer = buffer_next (buffer)) != NULL;) { name = buffer_name (buffer); fname = buffer_filename (buffer); lines = buffer_linecount (buffer); rf = (buffer_getreadfile (buffer) != NULL); curbf = (buffer == cur_position.buffer) ? '>' : ' '; dirty = buffer_dirty (buffer, -1) ? '*' : ' '; outfmt (strlen (name) + 16, " %c %c %*.*s: %5u%c line%c", curbf, dirty, l, l, name, lines, rf ? '+' : ' ', (lines == 1) ? ' ' : 's'); if (fname != NULL) outfmt (strlen (fname), " => %s", fname); if (buffer == main_buffer) outstr (" (main buffer)"); outchr ('\n'); } continue; } /* Show info about files */ if (strncasecmp ("files", cp, p - cp) == 0) { outfmt (0, "\nFiles:\n"); outfmt (strlen (help_name), " Help: %s\n", help_name); outfmt (strlen (journal_name), " Journal: %s\n", journal_name[0] == 0 ? "<none>" : journal_name); continue; } /* Show keypad definitions */ if (strncasecmp ("keypad", cp, p - cp) == 0) { show_keypad (); continue; } goto usage; } while (*(cp = skipspaces (p)) != 0); return; usage: outerr (0, "specify BUFFERS, FILES, KEYPAD\n"); }