1 /* This file is part of Eclat.
2 Copyright (C) 2012-2018 Sergey Poznyakoff.
3
4 Eclat is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 Eclat 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include "libeclat.h"
18 #include <string.h>
19 #include <sysexits.h>
20
21 const char *program_name;
22 struct debug_category debug_category[LIBECLAT_DBG_MAX];
main(int,char **)23 int debug_avail;
24
25 void
26 set_program_name(const char *arg)
27 {
28 program_name = strrchr(arg, '/');
29 if (!program_name)
30 program_name = arg;
31 else
32 program_name++;
33 }
34
35 void
36 vdiag(grecs_locus_t const *locus, const char *qual, const char *fmt,
37 va_list ap)
38 {
39 if (program_name)
40 fprintf(stderr, "%s: ", program_name);
41
42 if (locus) {
43 if (locus->beg.col == 0)
44 fprintf(stderr, "%s:%u",
45 locus->beg.file,
46 locus->beg.line);
47 else if (strcmp(locus->beg.file, locus->end.file))
48 fprintf(stderr, "%s:%u.%u-%s:%u.%u",
49 locus->beg.file,
50 locus->beg.line, locus->beg.col,
51 locus->end.file,
52 locus->end.line, locus->end.col);
53 else if (locus->beg.line != locus->end.line)
54 fprintf(stderr, "%s:%u.%u-%u.%u",
55 locus->beg.file,
56 locus->beg.line, locus->beg.col,
57 locus->end.line, locus->end.col);
58 else
59 fprintf(stderr, "%s:%u.%u-%u",
60 locus->beg.file,
61 locus->beg.line, locus->beg.col,
62 locus->end.col);
63 fprintf(stderr, ": ");
64 }
65
66 if (qual)
67 fprintf(stderr, "%s: ", qual);
68 vfprintf(stderr, fmt, ap);
69 fputc('\n', stderr);
70 }
71
72 void
73 diag(grecs_locus_t const *locus, const char *qual, const char *fmt, ...)
74 {
75 va_list ap;
76
77 va_start(ap, fmt);
78 vdiag(locus, qual, fmt, ap);
79 va_end(ap);
80 }
81
82 void
83 die(int status, const char *fmt, ...)
84 {
85 va_list ap;
86
87 va_start(ap, fmt);
88 vdiag(NULL, NULL, fmt, ap);
89 va_end(ap);
90 exit(status);
91 }
92
93 void
94 err(const char *fmt, ...)
95 {
96 va_list ap;
97
98 va_start(ap, fmt);
99 vdiag(NULL, NULL, fmt, ap);
100 va_end(ap);
101 }
102
103 void
104 warn(const char *fmt, ...)
105 {
106 va_list ap;
107
108 va_start(ap, fmt);
109 vdiag(NULL, "warning", fmt, ap);
110 va_end(ap);
111 }
112
113 void
114 debug_printf(const char *fmt, ...)
115 {
116 va_list ap;
117
118 va_start(ap, fmt);
119 vdiag(NULL, "debug", fmt, ap);
120 va_end(ap);
121 }
122
123 static struct debug_category *
124 find_category(const char *arg, size_t len)
125 {
126 struct debug_category *dp;
127
128 for (dp = debug_category; dp < debug_category + debug_avail; dp++)
129 if (dp->length == len && memcmp(dp->name, arg, len) == 0)
130 return dp;
131 return NULL;
132 }
133
134 int
135 parse_debug_level(const char *arg)
136 {
137 unsigned long lev;
138 char *p;
139 size_t len = strcspn(arg, ".");
140 struct debug_category *dp;
141
142 if (arg[len] == 0) {
143 lev = strtoul(arg, &p, 10);
144 if (*p == 0) {
145 for (dp = debug_category;
146 dp < debug_category + debug_avail;
147 dp++)
148 dp->level = lev;
149 return 0;
150 }
151 }
152
153 dp = find_category(arg, len);
154 if (!dp)
155 return -1;
156
157 p = (char*) arg + len;
158 if (*p == 0)
159 lev = 100;
160 else if (*p != '.')
161 return -1;
162 else {
163 lev = strtoul(p + 1, &p, 10);
164 if (*p)
165 return -1;
166 }
167 dp->level = lev;
168 return 0;
169 }
170
171 int
172 debug_register(char *name)
173 {
174 if (debug_avail >= LIBECLAT_DBG_MAX)
175 die(EX_SOFTWARE, "no more debug slots available");
176 debug_category[debug_avail].name = grecs_strdup(name);
177 debug_category[debug_avail].length = strlen(name);
178 debug_category[debug_avail].level = 0;
179 return debug_avail++;
180 }
181