"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/vendor/lua/src/lobject.c" (1 Oct 2021, 18890 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2 ** $Id: lobject.c $
    3 ** Some generic functions over Lua objects
    4 ** See Copyright Notice in lua.h
    5 */
    6 
    7 #define lobject_c
    8 #define LUA_CORE
    9 
   10 #include "lprefix.h"
   11 
   12 
   13 #include <locale.h>
   14 #include <math.h>
   15 #include <stdarg.h>
   16 #include <stdio.h>
   17 #include <stdlib.h>
   18 #include <string.h>
   19 
   20 #include "lua.h"
   21 
   22 #include "lctype.h"
   23 #include "ldebug.h"
   24 #include "ldo.h"
   25 #include "lmem.h"
   26 #include "lobject.h"
   27 #include "lstate.h"
   28 #include "lstring.h"
   29 #include "lvm.h"
   30 
   31 
   32 /*
   33 ** Computes ceil(log2(x))
   34 */
   35 int luaO_ceillog2 (unsigned int x) {
   36   static const lu_byte log_2[256] = {  /* log_2[i] = ceil(log2(i - 1)) */
   37     0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
   38     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
   39     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   40     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   41     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
   42     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
   43     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
   44     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
   45   };
   46   int l = 0;
   47   x--;
   48   while (x >= 256) { l += 8; x >>= 8; }
   49   return l + log_2[x];
   50 }
   51 
   52 
   53 static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
   54                                                    lua_Integer v2) {
   55   switch (op) {
   56     case LUA_OPADD: return intop(+, v1, v2);
   57     case LUA_OPSUB:return intop(-, v1, v2);
   58     case LUA_OPMUL:return intop(*, v1, v2);
   59     case LUA_OPMOD: return luaV_mod(L, v1, v2);
   60     case LUA_OPIDIV: return luaV_idiv(L, v1, v2);
   61     case LUA_OPBAND: return intop(&, v1, v2);
   62     case LUA_OPBOR: return intop(|, v1, v2);
   63     case LUA_OPBXOR: return intop(^, v1, v2);
   64     case LUA_OPSHL: return luaV_shiftl(v1, v2);
   65     case LUA_OPSHR: return luaV_shiftl(v1, -v2);
   66     case LUA_OPUNM: return intop(-, 0, v1);
   67     case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1);
   68     default: lua_assert(0); return 0;
   69   }
   70 }
   71 
   72 
   73 static lua_Number numarith (lua_State *L, int op, lua_Number v1,
   74                                                   lua_Number v2) {
   75   switch (op) {
   76     case LUA_OPADD: return luai_numadd(L, v1, v2);
   77     case LUA_OPSUB: return luai_numsub(L, v1, v2);
   78     case LUA_OPMUL: return luai_nummul(L, v1, v2);
   79     case LUA_OPDIV: return luai_numdiv(L, v1, v2);
   80     case LUA_OPPOW: return luai_numpow(L, v1, v2);
   81     case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
   82     case LUA_OPUNM: return luai_numunm(L, v1);
   83     case LUA_OPMOD: return luaV_modf(L, v1, v2);
   84     default: lua_assert(0); return 0;
   85   }
   86 }
   87 
   88 
   89 int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2,
   90                    TValue *res) {
   91   switch (op) {
   92     case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
   93     case LUA_OPSHL: case LUA_OPSHR:
   94     case LUA_OPBNOT: {  /* operate only on integers */
   95       lua_Integer i1; lua_Integer i2;
   96       if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) {
   97         setivalue(res, intarith(L, op, i1, i2));
   98         return 1;
   99       }
  100       else return 0;  /* fail */
  101     }
  102     case LUA_OPDIV: case LUA_OPPOW: {  /* operate only on floats */
  103       lua_Number n1; lua_Number n2;
  104       if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
  105         setfltvalue(res, numarith(L, op, n1, n2));
  106         return 1;
  107       }
  108       else return 0;  /* fail */
  109     }
  110     default: {  /* other operations */
  111       lua_Number n1; lua_Number n2;
  112       if (ttisinteger(p1) && ttisinteger(p2)) {
  113         setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
  114         return 1;
  115       }
  116       else if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
  117         setfltvalue(res, numarith(L, op, n1, n2));
  118         return 1;
  119       }
  120       else return 0;  /* fail */
  121     }
  122   }
  123 }
  124 
  125 
  126 void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
  127                  StkId res) {
  128   if (!luaO_rawarith(L, op, p1, p2, s2v(res))) {
  129     /* could not perform raw operation; try metamethod */
  130     luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
  131   }
  132 }
  133 
  134 
  135 int luaO_hexavalue (int c) {
  136   if (lisdigit(c)) return c - '0';
  137   else return (ltolower(c) - 'a') + 10;
  138 }
  139 
  140 
  141 static int isneg (const char **s) {
  142   if (**s == '-') { (*s)++; return 1; }
  143   else if (**s == '+') (*s)++;
  144   return 0;
  145 }
  146 
  147 
  148 
  149 /*
  150 ** {==================================================================
  151 ** Lua's implementation for 'lua_strx2number'
  152 ** ===================================================================
  153 */
  154 
  155 #if !defined(lua_strx2number)
  156 
  157 /* maximum number of significant digits to read (to avoid overflows
  158    even with single floats) */
  159 #define MAXSIGDIG   30
  160 
  161 /*
  162 ** convert a hexadecimal numeric string to a number, following
  163 ** C99 specification for 'strtod'
  164 */
  165 static lua_Number lua_strx2number (const char *s, char **endptr) {
  166   int dot = lua_getlocaledecpoint();
  167   lua_Number r = 0.0;  /* result (accumulator) */
  168   int sigdig = 0;  /* number of significant digits */
  169   int nosigdig = 0;  /* number of non-significant digits */
  170   int e = 0;  /* exponent correction */
  171   int neg;  /* 1 if number is negative */
  172   int hasdot = 0;  /* true after seen a dot */
  173   *endptr = cast_charp(s);  /* nothing is valid yet */
  174   while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
  175   neg = isneg(&s);  /* check sign */
  176   if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')))  /* check '0x' */
  177     return 0.0;  /* invalid format (no '0x') */
  178   for (s += 2; ; s++) {  /* skip '0x' and read numeral */
  179     if (*s == dot) {
  180       if (hasdot) break;  /* second dot? stop loop */
  181       else hasdot = 1;
  182     }
  183     else if (lisxdigit(cast_uchar(*s))) {
  184       if (sigdig == 0 && *s == '0')  /* non-significant digit (zero)? */
  185         nosigdig++;
  186       else if (++sigdig <= MAXSIGDIG)  /* can read it without overflow? */
  187           r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
  188       else e++; /* too many digits; ignore, but still count for exponent */
  189       if (hasdot) e--;  /* decimal digit? correct exponent */
  190     }
  191     else break;  /* neither a dot nor a digit */
  192   }
  193   if (nosigdig + sigdig == 0)  /* no digits? */
  194     return 0.0;  /* invalid format */
  195   *endptr = cast_charp(s);  /* valid up to here */
  196   e *= 4;  /* each digit multiplies/divides value by 2^4 */
  197   if (*s == 'p' || *s == 'P') {  /* exponent part? */
  198     int exp1 = 0;  /* exponent value */
  199     int neg1;  /* exponent sign */
  200     s++;  /* skip 'p' */
  201     neg1 = isneg(&s);  /* sign */
  202     if (!lisdigit(cast_uchar(*s)))
  203       return 0.0;  /* invalid; must have at least one digit */
  204     while (lisdigit(cast_uchar(*s)))  /* read exponent */
  205       exp1 = exp1 * 10 + *(s++) - '0';
  206     if (neg1) exp1 = -exp1;
  207     e += exp1;
  208     *endptr = cast_charp(s);  /* valid up to here */
  209   }
  210   if (neg) r = -r;
  211   return l_mathop(ldexp)(r, e);
  212 }
  213 
  214 #endif
  215 /* }====================================================== */
  216 
  217 
  218 /* maximum length of a numeral to be converted to a number */
  219 #if !defined (L_MAXLENNUM)
  220 #define L_MAXLENNUM 200
  221 #endif
  222 
  223 /*
  224 ** Convert string 's' to a Lua number (put in 'result'). Return NULL on
  225 ** fail or the address of the ending '\0' on success. ('mode' == 'x')
  226 ** means a hexadecimal numeral.
  227 */
  228 static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
  229   char *endptr;
  230   *result = (mode == 'x') ? lua_strx2number(s, &endptr)  /* try to convert */
  231                           : lua_str2number(s, &endptr);
  232   if (endptr == s) return NULL;  /* nothing recognized? */
  233   while (lisspace(cast_uchar(*endptr))) endptr++;  /* skip trailing spaces */
  234   return (*endptr == '\0') ? endptr : NULL;  /* OK iff no trailing chars */
  235 }
  236 
  237 
  238 /*
  239 ** Convert string 's' to a Lua number (put in 'result') handling the
  240 ** current locale.
  241 ** This function accepts both the current locale or a dot as the radix
  242 ** mark. If the conversion fails, it may mean number has a dot but
  243 ** locale accepts something else. In that case, the code copies 's'
  244 ** to a buffer (because 's' is read-only), changes the dot to the
  245 ** current locale radix mark, and tries to convert again.
  246 ** The variable 'mode' checks for special characters in the string:
  247 ** - 'n' means 'inf' or 'nan' (which should be rejected)
  248 ** - 'x' means a hexadecimal numeral
  249 ** - '.' just optimizes the search for the common case (no special chars)
  250 */
  251 static const char *l_str2d (const char *s, lua_Number *result) {
  252   const char *endptr;
  253   const char *pmode = strpbrk(s, ".xXnN");  /* look for special chars */
  254   int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
  255   if (mode == 'n')  /* reject 'inf' and 'nan' */
  256     return NULL;
  257   endptr = l_str2dloc(s, result, mode);  /* try to convert */
  258   if (endptr == NULL) {  /* failed? may be a different locale */
  259     char buff[L_MAXLENNUM + 1];
  260     const char *pdot = strchr(s, '.');
  261     if (pdot == NULL || strlen(s) > L_MAXLENNUM)
  262       return NULL;  /* string too long or no dot; fail */
  263     strcpy(buff, s);  /* copy string to buffer */
  264     buff[pdot - s] = lua_getlocaledecpoint();  /* correct decimal point */
  265     endptr = l_str2dloc(buff, result, mode);  /* try again */
  266     if (endptr != NULL)
  267       endptr = s + (endptr - buff);  /* make relative to 's' */
  268   }
  269   return endptr;
  270 }
  271 
  272 
  273 #define MAXBY10     cast(lua_Unsigned, LUA_MAXINTEGER / 10)
  274 #define MAXLASTD    cast_int(LUA_MAXINTEGER % 10)
  275 
  276 static const char *l_str2int (const char *s, lua_Integer *result) {
  277   lua_Unsigned a = 0;
  278   int empty = 1;
  279   int neg;
  280   while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
  281   neg = isneg(&s);
  282   if (s[0] == '0' &&
  283       (s[1] == 'x' || s[1] == 'X')) {  /* hex? */
  284     s += 2;  /* skip '0x' */
  285     for (; lisxdigit(cast_uchar(*s)); s++) {
  286       a = a * 16 + luaO_hexavalue(*s);
  287       empty = 0;
  288     }
  289   }
  290   else {  /* decimal */
  291     for (; lisdigit(cast_uchar(*s)); s++) {
  292       int d = *s - '0';
  293       if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg))  /* overflow? */
  294         return NULL;  /* do not accept it (as integer) */
  295       a = a * 10 + d;
  296       empty = 0;
  297     }
  298   }
  299   while (lisspace(cast_uchar(*s))) s++;  /* skip trailing spaces */
  300   if (empty || *s != '\0') return NULL;  /* something wrong in the numeral */
  301   else {
  302     *result = l_castU2S((neg) ? 0u - a : a);
  303     return s;
  304   }
  305 }
  306 
  307 
  308 size_t luaO_str2num (const char *s, TValue *o) {
  309   lua_Integer i; lua_Number n;
  310   const char *e;
  311   if ((e = l_str2int(s, &i)) != NULL) {  /* try as an integer */
  312     setivalue(o, i);
  313   }
  314   else if ((e = l_str2d(s, &n)) != NULL) {  /* else try as a float */
  315     setfltvalue(o, n);
  316   }
  317   else
  318     return 0;  /* conversion failed */
  319   return (e - s) + 1;  /* success; return string size */
  320 }
  321 
  322 
  323 int luaO_utf8esc (char *buff, unsigned long x) {
  324   int n = 1;  /* number of bytes put in buffer (backwards) */
  325   lua_assert(x <= 0x7FFFFFFFu);
  326   if (x < 0x80)  /* ascii? */
  327     buff[UTF8BUFFSZ - 1] = cast_char(x);
  328   else {  /* need continuation bytes */
  329     unsigned int mfb = 0x3f;  /* maximum that fits in first byte */
  330     do {  /* add continuation bytes */
  331       buff[UTF8BUFFSZ - (n++)] = cast_char(0x80 | (x & 0x3f));
  332       x >>= 6;  /* remove added bits */
  333       mfb >>= 1;  /* now there is one less bit available in first byte */
  334     } while (x > mfb);  /* still needs continuation byte? */
  335     buff[UTF8BUFFSZ - n] = cast_char((~mfb << 1) | x);  /* add first byte */
  336   }
  337   return n;
  338 }
  339 
  340 
  341 /*
  342 ** Maximum length of the conversion of a number to a string. Must be
  343 ** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT.
  344 ** (For a long long int, this is 19 digits plus a sign and a final '\0',
  345 ** adding to 21. For a long double, it can go to a sign, 33 digits,
  346 ** the dot, an exponent letter, an exponent sign, 5 exponent digits,
  347 ** and a final '\0', adding to 43.)
  348 */
  349 #define MAXNUMBER2STR   44
  350 
  351 
  352 /*
  353 ** Convert a number object to a string, adding it to a buffer
  354 */
  355 static int tostringbuff (TValue *obj, char *buff) {
  356   int len;
  357   lua_assert(ttisnumber(obj));
  358   if (ttisinteger(obj))
  359     len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj));
  360   else {
  361     len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj));
  362     if (buff[strspn(buff, "-0123456789")] == '\0') {  /* looks like an int? */
  363       buff[len++] = lua_getlocaledecpoint();
  364       buff[len++] = '0';  /* adds '.0' to result */
  365     }
  366   }
  367   return len;
  368 }
  369 
  370 
  371 /*
  372 ** Convert a number object to a Lua string, replacing the value at 'obj'
  373 */
  374 void luaO_tostring (lua_State *L, TValue *obj) {
  375   char buff[MAXNUMBER2STR];
  376   int len = tostringbuff(obj, buff);
  377   setsvalue(L, obj, luaS_newlstr(L, buff, len));
  378 }
  379 
  380 
  381 
  382 
  383 /*
  384 ** {==================================================================
  385 ** 'luaO_pushvfstring'
  386 ** ===================================================================
  387 */
  388 
  389 /* size for buffer space used by 'luaO_pushvfstring' */
  390 #define BUFVFS      200
  391 
  392 /* buffer used by 'luaO_pushvfstring' */
  393 typedef struct BuffFS {
  394   lua_State *L;
  395   int pushed;  /* number of string pieces already on the stack */
  396   int blen;  /* length of partial string in 'space' */
  397   char space[BUFVFS];  /* holds last part of the result */
  398 } BuffFS;
  399 
  400 
  401 /*
  402 ** Push given string to the stack, as part of the buffer, and
  403 ** join the partial strings in the stack into one.
  404 */
  405 static void pushstr (BuffFS *buff, const char *str, size_t l) {
  406   lua_State *L = buff->L;
  407   setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
  408   L->top++;  /* may use one extra slot */
  409   buff->pushed++;
  410   luaV_concat(L, buff->pushed);  /* join partial results into one */
  411   buff->pushed = 1;
  412 }
  413 
  414 
  415 /*
  416 ** empty the buffer space into the stack
  417 */
  418 static void clearbuff (BuffFS *buff) {
  419   pushstr(buff, buff->space, buff->blen);  /* push buffer contents */
  420   buff->blen = 0;  /* space now is empty */
  421 }
  422 
  423 
  424 /*
  425 ** Get a space of size 'sz' in the buffer. If buffer has not enough
  426 ** space, empty it. 'sz' must fit in an empty buffer.
  427 */
  428 static char *getbuff (BuffFS *buff, int sz) {
  429   lua_assert(buff->blen <= BUFVFS); lua_assert(sz <= BUFVFS);
  430   if (sz > BUFVFS - buff->blen)  /* not enough space? */
  431     clearbuff(buff);
  432   return buff->space + buff->blen;
  433 }
  434 
  435 
  436 #define addsize(b,sz)   ((b)->blen += (sz))
  437 
  438 
  439 /*
  440 ** Add 'str' to the buffer. If string is larger than the buffer space,
  441 ** push the string directly to the stack.
  442 */
  443 static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
  444   if (slen <= BUFVFS) {  /* does string fit into buffer? */
  445     char *bf = getbuff(buff, cast_int(slen));
  446     memcpy(bf, str, slen);  /* add string to buffer */
  447     addsize(buff, cast_int(slen));
  448   }
  449   else {  /* string larger than buffer */
  450     clearbuff(buff);  /* string comes after buffer's content */
  451     pushstr(buff, str, slen);  /* push string */
  452   }
  453 }
  454 
  455 
  456 /*
  457 ** Add a number to the buffer.
  458 */
  459 static void addnum2buff (BuffFS *buff, TValue *num) {
  460   char *numbuff = getbuff(buff, MAXNUMBER2STR);
  461   int len = tostringbuff(num, numbuff);  /* format number into 'numbuff' */
  462   addsize(buff, len);
  463 }
  464 
  465 
  466 /*
  467 ** this function handles only '%d', '%c', '%f', '%p', '%s', and '%%'
  468    conventional formats, plus Lua-specific '%I' and '%U'
  469 */
  470 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
  471   BuffFS buff;  /* holds last part of the result */
  472   const char *e;  /* points to next '%' */
  473   buff.pushed = buff.blen = 0;
  474   buff.L = L;
  475   while ((e = strchr(fmt, '%')) != NULL) {
  476     addstr2buff(&buff, fmt, e - fmt);  /* add 'fmt' up to '%' */
  477     switch (*(e + 1)) {  /* conversion specifier */
  478       case 's': {  /* zero-terminated string */
  479         const char *s = va_arg(argp, char *);
  480         if (s == NULL) s = "(null)";
  481         addstr2buff(&buff, s, strlen(s));
  482         break;
  483       }
  484       case 'c': {  /* an 'int' as a character */
  485         char c = cast_uchar(va_arg(argp, int));
  486         addstr2buff(&buff, &c, sizeof(char));
  487         break;
  488       }
  489       case 'd': {  /* an 'int' */
  490         TValue num;
  491         setivalue(&num, va_arg(argp, int));
  492         addnum2buff(&buff, &num);
  493         break;
  494       }
  495       case 'I': {  /* a 'lua_Integer' */
  496         TValue num;
  497         setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt)));
  498         addnum2buff(&buff, &num);
  499         break;
  500       }
  501       case 'f': {  /* a 'lua_Number' */
  502         TValue num;
  503         setfltvalue(&num, cast_num(va_arg(argp, l_uacNumber)));
  504         addnum2buff(&buff, &num);
  505         break;
  506       }
  507       case 'p': {  /* a pointer */
  508         const int sz = 3 * sizeof(void*) + 8; /* enough space for '%p' */
  509         char *bf = getbuff(&buff, sz);
  510         void *p = va_arg(argp, void *);
  511         int len = lua_pointer2str(bf, sz, p);
  512         addsize(&buff, len);
  513         break;
  514       }
  515       case 'U': {  /* a 'long' as a UTF-8 sequence */
  516         char bf[UTF8BUFFSZ];
  517         int len = luaO_utf8esc(bf, va_arg(argp, long));
  518         addstr2buff(&buff, bf + UTF8BUFFSZ - len, len);
  519         break;
  520       }
  521       case '%': {
  522         addstr2buff(&buff, "%", 1);
  523         break;
  524       }
  525       default: {
  526         luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'",
  527                          *(e + 1));
  528       }
  529     }
  530     fmt = e + 2;  /* skip '%' and the specifier */
  531   }
  532   addstr2buff(&buff, fmt, strlen(fmt));  /* rest of 'fmt' */
  533   clearbuff(&buff);  /* empty buffer into the stack */
  534   lua_assert(buff.pushed == 1);
  535   return svalue(s2v(L->top - 1));
  536 }
  537 
  538 
  539 const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
  540   const char *msg;
  541   va_list argp;
  542   va_start(argp, fmt);
  543   msg = luaO_pushvfstring(L, fmt, argp);
  544   va_end(argp);
  545   return msg;
  546 }
  547 
  548 /* }================================================================== */
  549 
  550 
  551 #define RETS    "..."
  552 #define PRE "[string \""
  553 #define POS "\"]"
  554 
  555 #define addstr(a,b,l)   ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
  556 
  557 void luaO_chunkid (char *out, const char *source, size_t srclen) {
  558   size_t bufflen = LUA_IDSIZE;  /* free space in buffer */
  559   if (*source == '=') {  /* 'literal' source */
  560     if (srclen <= bufflen)  /* small enough? */
  561       memcpy(out, source + 1, srclen * sizeof(char));
  562     else {  /* truncate it */
  563       addstr(out, source + 1, bufflen - 1);
  564       *out = '\0';
  565     }
  566   }
  567   else if (*source == '@') {  /* file name */
  568     if (srclen <= bufflen)  /* small enough? */
  569       memcpy(out, source + 1, srclen * sizeof(char));
  570     else {  /* add '...' before rest of name */
  571       addstr(out, RETS, LL(RETS));
  572       bufflen -= LL(RETS);
  573       memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char));
  574     }
  575   }
  576   else {  /* string; format as [string "source"] */
  577     const char *nl = strchr(source, '\n');  /* find first new line (if any) */
  578     addstr(out, PRE, LL(PRE));  /* add prefix */
  579     bufflen -= LL(PRE RETS POS) + 1;  /* save space for prefix+suffix+'\0' */
  580     if (srclen < bufflen && nl == NULL) {  /* small one-line source? */
  581       addstr(out, source, srclen);  /* keep it */
  582     }
  583     else {
  584       if (nl != NULL) srclen = nl - source;  /* stop at first newline */
  585       if (srclen > bufflen) srclen = bufflen;
  586       addstr(out, source, srclen);
  587       addstr(out, RETS, LL(RETS));
  588     }
  589     memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
  590   }
  591 }
  592