diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-29 11:33:31 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-29 11:33:31 -0300 |
commit | ac12f4db4b2f715b1556722b6ed65804cfd6348a (patch) | |
tree | 4c15a7988e19c766ed9e88451db92140200fd041 | |
parent | b691d4344bb67a1a09203466812877595b3bd744 (diff) | |
download | lua-ac12f4db4b2f715b1556722b6ed65804cfd6348a.tar.gz lua-ac12f4db4b2f715b1556722b6ed65804cfd6348a.tar.bz2 lua-ac12f4db4b2f715b1556722b6ed65804cfd6348a.zip |
C upvalues are the last arguments to a function
-rw-r--r-- | lauxlib.c | 5 | ||||
-rw-r--r-- | lbuiltin.c | 6 | ||||
-rw-r--r-- | ldo.c | 20 | ||||
-rw-r--r-- | liolib.c | 100 | ||||
-rw-r--r-- | lua.c | 4 | ||||
-rw-r--r-- | lua.h | 4 |
6 files changed, 74 insertions, 65 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.c,v 1.30 2000/08/09 19:16:57 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.31 2000/08/28 17:57:04 roberto Exp roberto $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -32,8 +32,7 @@ int luaL_findstring (const char *name, const char *const list[]) { | |||
32 | void luaL_argerror (lua_State *L, int narg, const char *extramsg) { | 32 | void luaL_argerror (lua_State *L, int narg, const char *extramsg) { |
33 | lua_Debug ar; | 33 | lua_Debug ar; |
34 | lua_getstack(L, 0, &ar); | 34 | lua_getstack(L, 0, &ar); |
35 | lua_getinfo(L, "nu", &ar); | 35 | lua_getinfo(L, "n", &ar); |
36 | narg -= ar.nups; | ||
37 | if (ar.name == NULL) | 36 | if (ar.name == NULL) |
38 | ar.name = "?"; | 37 | ar.name = "?"; |
39 | luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)", | 38 | luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)", |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbuiltin.c,v 1.121 2000/08/15 18:28:48 roberto Exp roberto $ | 2 | ** $Id: lbuiltin.c,v 1.122 2000/08/28 17:57:04 roberto Exp roberto $ |
3 | ** Built-in functions | 3 | ** Built-in functions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -640,7 +640,7 @@ static void deprecated_funcs (lua_State *L) { | |||
640 | hvalue(>) = L->gt; | 640 | hvalue(>) = L->gt; |
641 | for (i=0; i<num_deprecated; i++) { | 641 | for (i=0; i<num_deprecated; i++) { |
642 | lua_pushobject(L, >); | 642 | lua_pushobject(L, >); |
643 | lua_pushcclosure(L, deprecated_global_funcs[i].func, 1); | 643 | lua_pushcclosure(L, deprecated_global_funcs[i].func, 1); ?? |
644 | lua_setglobal(L, deprecated_global_funcs[i].name); | 644 | lua_setglobal(L, deprecated_global_funcs[i].name); |
645 | } | 645 | } |
646 | luaL_openl(L, other_deprecated_global_funcs); | 646 | luaL_openl(L, other_deprecated_global_funcs); |
@@ -652,7 +652,7 @@ static void deprecated_funcs (lua_State *L) { | |||
652 | ** gives an explicit error in any attempt to call a deprecated function | 652 | ** gives an explicit error in any attempt to call a deprecated function |
653 | */ | 653 | */ |
654 | static int deprecated_func (lua_State *L) { | 654 | static int deprecated_func (lua_State *L) { |
655 | luaL_verror(L, "function `%.20s' is deprecated", luaL_check_string(L, 1)); | 655 | luaL_verror(L, "function `%.20s' is deprecated", luaL_check_string(L, -1)); |
656 | return 0; /* to avoid warnings */ | 656 | return 0; /* to avoid warnings */ |
657 | } | 657 | } |
658 | 658 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.85 2000/08/10 19:50:47 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.86 2000/08/28 17:57:04 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -136,20 +136,14 @@ static void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, | |||
136 | static StkId callCclosure (lua_State *L, const struct Closure *cl, StkId base) { | 136 | static StkId callCclosure (lua_State *L, const struct Closure *cl, StkId base) { |
137 | int nup = cl->nupvalues; /* number of upvalues */ | 137 | int nup = cl->nupvalues; /* number of upvalues */ |
138 | StkId old_Cbase = L->Cbase; | 138 | StkId old_Cbase = L->Cbase; |
139 | int nres; /* number of results */ | 139 | int n; |
140 | if (nup > 0) { | ||
141 | int n = L->top - base; /* number of arguments */ | ||
142 | luaD_checkstack(L, nup); | ||
143 | /* open space for upvalues as extra arguments */ | ||
144 | while (n--) *(base+nup+n) = *(base+n); | ||
145 | L->top += nup; | ||
146 | /* copy upvalues into stack */ | ||
147 | while (nup--) *(base+nup) = cl->upvalue[nup]; | ||
148 | } | ||
149 | L->Cbase = base; /* new base for C function */ | 140 | L->Cbase = base; /* new base for C function */ |
150 | nres = (*cl->f.c)(L); /* do the actual call */ | 141 | luaD_checkstack(L, nup); |
142 | for (n=0; n<nup; n++) /* copy upvalues as extra arguments */ | ||
143 | *(L->top++) = cl->upvalue[n]; | ||
144 | n = (*cl->f.c)(L); /* do the actual call */ | ||
151 | L->Cbase = old_Cbase; /* restore old C base */ | 145 | L->Cbase = old_Cbase; /* restore old C base */ |
152 | return L->top - nres; /* return index of first result */ | 146 | return L->top - n; /* return index of first result */ |
153 | } | 147 | } |
154 | 148 | ||
155 | 149 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 1.71 2000/08/22 17:47:17 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 1.72 2000/08/28 17:57:04 roberto Exp roberto $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -109,7 +109,6 @@ static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) { | |||
109 | lua_getref(L, ctrl->ref[inout]); | 109 | lua_getref(L, ctrl->ref[inout]); |
110 | lua_rawget(L); | 110 | lua_rawget(L); |
111 | f = gethandle(L, ctrl, -1); | 111 | f = gethandle(L, ctrl, -1); |
112 | lua_settop(L, -1); /* remove global */ | ||
113 | if (f == NULL) | 112 | if (f == NULL) |
114 | luaL_verror(L, "global variable `%.10s' is not a file handle", | 113 | luaL_verror(L, "global variable `%.10s' is not a file handle", |
115 | filenames[inout]); | 114 | filenames[inout]); |
@@ -150,21 +149,23 @@ static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) { | |||
150 | 149 | ||
151 | 150 | ||
152 | static int io_close (lua_State *L) { | 151 | static int io_close (lua_State *L) { |
153 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 152 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
154 | return pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 2))); | 153 | lua_settop(L, -1); /* remove upvalue */ |
154 | return pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 1))); | ||
155 | } | 155 | } |
156 | 156 | ||
157 | 157 | ||
158 | static int file_collect (lua_State *L) { | 158 | static int file_collect (lua_State *L) { |
159 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 159 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
160 | if (ctrl == (IOCtrl *)lua_touserdata(L, 2)) { | 160 | lua_settop(L, -1); /* remove upvalue */ |
161 | if (ctrl == (IOCtrl *)lua_touserdata(L, 1)) { | ||
161 | /* collectig `ctrl' itself */ | 162 | /* collectig `ctrl' itself */ |
162 | lua_unref(L, ctrl->ref[INFILE]); | 163 | lua_unref(L, ctrl->ref[INFILE]); |
163 | lua_unref(L, ctrl->ref[OUTFILE]); | 164 | lua_unref(L, ctrl->ref[OUTFILE]); |
164 | free(ctrl); | 165 | free(ctrl); |
165 | } | 166 | } |
166 | else { /* collecting a file: Close it */ | 167 | else { /* collecting a file: Close it */ |
167 | FILE *f = getnonullfile(L, ctrl, 2); | 168 | FILE *f = getnonullfile(L, ctrl, 1); |
168 | if (f != stdin && f != stdout && f != stderr) | 169 | if (f != stdin && f != stdout && f != stderr) |
169 | CLOSEFILE(L, f); | 170 | CLOSEFILE(L, f); |
170 | } | 171 | } |
@@ -173,8 +174,10 @@ static int file_collect (lua_State *L) { | |||
173 | 174 | ||
174 | 175 | ||
175 | static int io_open (lua_State *L) { | 176 | static int io_open (lua_State *L) { |
176 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 177 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
177 | FILE *f = fopen(luaL_check_string(L, 2), luaL_check_string(L, 3)); | 178 | FILE *f; |
179 | lua_settop(L, -1); /* remove upvalue */ | ||
180 | f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); | ||
178 | if (f) { | 181 | if (f) { |
179 | lua_pushusertag(L, f, ctrl->iotag); | 182 | lua_pushusertag(L, f, ctrl->iotag); |
180 | return 1; | 183 | return 1; |
@@ -186,16 +189,17 @@ static int io_open (lua_State *L) { | |||
186 | 189 | ||
187 | 190 | ||
188 | static int io_fromto (lua_State *L, int inout, const char *mode) { | 191 | static int io_fromto (lua_State *L, int inout, const char *mode) { |
189 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 192 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
190 | FILE *current; | 193 | FILE *current; |
191 | if (lua_isnull(L, 2)) { | 194 | lua_settop(L, -1); /* remove upvalue */ |
195 | if (lua_isnull(L, 1)) { | ||
192 | closefile(L, ctrl, getfilebyref(L, ctrl, inout)); | 196 | closefile(L, ctrl, getfilebyref(L, ctrl, inout)); |
193 | current = (inout == 0) ? stdin : stdout; | 197 | current = (inout == 0) ? stdin : stdout; |
194 | } | 198 | } |
195 | else if (lua_tag(L, 2) == ctrl->iotag) /* deprecated option */ | 199 | else if (lua_tag(L, 1) == ctrl->iotag) /* deprecated option */ |
196 | current = (FILE *)lua_touserdata(L, 2); | 200 | current = (FILE *)lua_touserdata(L, 1); |
197 | else { | 201 | else { |
198 | const char *s = luaL_check_string(L, 2); | 202 | const char *s = luaL_check_string(L, 1); |
199 | current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode); | 203 | current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode); |
200 | } | 204 | } |
201 | return setreturn(L, ctrl, current, inout); | 205 | return setreturn(L, ctrl, current, inout); |
@@ -213,8 +217,10 @@ static int io_writeto (lua_State *L) { | |||
213 | 217 | ||
214 | 218 | ||
215 | static int io_appendto (lua_State *L) { | 219 | static int io_appendto (lua_State *L) { |
216 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 220 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
217 | FILE *current = fopen(luaL_check_string(L, 2), "a"); | 221 | FILE *current; |
222 | lua_settop(L, -1); /* remove upvalue */ | ||
223 | current = fopen(luaL_check_string(L, 1), "a"); | ||
218 | return setreturn(L, ctrl, current, OUTFILE); | 224 | return setreturn(L, ctrl, current, OUTFILE); |
219 | } | 225 | } |
220 | 226 | ||
@@ -353,28 +359,33 @@ static int read_chars (lua_State *L, FILE *f, size_t n) { | |||
353 | 359 | ||
354 | 360 | ||
355 | static int io_read (lua_State *L) { | 361 | static int io_read (lua_State *L) { |
356 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 362 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
357 | int lastarg = lua_gettop(L); | 363 | int lastarg = lua_gettop(L) - 1; |
358 | int firstarg = 2; | 364 | int firstarg = 1; |
359 | FILE *f = gethandle(L, ctrl, firstarg); | 365 | FILE *f = gethandle(L, ctrl, firstarg); |
360 | int n = 0; | 366 | int n; |
361 | if (f) firstarg++; | 367 | if (f) firstarg++; |
362 | else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */ | 368 | else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */ |
363 | do { /* repeat for each part */ | 369 | lua_settop(L, -1); |
370 | if (firstarg > lastarg) { /* no arguments? */ | ||
371 | lua_settop(L, 0); /* erase upvalue and other eventual garbage */ | ||
372 | firstarg = lastarg = 1; /* correct indices */ | ||
373 | lua_pushstring(L, "*l"); /* push default argument */ | ||
374 | } | ||
375 | for (n = firstarg; n<=lastarg; n++) { | ||
364 | size_t l; | 376 | size_t l; |
365 | int success; | 377 | int success; |
366 | luaL_resetbuffer(L); | 378 | luaL_resetbuffer(L); |
367 | if (lua_isnumber(L, firstarg+n)) | 379 | if (lua_isnumber(L, n)) |
368 | success = read_chars(L, f, (size_t)lua_tonumber(L, firstarg+n)); | 380 | success = read_chars(L, f, (size_t)lua_tonumber(L, n)); |
369 | else { | 381 | else { |
370 | const char *p = luaL_opt_string(L, firstarg+n, "*l"); | 382 | const char *p = luaL_check_string(L, n); |
371 | if (p[0] != '*') | 383 | if (p[0] != '*') |
372 | success = read_pattern(L, f, p); /* deprecated! */ | 384 | success = read_pattern(L, f, p); /* deprecated! */ |
373 | else { | 385 | else { |
374 | switch (p[1]) { | 386 | switch (p[1]) { |
375 | case 'n': /* number */ | 387 | case 'n': /* number */ |
376 | if (!read_number(L, f)) return n; /* read fails */ | 388 | if (!read_number(L, f)) goto endloop; /* read fails */ |
377 | n++; | ||
378 | continue; /* number is already pushed; avoid the "pushstring" */ | 389 | continue; /* number is already pushed; avoid the "pushstring" */ |
379 | case 'l': /* line */ | 390 | case 'l': /* line */ |
380 | success = read_line(L, f); | 391 | success = read_line(L, f); |
@@ -388,26 +399,25 @@ static int io_read (lua_State *L) { | |||
388 | success = 0; /* must read something to succeed */ | 399 | success = 0; /* must read something to succeed */ |
389 | break; | 400 | break; |
390 | default: | 401 | default: |
391 | luaL_argerror(L, firstarg+n, "invalid format"); | 402 | luaL_argerror(L, n, "invalid format"); |
392 | success = 0; /* to avoid warnings */ | 403 | success = 0; /* to avoid warnings */ |
393 | } | 404 | } |
394 | } | 405 | } |
395 | } | 406 | } |
396 | l = luaL_getsize(L); | 407 | l = luaL_getsize(L); |
397 | if (!success && l==0) return n; /* read fails */ | 408 | if (!success && l==0) break; /* read fails */ |
398 | lua_pushlstring(L, luaL_buffer(L), l); | 409 | lua_pushlstring(L, luaL_buffer(L), l); |
399 | n++; | 410 | } endloop: |
400 | } while (firstarg+n <= lastarg); | 411 | return n - firstarg; |
401 | return n; | ||
402 | } | 412 | } |
403 | 413 | ||
404 | /* }====================================================== */ | 414 | /* }====================================================== */ |
405 | 415 | ||
406 | 416 | ||
407 | static int io_write (lua_State *L) { | 417 | static int io_write (lua_State *L) { |
408 | int lastarg = lua_gettop(L); | 418 | int lastarg = lua_gettop(L) - 1; |
409 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 419 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
410 | int arg = 2; | 420 | int arg = 1; |
411 | int status = 1; | 421 | int status = 1; |
412 | FILE *f = gethandle(L, ctrl, arg); | 422 | FILE *f = gethandle(L, ctrl, arg); |
413 | if (f) arg++; | 423 | if (f) arg++; |
@@ -431,11 +441,15 @@ static int io_write (lua_State *L) { | |||
431 | static int io_seek (lua_State *L) { | 441 | static int io_seek (lua_State *L) { |
432 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; | 442 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; |
433 | static const char *const modenames[] = {"set", "cur", "end", NULL}; | 443 | static const char *const modenames[] = {"set", "cur", "end", NULL}; |
434 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 444 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
435 | FILE *f = getnonullfile(L, ctrl, 2); | 445 | FILE *f; |
436 | int op = luaL_findstring(luaL_opt_string(L, 3, "cur"), modenames); | 446 | int op; |
437 | long offset = luaL_opt_long(L, 4, 0); | 447 | long offset; |
438 | luaL_arg_check(L, op != -1, 3, "invalid mode"); | 448 | lua_settop(L, -1); /* remove upvalue */ |
449 | f = getnonullfile(L, ctrl, 1); | ||
450 | op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames); | ||
451 | offset = luaL_opt_long(L, 3, 0); | ||
452 | luaL_arg_check(L, op != -1, 2, "invalid mode"); | ||
439 | op = fseek(f, offset, mode[op]); | 453 | op = fseek(f, offset, mode[op]); |
440 | if (op) | 454 | if (op) |
441 | return pushresult(L, 0); /* error */ | 455 | return pushresult(L, 0); /* error */ |
@@ -447,9 +461,11 @@ static int io_seek (lua_State *L) { | |||
447 | 461 | ||
448 | 462 | ||
449 | static int io_flush (lua_State *L) { | 463 | static int io_flush (lua_State *L) { |
450 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, 1); | 464 | IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); |
451 | FILE *f = gethandle(L, ctrl, 2); | 465 | FILE *f; |
452 | luaL_arg_check(L, f || lua_isnull(L, 2), 2, "invalid file handle"); | 466 | lua_settop(L, -1); /* remove upvalue */ |
467 | f = gethandle(L, ctrl, 1); | ||
468 | luaL_arg_check(L, f || lua_isnull(L, 1), 1, "invalid file handle"); | ||
453 | return pushresult(L, fflush(f) == 0); | 469 | return pushresult(L, fflush(f) == 0); |
454 | } | 470 | } |
455 | 471 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.c,v 1.45 2000/08/14 17:45:59 roberto Exp roberto $ | 2 | ** $Id: lua.c,v 1.46 2000/08/28 17:57:04 roberto Exp roberto $ |
3 | ** Lua stand-alone interpreter | 3 | ** Lua stand-alone interpreter |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -142,7 +142,7 @@ static void getargs (char *argv[]) { | |||
142 | 142 | ||
143 | 143 | ||
144 | static int l_getargs (lua_State *l) { | 144 | static int l_getargs (lua_State *l) { |
145 | char **argv = (char **)lua_touserdata(l, 1); | 145 | char **argv = (char **)lua_touserdata(l, -1); |
146 | getargs(argv); | 146 | getargs(argv); |
147 | return 1; | 147 | return 1; |
148 | } | 148 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.59 2000/08/17 13:18:01 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.60 2000/08/28 17:57:04 roberto Exp roberto $ |
3 | ** Lua - An Extensible Extension Language | 3 | ** Lua - An Extensible Extension Language |
4 | ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil | 4 | ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil |
5 | ** e-mail: lua@tecgraf.puc-rio.br | 5 | ** e-mail: lua@tecgraf.puc-rio.br |
@@ -153,7 +153,7 @@ int lua_next (lua_State *L, int index, int i); | |||
153 | #define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) | 153 | #define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) |
154 | 154 | ||
155 | #define lua_isfunction(L,n) (*lua_type(L,n) == 'f') | 155 | #define lua_isfunction(L,n) (*lua_type(L,n) == 'f') |
156 | #define lua_isstring(L,n) (lua_tostring(L,n)) | 156 | #define lua_isstring(L,n) (lua_tostring(L,n) != 0) |
157 | #define lua_istable(L,n) (*lua_type(L,n) == 't') | 157 | #define lua_istable(L,n) (*lua_type(L,n) == 't') |
158 | #define lua_isuserdata(L,n) (*lua_type(L,n) == 'u') | 158 | #define lua_isuserdata(L,n) (*lua_type(L,n) == 'u') |
159 | #define lua_isnil(L,n) (lua_type(L,n)[2] == 'l') | 159 | #define lua_isnil(L,n) (lua_type(L,n)[2] == 'l') |