Skip to content

Commit

Permalink
v1.6
Browse files Browse the repository at this point in the history
7 add the feature to call multiple commands in one line
  • Loading branch information
constarg authored Apr 22, 2022
2 parents d1ca4b8 + 7d22815 commit a970342
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 49 deletions.
11 changes: 6 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ project(terminal-tool-builder C)

set(CMAKE_C_STANDARD 17)

set(HEADER_FILES include/tool_builder.h src/ds/queue.h)
set(SOURCE_FILES src/tool_builder.c src/ds/queue.c)
set(TO_INCLUDE include/ src/ds)


ADD_LIBRARY(
toolbuilder STATIC
src/tool_builder.c
include/tool_builder.h
${HEADER_FILES}
${SOURCE_FILES}
)

include_directories(
include/
)
include_directories(${TO_INCLUDE})

27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,32 @@ tool_builder_add_alias_both(&builder, "command_name", "alias_1", "alias_2", "ali
The `tool_builder_add_alias_both` function takes 2 parameters and an unlimited number of aliases. The first parameter is the builder, the second is the name of the command you want to add the aliases and the rest is the aliases. The defferent with this function is that it will also add the aliases in the docs.<br>
**Cation!!! the last alias must be NULL!**

## Multiple commands in one line
The tool by default can execute multiple commands that has been requested, even if it is in one line in terminal.
For example the below senario requests to execute two commands.
```
./your-tool-name --command1 arg1 arg2 --command2 arg1 arg2
```
If you want to disable this feature and allow only one command to be executed you can disable it with the below function.
```C
tool_builder_set_mc(c_builder, state);
```
Where c_builder is the builder and the state can be '1' or '0' depents if you want the feature enabled or not.
## Prepare
To prepare the tool to execute the requested commands the below function must be called.
```C
tool_builder_prepare(argc, argv, c_builder)
```
The `tool_builder_prepare` function has 3 parameters. The first parameter is the argc of main, the second is the argv of main and the third is the builder.
This function prepares the tool to execute the commands that the user has typed. The tool supports multiple commands in a line in terminal.

## Execution
To execute the command that the user has typed you have to call the below function in the main.
To execute the commands that the user has typed you have to call the below function in the main.
```C
tool_builder_execute(argc, argv, &builder);
tool_builder_execute();
```
The `tool_builder_execute` function has 3 parameters. The first parameter is the argc of main, the second is the argv of main and the third is the builder.
This function is responsible for the determination of what command has been given from the terminal and also is the function that calls the callback of the command thet has been requested.
The `tool_builder_execute` function has 0 parameters. This function is responsible for the execution of all the commands that the user has typed.

## Destroying
Once you have completed all the procedures you have to do with the builder you should free up the memory that the library is using. To do this you can call the following function.
Expand Down
33 changes: 18 additions & 15 deletions include/tool_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct tool_builder
struct tool_builder_command *t_commands; // array of commands.
int t_commandsc; // The number of the commands.
struct tool_builder_help t_help; // The help of the tool.
int t_mc: 1; // enable or disable multiple commands in one line.
};

struct tool_builder_args
Expand Down Expand Up @@ -172,23 +173,13 @@ extern int tool_builder_set_action(struct tool_builder *c_builder, const char *c
void (*c_callback)(const struct tool_builder_args *info));



extern int tool_builder_prepare(int argc, char *argv[], const struct tool_builder *c_builder);

/**
Execute the action that has been requested.
@param argc The argc parameter of the main function.
@param argv The argv parameter of the main function.
@param c_builder The bulder who has the information for each command.
@return On success 0 is returned. On error on integer error is returned.
Errors can be:
Wrong argument number: -1
Wrong command name or alias: -2
Empty command name: -3
No action defined: -4 -> when no call back exists.
failed to make exec info: -5
builder is not initiaized: -6
each error has a MACRO that can be used in if statements.
Execute the actions that has been requested.
*/
int tool_builder_execute(int argc, char *argv[], const struct tool_builder *c_builder);
extern void tool_builder_execute();

/**
* Execute a command with no values!. With this function you can
Expand All @@ -201,6 +192,18 @@ int tool_builder_execute(int argc, char *argv[], const struct tool_builder *c_bu
*/
int tool_builder_call_command(const char *c_name, const struct tool_builder *c_builder);


/**
* Enable or diable the feature to execute multiple commands in one
* line.
* @param state The new state of multiple commands enable variable.
* @param c_builder The builder.
*/
static void inline tool_builder_set_mc(struct tool_builder *c_builder, int state)
{
c_builder->t_mc = state & 0x01;
}

static int inline tool_builder_add_both(struct tool_builder *c_builder, const char *c_name,
int c_argc, void (*c_callback)(const struct tool_builder_args *info),
const char *c_description)
Expand Down
24 changes: 24 additions & 0 deletions src/ds/queue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <queue.h>

#include <malloc.h>


void tb_queue_enqueue(struct tb_queue_node_d *src, struct tb_queue *queue)
{
if (queue->front == NULL)
{
queue->front = (struct tb_queue_node *) malloc(sizeof(struct tb_queue_node));
memcpy(&queue->front->data, src, sizeof(struct tb_queue_node_d));
queue->front->next = NULL;
queue->rear = queue->front;
return;
}

struct tb_queue_node *new_node = (struct tb_queue_node *)
malloc(sizeof(struct tb_queue_node));
memcpy(&new_node->data, src, sizeof(struct tb_queue_node_d));
new_node->next = NULL;

queue->rear->next = new_node;
queue->rear = new_node;
}
80 changes: 80 additions & 0 deletions src/ds/queue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#ifndef TOOL_BUILDER_QUEUE_H
#define TOOL_BUILDER_QUEUE_H

#include <tool_builder.h>
#include <memory.h>

// node data.
struct tb_queue_node_d
{
struct tool_builder_args c_args;
void (*c_callback)(const struct tool_builder_args *info);
};

// queue node.
struct tb_queue_node
{
// data
struct tb_queue_node_d data;
// link to next node.
struct tb_queue_node *next;
};

// queue.
struct tb_queue
{
struct tb_queue_node *front; // the first element of queue.
struct tb_queue_node *rear; // the last element of queue.
};


static inline void tb_queue_init(struct tb_queue *queue)
{
memset(queue, 0x0, sizeof(struct tb_queue));
}

static inline void tb_queue_destroy(struct tb_queue *queue)
{
if (queue->front == NULL) return;
struct tb_queue_node *tmp = queue->front->next;
while(tmp)
{
free(queue->front->data.c_args.c_values);
free(queue->front);
queue->front = tmp;
tmp = queue->front->next;
}
memset(queue, 0x0, sizeof(struct tb_queue));
}

static inline int tb_queue_is_empty(struct tb_queue *queue)
{
return (queue->front == NULL)? 0x1 : 0x0;
}

/**
* Put's an element in queue.
* @param src The data to put.
* @param queue The queue to put the element.
*/
extern void tb_queue_enqueue(struct tb_queue_node_d *src, struct tb_queue *queue);


/**
* Removes an element from queue.
* @param dst The destination where the last element of queue must be stored.
* @param queue The queue to remove the element.
*/
static inline void tb_queue_dequeue(struct tb_queue_node_d *dst, struct tb_queue *queue)
{
if (queue->front == NULL) return;

memcpy(dst, &queue->front->data, sizeof(struct tb_queue_node_d));
struct tb_queue_node *removed = queue->front;
queue->front = queue->front->next;

free(removed);
}


#endif
82 changes: 59 additions & 23 deletions src/tool_builder.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <string.h>
#include <stdarg.h>
#include <tool_builder.h>
#include <queue.h>


// Priavte implementation of structs.
Expand Down Expand Up @@ -32,6 +33,9 @@ struct tool_builder_command
static inline struct tool_builder_command *find_command(const struct tool_builder_command *commands, const char *c_name,
int commandsc);

static struct tb_queue c_queue;


static void help_defualt_action(const struct tool_builder_args *info)
{
// Prints the help message.
Expand Down Expand Up @@ -62,7 +66,8 @@ void tool_builder_init(struct tool_builder *c_builder)
{
memset(c_builder, 0x0, sizeof(struct tool_builder));
c_builder->t_commands = (struct tool_builder_command *) calloc(1, sizeof(struct tool_builder_command));
c_builder->t_commandsc = 0;
c_builder->t_commandsc = 0x0;
c_builder->t_mc = 0x1;
}

void tool_builder_destroy(struct tool_builder *c_builder)
Expand Down Expand Up @@ -289,35 +294,66 @@ int tool_builder_call_command(const char *c_name, const struct tool_builder *c_b
int tool_builder_prepare(int argc, char *argv[], const struct tool_builder *c_builder)
{


}

int tool_builder_execute(int argc, char *argv[], const struct tool_builder *c_builder)
{
if (argv[1] == NULL) return TOOL_BUILDER_EMPTY_NAME;

tb_queue_init(&c_queue);

// Get the requested command to execute.
struct tool_builder_command *command = find_command((const struct tool_builder_command *) c_builder->t_commands, argv[1],
c_builder->t_commandsc);
struct tool_builder_command *c_curr;
struct tb_queue_node_d c_data;

if (command == NULL) return TOOL_BUILDER_WRONG_NAME_OR_ALIAS;

if (((argc - 2) - command->c_argc) < 0) return TOOL_BUILDER_WRONG_ARG_NUM;
memset(&c_data, 0x0, sizeof(struct tb_queue_node_d));

if (command->c_callback == NULL) return TOOL_BUILDER_NO_ACTION_DEFINED;
char *(*command) = (++argv); // point to the first command.

// Build the info to recieve the call back.
struct tool_builder_args exec_inf;
memset(&exec_inf, 0x0, sizeof(struct tool_builder_args));
exec_inf.c_name = command->c_name;
exec_inf.c_used_alias = argv[1];
exec_inf.c_argc = command->c_argc;
exec_inf.c_values = (command->c_argc > 0)? (argv + 2): NULL; // This points to the first argument of the requested command.
exec_inf.c_builder = (struct tool_builder *) c_builder;
while (*command)
{
c_curr = find_command((const struct tool_builder_command *) c_builder->t_commands, *command,
c_builder->t_commandsc);
if (c_curr == NULL) return TOOL_BUILDER_NO_SUCH_COMMAND_EXISTS;
if (c_curr->c_callback == NULL) return TOOL_BUILDER_NO_ACTION_DEFINED;

c_data.c_args.c_name = c_curr->c_name;
c_data.c_args.c_used_alias = *command;
c_data.c_args.c_argc = c_curr->c_argc;
c_data.c_args.c_values = (char **) malloc(sizeof(char *) * (c_curr->c_argc + 1));
c_data.c_args.c_builder = (struct tool_builder *) c_builder;
c_data.c_callback = c_curr->c_callback;

// store the values.
for (int v = 0; v < c_curr->c_argc; v++)
{
c_data.c_args.c_values[v] = ( *(command + v + 1) == NULL )? NULL : *(command + v + 1);
if ( c_data.c_args.c_values[v] == NULL
||
find_command((const struct tool_builder_command *) c_builder->t_commands, *(command + v + 1),
c_builder->t_commandsc) != NULL
)
{
free(c_data.c_args.c_values);
tb_queue_destroy(&c_queue);
return TOOL_BUILDER_WRONG_ARG_NUM;
}
}
c_data.c_args.c_values[c_curr->c_argc] = NULL;
tb_queue_enqueue(&c_data, &c_queue);
command += c_data.c_args.c_argc + 1;

// Call the callback with the values.
command->c_callback(&exec_inf);
if (!c_builder->t_mc) break;
}

return 0;
}

void tool_builder_execute()
{
// execute each command in the queue.
struct tb_queue_node_d c_to_exec;
memset(&c_to_exec, 0x0, sizeof(struct tb_queue_node_d));

while (!tb_queue_is_empty(&c_queue))
{
tb_queue_dequeue(&c_to_exec, &c_queue);
c_to_exec.c_callback(&c_to_exec.c_args);
free(c_to_exec.c_args.c_values);
}
}
8 changes: 6 additions & 2 deletions tests/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,13 @@ int main(int argc, char *argv[]) {
tool_builder_add_alias(&builder, "Testing", "Test", "t", "te", NULL);
tool_builder_add_alias_doc(&builder, "Testing");

tool_builder_call_command("--help", &builder);
//tool_builder_call_command("--help", &builder);

//tool_builder_set_mc(&builder, 0);

int error = tool_builder_prepare(argc, argv, &builder);
tool_builder_execute();

int error = tool_builder_execute(argc, argv, &builder);
printf("Error = %d\n", error);

tool_builder_destroy(&builder);
Expand Down

0 comments on commit a970342

Please sign in to comment.