cmd #1: use dynamic memory for managing args

This commit is contained in:
tylen 2024-09-23 22:01:29 +00:00 committed by Vasily Davydov
parent 9d40f081ac
commit 92f9c03128
5 changed files with 87 additions and 37 deletions

View File

@ -3,7 +3,7 @@
set -xe set -xe
CC="gcc" CC="gcc"
FLAGS="-Wall -Wpedantic" FLAGS="-Wall -Wpedantic -ggdb"
SRCS="$(find ./src -type f -name "*.c")" SRCS="$(find ./src -type f -name "*.c")"
CURRENT_DIR="$(git rev-parse --show-toplevel)" CURRENT_DIR="$(git rev-parse --show-toplevel)"
BUILD_DIR="${CURRENT_DIR}/build" BUILD_DIR="${CURRENT_DIR}/build"

View File

@ -2,8 +2,12 @@
#include "cmd.h" #include "cmd.h"
int main (int argc, char *argv[]) { static void __attribute__((constructor)) init_cdo(void) {
atexit(exit_cmd);
init_cmd(); init_cmd();
}
int main (int argc, char *argv[]) {
struct CommandLineArg* args = parse_args(argc, argv); struct CommandLineArg* args = parse_args(argc, argv);
return 0; return 0;
} }

View File

@ -5,43 +5,79 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
const struct CommandLineArg supported_args [] = { static struct ArgList* supported_args;
{
"PROJECT", static const char* PREDEFINED_ARG_NAMES [] = {
"Path to the project to be used for looking up TODO's", "project"
"Current Working directory", };
STRING
}, static const char* PREDEFINED_ARG_DESC [] = {
{} "Path to the project to be used for looking up TODO's"
};
static const char* PREDEFINED_ARG_VALUES [] = {
NULL
}; };
void usage(void) { void usage(void) {
Buffer * usage_lines = buffer_create(DEFAULT_USAGE_LINE_LEN); Buffer * usage_lines = buffer_create(DEFAULT_USAGE_LINE_LEN);
buffer_append(usage_lines, "Usage: cdo [PROJECT] [OPTION]\n"); buffer_append(usage_lines, "Usage: cdo [PROJECT] [OPTION]\n");
buffer_append(usage_lines, "Parse TODO's of the PROJECT.\n\n"); buffer_append(usage_lines, "Parse TODO's of the PROJECT.\n\n");
for (int i = 0; supported_args[i].type != EMPTY; i++) { for (int i = 0; i < ARG_COUNT; i++) {
buffer_append(usage_lines, supported_args[i].name); buffer_append(usage_lines, supported_args->args[i].name);
buffer_append(usage_lines, " - "); buffer_append(usage_lines, " - ");
buffer_append(usage_lines, supported_args[i].description); buffer_append(usage_lines, supported_args->args[i].description);
buffer_append(usage_lines, " [DEFAULT = "); if (supported_args->args[i].value) {
buffer_append(usage_lines, supported_args[i].value); buffer_append(usage_lines, " [DEFAULT = ");
buffer_append(usage_lines, supported_args->args[i].value);
buffer_append(usage_lines, "]");
}
} }
buffer_append(usage_lines, "\n]"); buffer_append(usage_lines, "\n");
buffer_flush(usage_lines); buffer_flush(usage_lines);
} }
void init_cmd(void) { static struct CommandLineArg* renderArg(ArgName name) {
return struct CommandLineArg* e = malloc(sizeof(struct CommandLineArg));
e->name = NULL;
e->description = NULL;
e->value = NULL;
if (PREDEFINED_ARG_NAMES[name]) {
e->name = malloc(strlen(PREDEFINED_ARG_NAMES[name]) + 1);
strcpy(e->name, PREDEFINED_ARG_NAMES[name]);
}
if (PREDEFINED_ARG_DESC[name]) {
e->description = malloc(strlen(PREDEFINED_ARG_DESC[name]) + 1);
strcpy(e->description, PREDEFINED_ARG_DESC[name]);
}
if (PREDEFINED_ARG_VALUES[name]) {
e->value = malloc(strlen(PREDEFINED_ARG_VALUES[name]) + 1);
strcpy(e->value, PREDEFINED_ARG_VALUES[name]);
}
return e;
} }
void create_arg_list(struct ArgList* list, size_t capacity) { void init_cmd(void) {
supported_args = create_arg_list(ARG_COUNT);
for (int i = 0; i < ARG_COUNT; i++) {
append_arg(supported_args, renderArg(i));
}
}
void exit_cmd(void) {
free_arg_list(supported_args);
}
struct ArgList* create_arg_list(size_t capacity) {
struct ArgList* list = NULL;
list = (struct ArgList*) malloc(sizeof(struct ArgList)); list = (struct ArgList*) malloc(sizeof(struct ArgList));
list->args = (struct CommandLineArg*) malloc(capacity * sizeof(struct CommandLineArg)); list->args = (struct CommandLineArg*) malloc(capacity * sizeof(struct CommandLineArg));
list->size = 0; list->size = 0;
list->capacity = capacity; list->capacity = capacity;
return list;
} }
void append_arg(struct ArgList* list, struct CommandLineArg arg) { void append_arg(struct ArgList* list, struct CommandLineArg* arg) {
if (list->size + 1 >= list->capacity) { if (list->size + 1 >= list->capacity) {
list->capacity *= 2; list->capacity *= 2;
list->args = list->args =
@ -51,11 +87,20 @@ void append_arg(struct ArgList* list, struct CommandLineArg arg) {
list->capacity * sizeof(struct CommandLineArg) list->capacity * sizeof(struct CommandLineArg)
); );
} }
memcpy( memcpy(list->args + list->size, arg, sizeof(struct CommandLineArg));
list->args + (list->size * sizeof(struct CommandLineArg)), free(arg);
&arg, list->size += 1;
sizeof(struct CommandLineArg) }
);
void free_arg_list(struct ArgList* list) {
for (size_t i = 0; i < ARG_COUNT; i++) {
free(list->args[i].name);
free(list->args[i].description);
free(list->args[i].value);
}
free(list->args);
free(list);
} }
struct CommandLineArg* parse_args(const int argc, char* argv[]) { struct CommandLineArg* parse_args(const int argc, char* argv[]) {

View File

@ -1,21 +1,22 @@
#ifndef __CMD_H__ #ifndef __CMD_H__
#define __CMD_H__ #define __CMD_H__
#include <stdlib.h>
#define MAX_CMD_LINE_ARG_NAME_LEN 256 #define MAX_CMD_LINE_ARG_NAME_LEN 256
#define MAX_CMD_LINE_ARG_DESC_LEN 1024 #define MAX_CMD_LINE_ARG_DESC_LEN 1024
#define DEFAULT_USAGE_LINE_LEN 256 #define DEFAULT_USAGE_LINE_LEN 256
#define SUPPORTED_ARGS_AMOUNT 2 #define SUPPORTED_ARGS_AMOUNT 2
typedef enum { typedef enum {
EMPTY, ARG_PROJECT,
STRING ARG_COUNT
} CmdType; } ArgName;
struct CommandLineArg { struct CommandLineArg {
char name[MAX_CMD_LINE_ARG_NAME_LEN]; char* name;
char description[MAX_CMD_LINE_ARG_DESC_LEN]; char* description;
char* value; char* value;
CmdType type;
}; };
struct ArgList { struct ArgList {
@ -24,12 +25,12 @@ struct ArgList {
size_t size; size_t size;
}; };
struct ArgList* supported_arg_list;
struct CommandLineArg* parse_args(const int argc, char* argv[]); struct CommandLineArg* parse_args(const int argc, char* argv[]);
void init_cmd(void); void init_cmd(void);
void create_arg_list(struct ArgList* list, size_t capacity); void exit_cmd(void);
void append_arg(struct ArgList* list, struct CommandLineArg arg); struct ArgList* create_arg_list(size_t capacity);
void append_arg(struct ArgList* list, struct CommandLineArg* arg);
void free_arg_list(struct ArgList* list);
void usage(void); void usage(void);
#endif /*__CMD_H__*/ #endif /*__CMD_H__*/

View File

@ -1,8 +1,8 @@
#include <stdlib.h>
#ifndef __BUFFER_H__ #ifndef __BUFFER_H__
#define __BUFFER_H__ #define __BUFFER_H__
#include <stdlib.h>
typedef struct { typedef struct {
char* data; char* data;
size_t size; size_t size;