/*
* j2t.lex : An example of the use (possibly abuse!)
*           of start states.
*/

%{
#define MAX_STATES 1024
#define TRUE  1
#define FALSE 0

#define CHAPTER   "@chapter"
#define SECTION   "@section"
#define SSECTION  "@subsection"
#define SSSECTION "@subsubsection"

int  states[MAX_STATES];
int  statep = 0;

int  need_closing = FALSE;

char buffer[YY_BUF_SIZE];

extern char *yytext;

/*
* set up the head of the *.texinfo file the program
* will produce. This is a standard texinfo header.
*/

void print_header(void)
{
  printf("\\input texinfo @c -*-texinfo-*-\n");
  printf("@c           %c**start of header\n",'%');
  printf("@setfilename       jargon.info\n");
  printf("@settitle          The New Hackers Dictionary\n");
  printf("@synindex          fn cp\n");
  printf("@synindex          vr cp\n");
  printf("@c           %c**end of header\n",'%');
  printf("@setchapternewpage odd\n");
  printf("@finalout\n");
  printf("@c @smallbook\n");
  printf("\n");
  printf("@c ==========================================================\n\n");
  printf("@c  This file was produced by j2t. Any mistakes are *not* the\n");
  printf("@c  fault of the jargon file editors.                        \n");
  printf("@c ==========================================================\n\n");
  printf("@titlepage\n");
  printf("@title     The New Hackers Dictionary\n");
  printf("@subtitle  Version 2.9.10\n");
  printf("@subtitle  Generated by j2t\n");
  printf("@author    Eric S. Raymond, Guy L. Steel, Mark Crispin et al.\n");
  printf("@end titlepage\n");
  printf("@page\n");
  printf("\n@c ==========================================================\n");
  printf("\n\n");
  printf("@unnumbered Preface\n");
  printf("@c          *******\n");
}

/*
* create the tail of the texinfo file produced.
*/

void print_trailer(void)
{
  printf("\n@c ==========================================================\n");
  printf("@contents\n");   /* print the table of contents */
  printf("@bye\n\n");
}

/*
* write an underline under a section
* or chapter so we can find it later.
*/

void write_underline(int len, int space, char ch)
{
 int loop;

 printf("@c ");

 for(loop=3; loop<space; loop++){
   printf(" ");
 }

 while(len--){
   printf("%c",ch);
 }
 printf("\n\n");
}

/*
* check for texinfo special characters
* and escape them
*/

char *check_and_convert(char *string)
{
 int  buffpos = 0;
 int  len,loop;

 len = strlen(string);
 for(loop=0; loop<len; loop++){
   if(string[loop] == '@' || string[loop] == '{' || string[loop] == '}'){
     buffer[buffpos++] = '@';
     buffer[buffpos++] = string[loop];
   } else {
     buffer[buffpos++] = string[loop];
   }
 }
 buffer[buffpos] = '\0';
 return(buffer);
}

/*
* write out a chapter,section, or subsection
* header
*/

void write_block_header(char *type)
{
 int loop;
 int len;

 (void)check_and_convert(yytext);
 len = strlen(buffer);
 for(loop=0; buffer[loop] != '\n';loop++)
        ;
 buffer[loop] = '\0';
 printf("%s %s\n",type,buffer);
 write_underline(strlen(buffer),strlen(type)+1,'*');
}

%}

/*
* the flex description starts here
*/

%x HEADING EXAMPLE ENUM EXAMPLE2
%x BITEM BITEM_ITEM
%s LITEM LITEM2

%%

^#[^#]*"#"  /* skip the header & trailer */
                    /* chapters have asterisks under them
                     * and are terminated by a colon
                     */
^[^\n:]+\n[*]+\n      write_block_header(CHAPTER);

^"= "[A-Z]" ="\n"="*  { /* we create a seciton for each category */
                       if(need_closing == TRUE){
                         printf("@end table\n\n\n");
                       }
                       need_closing = TRUE;
                       write_block_header(SECTION);
                       printf("\n\n@table @b\n");
                     }

"Examples:"[^\.]+     ECHO;

"*"[^*\n]+"*"         { /* @emph{}(emphasized) text */
                       yytext[yyleng-1] = '\0';
                       (void)check_and_convert(&yytext[1]);
                       printf("@i{%s}",buffer);
                     }

"{{"[^}]+"}}"         { /* special emphasis */
                       yytext[yyleng-2] = '\0';
                       (void)check_and_convert(&yytext[2]);
                       printf("@b{%s}",buffer);
                     }

"{"[^}]+"}"           { /* special emphasis */
                       yytext[yyleng-1] = '\0';
                       (void)check_and_convert(&yytext[1]);
                       printf("@b{%s}",buffer);
                     }

/* escape some special texinfo characters */
<INITIAL,LITEM,LITEM2,BITEM,ENUM,EXAMPLE,EXAMPLE2>"@"  printf("@@");
<INITIAL,LITEM,LITEM2,BITEM,ENUM,EXAMPLE,EXAMPLE2>"{"  printf("@{");
<INITIAL,LITEM,LITEM2,BITEM,ENUM,EXAMPLE,EXAMPLE2>"}"  printf("@}");

/*
 * reproduce @example code
 */

":"\n+[^\n0-9*]+\n"     "[^ ]   {
                       int loop;
                       int len;
                       int cnt;

                       printf(":\n\n@example \n");
                       strcpy(buffer,yytext);
                       len = strlen(buffer);
                       cnt = 0;
                       for(loop=len; loop > 0;loop--){
                         if(buffer[loop] == '\n')
                            cnt++;
                         if(cnt == 2)
                             break;
                       }
                       yyless(loop+1);
                       statep++;
                       states[statep] = EXAMPLE2;
                       BEGIN(EXAMPLE2);
                     }
<EXAMPLE,EXAMPLE2>^\n  {
                     printf("@end example\n\n");
                     statep--;
                     BEGIN(states[statep]);
                   }

/*
 * repoduce @enumerate lists
 */

":"\n+[ \t]*[0-9]+"."   {
                     int loop;
                     int len;

                     printf(":\n\n@enumerate \n");
                     strcpy(buffer,yytext);
                     len = strlen(buffer);
                     for(loop=len; loop > 0;loop--){
                       if(buffer[loop] == '\n')
                          break;
                     }
                     yyless(loop);
                     statep++;
                     states[statep] = ENUM;
                     BEGIN(ENUM);
                   }

<ENUM>"@"           printf("@@");
<ENUM>":"\n+"     "[^0-9]    {
                   printf(":\n\n@example\n");
                   statep++;
                   states[statep] = EXAMPLE;
                   BEGIN(EXAMPLE);
                 }


<ENUM>\n[ \t]+[0-9]+"." {
                   printf("\n\n@item ");
                  }
<ENUM>^[^ ] |
<ENUM>\n\n\n[ \t]+[^0-9] {
                   printf("\n\n@end enumerate\n\n");
                   statep--;
                   BEGIN(states[statep]);
                 }

/*
 * reproduce one kind of @itemize list
 */

":"\n+":"         {
                   int loop;
                   int len;

                   printf(":\n\n@itemize @bullet \n");
                   yyless(2);
                   statep++;
                   states[statep] = LITEM2;
                   BEGIN(LITEM2);
                 }
<LITEM2>^":".+":" {
                   (void)check_and_convert(&yytext[1]);
                   buffer[strlen(buffer)-1]='\0';
                   printf("@item @b{%s:}\n",buffer);
                 }

<LITEM2>\n\n\n+[^:\n] {
                   printf("\n\n@end itemize\n\n");
                   ECHO;
                   statep--;
                   BEGIN(states[statep]);
                 }

/*
 * create a list out of the revision history part.
 * We need the "Version" for this because it
 * clashes with other rules otherwise.
 */

:[\n]+"Version"[^:\n*]+":" {
                   int loop;
                   int len;

                   printf(":\n\n@itemize @bullet \n");
                   strcpy(buffer,yytext);
                   len = strlen(buffer);
                   for(loop=len; loop > 0;loop--){
                     if(buffer[loop] == '\n')
                        break;
                   }
                   yyless(loop);
                   statep++;
                   states[statep] = LITEM;
                   BEGIN(LITEM);
                 }
<LITEM>^.+":"     {
                   (void)check_and_convert(yytext);
                   buffer[strlen(buffer)-1]='\0';
                   printf("@item @b{%s}\n\n",buffer);
                 }

<LITEM>^[^:\n]+\n\n[^:\n]+\n  {
                   int loop;

                   strcpy(buffer,yytext);
                   for(loop=0; buffer[loop] != '\n'; loop++);
                   buffer[loop] = '\0';
                   printf("%s\n",buffer);
                   printf("@end itemize\n\n");
                   printf("%s",&buffer[loop+1]);
                   statep--;
                   BEGIN(states[statep]);
                 }

/*
 * reproduce @itemize @bullet lists
 */

":"\n[ ]*"*"      {
                   int loop;
                   int len;

                   printf(":\n\n@itemize @bullet \n");
                   len = strlen(buffer);
                   for(loop=0; loop < len;loop++){
                     if(buffer[loop] == '\n')
                        break;
                   }
                   yyless((len-loop)+2);
                   statep++;
                   states[statep] = BITEM;
                   BEGIN(BITEM);
                 }

<BITEM>^" "*"*"   {
                   printf("@item");
                   statep++;
                   states[statep] = BITEM_ITEM;
                   BEGIN(BITEM_ITEM);
                 }
<BITEM>"@"          printf("@@");
<BITEM>^\n        {
                   printf("@end itemize\n\n");
                   statep--;
                   BEGIN(states[statep]);
                 }
<BITEM_ITEM>[^\:]* {
                    printf(" @b{%s}\n\n",check_and_convert(yytext));
                  }
<BITEM_ITEM>":"   {
                   statep--;
                   BEGIN(states[statep]);
                 }

/*
 * recreate @chapter, @section etc.
 */

^:[^:]*           {
                   (void)check_and_convert(&yytext[1]);
                   statep++;
                   states[statep] = HEADING;
                   BEGIN(HEADING);
                 }
<HEADING>:[^\n]   {
                   printf("@item @b{%s}\n",buffer);
                   write_underline(strlen(buffer),6,'~');
                   statep--;
                   BEGIN(states[statep]);
                 }
<HEADING>:\n"*"*  {
                   if(need_closing == TRUE){
                     printf("@end table\n\n\n");
                     need_closing = FALSE;
                   }
                   printf("@chapter %s\n",buffer);
                   write_underline(strlen(buffer),9,'*');
                   statep--;
                   BEGIN(states[statep]);
                 }
<HEADING>:\n"="*  {
                   if(need_closing == TRUE){
                    printf("@end table\n\n\n");
                     need_closing = FALSE;
                   }
                   printf("@section %s\n",buffer);
                   write_underline(strlen(buffer),9,'=');
                   statep--;
                   BEGIN(states[statep]);
                 }
<HEADING>"@"        printf("@@");
<HEADING>:\n"-"*  {
                   if(need_closing == TRUE){
                     printf("@end table\n\n\n");
                     need_closing = FALSE;
                   }
                   printf("@subsection %s\n",buffer);
                   write_underline(strlen(buffer),12,'-');
                   statep--;
                   BEGIN(states[statep]);
                 }

/*
 * recreate @example text
 */

^"     "          {
                   printf("@example\n");
                   statep++;
                   states[statep] = EXAMPLE;
                   BEGIN(EXAMPLE);
                 }
<EXAMPLE>^"     "
                ECHO;

%%

/*
* initialise and go.
*/

int main(int argc, char *argv[])
{
 states[0] = INITIAL;
 statep    = 0;
 print_header();
 yylex();
 print_trailer();
 return(0);
}