ref: d04cbf3cc7ece02439e24f671af19c07e7745ae2
parent: 25821e6d74fab5fcc200fe5e818362e03e114428
author: Tor Andersson <tor.andersson@artifex.com>
date: Mon Apr 23 07:46:18 EDT 2018
Add pretty-printing command line tool.
--- a/Makefile
+++ b/Makefile
@@ -8,9 +8,9 @@
libdir ?= $(prefix)/lib
ifeq "$(wildcard .git)" ".git"
-VERSION := $(shell git describe --tags --always)
+ VERSION := $(shell git describe --tags --always)
else
-VERSION := $(shell basename $$PWD | sed -e s,^mujs-,,)
+ VERSION := $(shell basename $$PWD | sed -e s,^mujs-,,)
endif
# Compiler flags for various configurations:
@@ -18,22 +18,22 @@
CFLAGS := -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter
ifeq "$(CC)" "clang"
-CFLAGS += -Wunreachable-code
+ CFLAGS += -Wunreachable-code
endif
ifeq "$(shell uname)" "Linux"
-CFLAGS += -ffunction-sections -fdata-sections
-LDFLAGS += -Wl,--gc-sections
+ CFLAGS += -ffunction-sections -fdata-sections
+ LDFLAGS += -Wl,--gc-sections
endif
ifeq "$(build)" "debug"
-CFLAGS += -g
+ CFLAGS += -g
else ifeq "$(build)" "sanitize"
-CFLAGS += -pipe -g -fsanitize=address -fno-omit-frame-pointer
-LDFLAGS += -fsanitize=address
+ CFLAGS += -pipe -g -fsanitize=address -fno-omit-frame-pointer
+ LDFLAGS += -fsanitize=address
else
-CFLAGS += -Os
-LDFLAGS += -Wl,-s
+ CFLAGS += -Os
+ LDFLAGS += -Wl,-s
endif
CFLAGS += $(XCFLAGS)
@@ -46,7 +46,7 @@
HDRS := $(wildcard js*.h mujs.h utf.h regexp.h)
default: static
-static: $(OUT) $(OUT)/mujs $(OUT)/libmujs.a $(OUT)/mujs.pc
+static: $(OUT)/mujs-pp $(OUT)/mujs $(OUT)/libmujs.a $(OUT)/mujs.pc
shared: static $(OUT)/libmujs.so
astnames.h: jsparse.h
@@ -60,22 +60,28 @@
jsdump.c: astnames.h opnames.h
-$(OUT):
- mkdir -p $(OUT)
-
-$(OUT)/main.o: main.c $(HDRS)
+$(OUT)/%.o: %.c $(HDRS)
+ @ mkdir -p $(dir $@)
$(CC) $(CFLAGS) -o $@ -c $<
$(OUT)/libmujs.o: one.c $(HDRS)
+ @ mkdir -p $(dir $@)
$(CC) $(CFLAGS) -o $@ -c $<
$(OUT)/libmujs.a: $(OUT)/libmujs.o
+ @ mkdir -p $(dir $@)
$(AR) cru $@ $^
$(OUT)/libmujs.so: one.c $(HDRS)
+ @ mkdir -p $(dir $@)
$(CC) $(CFLAGS) -fPIC -shared -o $@ $< -lm
$(OUT)/mujs: $(OUT)/libmujs.o $(OUT)/main.o
+ @ mkdir -p $(dir $@)
+ $(CC) $(LDFLAGS) -o $@ $^ -lm
+
+$(OUT)/mujs-pp: $(OUT)/libmujs.o $(OUT)/pp.o
+ @ mkdir -p $(dir $@)
$(CC) $(LDFLAGS) -o $@ $^ -lm
$(OUT)/mujs.pc:
--- a/jsdump.c
+++ b/jsdump.c
@@ -17,6 +17,8 @@
NULL
};
+static int minify = 0;
+
const char *jsP_aststring(enum js_AstType type)
{
if (type < nelem(astname)-1)
@@ -34,6 +36,7 @@
static int prec(enum js_AstType type)
{
switch (type) {
+ case AST_IDENTIFIER:
case EXP_IDENTIFIER:
case EXP_NUMBER:
case EXP_STRING:
@@ -142,15 +145,29 @@
static void in(int d)
{
- while (d-- > 0)
- putchar('\t');
+ if (minify < 1)
+ while (d-- > 0)
+ putchar('\t');
}
static void nl(void)
{
- putchar('\n');
+ if (minify < 2)
+ putchar('\n');
}
+static void sp(void)
+{
+ if (minify < 1)
+ putchar(' ');
+}
+
+static void comma(void)
+{
+ putchar(',');
+ sp();
+}
+
/* Pretty-printed Javascript syntax */
static void pstmlist(int d, js_Ast *list);
@@ -166,26 +183,30 @@
pexpi(d, COMMA, list->a);
list = list->b;
if (list)
- ps(", ");
+ comma();
}
}
static void parray(int d, js_Ast *list)
{
- ps("[");
+ pc('[');
while (list) {
assert(list->type == AST_LIST);
pexpi(d, COMMA, list->a);
list = list->b;
if (list)
- ps(", ");
+ comma();
}
- ps("]");
+ pc(']');
}
static void pobject(int d, js_Ast *list)
{
- ps("{");
+ pc('{');
+ if (list) {
+ nl();
+ in(d+1);
+ }
while (list) {
js_Ast *kv = list->a;
assert(list->type == AST_LIST);
@@ -192,32 +213,38 @@
switch (kv->type) {
default: break;
case EXP_PROP_VAL:
- pexpi(d, COMMA, kv->a);
- ps(": ");
- pexpi(d, COMMA, kv->b);
+ pexpi(d+1, COMMA, kv->a);
+ pc(':'); sp();
+ pexpi(d+1, COMMA, kv->b);
break;
case EXP_PROP_GET:
ps("get ");
- pexpi(d, COMMA, kv->a);
- ps("() {\n");
- pstmlist(d, kv->c);
- in(d); ps("}");
+ pexpi(d+1, COMMA, kv->a);
+ ps("()"); sp(); pc('{'); nl();
+ pstmlist(d+1, kv->c);
+ in(d+1); pc('}');
break;
case EXP_PROP_SET:
ps("set ");
- pexpi(d, COMMA, kv->a);
- ps("(");
- pargs(d, kv->b);
- ps(") {\n");
- pstmlist(d, kv->c);
- in(d); ps("}");
+ pexpi(d+1, COMMA, kv->a);
+ pc('(');
+ pargs(d+1, kv->b);
+ pc(')'); sp(); pc('{'); nl();
+ pstmlist(d+1, kv->c);
+ in(d+1); pc('}');
break;
}
list = list->b;
- if (list)
- ps(", ");
+ if (list) {
+ pc(',');
+ nl();
+ in(d+1);
+ } else {
+ nl();
+ in(d);
+ }
}
- ps("}");
+ pc('}');
}
static void pstr(const char *s)
@@ -224,10 +251,11 @@
{
static const char *HEX = "0123456789ABCDEF";
Rune c;
- pc('"');
+ pc(minify ? '\'' : '"');
while (*s) {
s += chartorune(&c, s);
switch (c) {
+ case '\'': ps("\\'"); break;
case '"': ps("\\\""); break;
case '\\': ps("\\\\"); break;
case '\b': ps("\\b"); break;
@@ -247,7 +275,7 @@
}
}
}
- pc('"');
+ pc(minify ? '\'' : '"');
}
static void pregexp(const char *prog, int flags)
@@ -263,7 +291,9 @@
static void pbin(int d, int p, js_Ast *exp, const char *op)
{
pexpi(d, p, exp->a);
+ sp();
ps(op);
+ sp();
pexpi(d, p, exp->b);
}
@@ -316,49 +346,58 @@
case EXP_BITNOT: puna(d, p, exp, "~", ""); break;
case EXP_LOGNOT: puna(d, p, exp, "!", ""); break;
- case EXP_LOGOR: pbin(d, p, exp, " || "); break;
- case EXP_LOGAND: pbin(d, p, exp, " && "); break;
- case EXP_BITOR: pbin(d, p, exp, " | "); break;
- case EXP_BITXOR: pbin(d, p, exp, " ^ "); break;
- case EXP_BITAND: pbin(d, p, exp, " & "); break;
- case EXP_EQ: pbin(d, p, exp, " == "); break;
- case EXP_NE: pbin(d, p, exp, " != "); break;
- case EXP_STRICTEQ: pbin(d, p, exp, " === "); break;
- case EXP_STRICTNE: pbin(d, p, exp, " !== "); break;
- case EXP_LT: pbin(d, p, exp, " < "); break;
- case EXP_GT: pbin(d, p, exp, " > "); break;
- case EXP_LE: pbin(d, p, exp, " <= "); break;
- case EXP_GE: pbin(d, p, exp, " >= "); break;
- case EXP_INSTANCEOF: pbin(d, p, exp, " instanceof "); break;
- case EXP_IN: pbin(d, p, exp, " in "); break;
- case EXP_SHL: pbin(d, p, exp, " << "); break;
- case EXP_SHR: pbin(d, p, exp, " >> "); break;
- case EXP_USHR: pbin(d, p, exp, " >>> "); break;
- case EXP_ADD: pbin(d, p, exp, " + "); break;
- case EXP_SUB: pbin(d, p, exp, " - "); break;
- case EXP_MUL: pbin(d, p, exp, " * "); break;
- case EXP_DIV: pbin(d, p, exp, " / "); break;
- case EXP_MOD: pbin(d, p, exp, " % "); break;
- case EXP_ASS: pbin(d, p, exp, " = "); break;
- case EXP_ASS_MUL: pbin(d, p, exp, " *= "); break;
- case EXP_ASS_DIV: pbin(d, p, exp, " /= "); break;
- case EXP_ASS_MOD: pbin(d, p, exp, " %= "); break;
- case EXP_ASS_ADD: pbin(d, p, exp, " += "); break;
- case EXP_ASS_SUB: pbin(d, p, exp, " -= "); break;
- case EXP_ASS_SHL: pbin(d, p, exp, " <<= "); break;
- case EXP_ASS_SHR: pbin(d, p, exp, " >>= "); break;
- case EXP_ASS_USHR: pbin(d, p, exp, " >>>= "); break;
- case EXP_ASS_BITAND: pbin(d, p, exp, " &= "); break;
- case EXP_ASS_BITXOR: pbin(d, p, exp, " ^= "); break;
- case EXP_ASS_BITOR: pbin(d, p, exp, " |= "); break;
+ case EXP_LOGOR: pbin(d, p, exp, "||"); break;
+ case EXP_LOGAND: pbin(d, p, exp, "&&"); break;
+ case EXP_BITOR: pbin(d, p, exp, "|"); break;
+ case EXP_BITXOR: pbin(d, p, exp, "^"); break;
+ case EXP_BITAND: pbin(d, p, exp, "&"); break;
+ case EXP_EQ: pbin(d, p, exp, "=="); break;
+ case EXP_NE: pbin(d, p, exp, "!="); break;
+ case EXP_STRICTEQ: pbin(d, p, exp, "==="); break;
+ case EXP_STRICTNE: pbin(d, p, exp, "!=="); break;
+ case EXP_LT: pbin(d, p, exp, "<"); break;
+ case EXP_GT: pbin(d, p, exp, ">"); break;
+ case EXP_LE: pbin(d, p, exp, "<="); break;
+ case EXP_GE: pbin(d, p, exp, ">="); break;
+ case EXP_IN: pbin(d, p, exp, "in"); break;
+ case EXP_SHL: pbin(d, p, exp, "<<"); break;
+ case EXP_SHR: pbin(d, p, exp, ">>"); break;
+ case EXP_USHR: pbin(d, p, exp, ">>>"); break;
+ case EXP_ADD: pbin(d, p, exp, "+"); break;
+ case EXP_SUB: pbin(d, p, exp, "-"); break;
+ case EXP_MUL: pbin(d, p, exp, "*"); break;
+ case EXP_DIV: pbin(d, p, exp, "/"); break;
+ case EXP_MOD: pbin(d, p, exp, "%"); break;
+ case EXP_ASS: pbin(d, p, exp, "="); break;
+ case EXP_ASS_MUL: pbin(d, p, exp, "*="); break;
+ case EXP_ASS_DIV: pbin(d, p, exp, "/="); break;
+ case EXP_ASS_MOD: pbin(d, p, exp, "%="); break;
+ case EXP_ASS_ADD: pbin(d, p, exp, "+="); break;
+ case EXP_ASS_SUB: pbin(d, p, exp, "-="); break;
+ case EXP_ASS_SHL: pbin(d, p, exp, "<<="); break;
+ case EXP_ASS_SHR: pbin(d, p, exp, ">>="); break;
+ case EXP_ASS_USHR: pbin(d, p, exp, ">>>="); break;
+ case EXP_ASS_BITAND: pbin(d, p, exp, "&="); break;
+ case EXP_ASS_BITXOR: pbin(d, p, exp, "^="); break;
+ case EXP_ASS_BITOR: pbin(d, p, exp, "|="); break;
- case EXP_COMMA: pbin(d, p, exp, ", "); break;
+ case EXP_INSTANCEOF:
+ pexpi(d, p, exp->a);
+ ps(" instanceof ");
+ pexpi(d, p, exp->b);
+ break;
+ case EXP_COMMA:
+ pexpi(d, p, exp->a);
+ pc(','); sp();
+ pexpi(d, p, exp->b);
+ break;
+
case EXP_COND:
pexpi(d, p, exp->a);
- ps(" ? ");
+ sp(); pc('?'); sp();
pexpi(d, p, exp->b);
- ps(" : ");
+ sp(); pc(':'); sp();
pexpi(d, p, exp->c);
break;
@@ -396,7 +435,7 @@
pexpi(d, 0, exp->a);
pc('(');
pargs(d, exp->b);
- ps(") {\n");
+ pc(')'); sp(); pc('{'); nl();
pstmlist(d, exp->c);
in(d); pc('}');
if (p == 0) pc(')');
@@ -420,7 +459,7 @@
assert(var->type == EXP_VAR);
pexp(d, var->a);
if (var->b) {
- ps(" = ");
+ sp(); pc('='); sp();
pexp(d, var->b);
}
}
@@ -432,7 +471,7 @@
pvar(d, list->a);
list = list->b;
if (list)
- ps(", ");
+ comma();
}
}
@@ -439,7 +478,7 @@
static void pblock(int d, js_Ast *block)
{
assert(block->type == STM_BLOCK);
- ps(" {\n");
+ pc('{'); nl();
pstmlist(d, block->a);
in(d); pc('}');
}
@@ -446,9 +485,10 @@
static void pstmh(int d, js_Ast *stm)
{
- if (stm->type == STM_BLOCK)
+ if (stm->type == STM_BLOCK) {
+ sp();
pblock(d, stm);
- else {
+ } else {
nl();
pstm(d+1, stm);
}
@@ -459,11 +499,11 @@
while (list) {
js_Ast *stm = list->a;
if (stm->type == STM_CASE) {
- in(d); ps("case "); pexp(d, stm->a); ps(":\n");
+ in(d); ps("case "); pexp(d, stm->a); pc(':'); nl();
pstmlist(d, stm->b);
}
if (stm->type == STM_DEFAULT) {
- in(d); ps("default:\n");
+ in(d); ps("default:"); nl();
pstmlist(d, stm->a);
}
list = list->b;
@@ -485,9 +525,9 @@
pexp(d, stm->a);
pc('(');
pargs(d, stm->b);
- ps(") {\n");
+ pc(')'); sp(); pc('{'); nl();
pstmlist(d, stm->c);
- in(d); ps("}");
+ in(d); pc('}');
break;
case STM_EMPTY:
@@ -497,11 +537,11 @@
case STM_VAR:
ps("var ");
pvarlist(d, stm->a);
- ps(";");
+ pc(';');
break;
case STM_IF:
- ps("if ("); pexp(d, stm->a); ps(")");
+ ps("if"); sp(); pc('('); pexp(d, stm->a); pc(')');
pstmh(d, stm->b);
if (stm->c) {
nl(); in(d); ps("else");
@@ -513,87 +553,89 @@
ps("do");
pstmh(d, stm->a);
nl();
- in(d); ps("while ("); pexp(d, stm->b); ps(");");
+ in(d); ps("while"); sp(); pc('('); pexp(d, stm->b); pc(')'); pc(';');
break;
case STM_WHILE:
- ps("while ("); pexp(d, stm->a); ps(")");
+ ps("while"); sp(); pc('('); pexp(d, stm->a); pc(')');
pstmh(d, stm->b);
break;
case STM_FOR:
- ps("for (");
- pexp(d, stm->a); ps("; ");
- pexp(d, stm->b); ps("; ");
- pexp(d, stm->c); ps(")");
+ ps("for"); sp(); pc('(');
+ pexp(d, stm->a); pc(';'); sp();
+ pexp(d, stm->b); pc(';'); sp();
+ pexp(d, stm->c); pc(')');
pstmh(d, stm->d);
break;
case STM_FOR_VAR:
- ps("for (var ");
- pvarlist(d, stm->a); ps("; ");
- pexp(d, stm->b); ps("; ");
- pexp(d, stm->c); ps(")");
+ ps("for"); sp(); ps("(var ");
+ pvarlist(d, stm->a); pc(';'); sp();
+ pexp(d, stm->b); pc(';'); sp();
+ pexp(d, stm->c); pc(')');
pstmh(d, stm->d);
break;
case STM_FOR_IN:
- ps("for (");
+ ps("for"); sp(); pc('(');
pexp(d, stm->a); ps(" in ");
- pexp(d, stm->b); ps(")");
+ pexp(d, stm->b); pc(')');
pstmh(d, stm->c);
break;
case STM_FOR_IN_VAR:
- ps("for (var ");
+ ps("for"); sp(); ps("(var ");
pvarlist(d, stm->a); ps(" in ");
- pexp(d, stm->b); ps(")");
+ pexp(d, stm->b); pc(')');
pstmh(d, stm->c);
break;
case STM_CONTINUE:
+ ps("continue");
if (stm->a) {
- ps("continue "); pexp(d, stm->a); ps(";");
- } else {
- ps("continue;");
+ pc(' '); pexp(d, stm->a);
}
+ pc(';');
break;
case STM_BREAK:
+ ps("break");
if (stm->a) {
- ps("break "); pexp(d, stm->a); ps(";");
- } else {
- ps("break;");
+ pc(' '); pexp(d, stm->a);
}
+ pc(';');
break;
case STM_RETURN:
+ ps("return");
if (stm->a) {
- ps("return "); pexp(d, stm->a); ps(";");
- } else {
- ps("return;");
+ pc(' '); pexp(d, stm->a);
}
+ pc(';');
break;
case STM_WITH:
- ps("with ("); pexp(d, stm->a); ps(")");
+ ps("with"); sp(); pc('('); pexp(d, stm->a); pc(')');
pstmh(d, stm->b);
break;
case STM_SWITCH:
- ps("switch (");
+ ps("switch"); sp(); pc('(');
pexp(d, stm->a);
- ps(") {\n");
+ pc(')'); sp(); pc('{'); nl();
pcaselist(d, stm->b);
- in(d); ps("}");
+ in(d); pc('}');
break;
case STM_THROW:
- ps("throw "); pexp(d, stm->a); ps(";");
+ ps("throw "); pexp(d, stm->a); pc(';');
break;
case STM_TRY:
ps("try");
+ if (minify && stm->a->type != STM_BLOCK)
+ pc(' ');
pstmh(d, stm->a);
if (stm->b && stm->c) {
- nl(); in(d); ps("catch ("); pexp(d, stm->b); ps(")");
+ nl(); in(d); ps("catch"); sp(); pc('('); pexp(d, stm->b); pc(')');
pstmh(d, stm->c);
}
if (stm->d) {
@@ -603,15 +645,17 @@
break;
case STM_LABEL:
- pexp(d, stm->a); ps(": "); pstm(d, stm->b);
+ pexp(d, stm->a); pc(':'); sp(); pstm(d, stm->b);
break;
case STM_DEBUGGER:
- ps("debugger;");
+ ps("debugger");
+ pc(';');
break;
default:
- pexp(d, stm); pc(';');
+ pexp(d, stm);
+ pc(';');
}
}
@@ -625,8 +669,9 @@
}
}
-void jsP_dumpsyntax(js_State *J, js_Ast *prog)
+void jsP_dumpsyntax(js_State *J, js_Ast *prog, int dominify)
{
+ minify = dominify;
if (prog->type == AST_LIST)
pstmlist(-1, prog);
else {
@@ -633,6 +678,8 @@
pstm(0, prog);
nl();
}
+ if (minify > 1)
+ putchar('\n');
}
/* S-expression list representation */
@@ -708,6 +755,7 @@
void jsP_dumplist(js_State *J, js_Ast *prog)
{
+ minify = 0;
if (prog->type == AST_LIST)
sblock(0, prog);
else
@@ -723,6 +771,8 @@
js_Instruction *end = F->code + F->codelen;
int i;
+ minify = 0;
+
printf("%s(%d)\n", F->name, F->numparams);
if (F->lightweight) printf("\tlightweight\n");
if (F->arguments) printf("\targuments\n");
@@ -802,6 +852,7 @@
void js_dumpvalue(js_State *J, js_Value v)
{
+ minify = 0;
switch (v.type) {
case JS_TUNDEFINED: printf("undefined"); break;
case JS_TNULL: printf("null"); break;
@@ -843,6 +894,7 @@
static void js_dumpproperty(js_State *J, js_Property *node)
{
+ minify = 0;
if (node->left->level)
js_dumpproperty(J, node->left);
printf("\t%s: ", node->name);
@@ -854,6 +906,7 @@
void js_dumpobject(js_State *J, js_Object *obj)
{
+ minify = 0;
printf("{\n");
if (obj->properties->level)
js_dumpproperty(J, obj->properties);
--- a/jsparse.h
+++ b/jsparse.h
@@ -140,7 +140,7 @@
void jsP_freeparse(js_State *J);
const char *jsP_aststring(enum js_AstType type);
-void jsP_dumpsyntax(js_State *J, js_Ast *prog);
+void jsP_dumpsyntax(js_State *J, js_Ast *prog, int minify);
void jsP_dumplist(js_State *J, js_Ast *prog);
#endif
--- /dev/null
+++ b/pp.c
@@ -1,0 +1,115 @@
+/* Pretty-print input source by emitting parse tree back as syntax.
+ * with no flags: pretty-printed source
+ * with -m: minified source with line breaks
+ * with -mm: minified source without line breaks
+ * with -s: s-expression syntax tree
+ */
+
+#include <stdio.h>
+
+#include "jsi.h"
+#include "jsparse.h"
+
+static void js_ppstring(js_State *J, const char *filename, const char *source, int minify)
+{
+ js_Ast *P;
+ if (js_try(J)) {
+ jsP_freeparse(J);
+ js_throw(J);
+ }
+ P = jsP_parse(J, filename, source);
+ if (minify > 2)
+ jsP_dumplist(J, P);
+ else
+ jsP_dumpsyntax(J, P, minify);
+ jsP_freeparse(J);
+ js_endtry(J);
+}
+
+void js_ppfile(js_State *J, const char *filename, int minify)
+{
+ FILE *f;
+ char *s;
+ int n, t;
+
+ f = fopen(filename, "rb");
+ if (!f) {
+ js_error(J, "cannot open file: '%s'", filename);
+ }
+
+ if (fseek(f, 0, SEEK_END) < 0) {
+ fclose(f);
+ js_error(J, "cannot seek in file: '%s'", filename);
+ }
+
+ n = ftell(f);
+ if (n < 0) {
+ fclose(f);
+ js_error(J, "cannot tell in file: '%s'", filename);
+ }
+
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ fclose(f);
+ js_error(J, "cannot seek in file: '%s'", filename);
+ }
+
+ s = js_malloc(J, n + 1); /* add space for string terminator */
+ if (!s) {
+ fclose(f);
+ js_error(J, "cannot allocate storage for file contents: '%s'", filename);
+ }
+
+ t = fread(s, 1, (size_t)n, f);
+ if (t != n) {
+ js_free(J, s);
+ fclose(f);
+ js_error(J, "cannot read data from file: '%s'", filename);
+ }
+
+ s[n] = 0; /* zero-terminate string containing file data */
+
+ if (js_try(J)) {
+ js_free(J, s);
+ fclose(f);
+ js_throw(J);
+ }
+
+ js_ppstring(J, filename, s, minify);
+
+ js_free(J, s);
+ fclose(f);
+ js_endtry(J);
+}
+
+int
+main(int argc, char **argv)
+{
+ js_State *J;
+ int minify = 0;
+ int i;
+
+ J = js_newstate(NULL, NULL, 0);
+
+ for (i = 1; i < argc; ++i) {
+ if (!strcmp(argv[i], "-m"))
+ minify = 1;
+ else if (!strcmp(argv[i], "-mm"))
+ minify = 2;
+ else if (!strcmp(argv[i], "-s"))
+ minify = 3;
+ else {
+ if (js_try(J)) {
+ js_report(J, js_trystring(J, -1, "Error"));
+ js_pop(J, 1);
+ continue;
+ }
+ js_ppfile(J, argv[i], minify);
+ js_endtry(J);
+ }
+ }
+
+ js_gc(J, 0);
+ js_freestate(J);
+
+ return 0;
+}