Begin implementing liblocus
Liblocus is a part of libmailutils that will provide functions for manipulating source file locations, for use in lexers, grammars, etc. This will expand the functionality of the mu_locus type and logstreams. * configure.ac: add libmailutils/locus/ * include/mailutils/assoc.h (mu_assoc_install_ref2): New proto. * libmailutils/base/assoc.c (mu_assoc_install_ref2): New entry point. * libmailutils/base/copyfile.c (copy_regular_file): Add typecasts. * libmailutils/Makefile.am: Build liblocus * libmailutils/locus/Makefile.am: New file. * libmailutils/locus/debug.c: New file. * libmailutils/locus/ident.c: New file. * libmailutils/locus/tracker.c: New file. * libmailutils/tests/Makefile.am: New file. * libmailutils/tests/tracker.c: New file.
Showing
14 changed files
with
524 additions
and
5 deletions
... | @@ -1495,6 +1495,7 @@ AC_CONFIG_FILES([ | ... | @@ -1495,6 +1495,7 @@ AC_CONFIG_FILES([ |
1495 | libmailutils/filter/Makefile | 1495 | libmailutils/filter/Makefile |
1496 | libmailutils/imapio/Makefile | 1496 | libmailutils/imapio/Makefile |
1497 | libmailutils/list/Makefile | 1497 | libmailutils/list/Makefile |
1498 | libmailutils/locus/Makefile | ||
1498 | libmailutils/mailbox/Makefile | 1499 | libmailutils/mailbox/Makefile |
1499 | libmailutils/mailer/Makefile | 1500 | libmailutils/mailer/Makefile |
1500 | libmailutils/mime/Makefile | 1501 | libmailutils/mime/Makefile | ... | ... |
... | @@ -37,6 +37,8 @@ int mu_assoc_install (mu_assoc_t assoc, const char *name, void *value); | ... | @@ -37,6 +37,8 @@ int mu_assoc_install (mu_assoc_t assoc, const char *name, void *value); |
37 | 37 | ||
38 | int mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr); | 38 | int mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr); |
39 | int mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval); | 39 | int mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval); |
40 | int mu_assoc_install_ref2 (mu_assoc_t assoc, const char *name, | ||
41 | void *ret_val, const char **ret_name); | ||
40 | 42 | ||
41 | int mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator); | 43 | int mu_assoc_get_iterator (mu_assoc_t assoc, mu_iterator_t *piterator); |
42 | int mu_assoc_remove (mu_assoc_t assoc, const char *name); | 44 | int mu_assoc_remove (mu_assoc_t assoc, const char *name); | ... | ... |
include/mailutils/locus.h
0 → 100644
1 | #ifndef _MAILUTILS_LOCUS_H | ||
2 | #define _MAILUTILS_LOCUS_H | ||
3 | |||
4 | #include <string.h> | ||
5 | |||
6 | struct mu_locus_point | ||
7 | { | ||
8 | char const *mu_file; | ||
9 | unsigned mu_line; | ||
10 | unsigned mu_col; | ||
11 | }; | ||
12 | |||
13 | struct mu_locus_range | ||
14 | { | ||
15 | struct mu_locus_point beg; | ||
16 | struct mu_locus_point end; | ||
17 | }; | ||
18 | |||
19 | typedef struct mu_locus_track *mu_locus_track_t; | ||
20 | |||
21 | int mu_ident_ref (char const *name, char const **refname); | ||
22 | int mu_ident_deref (char const *); | ||
23 | |||
24 | static inline int | ||
25 | mu_locus_point_same_file (struct mu_locus_point const *a, | ||
26 | struct mu_locus_point const *b) | ||
27 | { | ||
28 | return a->mu_file == b->mu_file | ||
29 | || (a->mu_file && b->mu_file && strcmp(a->mu_file, b->mu_file) == 0); | ||
30 | } | ||
31 | |||
32 | static inline int | ||
33 | mu_locus_point_same_line (struct mu_locus_point const *a, | ||
34 | struct mu_locus_point const *b) | ||
35 | { | ||
36 | return mu_locus_point_same_file (a, b) && a->mu_line == b->mu_line; | ||
37 | } | ||
38 | |||
39 | void mu_lrange_debug (struct mu_locus_range const *loc, | ||
40 | char const *fmt, ...); | ||
41 | |||
42 | int mu_locus_track_create (mu_locus_track_t *ret, | ||
43 | char const *file_name, size_t max_lines); | ||
44 | void mu_locus_track_free (mu_locus_track_t trk); | ||
45 | void mu_locus_track_destroy (mu_locus_track_t *trk); | ||
46 | size_t mu_locus_track_level (mu_locus_track_t trk); | ||
47 | void mu_locus_tracker_advance (struct mu_locus_track *trk, | ||
48 | struct mu_locus_range *loc, | ||
49 | char const *text, size_t leng); | ||
50 | void mu_locus_tracker_retreat (struct mu_locus_track *trk, size_t n); | ||
51 | |||
52 | |||
53 | |||
54 | #endif |
include/mailutils/yyloc.h
0 → 100644
1 | #define YYLTYPE struct mu_locus_range | ||
2 | #define YYLLOC_DEFAULT(Current, Rhs, N) \ | ||
3 | do \ | ||
4 | { \ | ||
5 | if (N) \ | ||
6 | { \ | ||
7 | (Current).beg = YYRHSLOC(Rhs, 1).beg; \ | ||
8 | (Current).end = YYRHSLOC(Rhs, N).end; \ | ||
9 | } \ | ||
10 | else \ | ||
11 | { \ | ||
12 | (Current).beg = YYRHSLOC(Rhs, 0).end; \ | ||
13 | (Current).end = (Current).beg; \ | ||
14 | } \ | ||
15 | } while (0) | ||
16 | #define YY_LOCATION_PRINT(File, Loc) \ | ||
17 | do \ | ||
18 | { \ | ||
19 | if (!mu_locus_point_same_file (&(Loc).beg, &(Loc).end)) \ | ||
20 | fprintf (File, "%s:%u.%u-%s:%u.%u", \ | ||
21 | (Loc).beg.mu_file, \ | ||
22 | (Loc).beg.mu_line, (Loc).beg.mu_col, \ | ||
23 | (Loc).end.mu_file, \ | ||
24 | (Loc).end.mu_line, (Loc).end.mu_col); \ | ||
25 | else if ((Loc).beg.mu_line != (Loc).end.mu_line) \ | ||
26 | fprintf (File, "%s:%u.%u-%u.%u", \ | ||
27 | (Loc).beg.mu_file, \ | ||
28 | (Loc).beg.mu_line, (Loc).beg.mu_col, \ | ||
29 | (Loc).end.mu_line, (Loc).end.mu_col); \ | ||
30 | else if ((Loc).beg.mu_col != (Loc).end.mu_col) \ | ||
31 | fprintf (File, "%s:%u.%u-%u", \ | ||
32 | (Loc).beg.mu_file, \ | ||
33 | (Loc).beg.mu_line, (Loc).beg.mu_col, \ | ||
34 | (Loc).end.mu_col); \ | ||
35 | else \ | ||
36 | fprintf (File, "%s:%u.%u", \ | ||
37 | (Loc).beg.mu_file, \ | ||
38 | (Loc).beg.mu_line, (Loc).beg.mu_col); \ | ||
39 | } while (0) | ||
40 | |||
41 | |||
42 |
... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
18 | 18 | ||
19 | SUBDIRS = \ | 19 | SUBDIRS = \ |
20 | auth base address list sockaddr cidr cfg cli diag\ | 20 | auth base address list sockaddr cidr cfg cli diag\ |
21 | filter mailbox mailer mime msgset opt server string stream stdstream\ | 21 | filter locus mailbox mailer mime msgset opt server string stream stdstream\ |
22 | property url imapio datetime . tests | 22 | property url imapio datetime . tests |
23 | 23 | ||
24 | lib_LTLIBRARIES = libmailutils.la | 24 | lib_LTLIBRARIES = libmailutils.la |
... | @@ -39,6 +39,7 @@ libmailutils_la_LIBADD = \ | ... | @@ -39,6 +39,7 @@ libmailutils_la_LIBADD = \ |
39 | filter/libfilter.la\ | 39 | filter/libfilter.la\ |
40 | imapio/libimapio.la\ | 40 | imapio/libimapio.la\ |
41 | list/liblist.la\ | 41 | list/liblist.la\ |
42 | locus/liblocus.la\ | ||
42 | mailbox/libmailbox.la\ | 43 | mailbox/libmailbox.la\ |
43 | mailer/libmailer.la\ | 44 | mailer/libmailer.la\ |
44 | mime/libmime.la\ | 45 | mime/libmime.la\ | ... | ... |
... | @@ -387,7 +387,9 @@ mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr) | ... | @@ -387,7 +387,9 @@ mu_assoc_lookup_ref (mu_assoc_t assoc, const char *name, void *dataptr) |
387 | } | 387 | } |
388 | 388 | ||
389 | int | 389 | int |
390 | mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval) | 390 | mu_assoc_install_ref2 (mu_assoc_t assoc, const char *name, |
391 | void *ret_val, | ||
392 | const char **ret_name) | ||
391 | { | 393 | { |
392 | int rc; | 394 | int rc; |
393 | int inst; | 395 | int inst; |
... | @@ -425,11 +427,20 @@ mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval) | ... | @@ -425,11 +427,20 @@ mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval) |
425 | assoc_elem_link (assoc, idx); | 427 | assoc_elem_link (assoc, idx); |
426 | } | 428 | } |
427 | 429 | ||
428 | *(void**)pval = &assoc->tab[idx]->data; | 430 | *(void**)ret_val = &assoc->tab[idx]->data; |
431 | if (ret_name) | ||
432 | *ret_name = assoc->tab[idx]->name; | ||
433 | |||
429 | return inst ? 0 : MU_ERR_EXISTS; | 434 | return inst ? 0 : MU_ERR_EXISTS; |
430 | } | 435 | } |
431 | 436 | ||
432 | int | 437 | int |
438 | mu_assoc_install_ref (mu_assoc_t assoc, const char *name, void *pval) | ||
439 | { | ||
440 | return mu_assoc_install_ref2 (assoc, name, pval, NULL); | ||
441 | } | ||
442 | |||
443 | int | ||
433 | mu_assoc_remove (mu_assoc_t assoc, const char *name) | 444 | mu_assoc_remove (mu_assoc_t assoc, const char *name) |
434 | { | 445 | { |
435 | int rc; | 446 | int rc; | ... | ... |
... | @@ -163,7 +163,7 @@ copy_regular_file (const char *srcpath, const char *dstpath, int flags, | ... | @@ -163,7 +163,7 @@ copy_regular_file (const char *srcpath, const char *dstpath, int flags, |
163 | rc = mu_stream_ioctl (dst, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans); | 163 | rc = mu_stream_ioctl (dst, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans); |
164 | if (rc == 0) | 164 | if (rc == 0) |
165 | { | 165 | { |
166 | if (fchmod ((int) trans[0], mode)) | 166 | if (fchmod ((int) (intptr_t) trans[0], mode)) |
167 | { | 167 | { |
168 | mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, | 168 | mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, |
169 | (_("%s: cannot chmod: %s"), | 169 | (_("%s: cannot chmod: %s"), |
... | @@ -193,7 +193,7 @@ copy_regular_file (const char *srcpath, const char *dstpath, int flags, | ... | @@ -193,7 +193,7 @@ copy_regular_file (const char *srcpath, const char *dstpath, int flags, |
193 | 193 | ||
194 | if (gid != -1) | 194 | if (gid != -1) |
195 | { | 195 | { |
196 | if (fchown ((int) trans[0], uid, gid)) | 196 | if (fchown ((int) (intptr_t) trans[0], uid, gid)) |
197 | { | 197 | { |
198 | mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, | 198 | mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, |
199 | (_("%s: cannot chown to %lu.%lu: %s"), | 199 | (_("%s: cannot chown to %lu.%lu: %s"), | ... | ... |
libmailutils/locus/Makefile.am
0 → 100644
1 | # GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | # Copyright (C) 2017 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # This library is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU Lesser General Public | ||
6 | # License as published by the Free Software Foundation; either | ||
7 | # version 3 of the License, or (at your option) any later version. | ||
8 | # | ||
9 | # This library is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # Lesser General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU Lesser General | ||
15 | # Public License along with this library. If not, see | ||
16 | # <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | noinst_LTLIBRARIES = liblocus.la | ||
19 | |||
20 | liblocus_la_SOURCES = \ | ||
21 | ident.c\ | ||
22 | debug.c\ | ||
23 | tracker.c | ||
24 | |||
25 | AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils | ||
26 |
libmailutils/locus/debug.c
0 → 100644
1 | #include <stdlib.h> | ||
2 | #include <stdarg.h> | ||
3 | #include <mailutils/types.h> | ||
4 | #include <mailutils/locus.h> | ||
5 | #include <mailutils/error.h> | ||
6 | #include <mailutils/errno.h> | ||
7 | #include <mailutils/diag.h> | ||
8 | #include <mailutils/stream.h> | ||
9 | #include <mailutils/stdstream.h> | ||
10 | |||
11 | void | ||
12 | mu_lrange_debug (struct mu_locus_range const *loc, | ||
13 | char const *fmt, ...) | ||
14 | { | ||
15 | va_list ap; | ||
16 | int rc, mode; | ||
17 | |||
18 | rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
19 | MU_IOCTL_LOGSTREAM_GET_MODE, &mode); | ||
20 | if (rc == 0) | ||
21 | { | ||
22 | int new_mode = mode & ~MU_LOGMODE_LOCUS; | ||
23 | rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
24 | MU_IOCTL_LOGSTREAM_SET_MODE, &new_mode); | ||
25 | } | ||
26 | |||
27 | if (loc->beg.mu_col == 0) | ||
28 | mu_debug_log_begin ("%s:%u", loc->beg.mu_file, loc->beg.mu_line); | ||
29 | else if (!mu_locus_point_same_file (&loc->beg, &loc->end)) | ||
30 | mu_debug_log_begin ("%s:%u.%u-%s:%u.%u", | ||
31 | loc->beg.mu_file, | ||
32 | loc->beg.mu_line, loc->beg.mu_col, | ||
33 | loc->end.mu_file, | ||
34 | loc->end.mu_line, loc->end.mu_col); | ||
35 | else if (loc->beg.mu_line != loc->end.mu_line) | ||
36 | mu_debug_log_begin ("%s:%u.%u-%u.%u", | ||
37 | loc->beg.mu_file, | ||
38 | loc->beg.mu_line, loc->beg.mu_col, | ||
39 | loc->end.mu_line, loc->end.mu_col); | ||
40 | else if (loc->beg.mu_col != loc->end.mu_col) | ||
41 | mu_debug_log_begin ("%s:%u.%u-%u", | ||
42 | loc->beg.mu_file, | ||
43 | loc->beg.mu_line, loc->beg.mu_col, | ||
44 | loc->end.mu_col); | ||
45 | else | ||
46 | mu_debug_log_begin ("%s:%u.%u", | ||
47 | loc->beg.mu_file, | ||
48 | loc->beg.mu_line, loc->beg.mu_col); | ||
49 | |||
50 | mu_stream_write (mu_strerr, ": ", 2, NULL); | ||
51 | |||
52 | va_start (ap, fmt); | ||
53 | mu_stream_vprintf (mu_strerr, fmt, ap); | ||
54 | va_end (ap); | ||
55 | mu_debug_log_nl (); | ||
56 | if (rc == 0) | ||
57 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
58 | MU_IOCTL_LOGSTREAM_SET_MODE, &mode); | ||
59 | } |
libmailutils/locus/ident.c
0 → 100644
1 | #include <stdlib.h> | ||
2 | #include <mailutils/types.h> | ||
3 | #include <mailutils/assoc.h> | ||
4 | #include <mailutils/locus.h> | ||
5 | #include <mailutils/error.h> | ||
6 | #include <mailutils/errno.h> | ||
7 | #include <mailutils/diag.h> | ||
8 | #include <mailutils/list.h> | ||
9 | |||
10 | struct mu_ident_ref | ||
11 | { | ||
12 | size_t count; | ||
13 | }; | ||
14 | |||
15 | static mu_assoc_t nametab; | ||
16 | |||
17 | int | ||
18 | mu_ident_ref (char const *name, char const **refname) | ||
19 | { | ||
20 | int rc; | ||
21 | struct mu_ident_ref *ref, **refptr; | ||
22 | |||
23 | if (!name) | ||
24 | return EINVAL; | ||
25 | if (!refname) | ||
26 | return MU_ERR_OUT_PTR_NULL; | ||
27 | |||
28 | if (!nametab) | ||
29 | { | ||
30 | rc = mu_assoc_create (&nametab, 0); | ||
31 | if (rc) | ||
32 | { | ||
33 | mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_create", NULL, rc); | ||
34 | return rc; | ||
35 | } | ||
36 | mu_assoc_set_destroy_item (nametab, mu_list_free_item); | ||
37 | } | ||
38 | rc = mu_assoc_install_ref2 (nametab, name, &refptr, refname); | ||
39 | switch (rc) | ||
40 | { | ||
41 | case 0: | ||
42 | ref = malloc (sizeof *ref); | ||
43 | if (!ref) | ||
44 | { | ||
45 | rc = errno; | ||
46 | mu_assoc_remove (nametab, name); | ||
47 | return rc; | ||
48 | } | ||
49 | ref->count = 0; | ||
50 | break; | ||
51 | |||
52 | case MU_ERR_EXISTS: | ||
53 | ref = *refptr; | ||
54 | break; | ||
55 | |||
56 | default: | ||
57 | mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_install_ref2", name, rc); | ||
58 | return rc; | ||
59 | } | ||
60 | |||
61 | ref->count++; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | int | ||
66 | mu_ident_deref (char const *name) | ||
67 | { | ||
68 | struct mu_ident_ref *ref; | ||
69 | int rc; | ||
70 | |||
71 | if (!name) | ||
72 | return EINVAL; | ||
73 | if (!nametab) | ||
74 | return 0; | ||
75 | |||
76 | rc = mu_assoc_lookup (nametab, name, &ref); | ||
77 | switch (rc) | ||
78 | { | ||
79 | case 0: | ||
80 | if (--ref->count == 0) | ||
81 | mu_assoc_remove (nametab, name); | ||
82 | break; | ||
83 | |||
84 | case MU_ERR_NOENT: | ||
85 | break; | ||
86 | |||
87 | default: | ||
88 | mu_diag_funcall (MU_DIAG_ERROR, "mu_assoc_lookup", name, rc); | ||
89 | return rc; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | |||
96 |
libmailutils/locus/tracker.c
0 → 100644
1 | #include <stdlib.h> | ||
2 | #include <errno.h> | ||
3 | #include <mailutils/types.h> | ||
4 | #include <mailutils/locus.h> | ||
5 | |||
6 | struct mu_locus_track | ||
7 | { | ||
8 | char const *file_name; /* Name of the source file */ | ||
9 | size_t max_lines; /* Max. number of lines history kept by tracker */ | ||
10 | size_t head; /* Bottom of stack */ | ||
11 | size_t level; /* Number of elements on stack */ | ||
12 | unsigned hline; /* Number of line corresponding to cols[head] */ | ||
13 | unsigned *cols; /* Cyclic stack */ | ||
14 | }; | ||
15 | |||
16 | int | ||
17 | mu_locus_track_create (mu_locus_track_t *ret, | ||
18 | char const *file_name, size_t max_lines) | ||
19 | { | ||
20 | int rc; | ||
21 | struct mu_locus_track *trk; | ||
22 | |||
23 | trk = malloc (sizeof *trk); | ||
24 | if (!trk) | ||
25 | return errno; | ||
26 | trk->cols = calloc (max_lines, sizeof (trk->cols[0])); | ||
27 | if (!trk->cols) | ||
28 | { | ||
29 | rc = errno; | ||
30 | free (trk); | ||
31 | return rc; | ||
32 | } | ||
33 | rc = mu_ident_ref (file_name, &trk->file_name); | ||
34 | if (rc) | ||
35 | { | ||
36 | free (trk->cols); | ||
37 | free (trk); | ||
38 | return rc; | ||
39 | } | ||
40 | |||
41 | trk->max_lines = max_lines; | ||
42 | trk->head = 0; | ||
43 | trk->level = 0; | ||
44 | trk->hline = 1; | ||
45 | trk->cols[0] = 0; | ||
46 | |||
47 | *ret = trk; | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | void | ||
52 | mu_locus_track_free (mu_locus_track_t trk) | ||
53 | { | ||
54 | if (trk) | ||
55 | { | ||
56 | mu_ident_deref (trk->file_name); | ||
57 | free (trk->cols); | ||
58 | free (trk); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void | ||
63 | mu_locus_track_destroy (mu_locus_track_t *trk) | ||
64 | { | ||
65 | if (trk) | ||
66 | { | ||
67 | mu_locus_track_free (*trk); | ||
68 | *trk = NULL; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | size_t | ||
73 | mu_locus_track_level (mu_locus_track_t trk) | ||
74 | { | ||
75 | return trk->level; | ||
76 | } | ||
77 | |||
78 | static inline unsigned * | ||
79 | cols_tos_ptr (mu_locus_track_t trk) | ||
80 | { | ||
81 | return &trk->cols[(trk->head + trk->level) % trk->max_lines]; | ||
82 | } | ||
83 | |||
84 | static inline unsigned | ||
85 | cols_peek (mu_locus_track_t trk, size_t n) | ||
86 | { | ||
87 | return trk->cols[(trk->head + n) % trk->max_lines]; | ||
88 | } | ||
89 | |||
90 | static inline unsigned * | ||
91 | push (mu_locus_track_t trk) | ||
92 | { | ||
93 | unsigned *ptr; | ||
94 | if (trk->level == trk->max_lines) | ||
95 | { | ||
96 | trk->head++; | ||
97 | trk->hline++; | ||
98 | } | ||
99 | else | ||
100 | trk->level++; | ||
101 | *(ptr = cols_tos_ptr (trk)) = 0; | ||
102 | return ptr; | ||
103 | } | ||
104 | |||
105 | static inline unsigned * | ||
106 | pop (mu_locus_track_t trk) | ||
107 | { | ||
108 | if (trk->level == 0) | ||
109 | { | ||
110 | *cols_tos_ptr (trk) = 0; | ||
111 | return NULL; //FIXME | ||
112 | } | ||
113 | trk->level--; | ||
114 | return cols_tos_ptr (trk); | ||
115 | } | ||
116 | |||
117 | void | ||
118 | mu_locus_tracker_advance (struct mu_locus_track *trk, | ||
119 | struct mu_locus_range *loc, | ||
120 | char const *text, size_t leng) | ||
121 | { | ||
122 | unsigned *ptr; | ||
123 | |||
124 | if (text == NULL || leng == 0) | ||
125 | return; | ||
126 | |||
127 | loc->beg.mu_file = loc->end.mu_file = trk->file_name; | ||
128 | loc->beg.mu_line = trk->hline + trk->level; | ||
129 | ptr = cols_tos_ptr (trk); | ||
130 | loc->beg.mu_col = *ptr + 1; | ||
131 | while (leng--) | ||
132 | { | ||
133 | (*ptr)++; | ||
134 | if (*text == '\n') | ||
135 | ptr = push (trk); | ||
136 | text++; | ||
137 | } | ||
138 | if (*ptr) | ||
139 | { | ||
140 | loc->end.mu_line = trk->hline + trk->level; | ||
141 | loc->end.mu_col = *ptr; | ||
142 | } | ||
143 | else | ||
144 | { | ||
145 | loc->end.mu_line = trk->hline + trk->level - 1; | ||
146 | loc->end.mu_col = cols_peek (trk, trk->level - 1) - 1; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | void | ||
151 | mu_locus_tracker_retreat (struct mu_locus_track *trk, size_t n) | ||
152 | { | ||
153 | unsigned *ptr; | ||
154 | |||
155 | ptr = cols_tos_ptr (trk); | ||
156 | while (n--) | ||
157 | { | ||
158 | if (*ptr == 0) | ||
159 | { | ||
160 | ptr = pop (trk); | ||
161 | if (!ptr) | ||
162 | break; | ||
163 | } | ||
164 | --*ptr; | ||
165 | } | ||
166 | } | ||
167 | |||
168 |
libmailutils/tests/tracker.c
0 → 100644
1 | #include <mailutils/mailutils.h> | ||
2 | #include <mailutils/locus.h> | ||
3 | |||
4 | int | ||
5 | main (int argc, char **argv) | ||
6 | { | ||
7 | unsigned long max_lines; | ||
8 | char *end; | ||
9 | mu_locus_track_t trk; | ||
10 | int rc; | ||
11 | char *buf = NULL; | ||
12 | size_t size, n; | ||
13 | |||
14 | mu_set_program_name (argv[0]); | ||
15 | mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); | ||
16 | |||
17 | if (argc != 3) | ||
18 | { | ||
19 | mu_error ("usage: %s FILE LINES", mu_program_name); | ||
20 | return 1; | ||
21 | } | ||
22 | max_lines = strtoul (argv[2], &end, 10); | ||
23 | if (*end || max_lines == 0) | ||
24 | { | ||
25 | mu_error ("invalid number of lines"); | ||
26 | return 1; | ||
27 | } | ||
28 | |||
29 | MU_ASSERT (mu_locus_track_create (&trk, argv[1], max_lines)); | ||
30 | while ((rc = mu_stream_getline (mu_strin, &buf, &size, &n)) == 0 && n > 0) | ||
31 | { | ||
32 | struct mu_locus_range lr; | ||
33 | char *tok; | ||
34 | |||
35 | n = mu_rtrim_class (buf, MU_CTYPE_SPACE); | ||
36 | if (buf[0] == '\\') | ||
37 | { | ||
38 | long x = strtol (buf+1, &end, 10); | ||
39 | if (*end || x == 0) | ||
40 | { | ||
41 | mu_error ("bad number"); | ||
42 | continue; | ||
43 | } | ||
44 | mu_locus_tracker_retreat (trk, x); | ||
45 | } | ||
46 | else | ||
47 | { | ||
48 | mu_c_str_unescape (buf, "\\\n", "\\n", &tok); | ||
49 | mu_locus_tracker_advance (trk, &lr, tok, strlen (tok)); | ||
50 | free (tok); | ||
51 | mu_lrange_debug (&lr, "%s", buf); | ||
52 | } | ||
53 | } | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 |
-
Please register or sign in to post a comment