Simpler data types; header and pit info; refactored options

This commit is contained in:
Mike Dvorkin
2010-08-10 22:34:09 -07:00
parent 21b447d4ea
commit 346b35bf2d
14 changed files with 385 additions and 305 deletions

View File

@@ -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[])

View File

@@ -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");
}

View File

@@ -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");

View File

@@ -3,7 +3,7 @@
#include <stdio.h>
#include "pit.h"
void pit_note_delete(ulong id, PTask pt)
void pit_note_delete(int id, PTask pt)
{
}

View File

@@ -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

View File

@@ -3,14 +3,14 @@
#include <stdio.h>
#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

View File

@@ -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);

View File

@@ -4,10 +4,19 @@
#include <stdio.h>
#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;
}

View File

@@ -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 <time.h>
@@ -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);

View File

@@ -3,17 +3,17 @@
#include <stdio.h>
#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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -2,16 +2,16 @@
#include <string.h>
#include <stdio.h>
#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;

View File

@@ -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;