Jim Tcl
Check-in [df0a78320f]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Error on extra characters after close brace

In scripts, like Tcl does.

Signed-off-by: Steve Bennett <steveb@workware.net.au> Reported-by: tcler.yin

Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:df0a78320fd6af41425c3653b66757c12304be5e
User & Date: steveb@workware.net.au 2017-08-02 23:07:17
Context
2017-08-02
23:07
tree: Allow nodes to be deleted

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: 5bc773bac3 user: steveb@workware.net.au tags: trunk

23:07
Error on extra characters after close brace

In scripts, like Tcl does.

Signed-off-by: Steve Bennett <steveb@workware.net.au> Reported-by: tcler.yin check-in: df0a78320f user: steveb@workware.net.au tags: trunk

2017-06-01
23:53
jim-sqlite3: Fix error msg for 'query'

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: 0f3a120f22 user: steveb@workware.net.au tags: trunk

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to jim.c.

3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424







3425
3426
3427
3428
3429
3430
3431
....
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
....
3586
3587
3588
3589
3590
3591
3592




3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
....
3618
3619
3620
3621
3622
3623
3624



3625
3626
3627
3628
3629
3630
3631

/* Counts the number of adjoining non-separator tokens.
 *
 * Returns -ve if the first token is the expansion
 * operator (in which case the count doesn't include
 * that token).
 */
static int JimCountWordTokens(ParseToken *t)
{
    int expand = 1;
    int count = 0;

    /* Is the first word {*} or {expand}? */
    if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
        if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
            /* Create an expand token */
            expand = -1;
            t++;







        }
    }

    /* Now count non-separator words */
    while (!TOKEN_IS_SEP(t->type)) {
        t++;
        count++;
................................................................................
        int wordtokens;

        /* Skip any leading separators */
        while (tokenlist->list[i].type == JIM_TT_SEP) {
            i++;
        }

        wordtokens = JimCountWordTokens(tokenlist->list + i);

        if (wordtokens == 0) {
            /* None, so at end of line */
            if (lineargs) {
                linefirst->type = JIM_TT_LINE;
                linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
                Jim_IncrRefCount(linefirst->objPtr);
................................................................................
 * If 'stateCharPtr' != NULL, the function stores ' ' on complete script,
 * '{' on scripts incomplete missing one or more '}' to be balanced.
 * '[' on scripts incomplete missing one or more ']' to be balanced.
 * '"' on scripts incomplete missing a '"' char.
 * '\\' on scripts with a trailing backslash.
 *
 * If the script is complete, 1 is returned, otherwise 0.




 */
int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateCharPtr)
{
    ScriptObj *script = JimGetScript(interp, scriptObj);
    if (stateCharPtr) {
        *stateCharPtr = script->missing;
    }
    return (script->missing == ' ');
}

/**
 * Sets an appropriate error message for a missing script/expression terminator.
 *
 * Returns JIM_ERR if 'ch' represents an unmatched/missing character.
 *
................................................................................

        case '[':
            msg = "unmatched \"[\"";
            break;
        case '{':
            msg = "missing close-brace";
            break;



        case '"':
        default:
            msg = "missing quote";
            break;
    }

    Jim_SetResultString(interp, msg, -1);







|










>
>
>
>
>
>
>







 







|







 







>
>
>
>







|







 







>
>
>







3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
....
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
....
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
....
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645

/* Counts the number of adjoining non-separator tokens.
 *
 * Returns -ve if the first token is the expansion
 * operator (in which case the count doesn't include
 * that token).
 */
static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t)
{
    int expand = 1;
    int count = 0;

    /* Is the first word {*} or {expand}? */
    if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) {
        if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) {
            /* Create an expand token */
            expand = -1;
            t++;
        }
        else {
            if (script->missing == ' ') {
                /* This is a "extra characters after close-brace" error. Report the first error */
                script->missing = '}';
                script->linenr = t[1].line;
            }
        }
    }

    /* Now count non-separator words */
    while (!TOKEN_IS_SEP(t->type)) {
        t++;
        count++;
................................................................................
        int wordtokens;

        /* Skip any leading separators */
        while (tokenlist->list[i].type == JIM_TT_SEP) {
            i++;
        }

        wordtokens = JimCountWordTokens(script, tokenlist->list + i);

        if (wordtokens == 0) {
            /* None, so at end of line */
            if (lineargs) {
                linefirst->type = JIM_TT_LINE;
                linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr);
                Jim_IncrRefCount(linefirst->objPtr);
................................................................................
 * If 'stateCharPtr' != NULL, the function stores ' ' on complete script,
 * '{' on scripts incomplete missing one or more '}' to be balanced.
 * '[' on scripts incomplete missing one or more ']' to be balanced.
 * '"' on scripts incomplete missing a '"' char.
 * '\\' on scripts with a trailing backslash.
 *
 * If the script is complete, 1 is returned, otherwise 0.
 *
 * If the script has extra characters after a close brace, this still returns 1,
 * but sets *stateCharPtr to '}'
 * Evaluating the script will give the error "extra characters after close-brace".
 */
int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateCharPtr)
{
    ScriptObj *script = JimGetScript(interp, scriptObj);
    if (stateCharPtr) {
        *stateCharPtr = script->missing;
    }
    return script->missing == ' ' || script->missing == '}';
}

/**
 * Sets an appropriate error message for a missing script/expression terminator.
 *
 * Returns JIM_ERR if 'ch' represents an unmatched/missing character.
 *
................................................................................

        case '[':
            msg = "unmatched \"[\"";
            break;
        case '{':
            msg = "missing close-brace";
            break;
        case '}':
            msg = "extra characters after close-brace";
            break;
        case '"':
        default:
            msg = "missing quote";
            break;
    }

    Jim_SetResultString(interp, msg, -1);

Changes to tests/misc.test.

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
	catch -exit {
		set x 1
		if {[catch {exit 0}] == 1} {
			set x 2
		} else {
			set x 3
		}
	}]
} 6

# This one is for test coverage of an unusual case
test jimobj-1.1 "duplicate obj with no dupIntRepProc" {
	proc "x x" {} { return 2 }
	set a "x x"
	# force it to be a command object







|







481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
	catch -exit {
		set x 1
		if {[catch {exit 0}] == 1} {
			set x 2
		} else {
			set x 3
		}
	}
} 6

# This one is for test coverage of an unusual case
test jimobj-1.1 "duplicate obj with no dupIntRepProc" {
	proc "x x" {} { return 2 }
	set a "x x"
	# force it to be a command object

Changes to tests/subst.test.

138
139
140
141
142
143
144



145
146
147
148
149
150
151
152
153
154
155
} {foo }
test subst-10.2 {break in a subst} {
    subst {foo [break; return x; bogus code] bar}
} {foo }
test subst-10.3 {break in a subst} {
    subst {foo [if 1 { break; bogus code}] bar}
} {foo }



test subst-10.4 {break in a subst, parse error} {
    subst {foo [break ; set a {}{} ; stuff] bar}
} {foo }
test subst-10.5 {break in a subst, parse error} {
    subst {foo [break ;set bar baz ;set a {}{} ; stuff] bar}
} {foo }

test subst-11.1 {continue in a subst} {
    subst {foo [continue; bogus code] bar}
} {foo  bar}
test subst-11.2 {continue in a subst} {







>
>
>
|


|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
} {foo }
test subst-10.2 {break in a subst} {
    subst {foo [break; return x; bogus code] bar}
} {foo }
test subst-10.3 {break in a subst} {
    subst {foo [if 1 { break; bogus code}] bar}
} {foo }

# Note that unlike Tcl, Jim throws an error for these two before
# evaluating 
test subst-10.4 {break in a subst, parse error} tcl {
    subst {foo [break ; set a {}{} ; stuff] bar}
} {foo }
test subst-10.5 {break in a subst, parse error} tcl {
    subst {foo [break ;set bar baz ;set a {}{} ; stuff] bar}
} {foo }

test subst-11.1 {continue in a subst} {
    subst {foo [continue; bogus code] bar}
} {foo  bar}
test subst-11.2 {continue in a subst} {