Blame tools/smilint.c

Packit 022b05
/*
Packit 022b05
 * smilint.c --
Packit 022b05
 *
Packit 022b05
 *      MIB module checker main program.
Packit 022b05
 *
Packit 022b05
 * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
Packit 022b05
 *
Packit 022b05
 * See the file "COPYING" for information on usage and redistribution
Packit 022b05
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Packit 022b05
 *
Packit 022b05
 * @(#) $Id: smilint.c 1867 2004-10-06 13:45:31Z strauss $
Packit 022b05
 */
Packit 022b05
Packit 022b05
#include <config.h>
Packit 022b05
Packit 022b05
#include <stdlib.h>
Packit 022b05
#include <stdio.h>
Packit 022b05
#include <string.h>
Packit 022b05
#ifdef HAVE_UNISTD_H
Packit 022b05
#include <unistd.h>
Packit 022b05
#endif
Packit 022b05
#ifdef HAVE_WIN_H
Packit 022b05
#include "win.h"
Packit 022b05
#endif
Packit 022b05
Packit 022b05
#include "smi.h"
Packit 022b05
#include "shhopt.h"
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * These are functions that are not officially exported by the libsmi.
Packit 022b05
 * See the original prototype definitions in lib/error.h.
Packit 022b05
 */
Packit 022b05
Packit 022b05
extern int smiGetErrorSeverity(int id);
Packit 022b05
extern char* smiGetErrorTag(int id);
Packit 022b05
extern char* smiGetErrorMsg(int id);
Packit 022b05
extern char* smiGetErrorDescription(int id);
Packit 022b05
Packit 022b05
Packit 022b05
static int mFlag = 0;	/* show the name for error messages */
Packit 022b05
static int sFlag = 0;	/* show the severity for error messages */
Packit 022b05
static int eFlag = 0;	/* print the list of possible error messages */
Packit 022b05
static int flags;
Packit 022b05
Packit 022b05
Packit 022b05
typedef struct Error {
Packit 022b05
    int id;
Packit 022b05
    int severity;
Packit 022b05
    char *tag;
Packit 022b05
    char *msg;
Packit 022b05
    char *description;
Packit 022b05
    int used;
Packit 022b05
} Error;
Packit 022b05
Packit 022b05
Packit 022b05
static Error *errors = NULL;
Packit 022b05
Packit 022b05
Packit 022b05
static void fold(FILE *f, int indent, const char *msg)
Packit 022b05
{
Packit 022b05
    const char *p, *s;
Packit 022b05
Packit 022b05
    if (! msg) {
Packit 022b05
	fprintf(f, "\n");
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (s = msg; *s; s++) {
Packit 022b05
	for (p = s; *p && *p != '\n'; p++) ;
Packit 022b05
	if (*p) {
Packit 022b05
	    fprintf(f, "%.*s\n%*s", p - s, s, indent, "");
Packit 022b05
	    s = p;
Packit 022b05
	} else {
Packit 022b05
	    fprintf(f, "%.*s\n", p - s, s);
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static int compare(const void *v1, const void *v2)
Packit 022b05
{
Packit 022b05
    Error *err1 = (Error *) v1;
Packit 022b05
    Error *err2 = (Error *) v2;
Packit 022b05
Packit 022b05
    if (err1->severity < err2->severity) {
Packit 022b05
	return -1;
Packit 022b05
    }
Packit 022b05
    if (err1->severity > err2->severity) {
Packit 022b05
	return 1;
Packit 022b05
    }
Packit 022b05
    return strcmp(err1->msg, err2->msg);
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static Error* errors_new()
Packit 022b05
{
Packit 022b05
    int i, cnt;
Packit 022b05
    Error *errors;
Packit 022b05
    
Packit 022b05
    for (cnt = 0; smiGetErrorSeverity(cnt) >= 0; cnt++) ;
Packit 022b05
    
Packit 022b05
    errors = malloc((cnt + 1) * sizeof(Error));
Packit 022b05
    if (! errors) {
Packit 022b05
	fprintf(stderr, "smilint: malloc failed - running out of memory\n");
Packit 022b05
	exit(1);
Packit 022b05
    }
Packit 022b05
    memset(errors, 0, (cnt + 1) * sizeof(Error));
Packit 022b05
Packit 022b05
    for (i = 0; i < cnt; i++) {
Packit 022b05
	errors[i].id = i;
Packit 022b05
	errors[i].severity = smiGetErrorSeverity(i);
Packit 022b05
	errors[i].tag = smiGetErrorTag(i);
Packit 022b05
	errors[i].msg = smiGetErrorMsg(i);
Packit 022b05
	errors[i].description = smiGetErrorDescription(i);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    qsort(errors, cnt, sizeof(Error), compare);
Packit 022b05
Packit 022b05
    return errors;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void display_one(FILE *f, Error *error)
Packit 022b05
{
Packit 022b05
    const int indent = 12;
Packit 022b05
    char *type, *tag;
Packit 022b05
Packit 022b05
    type = (error->severity <= 3) ? "Error:" : "Warning:";
Packit 022b05
    tag = (error->tag && strlen(error->tag))
Packit 022b05
	? error->tag : "<xxx-missing-xxx>";
Packit 022b05
    fprintf(f, "%-*s %s (level %d%s)\n",
Packit 022b05
	    indent, type, tag, error->severity & 127,
Packit 022b05
	    error->severity & 128 ? ", ignored" : "");
Packit 022b05
    fprintf(f, "%-*s %s\n", indent, "Message:",
Packit 022b05
	    error->msg ? error->msg : "");
Packit 022b05
    if (error->description) {
Packit 022b05
	fprintf(f, "%-*s ", indent, "Description:");
Packit 022b05
	fold(f, indent + 1, error->description);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
static void display_all(Error *errors)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
    
Packit 022b05
    for (i = 0; errors[i].msg; i++) {
Packit 022b05
	if (i) printf("\n");
Packit 022b05
	display_one(stdout, errors + i);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void display_used(Error *errors)
Packit 022b05
{
Packit 022b05
    int i, n;
Packit 022b05
Packit 022b05
    for (i = 0, n = 0; errors[i].msg; i++) {
Packit 022b05
	if (errors[i].used && errors[i].description) n++;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (! n) {
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    fprintf(stderr,
Packit 022b05
	    "\nAdditional descriptions of some error/warning messages:\n"); 
Packit 022b05
Packit 022b05
    for (i = 0; errors[i].msg; i++) {
Packit 022b05
	if (! errors[i].used || !errors[i].description) continue;
Packit 022b05
	if (i) fprintf(stderr, "\n");
Packit 022b05
	display_one(stderr, errors + i);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void usage()
Packit 022b05
{
Packit 022b05
    fprintf(stderr,
Packit 022b05
	    "Usage: smilint [options] [module or path ...]\n"
Packit 022b05
	    "  -V, --version         show version and license information\n"
Packit 022b05
	    "  -h, --help            show usage information\n"
Packit 022b05
	    "  -c, --config=file     load a specific configuration file\n"
Packit 022b05
	    "  -p, --preload=module  preload <module>\n"
Packit 022b05
	    "  -e, --error-list      print list of known error messages\n"
Packit 022b05
	    "  -m, --error-names     print the name of errors in braces\n"
Packit 022b05
	    "  -s, --severity        print the severity of errors in brackets\n"
Packit 022b05
	    "  -r, --recursive       print errors also for imported modules\n"
Packit 022b05
	    "  -l, --level=level     set maximum level of errors and warnings\n"
Packit 022b05
	    "  -i, --ignore=prefix   ignore errors matching prefix pattern\n"
Packit 022b05
	    "  -I, --noignore=prefix do not ignore errors matching prefix pattern\n");
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void help() { usage(); exit(0); }
Packit 022b05
static void version() { printf("smilint " SMI_VERSION_STRING "\n"); exit(0); }
Packit 022b05
static void config(char *filename) { smiReadConfig(filename, "smilint"); }
Packit 022b05
static void preload(char *module) { smiLoadModule(module); }
Packit 022b05
static void recursive() { flags |= SMI_FLAG_RECURSIVE; smiSetFlags(flags); }
Packit 022b05
static void level(int lev) { smiSetErrorLevel(lev); }
Packit 022b05
static void ignore(char *ign) { smiSetSeverity(ign, 128); }
Packit 022b05
static void noignore(char *ign) { smiSetSeverity(ign, -1); }
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
static void
Packit 022b05
errorHandler(char *path, int line, int severity, char *msg, char *tag)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
    
Packit 022b05
    if (path) {
Packit 022b05
	fprintf(stderr, "%s:%d: ", path, line);
Packit 022b05
    }
Packit 022b05
    if (sFlag) {
Packit 022b05
	fprintf(stderr, "[%d] ", severity);
Packit 022b05
    }
Packit 022b05
    if (mFlag) {
Packit 022b05
	fprintf(stderr, "{%s} ", tag);
Packit 022b05
    }
Packit 022b05
    switch (severity) {
Packit 022b05
    case 4:
Packit 022b05
    case 5:
Packit 022b05
	fprintf(stderr, "warning: ");
Packit 022b05
	break;
Packit 022b05
    case 6:	
Packit 022b05
	fprintf(stderr, "info: ");
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
    fprintf(stderr, "%s\n", msg);
Packit 022b05
Packit 022b05
    if (severity <= 0) {
Packit 022b05
	exit(1);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /* If we are supposed to generate error descriptions, locate this
Packit 022b05
     * error in our error list and increment its usage counter. Note
Packit 022b05
     * that we assume that error tags are unique (and we should better
Packit 022b05
     * check for this somewhere). */
Packit 022b05
Packit 022b05
    if (errors) {
Packit 022b05
	for (i = 0; errors[i].msg; i++) {
Packit 022b05
	    if (strcmp(errors[i].tag, tag) == 0) {
Packit 022b05
		errors[i].used++;
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
int main(int argc, char *argv[])
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
Packit 022b05
    static optStruct opt[] = {
Packit 022b05
	/* short long              type        var/func       special       */
Packit 022b05
	{ 'h', "help",           OPT_FLAG,   help,          OPT_CALLFUNC },
Packit 022b05
	{ 'V', "version",        OPT_FLAG,   version,       OPT_CALLFUNC },
Packit 022b05
	{ 'c', "config",         OPT_STRING, config,        OPT_CALLFUNC },
Packit 022b05
	{ 'p', "preload",        OPT_STRING, preload,       OPT_CALLFUNC },
Packit 022b05
	{ 'e', "error-list",     OPT_FLAG,   &eFlag,        0 },
Packit 022b05
	{ 'm', "error-names",    OPT_FLAG,   &mFlag,        0 },
Packit 022b05
	{ 's', "severity",       OPT_FLAG,   &sFlag,        0 },
Packit 022b05
	{ 'r', "recursive",      OPT_FLAG,   recursive,     OPT_CALLFUNC },
Packit 022b05
	{ 'l', "level",          OPT_INT,    level,         OPT_CALLFUNC },
Packit 022b05
	{ 'i', "ignore",         OPT_STRING, ignore,        OPT_CALLFUNC },
Packit 022b05
	{ 'I', "noignore",       OPT_STRING, noignore,      OPT_CALLFUNC },
Packit 022b05
	{ 0, 0, OPT_END, 0, 0 }  /* no more options */
Packit 022b05
    };
Packit 022b05
    
Packit 022b05
    for (i = 1; i < argc; i++)
Packit 022b05
	if ((strstr(argv[i], "-c") == argv[i]) ||
Packit 022b05
	    (strstr(argv[i], "--config") == argv[i])) break;
Packit 022b05
    if (i == argc) 
Packit 022b05
	smiInit("smilint");
Packit 022b05
    else
Packit 022b05
	smiInit(NULL);
Packit 022b05
Packit 022b05
    flags = smiGetFlags();
Packit 022b05
    flags |= SMI_FLAG_ERRORS;
Packit 022b05
    flags |= SMI_FLAG_NODESCR;
Packit 022b05
    smiSetFlags(flags);
Packit 022b05
Packit 022b05
    optParseOptions(&argc, argv, opt, 0);
Packit 022b05
Packit 022b05
    if (eFlag) {
Packit 022b05
	mFlag = 1;
Packit 022b05
	errors = errors_new();
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (sFlag || mFlag) {
Packit 022b05
	smiSetErrorHandler(errorHandler);
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (eFlag && argc == 1) {
Packit 022b05
	if (errors) {
Packit 022b05
	    display_all(errors);
Packit 022b05
	    free(errors);
Packit 022b05
	}
Packit 022b05
	smiExit();
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (i = 1; i < argc; i++) {
Packit 022b05
	if (smiLoadModule(argv[i]) == NULL) {
Packit 022b05
	    fprintf(stderr, "smilint: cannot locate module `%s'\n",
Packit 022b05
		    argv[i]);
Packit 022b05
	    smiExit();
Packit 022b05
	    exit(1);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (eFlag) {
Packit 022b05
	if (errors) {
Packit 022b05
	    display_used(errors);
Packit 022b05
	    free(errors);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    smiExit();
Packit 022b05
Packit 022b05
    return 0;
Packit 022b05
}