/* ident copyright (c) 1985, Gimpel Software James F. Gimpel, President 3207 Hogarth Lane Collegeville, PA 19426 (215) 584-4261 Specializing in compilers, interpreters, and translators for the IBM PC and Unix worlds. This product has been released to public domain for non-profit use only. The purpose of this program is to display or replace a given identifier in a file. It will skip over any identifier in which the given identifier is embedded. Thus if the given identifier is "i" then the identifiers "hi" and "in" will be passed over. identifiers follow the rules of C but other than this the program knows nothing about C syntax. In particular, it knows nothing about comments or quotes. To find out how to use ident invoke it at command level with no arguments. JFG 11/11/84 */ #include "stdio.h" typedef char *STRING; #define BUFLEN 100 #define id_begin(c) (isalpha(c) || c == '_') #define id_cont(c) (isalnum(c) || c == '_') #define copyc(c) if(copy_flag) putc(c,stdout) extern STRING fgets(); int copy_flag; main(argc,argv) int argc; STRING *argv; { int i, j, n; int c; FILE *f; char buf[BUFLEN], newbuf[BUFLEN]; char first; STRING pat, pattern, replacement, p, rest; int match, rest_len; int lineno = 0; if( argc < 3 ) { help(); } f = fopen( argv[1], "r" ); if( !f ) error( "Can't open input file" ); pattern = argv[2]; first = pattern[0]; rest = pattern+1; rest_len = strlen(rest); copy_flag = argc > 3; replacement = copy_flag ? argv[3] : ""; while( fgets(buf, BUFLEN, f ) ) { lineno++; p = buf; match = 0; while( c = *p++ ) { if( c == first && strinb( rest, p ) && !id_cont( p[rest_len] ) && !after_id( p-1, buf ) ) { match = 1; copys( replacement ); p += rest_len ; } else copyc(c); } if( match && !copy_flag ) printf( "%d\t%s", lineno, buf ); } } /* copys(s) copies string s to stnd out (conditionally) */ copys(s) STRING s; { copyns( s, strlen(s) ); } /* copyns(s) copies n characters from string s to stnd out (conditionally). */ copyns(s,n) STRING s; int n; { while( n-- > 0 ) copyc(*s++); } /* error(s) writes an error message to standard error and quits (could have used abort instead). */ error(s) STRING s; { fprintf( stderr, "ident: %s\n", s ); exit(); } /* strinb( s, buf ) returns true (1) if string s lies in buffer buf */ strinb(s,buf) STRING s, buf; { while( *s ) if( *s++ != *buf++ ) return 0; return 1; } /* after_id( p, buf ) will return true (1) if an identifier precedes pointer p. buf is the beginning of the buffer into which p points. */ after_id( p, buf ) STRING p, buf; { char c; while( p > buf ) { c = *--p; if( id_begin(c) ) return 1; if( !id_cont(c) ) return 0; } return 0; } help() { p( "Format:" ); p( "" ); p( "ident file-name identifier [replacement]" ); p( "" ); p( "will search the file for the occurrence of the identifier" ); p( "given as argument. If a replacement is provided it will" ); p( "output the file onto standard out with all instances of the" ); p( "identifier replaced by the replacement. If the replacement" ); p( "is not given, all lines bearing the identifier are printed" ); p( "to standard out together with the line numbers." ); p( "The significance of this program is that only identifiers" ); p( "will be matched. Thus, if 'a' is given 'abc' or 'dada' " ); p( "will not match." ); exit(); } p(s) STRING s; { fprintf( stderr, "\t%s\n" , s); }