%{
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <ctype.h>

   #define MAXCHAR 4096
   #define YYSTYPE char *

   /* Varibili globali */

   FILE *ffd,*ffd2;
   int spazi=0; /* conta gli spazi prima della prossima stringa */
   int invio=0; /* conta i ritorno a capo prima della prossima stringa */
   int dfont=4; /* dimensione font per il tag <font> */
   int riga=1; /* riga di lavoro attuale */
   int lflag=0; /* flag per il comportamento di <li> */
   int iflag=0; /* flag per le stringhe dentro ol e ul */
   int liflag=0; /* li attivato in ol o ul */
   char str[MAXCHAR]; /* array per le stringhe */
   char str2[MAXCHAR]; /* array per i tag */
   char *file_grf;  /* puntatore al nome dei file da convertire */
   /* Prototipi delle funzioni */

   int tag_composto(char * tag);
   int riconosci_tag(char * tag);
   int yyparse(void);
   int yylex(void);
   void gestione_li(void);
   void setfont(void);
        %}

%token
        html    fhtml      /* I token richiamano i tag html   */
        head    fhead      /* in questo modo :                */
        title   ftitle     /* In HTML      In html2tex        */
        body    fbody      /* <tag>    ->   tag               */
        font    ffont      /* </tag>   ->   ftag              */
        pre     fpre
        h1      fh1
        h2      fh2
        h3      fh3
        h4      fh4
        h5      fh5
        h6      fh6
        center  fcenter
        b       fb
        i       fi
        ol      fol
        ul      ful
        hr
        img
        br
        li 
        arp   
        generic /* per i tag sconosciuti o non implementati (es. <DT>) */
        string  /* stringhe di testo */

%%

 doc       : {fprintf(ffd2,"\\documentclass{report}\n");
              fprintf(ffd2,"\\usepackage{epsfig}\n");
              fprintf(ffd2,"\\begin{document}\n");}
             generic {printf("\nWarning : unknown tag %s at line %d.",str2,riga);}
             htm {fprintf(ffd2,"\n\\end{document}\n");}

           | {fprintf(ffd2,"\\documentclass{report}\n");
              fprintf(ffd2,"\\usepackage{epsfig}\n");
              fprintf(ffd2,"\\begin{document}\n");}
             htm {fprintf(ffd2,"\n\\end{document}\n");}
           ;

 htm       : html testa fhtml
           | html testa
           | testa 
           | html corpo fhtml
           | html corpo
           | corpo
           ;

 testa     : head generic {printf("\nWarning : unknown tag %s at line %d.",str2,riga);} titolo fhead corpo /* per compatibilita' con */
           | head titolo generic {printf("\nWarning : unknown tag %s at line %d.",str2,riga);} fhead corpo  /* Frontpage 1.1 */
           | head titolo fhead corpo
           | titolo corpo
           ;

 titolo    : title {fprintf(ffd2,"\\title{");} stringhe1 ftitle {fprintf(ffd2,"}");} 
           ;

 corpo     : body scritte fbody 
           | body scritte
           | scritte
           ;

 scritte   : scritte1 
           | scritte1 scritte
           |
           ;        

 scritte1  : pre {fprintf(ffd2,"\n\n");} scritte fpre {fprintf(ffd2,"\n\n");}
           |  center {fprintf(ffd2,"\\begin{center}");} scritte fcenter {fprintf(ffd2,"\\end{center}");}
           |  font {setfont();} scritte ffont{fprintf(ffd2,"\\normalsize ");}
           |  h1 {fprintf(ffd2,"\\Huge \\bfseries ");} scritte fh1 {fprintf(ffd2,"\\upshape \\normalsize ");}
           |  h2 {fprintf(ffd2,"\\LARGE \\bfseries ");} scritte fh2 {fprintf(ffd2,"\\upshape \\normalsize ");}
           |  h3 {fprintf(ffd2,"\\large \\bfseries ");} scritte fh3 {fprintf(ffd2,"\\upshape \\normalsize ");} 
           |  h4 {fprintf(ffd2,"\\small \\bfseries ");} scritte fh4 {fprintf(ffd2,"\\upshape \\normalsize ");}
           |  h5 {fprintf(ffd2,"\\scriptsize \\bfseries ");} scritte fh5 {fprintf(ffd2,"\\upshape \\normalsize ");}
           |  h6 {fprintf(ffd2,"\\tiny \\bfseries ");} scritte fh6 {fprintf(ffd2,"\\upshape \\normalsize ");}
           |  b {fprintf(ffd2,"\\bfseries ");} scritte fb {fprintf(ffd2,"\\upshape ");} 
           |  i {fprintf(ffd2,"\\itshape ");} scritte fi {fprintf(ffd2,"\\upshape ");} 
           |  ol {fprintf(ffd2,"\\begin{enumerate}\n"); lflag=1; iflag=1;} scritte fol {fprintf(ffd2,"\\end{enumerate}\n"); lflag=0; iflag=0;} 
           |  ul {fprintf(ffd2,"\\begin{enumerate}\n"); lflag=2; iflag=1;} scritte ful {fprintf(ffd2,"\\end{enumerate}\n"); lflag=0; iflag=0;} 
           |  img {fprintf(ffd2,"\\includegraphics{%s.eps}",file_grf); printf("\nThe graphic file %s must be converted in EPS format by the user.", file_grf);}
           |  li {gestione_li();}
           |  hr {fprintf(ffd2," \\\\ \\rule{15cm}{1mm} \n");}
           |  br {fprintf(ffd2," \\\\ ");}
           |  generic {printf("\nWarning : unknown tag %s at line %d.",str2,riga);}
           |  arp {fprintf(ffd2,"\n\n");}
           |  stringhe
           ;

 stringhe  : stringhe string {
                              if (invio > 0)
                               iflag=1;
                              for(invio;invio > 0; invio--)
                               fprintf(ffd2,"\n");
                              for(spazi;spazi > 0; spazi--)
                               fprintf(ffd2," ");
                              if (lflag>0 && iflag==1 && liflag==0 )
                               fprintf(ffd2,"\\item[ ]%s",$2);
                              else
                               {
                               fprintf(ffd2,"%s",$2);
                               liflag=0;
                               }
                              iflag=0;
                              }
           | string {
                              if (invio > 0)
                               iflag=1;
                              for(invio;invio > 0; invio--)
                               fprintf(ffd2,"\n");
                              for(spazi;spazi > 0; spazi--)
                               fprintf(ffd2," ");
                              if (lflag>0 && iflag==1 && liflag==0 )
                               fprintf(ffd2,"\\item[ ]%s",$1);
                              else
                               {
                               fprintf(ffd2,"%s",$1);
                               liflag=0;
                               }
                              iflag=0;

                      }
                      ;

 stringhe1  : stringhe1 string {
                                fprintf(ffd2,"%s ",$2);
                                }
            |
            ;

%%

void gestione_li(void)
        {
        if (lflag==0)
         {
         fprintf(ffd2,"\\begin{math} \\bullet \\end{math} ");
         liflag=1;
          }
        else if (lflag==2)
         {
         fprintf(ffd2,"\\item[\\begin{math} \\bullet \\end{math}] ");
         liflag=1;
         }
        else if (lflag==1)
         {
         fprintf(ffd2,"\\item ");
         liflag=1;
          }
        }

void setfont(void)
        {
         switch(dfont) {
          case 0 :
           {fprintf(ffd2,"\\tiny ");}         
          break;
          case 1 :
           {fprintf(ffd2,"\\footnotesize ");}
          break;
          case 2 :
           {fprintf(ffd2,"\\small ");}
          break;
          case 3 :
           {fprintf(ffd2,"\\normalsize ");}
          break;
          case 4 :
           {fprintf(ffd2,"\\Large ");}
          break;
          case 5 :
           {fprintf(ffd2,"\\LARGE ");}
          break;
          case 6 :
           {fprintf(ffd2,"\\huge ");}
          break;
          default :
           {fprintf(ffd2,"\\normalsize ");}
         }
        }

void main(int argc, char *argv[])
{

 printf("\nHTML to (La)TeX Release 1.02\n");
 printf("(c)1997 Giovanni Andreani (Original code and MS-DOS version)\n");
 printf("        Antonio Sant (AMIGA version)\n\n");

 switch (argc){
  case 3:
          {
          if ((ffd=fopen(argv[1],"r"))==NULL)
                {
                   printf("Error opening %s !\n",argv[1]);
                   exit(1);
                   }
          if ((ffd2=fopen(argv[2],"w"))==NULL)
                {
                   printf("Error creating %s !\n",argv[2]);
                   exit(1);
                   }
          break;
           }

  default: printf("Use: html2tex HTML_file (La)TeX_file\n");
           exit(1);
           };

 yyparse();

 printf("\n\nTranslation ended.\n");

 fclose(ffd);
 fclose(ffd2);

      }

int yyerror(char *s)
       {
               if ((strstr(str2,"/"))!=NULL)
                {
                fprintf(stderr,"\nError : the tag %s at line %d has not a predecessor.\n",str2,riga);
                exit(1);
                 }
               else
               {
                fprintf(stderr,"\nError : the tag %s at line %d is misplaced.\n",str2,riga);             
                exit(1);
                }
       }

int yylex()
        {        
        int val=0; /* contatore per la posizione dei caratteri da mettere in str */
        char c;

              while (((c=fgetc(ffd)) == ' ') || (c == '\n')) /* eliminiamo gli spazi bianchi */
                {
                if (c=='\n')
                 {
                  riga++;
                  invio++;
                  }
                if (c==' ')
                 spazi++;
                }  

              if (c == EOF)
               return(0); /* il file di input e' finito, fermiamo anche il parser */

              if (c=='<') /* e' un tag HTML */
               {
                 do
                 {
                 if ((c==EOF) || (val >= MAXCHAR))/* controlliamo che il tag non sia incompleto (ossia senza '>') */
                  {
                   printf("Trovato tag incompleto.\nImpossibile proseguire dopo la riga %d.\n",riga);
                   return(0); 
                  }
                 str2[val++]=c;
                 }
                 while ((c=fgetc(ffd)) != '>'); /* leggiamo il TAG */
                 str2[val++]=c;   /* aggiungiamo '>' */
                 str2[val]='\0';  /* terminiamo correttamente il TAG */
                 val=(riconosci_tag(str2)); /* vediamo che tag abbiamo trovato e informiamo il parser */                 
                 return(val);
                }
              else
              {
                 do
                 {
                 if (c=='<') /* leggendo la stringa abbiamo trovato un tag (es. Questo<B>...)*/
                  {
                        ungetc(c,ffd);      /* rimettiamo < nello stream */
                        str[val]='\0';        /* terminiamo correttamente la stringa */                        
                        yylval=str;
                        return string;
                        }
                 if ( (c=='#') || (c=='\\') || (c=='_') || (c=='$') || (c=='&') || (c=='{') || (c=='}'))
                 {
                   str[val++]='\\';
                   str[val++]=c;
                   }
                 else
                  str[val++]=c;
                 c=fgetc(ffd);
                 }
                 while (!(c == EOF || c ==' ' || c =='\n' )); /* leggiamo la stringa */
                
                ungetc(c,ffd); /* rimettiamo sullo stream l'ultimo carattere */
                 
               /* la lettura della stringa e'finita */               
               str[val]='\0';        /* terminiamo correttamente la stringa */              
               yylval=str;
               return string;
              }
       }

int riconosci_tag(char * tag)
{
       int val;

       for (val=0 ; val<strlen(tag) ; val++) /* i caratteri del tag diventano */
        tag[val]=tolower(tag[val]);          /* minuscoli, se non lo sono gia' */

       /* vediamo se il tag non e' composto */

       if (strcmp(tag,"<html>")==0)
        return(html);
       else if (strcmp(tag,"</html>")==0)
        return(fhtml);

       else if (strcmp(tag,"<head>")==0)
        return(head);
       else if (strcmp(tag,"</head>")==0)
        return(fhead);

       else if (strcmp(tag,"<title>")==0)
        return(title);
       else if (strcmp(tag,"</title>")==0)
        return(ftitle);

       else if (strcmp(tag,"<body>")==0)
        return(body);
       else if (strcmp(tag,"</body>")==0)
        return(fbody);

       else if (strcmp(tag,"<font>")==0)
        return(font);
       else if (strcmp(tag,"</font>")==0)
        return(ffont);

       else if (strcmp(tag,"<h1>")==0)
        return(h1);
       else if (strcmp(tag,"</h1>")==0)
        return(fh1);

       else if (strcmp(tag,"<h2>")==0)
        return(h2);
       else if (strcmp(tag,"</h2>")==0)
        return(fh2);

       else if (strcmp(tag,"<h3>")==0)
        return(h3);
       else if (strcmp(tag,"</h3>")==0)
        return(fh3);

       else if (strcmp(tag,"<h4>")==0)
        return(h4);
       else if (strcmp(tag,"</h4>")==0)
        return(fh4);

       else if (strcmp(tag,"<h5>")==0)
        return(h5);
       else if (strcmp(tag,"</h5>")==0)
        return(fh5);

       else if (strcmp(tag,"<h6>")==0)
        return(h6);
       else if (strcmp(tag,"</h6>")==0)
        return(fh6);

       else if (strcmp(tag,"<center>")==0)
        return(center);
       else if (strcmp(tag,"</center>")==0)
        return(fcenter);

       else if (strcmp(tag,"<b>")==0)
        return(b);
       else if (strcmp(tag,"</b>")==0)
        return(fb);

      else if (strcmp(tag,"<pre>")==0)
        return(pre);
       else if (strcmp(tag,"</pre>")==0)
        return(fpre);
        
       else if (strcmp(tag,"<i>")==0)
        return(i);
       else if (strcmp(tag,"</i>")==0)
        return(fi);

       else if (strcmp(tag,"<ul>")==0)
        return(ul);
       else if (strcmp(tag,"</ul>")==0)
        return(ful);

       else if (strcmp(tag,"<ol>")==0)
        return(ol);
       else if (strcmp(tag,"</ol>")==0)
        return(fol);

       else if (strcmp(tag,"<li>")==0)
        return(li);

       else if (strcmp(tag,"<p>")==0)
        return(arp);

       else if (strcmp(tag,"<hr>")==0)
        return(hr);

       else if (strcmp(tag,"<br>")==0)
        return(br);

       /* vediamo se il tag e' composto (es. <img src=edit.gif>) */
       else
        return (tag_composto(tag));

        }

int tag_composto(char * tag)
{

        char * pt;
        int val=0;

        if ((strstr(tag,"<body "))!=NULL)
         return(body);
        
        if ((strstr(tag,"<p "))!=NULL)
         return(arp);

        else if ((strstr(tag,"<hr "))!=NULL)
         return(hr);
   

        else if ((strstr(tag,"<font "))!=NULL)
        {
         if ((pt=strstr(tag,"size="))!=NULL) /* dimensione font settata ? */
          {
            pt=pt+5;
            if (*pt=='+')            /* il font deve essere ingrandito */
             dfont=(dfont+atoi(pt+1))%7;
            else if (*pt=='-')       /* il font deve essere rimpicciolito */
             dfont=(dfont-atoi(pt+1))%7;
           else
             dfont=(atoi(pt))%7;         /* cambia dimensione font */
               }
         return(font);
         }

        else if ((strstr(tag,"<img "))!=NULL)
         {
          if ((pt=strstr(tag,"src=\""))!=NULL)
           pt=pt+5;

          while (*(pt+val)!='.')
           val++;
          *(pt+val)='\0';

          file_grf=pt;

          return(img);
          }

        /* il tag risulta sconosciuto */
        else
         return(generic);

        }

