p2  0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
string.c
Go to the documentation of this file.
1 //
6 // (c) 2008 why the lucky stiff, the freelance professor
7 //
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include "p2.h"
12 #include "internal.h"
13 #include "khash.h"
14 #include "table.h"
15 
16 #define BYTES_FACTOR 1 / 8 * 9
17 #define BYTES_CHUNK 32
18 #define BYTES_ALIGN(len) PN_ALIGN(len + sizeof(struct PNBytes), BYTES_CHUNK) - sizeof(struct PNBytes)
19 
20 void potion_add_str(Potion *P, PN s) {
21  int ret;
22  kh_put(str, P->strings, s, &ret);
23  PN_QUICK_FWD(struct PNTable *, P->strings);
24 }
25 
26 PN potion_lookup_str(Potion *P, const char *str) {
27  vPN(Table) t = P->strings;
28  unsigned k = kh_get(str, t, str);
29  if (k != kh_end(t)) return kh_key(str, t, k);
30  return PN_NIL;
31 }
32 
33 PN potion_str(Potion *P, const char *str) {
34  PN val = potion_lookup_str(P, str);
35  if (val == PN_NIL) {
36  size_t len = strlen(str);
37  vPN(String) s = PN_ALLOC_N(PN_TSTRING, struct PNString, len + 1);
38  s->len = (PN_SIZE)len;
39  PN_MEMCPY_N(s->chars, str, char, len);
40  s->chars[len] = '\0';
41  potion_add_str(P, (PN)s);
42  val = (PN)s;
43  }
44  return val;
45 }
46 
47 PN potion_str2(Potion *P, char *str, size_t len) {
48  PN exist = PN_NIL;
49 
50  vPN(String) s = PN_ALLOC_N(PN_TSTRING, struct PNString, len + 1);
51  s->len = (PN_SIZE)len;
52  assert(len < 0x10000000);
53  PN_MEMCPY_N(s->chars, str, char, len);
54  s->chars[len] = '\0';
55 
56  exist = potion_lookup_str(P, s->chars);
57  if (exist == PN_NIL) {
58  potion_add_str(P, (PN)s);
59  exist = (PN)s;
60  }
61  return exist;
62 }
63 
64 PN potion_strcat(Potion *P, char *str, char *str2) {
65  PN exist = PN_NIL;
66  int len = strlen(str);
67  int len2 = strlen(str2);
68  vPN(String) s = PN_ALLOC_N(PN_TSTRING, struct PNString, len+len2+1);
69  PN_MEMCPY_N(s->chars, str, char, len);
70  PN_MEMCPY_N(s->chars+len, str2, char, len2);
71  s->chars[len+len2] = '\0';
72  s->len = len+len2;
73  exist = potion_lookup_str(P, s->chars);
74  if (exist == PN_NIL) {
75  potion_add_str(P, (PN)s);
76  exist = (PN)s;
77  }
78  return exist;
79 }
80 
81 PN potion_str_format(Potion *P, const char *format, ...) {
82  vPN(String) s;
83  PN_SIZE len;
84  va_list args;
85 
86  va_start(args, format);
87  len = (PN_SIZE)vsnprintf(NULL, 0, format, args);
88  va_end(args);
89  s = PN_ALLOC_N(PN_TSTRING, struct PNString, len + 1);
90 
91  va_start(args, format);
92  vsnprintf(s->chars, len + 1, format, args);
93  va_end(args);
94  s->len = len;
95  return (PN)s;
96 }
97 
100 static PN potion_str_length(Potion *P, PN cl, PN self) {
101  return PN_NUM(potion_cp_strlen_utf8(PN_STR_PTR(self)));
102 }
103 
106 static PN potion_str_eval(Potion *P, PN cl, PN self) {
107  return potion_eval(P, self);
108 }
109 
112 static PN potion_str_number(Potion *P, PN cl, PN self) {
113  char *str = PN_STR_PTR(self);
114  int i = 0, dec = 0, sign = 0, len = PN_STR_LEN(self);
115  if (len < 1) return PN_ZERO;
116 
117  sign = (str[0] == '-' ? -1 : 1);
118  if (str[0] == '-' || str[0] == '+') {
119  dec++; str++; len--;
120  }
121  for (i = 0; i < len; i++)
122  if (str[i] < '0' || str[i] > '9')
123  break;
124  if (i < 10 && i == len) {
125  return PN_NUM(sign * PN_ATOI(str, i, 10));
126  }
127 
128  return potion_strtod(P, PN_STR_PTR(self), PN_STR_LEN(self));
129 }
130 
133 static PN potion_str_string(Potion *P, PN cl, PN self) {
134  return self;
135 }
136 
139 static PN potion_str_clone(Potion *P, PN cl, PN self) {
140  return self;
141 }
142 
146 static PN potion_str_print(Potion *P, PN cl, PN self) {
147  if (fwrite(PN_STR_PTR(self), 1, PN_STR_LEN(self), stdout))
148  return PN_STR0;
149  else
150  return PN_NIL;
151 }
152 
154 // Maybe use the optimized strlen in contrib.c
155 static size_t potion_utf8char_offset(const char *s, size_t index) {
156  int i;
157  for (i = 0; s[i]; i++)
158  if ((s[i] & 0xC0) != 0x80)
159  if (index-- == 0)
160  return i;
161  return i;
162 }
163 
165 static size_t potion_utf8char_nextchar(const char *s, size_t offset) {
166  size_t i;
167  for (i = offset+1; s[i]; i++)
168  if ((s[i] & 0xC0) != 0x80)
169  return i;
170  return i;
171 }
172 
173 /* By Bjoern Hoehrmann
174  from http://lists.w3.org/Archives/Public/www-archive/2009Apr/0001.html
175 
176  The first 128 entries are tuples of 4 bit values. The lower bits
177  are a mask that when xor'd with a byte removes the leading utf-8
178  bits. The upper bits are a character class number. The remaining
179  160 entries are a minimal deterministic finite automaton. It has
180  10 states and each state has 13 character class transitions, and
181  3 unused transitions for padding reasons. When the automaton en-
182  ters state zero, it has found a complete valid utf-8 code point;
183  if it enters state one then the input sequence is not utf-8. The
184  start state is state nine. Note the mixture of octal and double
185  for stylistic reasons.
186  The state is ignored in this code, since slice already ensures
187  that the utf8 codepoint is not malformed. */
188 static const uint8_t utf8d[] = {
189  070,070,070,070,070,070,070,070,070,070,070,070,070,070,070,070,
190  050,050,050,050,050,050,050,050,050,050,050,050,050,050,050,050,
191  030,030,030,030,030,030,030,030,030,030,030,030,030,030,030,030,
192  030,030,030,030,030,030,030,030,030,030,030,030,030,030,030,030,
193  204,204,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
194  188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
195  174,158,158,158,158,158,158,158,158,158,158,158,158,142,126,126,
196  111, 95, 95, 95, 79,207,207,207,207,207,207,207,207,207,207,207,
197 
198  0,1,1,1,8,7,6,4,5,4,3,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
199  1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
200  1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
201  1,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,
202  1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,8,7,6,4,5,4,3,2,1,1,1,1,
203 };
204 
206 static unsigned long potion_utf8char_decode(const char *s) {
207  unsigned char data, byte;
208  unsigned long unic = 0;
209  while ((byte = *s++)) {
210  if (byte >= 0x80) {
211  data = utf8d[ byte - 0x80 ];
212  byte = (byte ^ (uint8_t)(data << 4));
213  }
214  unic = (unic << 6) | byte;
215  }
216  return unic;
217 }
218 
220 inline static PN potion_str_slice_index(PN index, size_t len, int nilvalue) {
221  int i = PN_INT(index);
222  int corrected;
223  if (PN_IS_NIL(index)) {
224  corrected = nilvalue;
225  } else if (i < 0) {
226  corrected = i + len;
227  if (corrected < 0) {
228  corrected = 0;
229  }
230  } else if (i > len) {
231  corrected = len;
232  } else {
233  corrected = i;
234  }
235  return PN_NUM(corrected);
236 }
237 
243 static PN potion_str_slice(Potion *P, PN cl, PN self, PN start, PN end) {
244  char *str = PN_STR_PTR(self);
245  size_t len = potion_cp_strlen_utf8(str);
246  size_t endoffset;
247  if (!start)
248  return self;
249  else {
250  DBG_CHECK_TYPE(start, PN_TNUMBER);
251  }
252  size_t startoffset = potion_utf8char_offset(str,
253  PN_INT(potion_str_slice_index(start, len, 0)));
254  if (!end)
255  end = PN_NUM(len);
256  else {
257  DBG_CHECK_INT(end);
258  }
259  if (end < start) {
260  endoffset = potion_utf8char_offset(str,
261  PN_INT(potion_str_slice_index(start+end, len, len)));
262  } else {
263  endoffset = potion_utf8char_offset(str,
264  PN_INT(potion_str_slice_index(end, len, len)));
265  }
266  return potion_str2(P, str + startoffset, endoffset - startoffset);
267 }
268 
271 static PN potion_str_bytes(Potion *P, PN cl, PN self) {
272  return potion_byte_str2(P, PN_STR_PTR(self), PN_STR_LEN(self));
273 }
274 
279 PN potion_str_add(Potion *P, PN cl, PN self, PN x) {
280  char *s = malloc(PN_STR_LEN(self) + PN_STR_LEN(x));
281  PN str;
282  if (s == NULL) potion_allocation_error();
283  PN_MEMCPY_N(s, PN_STR_PTR(self), char, PN_STR_LEN(self));
284  PN_MEMCPY_N(s + PN_STR_LEN(self), PN_STR_PTR(x), char, PN_STR_LEN(x));
285  str = potion_str2(P, s, PN_STR_LEN(self) + PN_STR_LEN(x));
286  free(s);
287  return str;
288 }
289 
295 static PN potion_str_at(Potion *P, PN cl, PN self, PN index) {
296  size_t startoffset, endoffset;
297  ssize_t start;
298  char *str = PN_STR_PTR(potion_fwd(self));
299  DBG_CHECK_TYPE(index, PN_TNUMBER);
300  start = PN_INT(index);
301  if (start < 0) {
302  size_t len = potion_cp_strlen_utf8(str);
303  start = PN_INT(potion_str_slice_index(index, len, 0)); // supports s(-1)
304  }
305  startoffset = potion_utf8char_offset(str, start);
306  endoffset = potion_utf8char_nextchar(str, startoffset);
307  return potion_str2(P, str + startoffset, endoffset - startoffset);
308 }
309 
315 static PN potion_str_ord(Potion *P, PN cl, PN self, PN index) {
316  const char *str = PN_STR_PTR(potion_fwd(self));
317  if (PN_STR_LEN(self) > 255) goto slow;
318  else {
319  long len = potion_cp_strlen_utf8(str);
320  if (len == PN_STR_LEN(self) && PN_INT(index) < len) {
321  return PN_NUM(str[PN_INT(index)]);
322  }
323  else {
324  slow:
326  &str[potion_utf8char_offset(str, PN_INT(index))]));
327  }
328  }
329 }
330 
331 PN potion_byte_str(Potion *P, const char *str) {
332  return potion_byte_str2(P, str, strlen(str));
333 }
334 
335 PN potion_byte_str2(Potion *P, const char *str, size_t len) {
336  vPN(Bytes) s = (struct PNBytes *)potion_bytes(P, len);
337  PN_MEMCPY_N(s->chars, str, char, len);
338  s->chars[len] = '\0';
339  return (PN)s;
340 }
341 
342 PN potion_bytes(Potion *P, size_t len) {
343  size_t siz = BYTES_ALIGN(len + 1);
344  vPN(Bytes) s = PN_ALLOC_N(PN_TBYTES, struct PNBytes, siz);
345  s->siz = (PN_SIZE)siz;
346  s->len = (PN_SIZE)len;
347  return (PN)s;
348 }
349 
354  vPN(Bytes) b = (struct PNBytes *)potion_fwd(self);
355  vPN(Bytes) s = PN_ALLOC_N(PN_TBYTES, struct PNBytes, b->siz);
356  s->siz = b->siz;
357  s->len = b->len;
358  return (PN)s;
359 }
360 
361 PN_SIZE pn_printf(Potion *P, PN bytes, const char *format, ...) {
362  PN_SIZE len;
363  va_list args;
364  vPN(Bytes) s = (struct PNBytes *)potion_fwd(bytes);
365 
366  va_start(args, format);
367  len = (PN_SIZE)vsnprintf(NULL, 0, format, args);
368  va_end(args);
369 
370  if (s->len + len + 1 > s->siz) {
371  size_t siz = BYTES_ALIGN(((s->len + len) * BYTES_FACTOR) + 1);
372  PN_REALLOC(s, PN_TBYTES, struct PNBytes, siz);
373  s->siz = (PN_SIZE)siz;
374  }
375 
376  va_start(args, format);
377  vsnprintf(s->chars + s->len, len + 1, format, args);
378  va_end(args);
379 
380  s->len += len;
381  return len;
382 }
383 
384 void potion_bytes_obj_string(Potion *P, PN bytes, PN obj) {
385  potion_bytes_append(P, 0, bytes, obj ? potion_send(obj, PN_string) : PN_STR(NIL_NAME));
386 }
387 
392 PN potion_bytes_append(Potion *P, PN cl, PN self, PN str) {
393  vPN(Bytes) s = (struct PNBytes *)potion_fwd(self);
394  PN fstr = potion_fwd(str);
395  PN_SIZE len = PN_STR_LEN(fstr);
396 
397  if (s->len + len + 1 > s->siz) {
398  size_t siz = BYTES_ALIGN(((s->len + len) * BYTES_FACTOR) + 1);
399  PN_REALLOC(s, PN_TBYTES, struct PNBytes, siz);
400  s->siz = (PN_SIZE)siz;
401  }
402 
403  PN_MEMCPY_N(s->chars + s->len, PN_STR_PTR(fstr), char, len);
404  s->len += len;
405  s->chars[s->len] = '\0';
406  return self;
407 }
408 
412 static PN potion_bytes_length(Potion *P, PN cl, PN self) {
413  PN str = potion_fwd(self);
414  return PN_NUM(PN_STR_LEN(str));
415 }
416 
419 // TODO: ensure it's UTF-8 data
421  PN exist = potion_lookup_str(P, PN_STR_PTR(self = potion_fwd(self)));
422  if (exist == PN_NIL) {
423  PN_SIZE len = PN_STR_LEN(self);
424  vPN(String) s = PN_ALLOC_N(PN_TSTRING, struct PNString, len + 1);
425  s->len = len;
426  PN_MEMCPY_N(s->chars, PN_STR_PTR(self), char, len + 1);
427  potion_add_str(P, (PN)s);
428  exist = (PN)s;
429  }
430  return exist;
431 }
432 
435 static PN potion_bytes_print(Potion *P, PN cl, PN self) {
436  self = potion_fwd(self);
437  if (fwrite(PN_STR_PTR(self), 1, PN_STR_LEN(self), stdout))
438  return PN_STR0;
439  else
440  return PN_NIL;
441 }
442 
447 static PN potion_bytes_each(Potion *P, PN cl, PN self, PN block) {
448  self = potion_fwd(self);
449  char *s = PN_STR_PTR(self);
450  int i;
451  for (i = 0; i < PN_STR_LEN(self); i++) {
452  PN_CLOSURE(block)->method(P, block, P->lobby, potion_byte_str2(P, &s[i], 1));
453  }
454  return PN_NIL;
455 }
456 
461 static PN potion_bytes_at(Potion *P, PN cl, PN self, PN index) {
462  char c;
463  self = potion_fwd(self);
464  index = PN_INT(index);
465  if (index >= PN_STR_LEN(self) || (signed long)index < 0)
466  return PN_NIL;
467  c = PN_STR_PTR(self)[index];
468  return potion_byte_str2(P, &c, 1);
469 }
470 
479 static PN potion_str_cmp(Potion *P, PN cl, PN self, PN str) {
480  if (PN_IS_STR(str)) {
481  return strcmp(PN_STR_PTR(self), PN_STR_PTR(str));
482  } else {
483  return strcmp(PN_STR_PTR(self), PN_STR_PTR(potion_send(PN_string, str)));
484  }
485 }
486 
488  P->strings = PN_CALLOC_N(PN_TSTRINGS, struct PNTable, 0);
489 }
490 
492  PN str_vt = PN_VTABLE(PN_TSTRING);
493  PN byt_vt = PN_VTABLE(PN_TBYTES);
495  potion_method(str_vt, "eval", potion_str_eval, 0);
496  potion_method(str_vt, "length", potion_str_length, 0);
497  potion_method(str_vt, "number", potion_str_number, 0);
498  potion_method(str_vt, "print", potion_str_print, 0);
499  potion_method(str_vt, "string", potion_str_string, 0);
500  potion_method(str_vt, "clone", potion_str_clone, 0);
501  potion_method(str_vt, "slice", potion_str_slice, "start=N|end=N");
502  potion_method(str_vt, "bytes", potion_str_bytes, 0);
503  potion_method(str_vt, "+", potion_str_add, "str=S");
504  potion_method(str_vt, "ord", potion_str_ord, "|index=N");
505  potion_method(str_vt, "cmp", potion_str_cmp, "str=o");
506 
508  potion_method(byt_vt, "append", potion_bytes_append, "str=S");
509  potion_method(byt_vt, "length", potion_bytes_length, 0);
510  potion_method(byt_vt, "print", potion_bytes_print, 0);
511  potion_method(byt_vt, "string", potion_bytes_string, 0);
512  potion_method(byt_vt, "clone", potion_bytes_clone, 0);
513  potion_method(byt_vt, "ord", potion_str_ord, 0);
514  potion_method(byt_vt, "each", potion_bytes_each, "block=&");
515 }
static PN potion_str_ord(Potion *P, PN cl, PN self, PN index)
Definition: string.c:315
static size_t potion_utf8char_nextchar(const char *s, size_t offset)
returns byte position of next utf8 char after s[offset]
Definition: string.c:165
#define PN_IS_STR(v)
Definition: potion.h:175
#define DBG_CHECK_TYPE(obj, type)
Definition: potion.h:201
byte strings are raw character data, volatile, may be appended/changed.
Definition: potion.h:347
klib hash table library based on double hashing http://en.wikipedia.org/wiki/Double_hashing ...
#define PN_TSTRING
Definition: potion.h:112
PN potion_str_add(Potion *P, PN cl, PN self, PN x)
Definition: string.c:279
static PN potion_str_slice(Potion *P, PN cl, PN self, PN start, PN end)
Definition: string.c:243
static PN potion_str_at(Potion *P, PN cl, PN self, PN index)
Definition: string.c:295
#define PN_ALLOC_N(V, T, C)
Definition: internal.h:13
#define PN_CLOSURE(x)
Definition: potion.h:225
#define PN_REALLOC(X, V, T, N)
Definition: internal.h:15
PN potion_str(Potion *P, const char *str)
Definition: string.c:33
#define NIL_NAME
Definition: potion.h:149
static const uint8_t utf8d[]
Definition: string.c:188
#define potion_method(RCV, MSG, FN, SIG)
Definition: potion.h:789
void potion_bytes_obj_string(Potion *P, PN bytes, PN obj)
Definition: string.c:384
PN potion_bytes_append(Potion *P, PN cl, PN self, PN str)
Definition: string.c:392
PN_SIZE pn_printf(Potion *P, PN bytes, const char *format,...)
Definition: string.c:361
PN potion_str2(Potion *P, char *str, size_t len)
Definition: string.c:47
void potion_add_str(Potion *P, PN s)
Definition: string.c:20
#define PN_STR_LEN(x)
Definition: potion.h:223
static PN potion_fwd(PN)
the potion type is the 't' in the vtable tuple (m,t)
Definition: potion.h:570
#define kh_end(h)
Definition: khash.h:229
void potion_type_call_is(PN vt, PN cl)
sets the default call method of the PNVtable
Definition: objmodel.c:230
static PN potion_bytes_at(Potion *P, PN cl, PN self, PN index)
Definition: string.c:461
static size_t potion_utf8char_offset(const char *s, size_t index)
returns byte position of the index-th utf8 char
Definition: string.c:155
#define kh_put(name, h, k, r)
Definition: khash.h:221
PN PN_string
Definition: internal.c:14
PN potion_byte_str2(Potion *P, const char *str, size_t len)
Definition: string.c:335
#define PN_TBYTES
Definition: potion.h:121
#define PN_STR(x)
Definition: potion.h:219
#define PN_INT(x)
Definition: potion.h:214
#define PN_ZERO
Definition: potion.h:140
#define PN_NUM(i)
Definition: potion.h:213
static PN potion_str_eval(Potion *P, PN cl, PN self)
Definition: string.c:106
#define BYTES_FACTOR
Definition: string.c:16
unsigned int PN_SIZE
Definition: potion.h:79
static PN potion_bytes_print(Potion *P, PN cl, PN self)
Definition: string.c:435
#define PN_IS_NIL(v)
Definition: potion.h:169
PN potion_str_format(Potion *P, const char *format,...)
Definition: string.c:81
PN_SIZE siz
Definition: potion.h:350
PN lobby
root namespace
Definition: potion.h:657
static PN potion_bytes_length(Potion *P, PN cl, PN self)
Definition: string.c:412
static unsigned long potion_utf8char_decode(const char *s)
decode the utf8 codepoint at s, i.e. ord
Definition: string.c:206
PN potion_bytes_clone(Potion *P, PN cl, PN self)
Definition: string.c:353
static PN potion_str_length(Potion *P, PN cl, PN self)
Definition: string.c:100
the table class, based on khash
Definition: table.h:40
static PN potion_str_print(Potion *P, PN cl, PN self)
Definition: string.c:146
PN_SIZE len
Definition: potion.h:349
static PN potion_bytes_each(Potion *P, PN cl, PN self, PN block)
Definition: string.c:447
PN potion_strcat(Potion *P, char *str, char *str2)
Definition: string.c:64
#define PN_MEMCPY_N(X, Y, T, N)
Definition: internal.h:22
PN potion_eval(Potion *P, PN bytes)
Definition: compile.c:1415
static PN potion_str_clone(Potion *P, PN cl, PN self)
Definition: string.c:139
strings are immutable UTF-8, the ID is incremental and they may be garbage collected.
Definition: potion.h:337
PN potion_bytes_string(Potion *P, PN cl, PN self)
Definition: string.c:420
size_t potion_cp_strlen_utf8(const char *_s)
wonderful utf-8 counting trickery by colin percival
Definition: contrib.c:17
#define DBG_CHECK_INT(obj)
Definition: potion.h:203
PN potion_bytes(Potion *P, size_t len)
Definition: string.c:342
static PN potion_str_number(Potion *P, PN cl, PN self)
Definition: string.c:112
non-API internal parts
PN potion_strtod(Potion *P, char *str, int len)
Convert string to double.
Definition: number.c:24
static PN potion_str_slice_index(PN index, size_t len, int nilvalue)
helper function for potion_str_slice to fix index.
Definition: string.c:220
#define PN_ATOI(X, N, B)
Definition: internal.h:51
#define PN_TSTRINGS
Definition: potion.h:127
static PN potion_str_bytes(Potion *P, PN cl, PN self)
Definition: string.c:271
void potion_str_hash_init(Potion *P)
Definition: string.c:487
the global interpreter state P. currently singleton (not threads yet)
Definition: potion.h:653
#define kh_key(name, h, x)
Definition: khash.h:226
The p2 API.
PN potion_byte_str(Potion *P, const char *str)
Definition: string.c:331
#define PN_QUICK_FWD(t, obj)
PN_QUICK_FWD - doing a single fwd check after a possible realloc.
Definition: potion.h:558
the central table type, based on core/khash.h
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
Definition: potion.h:781
void potion_str_init(Potion *P)
Definition: string.c:491
#define BYTES_ALIGN(len)
Definition: string.c:18
void potion_allocation_error(void)
Definition: internal.c:305
#define vPN(t)
Definition: buffile.c:34
volatile _PN PN
Definition: potion.h:81
PN PN_STR0
Definition: internal.c:18
#define PN_NIL
Definition: potion.h:139
#define PN_TNUMBER
Definition: potion.h:108
#define PN_CALLOC_N(V, T, C)
Definition: internal.h:14
#define PN_FUNC(f, s)
Definition: potion.h:228
struct PNTable * strings
table of all strings
Definition: potion.h:656
static PN potion_str_string(Potion *P, PN cl, PN self)
Definition: string.c:133
static PN potion_str_cmp(Potion *P, PN cl, PN self, PN str)
Definition: string.c:479
const u8 args
Definition: compile.c:31
#define PN_STR_PTR(x)
Definition: potion.h:222
#define PN_VTABLE(t)
Definition: potion.h:136
PN potion_lookup_str(Potion *P, const char *str)
Definition: string.c:26
#define kh_get(name, h, k)
Definition: khash.h:222