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

#define SECTION		128
#define PAR		129
#define TABPAR		130
#define BREAK		131
#define ITEM		132
#define TABPARSET 	133
#define FILL		134
#define NOFILL		135

char namebuf[256];
int  ivalue;
%}

%START SHEAD 
%%
^\.UC.*\n			;
^\.TH.*\n			;
^\.ft.*\n			;
\\fI				return ('`');
\\fP				return ('\'');
^\.nf[ \t\n]*			return (NOFILL);
^\.fi[ \t\n]*			return (FILL);
^\.SH[ \t]*			BEGIN SHEAD;
<SHEAD>.*\n			{ char *cp = yytext;
				  char *np = namebuf;

				  BEGIN 0; 
				  while (*cp == ' ' || *cp == '\t')
				   { cp++;
				   }
				  while (*cp != '\n')
				   { *np++ = *cp++;
				   }
				  *np = '\0';
				  return (SECTION);
				}
^\.PP[ \t\n]*			return (PAR);
^\.TP[ \t\n]*			return (TABPAR);
^\.TP[ \t]*-?[0-9]+[ \t\n]*	{ char *cp = yytext+3;
				  sscanf (cp, "%d", &ivalue);
				  return (TABPARSET);
			 	}
^\.B[ \t]*.*\n			{ char *cp = yytext+2;
				  char *np = namebuf;
				  while (*cp == ' ' || *cp == '\t')
				   { cp++;
				   }
				  while (*cp != '\n')
				   { *np++ = *cp++;
				   }
				  *np = '\0';
				  return (ITEM);
				}
^\.br[ \t\n]*			return (BREAK);
\n				return (yytext[0]);
.				return (yytext[0]);
%%

int leftMargin = 0;

#define TEXT_MARGIN 14
#define HEADER_MARGIN 1

int newSection = 0;
int rawBreak = 0;
int fill = 1;

main()
{
	int c, l;
	int itemMargin = TEXT_MARGIN + 8;

	leftMargin = 0;
	outs ("/*=~=~=~=~ McGill-Computer-Vision-and-Robotics-Laboratory\
--C-Module ~=~=~=~=");
	setPrefix (" *");
	outc ('\n');
	leftMargin = TEXT_MARGIN;

	while ((c = yylex()) != 0)
	 { switch (c)
	    { case SECTION:
	       { leftMargin = HEADER_MARGIN;
		 outc ('\n');
		 if (!rawBreak)
		  { outc ('\n');
		  }
		 outs (namebuf);
		 leftMargin = TEXT_MARGIN;
		 advanceTo (leftMargin);
		 newSection = 1;
		 break;
	       }
	      case PAR:
	       { leftMargin = TEXT_MARGIN;
		 if (!newSection)
		  { outc ('\n');
		    if (!rawBreak)
		     { outc ('\n');
		     }
		  }
		 break;
	       }
	      case TABPAR:
	       { leftMargin = itemMargin;
		 if (!newSection)
		  { outc ('\n');
		    if (!rawBreak)
		     { outc ('\n');
		     }
		  }
		 break;
	       }
	      case TABPARSET:
	       { leftMargin = itemMargin = TEXT_MARGIN + ivalue;
		 if (!newSection)
		  { outc ('\n');
		    if (!rawBreak)
		     { outc ('\n');
		     }
		  }
		 break;
	       }
	      case ITEM:
	       { leftMargin = TEXT_MARGIN;
		 outs (namebuf);
	         leftMargin = itemMargin;
		 advanceTo (leftMargin);
		 break;
	       }
	      case BREAK:
	       { outc ('\n');
		 break;
	       }
	      case FILL:
	       { fill = 1;
		 break;
	       }
	      case NOFILL:
	       { fill = 0;
		 break;
	       }
	      case '\n':
	       { if (fill)
		  { outc (' ');
		    rawBreak = 0;
		  }
	         else
		  { outc ('\n');
		    rawBreak = 1;
		  }
		 break;
	       }
	      default:
	       { outc (c);
		 rawBreak = 0;
		 break;
	       }
	    }
	   if (c != SECTION)
	    { newSection = 0;
	    }
	 }

	outc ('\n');
	outc ('\n');
	leftMargin = 0;
	outs ("~=~=~=~=~=~= McGill-Computer-Vision-and-Robotics-Laboratory\
 ~=~=~=~=~=~=*/");
	outc ('\n');
}

#define TABSIZE 8

static int column = 0;
static int maxColumn = 78;
static int wordStart;
static char linebuf[256];
static char tempbuf[256];
static char prefixString[256] = "";

static char lastc = -1;
static int eolw = 0;
static int bp = 0;
static int pLength = 0;
static int pColumn = 0;
static int breakSet = 0;

setPrefix(s)
char *s;
{
	int i;

	strcpy (prefixString, s);
	pLength = strlen (prefixString);
	pColumn = 0;
	for (i=0; i<pLength; i++)
	 { pColumn = (prefixString[i] == '\t') ? 
		     (pColumn/TABSIZE+1)*TABSIZE : pColumn+1;
	 }
}


advanceTo (c)
int c;
{
	/* Pad with spaces up to the current column */

	int i;

	c = c + pColumn;

	if (column < c)
	 {
	   for (i = column/TABSIZE; i < c/TABSIZE; i++)
	    { linebuf[bp++] = '\t';
	      column = (column/TABSIZE+1)*TABSIZE;
	    }
	   for (i = column%TABSIZE; i < c%TABSIZE; i++)
	    { linebuf[bp++] = ' ';
	      column++;
	    }
	   if (column != c)
	    { printf ("INTERNAL ERROR: c = %d, column = %d\n", c, column);
	    }
	 }
}

newline()
{
	int i;

	strcpy (linebuf, prefixString);

	/* Now add spaces for the left margin */

	eolw = bp = pLength;
	column = pColumn;
	advanceTo (leftMargin);
}

outc(c)
char c;
{

	int i, k;

	if (lastc == -1)
	 { newline();
	 }

	if (c == '\n')
	 { if (breakSet)
	    { newline();
	    }
	   if (!isspace(lastc))
	    { eolw = bp;
	    }
	   linebuf[eolw] = '\0';
	   puts (linebuf);
	   breakSet = 1;	   
	 }
	else
	 { if (breakSet)
	    { newline();
	    }
	   breakSet = 0;
	   if (!isspace(lastc) && isspace(c))
	    { eolw = bp;
	    }
	   linebuf[bp++] = c;
	   column = (c == '\t') ? (column/TABSIZE+1)*TABSIZE : column+1 ;
	 }

	if (column > maxColumn && !isspace(c))
	 { char cc;
	   int tl;

	   if (!isspace(c) && eolw == pLength)
	    { eolw = bp-1;
	    }
	   cc = linebuf[eolw];
	   linebuf[eolw] = '\0';
	   puts (linebuf);
	   linebuf[eolw] = cc;

	   for (k = eolw; k < bp; k++)
	    { if (!isspace (linebuf[k]))
	       { break;
	       }
	    }
	   i = 0;
	   while (k < bp)
	    { tempbuf[i++] = linebuf[k++];
	    }
	   tl = i;

	   strcpy (linebuf, prefixString);
	   column = pColumn;
	   eolw = bp = pLength;
	   advanceTo (leftMargin);
	   for (i=0; i<tl; )
	    { linebuf[bp++] = tempbuf[i++];
	      column++;
	    }
	 }

	lastc = c;
}

outs (s)
char *s;
{
	char c;

	while (c = *s++)
	 { outc (c);
	 }
}

yywrap()
{
	return (1);
}
