/*
 * 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);
}



