summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/lbitlib.c
blob: 76c8d1d39b6fa8cf8136e3790c0b3eb06b459a95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* Bitwise operations library */
/* (c) Reuben Thomas 2000-2008 */
/* bitlib is copyright Reuben Thomas 2000-2008, and is released under the MIT
   license, like Lua (see http://www.lua.org/copyright.html; it's
   basically the same as the BSD license). There is no warranty. */

#include "config.h"

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <limits.h>


/* FIXME: Assume lua_Integer is ptrdiff_t */
#define LUA_INTEGER_MAX INTPTR_MAX
#define LUA_INTEGER_MIN INTPTR_MIN

/* FIXME: Assume size_t is an unsigned lua_Integer */
typedef size_t lua_UInteger;
#define LUA_UINTEGER_MAX UINT_MAX


/* Bit type size and limits */

#define BIT_BITS (CHAR_BIT * sizeof(lua_Integer))

/* This code may give warnings if BITLIB_FLOAT_* are too big to fit in
   long, but that doesn't matter since in that case they won't be
   used. */
#define BIT_MAX  (LUA_INTEGER_MAX)

#define BIT_MIN  (LUA_INTEGER_MIN)

#define BIT_UMAX (LUA_UINTEGER_MAX)


/* Define TOBIT to get a bit value */
#ifdef BUILTIN_CAST
#define 
#define TOBIT(L, n, res)                    \
  ((void)(res), luaL_checkinteger((L), (n)))
#else

#define TOBIT(L, n, res)                                            \
  ((lua_Integer)(((res) = luaL_checknumber(L, (n)) % BIT_UMAX), \
                 (res) > BIT_MAX ? ((res) -= BIT_UMAX, (res) -= 1) : \
                 ((res) < BIT_MIN ? ((res) += BIT_UMAX, (res) += 1) : (res))))
#endif


#define BIT_TRUNCATE(i)                         \
  ((i) & BIT_UMAX)


/* Operations

   The macros MONADIC and VARIADIC only deal with bitwise operations.

   LOGICAL_SHIFT truncates its left-hand operand before shifting so
   that any extra bits at the most-significant end are not shifted
   into the result.

   ARITHMETIC_SHIFT does not truncate its left-hand operand, so that
   the sign bits are not removed and right shift work properly.
   */
  
#define MONADIC(name, op)                                       \
  static int bit_ ## name(lua_State *L) {                       \
    lua_Number f;                                               \
    lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f)));        \
    return 1;                                                   \
  }

#define VARIADIC(name, op)                      \
  static int bit_ ## name(lua_State *L) {       \
    lua_Number f;                               \
    int n = lua_gettop(L), i;                   \
    lua_Integer w = TOBIT(L, 1, f);             \
    for (i = 2; i <= n; i++)                    \
      w op TOBIT(L, i, f);                      \
    lua_pushinteger(L, BIT_TRUNCATE(w));        \
    return 1;                                   \
  }

#define LOGICAL_SHIFT(name, op)                                         \
  static int bit_ ## name(lua_State *L) {                               \
    lua_Number f;                                                       \
    lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \
                                    (unsigned)luaL_checknumber(L, 2))); \
    return 1;                                                           \
  }

#define ARITHMETIC_SHIFT(name, op)                                      \
  static int bit_ ## name(lua_State *L) {                               \
    lua_Number f;                                                       \
    lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op      \
                                    (unsigned)luaL_checknumber(L, 2))); \
    return 1;                                                           \
  }

MONADIC(bnot,  ~)
VARIADIC(band, &=)
VARIADIC(bor,  |=)
VARIADIC(bxor, ^=)
ARITHMETIC_SHIFT(lshift,  <<)
LOGICAL_SHIFT(rshift,     >>)
ARITHMETIC_SHIFT(arshift, >>)

static const struct luaL_reg bitlib[] = {
  {"bnot",    bit_bnot},
  {"band",    bit_band},
  {"bor",     bit_bor},
  {"bxor",    bit_bxor},
  {"lshift",  bit_lshift},
  {"rshift",  bit_rshift},
  {"arshift", bit_arshift},
  {NULL, NULL}
};

LUALIB_API int luaopen_bit (lua_State *L) {
  luaL_register(L, "bit", bitlib);
  lua_pushnumber(L, BIT_BITS);
  lua_setfield(L, -2, "bits");
  return 1;
}
ORTED. remove deletes a name from the filesystem. It calls unlink for files, and rmdir for directories. Directories #include <dir.h> DIR *opendir(const char *name); The opendir() function opens a directory stream corresponding to the directory name, and returns a pointer to the directory stream. The stream is positioned at the first entry in the directory. struct dirent *readdir(DIR *dir); The readdir() function returns a pointer to a dirent structure representing the next directory entry in the directory stream pointed to by dir. It returns NULL on reaching the end-of-file or if an error occurred. Add a description of the struct here. int closedir(DIR *dir); The closedir() function closes the directory stream associated with dir. The directory stream descriptor dir is not available after this call. String/Memory #include <string.h> strcmp() strcpy() memcpy() memset() ... Memory allocation #include <dmalloc.h> void *malloc(size_t size); malloc() allocates size bytes and returns a pointer to the allocated memory. The memory is not cleared. void free(void *ptr); free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. void *realloc(void *ptr, size_t size); realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). void *calloc(size_t nmemb, size_t size); calloc() allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero. ID3 #include <id3.h> bool mp3info(mp3entry *entry, char *filename); Return FALSE if successful. The given mp3entry is then filled in with whatever id3 info it could find about the given file. Various #include <kernel.h> void kernel_init(void) Inits the kernel and starts the tick interrupt void sleep(ticks) Sleep a specified number of ticks, we have HZ ticks per second. void yield(void) Let another thread run. This should be used as soon as you have to "wait" for something or similar, and also if you do anything that takes "a long time". This function is the entire foundation that our "cooperative multitasking" is based on. Use it. int set_irq_level(int level) Sets the interrupt level (0 = lowest, 15 = highest) and returns the previous level. Note that you must shift the argument 4 bits to the left: set_irq_level(level << 4); void queue_init(struct event_queue *q) Initialize an event queue. The maximum number of events in a queue is QUEUE_LENGTH-1. void queue_wait(struct event_queue *q, struct event *ev) Receive an event in a queue, blocking the thread if the queue is empty. void queue_post(struct event_queue *q, int id, void *data) Post an event to a queue. NOTE: Negative event ID's are for system use only!!! bool queue_empty(struct event_queue* q) Returns true if the queue is empty. int queue_broadcast(int id, void *data) Posts an event in all queues that has been initiated with queue_init(). Returns the number of queues that were posted to. int tick_add_task(void (*f)(void)) Add a task to the tick task queue. The argument is a pointer to a function that will be called every tick interrupt. At most MAX_NUM_TICK_TASKS can be active at the same time. int tick_remove_task(void (*f)(void)) Remove a task from the task queue. void mutex_init(struct mutex *m) Initialize a mutex. void mutex_lock(struct mutex *m) Lock a mutex. This will block the thread if the mutex is already locked. Note that you will geta deadlock if you lock the mutex twice! void mutex_unlock(struct mutex *m) Unlock a mutex.