/* lqbyteline.c -- Copyright 1993, 1996 Liam R. E. Quin. All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. * * $Id: lqbyteline.c,v 1.5 1996/07/04 21:13:46 lee Exp $ * * Turns byte offsets into line numbers; see lqkwic -L, and also the * example use in the lq.sh shell script. */ #include "error.h" #include "globals.h" /* defines and declarations for database filenames */ #include #include #ifdef HAVE_STRING_H # include #else # include #endif #include #ifdef HAVE_SYSV_FCNTL_H # include /* needed for fcntl.h on some systems */ #endif #ifdef HAVE_FCNTL_H # include /* for O_RDONLY etc */ #endif #include #include "emalloc.h" #include "lqutil.h" #include "liblqtext.h" /** System calls and functions... **/ /** Unix system calls used in this file: **/ extern void exit(); /** Unix Library Functions used: **/ /** lqtext library functions: **/ /** functions used before they're defined within this file: **/ static void ProcessFile( #ifdef HAVE_PROTO t_LQTEXT_Database *db, char *InputFile #endif ); static void PrintLineNumber( #ifdef HAVE_PROTO t_LQTEXT_Database *db, unsigned long Offset, char *FileName #endif ); /** **/ static char *Revision = "@(#) $$"; char *progname = "lqbyteline"; int main(argc, argv) int argc; char *argv[]; { extern int optind, getopt(); extern char *optarg; int ch; int ErrorFlag = 0; char *InputFile = 0; t_LQTEXT_Database *db; t_lqdbOptions *Options; progname = argv[0]; Options = LQT_InitFromArgv(argc, argv); while ((ch = getopt(argc, argv, "Zz:af:hNpr:slxVv")) != EOF) { switch (ch) { case 'z': case 'Z': break; /* done by LQT_InitFromArgv(); */ case 'V': fprintf(stderr, "%s version %s\n", progname, Revision); break; case 'f': InputFile = optarg; break; case 'x': ErrorFlag = (-1); break; case '?': ErrorFlag = 1; } } if (ErrorFlag) { fprintf(stderr, "Usage: %s [options] [file [...]]\n", progname); LQT_PrintDefaultUsage(Options); exit( ErrorFlag > 0 ? 1 : 0); /* 0 means -x was used */ } db = LQT_OpenDatabase(Options, O_RDONLY, 0); if (InputFile) { ProcessFile(db, InputFile); } if (optind >= argc) { ProcessFile(db, "-"); } else { while (optind < argc) { ProcessFile(db, argv[optind++]); } } return 0; } static void ProcessFile(db, InputFile) t_LQTEXT_Database *db; char *InputFile; { FILE *f; char NeedClose = 1; char *theLine; if (STREQ(InputFile, "-")) { f = stdin; NeedClose = 0; InputFile = "standard input"; } else { f = LQU_fEopen(E_FATAL|E_SYS, InputFile, "List of bytes & files", "r"); } while (LQU_fReadLine(f, &theLine, LQUF_NORMAL) >= 0) { if (theLine && *theLine) { unsigned long theOffset; register char *p; for (p = theLine; *p; p++) { if (!isspace(*p)) break; } if (!isdigit(*p)) { Error(E_FATAL, "\"%s\" contains line with no leading byte offset: %s", InputFile ); break; } theOffset = 0L; do { theOffset *= 10; theOffset += (*p) - '0'; p++; } while (isdigit(*p)); if (!isspace(*p)) { Error(E_FATAL, "\"%s\" no space and filename after offset in: %s", InputFile, theLine ); break; } *p = '\0'; do { ++p; } while (isspace(*p)); PrintLineNumber(db, theOffset, p); } } if (NeedClose) { (void) fclose(f); } } static void PrintLineNumber(db, Offset, FileName) t_LQTEXT_Database *db; unsigned long Offset; char *FileName; { static FILE *f = 0; static unsigned long LastOffset = 0L; static unsigned long LastLineNumber; static char *LastName = 0; int ch; if (!LastName || !STREQ(FileName, LastName) || LastOffset > Offset) { if (f) { (void) fclose(f); f = 0; } if (LastName) { efree(LastName); } LastName = emalloc("PrintLineNumber::FileName", strlen(FileName) + 1); (void) strcpy(LastName, FileName); f = LQU_fEopen(E_WARN, LastName, "input file", "r"); if (!f) { return; } LastOffset = 0L; LastLineNumber = 1L; } while (LastOffset != Offset) { if ((ch = getc(f)) == EOF) { break; } else if (ch == '\n') { ++LastLineNumber; } ++LastOffset; } printf("%ld %s\n", LastLineNumber, FileName); }