rc-list - mailing list for the rc(1) shell
 help / color / mirror / Atom feed
From: netapp!byron@netcom.com (Byron Rakitzis)
To: rc@hawkwind.utcs.toronto.edu
Subject: a small diversion
Date: Tue, 11 May 1993 19:48:38 -0400	[thread overview]
Message-ID: <9305112348.AA07423@ghoti.netapp.com> (raw)

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 <files> <expr>' >[1=2]
-	exit 1
-}
-files=()
-while (! ~ $#* 1) {
-	files = ($1 $files)
-	shift
-}
-find $files `{echo $1 | prefind}
end of f

It is used as:

	f <files> <expr>

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 <s> find expr or and not un clist
-%type <s> 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 <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-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


                 reply	other threads:[~1993-05-11 23:48 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9305112348.AA07423@ghoti.netapp.com \
    --to=netapp!byron@netcom.com \
    --cc=rc@hawkwind.utcs.toronto.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).