Libecoli  0.11.3
Extensible COmmand LIne library
extension-editline/main.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2025, Olivier MATZ <zer0@droids-corp.org>
3  */
4 
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 */
46 static bool done;
47 
48 static 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 
79 static 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 
89 static int check_exit(void *opaque)
90 {
91  (void)opaque;
92  return done;
93 }
94 
95 static 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 
145 fail:
146  fprintf(stderr, "cannot initialize nodes\n");
147  ec_node_free(cmdlist);
148  ec_node_free(cmd);
149  return NULL;
150 }
151 
152 int 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 
187 fail:
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)
void ec_editline_free(struct ec_editline *editline)
struct ec_editline * ec_editline(const char *prog, FILE *f_in, FILE *f_out, FILE *f_err, enum ec_editline_init_flags flags)
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)
#define EC_NO_ID
Definition: node.h:64
struct ec_node * ec_node_find(struct ec_node *node, const char *id)
struct ec_node * ec_node(const char *typename, const char *id)
void ec_node_free(struct ec_node *node)
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 struct ec_strvec * ec_pnode_get_strvec(const struct ec_pnode *pnode)
const char * ec_strvec_val(const struct ec_strvec *strvec, size_t idx)