-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoption.c
More file actions
160 lines (144 loc) · 3.76 KB
/
Copy pathoption.c
File metadata and controls
160 lines (144 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "option.h"
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "expr.h"
#include "setter.h"
#include "slow.h"
#include "strtable.h"
#include "symtable.h"
#include "text.h"
#include "y_tab.h"
#define N_OPTS 16
struct option* active[N_OPTS];
int n_opts = 0;
struct option* create_option(int text, struct action* actions) {
struct option* option = malloc(sizeof(struct option));
if (!option) {
perror("create_option: malloc");
exit(errno);
}
option->text = text;
option->short_txt = -1;
option->actions = actions;
/* find and cache the action texts */
for (; actions != NULL; actions = actions->next) {
if (option->short_txt < 0 && actions->type == SHORT) {
option->short_txt = actions->arg.short_str;
}
if (option->text < 0 && actions->type == TEXT) {
option->text = actions->arg.text_str;
actions->arg.text_str = -1;
}
if (option->short_txt >= 0 && option->text >= 0) {
break;
}
}
return option;
}
void free_option(struct option* option) {
if (!option)
return;
free_option(option->next);
free_action(option->actions);
free(option);
}
void add_options(struct option* options) {
if (!options || n_opts >= N_OPTS)
return;
active[n_opts++] = options;
add_options(options->next);
}
void clear_options() {
n_opts = 0;
}
int option_count() {
return n_opts;
}
/* returns 1 if haystack contains needle, 2 if strings are the same; else 0 */
int str_match(const char* haystack, const char* needle) {
const char* hptr = haystack, *nptr = needle, *ptr = NULL;
while (*hptr && *nptr) {
if (toupper(*hptr) == toupper(*nptr)) {
if (!ptr)
ptr = hptr;
nptr++;
} else {
nptr = needle;
ptr = NULL;
}
hptr++;
}
if (*nptr) {
return 0; /* no match */
}
if (ptr == haystack && !*hptr) { /* exact match */
return 2;
}
return 1;
}
void exec_option(struct option* opt) {
print_text("> ");
print_text(get_string(opt->text));
print_text("\n");
wait(3);
exec_actions(opt->actions);
}
/* 2 on exact match of short or long texts,
* 1 on partial match of either,
* 0 on no match */
int eval_option(struct option* opt, const char* input) {
int t_match = str_match(get_string(opt->text), input);
if (t_match < 2) {
int s_match = str_match(get_string(opt->short_txt), input);
return t_match > s_match ? t_match : s_match;
}
return t_match;
}
void print_option(struct option* opt) {
int text = opt->short_txt >= 0 ? opt->short_txt : opt->text;
printf("%s\n", get_string(text));
}
int eval_options(const char* input) {
struct option* matched[N_OPTS];
int n_matched = 0, i;
if (input[0] != '\0') {
for(i = 0; i < n_opts; i++) {
int match = eval_option(active[i], input);
if (match > 1) {
exec_option(active[i]);
return 1;
} else if (match > 0) {
matched[n_matched++] = active[i];
}
}
} else if (n_opts == 1) {
exec_option(active[0]);
return 1;
}
if (n_matched == 1) {
exec_option(matched[0]);
#ifdef DEBUG
dump_syms();
#endif
return 1;
} else {
struct option** list;
int n;
if (n_matched > 1) {
printf("Which?\n");
list = matched;
n = n_matched;
} else {
printf("Options:\n");
list = active;
n = n_opts;
}
for (i = 0; i < n; i++) {
print_option(list[i]);
}
}
return 0;
}