Libecoli 0.11.1
Extensible COmmand LIne library
Loading...
Searching...
No Matches
extension-editline/main.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2025, Olivier MATZ <zer0@droids-corp.org>
3 */
4
35
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41#include <ecoli.h>
42
43#define ID_BOOL_TUPLE "id_bool_tuple"
44
45/* stop program when true */
46static bool done;
47
48static int convert_cb(const struct ec_pnode *parse)
49{
50 const char *bool_tuple;
51 const char *next_false;
52 const char *next_true;
53 unsigned int val = 0;
54 const char *t;
55
56 bool_tuple = ec_strvec_val(ec_pnode_get_strvec(ec_pnode_find(parse, ID_BOOL_TUPLE)), 0);
57 t = bool_tuple;
58
59 /* convert bool tuple into an integer */
60 while (1) {
61 next_true = strstr(t, "true");
62 next_false = strstr(t, "false");
63
64 if (next_true && (next_false == NULL || next_false > next_true)) {
65 val = (val << 1) | 1;
66 t = next_true + 1;
67 } else if (next_false && (next_true == NULL || next_true > next_false)) {
68 val = val << 1;
69 t = next_false + 1;
70 } else {
71 break;
72 }
73 }
74 printf("Integer value for %s is %u\n", bool_tuple, val);
75
76 return 0;
77}
78
79static int exit_cb(const struct ec_pnode *parse)
80{
81 (void)parse;
82
83 printf("Exit !\n");
84 done = true;
85
86 return 0;
87}
88
89static int check_exit(void *opaque)
90{
91 (void)opaque;
92 return done;
93}
94
95static struct ec_node *create_commands(void)
96{
97 struct ec_node *cmdlist = NULL, *cmd = NULL;
98 int ret;
99
100 /* the top node containing the list of commands */
101 cmdlist = ec_node("or", EC_NO_ID);
102 if (cmdlist == NULL)
103 goto fail;
104
105 /* the convert command */
106 cmd = EC_NODE_SEQ(
107 EC_NO_ID, ec_node_str(EC_NO_ID, "convert"), ec_node("bool_tuple", ID_BOOL_TUPLE)
108 );
109 if (cmd == NULL)
110 goto fail;
111 if (ec_interact_set_callback(cmd, convert_cb) < 0)
112 goto fail;
113 if (ec_interact_set_help(cmd, "Convert a tuple of boolean into its integer representation")
114 < 0)
115 goto fail;
117 ec_node_find(cmd, ID_BOOL_TUPLE),
118 "A tuple of booleans. Example: \"(true,false,true)\""
119 )
120 < 0)
121 goto fail;
122 ret = ec_node_or_add(cmdlist, cmd);
123 cmd = NULL; /* already freed, even on error */
124 if (ret < 0)
125 goto fail;
126
127 /* the exit command */
128 cmd = ec_node_str(EC_NO_ID, "exit");
129 if (ec_interact_set_callback(cmd, exit_cb) < 0)
130 goto fail;
131 if (ec_interact_set_help(cmd, "exit program") < 0)
132 goto fail;
133 ret = ec_node_or_add(cmdlist, cmd);
134 cmd = NULL; /* already freed, even on error */
135 if (ret < 0)
136 goto fail;
137
138 /* the lexer, added above the command list */
139 cmdlist = ec_node_sh_lex(EC_NO_ID, cmdlist);
140 if (cmdlist == NULL)
141 goto fail;
142
143 return cmdlist;
144
145fail:
146 fprintf(stderr, "cannot initialize nodes\n");
147 ec_node_free(cmdlist);
148 ec_node_free(cmd);
149 return NULL;
150}
151
152int main(void)
153{
154 struct ec_editline *editline = NULL;
155 struct ec_node *node = NULL;
156
157 if (ec_init() < 0) {
158 fprintf(stderr, "cannot init ecoli: %s\n", strerror(errno));
159 return 1;
160 }
161
162 node = create_commands();
163 if (node == NULL) {
164 fprintf(stderr, "failed to create commands: %s\n", strerror(errno));
165 goto fail;
166 }
167
168 editline = ec_editline("extension-editline", stdin, stdout, stderr, 0);
169 if (editline == NULL) {
170 fprintf(stderr, "Failed to initialize editline\n");
171 goto fail;
172 }
173
174 if (ec_editline_set_prompt(editline, "extension> ") < 0) {
175 fprintf(stderr, "Failed to set prompt\n");
176 goto fail;
177 }
178 ec_editline_set_node(editline, node);
179
180 if (ec_editline_interact(editline, check_exit, NULL) < 0)
181 goto fail;
182
183 ec_editline_free(editline);
184 ec_node_free(node);
185 return 0;
186
187fail:
188 ec_editline_free(editline);
189 ec_node_free(node);
190 return 1;
191}
int ec_editline_set_prompt(struct ec_editline *editline, const char *prompt)
struct ec_editline * ec_editline(const char *prog, FILE *f_in, FILE *f_out, FILE *f_err, enum ec_editline_init_flags flags)
void ec_editline_free(struct ec_editline *editline)
int ec_editline_interact(struct ec_editline *editline, ec_editline_check_exit_cb_t check_exit_cb, void *opaque)
int ec_editline_set_node(struct ec_editline *editline, const struct ec_node *node)
int ec_init(void)
int ec_interact_set_help(struct ec_node *node, const char *help)
int ec_interact_set_callback(struct ec_node *node, ec_interact_command_cb_t cb)
int ec_node_or_add(struct ec_node *node, struct ec_node *child)
#define EC_NODE_SEQ(args...)
Definition node_seq.h:29
struct ec_node * ec_node_sh_lex(const char *id, struct ec_node *child)
struct ec_node * ec_node_str(const char *id, const char *str)
struct ec_node * ec_node(const char *typename, const char *id)
struct ec_node * ec_node_find(struct ec_node *node, const char *id)
#define EC_NO_ID
Definition node.h:64
void ec_node_free(struct ec_node *node)
const struct ec_strvec * ec_pnode_get_strvec(const struct ec_pnode *pnode)
const struct ec_pnode * ec_pnode_find(const struct ec_pnode *root, const char *id)
struct ec_pnode * ec_pnode(const struct ec_node *node)
const char * ec_strvec_val(const struct ec_strvec *strvec, size_t idx)