%{
int indent= 0, pre= 0, chars= 0, last_is_nl= 1;

static void tabs(int i)
{
  while(i>0){
    putchar('\t');
    i--;
    chars+=8;
    last_is_nl= 0;
  }
}

static void newlines(int i)
{
  if (chars<=indent*8)
    i--;
  if (!last_is_nl)
  {
    while(i>0){
      putchar('\n');
      i--;
    }
  }
  chars= 0;
  last_is_nl= 1;
  if (!pre)
    tabs(indent);
}

static void space(void)
{
  if (!pre && (chars + 1 >= 80))
    newlines(1);
  else {
    if (chars>indent*8) {
      chars++;
      printf(" ");
      last_is_nl= 0;
    }
  }
}

static void word(char text[])
{
  int leng= strlen(text);
  if (!pre && (chars + leng >= 80))
    newlines(1);
  chars+= leng;
  printf("%s", text);
  last_is_nl= 0;
  if (text[leng-1]=='\n')
    {chars= 0; /*last_is_nl= 1;*/}
}

static void unknown(char text[])
{
  printf("\n[unknown:%s]", text);
  newlines(1);
}

%}

%e 1500

tail	(" "[^>]*)?">"(\n)?

%%

"<!"[^>]*">"		;
"<"HTML{tail}		;
"</"HTML{tail}		;
"<"TITLE{tail}		;
"</"TITLE{tail}		{newlines(1);}
"<"HEAD{tail}		;
"</"HEAD{tail}		;
"<"BODY{tail}		{indent= 0;}
"</"BODY{tail}		;
"<"NEXTID{tail}		;

"<"A{tail}		;
"</"A{tail}		;
"<"ADDRESS{tail}	;
"</"ADDRESS{tail}	;

"<"TT{tail}		;
"</"TT{tail}		;
"<"B{tail}		;
"</"B{tail}		;
"<"I{tail}		;
"</"I{tail}		;
"<"U{tail}		;
"</"U{tail}		;
"<"EM{tail}		;
"</"EM{tail}		;
"<"STRONG{tail}		;
"</"STRONG{tail}	;
"<"CODE{tail}		;
"</"CODE{tail}		;
"<"SAMP{tail}		;
"</"SAMP{tail}		;
"<"KBD{tail}		;
"</"KBD{tail}		;
"<"VAR{tail}		;
"</"VAR{tail}		;
"<"DFN{tail}		;
"</"DFN{tail}		;
"<"CITE{tail}		;
"</"CITE{tail}		;

"<"PRE{tail}		{pre= 1; newlines(2);}
"</"PRE{tail}		{pre= 0; newlines(2);}

"<"BR{tail}		{newlines(1);}

"<"H[0-9]+{tail}	{indent= 0; newlines(2);}
"</"H[0-9]+{tail}	{indent= 0; newlines(2);}

"<"HR{tail}		{newlines(1);
			word("--------------------------------------------");
			newlines(1);}

"<"P{tail}		{newlines(2);}
"</"P{tail}		;

"<"UL{tail}		{newlines(1); indent++;}
"<"OL{tail}		{newlines(1); indent++;}
"<"LI{tail}		{newlines(2); word("* ");
			/*really need a stack to number OL lists*/}
"</"LI{tail}		;
"</"UL{tail}		{indent--; newlines(2);}
"</"OL{tail}		{indent--; newlines(2);}

"<"DL{tail}		{newlines(1); indent++;}
"<"DT{tail}		{indent--; newlines(2);}
"<"DD{tail}		{indent++; newlines(1);}
"</"DL{tail}		{indent--; newlines(2);}

"<"BLOCKQUOTE{tail}	{indent++; newlines(2);}
"</"BLOCKQUOTE{tail}	{indent--; newlines(2);}

"<"[^>]*">"		{unknown(yytext);}

"&lt;"			{word("<");}
"&gt;"			{word(">");}
"&amp;"			{word("&");}
"&quot;"		{word("\"");}
"&nbsp;"		{word(" "); /* oops! */ } 

"&"[^;]*";"		{unknown(yytext);}

[ \t\n]+		{if (pre) word(yytext); else space();}
[^ \t\n&<]+		{word(yytext);}

.			{unknown(yytext);}

%%

int yywrap() {return 1;}

int main ()
{
  yy_flex_debug= 0;
  yylex();
  putchar('\n');
  return 0;
}
