/* cbake.l @BAKE flex @FILE && cc -std=c99 -D_GNU_SOURCE -o @{@SHORT} lex.yy.c @ARGS -lfl @STOP */
%{
-
-#include <ctype.h>
-
-#undef ECHO
-#define ECHO do { fprintf(stdout, yytext); if (gpipe) { fprintf(gpipe, yytext); } } while (0)
-#define CHAR(c) do { fputc(c, stdout); if (gpipe) { fputc(c, gpipe); } } while (0)
-#define STRING(s) do { fputs(s, stdout); if (gpipe) { fputs(s, gpipe); } } while (0)
-#define FORMAT(...) do { fprintf(stdout, __VA_ARGS__); if (gpipe) { fprintf(gpipe, __VA_ARGS__); } } while (0)
-#define FWRITE(str, len) do { fwrite(str, 1, len, stdout); if (gpipe) { fwrite(str, 1, len, gpipe); } } while (0)
-
-FILE * gpipe;
-
char * filename;
-int gac;
-char ** gav;
-/* Options */
-int gselect = 1;
-/* accum */
- int line = 1, expunge_depth = 0, first_nl, nth = 0;
+int gac; char ** gav;
+int gmax = 0, line = 1, expunge_depth = 0;
-extern void root(char * filename);
extern void args(int n);
extern void shorten(char * filename, int n);
%}
-
-SPACE [ \t\r\v\f]
-NUM [[:digit:]]
-
-%x FOUND STOP PADDING
-
-MACROS (@BAKE|@FILENAME|@FILE|@SHORT|@ARGS|@LINE|@STOP|$@|$*|$+)
-
+%x FOUND PADDING
%option nodefault noinput noyywrap
%%
-
<FOUND>{
- /* New behavior */
- @BAKE { if (!gselect) { return 0; } yyless(yyleng - strlen("@BAKE")); BEGIN INITIAL; }
- @FILENAME|@FILE|$@ { STRING(filename); }
- @SHORT:{NUM}+ { shorten(filename, atoi(strrchr(yytext, ':')+1)); }
- @SHORT|$\* { shorten(filename, 1); }
- @ARGS:{NUM}+ { args(atoi(strrchr(yytext, ':')+1)); }
- @ARGS|$\+ { args(-1); }
- @LINE { FORMAT("%d", line); }
- @STOP { CHAR('\n'); if (!gselect) { return 0; } BEGIN INITIAL; }
- \\\n { ++line; CHAR(' '); BEGIN PADDING; }
- \\{MACROS} { putchar(yytext[1]); }
- @\{ { ++expunge_depth; }
- \} { if (!expunge_depth--) { ECHO; } }
- \n { ++line; if (first_nl) { first_nl = 0; BEGIN STOP; } }
- {SPACE} { CHAR(' '); BEGIN PADDING; }
- . { ECHO; }
+ @FILENAME|@FILE|$@ { printf(filename); }
+ @SHORT:[[:digit:]]+ { shorten(filename, atoi(strrchr(yytext, ':')+1)); }
+ @SHORT|$\* { shorten(filename, 1); }
+ @ARGS:[[:digit:]]+ { args(atoi(strrchr(yytext, ':')+1)); }
+ @ARGS|$\+ { args(-1); }
+ @LINE { printf("%d", line); }
+ @BAKE { yyless(yyleng - strlen("@BAKE")); BEGIN INITIAL; }
+ @STOP { printf("@STOP\n"); BEGIN INITIAL; }
+ \\[@$] { putchar(yytext[1]); }
+ \\\n { ++line; }
+ @\{ { ++expunge_depth; }
+ \} { if (!expunge_depth--) { ECHO; } }
+ \n { ++line; putchar(yytext[0]); }
+ [ \v\t\r\f] { putchar(' '); BEGIN PADDING; }
+ . { putchar(yytext[0]); }
}
-
-<STOP>{
- @BAKE{SPACE} {
- first_nl = 1;
- if (gselect < 0) { printf("\n%s:%d s%d: ", filename, line, ++nth); }
- BEGIN FOUND;
- }
- @STOP { yyless(-1); BEGIN FOUND; }
- \n { yymore(); ++line; }
- .|\\@ { yymore(); }
-}
-
<PADDING>{
- {SPACE} { ; }
- .|\n { yyless(0); BEGIN FOUND; }
-}
-
-@BAKE[[:space:]] {
- first_nl = 1;
- if (gselect < 0) { printf("%s:%d s%d: ", filename, line, ++nth); BEGIN FOUND; }
- else if (gselect == 0) { BEGIN FOUND; }
- else { --gselect; }
+ [ \v\t\r\f] { ; }
+ .|\n { yyless(0); BEGIN FOUND; }
}
+\\[^\n] { ; }
+\\\n { ++line; }
+@BAKE[ \t\r\v\f] { goto bake; }
+@BAKE\n { ++line; bake: ++gmax; printf("@BAKE "); BEGIN FOUND; }
+\n { ++line; }
+. { ; }
+%%
-\n { ++line; }
-. { ; }
+#include <ctype.h>
-%%
+void help(void) { puts("See bake(1) - \"Buy high. Sell low.\"\n"); }
void root(char * filename) {
char * path, * terminator;
}
void args(int n) {
- if (n < 0) { for (int i = 0; i < gac; ++i) { STRING(gav[i]); if (i + 1 < gac) { CHAR(' '); } } }
- else if (n < gac) { STRING(gav[n]); }
+ if (n < 0) { for (int i = 0; i < gac; ++i) { printf(gav[i]); if (i + 1 < gac) { putchar(' '); } } }
+ else if (n < gac) { printf(gav[n]); }
}
void shorten(char * filename, int n) {
char * end = filename + strlen(filename);
while (n && (end = memrchr(filename, '.', end - filename))) { --n; }
- if (!end) { fprintf(stderr, "<SHORTEN> context error: Argument out of range.\n"); STRING("idiot"); return; }
- FWRITE(filename, end - filename);
+ if (!end) { fprintf(stderr, "<SHORTEN> context error: Argument out of range.\n"); printf("idiot"); return; }
+ fwrite(filename, 1, end - filename, stdout);
}
-#define HELP \
- "bake(1) - \"Buy high. Sell low.\"\n"
-void help(void) { puts(HELP); }
-
int main (int ac, char ** av) {
- int run = 1;
+ int run = 1, select = 1, list = 0;
char * av0 = av[0];
- FILE * fp, * op;
-
+ FILE * fp;
while (++av, --ac) {
int i;
if (av[0][0] != '-') { goto start; }
for (i = 1; i < strlen(av[0]); ++i) {
switch (av[0][i]) {
opt_dry_run: case 'n': run = 0; break;
- opt_select: case 's': gselect = atoi(av[0]+2+(av[0][2] == '=')); i = strlen(av[0]); break;
- opt_list: case 'l': run = 0; gselect = -1; break;
+ opt_select: case 's': select = atoi(av[0]+2+(av[0][2] == '=')); i = strlen(av[0]); break;
+ opt_list: case 'l': run = 0; select = -1; break;
opt_help: case 'h': help(); return 0;
opt_default: default: fprintf(stderr, "%s: Unknown option '%s'\n", av0, av[0]); return 1;
opt_arg: fprintf(stderr, "%s: Argument missing for '%s'\n", av0, av[0]); return 1;
}
}
}
-
- start:
+start:
if (!ac) { fprintf(stderr, "%s: Missing filename\n", av0); return 1; }
- if (gselect == 0) { fprintf(stderr, "%s: Out of range\n", av0); return 1; }
- /* filename and self placement */
+ /* filename and renaming */
filename = av[0];
root(filename);
{
char * tmp = strrchr(filename, '/');
if (tmp) { filename = tmp+1; }
}
-
/* open and prepare ac, av */
if (!(yyin = fp = fopen(filename, "rb")))
{ fprintf(stderr, "%s: '%s' %s\n", av0, filename, strerror(errno)); return 1; }
gac = --ac, gav = ++av;
-
- if (run) {
- gpipe = popen("/bin/sh -e", "w");
- if (!gpipe) { fprintf(stderr, "%s: <gpipe> %s\n", av0, strerror(errno)); return 1; }
+ {
+ FILE * bp = fmemopen(buf, 1 << 16, "wb+"), * stdout_old = stdout;
+ stdout = bp;
+ yylex();
+ stdout = stdout_old;
+ fclose(bp);
+ }
+ if (select > gmax) { fprintf(stderr, "%s: Out of range\n", av0); return 1; }
+ if (!list) {
+ fprintf(stderr, "%s: ", av0); fflush(stderr);
+ fwrite(buf,1,1000,stdout);
+ if (run) {
+ FILE * gpipe = popen("/bin/sh -e", "w");
+ if (!gpipe) { fprintf(stderr, "%s: <gpipe> %s\n", av0, strerror(errno)); return 1; }
+ run = pclose(gpipe); if (run) { printf("%s: Exit code %d\n", av0, run); } return run;
+ }
}
- if (gselect > 0) { fprintf(stderr, "%s: ", av0); fflush(stderr); }
- yylex();
- /* putchar('\n'); */
- fclose(fp);
- if (gselect > 0) { fprintf(stderr, "%s: Out of range\n", av0); }
-
- if (!run) { return 0; }
- fprintf(stderr, "output: "); fflush(stderr);
- run = pclose(gpipe);
- /* repurposed run */
- if (run) { printf("%s: Exit code %d\n", av0, run); }
- return run;
}