?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

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