From: Ethan M. <merritt@u.washington.edu> - 2004-07-20 17:47:01
|
On Tuesday 20 July 2004 01:53 am, Hans-Bernhard Broeker wrote: > > (3) It adds a check for this string-valued function in exactly two > > places where a function name was not previously accepted by > > the parser. > > I think what I'm getting at that this check had better go into isstring() > instead --- the function that every command parser fragment is supposed to > be using to check whether the upcoming command line token is a string or > not. That turns out not to help. Consider a typical call site, one of the 98 you counted: set.c (set_fontpath) line 1801: if (isstring(c_token)) { int len; char *ss = gp_alloc(token_len(c_token), "tmp storage"); len = (collect? strlen(collect) : 0); quote_str(ss,c_token,token_len(c_token)); collect = gp_realloc(collect, len+1+strlen(ss)+1, "tmp fontpath"); if (len != 0) { strcpy(collect+len+1,ss); *(collect+len) = PATHSEP; } else strcpy(collect,ss); free(ss); ++c_token; } I am not clever enough to re-write isstring() and quote_str() such that the code at this call site works when the length of the string changes mid-stream. So trying to be clever in isstring() and quote_str() paradoxically makes *more* work, since every call site would have to be inspected and re-written for compatibility. If the program were being re-written from scratch, then yes. But in the interest of sanity and not introducing 98 possible new bug sites, I would rather go for a solution that leaves the input code intact and focuses instead on identifying a small number of places where the string is actually used for something. case 1: the string is printed. I dealt with this by adding code to write_multiline(). case 2: the string is used as a file name. I haven't handled this yet, but I propose to create a new routine gp_fopen() which contains the same check for magic characters at the start of a string that I inserted into write_multiline(). Yes, this requires changing call sites from fd = fopen("...") to fd = gp_fopen("...") but this would be a piece of cake compared to rethinking and rewriting 98 sites like the one above . case 3: Are there any more end-uses for a string? > Ah, thanks, now this is a whole lot clearer than before. So this patch is > what I've been referring to as late evaluation, i.e. the technique of > storing an expression, rather than its result, to be evaluated at the > latest possible time. I'm still not confinced that 'sprintf( is a > suitable choice of trigger string, but now at least I understand what > you're doing. I am not trying to convince anyone that "sprintf" is the best choice. The only virtue it has is that we can refer people to "man sprintf" for help with the format specifiers. I would rather have either an alternate quote character (something different from ' or ") or a single magic character following a normal quote character. set title %<expression>% or set title "!<expression>" Unfortunately the '!' character is a unary operator already, as are '+' and '^' and many of the other obvious candidates. So sticking it in front of a general expression is at best a bit confusing, and at worst ambiguous to parse. I hesitate to suggest '$', but at least it is not a unary operator. The other alternative is a pseudo-function such as set title %(<expression>) but that leads us right back to the problem of those 98 call sites that are expecting a quote character. Please note that this doesn't get away from having to type "sprintf" if that is in fact the function you want to evaluate. So even with a single-%-character quoting convention, the full form would be set title %sprintf("<format>",var1,var2)% but if we allow other string-valued functions, then any one of them might replace "sprintf" in this example. Hypothetically it would look like set title %myfunc(par1,par2)% -- Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |