diff --git a/src/action.c b/src/action.c index 14a62e0..7a0030c 100644 --- a/src/action.c +++ b/src/action.c @@ -11,13 +11,13 @@ static void action_list() if (actions->number_of_records > 0) { ppager = pit_pager_initialize(PAGER_ACTION, actions->number_of_records); for_each_action(pa) { - pit_pager_print(ppager, (uchar *)pa); + pit_pager_print(ppager, (char *)pa); } pit_pager_flush(ppager); } } -void pit_action(ulong id, char *subject, char *message) +void pit_action(int id, char *subject, char *message) { static Action action; @@ -28,7 +28,7 @@ void pit_action(ulong id, char *subject, char *message) strncpy(action.username, current_user(), sizeof(action.username) - 1); strncpy(action.message, message, sizeof(action.message) - 1); - pit_table_insert(actions, (uchar *)&action); + pit_table_insert(actions, (char *)&action); } void pit_log(char *argv[]) diff --git a/src/args.c b/src/args.c index 962ae24..520ae98 100644 --- a/src/args.c +++ b/src/args.c @@ -28,9 +28,9 @@ char *pit_arg_string(char **arg, char *required) return *arg; } -ulong pit_arg_number(char **arg, char *required) +int pit_arg_number(char **arg, char *required) { - ulong number = 0L; + int number = 0; if (required && (!*arg || pit_arg_is_option(arg))) { die("missing %s", required); @@ -143,14 +143,15 @@ time_t pit_arg_date(char **arg, char *required) memset(&tm, 0, sizeof(tm)); // printf("format: %s\n", format); if (strptime(*arg, format, &tm)) { - printf("then: %s\n", asctime(&tm)); + // printf("then: %s\n", asctime(&tm)); if (!tm.tm_mday) tm.tm_mday = ptm->tm_mday; if (!tm.tm_mon) tm.tm_mon = ptm->tm_mon; if (!tm.tm_year) tm.tm_year = ptm->tm_year; - + tm.tm_isdst = -1; // printf(" now: %s\n", asctime(ptm)); // printf(" adj: %s\n", asctime(&tm)); seconds = mktime(&tm); + // printf("ctime: %s", ctime(&seconds)); if (seconds == (time_t)-1) { perish("invalid date"); } diff --git a/src/db.c b/src/db.c index 44734a8..8d648f3 100644 --- a/src/db.c +++ b/src/db.c @@ -19,31 +19,41 @@ static char *pit_file_name() return file_name; } -static void read_header(FILE *file) +static bool read_and_validate_header(FILE *file) { - Header hd; + header = (PHeader)calloc(1, sizeof(Header)); - if (fread(&hd, sizeof(hd), 1, file)) { - if (hd.signature[0] != 0x50 || hd.signature[1] != 0x49 || hd.signature[2] != 0x54) { - die("invalid pit file"); + if (fread(header, sizeof(Header), 1, file)) { + if (header->signature[0] != 0x50 || header->signature[1] != 0x49 || header->signature[2] != 0x54) { + printf("pit: invalid pit file (%s)\n", pit_file_name()); + return FALSE; } - if (hd.schema_version != 0x01) { - die("invalid pit file version"); + if (header->schema_version != PIT_SCHEMA_VERSION) { + printf("pit: invalid pit file version (%d)\n", header->schema_version); + return FALSE; } } else { - die("couldn't read header"); + puts("pit: error reading pit file header"); + return FALSE; } + + return TRUE; } static void write_header(FILE *file) { - Header hd; + if (!header) header = (PHeader)calloc(1, sizeof(Header)); - hd.signature[0] = 0x50; hd.signature[1] = 0x49; hd.signature[2] = 0x54; - hd.schema_version = 0x01; - memset(&hd.reserved, 0, sizeof(hd.reserved)); + header->signature[0] = 0x50; header->signature[1] = 0x49; header->signature[2] = 0x54; + header->schema_version = PIT_SCHEMA_VERSION; + if (!header->created_at) { + header->created_at = time(NULL); + strncpy(header->created_by, current_user(), sizeof(header->created_by) - 1); + } + header->updated_at = time(NULL); + strncpy(header->updated_by, current_user(), sizeof(header->updated_by) - 1); - if (!fwrite(&hd, sizeof(hd), 1, file)) { + if (!fwrite(header, sizeof(Header), 1, file)) { die("couldn't write header"); } } @@ -66,6 +76,19 @@ void pit_init(char *argv[]) { } } +void pit_info(char *argv[]) +{ + pit_db_load(); + printf("Pit file name: %s\n", pit_file_name()); + printf("Created by: %s on %s", header->created_by, ctime(&header->created_at)); + printf("Last updated by: %s on %s", header->updated_by, ctime(&header->updated_at)); + printf("Schema version: %d\n", header->schema_version); + printf("Projects: %d\n", projects->number_of_records); + printf("Tasks: %d\n", tasks->number_of_records); + printf("Notes: %d\n", notes->number_of_records); + printf("Log entries: %d\n", actions->number_of_records); +} + void pit_db_load() { char *file_name = pit_file_name(); FILE *file = fopen(file_name, "r"); @@ -73,20 +96,24 @@ void pit_db_load() { if (!file) { perish(file_name); } else { - read_header(file); - projects = pit_table_load(file); - tasks = pit_table_load(file); - notes = pit_table_load(file); - actions = pit_table_load(file); - fclose(file); + if (read_and_validate_header(file)) { + projects = pit_table_load(file); + tasks = pit_table_load(file); + notes = pit_table_load(file); + actions = pit_table_load(file); + fclose(file); + } else { + fclose(file); + die(NULL); + } } } void pit_db_initialize() { - projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); - tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); - notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); - actions = pit_table_initialize(sizeof(Action), TABLE_HAS_CREATED_AT); + projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); + tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); + notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); + actions = pit_table_initialize(sizeof(Action), TABLE_HAS_CREATED_AT); pit_action(0, "pit", "Initialized pit"); diff --git a/src/note.c b/src/note.c index 9a724dd..1d13450 100644 --- a/src/note.c +++ b/src/note.c @@ -3,7 +3,7 @@ #include #include "pit.h" -void pit_note_delete(ulong id, PTask pt) +void pit_note_delete(int id, PTask pt) { } diff --git a/src/object.h b/src/object.h index 05f8843..a6cdcbd 100644 --- a/src/object.h +++ b/src/object.h @@ -2,40 +2,43 @@ #define __MODELS_H__ typedef struct _Header { - char signature[3]; - char schema_version; - char reserved[16]; + char signature[3]; + int schema_version; + char created_by[32]; + char updated_by[32]; + time_t created_at; + time_t updated_at; } Header, *PHeader; typedef struct _Project { - ulong id; + int id; char username[32]; /* User the project belongs to. */ char name[128]; /* Project name. */ char status[16]; /* Project status. */ - ulong number_of_tasks; /* Number of tasks for the project. */ - ulong created_by; /* Who created the project? */ - ulong updated_by; /* Who last updated the project? */ + int number_of_tasks; /* Number of tasks for the project. */ + int created_by; /* Who created the project? */ + int updated_by; /* Who last updated the project? */ time_t created_at; /* When the project was created? */ time_t updated_at; /* When the project was last updated? */ } Project, *PProject; typedef struct _Task { - ulong id; - ulong project_id; /* Which project the task belongs to? */ + int id; + int project_id; /* Which project the task belongs to? */ char username[32]; /* User the task belongs to. */ char name[128]; /* Task name. */ char status[16]; /* Task status. */ char priority[16]; /* Task priority. */ time_t date; /* Generic date/time, ex: task deadline. */ time_t time; /* Generic time, ex: time spent on the task. */ - ulong number_of_notes; /* Number of notes for the task. */ + int number_of_notes; /* Number of notes for the task. */ time_t created_at; /* When the task was created? */ time_t updated_at; /* When the task was last updated? */ } Task, *PTask; typedef struct _Note { - ulong id; - ulong task_id; /* Task the note belongs to. */ + int id; + int task_id; /* Task the note belongs to. */ char username[32]; /* User the note belongs to. */ char message[255]; /* The body of the note. */ time_t created_at; /* When the note was created? */ @@ -43,11 +46,27 @@ typedef struct _Note { } Note, *PNote; typedef struct _Action { - ulong subject_id; /* Reference to the specific Project, Task, or Note. */ + int subject_id; /* Reference to the specific Project, Task, or Note. */ char subject[16]; /* Project, Task, or Note. */ char username[32]; /* Who added the log message? */ char message[255]; /* Log message. */ time_t created_at; /* When log message was added? */ } Action, *PAction; +typedef union _Options { + struct { + int id; + char *name; + char *status; + char *priority; + time_t date; + time_t time; + } task; + struct { + int id; + char *name; + char *status; + } project; +} Options, *POptions; + #endif diff --git a/src/pager.c b/src/pager.c index 7bc31e9..55ee4b3 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3,14 +3,14 @@ #include #include "pit.h" -#define for_each_entry(ppager, entry) for (entry = (uchar **)ppager->entries; (uchar *)*entry; entry++) +#define for_each_entry(ppager, entry) for (entry = (char **)ppager->entries; (char *)*entry; entry++) #define TASK(attr) (((PTask)*pentry)->attr) #define PROJECT(attr) (((PProject)*pentry)->attr) #define ACTION(attr) (((PAction)*pentry)->attr) static void print_actions(PPager ppager) { - uchar **pentry; + char **pentry; char format[64]; sprintf(format, "%%s (%%-%ds): %%s\n", ppager->max.action.username); @@ -21,10 +21,10 @@ static void print_actions(PPager ppager) static void print_projects(PPager ppager) { - uchar **pentry; + char **pentry; char format[64]; - sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] %%-%ds (%%lu task%%s)\n", + sprintf(format, "%%c %%%dd: (%%-%ds) [%%-%ds] %%-%ds (%%d task%%s)\n", ppager->max.project.id, ppager->max.project.username, ppager->max.project.status, ppager->max.project.name ); for_each_entry(ppager, pentry) { @@ -42,10 +42,10 @@ static void print_projects(PPager ppager) static void print_tasks(PPager ppager) { - uchar **pentry; + char **pentry; char format[64]; - sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds (%%lu note%%s)\n", + sprintf(format, "%%c %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds (%%d note%%s)\n", ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.name ); for_each_entry(ppager, pentry) { @@ -64,10 +64,10 @@ static void print_tasks(PPager ppager) static void print_tasks_with_date(PPager ppager) { - uchar **pentry; + char **pentry; char format[64]; - sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%-%ds (%%lu note%%s)\n", + sprintf(format, "%%c %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%-%ds (%%d note%%s)\n", ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.date, ppager->max.task.name ); for_each_entry(ppager, pentry) { @@ -87,10 +87,10 @@ static void print_tasks_with_date(PPager ppager) static void print_tasks_with_time(PPager ppager) { - uchar **pentry; + char **pentry; char format[64]; - sprintf(format, "%%c %%%dlu: (%%-%ds) %%-%ds %%-%ds %%%ds %%-%ds (%%lu note%%s)\n", + sprintf(format, "%%c %%%dd: (%%-%ds) %%-%ds %%-%ds %%%ds %%-%ds (%%d note%%s)\n", ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.time, ppager->max.task.name ); for_each_entry(ppager, pentry) { @@ -110,10 +110,10 @@ static void print_tasks_with_time(PPager ppager) static void print_tasks_with_date_and_time(PPager ppager) { - uchar **pentry; + char **pentry; char format[64]; - sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%%ds %%-%ds (%%lu note%%s)\n", + sprintf(format, "%%c %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%%ds %%-%ds (%%d note%%s)\n", ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.date, ppager->max.task.time, ppager->max.task.name ); for_each_entry(ppager, pentry) { @@ -132,28 +132,28 @@ static void print_tasks_with_date_and_time(PPager ppager) } } -PPager pit_pager_initialize(ulong type, ulong number_of_entries) +PPager pit_pager_initialize(int type, int number_of_entries) { PPager ppager = calloc(1, sizeof(Pager)); memset(ppager, 0, sizeof(Pager)); ppager->type = type; - ppager->entries = calloc(number_of_entries + 1, sizeof(uchar *)); + ppager->entries = calloc(number_of_entries + 1, sizeof(char *)); return ppager; } -void pit_pager_print(PPager ppager, uchar *entry) +void pit_pager_print(PPager ppager, char *entry) { char str[32]; - uchar **pentry = (uchar **)ppager->entries + ppager->number_of_entries++; + char **pentry = (char **)ppager->entries + ppager->number_of_entries++; *pentry = entry; for_each_entry(ppager, pentry) { switch(ppager->type) { case PAGER_TASK: - sprintf(str, "%lu", TASK(id)); + sprintf(str, "%d", TASK(id)); ppager->max.task.id = max(ppager->max.task.id, strlen(str)); ppager->max.task.username = max(ppager->max.task.username, strlen(TASK(username))); ppager->max.task.name = max(ppager->max.task.name, strlen(TASK(name))); @@ -167,7 +167,7 @@ void pit_pager_print(PPager ppager, uchar *entry) } break; case PAGER_PROJECT: - sprintf(str, "%lu", ((PProject)*pentry)->id); + sprintf(str, "%d", ((PProject)*pentry)->id); ppager->max.project.id = max(ppager->max.project.id, strlen(str)); ppager->max.project.username = max(ppager->max.project.username, strlen(((PProject)*pentry)->username)); ppager->max.project.name = max(ppager->max.project.name, strlen(((PProject)*pentry)->name)); @@ -220,3 +220,7 @@ void pit_pager_free(PPager ppager) free(ppager->entries); free(ppager); } + +#undef TASK +#undef PROJECT +#undef ACTION diff --git a/src/pager.h b/src/pager.h index cd5b539..f1e1e3c 100644 --- a/src/pager.h +++ b/src/pager.h @@ -7,9 +7,9 @@ #define PAGER_NOTE 8 typedef struct _Pager { - ulong type; - ulong number_of_entries; - uchar *entries; + int type; + int number_of_entries; + char *entries; union { struct { int id; @@ -33,8 +33,8 @@ typedef struct _Pager { } max; } Pager, *PPager; -PPager pit_pager_initialize(ulong type, ulong number_of_entries); -void pit_pager_print(PPager ppager, uchar *entry); +PPager pit_pager_initialize(int type, int number_of_entries); +void pit_pager_print(PPager ppager, char *entry); void pit_pager_flush(PPager ppager); void pit_pager_free(PPager ppager); diff --git a/src/pit.c b/src/pit.c index 9bf9c7e..73b5e21 100644 --- a/src/pit.c +++ b/src/pit.c @@ -4,10 +4,19 @@ #include #include "pit.h" -PTable projects; -PTable tasks; -PTable notes; -PTable actions; +PHeader header; +PTable projects; +PTable tasks; +PTable notes; +PTable actions; + +void free_externals() { + if (header) free(header); + if (actions) pit_table_free(actions); + if (notes) pit_table_free(notes); + if (projects) pit_table_free(projects); + if (tasks) pit_table_free(tasks); +} /* ** Suicide. @@ -17,11 +26,14 @@ void die(char *message, ...) char str[4096]; va_list params; - va_start(params, message); - vsnprintf(str, sizeof(str), message, params); - fprintf(stderr, "pit: %s\n", str); - va_end(params); + if (message) { + va_start(params, message); + vsnprintf(str, sizeof(str), message, params); + fprintf(stderr, "pit: %s\n", str); + va_end(params); + } + free_externals(); exit(0); } /* @@ -34,26 +46,36 @@ void perish(char *prefix) fprintf(stderr, "%s - ", prefix); } perror(NULL); + + free_externals(); exit(0); } -void pit_status(char *argv[]) +void pit_version(char *argv[]) { - puts("pit: status is not implemented yet"); + printf("pit version %s\n", PIT_VERSION); } int main(int argc, char *argv[]) { - register int i; - char *commands[] = { "project", "task", "note", "log", "init", "status", "help" }; - void (*handlers[])(char *argv[]) = { pit_project, pit_task, pit_note, pit_log, pit_init, pit_status, pit_help }; + register int i, candidate = -1; + char *command[] = { "project", "task", "note", "log", "init", "info", "help", "version" }; + void (*handler[])(char *argv[]) = { pit_project, pit_task, pit_note, pit_log, pit_init, pit_info, pit_help, pit_version }; if (argc == 1) argv[1] = "help"; - for(i = 0; i < ARRAY_SIZE(commands); i++) { - if (strstr(commands[i], argv[1]) == commands[i]) { - handlers[i](&argv[1]); - return 1; + for(i = 0; i < ARRAY_SIZE(command); i++) { + if (strstr(command[i], argv[1]) == command[i]) { + if (candidate < 0) { + candidate = i; + } else { + die("ambiguous command (%s)", argv[1]); + } } } - printf("invalid command: %s", argv[1]); - return 0; + + if (candidate < 0) + die("invalid command (%s), run 'pit help' for help", argv[1]); + + handler[candidate](&argv[1]); + free_externals(); + return 1; } diff --git a/src/pit.h b/src/pit.h index 7af3c09..3a23c77 100644 --- a/src/pit.h +++ b/src/pit.h @@ -1,9 +1,8 @@ #if !defined(__PIT_H__) #define __PIT_H__ +#define PIT_VERSION "0.1.0" +#define PIT_SCHEMA_VERSION 1 -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned char uchar; typedef int bool; #include @@ -11,7 +10,6 @@ typedef int bool; #include "table.h" #include "pager.h" - #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #ifndef FALSE @@ -36,13 +34,15 @@ typedef int bool; #define for_each_action(ptr) PAction ptr; for (ptr = (PAction)actions->slots; (ptr - (PAction)actions->slots) < actions->number_of_records; ptr++) /* Externals. */ -extern PTable actions; -extern PTable notes; -extern PTable projects; -extern PTable tasks; +extern PHeader header; +extern PTable actions; +extern PTable notes; +extern PTable projects; +extern PTable tasks; /* Command handlers and database APIs */ void pit_init(char *argv[]); +void pit_info(char *argv[]); void pit_project(char *argv[]); void pit_task(char *argv[]); void pit_note(char *argv[]); @@ -52,16 +52,16 @@ void pit_help(char *argv[]); void pit_db_load(); void pit_db_save(); void pit_db_initialize(); -void pit_action(ulong id, char *subject, char *message); -void pit_task_delete(ulong id, PProject pp); -void pit_note_delete(ulong id, PTask pt); +void pit_action(int id, char *subject, char *message); +void pit_task_delete(int id, PProject pp); +void pit_note_delete(int id, PTask pt); /* Argument parsing helpers */ int pit_arg_is_option(char **arg); int pit_arg_option(char **arg); char *pit_arg_string(char **arg, char *required); -ulong pit_arg_number(char **arg, char *required); +int pit_arg_number(char **arg, char *required); time_t pit_arg_date(char **arg, char *required); time_t pit_arg_time(char **arg, char *required); @@ -70,6 +70,7 @@ void die(char *msg, ...); void perish(char *prefix); char *str2str(char *str); char *mem2str(char *mem, int len); +bool zero(char *mem, int len); char *current_user(); char *home_dir(char *username, int len); char *expand_path(char *path, char *expanded); diff --git a/src/project.c b/src/project.c index 2df2d83..176dbe3 100644 --- a/src/project.c +++ b/src/project.c @@ -3,17 +3,17 @@ #include #include "pit.h" -static void project_list(char *name, char *status); -static void project_show(ulong id); -static void project_create(char *name, char *status); -static void project_update(ulong id, char *name, char *status); -static void project_delete(ulong id); +static void project_list(POptions po); +static void project_show(int id); +static void project_create(POptions po); +static void project_update(int id, POptions po); +static void project_delete(int id); static bool project_already_exist(char *name); -static void project_find_current(PProject *ppp, ulong *pid); -static void project_log_create(PProject pp, char *name, char *status); -static void project_log_update(PProject pp, char *name, char *status); -static void project_log_delete(ulong id, char *name, ulong number_of_tasks); -static void project_parse_options(char **arg, char **name, char **status); +static int project_find_current(int id, PProject *ppp); +static void project_log_create(PProject pp, POptions po); +static void project_log_update(PProject pp, POptions po); +static void project_log_delete(int id, char *name, int number_of_tasks); +static void project_parse_options(char **arg, POptions po); /* ** CREATING PROJECTS: @@ -32,7 +32,7 @@ static void project_parse_options(char **arg, char **name, char **status); ** pit project -q [number | [-n name] [-s status]] */ -static void project_list(char *name, char *status) +static void project_list(POptions po) { PPager ppager; @@ -40,49 +40,50 @@ static void project_list(char *name, char *status) if (projects->number_of_records > 0) { ppager = pit_pager_initialize(PAGER_PROJECT, projects->number_of_records); for_each_project(pp) { - pit_pager_print(ppager, (uchar *)pp); + pit_pager_print(ppager, (char *)pp); } pit_pager_flush(ppager); } } -static void project_create(char *name, char *status) +static void project_create(POptions po) { pit_db_load(); - if (project_already_exist(name)) { + if (project_already_exist(po->project.name)) { die("project with the same name already exists"); } else { Project p, *pp; memset(&p, 0, sizeof(p)); - if (!status) status = "active"; - printf("creating project [%s], status [%s]\n", name, status); + if (!po->project.status) po->project.status = "active"; - strncpy(p.name, name, sizeof(p.name) - 1); - strncpy(p.status, status, sizeof(p.status) - 1); - strncpy(p.username, current_user(), sizeof(p.username) - 1); + strncpy(p.name, po->project.name, sizeof(p.name) - 1); + strncpy(p.status, po->project.status, sizeof(p.status) - 1); + strncpy(p.username, current_user(), sizeof(p.username) - 1); - pp = (PProject)pit_table_insert(projects, (uchar *)&p); + pp = (PProject)pit_table_insert(projects, (char *)&p); pit_table_mark(projects, pp->id); + + project_log_create(pp, po); pit_db_save(); } } -static void project_show(ulong id) +static void project_show(int id) { PProject pp; pit_db_load(); pp = (PProject)pit_table_find(projects, id); if (pp) { - printf("%lu: %s (%s, %lu task%s)\n", + printf("%d: %s (%s, %d task%s)\n", pp->id, pp->name, pp->status, pp->number_of_tasks, (pp->number_of_tasks != 1 ? "s" : "")); if (pp->number_of_tasks > 0) { puts("Tasks:"); for_each_task(pt) { - printf(" %c %lu: %s (%lu notes)\n", (pt->id == tasks->current ? '*' : ' '), pt->id, pt->name, pt->number_of_notes); + printf(" %c %d: %s (%d notes)\n", (pt->id == tasks->current ? '*' : ' '), pt->id, pt->name, pt->number_of_notes); } } pit_table_mark(projects, pp->id); @@ -92,27 +93,27 @@ static void project_show(ulong id) } } -static void project_update(ulong id, char *name, char *status) +static void project_update(int id, POptions po) { PProject pp; pit_db_load(); - project_find_current(&pp, &id); + id = project_find_current(id, &pp); - if (name) strncpy(pp->name, name, sizeof(pp->name) - 1); - if (status) strncpy(pp->status, status, sizeof(pp->status) - 1); + if (po->project.name) strncpy(pp->name, po->project.name, sizeof(pp->name) - 1); + if (po->project.status) strncpy(pp->status, po->project.status, sizeof(pp->status) - 1); pit_table_mark(projects, pp->id); - project_log_update(pp, name, status); + project_log_update(pp, po); pit_db_save(); } -static void project_delete(ulong id) +static void project_delete(int id) { PProject pp; pit_db_load(); - project_find_current(&pp, &id); + id = project_find_current(id, &pp); /* ** Delete project tasks. */ @@ -129,7 +130,7 @@ static void project_delete(ulong id) ** name and number of tasks since we need these bits for logging. */ char *deleted_name = str2str(pp->name); - ulong deleted_number_of_tasks = pp->number_of_tasks; + int deleted_number_of_tasks = pp->number_of_tasks; pp = (PProject)pit_table_delete(projects, id); if (pp) { @@ -152,70 +153,69 @@ static bool project_already_exist(char *name) return FALSE; } -static void project_find_current(PProject *ppp, ulong *pid) +static int project_find_current(int id, PProject *ppp) { - if (*pid) { - *ppp = (PProject)pit_table_find(projects, *pid); - if (!*ppp) die("could not find project %lu", *pid); + if (id) { + *ppp = (PProject)pit_table_find(projects, id); + if (!*ppp) die("could not find project %d", id); } else { *ppp = (PProject)pit_table_current(projects); if (!*ppp) die("could not find current project"); - else *pid = (*(PProject *)ppp)->id; } + return *ppp ? (*(PProject *)ppp)->id : 0; } -static void project_log_create(PProject pp, char *name, char *status) +static void project_log_create(PProject pp, POptions po) { char str[256]; - sprintf(str, "created project %lu: %s (status: %s)", pp->id, name, status); + sprintf(str, "created project %d: %s (status: %s)", pp->id, po->project.name, po->project.status); puts(str); pit_action(pp->id, "project", str); } -static void project_log_update(PProject pp, char *name, char *status) +static void project_log_update(PProject pp, POptions po) { char str[256]; bool empty = TRUE; - sprintf(str, "updated project %lu:", pp->id); - if (name) { - sprintf(str + strlen(str), " (name: %s", name); + sprintf(str, "updated project %d:", pp->id); + if (po->project.name) { + sprintf(str + strlen(str), " (name: %s", po->project.name); empty = FALSE; } else { sprintf(str + strlen(str), " %s (", pp->name); } - if (status) { - sprintf(str + strlen(str), "%sstatus: %s)", (empty ? "" : ", "), status); + if (po->project.status) { + sprintf(str + strlen(str), "%sstatus: %s)", (empty ? "" : ", "), po->project.status); } + strcat(str, ")"); puts(str); pit_action(pp->id, "project", str); } -static void project_log_delete(ulong id, char *name, ulong number_of_tasks) +static void project_log_delete(int id, char *name, int number_of_tasks) { char str[256]; - sprintf(str, "deleted project %lu: %s", id, name); + sprintf(str, "deleted project %d: %s", id, name); if (number_of_tasks > 0) { - sprintf(str + strlen(str), " with %lu task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s")); + sprintf(str + strlen(str), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s")); } puts(str); pit_action(id, "project", str); } -static void project_parse_options(char **arg, char **name, char **status) +static void project_parse_options(char **arg, POptions po) { while(*++arg) { switch(pit_arg_option(arg)) { - case 's': - *status = pit_arg_string(++arg, "project status"); - break; case 'n': - if (name) { - *name = pit_arg_string(++arg, "project name"); - break; - } /* else fall though */ + po->project.name = pit_arg_string(++arg, "project name"); + break; + case 's': + po->project.status = pit_arg_string(++arg, "project status"); + break; default: die("invalid project option: %s", *arg); } @@ -224,12 +224,13 @@ static void project_parse_options(char **arg, char **name, char **status) void pit_project(char *argv[]) { + Options opt; char **arg = &argv[1]; - char *name = NULL, *status = NULL; - ulong number = 0L; + int number = 0; + memset(&opt, 0, sizeof(opt)); if (!*arg) { - project_list(name, status); /* Show all projects. */ + project_list(&opt); /* Show all projects. */ } else { /* pit project [number] */ number = pit_arg_number(arg, NULL); if (number) { @@ -237,18 +238,18 @@ void pit_project(char *argv[]) } else { switch(pit_arg_option(arg)) { case 'c': /* pit project -c name [-s status] */ - name = pit_arg_string(++arg, "project name"); - project_parse_options(arg, NULL, &status); - project_create(name, status); + opt.project.name = pit_arg_string(++arg, "project name"); + project_parse_options(arg, &opt); + project_create(&opt); break; case 'e': /* pit project -e [number] [-n name] [-s status] */ number = pit_arg_number(++arg, NULL); if (!number) --arg; - project_parse_options(arg, &name, &status); - if (!name && !status) { + project_parse_options(arg, &opt); + if (zero((char *)&opt.project, sizeof(opt.project))) { die("nothing to update"); } else { - project_update(number, name, status); + project_update(number, &opt); } break; case 'd': /* pit project -d [number] */ @@ -260,11 +261,11 @@ void pit_project(char *argv[]) if (number) { project_show(number); } else { - project_parse_options(--arg, &name, &status); - if (!name && !status) { + project_parse_options(--arg, &opt); + if (zero((char *)&opt.project, sizeof(opt.project))) { project_show(0); /* Show current project if any. */ } else { - project_list(name, status); + project_list(&opt); } } break; diff --git a/src/table.c b/src/table.c index 0238c53..5aa34ea 100644 --- a/src/table.c +++ b/src/table.c @@ -7,7 +7,7 @@ /* ** Initialize the table by alloocating necessary memory chunks. */ -PTable pit_table_initialize(ulong record_size, ulong flags) { +PTable pit_table_initialize(int record_size, int flags) { PTable pt = calloc(1, sizeof(Table)); pt->flags = flags; @@ -17,7 +17,7 @@ PTable pit_table_initialize(ulong record_size, ulong flags) { pt->auto_increment = 0; pt->current = 0; pt->slots = calloc(TABLE_INCREMENT, pt->record_size); - pt->index = calloc(TABLE_INCREMENT, sizeof(uchar *)); + pt->index = calloc(TABLE_INCREMENT, sizeof(char *)); return pt; } @@ -25,14 +25,14 @@ PTable pit_table_initialize(ulong record_size, ulong flags) { /* ** Return the address of next avaiable slot within pt->slots chunk. */ -static uchar *table_available_slot(PTable pt) { +static char *table_available_slot(PTable pt) { return pt->slots + pt->number_of_records * pt->record_size; } /* ** Return the address of last stored record. */ -static uchar *table_last_record(PTable pt) { +static char *table_last_record(PTable pt) { if (pt->number_of_records == 0) { return pt->slots; } else { @@ -43,14 +43,14 @@ static uchar *table_last_record(PTable pt) { /* ** Return the address of next available pointer within pt->index chunk. */ -static uchar **table_available_index(PTable pt) { +static char **table_available_index(PTable pt) { return pt->index + pt->auto_increment; } /* ** Return the address of last pointer within pt->index chunk. */ -static uchar **table_last_index(PTable pt) { +static char **table_last_index(PTable pt) { if (pt->auto_increment == 0) { return pt->index; } else { @@ -65,8 +65,8 @@ static uchar **table_last_index(PTable pt) { ** existing indices to make them point to reallocated record slots. */ static PTable table_extend(PTable pt) { - register ulong i; - register uchar **pi; + register int i; + register char **pi; pt->number_of_slots += TABLE_INCREMENT; /* @@ -93,7 +93,7 @@ static PTable table_extend(PTable pt) { /* ** Find a record by id and return its address. */ -uchar *pit_table_find(PTable pt, ulong id) { +char *pit_table_find(PTable pt, int id) { // TODO: retrn NULL (or raise?) if table doesn't have id. if (pt->number_of_records == 0 || id <= 0 || id > pt->auto_increment) { return NULL; @@ -106,14 +106,14 @@ uchar *pit_table_find(PTable pt, ulong id) { ** Delete a record by its ID. Return the address of deleted record or NULL ** if the record was not found. */ -uchar *pit_table_delete(PTable pt, ulong id) { +char *pit_table_delete(PTable pt, int id) { // TODO: return NULL (or die?) if table doesn't have id. - register uchar *pr = (uchar *)pit_table_find(pt, id); + register char *pr = (char *)pit_table_find(pt, id); if (pr) { - register ulong i; - register uchar **pi; - register uchar *last = table_last_record(pt); + register int i; + register char **pi; + register char *last = table_last_record(pt); /* ** Overwrite current record by shifting over remaining records */ @@ -144,8 +144,8 @@ uchar *pit_table_delete(PTable pt, ulong id) { ** Insert a record and return its address. The table gets extended ** as necessary. */ -uchar *pit_table_insert(PTable pt, uchar *record) { - register uchar **pi; +char *pit_table_insert(PTable pt, char *record) { + register char **pi; register time_t now; if (pt->number_of_records >= pt->number_of_slots) { @@ -163,7 +163,7 @@ uchar *pit_table_insert(PTable pt, uchar *record) { ** record field of type "unsigned long". */ if (pt->flags & TABLE_HAS_ID) { - *(ulong *)*pi = pt->auto_increment; + *(int *)*pi = pt->auto_increment; } /* ** Update created_at and/or updated_at which must be last one or two record @@ -182,14 +182,14 @@ uchar *pit_table_insert(PTable pt, uchar *record) { /* ** Find current record. */ -uchar *pit_table_current(PTable pt) { +char *pit_table_current(PTable pt) { return pit_table_find(pt, pt->current); } /* ** Set current record as indicated by the id, then find and return it. */ -uchar *pit_table_mark(PTable pt, ulong id) { +char *pit_table_mark(PTable pt, int id) { return pit_table_find(pt, pt->current = id); } @@ -218,7 +218,7 @@ int pit_table_save(FILE *file, PTable pt) { ** Save table header data: flags, record_size, number_of_slots, ** number_of_records, and auto_increment, current. */ - written += fwrite(pt, sizeof(ulong), 6, file); + written += fwrite(pt, sizeof(int), 6, file); /* ** Save the records. Note that we save the actual (not allocated) data. */ @@ -233,20 +233,20 @@ int pit_table_save(FILE *file, PTable pt) { PTable pit_table_load(FILE *file) { PTable pt; register int read = 0; - register ulong i; - uchar *pr, **pi; + register int i; + char *pr, **pi; pt = calloc(1, sizeof(Table)); /* ** First read the header. */ - read += fread(pt, sizeof(ulong), 6, file); + read += fread(pt, sizeof(int), 6, file); /* ** Now allocate slots and index based on the original number of slots. */ - /*** printf("Allocating %lu slots\n", pt->number_of_slots); ***/ + /*** printf("Allocating %d slots\n", pt->number_of_slots); ***/ pt->slots = pr = calloc(pt->number_of_slots, pt->record_size); - pt->index = pi = calloc(pt->number_of_slots, sizeof(uchar *)); + pt->index = pi = calloc(pt->number_of_slots, sizeof(char *)); /* ** Now read the records into the slots and rebuild the index if the ** table has primary key. @@ -254,7 +254,7 @@ PTable pit_table_load(FILE *file) { read += fread(pt->slots, pt->record_size, pt->number_of_records, file); if (pt->flags & TABLE_HAS_ID) { for(i = 1; i <= pt->number_of_slots; i++, pi++) { - if ((ulong)*pr == i) { + if ((int)*pr == i) { *pi = pr; pr += pt->record_size; } @@ -267,8 +267,8 @@ PTable pit_table_load(FILE *file) { #if defined(TEST) typedef struct { - ulong id; - ulong value; + int id; + int value; char name[30]; time_t created_at; time_t updated_at; @@ -276,8 +276,8 @@ typedef struct { void dump(Record *prec) { if (prec) { - printf("(%08lX) id: %08lu, value: %lu, created_at: %lu, updated_at: %lu\n", - (ulong)prec, prec->id, prec->value, prec->created_at, prec->updated_at); + printf("(%08lX) id: %08d, value: %d, created_at: %d, updated_at: %d\n", + (int)prec, prec->id, prec->value, prec->created_at, prec->updated_at); } else { printf("(NULL)\n"); } @@ -301,7 +301,7 @@ int main() { PTable pt; Record rec, *prec; - ulong i, total = 3; + int i, total = 3; pt = pit_table_initialize(sizeof(Record), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS); for(i = 0; i < total; i++) { @@ -310,20 +310,20 @@ int main() { strcpy(rec.name, "test"); rec.created_at = rec.updated_at = (time_t)0; - prec = (Record *)pit_table_insert(pt, (uchar *)&rec); + prec = (Record *)pit_table_insert(pt, (char *)&rec); dump(prec); } prec = (Record *)pit_table_find(pt, total - 1); pit_table_mark(pt, prec->id); - printf("current: %lu\n", pt->current); + printf("current: %d\n", pt->current); // for (i = 20; i < total; i++) { - // printf("Deleting %lu\n", i + 1); + // printf("Deleting %d\n", i + 1); // prec = (Record *)pit_table_delete(pt, i + 1); // } - printf("Deleting %lu\n", 1L); + printf("Deleting %d\n", 1L); prec = (Record *)pit_table_delete(pt, 1); - printf("current: %lu\n", pt->current); + printf("current: %d\n", pt->current); dump_all(pt); FILE *file = fopen("/tmp/.pit", "w"); @@ -333,7 +333,7 @@ int main() { file = fopen("/tmp/.pit", "r"); pt = pit_table_load(file); dump_all(pt); - printf("current: %lu\n", pt->current); + printf("current: %d\n", pt->current); fclose(file); pit_table_free(pt); diff --git a/src/table.h b/src/table.h index 60e43c8..7a5a610 100644 --- a/src/table.h +++ b/src/table.h @@ -7,24 +7,24 @@ #define TABLE_HAS_TIMESTAMPS (TABLE_HAS_CREATED_AT | TABLE_HAS_UPDATED_AT) typedef struct _Table { - ulong flags; /* Bit mask with table flags. */ - ulong record_size; /* Record size in bytes; all records are of fixed size. */ - ulong number_of_slots; /* Number of slots allocated, each slot is 'record_size' long. */ - ulong number_of_records; /* Number of records currently stored in slots. */ - ulong auto_increment; /* Current value of record id. */ - ulong current; /* The id of currently selected record, one per table. */ - uchar *slots; /* Memory chunk to store records; compacted when a record gets deleted (no holes). */ - uchar **index; /* Memory chunk to store pointers to individual records, holes for deleted record IDs. */ + int flags; /* Bit mask with table flags. */ + int record_size; /* Record size in bytes; all records are of fixed size. */ + int number_of_slots; /* Number of slots allocated, each slot is 'record_size' long. */ + int number_of_records; /* Number of records currently stored in slots. */ + int auto_increment; /* Current value of record id. */ + int current; /* The id of currently selected record, one per table. */ + char *slots; /* Memory chunk to store records; compacted when a record gets deleted (no holes). */ + char **index; /* Memory chunk to store pointers to individual records, holes for deleted record IDs. */ } Table, *PTable; -PTable pit_table_initialize(ulong record_size, ulong flags); +PTable pit_table_initialize(int record_size, int flags); void pit_table_free(PTable pt); -uchar *pit_table_find(PTable pt, ulong id); -uchar *pit_table_delete(PTable pt, ulong id); -uchar *pit_table_insert(PTable pt, uchar *record); +char *pit_table_find(PTable pt, int id); +char *pit_table_delete(PTable pt, int id); +char *pit_table_insert(PTable pt, char *record); -uchar *pit_table_current(PTable pt); -uchar *pit_table_mark(PTable pt, ulong id); +char *pit_table_current(PTable pt); +char *pit_table_mark(PTable pt, int id); int pit_table_save(FILE *file, PTable pt); PTable pit_table_load(FILE *file); diff --git a/src/task.c b/src/task.c index c74e8d1..4a555c0 100644 --- a/src/task.c +++ b/src/task.c @@ -2,16 +2,16 @@ #include #include #include "pit.h" - -static void task_list(char *name, char *status, char *priority, time_t date, time_t time); -static void task_show(ulong id); -static void task_create(char *name, char *status, char *priority, time_t date, time_t time); -static void task_update(ulong id, char *name, char *status, char *priority, time_t date, time_t time); -static void task_find_current(PTask *ppt, ulong *pid); -static void task_log_create(PTask pt, char *name, char *status, char *priority, time_t date, time_t time); -static void task_log_update(PTask pt, char *name, char *status, char *priority, time_t date, time_t time); -static void task_log_delete(ulong id, char *name, ulong number_of_notes); -static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *date, time_t *time); + +static void task_list(POptions po); +static void task_show(int id); +static void task_create(POptions po); +static void task_update(int id, POptions po); +static int task_find_current(int id, PTask *ppt); +static void task_log_create(PTask pt, POptions po); +static void task_log_update(PTask pt, POptions po); +static void task_log_delete(int id, char *name, int number_of_notes); +static void task_parse_options(char **arg, POptions po); /* ** CREATING TASKS: @@ -30,7 +30,7 @@ static void task_parse_options(char **arg, char **name, char **status, char **pr ** pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]] */ -static void task_list(char *name, char *status, char *priority, time_t date, time_t time) +static void task_list(POptions po) { pit_db_load(); if (tasks->number_of_records > 0) { @@ -41,21 +41,20 @@ static void task_list(char *name, char *status, char *priority, time_t date, tim if (pp && pt->project_id != pp->id) { continue; } - pit_pager_print(ppager, (uchar *)pt); + pit_pager_print(ppager, (char *)pt); } pit_pager_flush(ppager); } } -static void task_show(ulong id) +static void task_show(int id) { - printf("task_show(%lu)\n", id); + printf("task_show(%d)\n", id); } -static void task_create(char *name, char *status, char *priority, time_t date, time_t time) +static void task_create(POptions po) { pit_db_load(); - PProject pp = (PProject)pit_table_current(projects); if (!pp) { @@ -65,40 +64,40 @@ static void task_create(char *name, char *status, char *priority, time_t date, t memset(&t, 0, sizeof(t)); - if (!status) status = "open"; - if (!priority) priority = "normal"; + if (!po->task.status) po->task.status = "open"; + if (!po->task.priority) po->task.priority = "normal"; - strncpy(t.name, name, sizeof(t.name) - 1); - strncpy(t.status, status, sizeof(t.status) - 1); - strncpy(t.priority, priority, sizeof(t.priority) - 1); - strncpy(t.username, current_user(), sizeof(t.username) - 1); + strncpy(t.name, po->task.name, sizeof(t.name) - 1); + strncpy(t.status, po->task.status, sizeof(t.status) - 1); + strncpy(t.priority, po->task.priority, sizeof(t.priority) - 1); + strncpy(t.username, current_user(), sizeof(t.username) - 1); t.project_id = pp->id; - t.date = date; - t.time = time; + t.date = po->task.date; + t.time = po->task.time; - pt = (PTask)pit_table_insert(tasks, (uchar *)&t); + pt = (PTask)pit_table_insert(tasks, (char *)&t); pit_table_mark(tasks, pt->id); pp->number_of_tasks++; - task_log_create(pt, name, status, priority, date, time); + task_log_create(pt, po); pit_db_save(); } } -static void task_update(ulong id, char *name, char *status, char *priority, time_t date, time_t time) +static void task_update(int id, POptions po) { PTask pt; pit_db_load(); - task_find_current(&pt, &id); + id = task_find_current(id, &pt); - if (name) strncpy(pt->name, name, sizeof(pt->name) - 1); - if (status) strncpy(pt->status, status, sizeof(pt->status) - 1); - if (priority) strncpy(pt->priority, priority, sizeof(pt->priority) - 1); - if (date) pt->date = date; - if (time) pt->time = time; + if (po->task.name) strncpy(pt->name, po->task.name, sizeof(pt->name) - 1); + if (po->task.status) strncpy(pt->status, po->task.status, sizeof(pt->status) - 1); + if (po->task.priority) strncpy(pt->priority, po->task.priority, sizeof(pt->priority) - 1); + if (po->task.date) pt->date = po->task.date; + if (po->task.time) pt->time = po->task.time; pit_table_mark(tasks, pt->id); - task_log_update(pt, name, status, priority, date, time); + task_log_update(pt, po); pit_db_save(); } @@ -106,13 +105,13 @@ static void task_update(ulong id, char *name, char *status, char *priority, time ** A task could be deleted as standalone entity or as part of cascading project ** delete. In later case we're going to have 'pp' set and the database loaded. */ -void pit_task_delete(ulong id, PProject pp) +void pit_task_delete(int id, PProject pp) { PTask pt; bool standalone = (pp == NULL); if (standalone) pit_db_load(); - task_find_current(&pt, &id); + id = task_find_current(id, &pt); if (standalone) pp = (PProject)pit_table_find(projects, pt->project_id); if (pp) { @@ -132,7 +131,7 @@ void pit_task_delete(ulong id, PProject pp) ** we need these for logging. */ char *deleted_name = str2str(pt->name); - ulong deleted_number_of_notes = pt->number_of_notes; + int deleted_number_of_notes = pt->number_of_notes; pt = (PTask)pit_table_delete(tasks, id); if (pt) { @@ -145,100 +144,98 @@ void pit_task_delete(ulong id, PProject pp) free(deleted_name); } else { free(deleted_name); - die("could not delete task %lu", id); + die("could not delete task %d", id); } } else { - die("could not find project for task %lu", id); + die("could not find project for task %d", id); } } -static void task_find_current(PTask *ppt, ulong *pid) +static int task_find_current(int id, PTask *ppt) { - if (*pid) { - *ppt = (PTask)pit_table_find(tasks, *pid); - if (!*ppt) die("could not find task %lu", *pid); + if (id) { + *ppt = (PTask)pit_table_find(tasks, id); + if (!*ppt) die("could not find task %d", id); } else { *ppt = (PTask)pit_table_current(tasks); if (!*ppt) die("could not find current task"); - else *pid = (*(PTask *)ppt)->id; } + return *ppt ? (*(PTask *)ppt)->id : 0; } -static void task_log_create(PTask pt, char *name, char *status, char *priority, time_t date, time_t time) +static void task_log_create(PTask pt, POptions po) { char str[256]; - sprintf(str, "created task %lu: %s (status: %s, priority: %s", pt->id, name, status, priority); - if (date) sprintf(str + strlen(str), ", date: %s", format_date(date)); - if (time) sprintf(str + strlen(str), ", time: %s", format_date(time)); + sprintf(str, "created task %d: %s (status: %s, priority: %s", pt->id, po->task.name, po->task.status, po->task.priority); + if (po->task.date) sprintf(str + strlen(str), ", date: %s", format_date(po->task.date)); + if (po->task.time) sprintf(str + strlen(str), ", time: %s", format_time(po->task.time)); strcat(str, ")"); puts(str); pit_action(pt->id, "task", str); } -static void task_log_update(PTask pt, char *name, char *status, char *priority, time_t date, time_t time) +static void task_log_update(PTask pt, POptions po) { char str[256]; bool empty = TRUE; - sprintf(str, "updated task %lu:", pt->id); - if (name) { - sprintf(str + strlen(str), " (name: %s", name); + sprintf(str, "updated task %d:", pt->id); + if (po->task.name) { + sprintf(str + strlen(str), " (name: %s", po->task.name); empty = FALSE; } else { sprintf(str + strlen(str), " %s (", pt->name); } - if (status) { - sprintf(str + strlen(str), "%sstatus: %s", (empty ? "" : ", "), status); + if (po->task.status) { + sprintf(str + strlen(str), "%sstatus: %s", (empty ? "" : ", "), po->task.status); empty = FALSE; } - if (priority) { - sprintf(str + strlen(str), "%spriority: %s", (empty ? "" : ", "), priority); + if (po->task.priority) { + sprintf(str + strlen(str), "%spriority: %s", (empty ? "" : ", "), po->task.priority); empty = FALSE; } - if (date) { - sprintf(str + strlen(str), "%sdate: %s", (empty ? "" : ", "), format_date(date)); + if (po->task.date) { + sprintf(str + strlen(str), "%sdate: %s", (empty ? "" : ", "), format_date(po->task.date)); empty = FALSE; } - if (time) sprintf(str + strlen(str), "%stime: %s", (empty ? "" : ", "), format_date(time)); + if (po->task.time) sprintf(str + strlen(str), "%stime: %s", (empty ? "" : ", "), format_time(po->task.time)); strcat(str, ")"); puts(str); pit_action(pt->id, "task", str); } -static void task_log_delete(ulong id, char *name, ulong number_of_notes) +static void task_log_delete(int id, char *name, int number_of_notes) { char str[256]; - sprintf(str, "deleted task %lu: %s", id, name); + sprintf(str, "deleted task %d: %s", id, name); if (number_of_notes > 0) { - sprintf(str + strlen(str), " with %lu note%s", number_of_notes, (number_of_notes == 1 ? "" : "s")); + sprintf(str + strlen(str), " with %d note%s", number_of_notes, (number_of_notes == 1 ? "" : "s")); } puts(str); pit_action(id, "task", str); } -static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *date, time_t *time) +static void task_parse_options(char **arg, POptions po) { while(*++arg) { switch(pit_arg_option(arg)) { + case 'n': + po->task.name = pit_arg_string(++arg, "task name"); + break; case 's': - *status = pit_arg_string(++arg, "task status"); + po->task.status = pit_arg_string(++arg, "task status"); break; case 'p': - *priority = pit_arg_string(++arg, "task priority"); + po->task.priority = pit_arg_string(++arg, "task priority"); break; case 'd': - *date = pit_arg_date(++arg, "task date"); + po->task.date = pit_arg_date(++arg, "task date"); break; case 't': - *time = pit_arg_time(++arg, "task time"); + po->task.time = pit_arg_time(++arg, "task time"); break; - case 'n': - if (name) { - *name = pit_arg_string(++arg, "task name"); - break; - } /* else fall though */ default: die("invalid task option: %s", *arg); } @@ -247,14 +244,13 @@ static void task_parse_options(char **arg, char **name, char **status, char **pr void pit_task(char *argv[]) { + Options opt; + int number = 0; char **arg = &argv[1]; - char *name = NULL, *status = NULL, *priority = NULL; - time_t date = (time_t)0; - time_t time = (time_t)0; - ulong number = 0L; + memset(&opt, 0, sizeof(opt)); if (!*arg) { - task_list(name, status, priority, date, time); /* List all tasks (i.e. use default paramaters). */ + task_list(&opt); /* List all tasks (i.e. use default paramaters). */ } else { /* pit task [number] */ number = pit_arg_number(arg, NULL); if (number) { @@ -262,18 +258,18 @@ void pit_task(char *argv[]) } else { switch(pit_arg_option(arg)) { case 'c': /* pit task -c name [-s status] [-p priority] [-d date] [-t time] */ - name = pit_arg_string(++arg, "task name"); - task_parse_options(arg, NULL, &status, &priority, &date, &time); - task_create(name, status, priority, date, time); + opt.task.name = pit_arg_string(++arg, "task name"); + task_parse_options(arg, &opt); + task_create(&opt); break; case 'e': /* pit task -e [number] [-n name] [-s status] [-p priority] [-d date] [-t time] */ number = pit_arg_number(++arg, NULL); if (!number) --arg; - task_parse_options(arg, &name, &status, &priority, &date, &time); - if (!name && !status && !priority && !date && !time) { + task_parse_options(arg, &opt); + if (!opt.task.name && !opt.task.status && !opt.task.priority && !opt.task.date && !opt.task.time) { die("nothing to update"); } else { - task_update(number, name, status, priority, date, time); + task_update(number, &opt); } break; case 'd': /* pit task -d [number] */ @@ -281,15 +277,15 @@ void pit_task(char *argv[]) pit_task_delete(number, NULL); /* Delete the task, but keep its project. */ break; case 'q': /* pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]] */ - number = pit_arg_number(++arg, NULL); - if (number) { - task_show(number); + opt.task.id = pit_arg_number(++arg, NULL); + if (opt.task.id) { + task_show(opt.task.id); } else { - task_parse_options(--arg, &name, &status, &priority, &date, &time); - if (!name && !status && !priority && !date && !time) { + task_parse_options(--arg, &opt); + if (!opt.task.name && !opt.task.status && !opt.task.priority && !opt.task.date && !opt.task.time) { task_show(0); /* Show current task if any. */ } else { - task_list(name, status, priority, date, time); + task_list(&opt); } } break; diff --git a/src/util.c b/src/util.c index c6a0fe3..32e5241 100644 --- a/src/util.c +++ b/src/util.c @@ -18,6 +18,15 @@ char *mem2str(char *mem, int len) { return str; } +bool zero(char *mem, int len) { + char *pch = mem; + + while(pch - mem < len) { + if (*pch++) return FALSE; + } + return TRUE; +} + char *current_user() { static char *username = NULL;