LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Blogs > astrogeek
User Name
Password

Notices


Rate this Entry

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.

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);
}
Posted in Uncategorized
Views 529 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 05:29 PM.

Main Menu
Advertisement
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration