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