commit 14c31a433b611c8184d7d503eb71a5e7c648ef09 from: Omar Polo date: Fri Nov 25 16:12:06 2022 UTC template: add -o to specify the output file This way template can delete output file on parsing errors, which helps a lot with make(1). commit - 121058d7e6994e3577bbe541317d23db95847ace commit + 14c31a433b611c8184d7d503eb71a5e7c648ef09 blob - cc565367073134d2ca3c57c3490c0c75658581ce blob + 23136af5fef103ce02a1dc2506d9f42292b3bdf3 --- template/parse.y +++ template/parse.y @@ -50,7 +50,7 @@ static struct file { int lineno; int errors; } *file, *topfile; -int parse(const char *); +int parse(FILE *, const char *); struct file *pushfile(const char *, int); int popfile(void); int yyparse(void); @@ -70,6 +70,8 @@ void printq(const char *); extern int nodebug; +static FILE *fp; + static int block; static int in_define; static int errors; @@ -125,7 +127,7 @@ verbatim1 : /* empty */ | verbatim1 STRING { if (*$2 != '\0') { dbg(); - puts($2); + fprintf(fp, "%s\n", $2); } free($2); } @@ -137,23 +139,23 @@ verbatims : /* empty */ raw : STRING { dbg(); - printf("if ((tp_ret = tp->tp_puts(tp, "); + fprintf(fp, "if ((tp_ret = tp->tp_puts(tp, "); printq($1); - puts(")) == -1) goto err;"); + fputs(")) == -1) goto err;\n", fp); free($1); } ; block : define body end { - puts("err:"); - puts("return tp_ret;"); - puts("}"); + fputs("err:\n", fp); + fputs("return tp_ret;\n", fp); + fputs("}\n", fp); in_define = 0; } | define body finally end { - puts("return tp_ret;"); - puts("}"); + fputs("return tp_ret;\n", fp); + fputs("}\n", fp); in_define = 0; } ; @@ -162,8 +164,8 @@ define : '{' DEFINE string '}' { in_define = 1; dbg(); - printf("int\n%s\n{\n", $3); - puts("int tp_ret = 0;"); + fprintf(fp, "int\n%s\n{\n", $3); + fputs("int tp_ret = 0;\n", fp); free($3); } @@ -177,59 +179,63 @@ body : /* empty */ special : '{' RENDER string '}' { dbg(); - printf("if ((tp_ret = %s) == -1) goto err;\n", $3); + fprintf(fp, "if ((tp_ret = %s) == -1) goto err;\n", + $3); free($3); } | printf - | if body endif { puts("}"); } + | if body endif { fputs("}\n", fp); } | loop | '{' string '|' UNSAFE '}' { dbg(); - printf("if ((tp_ret = tp->tp_puts(tp, %s)) == -1)\n", + fprintf(fp, + "if ((tp_ret = tp->tp_puts(tp, %s)) == -1)\n", $2); - puts("goto err;"); + fputs("goto err;\n", fp); free($2); } | '{' string '|' URLESCAPE '}' { dbg(); - printf("if ((tp_ret = tp_urlescape(tp, %s)) == -1)\n", + fprintf(fp, + "if ((tp_ret = tp_urlescape(tp, %s)) == -1)\n", $2); - puts("goto err;"); + fputs("goto err;\n", fp); free($2); } | '{' string '}' { dbg(); - printf("if ((tp_ret = tp->tp_escape(tp, %s)) == -1)\n", + fprintf(fp, + "if ((tp_ret = tp->tp_escape(tp, %s)) == -1)\n", $2); - puts("goto err;"); + fputs("goto err;\n", fp); free($2); } ; printf : '{' PRINTF { dbg(); - printf("if (asprintf(&tp->tp_tmp, "); + fprintf(fp, "if (asprintf(&tp->tp_tmp, "); } printfargs '}' { - puts(") == -1)"); - puts("goto err;"); - puts("if ((tp_ret = tp->tp_escape(tp, tp->tp_tmp)) " - "== -1)"); - puts("goto err;"); - puts("free(tp->tp_tmp);"); - puts("tp->tp_tmp = NULL;"); + fputs(") == -1)\n", fp); + fputs("goto err;\n", fp); + fputs("if ((tp_ret = tp->tp_escape(tp, tp->tp_tmp)) " + "== -1)\n", fp); + fputs("goto err;\n", fp); + fputs("free(tp->tp_tmp);\n", fp); + fputs("tp->tp_tmp = NULL;\n", fp); } ; printfargs : /* empty */ | printfargs STRING { - printf(" %s", $2); + fprintf(fp, " %s", $2); free($2); } ; if : '{' IF stringy '}' { dbg(); - printf("if (%s) {\n", $3); + fprintf(fp, "if (%s) {\n", $3); free($3); } ; @@ -241,31 +247,31 @@ endif : end elsif : '{' ELSE IF stringy '}' { dbg(); - printf("} else if (%s) {\n", $4); + fprintf(fp, "} else if (%s) {\n", $4); free($4); } ; else : '{' ELSE '}' { dbg(); - puts("} else {"); + fputs("} else {\n", fp); } ; loop : '{' FOR stringy '}' { - printf("for (%s) {\n", $3); + fprintf(fp, "for (%s) {\n", $3); free($3); } body end { - puts("}"); + fputs("}\n", fp); } | '{' TQFOREACH STRING STRING STRING '}' { - printf("TAILQ_FOREACH(%s, %s, %s) {\n", + fprintf(fp, "TAILQ_FOREACH(%s, %s, %s) {\n", $3, $4, $5); free($3); free($4); free($5); } body end { - puts("}"); + fputs("}\n", fp); } ; @@ -274,7 +280,7 @@ end : '{' END '}' finally : '{' FINALLY '}' { dbg(); - puts("err:"); + fputs("err:\n", fp); } verbatims ; @@ -679,8 +685,10 @@ popfile(void) } int -parse(const char *filename) +parse(FILE *outfile, const char *filename) { + fp = outfile; + if ((file = pushfile(filename, 0)) == 0) return (-1); topfile = file; @@ -704,19 +712,19 @@ dbg(void) } lastline = yylval.lineno; - printf("#line %d ", yylval.lineno); + fprintf(fp, "#line %d ", yylval.lineno); printq(file->name); - putchar('\n'); + putc('\n', fp); } void printq(const char *str) { - putchar('"'); + putc('"', fp); for (; *str; ++str) { if (*str == '"') - putchar('\\'); - putchar(*str); + putc('\\', fp); + putc(*str, fp); } - putchar('"'); + putc('"', fp); } blob - f35c12a5a774cca9c6314d3441274f74714d17a9 blob + 9049862265fd87ccc1ab78e1c8e5be7694633be0 --- template/template.c +++ template/template.c @@ -19,9 +19,9 @@ #include #include -int parse(const char *); +int parse(FILE *, const char *); -int nodebug; +int nodebug; static void __dead usage(void) @@ -34,16 +34,18 @@ usage(void) int main(int argc, char **argv) { - int ch, i; + FILE *fp = stdout; + const char *out = NULL; + int ch, i; - if (pledge("stdio rpath", NULL) == -1) - err(1, "pledge"); - - while ((ch = getopt(argc, argv, "G")) != -1) { + while ((ch = getopt(argc, argv, "Go:")) != -1) { switch (ch) { case 'G': nodebug = 1; break; + case 'o': + out = optarg; + break; default: usage(); } @@ -51,17 +53,42 @@ main(int argc, char **argv) argc -= optind; argv += optind; + if (out && (fp = fopen(out, "w")) == NULL) + err(1, "can't open %s", out); + + if (out && unveil(out, "wc") == -1) + err(1, "unveil %s", out); + if (unveil("/", "r") == -1) + err(1, "unveil /"); + if (pledge(out ? "stdio rpath cpath" : "stdio rpath", NULL) == -1) + err(1, "pledge"); + /* preamble */ - puts("#include \"tmpl.h\""); + fprintf(fp, "#include \"tmpl.h\"\n"); if (argc == 0) { - parse("/dev/stdin"); - exit(0); + if (parse(fp, "/dev/stdin") == -1) + goto err; + } else { + for (i = 0; i < argc; ++i) + if (parse(fp, argv[i]) == -1) + goto err; } - for (i = 0; i < argc; ++i) - if (parse(argv[i]) == -1) - return (1); + if (ferror(fp)) + goto err; + if (fclose(fp) == -1) { + fp = NULL; + goto err; + } + return (0); + +err: + if (fp) + fclose(fp); + if (out && unlink(out) == -1) + err(1, "unlink %s", out); + return (1); }