This commit is contained in:
Chad C. Starz 2024-09-26 22:16:01 +00:00
parent dc5b390587
commit 688db98864
No known key found for this signature in database
GPG Key ID: CEEBC9208C287297

133
cbake.l
View File

@ -1,48 +1,69 @@
/* cbake.l @BAKE flex @FILE && cc -std=c99 -D_GNU_SOURCE -o @{@SHORT} lex.yy.c @ARGS -lfl @STOP */ /* cbake.l @BAKE flex @FILE && cc -Wall -Wextra -std=c99 -D_GNU_SOURCE -o @{@SHORT} lex.yy.c @ARGS -lfl @STOP */
/* TODO: implement expunge */
%{ %{
char * filename; #include <ctype.h>
int gac; char ** gav;
int gmax = 0, line = 1, expunge_depth = 0;
#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;
int gselect = 1, line = 1, first_nl, expunge_depth = 0;
int nth = 0, tmpline;
extern void root(char * filename);
extern void args(int n); extern void args(int n);
extern void shorten(char * filename, int n); extern void shorten(char * filename, int n);
%} %}
%x FOUND PADDING
%option nodefault noinput noyywrap SPACE [ \t\r\v\f]
MACROS (@BAKE|@FILENAME|@FILE|@SHORT|@ARGS|@LINE|@STOP|$@|$*|$+)
%x FOUND PADDING STOP
%option nodefault noinput nounput noyywrap
%% %%
@BAKE[[:space:]] { bake:
first_nl = 1;
if (yytext[yyleng-1] == '\n') { ++line; }
if (gselect < 0) { printf("\n%s:%d:s%d: ", filename, line, ++nth); BEGIN FOUND; }
else if (!--gselect) { BEGIN FOUND; }
}
\n { ++line; }
. {;}
<FOUND>{ <FOUND>{
@FILENAME|@FILE|$@ { printf(filename); } @BAKE|@STOP { BEGIN INITIAL; yyless(0); if (first_nl) { putchar('\n'); } if (!gselect) { return 0; } }
@FILENAME|@FILE|$@ { STRING(filename); }
@SHORT:[[:digit:]]+ { shorten(filename, atoi(strrchr(yytext, ':')+1)); } @SHORT:[[:digit:]]+ { shorten(filename, atoi(strrchr(yytext, ':')+1)); }
@SHORT|$\* { shorten(filename, 1); } @SHORT|$\* { shorten(filename, 1); }
@ARGS:[[:digit:]]+ { args(atoi(strrchr(yytext, ':')+1)); } @ARGS:[[:digit:]]+ { args(atoi(strrchr(yytext, ':')+1)); }
@ARGS|$\+ { args(-1); } @ARGS|$\+ { args(-1); }
@LINE { printf("%d", line); } @LINE { FORMAT("%d", line); }
@BAKE { yyless(yyleng - strlen("@BAKE")); BEGIN INITIAL; }
@STOP { printf("@STOP\n"); BEGIN INITIAL; }
\\[@$] { putchar(yytext[1]); }
\\\n { ++line; }
@\{ { ++expunge_depth; } @\{ { ++expunge_depth; }
\} { if (!expunge_depth--) { ECHO; } } \} { if (!expunge_depth--) { ECHO; } }
\n { ++line; putchar(yytext[0]); } \\\n { ++line; CHAR(' '); BEGIN PADDING; }
[ \v\t\r\f] { putchar(' '); BEGIN PADDING; } \\{MACROS} { STRING(yytext + 1); }
. { putchar(yytext[0]); } \n { putchar('\n'); ++line; if (first_nl) { first_nl = 0; tmpline = 0; BEGIN STOP; } }
{SPACE} { BEGIN PADDING; CHAR(' '); }
. { ECHO; }
} }
<PADDING>{ <PADDING>{
[ \v\t\r\f] { ; } {SPACE} { ; }
.|\n { yyless(0); BEGIN FOUND; } .|\n { yyless(0); BEGIN FOUND; }
}
<STOP>{
@BAKE[[:space:]] { line += tmpline; goto bake; }
@STOP { yyless(0); BEGIN FOUND; }
\n { ++tmpline; yymore(); }
.|\\@ { yymore(); }
} }
\\[^\n] { ; }
\\\n { ++line; }
@BAKE[ \t\r\v\f] { goto bake; }
@BAKE\n { ++line; bake: ++gmax; printf("@BAKE "); BEGIN FOUND; }
\n { ++line; }
. { ; }
%% %%
#include <ctype.h>
void help(void) { puts("See bake(1) - \"Buy high. Sell low.\"\n"); }
void root(char * filename) { void root(char * filename) {
char * path, * terminator; char * path, * terminator;
if (!(path = realpath(filename, NULL))) { return; } if (!(path = realpath(filename, NULL))) { return; }
@ -54,23 +75,26 @@ void root(char * filename) {
} }
void args(int n) { void args(int n) {
if (n < 0) { for (int i = 0; i < gac; ++i) { printf(gav[i]); if (i + 1 < gac) { putchar(' '); } } } if (n < 0) { for (int i = 0; i < gac; ++i) { STRING(gav[i]); if (i + 1 < gac) { CHAR(' '); } } }
else if (n < gac) { printf(gav[n]); } else if (n < gac) { STRING(gav[n]); }
} }
void shorten(char * filename, int n) { void shorten(char * filename, int n) {
char * end = filename + strlen(filename); char * end = filename + strlen(filename);
while (n && (end = memrchr(filename, '.', end - filename))) { --n; } while (n && (end = memrchr(filename, '.', end - filename))) { --n; }
if (!end) { fprintf(stderr, "<SHORTEN> context error: Argument out of range.\n"); printf("idiot"); return; } if (!end) { fprintf(stderr, "<SHORTEN> context error: Argument out of range.\n"); STRING("idiot"); return; }
fwrite(filename, 1, end - filename, stdout); FWRITE(filename, end - filename);
} }
void help(void) { puts("bake(1) - \"Buy high. Sell low.\"\n"); }
int main (int ac, char ** av) { int main (int ac, char ** av) {
int run = 1, select = 1, list = 0; int run = 1;
char * av0 = av[0]; char * av0 = av[0];
FILE * fp; FILE * fp;
while (++av, --ac) { while (++av, --ac) {
int i; size_t i;
if (av[0][0] != '-') { goto start; } if (av[0][0] != '-') { goto start; }
if (av[0][1] == '-') { if (av[0][1] == '-') {
if (av[0][2] == '\0') { ++av, --ac; goto start; } if (av[0][2] == '\0') { ++av, --ac; goto start; }
@ -84,44 +108,45 @@ int main (int ac, char ** av) {
for (i = 1; i < strlen(av[0]); ++i) { for (i = 1; i < strlen(av[0]); ++i) {
switch (av[0][i]) { switch (av[0][i]) {
opt_dry_run: case 'n': run = 0; break; opt_dry_run: case 'n': run = 0; break;
opt_select: case 's': select = atoi(av[0]+2+(av[0][2] == '=')); i = strlen(av[0]); break; opt_select: case 's': gselect = atoi(av[0]+i+1+(av[0][i+1] == '=')); i = strlen(av[0]); break;
opt_list: case 'l': run = 0; select = -1; break; opt_list: case 'l': run = 0; gselect = -1; break;
opt_help: case 'h': help(); return 0; opt_help: case 'h': help(); return 0;
opt_default: default: fprintf(stderr, "%s: Unknown option '%s'\n", av0, av[0]); return 1; 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; opt_arg: fprintf(stderr, "%s: Argument missing for '%s'\n", av0, av[0]); return 1;
} }
} }
} }
start:
if (!ac) { fprintf(stderr, "%s: Missing filename\n", av0); return 1; }
/* filename and renaming */ start:
if (!ac) { fprintf(stderr, "%s: Missing filename\n", av0); return 1; }
if (!gselect) { fprintf(stderr, "%s: Out of range\n", av0); return 1; }
/* filename and self placement */
filename = av[0]; filename = av[0];
root(filename); root(filename);
{ {
char * tmp = strrchr(filename, '/'); char * tmp = strrchr(filename, '/');
if (tmp) { filename = tmp+1; } if (tmp) { filename = tmp+1; }
} }
/* open and prepare ac, av */ /* open and prepare ac, av */
if (!(yyin = fp = fopen(filename, "rb"))) if (!(yyin = fp = fopen(filename, "rb")))
{ fprintf(stderr, "%s: '%s' %s\n", av0, filename, strerror(errno)); return 1; } { fprintf(stderr, "%s: '%s' %s\n", av0, filename, strerror(errno)); return 1; }
gac = --ac, gav = ++av; gac = --ac, gav = ++av;
{
FILE * bp = fmemopen(buf, 1 << 16, "wb+"), * stdout_old = stdout; if (run) {
stdout = bp; gpipe = popen("/bin/sh -e", "w");
yylex(); if (!gpipe) { fprintf(stderr, "%s: <gpipe> %s\n", av0, strerror(errno)); return 1; }
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(); fflush(stdout);
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;
} }