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