1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix enum type definition pre-parsing for shcomp and dot/source

Parser limitations prevent shcomp or source from handling enum
types correctly:

    $ cat /tmp/colors.sh
    enum Color_t=(red green blue orange yellow)
    Color_t -A Colors=([foo]=red)

    $ shcomp /tmp/colors.sh > /dev/null
    /tmp/colors.sh: syntax error at line 2: `(' unexpected
    $ source /tmp/colors.sh
    /bin/ksh: source: syntax error: `(' unexpected

Yet, for types created using 'typeset -T', this works. This is done
via a check_typedef() function that preliminarily adds the special
declaration builtin at parse time, with details to be filled in
later at execution time.

This hack will produce ugly undefined behaviour if the definition
command creating that type built-in is then not actually run at
execution time before the type built-in is accessed.

But the hack is necessary because we're dealing with a fundamental
design flaw in the ksh language. Dynamically addable built-ins that
change the syntactic parsing of the shell language on the fly are
an absurdity that violates the separation between parsing and
execution, which muddies the waters and creates the need for some
kind of ugly hack to keep things like shcomp more or less working.

This commit extends that hack to support enum.

src/cmd/ksh93/sh/parse.c:
- check_typedef():
  - Add 'intypeset' parameter that should be set to 1 for typeset
    and friends, 2 for enum.
  - When processing enum arguments, use AST getopt(3) to skip over
    enum's options to find the name of the type to be defined.
    (getopt failed if we were running a -c script; deal with this
    by zeroing opt_info.index first.)
- item(): Update check_typedef() call, passing lexp->intypeset.
- simple(): Set lexp->intypeset to 2 when processing enum.

The rest of the changes are all to support the above and should be
fairly obvious, except:

src/cmd/ksh93/bltins/enum.c:
- enuminfo(): Return on null pointer, avoiding a crash upon
  executing 'Type_t --man' if Type_t has not been fully defined due
  to the definition being pre-added at parse time but not executed.
  It's all still wrong, but a crash is worse.

Resolves: https://github.com/ksh93/ksh/issues/256
This commit is contained in:
Martijn Dekker 2021-11-21 07:12:27 +01:00
parent 996def3141
commit 8ced1daadf
9 changed files with 67 additions and 17 deletions

View file

@ -21,8 +21,8 @@
#pragma prototyped
#include "defs.h"
static const char enum_usage[] =
"[-?@(#)$Id: enum (AT&T Research) 2008-01-08 $\n]"
const char sh_optenum[] =
"[-?@(#)$Id: enum (ksh 93u+m) 2021-11-21 $\n]"
"[--catalog?" ERROR_CATALOG "]"
"[+NAME?enum - create an enumeration type]"
"[+DESCRIPTION?\benum\b is a declaration command that creates an enumeration "
@ -43,7 +43,7 @@ static const char enum_usage[] =
;
static const char enum_type[] =
"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-01-08 $\n]"
"[-1c?\n@(#)$Id: type (ksh 93u+m) 2021-11-21 $\n]"
"[--catalog?" ERROR_CATALOG "]"
"[+NAME?\f?\f - create an instance of type \b\f?\f\b]"
"[+DESCRIPTION?The \b\f?\f\b declaration command creates a variable for "
@ -98,6 +98,8 @@ static int enuminfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
const char *v;
np = *(Namval_t**)(fp+1);
ep = (struct Enum*)np->nvfun;
if(!ep)
return(0);
if(strcmp(str,"default")==0)
sfprintf(out,"\b%s\b",ep->values[0]);
else if(strcmp(str,"case")==0)
@ -192,7 +194,7 @@ int b_enum(int argc, char** argv, Shbltin_t *context)
cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
for (;;)
{
switch (optget(argv, enum_usage))
switch (optget(argv, sh_optenum))
{
case 'i':
iflag = 'i';