lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Tue, Feb 15, 2005 at 09:58:52PM -0200, I wrote:
> 
> Shameless plug: my ltokens library comes with a lstrip tools that does
> exactly what LuaSrcDiet does but uses the Lua lexer for that.

Here is a simpler and better version of lstrip.c. Build lstrip with

 cc -o lstrip -I/tmp/lhf/lua-5.0.2/include -I/tmp/lhf/lua-5.0.2/src -O2 lstrip.c -L/tmp/lhf/lua-5.0.2/lib -llua -llualib

with adequate paths, of course.

lstrip.c works by redefining the parser function to loop over all tokens,
printing it adding a space only when needed. Line breaks are preserved,
to help with error messages.

Enjoy.
--lhf
/*
* lstrip.c
* compress Lua programs by removing comments and whitespaces, but preserving
* line breaks (for error messages). Uses the internals of Lua politely.
* 15 Feb 2005 22:46:28
* Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
* This code is hereby placed in the public domain.
*/

#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include "lua.h"
#include "lauxlib.h"

#include "llex.h"
#include "lobject.h"
#include "lparser.h"
#include "lstring.h"
#include "lzio.h"

static void quote(const char* s)
{
 putchar('"');
 for (; *s; s++)
 {
  switch (*s)
  {
   case '"': printf("\\\""); break;
   case '\a': printf("\\a"); break;
   case '\b': printf("\\b"); break;
   case '\f': printf("\\f"); break;
   case '\n': printf("\\n"); break;
   case '\r': printf("\\r"); break;
   case '\t': printf("\\t"); break;
   case '\v': printf("\\v"); break;
   default: putchar(*s); break;
  }
 }
 putchar('"');
}

#define NEEDSPACE(t) (((t)>=FIRST_RESERVED && (t)<=TK_NAME) || (t)==TK_NUMBER)

Proto *luaY_parser(lua_State *L, ZIO *z, Mbuffer *buff)
{
 int ln=1;
 int lt=0;
 LexState X;
 X.buff = buff;
 luaX_setinput(L, &X, z, luaS_new(L, zname(z)));
 while (1)
 {
  int t=luaX_lex(&X,&X.t.seminfo);
#if 1
  if (X.linenumber!=ln)
  {
   while (X.linenumber!=ln++) printf("\n");
   ln=X.linenumber;
   lt=0;
  }
#endif
  if (NEEDSPACE(lt) && NEEDSPACE(t)) printf(" ");
  switch (t)
  {
   case TK_EOS:
    return NULL;
   case TK_STRING:
    quote(getstr(X.t.seminfo.ts));
    break;
   case TK_NAME:
    printf("%s",getstr(X.t.seminfo.ts));
    break;
   case TK_NUMBER:
#if 0
    printf("%.16g",X.t.seminfo.r);
#else
    printf("%s",X.buff->buffer);
#endif
    break;
   case TK_CONCAT:
    if (lt==TK_NUMBER) printf(" ");
   default:
    printf("%s",luaX_token2str(&X,t));
    break;
  }
  lt=t;
 }
 return NULL;
}

static int strip(lua_State *L, const char* file)
{
 int status=luaL_loadfile(L,file);
 if (status!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));
 return status;
}

int main(int argc, char* argv[])
{
 lua_State *L=lua_open();
 if (*++argv==NULL)
  strip(L,NULL);
 else
  while (*argv && strip(L,*argv++)==0)
   ;
 lua_close(L);
 return 0;
}