/* * smixlate.c -- * * Translate OIDs located in the input stream. * * Copyright (c) 2006 Juergen Schoenwaelder, International University Bremen. * * See the file "COPYING" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * @(#) $Id: smilint.c 1867 2004-10-06 13:45:31Z strauss $ */ #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_WIN_H #include "win.h" #endif #include "smi.h" #include "shhopt.h" #include "dstring.h" static int flags; static int aFlag = 0; /* translate all OIDs */ static int fFlag = 0; /* preserve formatting */ static void translate(dstring_t *token, dstring_t *subst) { SmiNode *smiNode; SmiSubid oid[256]; unsigned int oidlen = 0; unsigned int i; char *p; assert(token && subst); dstring_truncate(subst, 0); dstring_assign(subst, dstring_str(token)); for (oidlen = 0, p = strtok(dstring_str(token), ". "); p; oidlen++, p = strtok(NULL, ". ")) { oid[oidlen] = strtoul(p, NULL, 0); } smiNode = smiGetNodeByOID(oidlen, oid); if (smiNode && (aFlag || smiNode->nodekind == SMI_NODEKIND_SCALAR || smiNode->nodekind == SMI_NODEKIND_COLUMN || smiNode->nodekind == SMI_NODEKIND_NOTIFICATION || smiNode->nodekind == SMI_NODEKIND_TABLE || smiNode->nodekind == SMI_NODEKIND_ROW)) { dstring_assign(subst, smiNode->name); for (i = smiNode->oidlen; i < oidlen; i++) { dstring_append_printf(subst, ".%d", oid[i]); } } } static void process(FILE *stream) { int c, space = 0; enum { TXT, NUM, NUMDOT, NUMDOTNUM, OID, OIDDOT, EATSPACE } state = TXT; dstring_t *token, *subst; token = dstring_new(); subst = dstring_new(); if (! token || ! subst) { return; } /* * Shall we require iswhite() or ispunct() before and after the * OID? * * TODO: - translate instance identifier to something meaningful * (e.g. foobar["name",32]) where possible * - generate warnings if instance identifier are incomplete * - provide a reverse translation service (-x) (but this is * more complex since it is unclear how to identify names * - make the white space magic optional */ while ((c = fgetc(stream)) != EOF) { switch (state) { case TXT: fputs(dstring_str(token), stdout); dstring_truncate(token, 0); if (isdigit(c) && c >= '0' && c <= '2') { dstring_append_char(token, (char) c); state = NUM; } else { fputc(c, stdout); fflush(stdout); } break; case NUM: if (isdigit(c)) { dstring_append_char(token, (char) c); } else if (c == '.') { dstring_append_char(token, (char) c); state = NUMDOT; } else { dstring_append_char(token, (char) c); state = TXT; } break; case NUMDOT: if (isdigit(c)) { dstring_append_char(token, (char) c); state = NUMDOTNUM; } else { dstring_append_char(token, (char) c); state = TXT; } break; case NUMDOTNUM: if (isdigit(c)) { dstring_append_char(token, (char) c); } if (c == '.') { dstring_append_char(token, (char) c); state = OID; } else { dstring_append_char(token, (char) c); state = TXT; } break; case OID: if (isdigit(c)) { dstring_append_char(token, (char) c); } else if (c == '.') { dstring_append_char(token, (char) c); state = OIDDOT; } else { translate(token, subst); if (fFlag) { if (dstring_len(subst) < dstring_len(token)) { dstring_expand(subst, dstring_len(token), ' '); } } fputs(dstring_str(subst), stdout); if (dstring_len(subst) > dstring_len(token)) { space = dstring_len(subst) - dstring_len(token) - 1; } else { space = 0; } if (fFlag && space > 0 && c == ' ') { state = EATSPACE; space--; } else { state = TXT; space = 0; fputc(c, stdout); } dstring_truncate(token, 0); } break; case OIDDOT: if (isdigit(c)) { dstring_append_char(token, (char) c); state = OID; } else { translate(token, subst); fputs(dstring_str(subst), stdout); fputc(c, stdout); dstring_truncate(token, 0); state = TXT; } break; case EATSPACE: if (c == ' ' && space > 0) { space--; } else { state = TXT; } break; } } if (dstring_len(token)) { switch (state) { case TXT: case NUM: case NUMDOT: case NUMDOTNUM: fputs(dstring_str(token), stdout); dstring_truncate(token, 0); fputc(c, stdout); fflush(stdout); break; case OID: if (isdigit(c)) { dstring_append_char(token, (char) c); } else { translate(token, subst); if (fFlag) { if (dstring_len(subst) < dstring_len(token)) { dstring_expand(subst, dstring_len(token), ' '); } } fputs(dstring_str(subst), stdout); if (dstring_len(subst) > dstring_len(token)) { space = dstring_len(subst) - dstring_len(token) - 1; } else { space = 0; } if (fFlag && space > 0 && c == ' ') { space--; } else { space = 0; fputc(c, stdout); } dstring_truncate(token, 0); } break; case OIDDOT: if (isdigit(c)) { dstring_append_char(token, (char) c); } else { translate(token, subst); fputs(dstring_str(subst), stdout); fputc(c, stdout); dstring_truncate(token, 0); } break; case EATSPACE: if (c == ' ' && space > 0) { space--; } else { fputc(c, stdout); } break; } } } static void usage() { fprintf(stderr, "Usage: smixlate [options] [module or path ...]\n" " -V, --version show version and license information\n" " -h, --help show usage information\n" " -c, --config=file load a specific configuration file\n" " -p, --preload=module preload \n" " -r, --recursive print errors also for imported modules\n" " -l, --level=level set maximum level of errors and warnings\n" " -i, --ignore=prefix ignore errors matching prefix pattern\n" " -I, --noignore=prefix do not ignore errors matching prefix pattern\n" " -a, --all replace all OIDs (including OID prefixes)\n" " -f, --format preserve formatting as much as possible\n"); } static void help() { usage(); exit(0); } static void version() { printf("smixlate " SMI_VERSION_STRING "\n"); exit(0); } static void config(char *filename) { smiReadConfig(filename, "smixlate"); } static void preload(char *module) { smiLoadModule(module); } static void recursive() { flags |= SMI_FLAG_RECURSIVE; smiSetFlags(flags); } static void level(int lev) { smiSetErrorLevel(lev); } static void ignore(char *ign) { smiSetSeverity(ign, 128); } static void noignore(char *ign) { smiSetSeverity(ign, -1); } int main(int argc, char *argv[]) { int i; static optStruct opt[] = { /* short long type var/func special */ { 'a', "all", OPT_FLAG, &aFlag, 0 }, { 'f', "format", OPT_FLAG, &fFlag, 0 }, { 'h', "help", OPT_FLAG, help, OPT_CALLFUNC }, { 'V', "version", OPT_FLAG, version, OPT_CALLFUNC }, { 'c', "config", OPT_STRING, config, OPT_CALLFUNC }, { 'p', "preload", OPT_STRING, preload, OPT_CALLFUNC }, { 'r', "recursive", OPT_FLAG, recursive, OPT_CALLFUNC }, { 'l', "level", OPT_INT, level, OPT_CALLFUNC }, { 'i', "ignore", OPT_STRING, ignore, OPT_CALLFUNC }, { 'I', "noignore", OPT_STRING, noignore, OPT_CALLFUNC }, { 0, 0, OPT_END, 0, 0 } /* no more options */ }; for (i = 1; i < argc; i++) if ((strstr(argv[i], "-c") == argv[i]) || (strstr(argv[i], "--config") == argv[i])) break; if (i == argc) smiInit("smixlate"); else smiInit(NULL); flags = smiGetFlags(); flags |= SMI_FLAG_ERRORS; flags |= SMI_FLAG_NODESCR; smiSetFlags(flags); optParseOptions(&argc, argv, opt, 0); for (i = 1; i < argc; i++) { if (smiLoadModule(argv[i]) == NULL) { fprintf(stderr, "smixlate: cannot locate module `%s'\n", argv[i]); smiExit(); exit(1); } } process(stdin); smiExit(); return 0; }