//------------------------------------------------------------------------------
// Copyright (c) 2020, Mike Shea
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Design Name:    c2asciidoc
// File Name:      c2asciidoc.c
// Target Devices: Linux Machine
// Tool versions:  GNU build tools
//
// Organization:   MJ Shea Consulting and Design LLC
//                 mike@mjshea.com
// Creation Date:  02/13/2020
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Description: This program takes a text file with special comment tags
// and creates a file that asciidoc can use to output an HTML file with
// the original text along with headers and a table of contents.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Notes:
// Special comment tags:
// /*  .H1 <title> */ - Create Level 1 Heading
// /*  .H2 <title> */ - Create Level 2 Heading
// /*  .H3 <title> */ - Create Level 3 Heading
// etc...
// /*  .TOC */        - Place Table of Contents
//
// Example
// =======
// c2asciidoc helloworld.c
// asciidoc --backend=xhtml11  hellowworld.c.adoc
//------------------------------------------------------------------------------
Table of Contents

1. Includes

//------------------------------------------------------------------------------
// Includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

2. Defines

//------------------------------------------------------------------------------
// Defines
#define MAX_LEN  (1024)
#define ADOC_EXT ".adoc"

3. Main Section

//------------------------------------------------------------------------------
// Main
int main (int argc, char *argv[])
{
    //------------------------------------------------------------
    // Variables
    char *infilename;
    char *outfilename;
    FILE *infile;
    FILE *outfile;
    char  line [MAX_LEN];
    char *head_front;
    char *head_end;
    bool  header;
    bool  toc;
    bool  example_open;
    int   level;
    int   ii;
    bool  toc_found;

    //------------------------------------------------------------
    // Command Line
    if ((2 > argc) || (2 < argc))
    {
        // No file name or more than one argument given.  Display Help text.
        printf("Text to Asciidoc Converter (c2asciidoc).               \n");
        printf("=======================================================\n");
        printf("Usage: c2asciidoc <infile>                             \n");
        printf("                                                       \n");
        printf("example: c2asciidoc helloworld.c                       \n");
        printf("         asciidoc --backend=xhtml11 helloworld.c.adoc  \n");
        printf(" - or -                                                \n");
        printf("         c2asciidoc helloworld.c                       \n");
        printf("         asciidoc --backend docbook45 helloworld.c.adoc\n");
        printf("         a2x      --format=pdf        helloworld.c.xml \n");
        printf("                                                       \n");
        printf("Transforms input text file with special tags into a    \n");
        printf("text file with asciidoc tags that creates an html file.\n");
        printf("                                                       \n");
        printf("tags:                                                  \n");
        printf("=====                                                  \n");
        printf("/* .H1 <title> */ - Create Level 1 Heading             \n");
        printf("/* .H2 <title> */ - Create Level 2 Heading             \n");
        printf("/* .H3 <title> */ - Create Level 3 Heading             \n");
        printf("etc...                                                 \n");
        printf("/* .TOC */        - Place Table of Contents            \n");
        printf("                                                       \n");
        return 1;
    }

    //------------------------------------------------------------
    // Input file name.
    infilename = argv[1];
    if (0 != access(infilename, F_OK))
    {
        fprintf(stderr, "Error: File %s does not exist.\n", infilename);
        return 1;
    }

    //------------------------------------------------------------
    // Open the input file.
    infile = fopen (infilename, "r" );
    if (NULL == infile)
    {
        fprintf(stderr,
                "Error: Unable to open fFile %s with read access.\n",
                infilename);
        return 1;
    }

    //------------------------------------------------------------
    // Open the output file.
    outfilename = malloc(strlen(infilename) + strlen(ADOC_EXT) + 1);
    if (NULL == outfilename)
    {
        fprintf(stderr,
                "Error: Unable to allocate memory for %s%s filename.\n",
                outfilename,
                ADOC_EXT);
        return 1;
    }

    sprintf(outfilename, "%s%s", infilename, ADOC_EXT);
    outfile = fopen (outfilename, "w" );
    if (NULL == infile)
    {
        fprintf(stderr,
                "Error: Unable to open file %s with write access.\n",
                outfilename);
        free(outfilename);
        return 1;
    }
    free(outfilename);

    //------------------------------------------------------------------------
    // Read through the input file looking for TOC and then rewind it to
    // the beginning
    toc_found = false;
    while(NULL != fgets(line,sizeof line, infile))
    {
        // Look for the TOC tag
        if (NULL != strstr(line, "/* .TOC */"))
        {
            toc_found = true;
            break;
        }
    }

    //------------------------------------------------------------------------
    // Write the header - Print the title underlined with equal signs
    fprintf(outfile, "%s\n", infilename);
    for (ii = 0; ii < strlen(infilename); ii++)
    {
        fprintf(outfile, "=");
    }
    fprintf(outfile, "\n");

    // If the TOC tag was found, place where requested.  Else, place it
    // in the left column
    if (true == toc_found)
    {
        fprintf(outfile, ":toc:\n");
        fprintf(outfile, ":toc-placement: manual\n");
    }
    else
    {
        fprintf(outfile, ":toc2:\n");
    }

    // Number the chapter titles
    fprintf(outfile, ":numbered:\n");

    // Open the listing block for our file text
    fprintf(outfile, "\n----\n");
    example_open = true;

    //------------------------------------------------------------------------
    // Move back to the beginning of the input file
    if ( fseek(infile, 0L, SEEK_SET) != 0 )
    {
        fprintf(stderr, "Error: Unable to rewind %s.\n", infilename);
        return 1;
    }

    //-----------------------------------------------------------------------
    // Read the input file line-by-line until the end of the file is reached
    // NULL will be returned once we hit the end
    while(NULL != fgets(line,sizeof line, infile))
    {

        //---------------------------------------------------
        // Look for the header tag
        head_front = strstr(line, "/* .H");
        head_end   = strstr(line, " */" );
        if ((NULL != head_front) && (NULL != head_end))
        {
            // Read the header level which is right
            // after the '/* H.'
            level  = (int)head_front[5] - (int)'0';
            header = true;
        }
        else
        {
            level  = 0;
            header = false;
        }

        //---------------------------------------------------
        // Look for the TOC tag
        if (NULL != strstr(line, "/* .TOC */"))
        {
            toc = true;
        }
        else
        {
            toc = false;
        }

        //---------------------------------------------------
        // Write to the output file
        if (true == header)
        {
            // Output the asciidoc text for a header
            // First close the example block if it is open
            if (true == example_open)
            {
                fprintf(outfile, "----\n\n");
                example_open = false;
            }

            // Insert a page break instruction
            fprintf(outfile, "<<<\n\n");

            // Now write equal signs for the header
            fprintf(outfile, "=");
            for (ii = 0; ii < level; ii++)
            {
                fprintf(outfile, "=");
            }

            // Write the title after removing the */
            head_end[0] = '\0';
            fprintf(outfile, " %s\n\n", &head_front[7]);
        }
        else if (true == toc)
        {
            // Output the asciidoc text for the TOC
            // First close the example block if it is open
            if (true == example_open)
            {
                fprintf(outfile, "----\n\n");
                example_open = false;
            }

            // Insert a page break instruction
            fprintf(outfile, "<<<\n\n");

            // Now write the toc tag
            fprintf(outfile, "toc::[]\n\n");
        }
        else
        {
            // If no tags found, output the source text
            // First open the example block if it is closed
            if (false == example_open)
            {
                fprintf(outfile, "----\n");
                example_open = true;
            }

            // Just print the line as is,
            fprintf(outfile,"%s", line);
        }
    }

    //------------------------------------------------------------------------
    // Write the closing comment tag
    if (true == example_open)
    {
        fprintf(outfile, "\n----\n");
    }

    //------------------------------------------------------------------------
    // close the files
    fclose(infile);
    fclose(outfile);

   return 0;
}