4 * MIB module checker main program.
6 * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
8 * See the file "COPYING" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * @(#) $Id: smilint.c 1867 2004-10-06 13:45:31Z strauss $
32 * These are functions that are not officially exported by the libsmi.
33 * See the original prototype definitions in lib/error.h.
36 extern int smiGetErrorSeverity(int id);
37 extern char* smiGetErrorTag(int id);
38 extern char* smiGetErrorMsg(int id);
39 extern char* smiGetErrorDescription(int id);
42 static int mFlag = 0; /* show the name for error messages */
43 static int sFlag = 0; /* show the severity for error messages */
44 static int eFlag = 0; /* print the list of possible error messages */
48 typedef struct Error {
58 static Error *errors = NULL;
61 static void fold(FILE *f, int indent, const char *msg)
70 for (s = msg; *s; s++) {
71 for (p = s; *p && *p != '\n'; p++) ;
73 fprintf(f, "%.*s\n%*s", p - s, s, indent, "");
76 fprintf(f, "%.*s\n", p - s, s);
84 static int compare(const void *v1, const void *v2)
86 Error *err1 = (Error *) v1;
87 Error *err2 = (Error *) v2;
89 if (err1->severity < err2->severity) {
92 if (err1->severity > err2->severity) {
95 return strcmp(err1->msg, err2->msg);
100 static Error* errors_new()
105 for (cnt = 0; smiGetErrorSeverity(cnt) >= 0; cnt++) ;
107 errors = malloc((cnt + 1) * sizeof(Error));
109 fprintf(stderr, "smilint: malloc failed - running out of memory\n");
112 memset(errors, 0, (cnt + 1) * sizeof(Error));
114 for (i = 0; i < cnt; i++) {
116 errors[i].severity = smiGetErrorSeverity(i);
117 errors[i].tag = smiGetErrorTag(i);
118 errors[i].msg = smiGetErrorMsg(i);
119 errors[i].description = smiGetErrorDescription(i);
122 qsort(errors, cnt, sizeof(Error), compare);
128 static void display_one(FILE *f, Error *error)
130 const int indent = 12;
133 type = (error->severity <= 3) ? "Error:" : "Warning:";
134 tag = (error->tag && strlen(error->tag))
135 ? error->tag : "<xxx-missing-xxx>";
136 fprintf(f, "%-*s %s (level %d%s)\n",
137 indent, type, tag, error->severity & 127,
138 error->severity & 128 ? ", ignored" : "");
139 fprintf(f, "%-*s %s\n", indent, "Message:",
140 error->msg ? error->msg : "");
141 if (error->description) {
142 fprintf(f, "%-*s ", indent, "Description:");
143 fold(f, indent + 1, error->description);
148 static void display_all(Error *errors)
152 for (i = 0; errors[i].msg; i++) {
154 display_one(stdout, errors + i);
160 static void display_used(Error *errors)
164 for (i = 0, n = 0; errors[i].msg; i++) {
165 if (errors[i].used && errors[i].description) n++;
173 "\nAdditional descriptions of some error/warning messages:\n");
175 for (i = 0; errors[i].msg; i++) {
176 if (! errors[i].used || !errors[i].description) continue;
177 if (i) fprintf(stderr, "\n");
178 display_one(stderr, errors + i);
187 "Usage: smilint [options] [module or path ...]\n"
188 " -V, --version show version and license information\n"
189 " -h, --help show usage information\n"
190 " -c, --config=file load a specific configuration file\n"
191 " -p, --preload=module preload <module>\n"
192 " -e, --error-list print list of known error messages\n"
193 " -m, --error-names print the name of errors in braces\n"
194 " -s, --severity print the severity of errors in brackets\n"
195 " -r, --recursive print errors also for imported modules\n"
196 " -l, --level=level set maximum level of errors and warnings\n"
197 " -i, --ignore=prefix ignore errors matching prefix pattern\n"
198 " -I, --noignore=prefix do not ignore errors matching prefix pattern\n");
203 static void help() { usage(); exit(0); }
204 static void version() { printf("smilint " SMI_VERSION_STRING "\n"); exit(0); }
205 static void config(char *filename) { smiReadConfig(filename, "smilint"); }
206 static void preload(char *module) { smiLoadModule(module); }
207 static void recursive() { flags |= SMI_FLAG_RECURSIVE; smiSetFlags(flags); }
208 static void level(int lev) { smiSetErrorLevel(lev); }
209 static void ignore(char *ign) { smiSetSeverity(ign, 128); }
210 static void noignore(char *ign) { smiSetSeverity(ign, -1); }
215 errorHandler(char *path, int line, int severity, char *msg, char *tag)
220 fprintf(stderr, "%s:%d: ", path, line);
223 fprintf(stderr, "[%d] ", severity);
226 fprintf(stderr, "{%s} ", tag);
231 fprintf(stderr, "warning: ");
234 fprintf(stderr, "info: ");
237 fprintf(stderr, "%s\n", msg);
243 /* If we are supposed to generate error descriptions, locate this
244 * error in our error list and increment its usage counter. Note
245 * that we assume that error tags are unique (and we should better
246 * check for this somewhere). */
249 for (i = 0; errors[i].msg; i++) {
250 if (strcmp(errors[i].tag, tag) == 0) {
260 int main(int argc, char *argv[])
264 static optStruct opt[] = {
265 /* short long type var/func special */
266 { 'h', "help", OPT_FLAG, help, OPT_CALLFUNC },
267 { 'V', "version", OPT_FLAG, version, OPT_CALLFUNC },
268 { 'c', "config", OPT_STRING, config, OPT_CALLFUNC },
269 { 'p', "preload", OPT_STRING, preload, OPT_CALLFUNC },
270 { 'e', "error-list", OPT_FLAG, &eFlag, 0 },
271 { 'm', "error-names", OPT_FLAG, &mFlag, 0 },
272 { 's', "severity", OPT_FLAG, &sFlag, 0 },
273 { 'r', "recursive", OPT_FLAG, recursive, OPT_CALLFUNC },
274 { 'l', "level", OPT_INT, level, OPT_CALLFUNC },
275 { 'i', "ignore", OPT_STRING, ignore, OPT_CALLFUNC },
276 { 'I', "noignore", OPT_STRING, noignore, OPT_CALLFUNC },
277 { 0, 0, OPT_END, 0, 0 } /* no more options */
280 for (i = 1; i < argc; i++)
281 if ((strstr(argv[i], "-c") == argv[i]) ||
282 (strstr(argv[i], "--config") == argv[i])) break;
288 flags = smiGetFlags();
289 flags |= SMI_FLAG_ERRORS;
290 flags |= SMI_FLAG_NODESCR;
293 optParseOptions(&argc, argv, opt, 0);
297 errors = errors_new();
300 if (sFlag || mFlag) {
301 smiSetErrorHandler(errorHandler);
304 if (eFlag && argc == 1) {
313 for (i = 1; i < argc; i++) {
314 if (smiLoadModule(argv[i]) == NULL) {
315 fprintf(stderr, "smilint: cannot locate module `%s'\n",
324 display_used(errors);