# This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # 4tags.1 # 4tags.c # Makefile # README # echo x - 4tags.1 sed 's/^X//' >4tags.1 << 'END-of-4tags.1' X.TH 4gltags 1 X.SH NAME X4gltags \- Generates tags for Informix 4GL X.SH SYNOPSIS X.B 4gltags X.RB [ "-vqbo" ] X.I "file(s)" X.br X.SH OPTIONS X.TP 1.5i X.BR -v erbose XDisplay information about which file and line that are being processed. X.TP 1.5i X.BR -q uite XMake 4gltags not complaining about duplicated tags. X.TP 1.5i X.BR -b ackward XMake tags search backward (default=forward) X.TP 1.5i X.BI -o filename XOutput tags to X.I filename. XDefault is tags X.SH DESCRIPTION X.I 4gltags Xreads through the files given, checks for FUNCTION and REPORT definitions Xin the file, and creates a tag for each occurence. X.br XTags are automatically appended to the tagfile if it already Xexists. And the tagfile is automatically sorted. X.br XCurrent Version is 3.7 X X.SH FILES Xtags, *.4gl X X.SH PROGRAMMER X4gltags was programmed By : X.br X Lars Johansson (lajo@dsr.dk) X.br X Dansk Software R}dgivning Aps X.br X Current location: lajo@q8.dk END-of-4tags.1 echo x - 4tags.c sed 's/^X//' >4tags.c << 'END-of-4tags.c' X/* ------------------------------------------------------------------------- X * File : 4tags.c X * Author : Lars Johansson (lajo@q8.dk) X * Date : 16/12/94 X * Purpose : Creates tags for Informix 4gl file(s) X * X * Notice: X * Permission to use, copy, modify, and distribute this software and X * its documentation for any purpose is hereby granted without fee, provided X * that the above copyright notices and this permission notice appear in X * all copies of the software and related documentation. X * X * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, X * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY X * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. X * X * IN NO EVENT SHALL LARS JOHANSSON BE LIABLE FOR ANY SPECIAL, INCIDENTAL, X * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE X * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR X * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X * ------------------------------------------------------------------------- */ Xstatic char Copyright[] = "Copyright (c) 1994,1995 Lars Johansson"; Xstatic char sccs[] = "@(#)4tags.c 3.7 96/10/08 11:59:36"; X#include X#include X#include X Xchar *mem_error = "Sorry, no more memory"; X Xint verbose; Xint append; Xint update; X X Xint SaveTag1(void *Save ); Xint WriteTags(char *tmpname, char *mode); Xint TagSort(const void *p1, const void *p2); Xvoid ToUpperStr( char * InBuffer); Xvoid rm_trail( char *str); X Xstatic int Count=0; Xstatic int Line=0; Xstatic long TotalLines=0; Xstatic int Debug=0; Xstatic long Compares=0; Xstatic int Complain=1; Xstatic int backward=0; Xstatic FILE *OutFile; Xstatic void *Tree_Head; X Xmain( int argc, char **argv) X{ X X FILE *fp, *outfp; X char tmpname[1024]; X char omode[10]; X int files=0; X extern char *optarg; X extern int optind; X int c; X X if ( argc < 2) X { X printhelp(); X exit(1); X } X append=1; X strcpy(tmpname, "tags"); X strcpy(omode, "w"); X X /* Get some options */ X while ((c = getopt (argc, argv, "bo:qv?")) != -1 ) X { X switch (c) X { X case 'o': X strcpy(tmpname, optarg); X break; X case 'q': Complain=0; break; X case 'v': verbose=1; break; X case 'b': backward=1; break; X case '?': X default: X printhelp(); X exit(1); X X } X } X X /* X * Rest of argv must be files - loop thru 'em X */ X argc--; X for(; optind <= argc; optind++) X { X if ( (fp = fopen(argv[optind], "r")) != NULL) X { X MakeTag(fp, argv[optind]); X fclose(fp); X files++; X } X TotalLines+=Line; X Line=0; X } X if (files) X { X WriteTags(tmpname, omode); X } X else X if ( verbose ) X printf("No files processed\n"); X X if ( verbose ) X { X printf("%d Files Processed\n", files); X printf("%d Lines Process\n", TotalLines); X printf("%d Compares\n", Compares); X } X} X X/* X * Make tags from the file X */ XMakeTag(FILE *infile, char *filename) X{ X register char *ip; /* pointer to InBuffer */ X register char *op; /* Pointer to OutBuffer */ X register char *sp; /* Point to first char after 'FUNCTION'/'REPORT'*/ X register char *tp; /* pointer to Tag */ X char InBuffer[2048]; X char OutBuffer[2048]; X char WorkBuffer[2024]; X int Comment=0; X char Tag[100]; X int rc; X X X X if ( verbose ) X { X printf("%s %d\r", filename, 0); X fflush(stdout); X } X X while ( fgets(InBuffer, 2048, infile) && !feof(infile) ) X { X ip=InBuffer; X op=OutBuffer; X Line++; X X if ( verbose && !(Line % 100 ) ) X { X printf("%s %d\r", filename, Line); X fflush(stdout); X } X X if ( Comment==3) X { X /* We have seen an unclosed '{' X * now search for '}' X */ X while (*ip ) X { X /* We can skip white spaces */ X if ( *ip == ' ' || *ip == '\t') X { X ip++; X continue; X } X if ( *ip == '}' ) X { X /* Multi line comment ends here */ X Comment=0; X break; X } X *ip++; X X } X if ( Comment == 3 ) X continue; X } X else X Comment=0; X X /* X * If line does not start with [whitespace][fFtT] X * Then we don't make any further process on it X */ X while ( *ip ) X { X if ( *ip == 'r' || *ip == 'R' || *ip == 'f' || *ip == 'F' ) X break; X if ( (*ip >= 'A' && *ip <= 'z') || X *ip == '#' || X *ip == '\n' || X *ip == '"' || X *ip == '-' X ) X { X Comment++; X break; X } X if ( *ip == '{' ) X { X /* Lets check if this comment ends on this line */ X while (*ip ) X { X if ( *ip == '}' ) X { X /* Comments ends here */ X /* We need to fall through to the actual X * processing, because the might be a X * Function declaration after this comment */ X Comment=4; X break; X } X *ip++; X } X if ( !Comment ) X { X /* Comment span more lines */ X Comment = 3; X break; X } X } X *ip++; X } X if ( Comment == 4 || Comment == 0 ) X Comment=0; X else X continue; X X strcpy(WorkBuffer, InBuffer); X ToUpperStr(WorkBuffer); X X ip = (WorkBuffer + (ip - InBuffer)); X X if (strncmp(ip, "FUNCTION", 8)==0 || strncmp(ip, "REPORT", 6) ==0 ) X { X /* X * It's a FUNCTION or a REPORT X */ X if ( *ip == 'F') X { X ip+=8; X /* Check if this really looks like a function/report decl. */ X if ( *ip != ' ' && *ip != '\t') X continue; X } X else X { X ip+=6; X tp=ip; X /* Check if this really looks like a function/report decl. */ X if ( *ip != ' ' && *ip != '\t') X continue; X /* Check if not "REPORT TO" */ X op=Tag; X while(*ip==' ' || *ip =='\t') X ++ip; X while(*ip!=' ' && *ip !='\t') X { X /* If end of line breakout */ X if (*ip == '\n') X { X op=Tag; X *op=0; X break; X } X *op++ = *ip++; X } X *op=0; X ToUpperStr(Tag); X if (strcmp(Tag, "TO") == 0) X continue; X ip=tp; X } X X X X sp = (InBuffer + (ip - WorkBuffer)); X ip=InBuffer; X X op=OutBuffer; X tp = Tag; X /* Skip white spaces */ X while (*sp == ' ' || *sp == '\t') X sp++; X X while (*ip) X { X if ( *ip == '(') X { X *op++=*ip++; X break; X } X else if (*sp == '(') X *tp++=0; X X *op++=*ip++; X *tp++=*sp++; X } X *op=0; X *tp=0; X rm_trail(Tag); X sprintf(WorkBuffer, "%s\t%s %c^%s%c\n" X , Tag X , filename X , backward ? '?' : '/' X , OutBuffer X , backward ? '?' : '/' X ); X X rc= SaveTag1(WorkBuffer); X if (rc && Complain ) X { X printf("Duplicate tag: %s In file %s line %d\n", X Tag, filename, Line); X } X if ( rc == 0 ) X Count++; X X } X } X if ( verbose ) X { X printf("%s %d\n", filename, Line); X fflush(stdout); X } X} X X X/* X * toupper a string as the functionname says X */ Xvoid ToUpperStr( char * InBuffer) X{ X register char *p = InBuffer; X X while (*p) X *p++ = toupper(*p); X} X X/* X * Save A char strings in the array ONLY IF NOT ALREADY THERE !! X * X */ Xint SaveTag1(void *Save ) X{ X void *rc; X char *p = (char*) malloc(strlen(Save)+2); X char *q; X if ( p== NULL) X { X perror(mem_error); X exit(99); X } X strcpy(p, Save); X q = (char*)tfind(p, &Tree_Head, TagSort); X if ( q == NULL ) X { X strcpy(p, Save); X rc = (void *)tsearch(p, &Tree_Head, TagSort); X return(0); X } X else X free(p); X return(1); X} X X/* X * Sort function for qsort X */ Xint TagSort(const void *p1, const void *p2) X{ X register const char *c1, *c2; X c1=p1; X c2=p2; X X Compares++; X while ( *c1 == *c2 && *c1 != '\t' && *c2 != '\t') X { X *c1++; X *c2++; X } X if ( *c1 == '\t' && *c2 != '\t') X return(-1); X else if (*c2 == '\t' && *c1 != '\t') X return(1); X else if (*c1 != *c2) X { X if ( *c1 > *c2) X return(1); X else X return(-1); X } X else X return(0); X} X Xvoid TreeWalk( void *node, VISIT order, int level) X{ X if ( order == postorder || order == leaf ) X fprintf(OutFile, "%s", *((char **)node)); X} X X/* X * Writes all record saved in the tree X */ Xint WriteTags(char *tmpname, char *mode) X{ X char Buffer[2048]; X X if (append ) X { X if ((OutFile = fopen(tmpname, "r")) != NULL) X { X if (verbose) printf("Appending\n"); X while(fgets(Buffer, sizeof(Buffer)-1, OutFile)) X { X SaveTag1(Buffer); X } X fclose(OutFile); X } X else X if ( verbose ) X fprintf(stderr, X "Cannot open %s for reading - continuing anyway\n" X ,tmpname); X } X unlink(tmpname); X if ((OutFile = fopen(tmpname, mode)) == NULL) X { X perror("Cannot open tagfile"); X exit(1); X } X X twalk(Tree_Head, TreeWalk); X X if (verbose ) X printf("%d Tags created\n", Count); X fflush(OutFile); X fclose(OutFile); X} X Xint printhelp() X{ X X printf("4gltags - (Ver. 3.7) %s\n", Copyright); X printf("Usage :4gltags [options] file(s)\n"); X printf("\toptions:\n"); X printf("\t -v verbose mode (show what's going on)\n"); X printf("\t -o FILE output to file instead of tags\n"); X printf("\t -b use backward search (default=forward)\n"); X printf("\t -q be quiet about duplicated tags\n"); X} X Xvoid rm_trail( char *str) X{ X register char *p1=str; X X while(*p1 != '\0') p1++; X p1--; X while(*p1 == ' ') X *p1-- = '\0'; X} X END-of-4tags.c echo x - Makefile sed 's/^X//' >Makefile << 'END-of-Makefile' XCC=gcc XCCOPT=-O -s XCFLAGS=$(CCOPT) XCHMOD=/bin/chmod XCP=/bin/cp XRM=/bin/rm X XOBJS = 4tags.o XSRCS = 4tags.c X Xall: 4gltags Xexport : install clean X4gltags: $(OBJS) X $(CC) $(CCOPT) -o 4gltags $(OBJS) X X#install: 4gltags X# -$(CHMOD) 666 /Sys/Bin/4gltags X# $(CP) 4gltags /Sys/Bin/4gltags X# -$(CHMOD) 511 /Sys/Bin/4gltags X Xclean: X $(RM) -f $(OBJS) X $(RM) -f 4gltags END-of-Makefile echo x - README sed 's/^X//' >README << 'END-of-README' X X 4gltags - A 'C' Version X By X Lars Johansson X X ------------------------------------------------------------------------------ X X This 'C' version of 4gltags was programmed because I was beginning to get X a bit tired of the poor speed of the original 4gltags, which was programmed X in shell. X X This version highlights : X X - Very fast. X - Generates tags for both REPORT and FUNCTION. X - Automatically appends to and sorts the tagfile. X - knows about '--' '#' and '{}' type comments. X X 4gltags has been tested in-house and by Kerry Sainsbury (thanks Kerry). X It has been used in-house for several months with no complains. X X 4gltags can be found at: http://q8t.q8.dk/~lajo X Current Version is 3.7 X X 4gltags Syntax. X X 4gltags [options] 4gl-file(s) X X Three options are available for your use: X X -o outputfile use 'outputfile' as tagfile X -v verbose run. X -q be quiet, don't complain about duplicated tags. X -b Make backward searching tags X X X All this can be read in the man-page. X X X The included makefile is ready for GNU-C compiler, and should work X with most ANSI-C compilers. Users of NON ANSI-C compilers needs to X fiddle a little with the prototypes and functions declarations for X a clean compile. X X All comments,suggestions and bugs are welcomed at lajo@dsr.dk. X X Thanks to : X Kerry Sainsbury(kerry@kcbbs.gen.nz) for testing and the Informix FAQ. X X Regards, X Lars Johansson. X X X Lars Johansson X Dansk Software R}dgivning Aps. X Bydammen 5 X DK-2750 Ballerup X Denmark X lajo@dsr.dk X X Currently located (as consultant) at: X X Kuwait Petroleum (Danmark) A/S X Hummeltoftevej 49 X DK-2830 Virum X Denmark X lajo@q8.dk END-of-README exit