모이가 풍족하면 병아리들은 모이를 놓고 서로 싸우지 않는다. 우리 인류도 마찬가지가 아닐까 ―돈 마키스(美 언론인)
* 원저자 : Peter Shook (
http://lua-users.org/wiki/PeterShook)
http://lua-users.org/wiki/PeterShook)
- 간단히 말해서, self.i와 self:func()을 각각 @i, @func()으로 줄여주는 기능을 추가하는 겁니다.
- 타이핑 노가다를 덜어주는 쓸만한 기능이라 생각합니다. 청크로딩할때 각각 self. 또는 self:으로 replace해주는거라 실행상의 부하는 없어보입니다. (로딩만 조금 느려지는 거겠죠)
- lua 5.0.2까지는 위 원저자 링크에 있는
lauxlib.c화일을 덮어쓴다음 컴파일하면 됩니다.
수동으로 패치하기 #
- 5.1work5, 5.1work6에서 각각 테스트 해봤습니다.
- 우선 아래 코드를 lua소스중 lauxlib.c의 다음 부분에 삽입합니다.
/* ** {====================================================== ** Load functions ** ======================================================= */ (이부분입니다) typedef struct LoadF { ...추가 코드 :#define BINARY_SIG '\033' /* binary files start with "<esc>Lua" */ #define MAX_NAME 64 typedef struct LoadX { lua_Chunkreader reader; void *ud; int state; int nest_count; const char *bp; const char *ep; char *np; char name[MAX_NAME]; } LoadX; static LoadX *initLoadX (LoadX *lx, lua_Chunkreader reader, void *ud) { lx->reader = reader; lx->ud = ud; lx->state = 1; lx->nest_count = 0; lx->bp = lx->ep = 0; lx->np = lx->name; return lx; } static const char *fillX (lua_State *L, LoadX *lx, size_t *size) { if (lx->bp >= lx->ep) { lx->bp = lx->reader(L, lx->ud, size); /* get chunk */ if (lx->bp) lx->ep = lx->bp + *size; } return lx->bp; } static const char *emptyX (LoadX *lx, size_t *size) { if (lx->np > lx->name) { *size = lx->np - lx->name; lx->np = lx->name; return lx->name; } return NULL; } static const char *scanX (LoadX *lx, const char *bp, const char *sc) { const char *s; for ( ; bp < lx->ep; bp++) for ( s = sc; *s; s++) if (*s == *bp) return bp; return bp; } #define match(lx, c) (*lx->bp == c) #define yield(lx, st, act) { lx->state = st; act; case st: ; } #define scanfor(lx, st, sc) case st: \ if ((lx->bp=scanX(lx, lx->bp, sc)) >= lx->ep) { lx->state = st; break; } else #define next(lx, st) \ if (++lx->bp >= lx->ep) yield(lx, st, break) else #define flush(lx, st, sp) \ if (sp < lx->bp) yield(lx, st, break) else #define fill(L, lx, st) \ ( (lx->bp >= lx->ep) ? fillX(L, lx, size) : lx->bp ) #define copy(L, lx, size, sp) (*lx->np++ = *lx->bp++, sp=fill(L, lx, size)) #define skip(L, lx, size, sp) (lx->bp++, sp=fill(L, lx, size)) static const char *getX (lua_State *L, void *ud, size_t *size) { LoadX *lx = (LoadX *)ud; const char *sp; if ((sp=fill(L, lx, size)) == NULL) return emptyX(lx, size); switch (lx->state) { case 0: return lx->reader(L, lx->ud, size); /* get chunk */ case 1: if (match(lx, BINARY_SIG)) { lx->state = 0; return sp; } Code: scanfor(lx, 2, "#-\'\"[@"); if (match(lx, '#')) { flush(lx, 3, sp); yield(lx, 4, *size = 2; return "--"); Comment: scanfor(lx, 5, "\n"); goto Code; } if (match(lx, '-')) { next(lx, 6); if (!match(lx, '-')) goto Code; next(lx, 7); if (!match(lx, '[')) goto Comment; next(lx, 8); if (!match(lx, '[')) goto Comment; next(lx, 9); lx->nest_count = 0; goto LongString; } if (match(lx, '\'')) { next(lx, 10); sqString: scanfor(lx, 11, "\'\\"); if (match(lx, '\'')) { next(lx, 12); goto Code; } if (match(lx, '\\')) { next(lx, 13); next(lx, 14); goto sqString; } break; /* impossible? */ } if (match(lx, '\"')) { next(lx, 15); dqString: scanfor(lx, 16, "\"\\"); if (match(lx, '\"')) { next(lx, 17); goto Code; } if (match(lx, '\\')) { next(lx, 18); next(lx, 19); goto dqString; } break; /* impossible? */ } if (match(lx, '[')) { next(lx, 20); if (!match(lx, '[')) goto Code; next(lx, 21); lx->nest_count = 0; LongString: scanfor(lx, 22, "[]"); if (match(lx, ']')) { next(lx, 23); if (!match(lx, ']')) goto LongString; next(lx, 24); if (lx->nest_count == 0) goto Code; lx->nest_count--; goto LongString; } if (match(lx, '[')) { next(lx, 25); if (!match(lx, '[')) goto LongString; next(lx, 26); lx->nest_count++; goto LongString; } break; /* impossible? */ } if (match(lx, '@')) { flush(lx, 27, sp); lx->np = lx->name; copy(L, lx, size, sp); if (sp && isalpha(*sp)) { const char *en = &lx->name[MAX_NAME]; copy(L, lx, size, sp); while (sp && lx->np < en && isalnum(*sp)) copy(L, lx, size, sp); if (lx->np < en) { if (sp && isspace(*sp) && *sp != '\n') copy(L, lx, size, sp); while (sp && isspace(*sp) && *sp != '\n') skip(L, lx, size, sp); *lx->name = (sp && (*sp=='(' || *sp=='\'' || *sp=='\"')) ? ':' : '.'; if (sp && lx->np < en && *sp == '[') { copy(L, lx, size, sp); if (sp && *sp == '[') *lx->name = ':'; } yield(lx, 28, *size = 4; return "self"); } } yield(lx, 29, return emptyX(lx, size)); goto Code; } } *size = lx->bp - sp; return sp; } - 그다음 luaL_loadfile 함수부분으로 가서 함수 초반에 다음을 선언합니다.
LoadX lx;
그런다음 다음 부분을 찾아서,... ungetc(c, lf.f); status = lua_load(L, getF, &lf, lua_tostring(L, -1)); readstatus = ferror(lf.f); ...
여기서 lua_load부분을 다음과 같이 고칩니다.... ungetc(c, lf.f); initLoadX(&lx, getF, &lf); status = lua_load(L, getX, &lx, lua_tostring(L, -1)); readstatus = ferror(lf.f); ...
- 마찬가지로 luaL_loadbuffer 함수도 같이 바꿔줍니다. LoadX lx; 선언하신다음,
... return lua_load(L, getX, &lx, name); }
이 부분을 다음과 같이 바꿉니다.... initLoadX(&lx, getS, &ls); return lua_load(L, getX, &lx, name); }









