From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from netcomsv.netcom.com ([163.179.1.13]) by hawkwind.utcs.toronto.edu with SMTP id <2811>; Tue, 11 May 1993 19:48:42 -0400 Received: from netapp.UUCP by netcomsv.netcom.com with UUCP (4.1/SMI-4.1) id AA14125; Tue, 11 May 93 16:48:45 PDT Received: from ghoti.netapp.com by netapp.netapp.com (4.1/SMI-4.1) id AA06236; Tue, 11 May 93 16:48:45 PDT Received: by ghoti.netapp.com (4.1/SMI-4.1) id AA07423; Tue, 11 May 93 16:48:38 PDT Date: Tue, 11 May 1993 19:48:38 -0400 From: netapp!byron@netcom.com (Byron Rakitzis) Message-Id: <9305112348.AA07423@ghoti.netapp.com> To: rc@hawkwind.utcs.toronto.edu Subject: a small diversion Hi, I am just posting a small piece of code for your amusement. I've always been sick of /bin/find's syntax, so about a year ago I wrote a little toy program to explore an alternative user interface. I have a small yacc program which takes a C-like expression syntax on stdin and produces find-compatible syntax on stdout. Doubtless it is incomplete, which is why I call it a toy. I also have an rc script which interfaces my preprocessor to /bin/find itself. Here are some examples of find pre-processor input and output: (type(d)||type(f))&&print becomes ( -type d -o -type f ) -a -print and name(*.o)&&exec(rm {}) becomes -name *.o -a -exec rm {} As I see it, the main advantages of my approach are: 1) You don't need to split up the find expression so that one token == one argv[] element. e.g., I find '(foo||bar)&&print' much easier to type than '(' foo -o bar ')' -a -print 2) I find that /bin/find syntax is write-only, whereas it's easier for me to parse visually what's going on, even with the above two simple expressions. Well, that's enough for now. I mostly just want to amuse, as well as provoke thought. This is not a "production" solution. Here's the script I use as a replacement to find, which I call "f": # to unbundle, sh this file # bundled by byron on ghoti at Tue May 11 16:43:31 PDT 1993 # contents of bundle: # f echo f sed 's/^-//' > f <<'end of f' -#!/bin/rc -if (~ $#* 0 1) { - echo 'usage: f ' >[1=2] - exit 1 -} -files=() -while (! ~ $#* 1) { - files = ($1 $files) - shift -} -find $files `{echo $1 | prefind} end of f It is used as: f where expr is a *single* argument, usually surrounded in quotes. For example: f . 'type(d)&&print' The yacc source follows. Run through yacc, and compile it into "prefind". Byron. # to unbundle, sh this file # bundled by byron on ghoti at Tue May 11 16:44:00 PDT 1993 # contents of bundle: # find.y echo find.y sed 's/^-//' > find.y <<'end of find.y' -%term ORELSE ANDALSO CMD - -%{ -static int yylex(void); -static char *sprint(const char *fmt,...); -static void *ealloc(unsigned n); -static void *erealloc(void *p, unsigned n); -#define WORDSIZE 8 -#define CHECKSIZE() if (i >= size) buf = erealloc(buf, size *= 2) -%} - -%union { - char *s; -} - -%type find expr or and not un clist -%type CMD - -%% - -find : expr { printf("%s\n", $1); } - -expr : or - -or : and - | or ORELSE and { $$ = sprint("% -o %", $1, $3); } - -and : not - | and ANDALSO not { $$ = sprint("% -a %", $1, $3); } - -not : '!' un { $$ = sprint("! %", $2); } - | un - -un : '(' expr ')' { $$ = sprint("( % )", $2); } - | CMD { $$ = sprint("-%", $1); } - | CMD '(' clist ')' { $$ = sprint("-% %", $1, $3); } - -clist : CMD - | clist CMD { $$ = sprint("% %", $1, $2); } - -%% - -#include -#include -#include - -static int yylex() { - char *buf; - int c; - unsigned i, size; - -top: switch (c = getchar()) { - case ' ': case '\t': case '\n': - goto top; - case EOF: case '\0': - case '!': case ',': - case '(': case ')': - return c; - case '&': - if ((c = getchar()) == '&') - return ANDALSO; - return '?'; - case '|': - if ((c = getchar()) == '|') - return ORELSE; - return '?'; - default: - buf = ealloc(size = WORDSIZE); - i = 0; - while (1) { - buf[i++] = c; - CHECKSIZE(); - switch (c = getchar()) { - default: - break; - case EOF: case '\0': - case ' ': case '\t': case '\n': - case '(': case ')': case ',': - case '!': case '&': case '|': - ungetc(c, stdin); - buf[i] = '\0'; - yylval.s = buf; - return CMD; - } - } - } -} - -static char *sprint(const char *fmt,...) { - va_list ap; - unsigned size, i = 0; - char *buf = ealloc(size = WORDSIZE); - - va_start(ap, fmt); - - while (*fmt != '\0') { - if (*fmt != '%') { - buf[i++] = *fmt++; - CHECKSIZE(); - } else { - char *word = va_arg(ap, char *); - while (*word != '\0') { - buf[i++] = *word++; - CHECKSIZE(); - } - fmt++; - } - } - - va_end(ap); - - buf[i] = '\0'; - return buf; -} - -static void *ealloc(unsigned n) { - void *p = malloc(n); - if (p == NULL) { - perror("malloc"); - exit(1); - } - return p; -} - -static void *erealloc(void *p, unsigned n) { - p = realloc(p, n); - if (p == NULL) { - perror("realloc"); - exit(1); - } - return p; -} - -static void yyerror(char *s) { - fprintf(stderr, "%s\n", s); - exit(1); -} - -extern int main() { - yyparse(); - return 0; -} end of find.y