[comp.unix.shell] ash internals: evalstring

dfenyes@thesis1.med.uth.tmc.edu (David Fenyes) (03/26/91)

Ash is certainly an undersold shell;  for its power and flexibility,
it's remarkably small.  I was able to port ash to Coherent, a v7
variant, with little difficulty, and because Coherent won't run atty,
I added a command line editor & history.  I want to be able to expand
variables in PS1, and also execute the contents of the variable EVERY
befor each prompt.  To do this, I call the function evalstring in eval.c.
This works perfectly for valid expressions, but if there is a syntax error,
the shell goes into an infinite loop, reporting the error endlessly.

When the pre-existing code calls evalstring (for example, with the contents
of SHINIT at startup) an error is reported once and evaluation is terminated
properly.  I have studied these invokations and can't find the difference.

Is there anyone out there familiar with the internals of ash that can offer
some insight?.

Also, did anyone notice that a () (empty subshell) at the command line
gives funny results (on my system it caused a reset).  I avoided this
by returning a syntax error on an empty subshell. (Obviously a kludge).

Thanks a lot-- BTW, if anyone wants to alpha test this adaptation of ash,
please contact me.  If you currently use ash and don't have atty, or use
sh and wish you had ksh, this may be an improvement.  Personally, I think
ash is every bit as powerful and not as huge as ksh.

David.
--
David Fenyes                                  dfenyes@thesis1.hsch.utexas.edu
University of Texas Medical School            Houston, Texas

alex@am.sublink.org (Alex Martelli) (03/27/91)

dfenyes@thesis1.med.uth.tmc.edu (David Fenyes) writes:
:Ash is certainly an undersold shell;  for its power and flexibility,
I fully agree...

:I added a command line editor & history.  I want to be able to expand
:variables in PS1, and also execute the contents of the variable EVERY
:befor each prompt.  To do this, I call the function evalstring in eval.c.
:This works perfectly for valid expressions, but if there is a syntax error,
:the shell goes into an infinite loop, reporting the error endlessly.

Here's the relevant portion from mash, my own ash dialect:

		handler = &jmploc;
		TRACE(("putprompt(%s)\n", prompter));
		if (setjmp(jmploc.loc)) {
			TRACE(("putprompt error recovery\n"));
			popstackmark(&smark);
			popfile();
			p = 0;
		} else {
			setstackmark(&smark);
			evalstring(prompter);
			popstackmark(&smark);
			p = lookupvar("__P");
		}

where "prompter" is a string I build up by catting __P=" in front of
lookupvar("PS1"), and " after that.
BTW, as a reminder for others, ash and atty are available in volume 19
of comp.sources.unix, and are very interesting to study as a possibly
optimal design point in the complexity/function tradeoff for shells.
Just a pity that atty ain't easy to integrate into most Unices... so
we all build history and line editing into each of our shells and
interactive programs... hafta look into shared libraries one day...:-)
-- 
Alex Martelli - (home snailmail:) v. Barontini 27, 40138 Bologna, ITALIA
Email: (work:) martelli@cadlab.sublink.org, (home:) alex@am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; 
Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).

dfenyes@thesis1.med.uth.tmc.edu (David Fenyes) (03/31/91)

In article <1991Mar26.212622.757@am.sublink.org> alex@am.sublink.org (Alex Martelli) writes:

>Here's the relevant portion from mash, my own ash dialect:
>
>		handler = &jmploc;
>		TRACE(("putprompt(%s)\n", prompter));
>		if (setjmp(jmploc.loc)) {
>			TRACE(("putprompt error recovery\n"));
>			popstackmark(&smark);
>			popfile();
>			p = 0;
>		} else {
>			setstackmark(&smark);
>			evalstring(prompter);
>			popstackmark(&smark);
>			p = lookupvar("__P");
>		}
>
>where "prompter" is a string I build up by catting __P=" in front of
>lookupvar("PS1"), and " after that.

My solution was very similar looking-- I call a function cheapexpand()
from putprompt in parser.c, which epands the ~/, then calls expandstr,
which cats up a similar string & calls evalstring in eval.c.

The problem I had was, of course, that syntax errors invoked error(),
which did a longjmp back to the main loop, which tried to parse the
offending string again.  Judicious local use of setjmp, INTON, and INTOFF
fixed the problem.

For those of us who use ash, it may be useful to pool information,
such as bug fixes, etc.  2 bugs I found are a bomb on an empty subshell
(), avoided by making an empty subshell a syntax error (I know it's a
kludge), and improper shell exiting from scripts in the -I mode, fixed
by including a `!top ||' in the test for exit on an EOF.

Bye,
--
David Fenyes                                 dfenyes@thesis1.hsch.utexas.edu
University of Texas Medical School           Houston, Texas

peter@ficc.ferranti.com (Peter da Silva) (04/03/91)

I was trying to use ash for real work, but had to abandon it because it
was quoting strings in places where the bourne shell left them unquoted
and scripts kept breaking. Is this fixed in a recent version?
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

alex@am.sublink.org (Alex Martelli) (04/04/91)

peter@ficc.ferranti.com (Peter da Silva) writes:
:I was trying to use ash for real work, but had to abandon it because it
:was quoting strings in places where the bourne shell left them unquoted
:and scripts kept breaking. Is this fixed in a recent version?

I don't know of any "recent version" - I hacked my changes right on
top of the version from comp.sources.unix volume 19.  Could you please
clarify what you mean by 'quoting strings'?  I'm not sure I understand
what you mean.  I have used mash (My ash) mostly for interactive work,
although it should indeed be faster than most sh's, what with the
builtin test+expr - but the latter should also guarantee a lack of
complete compatibility, so...

-- 
Alex Martelli - (home snailmail:) v. Barontini 27, 40138 Bologna, ITALIA
Email: (work:) martelli@cadlab.sublink.org, (home:) alex@am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; 
Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).