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;
+}
--
⑨