tcl-websh-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dav...@dedasys.com (David N. Welton)
Subject Re: putx {= bug
Date Thu, 27 Dec 2001 10:44:21 GMT
Ronnie Brunner <ronnie@netcetera.ch> writes:

> To be honest, I don't know how that got into the code. Imho: just
> thrw it out. It looks as if it was just a short cu way to "web::put"
> stuff in a template, but I don't see the necessitiy. Sure you would
> need to type less, but it adds a completely new syntax not used
> anywhere else.

Ok.  Without it, I *think* I can get a generic parser to work for both
<?, ?>, and whatever else we want to add, either as a config option,
or at compile time.  I'm still experimenting, but what I'm working on
goes something like this:

int webout_eval_tag(Tcl_Interp * interp, ResponseObj * responseObj,
		    Tcl_Obj * in, const char *strstart, const char *strend)
{
    Tcl_DString dstr;
    Tcl_DString convdstr;
    Tcl_Obj *tclo = NULL;

    int inLen;
    char *cur = NULL;
    char *prev = NULL;
    int cntOpen = 0;
    int res = 0;
    int startmatch = 0;
    int endmatch = 0;

/*     const char *strstart = START_TAG;
    const char *strend = END_TAG;  */
/*     int endseqlen = strlen(END_TAG);
    int startseqlen = strlen(START_TAG);
  */
    int endseqlen = strlen(strstart);
    int startseqlen = strlen(strend);

    if ((responseObj == NULL) || (in == NULL))
	return TCL_ERROR;

    Tcl_DStringInit(&dstr);

    cur = Tcl_GetStringFromObj(in, &inLen);
    prev = cur;

    if (inLen == 0)
	return TCL_OK;

    while (*cur != 0) {
	if (*cur == strstart[startmatch])
	{
	    if (*prev == '\\') {
		Tcl_DStringAppend(&dstr, cur, 1);		
	    } else if ((++startmatch) == startseqlen) {
		/* We have matched the starting sequence. */
		if (cntOpen < 1) {
		    Tcl_DStringAppend(&dstr, "\"\n", 2);
		} else {
		    Tcl_DStringAppend(&dstr, strstart, -1);
		}
		cntOpen ++;
		startmatch = 0;
	    }
	    prev = cur;
	    cur ++;
	    continue;
	} else if (*cur == strend[endmatch]) {
	    if (*prev == '\\') {
		Tcl_DStringAppend(&dstr, cur, 1);		
	    } else if ((++endmatch) == endseqlen)
	    {
		/* We have matched the ending sequence. */
		if (cntOpen == 1) 
		    Tcl_DStringAppend(&dstr, "\n web::put \"", -1);
		else 
		    Tcl_DStringAppend(&dstr, strend, -1);
		cntOpen --;
		endmatch = 0;
	    }
	    prev = cur;
	    cur ++;
	    continue;
	} else if (startmatch) {
	    Tcl_DStringAppend(&dstr, (char *)strstart, startmatch);
	    startmatch = 0;
	} else if (endmatch) {
	    Tcl_DStringAppend(&dstr, (char *)strend, endmatch);
	    endmatch = 0;
	}
	/* Put the current character in the output.  If we are in Tcl
	       code, then don't escape Tcl characters. */
	if (cntOpen < 1) {
	    switch (*cur)
	    {
	    case '{':
		Tcl_DStringAppend(&dstr, "\\{", -1);
		break;
	    case '}':
		Tcl_DStringAppend(&dstr, "\\}", -1);
		break;
	    case '$':
		Tcl_DStringAppend(&dstr, "\\$", -1);
		break;
	    case '[':
		Tcl_DStringAppend(&dstr, "\\[", -1);
		break;
	    case ']':
		Tcl_DStringAppend(&dstr, "\\]", -1);
		break;
	    case '"':
		Tcl_DStringAppend(&dstr, "\\\"", -1);
		break;
/* 	    case '\\':
		Tcl_DStringAppend(&dstr, "\\\\", -1);
		break;  */
	    default:
		Tcl_DStringAppend(&dstr, cur, 1);
		break;
	    }
	} else {
	    Tcl_DStringAppend(&dstr, cur, 1);
	}
	prev = cur;	
	cur ++;
	continue;
    }

    Tcl_ExternalToUtfDString(NULL,
			     Tcl_DStringValue(&dstr),
			     Tcl_DStringLength(&dstr),
			     &convdstr);

    tclo = Tcl_NewStringObj("web::put \"", -1);

    Tcl_AppendToObj(tclo, Tcl_DStringValue(&convdstr),
		    Tcl_DStringLength(&convdstr));

    if (cntOpen < 1) {
	Tcl_AppendToObj(tclo, "\"\n", 2);
    }

    fprintf(stderr, "'%s'\n", Tcl_GetString(tclo));
    return Tcl_EvalObjEx(interp, tclo, TCL_EVAL_DIRECT);
}

I'm not totally sure about the i18n aspects of it.  For example, you
guys use the Tcl_UtfNext and do things that way.  Maybe that's more
efficient/correct than doing the whole thing and then converting it.

There are also some issues with backslashes and whether to pass them
literally (so they don't escape the next character), but in general, I
think this can be made to work.  It's a very heavily redone version of
what I have in Rivet (but I think I will port it to Rivet even if we
don't use it here, as I think it's more compact than what I have now.

-- 
David N. Welton
   Consulting: http://www.dedasys.com/
Free Software: http://people.debian.org/~davidw/
   Apache Tcl: http://tcl.apache.org/
     Personal: http://www.efn.org/~davidw/

Mime
View raw message