summaryrefslogtreecommitdiffstats
path: root/fcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fcomp.c')
-rw-r--r--fcomp.c108
1 files changed, 96 insertions, 12 deletions
diff --git a/fcomp.c b/fcomp.c
index f4715f5..33944eb 100644
--- a/fcomp.c
+++ b/fcomp.c
@@ -21,7 +21,9 @@
#include "stdio.h"
#include "string.h"
#include "getopt.h"
+#include "unistd.h"
#include "ctype.h"
+#include "linenoise.h"
typedef struct slist {
char **s;
@@ -49,12 +51,14 @@ static int fuz(const char *str, const char *c);
/**
* stats for debugging */
typedef struct stats {
+ unsigned int discarded;
char *search_results;
char *tok_results;
char *unique_results;
} stats;
static stats st = {
+ 0,
NULL,
NULL,
NULL
@@ -71,6 +75,9 @@ typedef struct config {
int lisp_print; /** 0: off 1: on */
int print_count; /** 0: off 1: on */
int print_all; /** 0: off 1: on */
+ int interactive; /** 0: off 1: on */
+ int prompt; /** 0: off 1: on */
+ int filestream; /** 0: off 1: on */
char *file;
char *query;
unsigned int min_word_size;
@@ -93,6 +100,9 @@ static config cfg = {
0,
0,
0,
+ 0,
+ 1,
+ 0,
NULL,
NULL,
3,
@@ -153,6 +163,10 @@ static void print_help(char *argv0)
"Show debug information");
fprintf(stderr, "%8s %4s %15s %50s\n", "-s", "", "stats",
"Print some stats");
+ fprintf(stderr, "%8s %4s %15s %50s\n", "-I", "", "interactive",
+ "Run with interactive query input");
+ fprintf(stderr, "%8s %4s %15s %50s\n", "", "", "",
+ "(Pass it twice to disable prompt)");
}
static void print_cfg()
@@ -184,6 +198,7 @@ static void print_cfg()
static void print_stats()
{
fprintf(stderr, "\nStats:\n~~~~~~\n");
+ fprintf(stderr, "Discarded chars:\t%d\n", st.discarded);
if (st.tok_results) {
fprintf(stderr, "%s", st.tok_results);
free(st.tok_results);
@@ -203,8 +218,19 @@ static int parse_cli(int argc, char *argv[])
if (argc < 2)
return -1;
char c;
- while ((c = getopt(argc, argv, "-hxzsadclrf:i:v:w:t:")) != -1) {
+ while ((c = getopt(argc, argv, "-hIF:xzsadclrf:i:v:w:t:")) != -1) {
switch (c) {
+ case 'I':
+ if (cfg.interactive) {
+ cfg.prompt = 0;
+ }
+ cfg.interactive = 1;
+ break;
+ case 'F':
+ cfg.stdin = 0;
+ cfg.filestream = 1;
+ cfg.file = optarg;
+ break;
case 'h':
cfg.help = 1;
break;
@@ -421,6 +447,7 @@ static void cfree(result * res)
free(res->tok[i]);
}
free(res->tok);
+ res->n = 0;
}
/**
@@ -433,6 +460,7 @@ static void sfree(slist * l)
}
if (l->s)
free(l->s);
+ l->n = 0;
}
/**
@@ -486,7 +514,7 @@ static int fuz(const char *str, const char *c)
/**
* Search an slist for @query and place the matches on @res
* The search method is in the config struct */
-static int search(slist * l, const char *query, slist * res)
+static int search(const slist * l, const char *query, slist * res)
{
int flag = 0;
for (unsigned int i = 0; i < l->n; i++) {
@@ -575,11 +603,12 @@ static void pc(const result * res)
static int tokenize(FILE * f, slist * l)
{
unsigned int n = 0;
- char c;
+ int c;
char *tmp = NULL;
while ((c = fgetc(f)) != EOF) {
if (!is_valid(c)) {
+ st.discarded++;
if (tmp) {
finalize_str(tmp, n, l);
free(tmp);
@@ -622,7 +651,7 @@ static void get_slist_stats(slist * l)
(char *)
malloc((strlen(tmp) + snprintf(NULL, 0, "%d", l->n) +
3) * sizeof(char));
- sprintf(st.tok_results, "%s\t%d\n", tmp, l->n);
+ sprintf(st.tok_results, "%s\t\t%d\n", tmp, l->n);
}
}
@@ -634,7 +663,7 @@ static void get_search_stats(slist * l)
(char *)
malloc((strlen(tmp) + snprintf(NULL, 0, "%d", l->n) +
3) * sizeof(char));
- sprintf(st.search_results, "%s\t%d\n", tmp, l->n);
+ sprintf(st.search_results, "%s\t\t%d\n", tmp, l->n);
}
}
@@ -646,12 +675,55 @@ static void get_result_stats(result * r)
(char *)
malloc((strlen(tmp) + snprintf(NULL, 0, "%d", r->n) +
3) * sizeof(char));
- sprintf(st.unique_results, "%s\t%d\n", tmp, r->n);
+ sprintf(st.unique_results, "%s\t\t%d\n", tmp, r->n);
+ }
+}
+
+void clean_stdin(void)
+{
+ int c;
+ do {
+ c = getchar();
+ } while (c != '\n' && c != EOF);
+}
+
+static void prompt(slist *l)
+{
+ int r = 0;
+ char p[20] = "";
+ char *tmp = NULL;
+ if (cfg.prompt) sprintf(p, "[%d]> ", r);
+ fflush(NULL);
+ while((tmp = linenoise(p)) != NULL) {
+ slist search_res = { 0 };
+ if (search(l, tmp, &search_res)) {
+ result count_res = { 0 };
+ /* sort the results */
+ qsort(&search_res.s[0], search_res.n, sizeof(char *),
+ cmpstringp);
+
+ /* count the unique */
+ count(&search_res, &count_res);
+ sort_by_count(&count_res);
+
+ r = count_res.n;
+ /* print them */
+ pc(&count_res);
+
+ cfree(&count_res);
+ }
+ if (cfg.prompt) sprintf(p, "[%d]> ", r);
+ r = 0;
+ free(search_res.s);
+ free(tmp);
+ tmp = NULL;
}
+ if (tmp) free(tmp);
}
int main(int argc, char *argv[])
{
+ int rc = 0;
FILE *f;
slist list = { 0 };
slist search_res = { 0 };
@@ -665,14 +737,20 @@ int main(int argc, char *argv[])
return -1;
}
- if (cfg.query == NULL && !cfg.print_all) {
+ if (cfg.query == NULL && !cfg.print_all && !cfg.interactive) {
fprintf(stderr, "Query missing ... terminating\n");
return -1;
}
/* set input */
if (cfg.stdin) {
+ if (cfg.interactive) {
+ fprintf(stderr, "Can't read from stdin in interactive mode.\n");
+ return -1;
+ }
f = stdin;
+ } else if (cfg.filestream) {
+ f = fmemopen(cfg.file, strlen(cfg.file), "r");
} else {
f = fopen(cfg.file, "r");
if (!f) {
@@ -680,14 +758,20 @@ int main(int argc, char *argv[])
return -1;
}
}
-
/* tokenize */
- if (tokenize(f, &list))
- goto err;
+ if (tokenize(f, &list)) {
+ rc = -1;
+ goto done;
+ }
if (cfg.stats)
get_slist_stats(&list);
+ if (cfg.interactive) {
+ prompt(&list);
+ goto done;
+ }
+
if (cfg.print_all) {
pp(&list);
} else {
@@ -721,8 +805,8 @@ int main(int argc, char *argv[])
if (cfg.stats)
print_stats();
- err:
+done:
sfree(&list);
fclose(f);
- return 0;
+ return rc;
}