aboutsummaryrefslogtreecommitdiff
path: root/sdep-0.2
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2023-05-15 18:28:45 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2023-05-15 18:28:45 +0200
commit3a33fa3c7921c69efbc9beaaa922452ba2eaf271 (patch)
tree0d903c8d075752a1c4bf63eab783c702aa3557b6 /sdep-0.2
parent022d9c173d78c04ec2569a2394e2b04b81d60794 (diff)
downloadsdep-3a33fa3c7921c69efbc9beaaa922452ba2eaf271.tar.gz
sdep-3a33fa3c7921c69efbc9beaaa922452ba2eaf271.zip
Makefile fix
Diffstat (limited to 'sdep-0.2')
-rw-r--r--sdep-0.2/LICENSE21
-rw-r--r--sdep-0.2/Makefile61
-rw-r--r--sdep-0.2/sdep.194
-rw-r--r--sdep-0.2/sdep.c277
4 files changed, 453 insertions, 0 deletions
diff --git a/sdep-0.2/LICENSE b/sdep-0.2/LICENSE
new file mode 100644
index 0000000..b47cbe9
--- /dev/null
+++ b/sdep-0.2/LICENSE
@@ -0,0 +1,21 @@
1MIT License
2
3Copyright (c) 2021-2023 Sebastiano Tronto
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/sdep-0.2/Makefile b/sdep-0.2/Makefile
new file mode 100644
index 0000000..444c6f2
--- /dev/null
+++ b/sdep-0.2/Makefile
@@ -0,0 +1,61 @@
1# See LICENSE file for copyright and license details.
2
3VERSION = 0.2
4
5PREFIX = /usr/local
6MANPREFIX = ${PREFIX}/share/man
7SCRIPTS = sdep-add sdep-checknow sdep-checkpast sdep-clear sdep-edit sdep-list
8
9CPPFLAGS = -D_XOPEN_SOURCE=700 -DVERSION=\"${VERSION}\"
10CFLAGS = -pedantic -Wall -Os ${CPPFLAGS}
11DBGFLAGS = -pedantic -Wall -Wextra \
12 -fsanitize=address -fsanitize=undefined ${CPPFLAGS}
13
14CC = cc
15
16
17all: options sdep
18
19options:
20 @echo sdep build options:
21 @echo "CFLAGS = ${CFLAGS}"
22 @echo "CC = ${CC}"
23
24sdep:
25 ${CC} ${CFLAGS} -o sdep sdep.c
26
27debug:
28 ${CC} ${CFLAGS} -o sdep sdep.c
29
30clean:
31 rm -rf sdep sdep-${VERSION}.tar.gz
32
33dist: clean
34 mkdir -p sdep-${VERSION}
35 cp -R LICENSE Makefile README sdep.1 sdep.c sdep-${VERSION}
36 tar -cf sdep-${VERSION}.tar sdep-${VERSION}
37 gzip sdep-${VERSION}.tar
38 rm -rf sdep-${VERSION}
39
40install: all
41 mkdir -p ${DESTDIR}${PREFIX}/bin
42 cp -f sdep ${DESTDIR}${PREFIX}/bin/sdep
43 chmod 755 ${DESTDIR}${PREFIX}/bin/sdep
44 mkdir -p ${DESTDIR}${MANPREFIX}/man1
45 sed "s/VERSION/${VERSION}/g" < sdep.1 \
46 > ${DESTDIR}${MANPREFIX}/man1/sdep.1
47 chmod 644 ${DESTDIR}${MANPREFIX}/man1/sdep.1
48
49scripts:
50 for s in ${SCRIPTS}; do\
51 sed "s|SDEPDATA|${SD}|g" < scripts/$$s > \
52 ${DESTDIR}${PREFIX}/bin/$$s ; \
53 chmod 755 ${DESTDIR}${PREFIX}/bin/$$s ;\
54 done
55
56uninstall:
57 rm -rf ${DESTDIR}${PREFIX}/bin/sdep ${DESTDIR}${MANPREFIX}/man1/sdep.1
58 for s in ${SCRIPTS}; do rm -rf ${DESTDIR}${PREFIX}/bin/$$s; done
59
60.PHONY: all options debug clean dist install scripts uninstall
61
diff --git a/sdep-0.2/sdep.1 b/sdep-0.2/sdep.1
new file mode 100644
index 0000000..302c45d
--- /dev/null
+++ b/sdep-0.2/sdep.1
@@ -0,0 +1,94 @@
1.Dd May 13, 2021
2.Dt SDEP 1
3.Os
4.Sh NAME
5.Nm sdep
6.Nd a simple "date+event" line parser
7
8.Sh SYNOPSIS
9.Nm
10.Op Fl dv
11.Op Ar +format
12.Op Fl f Op Ar date
13.Op Fl t Op Ar date
14.Op Fl w Ar format
15.Op Fl s Ar string
16
17.Sh DESCRIPTION
18.Nm
19reads lines of the form
20
21.Dl Ar "date text"
22
23from stdin and writes to stdout those lines such that
24.Ar date
25is between the dates specified by the
26.Fl f
27and
28.Fl t
29options, both defaulting to the current minute.
30The dates should correspond to a unique minute in time. The format for
31.Ar date
32can be specified with the same syntax as for
33.Xr date 1 .
34
35The options are as follows:
36.Bl -tag -width Ds
37.It Fl d
38print the default date format and exit.
39.It Fl f Op Ar date
40initial date for the range (default: current minute). If
41.Ar date
42is not specified there will be no lower bound for the dates.
43.It Fl s Ar string
44change the string that separates the date from the text in the output
45lines (deafult: "\t").
46.It Fl t Op Ar date
47final date for the range (default: current minute). If
48.Ar date
49is not specified then there will be no upper bound for the dates.
50.It Fl v
51print version information and exit.
52.It Fl w Ar format
53change the format in which the date is written in the output lines.
54
55.Sh EXAMPLES
56If
57.Ar events.txt
58contains lines formatted as
59.Ar "date text"
60then
61
62.Dl sdep -f <events.txt
63
64will print all the lines whose date is in the past, while
65
66.Dl sdep -t -w "%A" <events.txt
67
68will print all lines whose date is in the future, showing only the day of the
69week and the text.
70
71.Dl sdep -f "1999-01-01 00:00" -t "1999-12-31 23:59" -w "" <events.txt
72
73will show only the
74.Ar text
75of all lines with a date in 1999. You can specify a different format for the
76dates, for example
77
78.Dl sdep +"%m/%d/%Y %I:%M%p" -t "12/31/2020 11:59pm" -w "" <events.txt
79
80will match all dates from December 31st, 2020, one minute before midnight
81(included). Note: this only works if your locale has an am/pm format, see
82.Xr date 1 .
83
84.Sh AUTHORS
85.An Sebastiano Tronto Aq Mt sebastiano.tronto@gmail.com
86
87.Sh SOURCE CODE
88Source code is available at
89.Lk https://github.com/sebastianotronto/sdep
90
91.Sh SEE ALSO
92.Xr date 1 ,
93.Xr strftime 3 ,
94.Xr strptime 3
diff --git a/sdep-0.2/sdep.c b/sdep-0.2/sdep.c
new file mode 100644
index 0000000..629387b
--- /dev/null
+++ b/sdep-0.2/sdep.c
@@ -0,0 +1,277 @@
1/* See LICENSE file for copyright and license details. */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <time.h>
7
8/*
9 * Maximum number of characters in a line. The rest will be truncated.
10 * Change this if you need very long lines.
11 */
12#define MAXLEN 10000
13
14/*
15 * Default date format. Anything that strftime(3) understands works, but
16 * it should determine a date completely up to the minute.
17 */
18static char *default_format = "%Y-%m-%d %H:%M";
19
20
21typedef struct Event Event;
22typedef struct EventList EventList;
23typedef struct EventNode EventNode;
24typedef struct Options Options;
25
26struct Event{
27 struct tm time;
28 char *text;
29};
30
31struct EventList {
32 EventNode *first;
33 EventNode *last;
34 int count;
35};
36
37struct EventNode {
38 Event ev;
39 EventNode *next;
40};
41
42struct Options {
43 struct tm from;
44 struct tm to;
45 char *format_in;
46 char *format_out;
47 char *separator;
48};
49
50static void add_event(struct tm, char *, EventList *);
51static int compare_tm(const void *, const void *);
52static int compare_event(const void *, const void *);
53static Options default_op(void);
54static int events_in_range(EventList *, Options, Event *);
55static char *format_line(Event, Options, char *);
56static int is_space(char);
57static void read_input(Options, EventList *);
58static Options read_op(int, char *[]);
59static void str_copy(char *, char *, int);
60static char *str_trim(char *);
61static void write_output(Options, Event *, int);
62
63
64static void
65add_event(struct tm t, char *text, EventList *evlist)
66{
67 size_t l = strlen(text)+1;
68 EventNode *next = malloc(sizeof(EventNode));
69
70 next->ev.time = t;
71 next->ev.text = malloc(l);
72 str_copy(next->ev.text, text, l);
73 next->ev.text = str_trim(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(const void *v1, const void *v2)
87{
88 const struct tm *t1 = v1;
89 const struct tm *t2 = v2;
90
91 if (t1->tm_year != t2->tm_year)
92 return t1->tm_year - t2->tm_year;
93 if (t1->tm_mon != t2->tm_mon)
94 return t1->tm_mon - t2->tm_mon;
95 if (t1->tm_mday != t2->tm_mday)
96 return t1->tm_mday - t2->tm_mday;
97 if (t1->tm_hour != t2->tm_hour)
98 return t1->tm_hour - t2->tm_hour;
99 return t1->tm_min - t2->tm_min;
100}
101
102static int
103compare_event(const void *v1, const void *v2)
104{
105 const Event *ev1 = v1;
106 const Event *ev2 = v2;
107
108 return compare_tm(&ev1->time, &ev2->time);
109}
110
111static Options
112default_op(void)
113{
114 Options op;
115 time_t t_now = time(NULL);
116 struct tm *now = localtime(&t_now);
117
118 op.format_in = malloc(MAXLEN);
119 op.format_out = malloc(MAXLEN);
120 op.separator = malloc(MAXLEN);
121 strcpy(op.format_in, default_format);
122 strcpy(op.format_out, default_format);
123 strcpy(op.separator, "\t");
124 op.from = *now;
125 op.to = *now;
126
127 return op;
128}
129
130/*
131 * Saves the events in ev[] that happen between op->from and op->to in sel[]
132 * sorted by date and returns their number.
133 */
134static int
135events_in_range(EventList *evlist, Options op, Event *sel)
136{
137 EventNode *i;
138 int n = 0;
139
140 for (i = evlist->first; i != NULL; i = i->next)
141 if (compare_tm(&i->ev.time, &op.from) >= 0 &&
142 compare_tm(&i->ev.time, &op.to) <= 0)
143 sel[n++] = i->ev;
144
145 qsort(sel, n, sizeof(Event), compare_event);
146
147 return n;
148}
149
150static char *
151format_line(Event ev, Options op, char *out)
152{
153 size_t l;
154
155 strftime(out, MAXLEN, op.format_out, &ev.time);
156 l = strlen(out);
157
158 str_copy(out+l, op.separator, MAXLEN - l);
159 l = strlen(out);
160
161 str_copy(out+l, ev.text, MAXLEN - l);
162
163 return out;
164}
165
166static int
167is_space(char c)
168{
169 return c == ' ' || c == '\t';
170}
171
172static void
173read_input(Options op, EventList *evlist)
174{
175 struct tm t;
176 char line[MAXLEN], *text_ptr;
177
178 while (fgets(line, MAXLEN, stdin) != NULL)
179 if ((text_ptr = strptime(line, op.format_in, &t)) != NULL)
180 add_event(t, text_ptr, evlist);
181}
182
183static Options
184read_op(int argc, char *argv[])
185{
186 Options op = default_op();
187 int i;
188
189 /* Check for format specification.
190 * This changes the way other options are read */
191 for (i = 1; i < argc; i++) {
192 if (argv[i][0] == '+') {
193 str_copy(op.format_in, &argv[i][1], MAXLEN);
194 str_copy(op.format_out, &argv[i][1], MAXLEN);
195 }
196 }
197
198 for (i = 1; i < argc; i++) {
199 if (!strcmp(argv[i], "-v")) {
200 puts("sdep-"VERSION);
201 exit(0);
202 } else if (!strcmp(argv[i], "-d")) {
203 puts(default_format);
204 exit(0);
205 } else if (!strcmp(argv[i], "-s")) {
206 str_copy(op.separator, argv[++i], MAXLEN);
207 } else if (!strcmp(argv[i], "-f")) {
208 if (i+1 >= argc ||
209 strptime(argv[i+1], op.format_in, &op.from) == NULL)
210 op.from.tm_year = -1000000000; /* Very large number */
211 else
212 i++;
213 } else if (!strcmp(argv[i], "-t")) {
214 if (i+1 >= argc ||
215 strptime(argv[i+1], op.format_in, &op.to) == NULL)
216 op.to.tm_year = 1000000000; /* Very small number */
217 else
218 i++;
219 } else if (!strcmp(argv[i], "-w")) {
220 op.format_out = argv[++i];
221 } else if (argv[i][0] != '+' && strlen(argv[i]) != 0) {
222 fprintf(stderr, "usage: sdep [-dv]");
223 fprintf(stderr, " [+format] [-f [date]] [-t [date]]");
224 fprintf(stderr, " [-w format] [-s string]\n");
225 exit(1);
226 }
227 }
228
229 return op;
230}
231
232/*
233 * Copy up to n characters of the string str to dst and append '\0'.
234 * Suggested by NRK.
235 */
236static void
237str_copy(char *dst, char *src, int n)
238{
239 if (memccpy(dst, src, '\0', n) == NULL)
240 dst[n-1] = '\0';
241}
242
243static char *
244str_trim(char *t)
245{
246 char *s;
247
248 for (s = &t[strlen(t)-1]; s != t && is_space(*s); *s = '\0', s--);
249 for (; *t != '\0' && is_space(*t); t++);
250
251 return t;
252}
253
254static void
255write_output(Options op, Event *ev, int n)
256{
257 char outline[MAXLEN];
258 int i;
259
260 for (i = 0; i < n; i++)
261 printf("%s\n", format_line(ev[i], op, outline));
262}
263
264int
265main(int argc, char *argv[])
266{
267 Options op;
268 EventList evlist = {0};
269 Event *selected;
270
271 op = read_op(argc, argv);
272 read_input(op, &evlist);
273 selected = malloc(sizeof(Event) * evlist.count);
274 write_output(op, selected, events_in_range(&evlist, op, selected));
275
276 return 0;
277}

Generated with cgit - Back to sebastiano.tronto.net