~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to debian/grub-extras/lua/lbaselib.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $
 
3
** Basic library
 
4
** See Copyright Notice in lua.h
 
5
*/
 
6
 
 
7
#if 0
 
8
#include <ctype.h>
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <string.h>
 
12
#endif
 
13
 
 
14
#define lbaselib_c
 
15
#define LUA_LIB
 
16
 
 
17
#include "lua.h"
 
18
 
 
19
#include "lauxlib.h"
 
20
#include "lualib.h"
 
21
 
 
22
 
 
23
 
 
24
 
 
25
/*
 
26
** If your system does not support `stdout', you can just remove this function.
 
27
** If you need, you can define your own `print' function, following this
 
28
** model but changing `fputs' to put the strings at a proper place
 
29
** (a console window or a log file, for instance).
 
30
*/
 
31
static int luaB_print (lua_State *L) {
 
32
  int n = lua_gettop(L);  /* number of arguments */
 
33
  int i;
 
34
  lua_getglobal(L, "tostring");
 
35
  for (i=1; i<=n; i++) {
 
36
    const char *s;
 
37
    lua_pushvalue(L, -1);  /* function to be called */
 
38
    lua_pushvalue(L, i);   /* value to print */
 
39
    lua_call(L, 1, 1);
 
40
    s = lua_tostring(L, -1);  /* get result */
 
41
    if (s == NULL)
 
42
      return luaL_error(L, LUA_QL("tostring") " must return a string to "
 
43
                           LUA_QL("print"));
 
44
    if (i>1) fputs("\t", stdout);
 
45
    fputs(s, stdout);
 
46
    lua_pop(L, 1);  /* pop result */
 
47
  }
 
48
  fputs("\n", stdout);
 
49
  return 0;
 
50
}
 
51
 
 
52
 
 
53
static int luaB_tonumber (lua_State *L) {
 
54
  int base = luaL_optint(L, 2, 10);
 
55
  if (base == 10) {  /* standard conversion */
 
56
    luaL_checkany(L, 1);
 
57
    if (lua_isnumber(L, 1)) {
 
58
      lua_pushnumber(L, lua_tonumber(L, 1));
 
59
      return 1;
 
60
    }
 
61
  }
 
62
  else {
 
63
    const char *s1 = luaL_checkstring(L, 1);
 
64
    char *s2;
 
65
    unsigned long n;
 
66
    luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
 
67
    n = strtoul(s1, &s2, base);
 
68
    if (s1 != s2) {  /* at least one valid digit? */
 
69
      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
 
70
      if (*s2 == '\0') {  /* no invalid trailing characters? */
 
71
        lua_pushnumber(L, (lua_Number)n);
 
72
        return 1;
 
73
      }
 
74
    }
 
75
  }
 
76
  lua_pushnil(L);  /* else not a number */
 
77
  return 1;
 
78
}
 
79
 
 
80
 
 
81
static int luaB_error (lua_State *L) {
 
82
  int level = luaL_optint(L, 2, 1);
 
83
  lua_settop(L, 1);
 
84
  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
 
85
    luaL_where(L, level);
 
86
    lua_pushvalue(L, 1);
 
87
    lua_concat(L, 2);
 
88
  }
 
89
  return lua_error(L);
 
90
}
 
91
 
 
92
 
 
93
static int luaB_getmetatable (lua_State *L) {
 
94
  luaL_checkany(L, 1);
 
95
  if (!lua_getmetatable(L, 1)) {
 
96
    lua_pushnil(L);
 
97
    return 1;  /* no metatable */
 
98
  }
 
99
  luaL_getmetafield(L, 1, "__metatable");
 
100
  return 1;  /* returns either __metatable field (if present) or metatable */
 
101
}
 
102
 
 
103
 
 
104
static int luaB_setmetatable (lua_State *L) {
 
105
  int t = lua_type(L, 2);
 
106
  luaL_checktype(L, 1, LUA_TTABLE);
 
107
  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
 
108
                    "nil or table expected");
 
109
  if (luaL_getmetafield(L, 1, "__metatable"))
 
110
    luaL_error(L, "cannot change a protected metatable");
 
111
  lua_settop(L, 2);
 
112
  lua_setmetatable(L, 1);
 
113
  return 1;
 
114
}
 
115
 
 
116
 
 
117
static void getfunc (lua_State *L, int opt) {
 
118
  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
 
119
  else {
 
120
    lua_Debug ar;
 
121
    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
 
122
    luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
 
123
    if (lua_getstack(L, level, &ar) == 0)
 
124
      luaL_argerror(L, 1, "invalid level");
 
125
    lua_getinfo(L, "f", &ar);
 
126
    if (lua_isnil(L, -1))
 
127
      luaL_error(L, "no function environment for tail call at level %d",
 
128
                    level);
 
129
  }
 
130
}
 
131
 
 
132
 
 
133
static int luaB_getfenv (lua_State *L) {
 
134
  getfunc(L, 1);
 
135
  if (lua_iscfunction(L, -1))  /* is a C function? */
 
136
    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */
 
137
  else
 
138
    lua_getfenv(L, -1);
 
139
  return 1;
 
140
}
 
141
 
 
142
 
 
143
static int luaB_setfenv (lua_State *L) {
 
144
  luaL_checktype(L, 2, LUA_TTABLE);
 
145
  getfunc(L, 0);
 
146
  lua_pushvalue(L, 2);
 
147
  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
 
148
    /* change environment of current thread */
 
149
    lua_pushthread(L);
 
150
    lua_insert(L, -2);
 
151
    lua_setfenv(L, -2);
 
152
    return 0;
 
153
  }
 
154
  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
 
155
    luaL_error(L,
 
156
          LUA_QL("setfenv") " cannot change environment of given object");
 
157
  return 1;
 
158
}
 
159
 
 
160
 
 
161
static int luaB_rawequal (lua_State *L) {
 
162
  luaL_checkany(L, 1);
 
163
  luaL_checkany(L, 2);
 
164
  lua_pushboolean(L, lua_rawequal(L, 1, 2));
 
165
  return 1;
 
166
}
 
167
 
 
168
 
 
169
static int luaB_rawget (lua_State *L) {
 
170
  luaL_checktype(L, 1, LUA_TTABLE);
 
171
  luaL_checkany(L, 2);
 
172
  lua_settop(L, 2);
 
173
  lua_rawget(L, 1);
 
174
  return 1;
 
175
}
 
176
 
 
177
static int luaB_rawset (lua_State *L) {
 
178
  luaL_checktype(L, 1, LUA_TTABLE);
 
179
  luaL_checkany(L, 2);
 
180
  luaL_checkany(L, 3);
 
181
  lua_settop(L, 3);
 
182
  lua_rawset(L, 1);
 
183
  return 1;
 
184
}
 
185
 
 
186
 
 
187
static int luaB_gcinfo (lua_State *L) {
 
188
  lua_pushinteger(L, lua_getgccount(L));
 
189
  return 1;
 
190
}
 
191
 
 
192
 
 
193
static int luaB_collectgarbage (lua_State *L) {
 
194
  static const char *const opts[] = {"stop", "restart", "collect",
 
195
    "count", "step", "setpause", "setstepmul", NULL};
 
196
  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
 
197
    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
 
198
  int o = luaL_checkoption(L, 1, "collect", opts);
 
199
  int ex = luaL_optint(L, 2, 0);
 
200
  int res = lua_gc(L, optsnum[o], ex);
 
201
  switch (optsnum[o]) {
 
202
    case LUA_GCCOUNT: {
 
203
      int b = lua_gc(L, LUA_GCCOUNTB, 0);
 
204
      lua_pushnumber(L, res + ((lua_Number)b/1024));
 
205
      return 1;
 
206
    }
 
207
    case LUA_GCSTEP: {
 
208
      lua_pushboolean(L, res);
 
209
      return 1;
 
210
    }
 
211
    default: {
 
212
      lua_pushnumber(L, res);
 
213
      return 1;
 
214
    }
 
215
  }
 
216
}
 
217
 
 
218
 
 
219
static int luaB_type (lua_State *L) {
 
220
  luaL_checkany(L, 1);
 
221
  lua_pushstring(L, luaL_typename(L, 1));
 
222
  return 1;
 
223
}
 
224
 
 
225
 
 
226
static int luaB_next (lua_State *L) {
 
227
  luaL_checktype(L, 1, LUA_TTABLE);
 
228
  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
 
229
  if (lua_next(L, 1))
 
230
    return 2;
 
231
  else {
 
232
    lua_pushnil(L);
 
233
    return 1;
 
234
  }
 
235
}
 
236
 
 
237
 
 
238
static int luaB_pairs (lua_State *L) {
 
239
  luaL_checktype(L, 1, LUA_TTABLE);
 
240
  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
 
241
  lua_pushvalue(L, 1);  /* state, */
 
242
  lua_pushnil(L);  /* and initial value */
 
243
  return 3;
 
244
}
 
245
 
 
246
 
 
247
static int ipairsaux (lua_State *L) {
 
248
  int i = luaL_checkint(L, 2);
 
249
  luaL_checktype(L, 1, LUA_TTABLE);
 
250
  i++;  /* next value */
 
251
  lua_pushinteger(L, i);
 
252
  lua_rawgeti(L, 1, i);
 
253
  return (lua_isnil(L, -1)) ? 0 : 2;
 
254
}
 
255
 
 
256
 
 
257
static int luaB_ipairs (lua_State *L) {
 
258
  luaL_checktype(L, 1, LUA_TTABLE);
 
259
  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
 
260
  lua_pushvalue(L, 1);  /* state, */
 
261
  lua_pushinteger(L, 0);  /* and initial value */
 
262
  return 3;
 
263
}
 
264
 
 
265
 
 
266
static int load_aux (lua_State *L, int status) {
 
267
  if (status == 0)  /* OK? */
 
268
    return 1;
 
269
  else {
 
270
    lua_pushnil(L);
 
271
    lua_insert(L, -2);  /* put before error message */
 
272
    return 2;  /* return nil plus error message */
 
273
  }
 
274
}
 
275
 
 
276
 
 
277
static int luaB_loadstring (lua_State *L) {
 
278
  size_t l;
 
279
  const char *s = luaL_checklstring(L, 1, &l);
 
280
  const char *chunkname = luaL_optstring(L, 2, s);
 
281
  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
 
282
}
 
283
 
 
284
 
 
285
static int luaB_loadfile (lua_State *L) {
 
286
  const char *fname = luaL_optstring(L, 1, NULL);
 
287
  return load_aux(L, luaL_loadfile(L, fname));
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
** Reader for generic `load' function: `lua_load' uses the
 
293
** stack for internal stuff, so the reader cannot change the
 
294
** stack top. Instead, it keeps its resulting string in a
 
295
** reserved slot inside the stack.
 
296
*/
 
297
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
 
298
  (void)ud;  /* to avoid warnings */
 
299
  luaL_checkstack(L, 2, "too many nested functions");
 
300
  lua_pushvalue(L, 1);  /* get function */
 
301
  lua_call(L, 0, 1);  /* call it */
 
302
  if (lua_isnil(L, -1)) {
 
303
    *size = 0;
 
304
    return NULL;
 
305
  }
 
306
  else if (lua_isstring(L, -1)) {
 
307
    lua_replace(L, 3);  /* save string in a reserved stack slot */
 
308
    return lua_tolstring(L, 3, size);
 
309
  }
 
310
  else luaL_error(L, "reader function must return a string");
 
311
  return NULL;  /* to avoid warnings */
 
312
}
 
313
 
 
314
 
 
315
static int luaB_load (lua_State *L) {
 
316
  int status;
 
317
  const char *cname = luaL_optstring(L, 2, "=(load)");
 
318
  luaL_checktype(L, 1, LUA_TFUNCTION);
 
319
  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */
 
320
  status = lua_load(L, generic_reader, NULL, cname);
 
321
  return load_aux(L, status);
 
322
}
 
323
 
 
324
 
 
325
static int luaB_dofile (lua_State *L) {
 
326
  const char *fname = luaL_optstring(L, 1, NULL);
 
327
  int n = lua_gettop(L);
 
328
  if (luaL_loadfile(L, fname) != 0) lua_error(L);
 
329
  lua_call(L, 0, LUA_MULTRET);
 
330
  return lua_gettop(L) - n;
 
331
}
 
332
 
 
333
 
 
334
static int luaB_assert (lua_State *L) {
 
335
  luaL_checkany(L, 1);
 
336
  if (!lua_toboolean(L, 1))
 
337
    return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
 
338
  return lua_gettop(L);
 
339
}
 
340
 
 
341
 
 
342
static int luaB_unpack (lua_State *L) {
 
343
  int i, e, n;
 
344
  luaL_checktype(L, 1, LUA_TTABLE);
 
345
  i = luaL_optint(L, 2, 1);
 
346
  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
 
347
  if (i > e) return 0;  /* empty range */
 
348
  n = e - i + 1;  /* number of elements */
 
349
  if (n <= 0 || !lua_checkstack(L, n))  /* n <= 0 means arith. overflow */
 
350
    return luaL_error(L, "too many results to unpack");
 
351
  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */
 
352
  while (i++ < e)  /* push arg[i + 1...e] */
 
353
    lua_rawgeti(L, 1, i);
 
354
  return n;
 
355
}
 
356
 
 
357
 
 
358
static int luaB_select (lua_State *L) {
 
359
  int n = lua_gettop(L);
 
360
  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
 
361
    lua_pushinteger(L, n-1);
 
362
    return 1;
 
363
  }
 
364
  else {
 
365
    int i = luaL_checkint(L, 1);
 
366
    if (i < 0) i = n + i;
 
367
    else if (i > n) i = n;
 
368
    luaL_argcheck(L, 1 <= i, 1, "index out of range");
 
369
    return n - i;
 
370
  }
 
371
}
 
372
 
 
373
 
 
374
static int luaB_pcall (lua_State *L) {
 
375
  int status;
 
376
  luaL_checkany(L, 1);
 
377
  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
 
378
  lua_pushboolean(L, (status == 0));
 
379
  lua_insert(L, 1);
 
380
  return lua_gettop(L);  /* return status + all results */
 
381
}
 
382
 
 
383
 
 
384
static int luaB_xpcall (lua_State *L) {
 
385
  int status;
 
386
  luaL_checkany(L, 2);
 
387
  lua_settop(L, 2);
 
388
  lua_insert(L, 1);  /* put error function under function to be called */
 
389
  status = lua_pcall(L, 0, LUA_MULTRET, 1);
 
390
  lua_pushboolean(L, (status == 0));
 
391
  lua_replace(L, 1);
 
392
  return lua_gettop(L);  /* return status + all results */
 
393
}
 
394
 
 
395
static int luaB_tostring (lua_State *L) {
 
396
  luaL_checkany(L, 1);
 
397
  if (luaL_callmeta(L, 1, "__tostring"))  /* is there a metafield? */
 
398
    return 1;  /* use its value */
 
399
  switch (lua_type(L, 1)) {
 
400
    case LUA_TNUMBER:
 
401
      lua_pushstring(L, lua_tostring(L, 1));
 
402
      break;
 
403
    case LUA_TSTRING:
 
404
      lua_pushvalue(L, 1);
 
405
      break;
 
406
    case LUA_TBOOLEAN:
 
407
      lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
 
408
      break;
 
409
    case LUA_TNIL:
 
410
      lua_pushliteral(L, "nil");
 
411
      break;
 
412
    default:
 
413
      lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
 
414
      break;
 
415
  }
 
416
  return 1;
 
417
}
 
418
 
 
419
 
 
420
static int luaB_newproxy (lua_State *L) {
 
421
  lua_settop(L, 1);
 
422
  lua_newuserdata(L, 0);  /* create proxy */
 
423
  if (lua_toboolean(L, 1) == 0)
 
424
    return 1;  /* no metatable */
 
425
  else if (lua_isboolean(L, 1)) {
 
426
    lua_newtable(L);  /* create a new metatable `m' ... */
 
427
    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */
 
428
    lua_pushboolean(L, 1);
 
429
    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */
 
430
  }
 
431
  else {
 
432
    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */
 
433
    if (lua_getmetatable(L, 1)) {
 
434
      lua_rawget(L, lua_upvalueindex(1));
 
435
      validproxy = lua_toboolean(L, -1);
 
436
      lua_pop(L, 1);  /* remove value */
 
437
    }
 
438
    luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
 
439
    lua_getmetatable(L, 1);  /* metatable is valid; get it */
 
440
  }
 
441
  lua_setmetatable(L, 2);
 
442
  return 1;
 
443
}
 
444
 
 
445
 
 
446
static const luaL_Reg base_funcs[] = {
 
447
  {"assert", luaB_assert},
 
448
  {"collectgarbage", luaB_collectgarbage},
 
449
  {"dofile", luaB_dofile},
 
450
  {"error", luaB_error},
 
451
  {"gcinfo", luaB_gcinfo},
 
452
  {"getfenv", luaB_getfenv},
 
453
  {"getmetatable", luaB_getmetatable},
 
454
  {"loadfile", luaB_loadfile},
 
455
  {"load", luaB_load},
 
456
  {"loadstring", luaB_loadstring},
 
457
  {"next", luaB_next},
 
458
  {"pcall", luaB_pcall},
 
459
  {"print", luaB_print},
 
460
  {"rawequal", luaB_rawequal},
 
461
  {"rawget", luaB_rawget},
 
462
  {"rawset", luaB_rawset},
 
463
  {"select", luaB_select},
 
464
  {"setfenv", luaB_setfenv},
 
465
  {"setmetatable", luaB_setmetatable},
 
466
  {"tonumber", luaB_tonumber},
 
467
  {"tostring", luaB_tostring},
 
468
  {"type", luaB_type},
 
469
  {"unpack", luaB_unpack},
 
470
  {"xpcall", luaB_xpcall},
 
471
  {NULL, NULL}
 
472
};
 
473
 
 
474
 
 
475
/*
 
476
** {======================================================
 
477
** Coroutine library
 
478
** =======================================================
 
479
*/
 
480
 
 
481
#define CO_RUN  0       /* running */
 
482
#define CO_SUS  1       /* suspended */
 
483
#define CO_NOR  2       /* 'normal' (it resumed another coroutine) */
 
484
#define CO_DEAD 3
 
485
 
 
486
static const char *const statnames[] =
 
487
    {"running", "suspended", "normal", "dead"};
 
488
 
 
489
static int costatus (lua_State *L, lua_State *co) {
 
490
  if (L == co) return CO_RUN;
 
491
  switch (lua_status(co)) {
 
492
    case LUA_YIELD:
 
493
      return CO_SUS;
 
494
    case 0: {
 
495
      lua_Debug ar;
 
496
      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
 
497
        return CO_NOR;  /* it is running */
 
498
      else if (lua_gettop(co) == 0)
 
499
          return CO_DEAD;
 
500
      else
 
501
        return CO_SUS;  /* initial state */
 
502
    }
 
503
    default:  /* some error occured */
 
504
      return CO_DEAD;
 
505
  }
 
506
}
 
507
 
 
508
 
 
509
static int luaB_costatus (lua_State *L) {
 
510
  lua_State *co = lua_tothread(L, 1);
 
511
  luaL_argcheck(L, co, 1, "coroutine expected");
 
512
  lua_pushstring(L, statnames[costatus(L, co)]);
 
513
  return 1;
 
514
}
 
515
 
 
516
 
 
517
static int auxresume (lua_State *L, lua_State *co, int narg) {
 
518
  int status = costatus(L, co);
 
519
  if (!lua_checkstack(co, narg))
 
520
    luaL_error(L, "too many arguments to resume");
 
521
  if (status != CO_SUS) {
 
522
    lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
 
523
    return -1;  /* error flag */
 
524
  }
 
525
  lua_xmove(L, co, narg);
 
526
  lua_setlevel(L, co);
 
527
  status = lua_resume(co, narg);
 
528
  if (status == 0 || status == LUA_YIELD) {
 
529
    int nres = lua_gettop(co);
 
530
    if (!lua_checkstack(L, nres + 1))
 
531
      luaL_error(L, "too many results to resume");
 
532
    lua_xmove(co, L, nres);  /* move yielded values */
 
533
    return nres;
 
534
  }
 
535
  else {
 
536
    lua_xmove(co, L, 1);  /* move error message */
 
537
    return -1;  /* error flag */
 
538
  }
 
539
}
 
540
 
 
541
 
 
542
static int luaB_coresume (lua_State *L) {
 
543
  lua_State *co = lua_tothread(L, 1);
 
544
  int r;
 
545
  luaL_argcheck(L, co, 1, "coroutine expected");
 
546
  r = auxresume(L, co, lua_gettop(L) - 1);
 
547
  if (r < 0) {
 
548
    lua_pushboolean(L, 0);
 
549
    lua_insert(L, -2);
 
550
    return 2;  /* return false + error message */
 
551
  }
 
552
  else {
 
553
    lua_pushboolean(L, 1);
 
554
    lua_insert(L, -(r + 1));
 
555
    return r + 1;  /* return true + `resume' returns */
 
556
  }
 
557
}
 
558
 
 
559
 
 
560
static int luaB_auxwrap (lua_State *L) {
 
561
  lua_State *co = lua_tothread(L, lua_upvalueindex(1));
 
562
  int r = auxresume(L, co, lua_gettop(L));
 
563
  if (r < 0) {
 
564
    if (lua_isstring(L, -1)) {  /* error object is a string? */
 
565
      luaL_where(L, 1);  /* add extra info */
 
566
      lua_insert(L, -2);
 
567
      lua_concat(L, 2);
 
568
    }
 
569
    lua_error(L);  /* propagate error */
 
570
  }
 
571
  return r;
 
572
}
 
573
 
 
574
 
 
575
static int luaB_cocreate (lua_State *L) {
 
576
  lua_State *NL = lua_newthread(L);
 
577
  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
 
578
    "Lua function expected");
 
579
  lua_pushvalue(L, 1);  /* move function to top */
 
580
  lua_xmove(L, NL, 1);  /* move function from L to NL */
 
581
  return 1;
 
582
}
 
583
 
 
584
 
 
585
static int luaB_cowrap (lua_State *L) {
 
586
  luaB_cocreate(L);
 
587
  lua_pushcclosure(L, luaB_auxwrap, 1);
 
588
  return 1;
 
589
}
 
590
 
 
591
 
 
592
static int luaB_yield (lua_State *L) {
 
593
  return lua_yield(L, lua_gettop(L));
 
594
}
 
595
 
 
596
 
 
597
static int luaB_corunning (lua_State *L) {
 
598
  if (lua_pushthread(L))
 
599
    lua_pushnil(L);  /* main thread is not a coroutine */
 
600
  return 1;
 
601
}
 
602
 
 
603
 
 
604
static const luaL_Reg co_funcs[] = {
 
605
  {"create", luaB_cocreate},
 
606
  {"resume", luaB_coresume},
 
607
  {"running", luaB_corunning},
 
608
  {"status", luaB_costatus},
 
609
  {"wrap", luaB_cowrap},
 
610
  {"yield", luaB_yield},
 
611
  {NULL, NULL}
 
612
};
 
613
 
 
614
/* }====================================================== */
 
615
 
 
616
 
 
617
static void auxopen (lua_State *L, const char *name,
 
618
                     lua_CFunction f, lua_CFunction u) {
 
619
  lua_pushcfunction(L, u);
 
620
  lua_pushcclosure(L, f, 1);
 
621
  lua_setfield(L, -2, name);
 
622
}
 
623
 
 
624
 
 
625
static void base_open (lua_State *L) {
 
626
  /* set global _G */
 
627
  lua_pushvalue(L, LUA_GLOBALSINDEX);
 
628
  lua_setglobal(L, "_G");
 
629
  /* open lib into global table */
 
630
  luaL_register(L, "_G", base_funcs);
 
631
  lua_pushliteral(L, LUA_VERSION);
 
632
  lua_setglobal(L, "_VERSION");  /* set global _VERSION */
 
633
  /* `ipairs' and `pairs' need auxliliary functions as upvalues */
 
634
  auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
 
635
  auxopen(L, "pairs", luaB_pairs, luaB_next);
 
636
  /* `newproxy' needs a weaktable as upvalue */
 
637
  lua_createtable(L, 0, 1);  /* new table `w' */
 
638
  lua_pushvalue(L, -1);  /* `w' will be its own metatable */
 
639
  lua_setmetatable(L, -2);
 
640
  lua_pushliteral(L, "kv");
 
641
  lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
 
642
  lua_pushcclosure(L, luaB_newproxy, 1);
 
643
  lua_setglobal(L, "newproxy");  /* set global `newproxy' */
 
644
}
 
645
 
 
646
 
 
647
LUALIB_API int luaopen_base (lua_State *L) {
 
648
  base_open(L);
 
649
  luaL_register(L, LUA_COLIBNAME, co_funcs);
 
650
  return 2;
 
651
}
 
652