/* See LICENSE file for copyright and license details. */ #include #include #include #include #include #define min(X,Y) (Xev.time = t; next->ev.text = malloc(sizeof(char) * l); strncpy(next->ev.text, text, l); next->ev.text = strtrim(next->ev.text); next->next = NULL; if (++evlist->count == 1) { evlist->first = next; evlist->last = next; } else { evlist->last->next = next; evlist->last = next; } } static int compare_tm(struct tm *t1, struct tm *t2) { if (t1->tm_year != t2->tm_year) return t1->tm_year - t2->tm_year; if (t1->tm_mon != t2->tm_mon) return t1->tm_mon - t2->tm_mon; if (t1->tm_mday != t2->tm_mday) return t1->tm_mday - t2->tm_mday; if (t1->tm_hour != t2->tm_hour) return t1->tm_hour - t2->tm_hour; return t1->tm_min - t2->tm_min; } static int compare_event(Event *ev1, Event *ev2) { return compare_tm(&ev1->time, &ev2->time); } static Options default_op() { Options op; time_t t_now = time(NULL); struct tm *now = localtime(&t_now); op.format_in = malloc(sizeof(char) * MAXLEN); op.format_out = malloc(sizeof(char) * MAXLEN); op.separator = malloc(sizeof(char) * MAXLEN); strcpy(op.format_in, default_format); strcpy(op.format_out, default_format); strcpy(op.separator, "\t"); op.from = *now; op.to = *now; return op; } /* * Saves the events in ev[] that happen between op->from and op->to in sel[] * sorted by date and returns their number. */ static int events_in_range(EventList *evlist, Options op, Event *sel) { EventNode *i; int n = 0; for (i = evlist->first; i != NULL; i = i->next) if (compare_tm(&i->ev.time, &op.from) >= 0 && compare_tm(&i->ev.time, &op.to) <= 0) sel[n++] = i->ev; qsort(sel, n, sizeof(Event), (int (*)(const void *, const void *))compare_event); return n; } static char * format_line(Event ev, Options op, char *out) { strftime(out, MAXLEN, op.format_out, &ev.time); strncat(out, op.separator, MAXLEN - strlen(out)); strncat(out, ev.text, MAXLEN - strlen(out)); return out; } static void read_input(Options op, EventList *evlist) { struct tm t; char line[MAXLEN], *text_ptr; while (fgets(line, MAXLEN, stdin) != NULL) if ((text_ptr = strptime(line, op.format_in, &t)) != NULL) add_event(t, text_ptr, evlist); } static Options read_op(int argc, char *argv[]) { Options op = default_op(); int i; /* Check for format specification. * This changes the way other options are read */ for (i = 1; i < argc; i++) { if (argv[i][0] == '+') { strncpy(op.format_in, &argv[i][1], MAXLEN); strncpy(op.format_out, &argv[i][1], MAXLEN); } } for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-v")) { puts("sdep-"VERSION); exit(0); } else if (!strcmp(argv[i], "-d")) { puts(default_format); exit(0); } else if (!strcmp(argv[i], "-s")) { strncpy(op.separator, argv[++i], MAXLEN); } else if (!strcmp(argv[i], "-f")) { if (i+1 >= argc || strptime(argv[i+1], op.format_in, &op.from) == NULL) op.from.tm_year = -1000000000; /* Very large number */ else i++; } else if (!strcmp(argv[i], "-t")) { if (i+1 >= argc || strptime(argv[i+1], op.format_in, &op.to) == NULL) op.to.tm_year = 1000000000; /* Very small number */ else i++; } else if (!strcmp(argv[i], "-w")) { op.format_out = argv[++i]; } else if (argv[i][0] != '+' && strlen(argv[i]) != 0) { fprintf(stderr, "usage: sdep [-dv]"); fprintf(stderr, " [+format] [-f [date]] [-t [date]]"); fprintf(stderr, " [-w format] [-s string]\n"); exit(1); } } return op; } static char * strtrim(char *t) { char *s; for (s = &t[strlen(t)-1]; s != t && isspace(*s); *s = '\0', s--); for (; *t != '\0' && isspace(*t); t++); return t; } static void write_output(Options op, Event *ev, int n) { char outline[MAXLEN]; int i; for (i = 0; i < n; i++) printf("%s\n", format_line(ev[i], op, outline)); } int main(int argc, char *argv[]) { Options op; EventList evlist = {0}; Event *selected; op = read_op(argc, argv); read_input(op, &evlist); selected = malloc(sizeof(Event) * evlist.count); write_output(op, selected, events_in_range(&evlist, op, selected)); return 0; }