home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-02-09 | 28.2 KB | 1,226 lines |
- Path: wugate!wucs1!uunet!bbn.com!rsalz
- From: rsalz@uunet.uu.net (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v17i093: Create tags file for Prolog
- Message-ID: <1485@fig.bbn.com>
- Date: 8 Feb 89 22:40:50 GMT
- Lines: 1216
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Chris Tweed <caad.ed.ac.uk!chris>
- Posting-number: Volume 17, Issue 93
- Archive-name: prologtags
-
- [ I haven't tried this. --r$ ]
-
-
- Ptags creates tags for Prolog predicates as defined in the source
- files supplied as input. Its use is analogous to that of ctags(1).
-
- ------------------------------ CUT HERE ------------------------------
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Contents: TestFiles/ READ_ME ptags.L Makefile ptags.h config.h main.c
- # process.c symbol.c tags TestFiles/comments.pl TestFiles/crazy.pl
- # TestFiles/difficult.pl TestFiles/morecomments.pl TestFiles/tags
- # TestFiles/tricky.pl
-
- echo x - READ_ME
- sed 's/^@//' > "READ_ME" <<'@//E*O*F READ_ME//'
- Making and installing ptags should be straightforward. Two things need
- to be done before attempting to compile and link the program on your
- system.
-
- First edit Makefile and set DFLAGS to be either -DBSD4_2 (the default)
- or -DSYSV, depending on which system you are using. If you're not
- using either of these you may have to make some changes to the code -
- sorry. You may also want to change the assignments to FINALVN such
- that ptags is installed somewhere else.
-
- Second make sure you know which characters your Prolog treats as
- symbols. Edit config.h and make any necessary changes to my
- definitions.
-
- After you have gone through these two stages you should be ready to
- type 'make ptags' or 'make install'.
-
- Happy tagging!
-
- Chris Tweed
- chris@caad.ed.ac.uk
- @...!mcvax!ukc!edcaad!chris
- @//E*O*F READ_ME//
- chmod u=rw,g=rw,o=r READ_ME
-
- echo x - ptags.L
- sed 's/^@//' > "ptags.L" <<'@//E*O*F ptags.L//'
- @.TH PTAGS L "February 11, 1988" "" "Local UNIX Programmer's Manual"
- @.UC 4
- @.SH NAME
- ptags \- creates a tags file from Prolog sources
- @.SH SYNOPSIS
- @.B ptags
- [\-w] [\-l] [\-a] [\-p] files
- @.br
- @.SH DESCRIPTION
- @.I Ptags
- creates a tags file from one or more Prolog source files.
- It will do for Prolog predicates what
- @.IR ctags (1)
- does for C functions.
- Like
- @.I ctags,
- output is sent to a file called
- @.I tags
- in the current directory.
- Each line in
- the tags file contains three tab-separated fields:
- the first is the name of each predicate defined in the source files;
- the second is the name of the file where the predicate is defined;
- and the third is an instruction to be executed by
- @.IR vi (1)
- or
- @.IR ex (1)
- to find the definition within the source file.
- As with
- @.I ctags,
- the tags file is sorted alphabetically by predicate name.
- @.PP
- @.I Ptags
- accepts four flags to control its operation and output:
- @.TP
- @.B \-w
- suppresses warnings about multiple definitions of the same predicate
- in different files.
- Only the first occurrence of a definition is entered in the tags file.
- @.TP
- @.B \-l
- use line numbers,
- rather than regular expressions,
- to locate predicate definitions in source files.
- @.TP
- @.B \-a
- append the output to an existing tags file in the current directory.
- This allows you to combine output from
- @.I ptags
- with output from
- @.I ctags.
- A single tags file can be used to access Prolog predicates and C functions
- \(em useful if you are mixing Prolog and C in a single program.
- @.TP
- @.B \-p
- sends the output to
- @.I stdout
- instead of to tags file.
- @.PP
- @.SH "FILES"
- @.PP
- \&./tags tags file created or appended to
- @.SH "SEE ALSO"
- ctags(1), ex(1), vi(1)
- @.SH "DIAGNOSTICS"
- @.I Ptags
- complains about a variety of things, mostly related to reaching limits
- of static arrays, e.g. predicate name too long, too many symbols (predicates),
- too many source files, etc.
- @.sp
- @.I Ptags
- can optionally produce warnings about predicates defined
- across different files - see \-w above.
- Warnings are only issued once for each different file.
- Note that the arity of these predicates may be different -
- @.I ptags
- doesn't care.
- @.SH "BUGS"
- @.I Ptags
- is NOT a syntax checker for Prolog code, and will quite happily swallow
- syntax errors without complaint, probably filling the tags file with
- garbage at the same time.
- @.sp
- The parser is very basic and may not tolerate your style of layout
- for Prolog code.
- For example,
- if regular expressions are used to locate definitions
- (rather than line numbers), they will
- expect all definitions to begin at the leftmost side of the
- screen, because the regular expressions always begin with a
- leading `^' character, followed immediately by the predicate
- name, and some trailing context characters.
- @.sp
- Most Prologs will allow "strange" characters in predicate names,
- provided the names are enclosed in single quotes.
- These names will often not be acceptable as tags, though they seem to
- be accepted on the command line with the \-t option in ex or vi.
- Nothing we can do about this.
- Anybody care to modify ex?
- @.SH "AUTHORS"
- @.PP
- Chris Tweed
- @.br
- Bob Kemp
- @//E*O*F ptags.L//
- chmod u=rw,g=r,o=r ptags.L
-
- echo x - Makefile
- sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
- INCDIR=.
- INC=-I$(INCDIR)
- # change to -DSYSV for System V
- DFLAGS=-DBSD4_2
- CFLAGS=-g $(INC) $(DFLAGS)
- HDRS=ptags.h config.h
- OBJS=main.o process.o symbol.o
- BIN=ptags
- FINAL=/usr/local/bin/ptags
- MAN=/usr/man/manl/ptags.l
- SRCS=READ_ME ptags.L Makefile $(HDRS) $(OBJS:.o=.c) tags TestFiles TestFiles/*
-
- $(BIN): $(OBJS)
- cc $(CFLAGS) -o $(BIN) $(OBJS)
-
- install: $(BIN) $(MAN)
- install -s $(BIN) $(FINAL)
-
- $(MAN): ptags.L
- cp ptags.L $(MAN)
-
- shar: $(SRCS)
- shar -c -v $(SRCS) > ptags.shar
-
- lint:
- lint -h $(OBJS:.o=.c)
-
- tags: $(OBJS:.o=.c) $(HDRS)
- ctags -t $(HDRS) $(OBJS:.o=.c)
-
- clean:
- rm -f core makerr $(OBJS) p.c
-
- veryclean: clean
- rm -f $(BIN)
-
- # dependencies
- $(OBJS): $(HDRS)
- @//E*O*F Makefile//
- chmod u=rw,g=rw,o=r Makefile
-
- echo x - ptags.h
- sed 's/^@//' > "ptags.h" <<'@//E*O*F ptags.h//'
- /*
- * ptags - creates entries in a tags file for Prolog predicates
- *
- * Usage: ptags [-w] [-l] [-a] [-p] file1 ... filen
- *
- * This program code may be freely distributed provided
- *
- * a) it, or any part of it, is not sold for profit; and
- *
- * b) this entire comment remains intact.
- *
- * Copyright (c) 1988, Chris Tweed & Bob Kemp, EdCAAD,
- * University of Edinburgh
- *
- * Please mail us any changes, enhancements, or bug fixes.
- *
- * Chris Tweed
- * chris@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!chris
- *
- * or
- *
- * Bob Kemp
- * bob@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!bob
- *
- */
-
- #define local static
- #define global
- #define VOID (void)
- #define REG register
- #define BOOL int
-
- #define MAXFILE 128
- #define MAXSYM 1024
- #define MAXSTR 256
- #define MAXBUF MAXSTR
-
- #define TRUE 1
- #define FALSE 0
-
- #define FSEP '\t'
-
- typedef struct symbol {
- char name[MAXSTR];
- char *file;
- } SYMBOL;
-
- /* NULLS etc. */
-
- #define NOSYM (SYMBOL *)0
- #define NOSTR (char *)0
- #define NOOP 0
-
- /* MISC */
- #define EOSTR '\0'
-
- /* MACROS */
- #define STREQ(s1, s2) (strcmp((s1), (s2))==0) /* string compare */
-
- @//E*O*F ptags.h//
- chmod u=rw,g=rw,o=r ptags.h
-
- echo x - config.h
- sed 's/^@//' > "config.h" <<'@//E*O*F config.h//'
- /* header file to define system dependent things */
-
- /*
- * ptags - creates entries in a tags file for Prolog predicates
- *
- * Usage: ptags [-w] [-l] [-a] [-p] file1 ... filen
- *
- * This program code may be freely distributed provided
- *
- * a) it, or any part of it, is not sold for profit; and
- *
- * b) this entire comment remains intact.
- *
- * Copyright (c) 1988, Chris Tweed & Bob Kemp, EdCAAD,
- * University of Edinburgh
- *
- * Please mail us any changes, enhancements, or bug fixes.
- *
- * Chris Tweed
- * chris@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!chris
- *
- * or
- *
- * Bob Kemp
- * bob@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!bob
- *
- */
-
-
- #if SYSV
- # define INDEX strchr
- #else BSD4_2
- # define INDEX index
- #endif
-
- /*
- * According to "Programming in Prolog", Clocksin and Mellish,
- * Springer-Verlag, 1981, Prolog has two types of atom: one
- * composed of letters and digits, and one composed of symbols.
- * In ptags we need to recognise both and distinguish between them
- * because they determine the valid characters in predicate names.
- *
- * The definitions used below are those used in C-Prolog 1.5+, but
- * your Prolog may be different. C-Prolog differs from Clocksin
- * and Mellish in that '$' has the same status as alphanumeric
- * characters and is not, therefore, a symbol. Check your Prolog
- * and edit these definitions if necessary.
- *
- * Also defined is a line comment character which may be different
- * in your Prolog.
- *
- */
-
- /* valid symbol characters - NOTE '$' is not one of these */
- #define SYM_CHRS "+-*/\\^<>=`~:.?@#&"
-
- /* test for valid symbol characters */
- #define IS_SYM(c) (INDEX(SYM_CHRS, c) != NULL)
-
- /* test for valid character at start of predicate name */
- #define BEGIN_NAME(c) (islower(c) || c == '\'' || c == '$')
-
- /* test for valid characters within predicate name */
- #define IN_NAME(c) (isalnum(c) || c == '_' || c == '$')
-
- #define L_COMMENT_CHR '%'
- @//E*O*F config.h//
- chmod u=rw,g=rw,o=r config.h
-
- echo x - main.c
- sed 's/^@//' > "main.c" <<'@//E*O*F main.c//'
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/stat.h>
- #include "ptags.h"
-
- /*
- * ptags - creates entries in a tags file for Prolog predicates
- *
- * Usage: ptags [-w] [-l] [-a] [-p] file1 ... filen
- *
- * This program code may be freely distributed provided
- *
- * a) it, or any part of it, is not sold for profit; and
- *
- * b) this entire comment remains intact.
- *
- * Copyright (c) 1988, Chris Tweed & Bob Kemp, EdCAAD,
- * University of Edinburgh
- *
- * Please mail us any changes, enhancements, or bug fixes.
- *
- * Chris Tweed
- * chris@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!chris
- *
- * or
- *
- * Bob Kemp
- * bob@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!bob
- *
- */
-
- #define TEMPLATE "/tmp/ptXXXXXXXX"
-
- /* shorthand for usage messages */
- #define USE(mesg) VOID fprintf(stderr, mesg)
-
- global char *progname; /* name of this program */
- global BOOL warnings = TRUE; /* warns of defs across files if TRUE */
- global BOOL lines = FALSE; /* TRUE for line numbers in tags file */
- global BOOL appending = FALSE; /* append to existing tags if TRUE */
- global BOOL piping = FALSE; /* send output to stdout if TRUE */
- global char *cfile; /* current input filename */
- global char *filename[MAXFILE]; /* list of filenames to be processed */
- global int nf = 0; /* number of files to be processed */
- global FILE *tags; /* pointer to the tags file */
-
- local void usage(); /* displays usage and EXITS */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- extern char *strcpy();
- extern char *mktemp();
- extern FILE *fopen();
- extern BOOL process_file();
- int i;
- char *p;
- FILE *ifp;
- char tagfile[MAXPATHLEN];
- char cmd[MAXPATHLEN];
- struct stat stbuf;
-
- #if BSD4_2
- setlinebuf(stderr);
- #endif
-
- progname = argv[0];
- /* process arguments */
- while (--argc) {
- if (argv[1][0] == '-') {
- p = argv[1] + 1;
- if (p == NOSTR)
- usage(progname); /* EXITS */
- while(*p) {
- switch(*p) {
- case 'w':
- warnings = FALSE;
- break;
- case 'l':
- lines = TRUE;
- break;
- case 'a':
- appending = TRUE;
- break;
- case 'p': /* send output to stdout */
- piping = TRUE;
- break;
- default:
- VOID usage(progname); /* EXITS */
- break;
- }
- p++;
- }
- } else if (nf < MAXFILE)
- filename[nf++] = argv[1];
- else {
- VOID fprintf(stderr, "%s: too many files\n", progname);
- exit(1);
- }
- argv++;
- }
-
- if (nf == 0)
- usage(progname); /* EXITS */
-
- /* open temporary tags file */
- VOID strcpy(tagfile, TEMPLATE);
- VOID mktemp(tagfile);
- /* if appending, copy existing tags file */
- if (appending && stat("./tags", &stbuf) == 0) {
- VOID sprintf(cmd, "cp tags %s", tagfile);
- if (system(cmd) != 0) {
- VOID fprintf(stderr, "%s: error copying existing tags file\n",
- tagfile);
- }
- tags = fopen(tagfile, "a");
- } else
- tags = fopen(tagfile, "w");
-
- if (tags == NULL) {
- VOID fprintf(stderr, "%s: can't open tags file\n", progname);
- exit(1);
- }
-
- for(i=0; i<nf; i++) {
- cfile = filename[i];
- /* open input file */
- ifp = fopen(cfile, "r");
- if (ifp == NULL) {
- VOID fprintf(stderr, "%s: can't open %s\n", progname, cfile);
- continue;
- }
- /* process the file */
- VOID process_file(ifp);
- VOID fclose(ifp);
- }
- VOID fclose(tags);
- if (piping == TRUE)
- VOID sprintf(cmd, "sort %s", tagfile);
- else
- VOID sprintf(cmd, "sort %s > tags", tagfile);
- if (system(cmd) == 0)
- VOID unlink(tagfile);
- else {
- VOID fprintf(stderr, "%s: error copying temp file (%s)\n",
- progname,
- tagfile);
- exit(1);
- }
- }
-
- /*
- * local void
- * usage(s)
- *
- * Prints usage and EXITS.
- *
- */
-
- local void
- usage(s)
- char *s;
- {
- VOID fprintf(stderr, "usage: %s\n", s);
- USE("\t\t[-w]\t/* suppress warnings about multiple defs */\n");
- USE("\t\t[-l]\t/* use line numbers instead of search strings */\n");
- USE("\t\t[-a]\t/* append to tags file */\n");
- USE("\t\t[-p]\t/* send output to stdout */\n");
- USE("\t\tfile1 ... filen\n");
- exit(1);
- }
- @//E*O*F main.c//
- chmod u=rw,g=rw,o=r main.c
-
- echo x - process.c
- sed 's/^@//' > "process.c" <<'@//E*O*F process.c//'
- #include <stdio.h>
- #include <ctype.h>
- #include "config.h"
- #include "ptags.h"
-
- /*
- * ptags - creates entries in a tags file for Prolog predicates
- *
- * Usage: ptags [-w] [-l] [-a] [-p] file1 ... filen
- *
- * This program code may be freely distributed provided
- *
- * a) it, or any part of it, is not sold for profit; and
- *
- * b) this entire comment remains intact.
- *
- * Copyright (c) 1988, Chris Tweed & Bob Kemp, EdCAAD,
- * University of Edinburgh
- *
- * Please mail us any changes, enhancements, or bug fixes.
- *
- * Chris Tweed
- * chris@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!chris
- *
- * or
- *
- * Bob Kemp
- * bob@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!bob
- *
- */
-
- /* lexical states */
-
- #define S_SPACE 1
- #define S_NAME 2
- #define S_SYM 3
- #define S_CLAUSE 4
- #define S_DOT 5
- #define S_STR 6
- #define S_QUOTE 7
-
- /* define characters that must be escaped in regular expressions */
- #define ESC_CHRS ".\\$*%&^/[]"
-
- /* print character - with escape if necessary */
- #define PRINTC(ch, fp) if (INDEX(ESC_CHRS, ch) != NULL) { \
- VOID fprintf(fp, "\\%c", ch); \
- } else VOID putc(ch, fp)
-
- extern char *INDEX();
- extern SYMBOL *lookup();
- local void skip_comment(); /* skips comments in source */
- local int skip_to_chr(); /* move read pointer to chr */
- local BOOL print_tag(); /* print the tag */
- local void print_search(); /* print search string */
-
- local int lineno = 1; /* line number in input file */
-
- /*
- * global BOOL
- * process_file(fp)
- *
- * Main processing routine.
- *
- */
-
- global BOOL
- process_file(fp)
- FILE *fp; /* pointer to current file */
- {
- extern char *strcpy();
- extern char *progname; /* name of this program */
- extern char *cfile; /* name of current file */
- char buff[MAXSTR]; /* buffer */
- REG int chno = 0; /* current position in buff */
- REG int state = S_SPACE; /* state of the parser */
- int pstate = S_SPACE; /* previous state */
- REG int ch; /* current character */
- REG int lastch = EOSTR; /* previous character */
- int c; /* temporary character store */
- int startno;
- BOOL inquote = FALSE;
-
- lineno = 1;
-
- for (chno = 0; chno < MAXSTR; chno++)
- buff[chno] = EOSTR;
-
- while ((ch = getc(fp)) != EOF ) {
-
- if (ch == '\n')
- lineno++;
-
- switch (state) {
- case S_SPACE: /* in whitespace preceding clause */
- if (!isspace(ch)) { /* usually will be space */
- if (ch == L_COMMENT_CHR)
- skip_comment(ch, fp);
- else if (ch == '\'') {
- state = S_QUOTE;
- } else if (ch == '"' && ! inquote) {
- pstate = state;
- state = S_STR;
- } else if (BEGIN_NAME(ch)) {
- state = S_NAME;
- buff[0] = ch;
- chno = 1;
- /* look for comments */
- } else if (ch == '/') {
- if ((c=getc(fp)) == '*') {
- skip_comment(c, fp);
- } else {
- ungetc(c, fp);
- state = S_SYM;
- buff[0] = ch;
- chno = 1;
- }
- } else if (IS_SYM(ch)) {
- state = S_SYM;
- buff[0] = ch;
- chno = 1;
- } else if (ch != '/') /* skip "rubbish" */
- state = S_CLAUSE;
- }
- break;
- case S_NAME: /* in predicate name */
- /* FALLS THROUGH */
- case S_SYM:
- /* weed out directives and queries */
- if (chno == 1 && ch == '-' &&
- (lastch == ':' || lastch == '?')) {
- state = S_CLAUSE;
- break;
- }
-
- if (chno == MAXSTR) {
- VOID fprintf(stderr,
- "%s: predicate name too long at line %d\n",
- progname, lineno);
- return FALSE;
- }
- buff[chno++] = ch;
- if (ch == '\'') {
- state = S_QUOTE;
- } else if (inquote) {
- break;
- } else if (state == S_NAME && ch == '.') {
- state = S_DOT;
- } else if (ch == '/') { /* comment in symbol or name */
- /* weed comments out */
- if ((c=getc(fp)) == '*') {
- skip_comment(c, fp);
- chno--;
- break;
- } else {
- ungetc(c, fp);
- if (state == S_NAME)
- state = S_CLAUSE;
- }
- } else if ((state == S_NAME && ! IN_NAME(ch)) ||
- (state == S_SYM && !IS_SYM(ch)))
- state = S_CLAUSE;
-
- if (state != S_NAME && state != S_SYM) {
- buff[--chno] = EOSTR;
- if (print_tag(buff, ch, lineno) == FALSE)
- exit(1);
- }
- if (ch == L_COMMENT_CHR)
- skip_comment(ch, fp);
- break;
- case S_CLAUSE: /* in the clause text */
- if (ch == '\'') {
- inquote = (! inquote);
- } else if (inquote)
- break;
- else if (ch == L_COMMENT_CHR) {
- skip_comment(ch, fp);
- } else if (ch == '"') {
- pstate = state;
- state = S_STR;
- } else if (ch == '.')
- state = S_DOT;
- else if (ch == '*' && lastch == '/')
- skip_comment(ch, fp);
- break;
- case S_DOT:
- if (isspace(ch))
- state = S_SPACE;
- else
- state = S_CLAUSE;
- break;
- case S_STR:
- /* we're not really interested in strings, but we want to
- * get them out of the way as soon as possible because they
- * may contain nasty things like a dot (.) followed by
- * white space which would otherwise throw the states off.
- * Note that we must also allow for "" within a string as
- * this is used to put a single " into the string.
- */
- startno = lineno;
- do {
- if (skip_to_chr(fp, ch, '"') == EOF) {
- fprintf(stderr,
- "%s: can't find end of string on line %d in %s\n",
- progname, startno, cfile);
- exit(1);
- }
- } while((ch = getc(fp)) == '"');
- state = pstate;
- break;
- case S_QUOTE:
- inquote = ( ! inquote);
- if (inquote) {
- state = S_NAME;
- buff[0] = '\'';
- buff[1] = ch;
- chno = 2;
- } else
- state = S_CLAUSE;
- break;
- }
- lastch = ch;
- }
- return TRUE;
- }
-
- /*
- * local void
- * skip_comment(ch, fp)
- *
- * Move reading position to beyond end of comment.
- *
- */
-
- local void
- skip_comment(ch, fp)
- FILE *fp; /* pointer to current file */
- REG int ch; /* current input character */
- {
- extern char *progname;
- extern char *cfile;
- int startno = lineno;
-
- if (ch == L_COMMENT_CHR) { /* rest-of-line comment */
- while ((ch = getc(fp)) != '\n')
- if (ch == EOF)
- return;
- lineno++;
- } else { /* this style of comment (slash-star star-slash) */
- do {
- if (skip_to_chr(fp, ch, '*') == EOF) {
- fprintf(stderr,
- "%s: can't find end of comment, from line %d in %s\n",
- progname, startno, cfile);
- exit(1);
- }
- while ((ch = getc(fp)) == '*')
- ;
- } while (ch != '/');
- }
- }
-
- /*
- * local BOOL
- * print_tag(fn_name, followch, lno)
- *
- * Process the predicate name, removing initial quotes if necessary.
- * Quotes must be retained in the search string.
- *
- */
-
- local BOOL
- print_tag(fn_name, followch, lno)
- char *fn_name; /* predicate name */
- char followch; /* char immediately after it */
- int lno; /* current line number */
- {
- extern SYMBOL *install();
- extern char *progname; /* program name */
- extern char *cfile; /* current source filename */
- extern FILE *tags; /* pointer to tags file */
- extern BOOL lines; /* TRUE if line numbers are requested */
- extern BOOL warnings; /* warn about multiple defs? */
- REG SYMBOL *sym; /* symbol table entry */
- REG char *p;
-
- /* skip initial quote if necessary */
- p = (*fn_name == '\'') ? fn_name+1 : fn_name;
-
- if ((sym = lookup(p)) == NOSYM) {
- #if DEBUG
- VOID printf("process_head: installing %s\n", s);
- #endif
- if (install(p, cfile) == NOSYM)
- return FALSE;
- } else if (warnings && sym->file != cfile) {
- VOID fprintf(stderr,
- "%s: warning - '%s' is defined in more than one file\n",
- progname, p);
- sym->file = cfile; /* no more warnings for this file */
- } else /* already recorded for this file */
- return TRUE;
-
- if (lines == TRUE) /* use line numbers */
- VOID fprintf(tags, "%s\t%s\t%d\n", p, cfile, lno);
- else { /* use search string */
- VOID fprintf(tags, "%s\t%s\t", p, cfile);
- VOID print_search(tags, fn_name, followch);
- }
-
- return TRUE;
- }
-
- /*
- * local void
- * print_search(fp, s, c)
- *
- * Construct a vi/ex regular expression as a search string, escaping
- * special characters if necessary.
- *
- */
-
- local void
- print_search(fp, s, c)
- FILE *fp;
- REG char *s; /* string to search for */
- char c; /* trailing context character */
- {
- /* The definition is assumed to start on a line of its own
- * flush with the left margin.
- */
- VOID fprintf(fp, "/^");
- for ( ; *s != EOSTR; s++)
- PRINTC(*s, fp);
- /* Can't put these in search string */
- if (c != '\n' && c != '\r' && c != '\f')
- PRINTC(c, fp); /* print char following name */
- VOID fprintf(fp, "/\n");
- }
-
- /*
- * local int
- * skip_to_chr(fp, ch, match)
- *
- * Skips input up to match character. Leaves ch at match.
- * Returns match or EOF on end-of-file.
- *
- */
-
- local int
- skip_to_chr(fp, ch, match)
- FILE *fp; /* pointer to current input file */
- int ch; /* current character */
- char match; /* character to match */
- {
- extern int lineno;
- extern char *progname; /* program name */
- extern char *cfile; /* current input filename */
-
- while (ch != match) {
- if (ch == '\n')
- lineno++;
- else if (ch == EOF) {
- fprintf(stderr, "%s: character (%c) not matched in %s\n",
- progname, match, cfile);
- return EOF;
- }
- ch = getc(fp);
- }
- return ch;
- }
- @//E*O*F process.c//
- chmod u=rw,g=rw,o=r process.c
-
- echo x - symbol.c
- sed 's/^@//' > "symbol.c" <<'@//E*O*F symbol.c//'
- #include <stdio.h>
- #include "ptags.h"
-
- /*
- * ptags - creates entries in a tags file for Prolog predicates
- *
- * Usage: ptags [-w] [-l] [-a] [-p] file1 ... filen
- *
- * This program code may be freely distributed provided
- *
- * a) it, or any part of it, is not sold for profit; and
- *
- * b) this entire comment remains intact.
- *
- * Copyright (c) 1988, Chris Tweed & Bob Kemp, EdCAAD,
- * University of Edinburgh
- *
- * Please mail us any changes, enhancements, or bug fixes.
- *
- * Chris Tweed
- * chris@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!chris
- *
- * or
- *
- * Bob Kemp
- * bob@caad.ed.ac.uk
- * ...!mcvax!ukc!edcaad!bob
- *
- */
-
- extern BOOL warnings;
- local int nsym = 0;
- local SYMBOL symbol[MAXSYM];
-
- /*
- * global SYMBOL *
- * install(name, file)
- *
- * Installs a symbol in the symbol table. NOTE: it doesn't check
- * if the symbol has already been entered.
- *
- */
-
- global SYMBOL *
- install(name, file)
- char *name; /* predicate name */
- char *file; /* name of file where pred is defined */
- {
- extern SYMBOL *new_sym();
- extern char *strcpy();
- SYMBOL *sym;
-
- if ((sym = new_sym()) == NOSYM)
- return NOSYM;
- VOID strcpy(sym->name, name);
- sym->file = file;
-
- return sym;
- }
-
- /*
- * local SYMBOL *
- * new_sym()
- *
- * Returns a pointer to a new symbol, or NOSYM (NULL) if no
- * space is available.
- *
- */
-
- local SYMBOL *
- new_sym()
- {
- extern char *progname;
-
- if (nsym < MAXSYM)
- return &symbol[nsym++];
- else {
- fprintf(stderr, "%s: too many symbols\n", progname);
- return NOSYM;
- }
- }
-
- /*
- * global SYMBOL *
- * lookup(name)
- *
- * Returns pointer to symbol if it is in the symbol table; otherwise
- * it returns NOSYM (NULL).
- *
- */
-
- global SYMBOL *
- lookup(name)
- REG char *name;
- {
- extern int nsym;
- REG int i;
-
- for (i = 0; i < nsym; i++)
- if (STREQ(name, symbol[i].name))
- return &symbol[i];
-
- return NOSYM;
- }
- @//E*O*F symbol.c//
- chmod u=rw,g=rw,o=r symbol.c
-
- echo x - tags
- sed 's/^@//' > "tags" <<'@//E*O*F tags//'
- BEGIN_NAME config.h /^#define BEGIN_NAME(c) (islower(c) || c == '\\'' || /
- IN_NAME config.h /^#define IN_NAME(c) (isalnum(c) || c == '_' || c ==/
- IS_SYM config.h /^#define IS_SYM(c) (INDEX(SYM_CHRS, c) != NULL)$/
- Mmain main.c /^main(argc, argv)$/
- PRINTC process.c /^#define PRINTC(ch, fp) if (INDEX(ESC_CHRS, ch) != /
- STREQ ptags.h /^#define STREQ(s1, s2) (strcmp((s1), (s2))==0) \/* /
- USE main.c /^#define USE(mesg) VOID fprintf(stderr, mesg)$/
- install symbol.c /^install(name, file)$/
- lookup symbol.c /^lookup(name)$/
- new_sym symbol.c /^new_sym()$/
- print_search process.c /^print_search(fp, s, c)$/
- print_tag process.c /^print_tag(fn_name, followch, lno)$/
- process_file process.c /^process_file(fp)$/
- skip_comment process.c /^skip_comment(ch, fp)$/
- skip_to_chr process.c /^skip_to_chr(fp, ch, match)$/
- usage main.c /^usage(s)$/
- @//E*O*F tags//
- chmod u=rw,g=rw,o=r tags
-
- echo mkdir - TestFiles
- mkdir TestFiles
- chmod u=rwx,g=rwx,o=rx TestFiles
-
- echo x - TestFiles/comments.pl
- sed 's/^@//' > "TestFiles/comments.pl" <<'@//E*O*F TestFiles/comments.pl//'
- :- b, c, d.
-
- a.
-
- /* hello .
- x.
- */
-
- /**
- m.
- **/
-
- /***
- n.
- **/
-
- b(x,
- y) :-
- c(x),
- d(y,z).
-
- c
- (x, a) :-
- zxc(a).
-
- d :- true. % hi!
-
- e% .
- zzz.
-
- f/* . */ x .
-
- @//E*O*F TestFiles/comments.pl//
- chmod u=rw,g=rw,o=r TestFiles/comments.pl
-
- echo x - TestFiles/crazy.pl
- sed 's/^@//' > "TestFiles/crazy.pl" <<'@//E*O*F TestFiles/crazy.pl//'
- /* crazy program layout */
-
- c(A, B)
- :-
- a(A),
-
-
-
-
- b(B).
-
- d(a(_),D) :-
- b(D).
- @//E*O*F TestFiles/crazy.pl//
- chmod u=rw,g=rw,o=r TestFiles/crazy.pl
-
- echo x - TestFiles/difficult.pl
- sed 's/^@//' > "TestFiles/difficult.pl" <<'@//E*O*F TestFiles/difficult.pl//'
- :- b, c, d.
-
- a.
-
- /* hello .
- x.
- */
-
- :- op(500, xfx, '.').
-
- b(n.n,
- y) :-
- c(x),
- d(y,z).
-
- c(
- x, a) :-
- zxc(a).
-
- 'a b c'(A,1.2) :-
- a(A),
- b(B).
-
- d("a dot. followed by white space", "", "and a quote in a string""") :-
- it_works(ok).
-
- e :- true. % hi!
-
- :- op(300, fx, f).
- /* below should be interpretable as 'f yyy.' */
- f% .
- yyy.
-
- 'z & () . zz'.
-
- :- op(300, fx, g).
- g/* . */ x .
-
- h(a).
-
- /* symbolic atoms as predicate names */
-
- ++(X).
- +.+(X).
- &+`(X).
- @~*\/#?```=(X).
-
- /* some really tricky ones ;-) */
- x/*******/y(X).
- */**/*(X).
- /*******/y(X).
- /**/*(X).
- x/***//****/y(X).
- @//E*O*F TestFiles/difficult.pl//
- chmod u=rw,g=rw,o=r TestFiles/difficult.pl
-
- echo x - TestFiles/morecomments.pl
- sed 's/^@//' > "TestFiles/morecomments.pl" <<'@//E*O*F TestFiles/morecomments.pl//'
- a(b) :- true.
- /**/
- c(b) :- true.
- d(b).
- @//E*O*F TestFiles/morecomments.pl//
- chmod u=rw,g=rw,o=r TestFiles/morecomments.pl
-
- echo x - TestFiles/tags
- sed 's/^@//' > "TestFiles/tags" <<'@//E*O*F TestFiles/tags//'
- &+` difficult.pl /^\&+`(/
- * difficult.pl /^\*(/
- ** difficult.pl /^\*\*(/
- ++ difficult.pl /^++(/
- +.+ difficult.pl /^+\.+(/
- a difficult.pl /^a\./
- a b c difficult.pl /^'a b c'/
- b difficult.pl /^b(/
- c difficult.pl /^c(/
- d difficult.pl /^d(/
- e difficult.pl /^e /
- f difficult.pl /^f\%/
- g difficult.pl /^g /
- h difficult.pl /^h(/
- xy difficult.pl /^xy(/
- y difficult.pl /^y(/
- z & () . zz difficult.pl /^'z \& () \. zz'/
- @~*\/#?```= difficult.pl /^~\*\\\/#?```=(/
- @//E*O*F TestFiles/tags//
- chmod u=rw,g=rw,o=r TestFiles/tags
-
- echo x - TestFiles/tricky.pl
- sed 's/^@//' > "TestFiles/tricky.pl" <<'@//E*O*F TestFiles/tricky.pl//'
- x/*******/y(X).
- */**/*(X).
- /*******/y(X).
- /**/*(X).
- x/***//****/y(X).
- @//E*O*F TestFiles/tricky.pl//
- chmod u=rw,g=rw,o=r TestFiles/tricky.pl
-
- echo Inspecting for damage in transit...
- temp=/tmp/shar$$; dtemp=/tmp/.shar$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 22 128 788 READ_ME
- 104 533 3067 ptags.L
- 38 83 677 Makefile
- 61 182 1128 ptags.h
- 68 325 1908 config.h
- 174 590 3995 main.c
- 374 1484 8989 process.c
- 105 309 1843 symbol.c
- 16 96 831 tags
- 32 39 155 comments.pl
- 13 13 82 crazy.pl
- 53 104 576 difficult.pl
- 4 8 39 morecomments.pl
- 18 68 452 tags
- 5 5 70 tricky.pl
- 1087 3967 24600 total
- !!!
- wc READ_ME ptags.L Makefile ptags.h config.h main.c process.c symbol.c tags TestFiles/comments.pl TestFiles/crazy.pl TestFiles/difficult.pl TestFiles/morecomments.pl TestFiles/tags TestFiles/tricky.pl | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if [ -s $dtemp ]
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-
-
- --
- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
-