aboutsummaryrefslogtreecommitdiff
path: root/sdep.c
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2021-05-08 19:19:41 +0200
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2021-05-08 19:19:41 +0200
commit82bcfe3f25b1f0c08c93fd35497019b546e24ce2 (patch)
tree055309330ff16f6d3f754b2ef6eaff92fe3925ed /sdep.c
parent61d15dd4854fe4607442b87602448d6dee16b6a8 (diff)
downloadsdep-82bcfe3f25b1f0c08c93fd35497019b546e24ce2.tar.gz
sdep-82bcfe3f25b1f0c08c93fd35497019b546e24ce2.zip
First commit, v0.1
Diffstat (limited to '')
-rw-r--r--sdep.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/sdep.c b/sdep.c
new file mode 100644
index 0000000..e2b9442
--- /dev/null
+++ b/sdep.c
@@ -0,0 +1,250 @@
1/* See LICENSE file for copyright and license details. */
2
3#include <ctype.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <time.h>
8
9#define min(X,Y) (X<Y ? X : Y)
10
11/*
12 * Maximum number of characters in a line. The rest will be truncated.
13 * Change this if you need very long lines.
14 */
15static const int MAXLEN = 10000;
16
17/*
18 * Default date format. Anything that strftime(3) understands works, but
19 * it should determine a date completely up to the minute.
20 */
21static char *default_format = "%Y-%m-%d %H:%M";
22
23typedef struct Event Event;
24typedef struct EventList EventList;
25typedef struct EventNode EventNode;
26typedef struct Options Options;
27
28struct Event{
29 struct tm time;
30 char *text;
31};
32
33struct EventList {
34 EventNode *first;
35 EventNode *last;
36 int count;
37};
38
39struct EventNode {
40 Event ev;
41 EventNode *next;
42};
43
44struct Options {
45 struct tm from;
46 struct tm to;
47 char *format_in;
48 char *format_out;
49 char *separator;
50};
51
52static void add_event(struct tm t, char *text, EventList *evlist);
53static int compare_tm(struct tm *t1, struct tm *t2);
54static int compare_event(Event *event1, Event *event2);
55static Options default_op();
56static int events_in_range(EventList *evlist, Options op, Event *sel);
57static char *format_line(Event ev, Options op, char *out);
58static void read_input(Options op, EventList *evlist);
59static Options read_op(int argc, char *argv[]);
60static char *strtrim(char *t);
61static void write_output(Options op, Event *ev, int n);
62
63
64static void
65add_event(struct tm t, char *text, EventList *evlist)
66{
67 int l = strlen(text)+1;
68 EventNode *next = malloc(sizeof(EventNode));
69
70 next->ev.time = t;
71 next->ev.text = malloc(sizeof(char) * l);
72 strncpy(next->ev.text, text, l);
73 next->ev.text = strtrim(next->ev.text);
74 next->next = NULL;
75
76 if (++evlist->count == 1) {
77 evlist->first = next;
78 evlist->last = next;
79 } else {
80 evlist->last->next = next;
81 evlist->last = next;
82 }
83}
84
85static int
86compare_tm(struct tm *t1, struct tm *t2)
87{
88 if (t1->tm_year != t2->tm_year)
89 return t1->tm_year - t2->tm_year;
90 if (t1->tm_mon != t2->tm_mon)
91 return t1->tm_mon - t2->tm_mon;
92 if (t1->tm_mday != t2->tm_mday)
93 return t1->tm_mday - t2->tm_mday;
94 if (t1->tm_hour != t2->tm_hour)
95 return t1->tm_hour - t2->tm_hour;
96 return t1->tm_min - t2->tm_min;
97}
98
99static int
100compare_event(Event *ev1, Event *ev2)
101{
102 return compare_tm(&ev1->time, &ev2->time);
103}
104
105static Options
106default_op()
107{
108 Options op;
109 time_t t_now = time(NULL);
110 struct tm *now = localtime(&t_now);
111
112 op.format_in = malloc(sizeof(char) * MAXLEN);
113 op.format_out = malloc(sizeof(char) * MAXLEN);
114 op.separator = malloc(sizeof(char) * MAXLEN);
115 strcpy(op.format_in, default_format);
116 strcpy(op.format_out, default_format);
117 strcpy(op.separator, "\t");
118 op.from = *now;
119 op.to = *now;
120
121 return op;
122}
123
124/*
125* Saves the events in ev[] that happen between op->from and op->to in sel[]
126* sorted by date and returns their number.
127*/
128static int
129events_in_range(EventList *evlist, Options op, Event *sel)
130{
131 EventNode *i;
132 int n = 0;
133
134
135 for (i = evlist->first; i != NULL; i = i->next)
136 if (compare_tm(&i->ev.time, &op.from) >= 0 &&
137 compare_tm(&i->ev.time, &op.to) <= 0)
138 sel[n++] = i->ev;
139
140 qsort(sel, n, sizeof(Event),
141 (int (*)(const void *, const void *))compare_event);
142
143 return n;
144}
145
146static char *
147format_line(Event ev, Options op, char *out)
148{
149 strftime(out, MAXLEN, op.format_out, &ev.time);
150 strncat(out, op.separator, MAXLEN - strlen(out));
151 strncat(out, ev.text, MAXLEN - strlen(out));
152
153 return out;
154}
155
156static void
157read_input(Options op, EventList *evlist)
158{
159 struct tm t;
160 char line[MAXLEN], *text_ptr;
161
162 while (fgets(line, MAXLEN, stdin) != NULL)
163 if ((text_ptr = strptime(line, op.format_in, &t)) != NULL)
164 add_event(t, text_ptr, evlist);
165}
166
167static Options
168read_op(int argc, char *argv[])
169{
170 Options op = default_op();
171 int i;
172
173 /* Check for format specification.
174 * This changes the way other options are read */
175 for (i = 1; i < argc; i++) {
176 if (argv[i][0] == '+') {
177 strncpy(op.format_in, &argv[i][1], MAXLEN);
178 strncpy(op.format_out, &argv[i][1], MAXLEN);
179 }
180 }
181
182 for (i = 1; i < argc; i++) {
183 if (!strcmp(argv[i], "-v")) {
184 puts("sdep-"VERSION);
185 exit(0);
186 } else if (!strcmp(argv[i], "-d")) {
187 puts(default_format);
188 exit(0);
189 } else if (!strcmp(argv[i], "-s")) {
190 strncpy(op.separator, argv[++i], MAXLEN);
191 } else if (!strcmp(argv[i], "-f")) {
192 if (i+1 >= argc ||
193 strptime(argv[i+1], op.format_in, &op.from) == NULL)
194 op.from.tm_year = -1000000000; /* Very large number */
195 else
196 i++;
197 } else if (!strcmp(argv[i], "-t")) {
198 if (i+1 >= argc ||
199 strptime(argv[i+1], op.format_in, &op.to) == NULL)
200 op.to.tm_year = 1000000000; /* Very small number */
201 else
202 i++;
203 } else if (!strcmp(argv[i], "-w")) {
204 op.format_out = argv[++i];
205 } else if (argv[i][0] != '+' && strlen(argv[i]) != 0) {
206 fprintf(stderr, "usage: sdep [-dv]");
207 fprintf(stderr, " [+format] [-f [date]] [-t [date]]");
208 fprintf(stderr, " [-w format] [-s string]\n");
209 exit(1);
210 }
211 }
212
213 return op;
214}
215
216static char *
217strtrim(char *t)
218{
219 char *s;
220
221 for (s = &t[strlen(t)-1]; s != t && isspace(*s); *s = '\0', s--);
222 for (; *t != '\0' && isspace(*t); t++);
223
224 return t;
225}
226
227static void
228write_output(Options op, Event *ev, int n)
229{
230 char outline[MAXLEN];
231 int i;
232
233 for (i = 0; i < n; i++)
234 printf("%s\n", format_line(ev[i], op, outline));
235}
236
237int
238main(int argc, char *argv[])
239{
240 Options op;
241 EventList evlist = {0};
242 Event *selected;
243
244 op = read_op(argc, argv);
245 read_input(op, &evlist);
246 selected = malloc(sizeof(Event) * evlist.count);
247 write_output(op, selected, events_in_range(&evlist, op, selected));
248
249 return 0;
250}

Generated with cgit - Back to sebastiano.tronto.net