Flex Outline Generator Spec File
Posted 11-15-2021 at 02:31 AM by astrogeek
Following is the Flex specification source for the post Flex Based Outline Generator.
Build instructions are included in the comments at top of the source below.
Copy and paste into a file named outline.l in your build directory. You may test your build using the example input file referenced in the above linked post.
Build instructions are included in the comments at top of the source below.
Copy and paste into a file named outline.l in your build directory. You may test your build using the example input file referenced in the above linked post.
Code:
%top{ /* Robert Allen Nov 14, 2021 astrogeek::linuxquestions.org License: Love and respect others as yourself, do unto others as you would have them do to you, WITHOUT REGARD TO ANY OTHER standard, law, order, license, command or authority. Period. Generate formatted outline from annotated text file - one outline item per line Each line of text is broken on word boundaries and wrapped to fit current margin plus indentation Internal whitespace is coalesced into a single space character, leading and trailing whitespace trimmed Lines optionally prefixed with outline order, alternating between numeric and alphabetic by indent level Title lines may be aligned left or center Prints page number centered on last line of each page Build with: flex -d outline.l gcc -Wall -std=c17 -o ol lex.yy.c ... or whatever works for your system! ./ol -h to see runtime help */ #define _POSIX_C_SOURCE 200809L } %{ #include <stdio.h> #include <string.h> #include <stdarg.h> #define DEF_PAGE_WIDTH 80 #define DEF_PAGE_LENGTH 56 #define DEF_LEFT_MARGIN 8 #define DEF_RGHT_MARGIN 12 #define DEF_TOP_MARGIN 5 #define DEF_BOT_MARGIN 3 #define DEF_INDENT_SPCS 4 #define MAX_INDENT_LEVEL 12 void yyerror(char *s, ...); void start_line(int nxlen); void break_line(); void set_page(); void page_top(); void page_bot(); void check_page(char *param); void title(char *title, int align); void usage(char *prgnam); extern int yy_flex_debug; /* Margins */ int tm, bm, lm, rm, rmax; /* Page parameters */ int pl, pw, pn; /* indentation parameters (spaces per, depth) */ int is, id; /* Current location in page */ int ln, col; /* Whitespace handling */ int notrim; /* Items */ int item=1; int enitem=1; int iptr; int istack[MAX_INDENT_LEVEL]; /* Source file lines */ int sln; %} %option nodefault nounput noinput noyywrap case-insensitive %% /* Control specifiers */ ^"#".*\n { sln++; /*Comment line, do nothing */ } ^[.]"pl"[ \t]+[0-9]+[ \t]*\n { pl = atoi(yytext+4); sln++; check_page(yytext);} ^[.]"pw"[ \t]+[0-9]+[ \t]*\n { pw = atoi(yytext+4); rmax = pw - rm; sln++; check_page(yytext); } ^[.]"tl".*\n { title(yytext + 3, 0); sln++; } ^[.]"tc".*\n { title(yytext + 3, 1); sln++; } ^[.]"lm"[ \t]+[0-9]+[ \t]*\n { lm = atoi(yytext+4); sln++; check_page(yytext); } ^[.]"tm"[ \t]+[0-9]+[ \t]*\n { tm = atoi(yytext+4); sln++; check_page(yytext); } ^[.]"bm"[ \t]+[0-9]+[ \t]*\n { bm = atoi(yytext+4); sln++; check_page(yytext); } ^[.]"rm"[ \t]+[0-9]+[ \t]*\n { rm = atoi(yytext+4); sln++; check_page(yytext); } ^[.]"is"[ \t]+[0-9]+[ \t]*\n { is = atoi(yytext+4); sln++; check_page(yytext); } ^[.]"si"[ \t]*\n { id++; iptr++; if(iptr >= MAX_INDENT_LEVEL){ yyerror("Max indent level exceeded!"); exit(EXIT_FAILURE); } istack[iptr] = iptr%2 ? 'a' : '1' ; sln++; check_page(yytext); } ^[.]"so"[ \t]*\n { id = id>0 ? id - 1 : 0; iptr = iptr ? iptr - 1 : 0; sln++; } ^[.]"sl"[ \t]*\n { id = 0; iptr = 0; sln++; } ^[.]"it"[ \t]*\n { enitem=!enitem; item=enitem; sln++; } /* Text handling */ [^ \t\n]+ { if((col + yyleng)>rmax) break_line(); if(col == 0) start_line(yyleng); printf("%s", yytext); col += yyleng; notrim++; } [ \t]+ { if((col + 1)>=rmax) break_line(); if(col == 0) start_line(yyleng); if(notrim) putchar(' '), col++; } \n { if(col>0) break_line(); item=enitem; sln++; } <<EOF>> { page_bot(); return 1; } %% int main(int argc, char *argv[]){ char *filename = NULL; tm = DEF_TOP_MARGIN; bm = DEF_BOT_MARGIN; lm = DEF_LEFT_MARGIN; rm = DEF_RGHT_MARGIN; pl = DEF_PAGE_LENGTH; pw = DEF_PAGE_WIDTH; is = DEF_INDENT_SPCS; rmax=pw-rm; pn=1; sln=1; istack[iptr]='1'; yy_flex_debug = 0; for(int i=1; i<argc; i++) { if(argv[i][0] != '-') { if(filename) { fprintf(stderr, "warning: ignoring trailing characters from: %s\n", argv[i]); break; } else filename = strdup(argv[i]); } else{ if(!strcmp(argv[i], "-h")) { usage(argv[0]); return EXIT_SUCCESS; } else if(!strcmp(argv[i], "-d")) yy_flex_debug=1; else { fprintf(stderr, "error: unknown option: %s\n", argv[i]); usage(argv[0]); return EXIT_FAILURE; } } } if(filename) { if((yyin = fopen(filename, "r")) == NULL) { perror(filename); return EXIT_FAILURE; } yylex(); fclose(yyin); } else{ yylex(); } return EXIT_SUCCESS; } void yyerror(char *s, ...) { va_list ap; va_start(ap, s); fprintf(stderr, "Error at line %d: ", sln); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); } void page_top() { while(ln++ <tm) putchar('\n'); col=0; } void page_bot() { while(ln < pl) putchar('\n'), ln++; col=0; while(col++ <((rmax - lm)/2 - 4)) putchar(' '); printf("Page %d\n", pn++); ln = 0; col = 0; } void set_page() { if((ln > ( pl - bm ))) page_bot(); if(ln<tm) page_top(); } void start_line(int nxlen) { set_page(); for(int i = lm + is * id; i>0; i--, col++) { putchar(' '); if((col + nxlen) > rmax) { yyerror("Text too long, %d chars!", nxlen); exit(EXIT_FAILURE); } } if(item){ printf("%c) ", istack[iptr]++); col+=3; } item=0; } void break_line() { putchar('\n'); ln++; notrim=col=0; } void title(char *title, int align) { set_page(); int tlen = strlen(title); if(tlen > (rmax - lm - (is * id))) { yyerror("Title string too long, use multiple title lines!\n"); exit(EXIT_FAILURE); } int left = lm; if(align==1) left += (rmax - lm - tlen)/2; while(col < left) putchar(' '), col++; printf("%s", title); ln++; col=0; } void check_page(char *param) { /* Check that page parameters make sense after each change */ if(pl <= (tm + bm)) yyerror("page length less than margins: %s\n", param), exit(EXIT_FAILURE); if(pw <= (lm + rm)) yyerror("page width less than margins: %s\n", param), exit(EXIT_FAILURE); if(rmax <= (lm + (is * id))) yyerror("indent beyond max width: %s\n", param), exit(EXIT_FAILURE); } void usage(char *prgnam) { printf("Usage: %s [-h -d] [file-name]\n" "\t-d\tEnable lexer debug trace (must be compiled with Flex debug option)\n" "\t-h\tPrint this help and exit\n" "\tReads markup from STDIN or file, writes formatted outline to STDOUT\n" "\tIgnores empty lines and collapses contiguous whitespace into a single space character\n" "\tRecognized markup, one per line, must be first characters on line:\n" "\t\t.pl [0-9]+\tSet page length in lines\n" "\t\t.pw [0-9]+\tSet page width in characters\n" "\t\t.lm [0-9]+\tSet left margin in characters\n" "\t\t.rm [0-9]+\tSet right margin in characters\n" "\t\t.tm [0-9]+\tSet top margin in lines\n" "\t\t.bm [0-9]+\tSet bottom margin in lines\n" "\t\t.is [0-9]+\tSet indent spaces for each level\n" "\t\t.si\tShift in one level (# spaces set by .is)\n" "\t\t.so\tShift out one level (# spaces set by .is)\n" "\t\t.sl\tShift out to left margin\n" "\t\t.it\tToggle item prefix, on by default (i.e., 1)..., a)... outline prefix)\n" "\t\t\tPrint indented paragraphs when off\n" "\t\t.tl[TEXT]\tPrints following text as left aligned title\n" "\t\t.tc[TEXT]\tPrints following text as center aligned title\n" "\t\t#...\tEmbedded comment lines not printed to output\n", prgnam); }
Total Comments 0