Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. ** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $
  3. ** Lua compiler (saves bytecodes to files; also list bytecodes)
  4. ** See Copyright Notice in lua.h
  5. */
  6.  
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #define luac_c
  13. #define LUA_CORE
  14.  
  15. #include "lua.h"
  16. #include "lauxlib.h"
  17.  
  18. #include "lobject.h"
  19. #include "lstate.h"
  20. #include "lundump.h"
  21.  
  22. static void PrintFunction(const Proto* f, int full);
  23. #define luaU_print      PrintFunction
  24.  
  25. #define PROGNAME        "luac"          /* default program name */
  26. #define OUTPUT          PROGNAME ".out" /* default output file */
  27.  
  28. static int listing=0;                   /* list bytecodes? */
  29. static int dumping=1;                   /* dump bytecodes? */
  30. static int stripping=0;                 /* strip debug information? */
  31. static char Output[]={ OUTPUT };        /* default output file name */
  32. static const char* output=Output;       /* actual output file name */
  33. static const char* progname=PROGNAME;   /* actual program name */
  34.  
  35. static void fatal(const char* message)
  36. {
  37.  fprintf(stderr,"%s: %s\n",progname,message);
  38.  exit(EXIT_FAILURE);
  39. }
  40.  
  41. static void cannot(const char* what)
  42. {
  43.  fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
  44.  exit(EXIT_FAILURE);
  45. }
  46.  
  47. static void usage(const char* message)
  48. {
  49.  if (*message=='-')
  50.   fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
  51.  else
  52.   fprintf(stderr,"%s: %s\n",progname,message);
  53.  fprintf(stderr,
  54.   "usage: %s [options] [filenames]\n"
  55.   "Available options are:\n"
  56.   "  -l       list (use -l -l for full listing)\n"
  57.   "  -o name  output to file " LUA_QL("name") " (default is \"%s\")\n"
  58.   "  -p       parse only\n"
  59.   "  -s       strip debug information\n"
  60.   "  -v       show version information\n"
  61.   "  --       stop handling options\n"
  62.   "  -        stop handling options and process stdin\n"
  63.   ,progname,Output);
  64.  exit(EXIT_FAILURE);
  65. }
  66.  
  67. #define IS(s)   (strcmp(argv[i],s)==0)
  68.  
  69. static int doargs(int argc, char* argv[])
  70. {
  71.  int i;
  72.  int version=0;
  73.  if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
  74.  for (i=1; i<argc; i++)
  75.  {
  76.   if (*argv[i]!='-')                    /* end of options; keep it */
  77.    break;
  78.   else if (IS("--"))                    /* end of options; skip it */
  79.   {
  80.    ++i;
  81.    if (version) ++version;
  82.    break;
  83.   }
  84.   else if (IS("-"))                     /* end of options; use stdin */
  85.    break;
  86.   else if (IS("-l"))                    /* list */
  87.    ++listing;
  88.   else if (IS("-o"))                    /* output file */
  89.   {
  90.    output=argv[++i];
  91.    if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
  92.     usage(LUA_QL("-o") " needs argument");
  93.    if (IS("-")) output=NULL;
  94.   }
  95.   else if (IS("-p"))                    /* parse only */
  96.    dumping=0;
  97.   else if (IS("-s"))                    /* strip debug information */
  98.    stripping=1;
  99.   else if (IS("-v"))                    /* show version */
  100.    ++version;
  101.   else                                  /* unknown option */
  102.    usage(argv[i]);
  103.  }
  104.  if (i==argc && (listing || !dumping))
  105.  {
  106.   dumping=0;
  107.   argv[--i]=Output;
  108.  }
  109.  if (version)
  110.  {
  111.   printf("%s\n",LUA_COPYRIGHT);
  112.   if (version==argc-1) exit(EXIT_SUCCESS);
  113.  }
  114.  return i;
  115. }
  116.  
  117. #define FUNCTION "(function()end)();"
  118.  
  119. static const char* reader(lua_State *L, void *ud, size_t *size)
  120. {
  121.  UNUSED(L);
  122.  if ((*(int*)ud)--)
  123.  {
  124.   *size=sizeof(FUNCTION)-1;
  125.   return FUNCTION;
  126.  }
  127.  else
  128.  {
  129.   *size=0;
  130.   return NULL;
  131.  }
  132. }
  133.  
  134. #define toproto(L,i) getproto(L->top+(i))
  135.  
  136. static const Proto* combine(lua_State* L, int n)
  137. {
  138.  if (n==1)
  139.   return toproto(L,-1);
  140.  else
  141.  {
  142.   Proto* f;
  143.   int i=n;
  144.   if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
  145.   f=toproto(L,-1);
  146.   for (i=0; i<n; i++)
  147.   {
  148.    f->p[i]=toproto(L,i-n-1);
  149.    if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
  150.   }
  151.   f->sizelineinfo=0;
  152.   return f;
  153.  }
  154. }
  155.  
  156. static int writer(lua_State* L, const void* p, size_t size, void* u)
  157. {
  158.  UNUSED(L);
  159.  return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
  160. }
  161.  
  162. static int pmain(lua_State* L)
  163. {
  164.  int argc=(int)lua_tointeger(L,1);
  165.  char** argv=(char**)lua_touserdata(L,2);
  166.  const Proto* f;
  167.  int i;
  168.  if (!lua_checkstack(L,argc)) fatal("too many input files");
  169.  for (i=0; i<argc; i++)
  170.  {
  171.   const char* filename=IS("-") ? NULL : argv[i];
  172.   if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1));
  173.  }
  174.  f=combine(L,argc);
  175.  if (listing) luaU_print(f,listing>1);
  176.  if (dumping)
  177.  {
  178.   FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
  179.   if (D==NULL) cannot("open");
  180.   lua_lock(L);
  181.   luaU_dump(L,f,writer,D,stripping);
  182.   lua_unlock(L);
  183.   if (ferror(D)) cannot("write");
  184.   if (fclose(D)) cannot("close");
  185.  }
  186.  return 0;
  187. }
  188.  
  189. int main(int argc, char* argv[])
  190. {
  191.  lua_State* L;
  192.  int i=doargs(argc,argv);
  193.  argc-=i; argv+=i;
  194.  if (argc<=0) usage("no input files given");
  195.  L=luaL_newstate();
  196.  if (L==NULL) fatal("cannot create state: not enough memory");
  197.  lua_pushcfunction(L,&pmain);
  198.  lua_pushinteger(L,argc);
  199.  lua_pushlightuserdata(L,argv);
  200.  if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
  201.  lua_close(L);
  202.  return EXIT_SUCCESS;
  203. }
  204.  
  205. /*
  206. ** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $
  207. ** print bytecodes
  208. ** See Copyright Notice in lua.h
  209. */
  210.  
  211. #include <ctype.h>
  212. #include <stdio.h>
  213.  
  214. #define luac_c
  215. #define LUA_CORE
  216.  
  217. #include "ldebug.h"
  218. #include "lobject.h"
  219. #include "lopcodes.h"
  220.  
  221. #define VOID(p)         ((const void*)(p))
  222.  
  223. static void PrintString(const TString* ts)
  224. {
  225.  const char* s=getstr(ts);
  226.  size_t i,n=ts->tsv.len;
  227.  printf("%c",'"');
  228.  for (i=0; i<n; i++)
  229.  {
  230.   int c=(int)(unsigned char)s[i];
  231.   switch (c)
  232.   {
  233.    case '"':  printf("\\\""); break;
  234.    case '\\': printf("\\\\"); break;
  235.    case '\a': printf("\\a"); break;
  236.    case '\b': printf("\\b"); break;
  237.    case '\f': printf("\\f"); break;
  238.    case '\n': printf("\\n"); break;
  239.    case '\r': printf("\\r"); break;
  240.    case '\t': printf("\\t"); break;
  241.    case '\v': printf("\\v"); break;
  242.    default:     if (isprint(c))
  243.                         printf("%c",c);
  244.                 else
  245.                         printf("\\%03d",c);
  246.   }
  247.  }
  248.  printf("%c",'"');
  249. }
  250.  
  251. static void PrintConstant(const Proto* f, int i)
  252. {
  253.  const TValue* o=&f->k[i];
  254.  switch (ttype(o))
  255.  {
  256.   case LUA_TNIL:
  257.         printf("nil");
  258.         break;
  259.   case LUA_TBOOLEAN:
  260.         printf(bvalue(o) ? "true" : "false");
  261.         break;
  262.   case LUA_TNUMBER:
  263.         printf(LUA_NUMBER_FMT,nvalue(o));
  264.         break;
  265.   case LUA_TSTRING:
  266.         PrintString(rawtsvalue(o));
  267.         break;
  268.   default:                              /* cannot happen */
  269.         printf("? type=%d",ttype(o));
  270.         break;
  271.  }
  272. }
  273.  
  274. #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
  275. #define MYK(x)          (-1-(x))
  276.  
  277. static void PrintCode(const Proto* f)
  278. {
  279.  const Instruction* code=f->code;
  280.  int pc,n=f->sizecode;
  281.  for (pc=0; pc<n; pc++)
  282.  {
  283.   Instruction i=code[pc];
  284.   OpCode o=GET_OPCODE(i);
  285.   int a=GETARG_A(i);
  286.   int b=GETARG_B(i);
  287.   int c=GETARG_C(i);
  288.   int ax=GETARG_Ax(i);
  289.   int bx=GETARG_Bx(i);
  290.   int sbx=GETARG_sBx(i);
  291.   int line=getfuncline(f,pc);
  292.   printf("\t%d\t",pc+1);
  293.   if (line>0) printf("[%d]\t",line); else printf("[-]\t");
  294.   printf("%-9s\t",luaP_opnames[o]);
  295.   switch (getOpMode(o))
  296.   {
  297.    case iABC:
  298.     printf("%d",a);
  299.     if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b);
  300.     if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c);
  301.     break;
  302.    case iABx:
  303.     printf("%d",a);
  304.     if (getBMode(o)==OpArgK) printf(" %d",MYK(bx));
  305.     if (getBMode(o)==OpArgU) printf(" %d",bx);
  306.     break;
  307.    case iAsBx:
  308.     printf("%d %d",a,sbx);
  309.     break;
  310.    case iAx:
  311.     printf("%d",MYK(ax));
  312.     break;
  313.   }
  314.   switch (o)
  315.   {
  316.    case OP_LOADK:
  317.     printf("\t; "); PrintConstant(f,bx);
  318.     break;
  319.    case OP_GETUPVAL:
  320.    case OP_SETUPVAL:
  321.     printf("\t; %s",UPVALNAME(b));
  322.     break;
  323.    case OP_GETTABUP:
  324.     printf("\t; %s",UPVALNAME(b));
  325.     if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
  326.     break;
  327.    case OP_SETTABUP:
  328.     printf("\t; %s",UPVALNAME(a));
  329.     if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); }
  330.     if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
  331.     break;
  332.    case OP_GETTABLE:
  333.    case OP_SELF:
  334.     if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
  335.     break;
  336.    case OP_SETTABLE:
  337.    case OP_ADD:
  338.    case OP_SUB:
  339.    case OP_MUL:
  340.    case OP_DIV:
  341.    case OP_POW:
  342.    case OP_EQ:
  343.    case OP_LT:
  344.    case OP_LE:
  345.     if (ISK(b) || ISK(c))
  346.     {
  347.      printf("\t; ");
  348.      if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
  349.      printf(" ");
  350.      if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
  351.     }
  352.     break;
  353.    case OP_JMP:
  354.    case OP_FORLOOP:
  355.    case OP_FORPREP:
  356.    case OP_TFORLOOP:
  357.     printf("\t; to %d",sbx+pc+2);
  358.     break;
  359.    case OP_CLOSURE:
  360.     printf("\t; %p",VOID(f->p[bx]));
  361.     break;
  362.    case OP_SETLIST:
  363.     if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c);
  364.     break;
  365.    case OP_EXTRAARG:
  366.     printf("\t; "); PrintConstant(f,ax);
  367.     break;
  368.    default:
  369.     break;
  370.   }
  371.   printf("\n");
  372.  }
  373. }
  374.  
  375. #define SS(x)   ((x==1)?"":"s")
  376. #define S(x)    (int)(x),SS(x)
  377.  
  378. static void PrintHeader(const Proto* f)
  379. {
  380.  const char* s=f->source ? getstr(f->source) : "=?";
  381.  if (*s=='@' || *s=='=')
  382.   s++;
  383.  else if (*s==LUA_SIGNATURE[0])
  384.   s="(bstring)";
  385.  else
  386.   s="(string)";
  387.  printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
  388.         (f->linedefined==0)?"main":"function",s,
  389.         f->linedefined,f->lastlinedefined,
  390.         S(f->sizecode),VOID(f));
  391.  printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
  392.         (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
  393.         S(f->maxstacksize),S(f->sizeupvalues));
  394.  printf("%d local%s, %d constant%s, %d function%s\n",
  395.         S(f->sizelocvars),S(f->sizek),S(f->sizep));
  396. }
  397.  
  398. static void PrintDebug(const Proto* f)
  399. {
  400.  int i,n;
  401.  n=f->sizek;
  402.  printf("constants (%d) for %p:\n",n,VOID(f));
  403.  for (i=0; i<n; i++)
  404.  {
  405.   printf("\t%d\t",i+1);
  406.   PrintConstant(f,i);
  407.   printf("\n");
  408.  }
  409.  n=f->sizelocvars;
  410.  printf("locals (%d) for %p:\n",n,VOID(f));
  411.  for (i=0; i<n; i++)
  412.  {
  413.   printf("\t%d\t%s\t%d\t%d\n",
  414.   i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
  415.  }
  416.  n=f->sizeupvalues;
  417.  printf("upvalues (%d) for %p:\n",n,VOID(f));
  418.  for (i=0; i<n; i++)
  419.  {
  420.   printf("\t%d\t%s\t%d\t%d\n",
  421.   i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
  422.  }
  423. }
  424.  
  425. static void PrintFunction(const Proto* f, int full)
  426. {
  427.  int i,n=f->sizep;
  428.  PrintHeader(f);
  429.  PrintCode(f);
  430.  if (full) PrintDebug(f);
  431.  for (i=0; i<n; i++) PrintFunction(f->p[i],full);
  432. }
  433.