summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAriadna Vigo <arivigodr@gmail.com>2020-08-08 20:22:28 +0200
committerAriadna Vigo <arivigodr@gmail.com>2020-08-08 20:46:19 +0200
commita72a5c9685b0c45d8b45c94bb4ec069ecc22f9a5 (patch)
tree141f659acd6ee2adca8f9ef6d6f9cf0535223d24
parent95704a9cf40e456d882cf369f63851f4d29efb61 (diff)
Number of tasks is no longer limited
-rw-r--r--cras.c139
-rw-r--r--tasklst.c143
-rw-r--r--tasklst.h32
3 files changed, 193 insertions, 121 deletions
diff --git a/cras.c b/cras.c
index 69b51aa..1c7e4c6 100644
--- a/cras.c
+++ b/cras.c
@@ -29,17 +29,17 @@ enum {
static void die(const char *fmt, ...);
static void printf_color(const char *ansi_color, const char *fmt, ...);
-static void print_task(TaskLst tasks, int i);
-static void print_short_output(TaskLst tasks);
-static void print_output(TaskLst tasks);
-static int read_crasfile(TaskLst *tasks, const char *crasfile);
-static void write_crasfile(const char *crasfile, TaskLst tasks);
-static int store_input(TaskLst *tasks, FILE *fp);
+static void print_task(Task task, int i);
+static void print_short_output(TaskLst list);
+static void print_output(TaskLst list);
+static int read_crasfile(TaskLst *list, const char *crasfile);
+static void write_crasfile(const char *crasfile, TaskLst list);
+static int store_input(TaskLst *list, FILE *fp);
static void usage(void);
static void new_mode(const char *crasfile);
static void output_mode(const char *crasfile, int mode);
-static void mark_tasks_mode(const char *crasfile, const char *id, int value);
+static void mark_list_mode(const char *crasfile, const char *id, int value);
static void
die(const char *fmt, ...)
@@ -70,7 +70,7 @@ printf_color(const char *ansi_color, const char *fmt, ...)
}
static void
-print_task(TaskLst tasks, int i)
+print_task(Task task, int i)
{
const char *todo_color, *done_color;
@@ -83,46 +83,45 @@ print_task(TaskLst tasks, int i)
done_color = task_done_color;
}
- /* Null tasks are never printed */
- if (tasks.status[i] == TASK_VOID)
- return;
-
printf("#%02d ", i + 1);
- if (tasks.status[i] == TASK_TODO)
+ if (task.status == TASK_TODO)
printf_color(todo_color, "%s ", task_todo_str);
else /* TASK_DONE */
printf_color(done_color, "%s ", task_done_str);
- printf("%s\n", tasks.tdesc[i]);
+ printf("%s\n", task.tdesc);
}
static void
-print_short_output(TaskLst tasks)
+print_short_output(TaskLst list)
{
- printf("%d/%d/%d", tasklst_tasks_todo(tasks),
- tasklst_tasks_done(tasks), tasklst_tasks_total(tasks));
+ printf("%d/%d/%d", task_lst_count_todo(list),
+ task_lst_count_done(list), task_lst_get_size(list));
}
static void
-print_output(TaskLst tasks)
+print_output(TaskLst list)
{
int i;
+ Task *ptr;
- printf("Due date: %s\n", ctime(&tasks.expiry));
+ printf("Due date: %s\n", ctime(&list.expiry));
- for(i = 0; i < TASK_LST_MAX_NUM; ++i)
- print_task(tasks, i);
+ for(i = 0, ptr = list.first; ptr != NULL; ptr = ptr->next) {
+ print_task(*ptr, i);
+ ++i;
+ }
if (i > 0)
putchar('\n');
- print_short_output(tasks);
+ print_short_output(list);
printf(" to do/done/total");
}
static int
-read_crasfile(TaskLst *tasks, const char *crasfile)
+read_crasfile(TaskLst *list, const char *crasfile)
{
int read_stat;
FILE *fp;
@@ -131,47 +130,52 @@ read_crasfile(TaskLst *tasks, const char *crasfile)
if (errno == ENOENT)
return -1; /* We give the chance to create the file later. */
- if (fp == NULL)
+ if (fp == NULL) {
+ task_lst_cleanup(list);
die("Could not read from %s: %s", crasfile, strerror(errno));
+ }
- read_stat = tasklst_read_from_file(tasks, fp);
+ read_stat = task_lst_read_from_file(list, fp);
fclose(fp);
- if (read_stat < 0)
+ if (read_stat < 0) {
+ task_lst_cleanup(list);
die("Parsing error: task file corrupted.");
+ }
- if (tasklst_expired(*tasks) > 0)
- die("Due date passed (%d tasks overdue).",
- tasklst_tasks_todo(*tasks));
+ if (task_lst_expired(*list) > 0) {
+ task_lst_cleanup(list);
+ die("Due date passed (%d list overdue).",
+ task_lst_count_todo(*list));
+ }
return 0;
}
static void
-write_crasfile(const char *crasfile, TaskLst tasks)
+write_crasfile(const char *crasfile, TaskLst list)
{
FILE *fp;
- if ((fp = fopen(crasfile, "w")) == NULL)
+ if ((fp = fopen(crasfile, "w")) == NULL) {
+ task_lst_cleanup(&list);
die("Could not write to %s: %s", crasfile, strerror(errno));
+ }
- tasklst_write_to_file(fp, tasks);
+ task_lst_write_to_file(fp, list);
fclose(fp);
}
static int
-store_input(TaskLst *tasks, FILE *fp)
+store_input(TaskLst *list, FILE *fp)
{
char linebuf[TASK_LST_DESC_MAX_SIZE];
- int i;
-
- for (i = 0; i < TASK_LST_MAX_NUM; ++i) {
+
+ while (feof(fp) == 0) {
fgets(linebuf, TASK_LST_DESC_MAX_SIZE, fp);
- if (feof(fp) != 0)
- return 0;
linebuf[strlen(linebuf) - 1] = '\0'; /* Chomp '\n' */
- if (tasklst_add_task(tasks, TASK_TODO, linebuf) < 0)
+ if (task_lst_add_task(list, TASK_TODO, linebuf) < 0)
return -1;
}
@@ -188,60 +192,73 @@ static void
new_mode(const char *crasfile)
{
int file_exists;
- TaskLst tasks;
+ TaskLst list;
- tasklst_init(&tasks);
- file_exists = read_crasfile(&tasks, crasfile);
+ task_lst_init(&list);
+ file_exists = read_crasfile(&list, crasfile);
- if (store_input(&tasks, stdin) < 0)
+ if (store_input(&list, stdin) < 0)
fprintf(stderr, "Warning: Task file already full.\n");
if (file_exists < 0) /* Only set if this is a new file */
- tasklst_set_expiration(&tasks, crasfile_expiry);
- write_crasfile(crasfile, tasks);
+ task_lst_set_expiration(&list, crasfile_expiry);
+ write_crasfile(crasfile, list);
+
+ task_lst_cleanup(&list);
}
static void
output_mode(const char *crasfile, int mode)
{
- TaskLst tasks;
+ TaskLst list;
- tasklst_init(&tasks);
- read_crasfile(&tasks, crasfile);
+ task_lst_init(&list);
+ read_crasfile(&list, crasfile);
if (mode == SHORT_OUTPUT)
- print_short_output(tasks);
+ print_short_output(list);
else
- print_output(tasks);
+ print_output(list);
putchar('\n');
+
+ task_lst_cleanup(&list);
}
static void
-mark_tasks_mode(const char *crasfile, const char *id, int value)
+mark_list_mode(const char *crasfile, const char *id, int value)
{
int tasknum;
char *endptr;
- TaskLst tasks;
+ TaskLst list;
+ Task *task;
tasknum = strtol(id, &endptr, 10);
if (endptr[0] != '\0')
die("'%s' not a number.", id);
- tasklst_init(&tasks);
- read_crasfile(&tasks, crasfile);
+ task_lst_init(&list);
+ read_crasfile(&list, crasfile);
- if (tasknum <= 0)
+ if (tasknum <= 0) {
+ task_lst_cleanup(&list);
die("Task number must be greater than zero.");
+ }
- if (tasknum <= tasklst_tasks_total(tasks))
- tasks.status[tasknum - 1] = value;
- else
+ if (tasknum <= task_lst_get_size(list))
+ task = task_lst_get_task(list, tasknum - 1);
+
+ if (task == NULL) {
+ task_lst_cleanup(&list);
die("Task #%d does not exist.", tasknum);
+ }
+
+ task->status = value;
+ write_crasfile(crasfile, list);
- write_crasfile(crasfile, tasks);
+ print_task(*task, tasknum - 1);
- print_task(tasks, tasknum - 1);
+ task_lst_cleanup(&list);
}
int
@@ -295,7 +312,7 @@ main(int argc, char *argv[])
output_mode(argv[0], SHORT_OUTPUT);
return 0;
case MARK_MODE:
- mark_tasks_mode(argv[0], numarg, task_value);
+ mark_list_mode(argv[0], numarg, task_value);
return 0;
}
diff --git a/tasklst.c b/tasklst.c
index ed3d3e5..ab30f31 100644
--- a/tasklst.c
+++ b/tasklst.c
@@ -8,91 +8,144 @@
#include "tasklst.h"
-static int tasklst_tasks_status(TaskLst tasks, int status);
+static int task_lst_count_status(TaskLst list, int status);
+static Task *task_lst_get_last_task(TaskLst list);
static int
-tasklst_tasks_status(TaskLst tasks, int status)
+task_lst_count_status(TaskLst list, int status)
{
- int i, total;
+ int total;
+ Task *ptr;
- for (i = 0, total = 0; i < TASK_LST_MAX_NUM; ++i) {
- if (tasks.status[i] == status)
+ for (ptr = list.first, total = 0; ptr != NULL; ptr = ptr->next) {
+ if (ptr->status == status)
++total;
}
return total;
}
-void
-tasklst_init(TaskLst *tasks)
+static Task *
+task_lst_get_last_task(TaskLst list)
{
- int i;
+ Task *ptr, *next;
- tasks->expiry = 0;
+ ptr = list.first;
+ while (ptr != NULL) {
+ next = ptr->next;
+ if (next == NULL)
+ return ptr;
- for (i = 0; i < TASK_LST_MAX_NUM; ++i) {
- memset(&tasks->status[i], TASK_VOID, sizeof(int));
- memset(tasks->tdesc[i], 0, TASK_LST_DESC_MAX_SIZE);
+ ptr = next;
}
+
+ return ptr;
+}
+
+void
+task_lst_init(TaskLst *list)
+{
+ list->expiry = 0;
+ list->first = NULL;
}
void
-tasklst_set_expiration(TaskLst *tasks, int64_t delta)
+task_lst_cleanup(TaskLst *list)
{
- tasks->expiry = time(NULL) + delta;
+ Task *ptr, *next;
+
+ ptr = list->first;
+ while (ptr != NULL) {
+ next = ptr->next;
+ free(ptr);
+ ptr = next;
+ }
}
int
-tasklst_expired(TaskLst tasks)
+task_lst_get_size(TaskLst list)
{
- return (time(NULL) > tasks.expiry) ? 1 : 0;
+ Task *ptr;
+ int count;
+
+ for (count = 0, ptr = list.first; ptr != NULL; ptr = ptr->next)
+ ++count;
+
+ return count;
+}
+
+void
+task_lst_set_expiration(TaskLst *list, int64_t delta)
+{
+ list->expiry = time(NULL) + delta;
}
int
-tasklst_tasks_total(TaskLst tasks)
+task_lst_expired(TaskLst list)
{
- return tasklst_tasks_todo(tasks) + tasklst_tasks_done(tasks);
+ return (time(NULL) > list.expiry) ? 1 : 0;
}
int
-tasklst_tasks_todo(TaskLst tasks)
+task_lst_count_todo(TaskLst list)
{
- return tasklst_tasks_status(tasks, TASK_TODO);
+ return task_lst_count_status(list, TASK_TODO);
}
int
-tasklst_tasks_done(TaskLst tasks)
+task_lst_count_done(TaskLst list)
{
- return tasklst_tasks_status(tasks, TASK_DONE);
+ return task_lst_count_status(list, TASK_DONE);
}
int
-tasklst_add_task(TaskLst *tasks, int status, const char *str)
+task_lst_add_task(TaskLst *list, int status, const char *str)
{
- int i;
-
- for (i = 0; i < TASK_LST_MAX_NUM; ++i) {
- if (tasks->status[i] == TASK_VOID) {
- strncpy(tasks->tdesc[i], str, TASK_LST_DESC_MAX_SIZE);
- tasks->status[i] = status;
- return i;
- }
- }
+ Task *last, *newtask;
- return -1; /* We couldn't add any new task, because tasks is full */
+ newtask = malloc(sizeof(Task));
+ if (newtask == NULL)
+ return -1;
+
+ newtask->status = status;
+ newtask->next = NULL;
+ strncpy(newtask->tdesc, str, TASK_LST_DESC_MAX_SIZE);
+
+ last = task_lst_get_last_task(*list);
+ if (last == NULL)
+ list->first = newtask;
+ else
+ last->next = newtask;
+
+ return 0;
}
+Task *
+task_lst_get_task(TaskLst list, int i)
+{
+ Task *ptr;
+
+ for (ptr = list.first; i > 0; ptr = ptr->next) {
+ if (ptr == NULL) /* We're out of bounds */
+ return NULL;
+
+ --i;
+ }
+
+ return ptr;
+}
+
int
-tasklst_read_from_file(TaskLst *tasks, FILE *fp)
+task_lst_read_from_file(TaskLst *list, FILE *fp)
{
- int i, stat_buf;
+ int stat_buf;
char *ptr, *endptr;
char linebuf[TASK_LST_DESC_MAX_SIZE];
- if (fscanf(fp, "%" SCNd64 "\n", &tasks->expiry) <= 0)
+ if (fscanf(fp, "%" SCNd64 "\n", &list->expiry) <= 0)
return -1;
- for (i = 0; i < TASK_LST_MAX_NUM && feof(fp) == 0; ++i) {
+ while (feof(fp) == 0) {
if (fgets(linebuf, sizeof(linebuf), fp) == NULL)
break;
@@ -108,23 +161,19 @@ tasklst_read_from_file(TaskLst *tasks, FILE *fp)
if (ptr == NULL)
return -1;
- tasklst_add_task(tasks, stat_buf, ptr);
+ task_lst_add_task(list, stat_buf, ptr);
}
return 0;
}
void
-tasklst_write_to_file(FILE *fp, TaskLst tasks)
+task_lst_write_to_file(FILE *fp, TaskLst list)
{
- int i;
+ Task *ptr;
- fprintf(fp, "%" PRId64 "\n", tasks.expiry);
+ fprintf(fp, "%" PRId64 "\n", list.expiry);
- for (i = 0; i < TASK_LST_MAX_NUM; ++i) {
- if (tasks.status[i] == TASK_VOID)
- break;
-
- fprintf(fp, "%d\t%s\n", tasks.status[i], tasks.tdesc[i]);
- }
+ for (ptr = list.first; ptr != NULL; ptr = ptr->next)
+ fprintf(fp, "%d\t%s\n", ptr->status, ptr->tdesc);
}
diff --git a/tasklst.h b/tasklst.h
index c4be946..ee3b56b 100644
--- a/tasklst.h
+++ b/tasklst.h
@@ -1,27 +1,33 @@
/* See LICENSE file for copyright and license details. */
-#define TASK_LST_MAX_NUM 11
#define TASK_LST_DESC_MAX_SIZE 64
enum {
- TASK_VOID,
TASK_TODO,
TASK_DONE
};
+typedef struct TASK_ Task;
+struct TASK_ {
+ int status;
+ Task *next;
+ char tdesc[TASK_LST_DESC_MAX_SIZE];
+};
+
typedef struct {
int64_t expiry;
- int status[TASK_LST_MAX_NUM];
- char tdesc[TASK_LST_MAX_NUM][TASK_LST_DESC_MAX_SIZE];
+ Task *first;
} TaskLst;
-void tasklst_init(TaskLst *tasks);
-void tasklst_set_expiration(TaskLst *tasks, int64_t delta);
-int tasklst_expired(TaskLst tasks);
-int tasklst_tasks_total(TaskLst tasks);
-int tasklst_tasks_todo(TaskLst tasks);
-int tasklst_tasks_done(TaskLst tasks);
-int tasklst_add_task(TaskLst *tasks, int status, const char *str);
-int tasklst_read_from_file(TaskLst *tasks, FILE *fp);
-void tasklst_write_to_file(FILE *fp, TaskLst tasks);
+void task_lst_init(TaskLst *list);
+void task_lst_cleanup(TaskLst *list);
+int task_lst_get_size(TaskLst list);
+void task_lst_set_expiration(TaskLst *list, int64_t delta);
+int task_lst_expired(TaskLst list);
+int task_lst_count_todo(TaskLst list);
+int task_lst_count_done(TaskLst list);
+Task *task_lst_get_task(TaskLst list, int i);
+int task_lst_add_task(TaskLst *list, int status, const char *str);
+int task_lst_read_from_file(TaskLst *list, FILE *fp);
+void task_lst_write_to_file(FILE *fp, TaskLst list);