/***********************/
/* LOTOS-2-HTML filter */
/***********************/

/* Daniel Amyot, University of Ottawa, August 10, 1996 */
/* Translates a LOTOS spec into a readable HTML file. */
/* Compile using:  flex -i flex -i lot2html.lex */
/*                 gcc -O2 lexyy.c -o lot2html.exe */  

/* Keywords, comments, process names and type names   */
/* are enhanced with user-defined tags. Lists of processes */
/* and types, with hyperlinks, are automaticaly generated. */
/* ADTs from the International Standard are emphasized as well. */

/* The structure of the spec and upper/lowercase characters */
/* remain unchanged.  No grammatical checking done. */

/* Last update: September 14 1996 */

/************************************************************/

%option noyywrap
%{
    #define VERSION "0.2"
    #define TODAY "September 14, 1996"
    #define NBIDENTIFIERS 256
    #define IDENTIFIERLENGTH 64

    #include <stdio.h>
    #include <time.h>
    #include <ctype.h>
    #include <string.h>
    
    struct tm *date_time;
    time_t timer;
    char proctable[NBIDENTIFIERS][IDENTIFIERLENGTH];
    char sorttable[NBIDENTIFIERS][IDENTIFIERLENGTH];
    char typetable[NBIDENTIFIERS][IDENTIFIERLENGTH];
    int numproc=0;
    int numsort=0;
    int numtype=0;
    
    char /* Associated HTML Tags - Default values */
         /* KeyWords */
         BKW[128]="<B>",
         EKW[128]="</B>",
         /* Process Names */ 
         BPN[128]="<FONT color=\"#C00000\">",
         EPN[128]="</FONT>",
         /* Type Names */
         BTN[128]="<FONT color=\"#0000FF\">",
         ETN[128]="</FONT>", 
         /* Comments */
         BCOM[128]="<I><FONT color=\"#208000\">", 
         ECOM[128]="</FONT></I>",
         /* Type from International Standard */
         BTIS[128]="<FONT color=\"#4040C0\">",
         ETIS[128]="</FONT>";
%}

%%
\t          printf(" ");
\<          printf("&lt;");;
\>          printf("&gt;");
"&"         printf("amp;");
\"          printf("&quot");

accept|actualizedby|any|endlib|endproc|endspec|endtype|eqns|exit|for|forall|formaleqns|formalopns|formalsorts|hide|i|in|is|let|library|noexit|of|ofsort|opnnames|opns|par|renamedby|sorts|sortnames|stop|using|where { 
            /* MOST KEYWORDS */
            printf("%s%s%s", BKW, yytext, EKW);
    };

specification  {
            /* SPEC NAME */
            register int c;
    
            printf("%s%s%s", BKW, yytext, EKW);
            while ( (c=input()) == ' ' || (c == '\t') )
                printf(" ");

            /* Color spec name */
            printf("%s%c", BPN, c);
            while ( ((c=input())=='_') || isalnum(c) )
                    printf("%c", c);
            printf("%s%c", EPN, c);        
    };


behavior|behaviour  {
            /* BEHAVIOUR SECTION */
            printf("<HR><P>%s%s%s", BKW, yytext, EKW);
    };


process {
            register int c;
            register int i=0;
    
            printf("%s%s%s", BKW, yytext, EKW);
            while ( (c=input()) == ' ' || (c == '\t') )
                printf(" ");
            
            /* Get process names */
            proctable[numproc][i++]=c;
            while ( ((c=input())=='_') || isalnum(c) )
                    proctable[numproc][i++]=c;
            proctable[numproc][i++]='\0';
            printf("%s<A NAME=\"P_%s\">%s</A>%s%c", 
                   BPN, proctable[numproc], proctable[numproc], EPN, c);
            numproc++;
    };


type  {
            register int c;
            register int i=0;
    
            printf("%s%s%s", BKW, yytext, EKW);
            while ( (c=input()) == ' ' || (c == '\t') )
                printf(" ");
            
            /* Get type names */
            typetable[numtype][i++]=c;
            while ( ((c=input())=='_') || isalnum(c) )
                    typetable[numtype][i++]=c;
            proctable[numtype][i++]='\0';
            printf("%s<A NAME=\"T_%s\">%s</A>%s%c", 
                   BTN, typetable[numtype], typetable[numtype], ETN, c);
            numtype++;
    };


Boolean|Bool|FBoolean|FBool|Element|Set|BasicEmptyString|NonEmptyString|RicherNonEmptyString|String0|String1|String|BasicNaturalNumber|Nat|NaturalNumber|NatRepresentations|HexNatRepr|HexString|HexDigit|DecNatRepr|DecString|DecDigit|OctNatRepr|OctString|OctDigit|BitNatRepr|BitString|Bit|Octet|OctetString {
        /* ADT Type from International Standards */
        printf("%s%s%s", BTIS, yytext, ETIS);
    };


"(*"        {
            /* COMMENTS */
            register int c;
            printf("%s(*", BCOM);
            for ( ; ; )
                {
                while ( (c = input()) != '*' &&
                        c != EOF )
                    switch (c) {
                        case '\t' :         printf(" "); break;
                        case '<'  :         printf("&lt;"); break;
                        case '>'  :         printf("&gt;"); break;
                        case '&' :          printf("&amp;"); break;
                        case '\"' :         printf("&quot"); break;
                        default :           printf("%c", c);
                    };    /* text comment */

                if ( c == '*' )
                    {
                    printf("*");
                    while ( (c = input()) == '*' )
                        printf("*");
                    if ( c == ')' )
                        {
                           /* End of comment */
                           printf(")%s", ECOM);
                           break;    
                        }
                    else
                     switch (c) {
                        case '\t' :         printf(" "); break;
                        case '<'  :         printf("&lt;"); break;
                        case '>'  :         printf("&gt;"); break;
                        case '&' :          printf("&amp;"); break;
                        case '\"' :         printf("&quot"); break;
                        default :           printf("%c", c);
                    };    /* Comment body chracter */
                    }

                if ( c == EOF )
                    {
                    fprintf(stderr, "Warning: EOF in comment.");
                    printf(")%s", ECOM);
                    break;
                    }
                }
            }

[a-z0-9_][a-z0-9_]*  {
        /* IDENTIFIERS */;
        printf("%s", yytext);
    };

%%

/**************************************************************/

int id_cmp(const void *j, const void *k)
    /* Compares two identifiers.  Used by qsort. */
    {
        return strnicmp(j, k, IDENTIFIERLENGTH);
    }
     

/**************************************************************/

int get_tags(def_file_name)
char *def_file_name;
    /* HTML tags definitions */
    {
        FILE *def_file;
        char tag[128], value[128];
        int register i;
        int register j;

        /* Open definition file */
        if ((def_file = fopen(def_file_name, "r")) == NULL)
            {
                fprintf(stderr, "Warning: Unknown definition file. Using internal defaults.\n\n");
                return(0);
            }
        
        /* Parse and adjust tag variables */
        while (!feof(def_file))
        {
           i=0;
           tag[i]=fgetc(def_file);
           switch (tag[i])
           {
               case ' ' :
               case '\t': 
               case '\n': break;
               
               case ';' : /* comment */
                          while (fgetc(def_file) != '\n');
                          break;
                          
               case 'E' :
               case 'B' : /* Tag name */
                          while ( isalpha(tag[++i]=fgetc(def_file)) );
                          if (tag[i]!='\n') while (fgetc(def_file) != '\n');
                          tag[i]='\0';
                          /* Get value */
                          j = 0;
                          while ( (value[j++]=fgetc(def_file)) != '\n' );
                          value[j-1]='\0';
                          fprintf(stderr, "TAG CHANGED: %s=%s\n", tag, value);
                          if (!strcmp(tag, "BKW")) strcpy(BKW, value);
                          else if (!strcmp(tag, "EKW")) strcpy(EKW, value);
                          else if (!strcmp(tag, "BCOM")) strcpy(BCOM, value);
                          else if (!strcmp(tag, "ECOM")) strcpy(ECOM, value);
                          else if (!strcmp(tag, "BPN")) strcpy(BPN, value);
                          else if (!strcmp(tag, "EPN")) strcpy(EPN, value);
                          else if (!strcmp(tag, "BTN")) strcpy(BTN, value);
                          else if (!strcmp(tag, "ETN")) strcpy(ETN, value);
                          else if (!strcmp(tag, "BTIS")) strcpy(BTIS, value);
                          else if (!strcmp(tag, "ETIS")) strcpy(ETIS, value);
                          else fprintf(stderr, "Warning: error in definition file on \"%s\".\n", tag);
                          break;

               
               default :  if (isalnum(tag[i]))
                             fprintf(stderr, "Warning: error in definition file on '%c'.\n", tag[i]);
           }        
        }
       
        fclose(def_file);
        return(0);
    }

/**************************************************************/

main( argc, argv )
int argc;
char **argv;
    {
    int register i;
    char title[128]="Untitled";

    /* SDTIN or file? */
    ++argv, --argc;  /* skip over program name */
    yyin = stdin;
    if ( argc > 0 )
        if (strnicmp(argv[0], "-h", 2))
            {
            if (!strnicmp(argv[0], "-d", 2))
                {
                    get_tags(argv[1]);
                    if (argc > 2)
                        if ((yyin = fopen( argv[2], "r" ))==NULL)
                           {
                               fprintf(stderr, "Unknown input file. Translation aborted.\n\n");
                               exit(0);
                           }
                        else 
                           strcpy(title, argv[2]);
                }
            else
                if ((yyin = fopen( argv[0], "r" ))==NULL)
                   {
                       fprintf(stderr, "Unknown input file. Translation aborted.\n\n");
                       exit(0);
                   }
               else
                   strcpy(title, argv[0]);
               
            }
        else
        /* HELP FILE */
        {
            printf("\n\tlot2html, by Daniel Amyot (damyot@csi.uottawa.ca).\n");
            printf("\tVersion %s, %s\n\n", VERSION, TODAY);

            printf("\tUsage:  lot2html [-d DefFile] [InFile] [>OutFile]\n");
            printf("\t        lot2html -h      (get this help file)\n\n");
            
            printf("\tWhere:  DefFile = Definition file (HTML tags). Internal default values.\n");
            printf("\t        InFile  = Input file (in LOTOS). Default is  stdin\n");
            printf("\t        OutFile = Output file (in HTML). Default is  stdout\n");
            printf("\tSee also the configuration file: lot2html.def\n\n");
            exit(0);
        }
     
    /* Header */
    printf("<!doctype html public \"-//IETF//DTD HTML//EN\">\n");
    printf("<HTML>\n<HEAD>\n", (argc>0?argv[0]:"STDIN") );
    printf("<META NAME=\"GENERATOR\" CONTENT=\"lot2html, version %s\">\n", VERSION);
    printf("<META NAME=\"AUTHOR\" CONTENT=\"Daniel Amyot\">\n");
    time(&timer);
    date_time=localtime(&timer);
    printf("<!--\n    Translated on %s-->\n", asctime(date_time));
    printf("\t<TITLE>%s</TITLE>\n</HEAD>\n\n<BODY>", title );
    printf("<H1>%s</H1>\n", title );
    printf("<UL>\n    <LI><A HREF=\"#spec\">LOTOS Specification</A>\n\
    <LI><A HREF=\"#processlist\">Process list</A>\n\
    <LI><A HREF=\"#typelist\">Type list</A>\n</UL>\n<P>\n<HR>\n\n");


    /* Specification */
    printf("<H2><A NAME=\"spec\">LOTOS Specification</A></H2>\n<PRE>\n");
    yylex();
    printf("</PRE>\n<HR>\n\n");

    /* List of Processes */ 
    printf("<H2><A NAME=\"processlist\">List of Processes</A></H2>\n<UL>\n");
    qsort(proctable, numproc, sizeof(proctable[0]), id_cmp); 
    for (i=0; i< numproc; i++)
        printf("<LI>process <A HREF=\"#P_%s\">%s</A><BR>\n", proctable[i], proctable[i]);
    printf("</UL>\n<P>\n<HR>\n\n");
            
    /* List of Types */
    printf("<H2><A NAME=\"typelist\">List of Types</A></H2>\n<UL>\n");
    qsort(typetable, numtype, sizeof(typetable[0]), id_cmp); 
    for (i=0; i< numtype; i++)
        printf("<LI>type <A HREF=\"#T_%s\">%s</A><BR>\n", typetable[i], typetable[i]);
    printf("</UL>\n<P>\n<HR>\n\n");

    /* Footer */
    printf("<I>Converted in HTML using <B><FONT color=\"#0000FF\">lot2html</FONT></B> (ver. %s, &copy; Daniel Amyot), %s</I><P>\n</BODY>\n</HTML>", 
            VERSION, asctime(date_time) );

    }
