116a5fed65808adf648004b34f98718301d718fa2darylm/* 216a5fed65808adf648004b34f98718301d718fa2darylm** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ 316a5fed65808adf648004b34f98718301d718fa2darylm** Some generic functions over Lua objects 416a5fed65808adf648004b34f98718301d718fa2darylm** See Copyright Notice in lua.h 516a5fed65808adf648004b34f98718301d718fa2darylm*/ 616a5fed65808adf648004b34f98718301d718fa2darylm 716a5fed65808adf648004b34f98718301d718fa2darylm#include <stdarg.h> 816a5fed65808adf648004b34f98718301d718fa2darylm#include <stdio.h> 916a5fed65808adf648004b34f98718301d718fa2darylm#include <stdlib.h> 1016a5fed65808adf648004b34f98718301d718fa2darylm#include <string.h> 1116a5fed65808adf648004b34f98718301d718fa2darylm 1216a5fed65808adf648004b34f98718301d718fa2darylm#define lobject_c 1316a5fed65808adf648004b34f98718301d718fa2darylm#define LUA_CORE 1416a5fed65808adf648004b34f98718301d718fa2darylm 1516a5fed65808adf648004b34f98718301d718fa2darylm#include "lua.h" 1616a5fed65808adf648004b34f98718301d718fa2darylm 1716a5fed65808adf648004b34f98718301d718fa2darylm#include "lctype.h" 1816a5fed65808adf648004b34f98718301d718fa2darylm#include "ldebug.h" 1916a5fed65808adf648004b34f98718301d718fa2darylm#include "ldo.h" 2016a5fed65808adf648004b34f98718301d718fa2darylm#include "lmem.h" 2116a5fed65808adf648004b34f98718301d718fa2darylm#include "lobject.h" 2216a5fed65808adf648004b34f98718301d718fa2darylm#include "lstate.h" 2316a5fed65808adf648004b34f98718301d718fa2darylm#include "lstring.h" 2416a5fed65808adf648004b34f98718301d718fa2darylm#include "lvm.h" 2516a5fed65808adf648004b34f98718301d718fa2darylm 2616a5fed65808adf648004b34f98718301d718fa2darylm 2716a5fed65808adf648004b34f98718301d718fa2darylm 2816a5fed65808adf648004b34f98718301d718fa2darylmLUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; 2916a5fed65808adf648004b34f98718301d718fa2darylm 3016a5fed65808adf648004b34f98718301d718fa2darylm 3116a5fed65808adf648004b34f98718301d718fa2darylm/* 3216a5fed65808adf648004b34f98718301d718fa2darylm** converts an integer to a "floating point byte", represented as 3316a5fed65808adf648004b34f98718301d718fa2darylm** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if 3416a5fed65808adf648004b34f98718301d718fa2darylm** eeeee != 0 and (xxx) otherwise. 3516a5fed65808adf648004b34f98718301d718fa2darylm*/ 3616a5fed65808adf648004b34f98718301d718fa2darylmint luaO_int2fb (unsigned int x) { 3716a5fed65808adf648004b34f98718301d718fa2darylm int e = 0; /* exponent */ 3816a5fed65808adf648004b34f98718301d718fa2darylm if (x < 8) return x; 3916a5fed65808adf648004b34f98718301d718fa2darylm while (x >= 0x10) { 4016a5fed65808adf648004b34f98718301d718fa2darylm x = (x+1) >> 1; 4116a5fed65808adf648004b34f98718301d718fa2darylm e++; 4216a5fed65808adf648004b34f98718301d718fa2darylm } 4316a5fed65808adf648004b34f98718301d718fa2darylm return ((e+1) << 3) | (cast_int(x) - 8); 4416a5fed65808adf648004b34f98718301d718fa2darylm} 4516a5fed65808adf648004b34f98718301d718fa2darylm 4616a5fed65808adf648004b34f98718301d718fa2darylm 4716a5fed65808adf648004b34f98718301d718fa2darylm/* converts back */ 4816a5fed65808adf648004b34f98718301d718fa2darylmint luaO_fb2int (int x) { 4916a5fed65808adf648004b34f98718301d718fa2darylm int e = (x >> 3) & 0x1f; 5016a5fed65808adf648004b34f98718301d718fa2darylm if (e == 0) return x; 5116a5fed65808adf648004b34f98718301d718fa2darylm else return ((x & 7) + 8) << (e - 1); 5216a5fed65808adf648004b34f98718301d718fa2darylm} 5316a5fed65808adf648004b34f98718301d718fa2darylm 5416a5fed65808adf648004b34f98718301d718fa2darylm 5516a5fed65808adf648004b34f98718301d718fa2darylmint luaO_ceillog2 (unsigned int x) { 5616a5fed65808adf648004b34f98718301d718fa2darylm static const lu_byte log_2[256] = { 5716a5fed65808adf648004b34f98718301d718fa2darylm 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, 5816a5fed65808adf648004b34f98718301d718fa2darylm 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, 5916a5fed65808adf648004b34f98718301d718fa2darylm 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, 6016a5fed65808adf648004b34f98718301d718fa2darylm 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, 6116a5fed65808adf648004b34f98718301d718fa2darylm 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, 6216a5fed65808adf648004b34f98718301d718fa2darylm 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, 6316a5fed65808adf648004b34f98718301d718fa2darylm 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, 6416a5fed65808adf648004b34f98718301d718fa2darylm 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 6516a5fed65808adf648004b34f98718301d718fa2darylm }; 6616a5fed65808adf648004b34f98718301d718fa2darylm int l = 0; 6716a5fed65808adf648004b34f98718301d718fa2darylm x--; 6816a5fed65808adf648004b34f98718301d718fa2darylm while (x >= 256) { l += 8; x >>= 8; } 6916a5fed65808adf648004b34f98718301d718fa2darylm return l + log_2[x]; 7016a5fed65808adf648004b34f98718301d718fa2darylm} 7116a5fed65808adf648004b34f98718301d718fa2darylm 7216a5fed65808adf648004b34f98718301d718fa2darylm 7316a5fed65808adf648004b34f98718301d718fa2darylmlua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { 7416a5fed65808adf648004b34f98718301d718fa2darylm switch (op) { 7516a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPADD: return luai_numadd(NULL, v1, v2); 7616a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPSUB: return luai_numsub(NULL, v1, v2); 7716a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPMUL: return luai_nummul(NULL, v1, v2); 7816a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); 7916a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPMOD: return luai_nummod(NULL, v1, v2); 8016a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPPOW: return luai_numpow(NULL, v1, v2); 8116a5fed65808adf648004b34f98718301d718fa2darylm case LUA_OPUNM: return luai_numunm(NULL, v1); 8216a5fed65808adf648004b34f98718301d718fa2darylm default: lua_assert(0); return 0; 8316a5fed65808adf648004b34f98718301d718fa2darylm } 8416a5fed65808adf648004b34f98718301d718fa2darylm} 8516a5fed65808adf648004b34f98718301d718fa2darylm 8616a5fed65808adf648004b34f98718301d718fa2darylm 8716a5fed65808adf648004b34f98718301d718fa2darylmint luaO_hexavalue (int c) { 8816a5fed65808adf648004b34f98718301d718fa2darylm if (lisdigit(c)) return c - '0'; 8916a5fed65808adf648004b34f98718301d718fa2darylm else return ltolower(c) - 'a' + 10; 9016a5fed65808adf648004b34f98718301d718fa2darylm} 9116a5fed65808adf648004b34f98718301d718fa2darylm 9216a5fed65808adf648004b34f98718301d718fa2darylm 9316a5fed65808adf648004b34f98718301d718fa2darylm#if !defined(lua_strx2number) 9416a5fed65808adf648004b34f98718301d718fa2darylm 9516a5fed65808adf648004b34f98718301d718fa2darylm#include <math.h> 9616a5fed65808adf648004b34f98718301d718fa2darylm 9716a5fed65808adf648004b34f98718301d718fa2darylm 9816a5fed65808adf648004b34f98718301d718fa2darylmstatic int isneg (const char **s) { 9916a5fed65808adf648004b34f98718301d718fa2darylm if (**s == '-') { (*s)++; return 1; } 10016a5fed65808adf648004b34f98718301d718fa2darylm else if (**s == '+') (*s)++; 10116a5fed65808adf648004b34f98718301d718fa2darylm return 0; 10216a5fed65808adf648004b34f98718301d718fa2darylm} 10316a5fed65808adf648004b34f98718301d718fa2darylm 10416a5fed65808adf648004b34f98718301d718fa2darylm 10516a5fed65808adf648004b34f98718301d718fa2darylmstatic lua_Number readhexa (const char **s, lua_Number r, int *count) { 10616a5fed65808adf648004b34f98718301d718fa2darylm for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ 10716a5fed65808adf648004b34f98718301d718fa2darylm r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); 10816a5fed65808adf648004b34f98718301d718fa2darylm (*count)++; 10916a5fed65808adf648004b34f98718301d718fa2darylm } 11016a5fed65808adf648004b34f98718301d718fa2darylm return r; 11116a5fed65808adf648004b34f98718301d718fa2darylm} 11216a5fed65808adf648004b34f98718301d718fa2darylm 11316a5fed65808adf648004b34f98718301d718fa2darylm 11416a5fed65808adf648004b34f98718301d718fa2darylm/* 11516a5fed65808adf648004b34f98718301d718fa2darylm** convert an hexadecimal numeric string to a number, following 11616a5fed65808adf648004b34f98718301d718fa2darylm** C99 specification for 'strtod' 11716a5fed65808adf648004b34f98718301d718fa2darylm*/ 11816a5fed65808adf648004b34f98718301d718fa2darylmstatic lua_Number lua_strx2number (const char *s, char **endptr) { 11916a5fed65808adf648004b34f98718301d718fa2darylm lua_Number r = 0.0; 12016a5fed65808adf648004b34f98718301d718fa2darylm int e = 0, i = 0; 12116a5fed65808adf648004b34f98718301d718fa2darylm int neg = 0; /* 1 if number is negative */ 12216a5fed65808adf648004b34f98718301d718fa2darylm *endptr = cast(char *, s); /* nothing is valid yet */ 12316a5fed65808adf648004b34f98718301d718fa2darylm while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ 12416a5fed65808adf648004b34f98718301d718fa2darylm neg = isneg(&s); /* check signal */ 12516a5fed65808adf648004b34f98718301d718fa2darylm if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ 12616a5fed65808adf648004b34f98718301d718fa2darylm return 0.0; /* invalid format (no '0x') */ 12716a5fed65808adf648004b34f98718301d718fa2darylm s += 2; /* skip '0x' */ 12816a5fed65808adf648004b34f98718301d718fa2darylm r = readhexa(&s, r, &i); /* read integer part */ 12916a5fed65808adf648004b34f98718301d718fa2darylm if (*s == '.') { 13016a5fed65808adf648004b34f98718301d718fa2darylm s++; /* skip dot */ 13116a5fed65808adf648004b34f98718301d718fa2darylm r = readhexa(&s, r, &e); /* read fractional part */ 13216a5fed65808adf648004b34f98718301d718fa2darylm } 13316a5fed65808adf648004b34f98718301d718fa2darylm if (i == 0 && e == 0) 13416a5fed65808adf648004b34f98718301d718fa2darylm return 0.0; /* invalid format (no digit) */ 13516a5fed65808adf648004b34f98718301d718fa2darylm e *= -4; /* each fractional digit divides value by 2^-4 */ 13616a5fed65808adf648004b34f98718301d718fa2darylm *endptr = cast(char *, s); /* valid up to here */ 13716a5fed65808adf648004b34f98718301d718fa2darylm if (*s == 'p' || *s == 'P') { /* exponent part? */ 13816a5fed65808adf648004b34f98718301d718fa2darylm int exp1 = 0; 13916a5fed65808adf648004b34f98718301d718fa2darylm int neg1; 14016a5fed65808adf648004b34f98718301d718fa2darylm s++; /* skip 'p' */ 14116a5fed65808adf648004b34f98718301d718fa2darylm neg1 = isneg(&s); /* signal */ 14216a5fed65808adf648004b34f98718301d718fa2darylm if (!lisdigit(cast_uchar(*s))) 14316a5fed65808adf648004b34f98718301d718fa2darylm goto ret; /* must have at least one digit */ 14416a5fed65808adf648004b34f98718301d718fa2darylm while (lisdigit(cast_uchar(*s))) /* read exponent */ 14516a5fed65808adf648004b34f98718301d718fa2darylm exp1 = exp1 * 10 + *(s++) - '0'; 14616a5fed65808adf648004b34f98718301d718fa2darylm if (neg1) exp1 = -exp1; 14716a5fed65808adf648004b34f98718301d718fa2darylm e += exp1; 14816a5fed65808adf648004b34f98718301d718fa2darylm } 14916a5fed65808adf648004b34f98718301d718fa2darylm *endptr = cast(char *, s); /* valid up to here */ 15016a5fed65808adf648004b34f98718301d718fa2darylm ret: 15116a5fed65808adf648004b34f98718301d718fa2darylm if (neg) r = -r; 15216a5fed65808adf648004b34f98718301d718fa2darylm return l_mathop(ldexp)(r, e); 15316a5fed65808adf648004b34f98718301d718fa2darylm} 15416a5fed65808adf648004b34f98718301d718fa2darylm 15516a5fed65808adf648004b34f98718301d718fa2darylm#endif 15616a5fed65808adf648004b34f98718301d718fa2darylm 15716a5fed65808adf648004b34f98718301d718fa2darylm 15816a5fed65808adf648004b34f98718301d718fa2darylmint luaO_str2d (const char *s, size_t len, lua_Number *result) { 15916a5fed65808adf648004b34f98718301d718fa2darylm char *endptr; 16016a5fed65808adf648004b34f98718301d718fa2darylm if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ 16116a5fed65808adf648004b34f98718301d718fa2darylm return 0; 16216a5fed65808adf648004b34f98718301d718fa2darylm else if (strpbrk(s, "xX")) /* hexa? */ 16316a5fed65808adf648004b34f98718301d718fa2darylm *result = lua_strx2number(s, &endptr); 16416a5fed65808adf648004b34f98718301d718fa2darylm else 16516a5fed65808adf648004b34f98718301d718fa2darylm *result = lua_str2number(s, &endptr); 16616a5fed65808adf648004b34f98718301d718fa2darylm if (endptr == s) return 0; /* nothing recognized */ 16716a5fed65808adf648004b34f98718301d718fa2darylm while (lisspace(cast_uchar(*endptr))) endptr++; 16816a5fed65808adf648004b34f98718301d718fa2darylm return (endptr == s + len); /* OK if no trailing characters */ 16916a5fed65808adf648004b34f98718301d718fa2darylm} 17016a5fed65808adf648004b34f98718301d718fa2darylm 17116a5fed65808adf648004b34f98718301d718fa2darylm 17216a5fed65808adf648004b34f98718301d718fa2darylm 17316a5fed65808adf648004b34f98718301d718fa2darylmstatic void pushstr (lua_State *L, const char *str, size_t l) { 17416a5fed65808adf648004b34f98718301d718fa2darylm setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); 17516a5fed65808adf648004b34f98718301d718fa2darylm} 17616a5fed65808adf648004b34f98718301d718fa2darylm 17716a5fed65808adf648004b34f98718301d718fa2darylm 17816a5fed65808adf648004b34f98718301d718fa2darylm/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ 17916a5fed65808adf648004b34f98718301d718fa2darylmconst char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { 18016a5fed65808adf648004b34f98718301d718fa2darylm int n = 0; 18116a5fed65808adf648004b34f98718301d718fa2darylm for (;;) { 18216a5fed65808adf648004b34f98718301d718fa2darylm const char *e = strchr(fmt, '%'); 18316a5fed65808adf648004b34f98718301d718fa2darylm if (e == NULL) break; 18416a5fed65808adf648004b34f98718301d718fa2darylm luaD_checkstack(L, 2); /* fmt + item */ 18516a5fed65808adf648004b34f98718301d718fa2darylm pushstr(L, fmt, e - fmt); 18616a5fed65808adf648004b34f98718301d718fa2darylm switch (*(e+1)) { 18716a5fed65808adf648004b34f98718301d718fa2darylm case 's': { 18816a5fed65808adf648004b34f98718301d718fa2darylm const char *s = va_arg(argp, char *); 18916a5fed65808adf648004b34f98718301d718fa2darylm if (s == NULL) s = "(null)"; 19016a5fed65808adf648004b34f98718301d718fa2darylm pushstr(L, s, strlen(s)); 19116a5fed65808adf648004b34f98718301d718fa2darylm break; 19216a5fed65808adf648004b34f98718301d718fa2darylm } 19316a5fed65808adf648004b34f98718301d718fa2darylm case 'c': { 19416a5fed65808adf648004b34f98718301d718fa2darylm char buff; 19516a5fed65808adf648004b34f98718301d718fa2darylm buff = cast(char, va_arg(argp, int)); 19616a5fed65808adf648004b34f98718301d718fa2darylm pushstr(L, &buff, 1); 19716a5fed65808adf648004b34f98718301d718fa2darylm break; 19816a5fed65808adf648004b34f98718301d718fa2darylm } 19916a5fed65808adf648004b34f98718301d718fa2darylm case 'd': { 20016a5fed65808adf648004b34f98718301d718fa2darylm setnvalue(L->top++, cast_num(va_arg(argp, int))); 20116a5fed65808adf648004b34f98718301d718fa2darylm break; 20216a5fed65808adf648004b34f98718301d718fa2darylm } 20316a5fed65808adf648004b34f98718301d718fa2darylm case 'f': { 20416a5fed65808adf648004b34f98718301d718fa2darylm setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); 20516a5fed65808adf648004b34f98718301d718fa2darylm break; 20616a5fed65808adf648004b34f98718301d718fa2darylm } 20716a5fed65808adf648004b34f98718301d718fa2darylm case 'p': { 20816a5fed65808adf648004b34f98718301d718fa2darylm char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ 20916a5fed65808adf648004b34f98718301d718fa2darylm int l = sprintf(buff, "%p", va_arg(argp, void *)); 21016a5fed65808adf648004b34f98718301d718fa2darylm pushstr(L, buff, l); 21116a5fed65808adf648004b34f98718301d718fa2darylm break; 21216a5fed65808adf648004b34f98718301d718fa2darylm } 21316a5fed65808adf648004b34f98718301d718fa2darylm case '%': { 21416a5fed65808adf648004b34f98718301d718fa2darylm pushstr(L, "%", 1); 21516a5fed65808adf648004b34f98718301d718fa2darylm break; 21616a5fed65808adf648004b34f98718301d718fa2darylm } 21716a5fed65808adf648004b34f98718301d718fa2darylm default: { 21816a5fed65808adf648004b34f98718301d718fa2darylm luaG_runerror(L, 21916a5fed65808adf648004b34f98718301d718fa2darylm "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), 22016a5fed65808adf648004b34f98718301d718fa2darylm *(e + 1)); 22116a5fed65808adf648004b34f98718301d718fa2darylm } 22216a5fed65808adf648004b34f98718301d718fa2darylm } 22316a5fed65808adf648004b34f98718301d718fa2darylm n += 2; 22416a5fed65808adf648004b34f98718301d718fa2darylm fmt = e+2; 22516a5fed65808adf648004b34f98718301d718fa2darylm } 22616a5fed65808adf648004b34f98718301d718fa2darylm luaD_checkstack(L, 1); 22716a5fed65808adf648004b34f98718301d718fa2darylm pushstr(L, fmt, strlen(fmt)); 22816a5fed65808adf648004b34f98718301d718fa2darylm if (n > 0) luaV_concat(L, n + 1); 22916a5fed65808adf648004b34f98718301d718fa2darylm return svalue(L->top - 1); 23016a5fed65808adf648004b34f98718301d718fa2darylm} 23116a5fed65808adf648004b34f98718301d718fa2darylm 23216a5fed65808adf648004b34f98718301d718fa2darylm 23316a5fed65808adf648004b34f98718301d718fa2darylmconst char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { 23416a5fed65808adf648004b34f98718301d718fa2darylm const char *msg; 23516a5fed65808adf648004b34f98718301d718fa2darylm va_list argp; 23616a5fed65808adf648004b34f98718301d718fa2darylm va_start(argp, fmt); 23716a5fed65808adf648004b34f98718301d718fa2darylm msg = luaO_pushvfstring(L, fmt, argp); 23816a5fed65808adf648004b34f98718301d718fa2darylm va_end(argp); 23916a5fed65808adf648004b34f98718301d718fa2darylm return msg; 24016a5fed65808adf648004b34f98718301d718fa2darylm} 24116a5fed65808adf648004b34f98718301d718fa2darylm 24216a5fed65808adf648004b34f98718301d718fa2darylm 24316a5fed65808adf648004b34f98718301d718fa2darylm/* number of chars of a literal string without the ending \0 */ 24416a5fed65808adf648004b34f98718301d718fa2darylm#define LL(x) (sizeof(x)/sizeof(char) - 1) 24516a5fed65808adf648004b34f98718301d718fa2darylm 24616a5fed65808adf648004b34f98718301d718fa2darylm#define RETS "..." 24716a5fed65808adf648004b34f98718301d718fa2darylm#define PRE "[string \"" 24816a5fed65808adf648004b34f98718301d718fa2darylm#define POS "\"]" 24916a5fed65808adf648004b34f98718301d718fa2darylm 25016a5fed65808adf648004b34f98718301d718fa2darylm#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) 25116a5fed65808adf648004b34f98718301d718fa2darylm 25216a5fed65808adf648004b34f98718301d718fa2darylmvoid luaO_chunkid (char *out, const char *source, size_t bufflen) { 25316a5fed65808adf648004b34f98718301d718fa2darylm size_t l = strlen(source); 25416a5fed65808adf648004b34f98718301d718fa2darylm if (*source == '=') { /* 'literal' source */ 25516a5fed65808adf648004b34f98718301d718fa2darylm if (l <= bufflen) /* small enough? */ 25616a5fed65808adf648004b34f98718301d718fa2darylm memcpy(out, source + 1, l * sizeof(char)); 25716a5fed65808adf648004b34f98718301d718fa2darylm else { /* truncate it */ 25816a5fed65808adf648004b34f98718301d718fa2darylm addstr(out, source + 1, bufflen - 1); 25916a5fed65808adf648004b34f98718301d718fa2darylm *out = '\0'; 26016a5fed65808adf648004b34f98718301d718fa2darylm } 26116a5fed65808adf648004b34f98718301d718fa2darylm } 26216a5fed65808adf648004b34f98718301d718fa2darylm else if (*source == '@') { /* file name */ 26316a5fed65808adf648004b34f98718301d718fa2darylm if (l <= bufflen) /* small enough? */ 26416a5fed65808adf648004b34f98718301d718fa2darylm memcpy(out, source + 1, l * sizeof(char)); 26516a5fed65808adf648004b34f98718301d718fa2darylm else { /* add '...' before rest of name */ 26616a5fed65808adf648004b34f98718301d718fa2darylm addstr(out, RETS, LL(RETS)); 26716a5fed65808adf648004b34f98718301d718fa2darylm bufflen -= LL(RETS); 26816a5fed65808adf648004b34f98718301d718fa2darylm memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); 26916a5fed65808adf648004b34f98718301d718fa2darylm } 27016a5fed65808adf648004b34f98718301d718fa2darylm } 27116a5fed65808adf648004b34f98718301d718fa2darylm else { /* string; format as [string "source"] */ 27216a5fed65808adf648004b34f98718301d718fa2darylm const char *nl = strchr(source, '\n'); /* find first new line (if any) */ 27316a5fed65808adf648004b34f98718301d718fa2darylm addstr(out, PRE, LL(PRE)); /* add prefix */ 27416a5fed65808adf648004b34f98718301d718fa2darylm bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ 27516a5fed65808adf648004b34f98718301d718fa2darylm if (l < bufflen && nl == NULL) { /* small one-line source? */ 27616a5fed65808adf648004b34f98718301d718fa2darylm addstr(out, source, l); /* keep it */ 27716a5fed65808adf648004b34f98718301d718fa2darylm } 27816a5fed65808adf648004b34f98718301d718fa2darylm else { 27916a5fed65808adf648004b34f98718301d718fa2darylm if (nl != NULL) l = nl - source; /* stop at first newline */ 28016a5fed65808adf648004b34f98718301d718fa2darylm if (l > bufflen) l = bufflen; 28116a5fed65808adf648004b34f98718301d718fa2darylm addstr(out, source, l); 28216a5fed65808adf648004b34f98718301d718fa2darylm addstr(out, RETS, LL(RETS)); 28316a5fed65808adf648004b34f98718301d718fa2darylm } 28416a5fed65808adf648004b34f98718301d718fa2darylm memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); 28516a5fed65808adf648004b34f98718301d718fa2darylm } 28616a5fed65808adf648004b34f98718301d718fa2darylm} 28716a5fed65808adf648004b34f98718301d718fa2darylm 288