Here is how the C2AsciiDoc program works.
First, the C2AsciiDoc program opens the text file for reading and creates an output file for writing. It names the output file the same as the input file and appends a new file type ".adoc" to the end. For helloworld.c
it creates helloworld.c.adoc
.
//------------------------------------------------------------
// 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);
Next, it reads through the input file and looks for the ".TOC" tag. If found, it knows where to put the table of contents.
//------------------------------------------------------------------------
// 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;
}
}
If no ".TOC" tag is found, it will tell AsciiDoc to put the table of contents to the left of the code listing. In other words, if a ".TOC" tag was found, a :toc:
tag will be written to the output file. If no ".TOC" tag is found, a :toc2:
tag will be written. The former says to include the table of contents in line with the output. The later says to put the table of contents to the left of the the output.
ow knowing the name of the file and where you want to put the table of contents, the header information is written to the output file and four dashes are written to open a listing block.
//------------------------------------------------------------------------
// 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;
Next, starting at the top of the file, the program reads your source code line-by-line looking for the tags listed above.
//------------------------------------------------------------------------
// 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;
}
...
If it finds one of the tags, the listing block is closed, the AsciiDoc information is written, and a new listing block is started.
To prevent empty listing blocks, as might happen if you put a ".H1" tag right after a ".TOC" tag, the program keeps track of whether the listing block is open or closed using the example_open
boolean value. When a tag is encountered, the listing block is closed only if it is opened. Likewise, when source data is found after a tag, a new listing block is started only if it is currently closed.
To force a page break when you use AsciiDoc to create a PDF document, a "<<<" tag is added to the output. This addition is ignored when formatting as markup or HTML.
//---------------------------------------------------
// 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);
}
Here is a link to the AsciiDoc HTML formatted output for this program.
And, here is a link to the source. Feel free to use this as you wish. If you download it, copy it, use it, change it, or whatever, it becomes yours.