#!/bin/sh

TMP_DIR="/tmp"

trap "/bin/rm -r -f $TMP_DIR/ref.tmp.* $TMP_DIR/ref.tmp.?.awk" 0 1 2 3 15

#{{{}}}
#{{{  maybe show help
if test x$1 = x-h
then
   cat <<\HERE

USAGE:
ref2ocl AWK sourcefile roff outfile
 for generating documents:  AWK is the awk-command to use
                            sourcefile is :-)

ref2ocl AWK sourcefile [extension]
 for generating ocl source: AWK is your the awk-command to use
                            sourcefile is :-)
                            extension may be  an  postfix  for  sourcefile,  if
                              given, sourcefileextension will be added in front
                              and after including libary references.

The reference source may use:

 command            | effect
                    |  help browser           | reference-file
 ----------------------------------------------------------------------------
 text               | will be printed         | will be printed
 ----------------------------------------------------------------------------
 fold               | a subnode in help tree  | chapter
  comments:         |   first word starting with @ will not be used as
    start="@"       |   for the printed header. But it will be used for
     end =""        |   distinguishing the chapters/nodes!
                    | if same header used,    |   if same header used,
                    |   use previous fold!    |   leave a hint
 ----------------------------------------------------------------------------
 @ref-doc-only      | write only the man page to standard-out
 ----------------------------------------------------------------------------
 @ref-class-id      | use class-d's n,n+1,..  | none
 ----------------------------------------------------------------------------
 @ref-menu          | specify menu string and | none
                    | subnode names:          -------------------------------
                    | @ref-menu n op1 str1 .. args
                    | n is the default action, highlighted at startup
                    | op1,op2,.. can be quit - exit browser
                    |                   ret  - return to upper node
                    |                   next - page )down
                    |                   prev - page-up
                    |                   kill - copy node to kill-buffer
                    |               or  a user defined function, which has to
                    |                   return a value:
                    |                     0 - continue current page afterwards
                    |                     1 - quit afterwards like quit
                    |
                    | str1,str2,..  can be any string, not containing " "
                    | args can be any list of characters, not containing " "
 ----------------------------------------------------------------------------
 @ref-see-also      | none                    | specify text for see-also
                    |                         | hint. Leading C will be cut
                    |                         | and used to start as chapter
 ----------------------------------------------------------------------------
 @ref-fun           | make menu entry, call   | none
                    | first word as function  |
                    | use following as title  |
                    | function must be deffun!|
                    | returning a value:      |
                    |  0 continue current page|
                    |    afterwards           |
                    |  1 quit from infobrowser|
                    |    afterwards           |
 ----------------------------------------------------------------------------
 @ref-top-start-box | specify the box char-   | title, if not underline/bold
 @ref-top-end-box   | acters:                 | none
 @ref-sub-start-box |   top-left top top-right| none
 @ref-sub-end-box   |   left right            | none
                    |   bot-left bot bot-right|
 ----------------------------------------------------------------------------
 @ref-start-picture | Start and end the unmodified output of the given text.
 @ref-end-picture   | No formatting will be done.
 ----------------------------------------------------------------------------
 @ref-start-item .. | Start and end a indented block, not handled as
 @ref-end-item      | chapter/reference-node
 ----------------------------------------------------------------------------
 @ref-start-tbl ..  | Start and end the display of a table. the argument to
 @ref-end-tbl       | start are name,length pairs for the fields
                    | Items are separetded by @@
                    | A @@ between the arguments to @ref-start-tbl generate
                    | additional space between the columns
 ----------------------------------------------------------------------------
 @ref-comment-start | text between will be ignored
      :             |   nested commentsare allowed
 @ref-comment-end   |
 ----------------------------------------------------------------------------
 @ref-indent l r i s| This command is only allowed outside of text nodes!
                    | i specifies the indent  |
                    | of items in the text    |
                    | l/r specify first/last  |
                    |    used for text        |
                    | s additional spaces,    | s=0 -> .ad l
                    |    allowed for blockfill| s>0 -> .ad b
 ----------------------------------------------------------------------------
 fold, with 1st     | text inside will be ignored
  fold-comment-word |   nested commentsare allowed
 =@ref-comment-start|
 ----------------------------------------------------------------------------
 @ref-lib filename tags ..
                    | none                    | none
                    | Make uses thee entries to collet all needed info files.
 ----------------------------------------------------------------------------
 {{{  @ref-header name  | A fold like this will change the display of the
 @ref-title foobar      | node/chapter 'name' in the following way:
 @ref-author foo        |   use 'foobar' as chapter/node header
      :                 |   add all authors
 @ref-author bar        |      roff:    below the header
 abstract for foobar    |      browser: as list behind 'name'
 }}}                    |   add he abstract as small left and right indented
                        | No other folds are allowed inside this description!
                        | The definition has to be made outside the definition
                        | of 'name'!
 ----------------------------------------------------------------------------
 @...               | none                    | none
                    |   put unchanged in the output, @if..,.. can be used.

 Each toplevel fold may be accessed by `fold-comment` as help-browser, if
 @use ( REF-TREE )
 is active.

 toplevel folds are put into the reference-file, if
    @use ( `fold-comment`-REF )
 is active.

 demand-load is used.
HERE
   exit
fi
#}}}

#{{{  generate awk scripts
#{{{  common stuff
cat >$TMP_DIR/ref.tmp.o.awk <<\HERE
BEGIN {
#   {{{  constants
   long_line="                                                                                                                        "
   BACKSPACE=sprintf("%c",8)
   DQ=sprintf("%c",34)
#   {{{  some strings, used for generating the ocl-source
   start_ref = "@if-using(%s-REF)\n@reference-begin\n"
   end_ref = "@reference-end\n@fi"
   start_tree="@if-using(REF-TREE)"
   end_tree="@fi"
   start_ref_class = start_tree"\n@use(U-C-%s)\n@reference-begin-class %s\n"
   end_ref_class = "@reference-end\n"end_tree
#   }}}
   case_entry_lg=128
   ref_indent=8
   ref_first=4
   info_indent=substr(long_line,1,ref_first-1)
   ref_last=77
#   }}}
#   {{{  default values for menu,args,see also,boxes
#   {{{  menu and arguments
   MENU_DEF[0]=1
   MENU_OPS[0]=4
   MENU[0]=" Quit Return #(next-page) Back"
   MENU_OP["0#0"]="quit"
   MENU_OP["0#1"]="ret"
   MENU_OP["0#2"]="next"
   MENU_OP["0#3"]="prev"
   MENU_OP["0#4"]="kill"
   ARGS[0]="0123456789<>[]@$"
   VIEWER[0]="ref-viewer-0"
   VIEWER_ID["1 quit Quit ret Return next #(next-page) prev Back  kill Kill  0123456789<>[]@$"]=0
   known_menu=1
   cur_menu=0
#   }}}
   ADD="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@$()<>{}[]'`;:/\\_^#+-=,.&|"
   COMPLAIN=sprintf("%sinvalid %s  %sinput! ",DQ,DQ,DQ)
   box["@ref-top-start-box"]="********"
   box["@ref-top-end-box"]="********"
   box["@ref-sub-start-box"]="+-+||+-+"
   box["@ref-sub-end-box"]="+-+||+-+"
   SEE_ALSO="See also: %s"
#   }}}
#   {{{  ocl init
   commenting=0
   item_txt="\n"
   known_classes = 0
   known_functions = 0
   top_funs=""
#   }}}
#   {{{  roff init
   bold="\\fB"
   norm="\\fP"
   tbl_limiter=sprintf("%c",27)
   commenting=0
   doc_out=0
   ritem_txt="\n"
   new_para=".LP"
#   }}}
#   {{{  prepare info tree parsing
   fold_level=0
   level = 0
   ref_buffer = ""
   info_buffer_use = 0
   ref_error = ""
   lines = 0
   use_id = 1
   picture = 0
   item_level = 0
   tbl_size=0
#   }}}
}
#{{{  error
(ref_error!="") {
   if (ref_error!="-") {
      printf("@error %s line %s: %s\n",FILENAME,lines,ref_error)
      ref_error="-"
   }
   next
}
#}}}
#{{{  count lines
{ if (infile==FILENAME)
     lines++
  else {
     infile=FILENAME
     lines=1
  }
  if ($1=="@{{{") {
     if ($2=="@ref-comment-start")
        fold_typ[fold_level]=1
     else
        fold_typ[fold_level]=0
     if (fold_typ[fold_level++]) {
        commenting++
        next
     }
  } else if ($1=="@}}}") {
     if (fold_typ[--fold_level]) {
        commenting--
        if (commenting<0)
           ref_error="no matching fold-comment left!"
        next
     }
  }
}
#}}}
#{{{  @ref-comment-start
/^@ref-comment-start/ {
  commenting++
  next
}
#}}}
#{{{  @ref-comment-end
/^@ref-comment-end/ {
   if (!commenting)
       ref_error="no comment started!"
   commenting--
   next
}
#}}}
#{{{  @ref-indent
/^@ref-indent [0123456789]+ +[0123456789]+ +[0123456789]+( +[0123456789]+)? *$/ && level==0 {
   ref_first=$2
   ref_last=$3
   ref_indent=$4
   ref_spaces=$5
   info_indent=substr(long_line,1,ref_first-1)
   next
}
#}}}
commenting!=0 || (level==0 && /^$/) { next }
HERE
cp $TMP_DIR/ref.tmp.o.awk $TMP_DIR/ref.tmp.r.awk
#}}}
#{{{  ocl-stuff
cat >>$TMP_DIR/ref.tmp.o.awk <<\HERE
#{{{  header
/^@\{\{\{  @ref-header +[^ ]* *$/ {
   header_name=$3
   next
}
header_name!="" {
   if ($1=="@ref-title")
      title[header_name]=substr($0,12)
   else if ($1=="@ref-author") {
      if (author[header_name]=="")
         author[header_name]=" ("
      else
         author[header_name]=author[header_name]","
      author[header_name]=author[header_name] substr($0,13)
   } else if ($1=="@}}}")
      header_name=""
   else
      abstract[header_name]=abstract[header_name] $0 " "
   next
}
#}}}
#{{{  flushing text to out
#{{{  link used -> print it first
link_txt!="" {
   printf(start_ref_class,link_class,link_class)
   print(link_txt)
   print(end_ref_class)
   link_txt=""
}
#}}}
#{{{  class-box used
box_txt!="" {
   if (box_head==1 || box_type!="        ") {
      if (box_center==1)
         box_indent=substr(long_line,1,ref_first-1+(ref_last-ref_first-3-length(box_txt))/2)
      else
         box_indent=info_indent
      printf(start_ref_class,box_class,box_class)
      if (box_head==0)
         print("")
      if (substr(box_type,1,3)!="   ") {
         txt=box_indent substr(box_type,1,1)
         for (i=length(box_txt)+2;i;i--)
            txt=txt substr(box_type,2,1)
         txt=txt substr(box_type,3,1)
         print(txt)
      }
      print(box_indent substr(box_type,4,1)" "box_txt" "substr(box_type,5,1))
      if (substr(box_type,6,3)!="   ") {
         txt=box_indent substr(box_type,6,1)
         for (i=length(box_txt)+2;i;i--)
            txt=txt substr(box_type,7,1)
         txt=txt substr(box_type,8,1)
         print(txt)
      }
      if (box_head==1) {
         print("")
#         {{{  maybe add abstract
         if (level==1 && abstract[header[level]]!="") {
            s=abstract[header[level]]
            of1=1
            for (;of1<=length(s);)
               if (substr(s,of1,1)==" ")
                  of1++
               else {
                  for (of=1;of1+of<=length(s) && substr(s,of1+of,1)!=" ";of++);
                  info_buffer[info_buffer_use++]=substr(s,of1,of)
                  of1+=of
               }
            info_buffer[info_buffer_use++]="\n"
            do_abstract=1
         }
#         }}}
      }
      print(end_ref_class)
   }
   box_txt=""
}
#}}}
#{{{  special line and buffer used -> flush it
/^@/ || do_abstract==1 {
#   {{{  change indentation for abstract
   if (do_abstract) {
      ref_first+=ref_indent
      ref_last-=ref_indent
      info_indent=substr(long_line,1,ref_first-1)
   }
#   }}}
#   {{{  generate dummy text for item flush
   if (info_buffer_use==0 && item_txt!="\n" && level>0)
      info_buffer[info_buffer_use++]=" "
#   }}}
#   {{{  if info-buffer used, flush it boxed
   if (info_buffer_use!=0) {
      printf(start_ref_class,class_id[level],class_id[level])
      of=0
      if (info_buffer[0]=="\n")
         txt="\n"
      else
         txt=""
      while (of<info_buffer_use)
         if (info_buffer[of]!="\n")
          {
#             {{{  set of1,of2 to begin, after end of words of current line
             of1=of
             of2=of+1
             if (picture==1)
                space=0
             else {
                space=ref_last-ref_first+1-length(info_buffer[of1])
                while (of2<info_buffer_use && (length(info_buffer[of2])<space && info_buffer[of2]!="\n"))
                   space-=length(info_buffer[of2++])+1
             }
#             }}}
             if (txt!="") txt=txt"\n"
             txt=txt info_indent
#             {{{  last line no fill
             if (of2==info_buffer_use || info_buffer[of2]=="\n")
                space=0
#             }}}
#             {{{  append words, maybe fill spaces
             for (of=of1;of<of2;of++) {
                txt=txt info_buffer[of]
#                {{{  get number of needed limiter spaces
                xx=space-(of2-of)+2
                if (xx>ref_spaces)
                   xx=ref_spaces
                else if (xx<0)
                   xx=0
                space=space-xx
#                }}}
                txt=txt substr(long_line,1,xx+1)
             }
#             }}}
#             {{{  empty line, force line break
             if (of2<info_buffer_use && info_buffer[of2]=="\n")
                txt=txt"\n"
#             }}}
             info_indent=substr(long_line,1,ref_first-1)
             item_txt="\n"
          }
         else
            of++
      print(txt)
      print(end_ref_class)
      info_buffer_use=0
   }
#   }}}
#   {{{  maybe restore indentation (abstract)
   if (do_abstract==1) {
      ref_first-=ref_indent
      ref_last+=ref_indent
      info_indent=substr(long_line,1,ref_first-1)
      do_abstract=0
   }
#   }}}
}
#}}}
#}}}
#{{{  ref/opp statements
#{{{  tbl-handling
#{{{  start-tbl
/^@ref-start-tbl/ {
   if (tbl_size || picture)
      ref_error="tbl not allowed here"
   else {
#      {{{  get head/tail string for info
      tbl_head="|"
      tbl_line="+"
      x=""
      for (of=2;of<NF;)
         if ($of=="@@")
            if (of>2 && of<NF) {
               x="+"
               y="|"
               of++
            } else {
               ref_error="invalid limiter place"
               next
         } else {
            if ($(of+1)<=0) {
               ref_error="invalid tbl-pattern-size "$(of+1)
               next
            }
            tbl_lim[tbl_size]=y"|"
            tbl_len[tbl_size++]=$(of+1)
            tbl_line=tbl_line x "-"
            tbl_head=tbl_head y " "
            x=substr($of,1,$(of+1))
            for (of1=length(x);of1>0;of1--)
               tbl_line=tbl_line"-"
            tbl_head=tbl_head x
            for (of1=$(of+1)-length(x)+1;of1>0;of1--) {
               tbl_line=tbl_line"-"
               tbl_head=tbl_head" "
            }
            tbl_head=tbl_head"|"
            tbl_line=tbl_line"+"
            x=""
            y=""
            of+=2
         }
      tbl_lim[tbl_size]="|"
#      }}}
      xx=length(tbl_line)
      if (tbl_size==0)
         ref_error="no tbl parameter given"
      else if (xx>ref_last-ref_first+1)
         ref_error="tbl to long"
      else {
#         {{{  get leading indentation for tab
         tbl_indent=""
         of=(ref_last-ref_first-xx)/3+ref_first
         tbl_indent=substr(long_line,1,of-1)
#         }}}
#         {{{  print info-tree
         printf(start_ref_class,class_id[level],class_id[level])
         print("")
         print(tbl_indent tbl_line)
         print(tbl_indent tbl_head)
         print(tbl_indent tbl_line)
         print(end_ref_class)
#         }}}
      }
   }
   next
}
#}}}
#{{{  end-tbl
/^@ref-end-tbl/ {
   if (tbl_size==0)
      ref_error="no tbl active"
   else {
      tbl_size=0
#      {{{  print info-tree
      printf(start_ref_class,class_id[level],class_id[level])
      print(tbl_indent tbl_line)
      print(end_ref_class)
#      }}}
   }
   next
}
#}}}
#{{{  inside tbl, no commands, other the @use,@if-using,@fi are allowed
/^@[^@ ]/ && tbl_size>0 {
   if ((substr($0,1,9)!="@if-using")&&(substr($0,1,3)!="@fi")&&(substr($0,1,4)!="@use")) {
      ref_error="tbl crashed"
      next
   }
}
#}}}
#{{{  text -> format it
/^([^@]|@@|$)/ && tbl_size>0 {
#   {{{  decode and format table data
   of1=0
   for (of=1;of<=NF;of++)
      if ($of=="@@")
         of1++
      else {
         if (tbl_txt[of1]!="")
            tbl_txt[of1]=tbl_txt[of1]" "
         tbl_txt[of1]=tbl_txt[of1]$of
      }
   txt=tbl_indent tbl_lim[0]
   for (of=0;of<tbl_size;of++) {
      tbl_txt[of]=tbl_txt[of] long_line
      txt=txt" "substr(tbl_txt[of],1,tbl_len[of])" "tbl_lim[of+1]
      tbl_txt[of]=""
   }
#   }}}
#   {{{  print info-tree
   printf(start_ref_class,class_id[level],class_id[level])
   print(txt)
   print(end_ref_class)
#   }}}
   next
}
#}}}
#}}}
#{{{  @ref-doc-only
/^@ref-doc-only/ { next }
#}}}
#{{{  @ref-lib
/^@ref-lib/ { next }
#}}}
#{{{  @ref-menu
/^@ref-menu [0123456789]+( +((quit)|(ret)|(next)|(prev)|(kill)|([^ ()@]+)) +([^ ]+))+ +([^ ]*)$/ {
   if (level!=0)
      ref_error="@ref-menu only allowed on toplevel"
   else {
      id=substr($0,11)
      if (VIEWER_ID[id]=="") {
         MENU_DEF[known_menu]=$2
         MENU_OPS[known_menu]=0
         MENU[known_menu]=""
         for (i=3;i<NF;i+=2) {
            MENU_OP[known_menu"#"(MENU_OPS[known_menu]++)]=$i
            MENU[known_menu]=MENU[known_menu]" "$(i+1)
         }
         ARGS[known_menu]=$NF
         VIEWER[known_menu]="ref-viewer-"known_menu
         VIEWER_ID[id]=known_menu++
      }
      if (cur_menu!=VIEWER_ID[id])
         cur_menu=VIEWER_ID[id]
   }
   next
}
#}}}
#{{{  @ref-see-also
/^@ref-see-also((%%)|(%s)|[^%])*$/ {
   next
}
#}}}
#{{{  @ref-class-id
/^@ref-class-id/ {
   if (use_id<0+$2)
      use_id=0+$2
   next
}
#}}}
#{{{  @ref-*-*-box
/^@ref-(top|sub)-(start|end)-box/ {
   box[$1]=substr($0 long_line,length($1)+2,8)
   next
}
#}}}
#{{{  @ref-start-picture
/^@ref-start-picture *$/ {
   picture=1
   next
}
#}}}
#{{{  @ref-end-picture
/^@ref-end-picture *$/ {
   picture=0
   next
}
#}}}
#{{{  @ref-start-item
/^@ref-start-item/ {
   if (picture!=0)
      ref_error="item<->picture conflict"
   else {
      item_level++
      item_txt=substr($0,17)" "
      ref_first+=ref_indent
      if (length(item_txt)<=ref_indent)
          info_indent=substr(info_indent item_txt long_line,1,ref_first-1)
      else
          info_indent=info_indent item_txt"\n"substr(long_line,1,ref_first-1)
   }
   next
}
#}}}
#{{{  @ref-end-item
/^@ref-end-item/ {
   if (item_level!=0) {
      item_level--
      ref_first-=ref_indent
      info_indent=substr(long_line,1,ref_first-1)
   } else
      ref_error="no item to leave"
   next
}
#}}}
#{{{  @ref-fun
/^@ref-fun/ {
   if (level>0) {
      if (def[level]==0) {
         ref_error="new class not allowed in reused class!"
         next
      }
      fun_header=substr($0,length($2)+11)
      if (fun_header=="")
         fun_header=$2
      if (fun_header=="") {
         ref_error="no function given"
         next
      }
#      {{{  store link print data for flush
      link_txt=info_indent"< "substr(ARGS[cur_menu],calls[level]+1,1)" > "fun_header
      link_class=class_id[level]
#      }}}
#      {{{  look for existing function
      for (i=1;i<=known_functions;i++)
         if (known_f_name[i]==$2)
            break
#      }}}
      if (i>known_functions)
         known_f_name[++known_functions]=$2
      calls[level]++
      known_class_sets[known_id[level]]=known_class_sets[known_id[level]] " set c-" calls[level] " " 0-i
   }
   next
}
#}}}
/^@[^{}@]/ {
    print($0)
    next
}
#}}}
#{{{  start toplevel definition
level==0 && /^@\{\{\{  [^ ]+/ {
   if ($3!="") {
#      {{{  error
      ref_error="toplevel definition may only use one word as label!"
      next
#      }}}
   }
   level++
#   {{{  init the level
   calls[level]=0
   call_sets=""
   def[level]=1
   class_name=$2
   class_id[level]=use_id++
   header[level]=$2
#   }}}
#   {{{  add to list of known
   known_header[$0]=known_classes
   known_prt_header[known_classes]=header[level]
   known_top_class[known_classes]=class_name
   known_class_chapter[known_classes]=""
   known_class_id[known_classes]=class_id[level]
   known_id[level]=known_classes
   known_class_call[known_classes]="set ref-call "class_id[level]
   known_class_browser[known_classes]=VIEWER[cur_menu]
   known_class_sets[known_classes]=""
   known_classes++
#   }}}
#   {{{  print tree header
   box_type=box["@ref-top-start-box"]
   box_txt=header[level]
   if (title[box_txt]!="")
      box_txt=title[box_txt]
   if (author[header[level]]!="")
      box_txt=box_txt author[header[level]] ")"
   box_head=1
   box_center=1
   box_class=class_id[level]
#   }}}
   next
}
#}}}
#{{{  end toplevel definition
level==1 && /^@\}\}\}[ ]*$/ {
   known_class_args[known_id[level]]=calls[level]
#   {{{  print tree end header
   box_type=box["@ref-top-end-box"]
   box_txt=header[level]
   box_head=0
   box_center=1
   box_class=class_id[level]
#   }}}
#   {{{  define toplevel access functions
   top_funs=top_funs"@if-using("class_name"-TREE)(deffun "class_name"(set ref-call "class_id[level]" ref-case-fun ref-abort-unload redraw-display))@fi\n"
#   }}}
   print("@use("known_class_browser[known_id[level]]"-"calls[level]"-USED)")
   level--
   next
}
#}}}
#{{{  start sub-class
/^@\{\{\{  [^ ]+/  {
#   {{{  not allowed, if not defining
   if (def[level]==0) {
       ref_error="new class not allowed in reused class!"
       next
   }
#   }}}
#   {{{  get name for this entry
   sub_header=substr($0,7)
   if (substr(sub_header,1,1)=="@")
      prt_header=substr(sub_header,length($2)+2)
   else
      prt_header=sub_header
#   }}}
   if (doc_out==0){
#      {{{  extend arguments
      while (calls[level]>=length(ARGS[cur_menu]) ) {
         for (lm=length(ARGS[cur_menu]);ADD!="*";) {
            if (lm==0) {
               break
            } else if (substr(ADD,1,1)==substr(ARGS[cur_menu],lm,1)) {
               lm=length(ARGS[cur_menu])
               ADD=substr(ADD,2)"*"
            } else
               lm--
         }
         ARGS[cur_menu]=ARGS[cur_menu]substr(ADD,1,1)
         ADD=substr(ADD,2)"*"
      }
#      }}}
#      {{{  store link in ref-tree
      link_txt=info_indent"< "substr(ARGS[cur_menu],calls[level]+1,1)" > "prt_header
      link_class=class_id[level]
#      }}}
   }
   calls[level]++
   level++
#   {{{  x=chapter id
   x="" ref_chapter[1]
   for (i=2;i<level;i++)
      x=x "." ref_chapter[i]
#   }}}
   if ((i=known_header[$0])=="") {
      i=known_classes
      def[level]=1
      class_id[level]=use_id++
      class_name_used=class_name
#      {{{  add to list of known
      known_header[$0]=known_classes
      known_prt_header[known_classes]=prt_header
      known_top_class[known_classes]=class_name
      known_class_chapter[known_classes]=x
      known_class_id[known_classes]=class_id[level]
      known_id[level]=known_classes
      known_class_call[known_classes]="set ref-call "class_id[level]
      known_class_browser[known_classes]=VIEWER[cur_menu]
      known_class_sets[known_classes]=""
      known_classes++
#      }}}
      header[level]=prt_header
#      {{{  print tree header
      box_type=box["@ref-sub-start-box"]
      box_txt=header[level]
      box_head=1
      box_center=0
      box_class=class_id[level]
#      }}}
   } else {
      def[level]=0
      class_id[level]=known_class_id[i]
      class_name_used=known_top_class[i]
   }
   calls[level]=0
   known_class_sets[known_id[level-1]]=known_class_sets[known_id[level-1]] " set c-" calls[level-1] " " class_id[level]
   ind_pop[level]=item_level
   ref_first-=item_level*ref_indent
   info_indent=substr(long_line,1,ref_first-1)
   item_level=0
   next
}
#}}}
#{{{  end sub-class
/^@\}\}\}[ ]*/  {
    if (def[level]) {
       known_class_args[known_id[level]]=calls[level]
#       {{{  print tree header
       box_type=box["@ref-sub-end-box"]
       box_txt=header[level]
       box_head=0
       box_center=0
       box_class=class_id[level]
#       }}}
       print("@use("known_class_browser[known_id[level]]"-"calls[level]"-USED)")
    }
    item_level=ind_pop[level]
    ref_first+=item_level*ref_indent
    info_indent=substr(long_line,1,ref_first-1)
    level--
    ref_chapter[level]++
    next
}
#}}}
#{{{  store simple line data
{
#   {{{  not allowed, if not defining
   if (def[level]==0) {
       if ($0!="@{{{}}}")
          ref_error="new text not allowed in reused class!"
       next
   }
#   }}}
   if (picture==0)
#    {{{  blocking, single word storing
      if (NF==0)
         info_buffer[info_buffer_use++]="\n"
      else
         for (of=1;of<=NF;of++)
            info_buffer[info_buffer_use++]=$of
#    }}}
   else
      info_buffer[info_buffer_use++]=$0
}
#}}}
END {
   if (ref_error=="") {
      if (item_level>0)
         ref_error="missing end item"
      else if (picture==1)
         ref_error="missing end picture"
      else if (tbl_size)
         ref_error="missing end tbl"
      else
#         {{{  print functions..
         if (commenting)
            ref_error="open comment"
         else if (known_classes==0)
            ref_error="no data found"
         else if (doc_out==0){
            print(start_tree)
            print("(demand-load(")
#            {{{  forward some functions
            print("(forward ref-abort-unload)(forward ref-case-fun)")
            print("(defvar(ref-class ref-call ref-n ref-call-i-next ref-call-i-quit ref-call-i-back ref-call-i-kill ))")
            undeclares="ref-case-fun ref-class ref-n"
            unload_funs = "ref-case-fun"
#            }}}
#            {{{  print toplevel access functions
            print(top_funs)
#            }}}
#            {{{  print all needed browsers
            defined_vars=0
            for (id in VIEWER_ID) {
               cur_menu=VIEWER_ID[id]
#               {{{  define missing argument variables
               if (defined_vars<length(ARGS[cur_menu])) {
                  printf("(defvar( ")
                  while(defined_vars<length(ARGS[cur_menu])) {
                     defined_vars++
                     printf("c-%d ",defined_vars)
                     undeclares=undeclares " c-" defined_vars
                  }
                  print("))")
               }
#               }}}
#               {{{  @if-using classes, needing current browser
               printf("@if-using( ")
               for (j=length(ARGS[cur_menu]);j>=0;j--)
                  printf(VIEWER[cur_menu]"-"j"-USED ")
               print(")")
#               }}}
#               {{{  get ocl-source for menu string
               menu=""
               for (i=length(MENU[cur_menu]);i>0;i--)
                  menu=" "DQ substr(MENU[cur_menu],i,1) " " menu
#               }}}
#               {{{  define and undeclare a macro, to generate menu strings
               printf("%s","(demand-load not((defmac "VIEWER[cur_menu]"("menu" next-line "COMPLAIN" next-line ")
               for (i=1;i<=5;i++) printf("%s  %s%s ",DQ,DQ,substr(ARGS[cur_menu],i,1))
               printf(" next-line ")
               for (i=6;i<(3*length(ARGS[cur_menu]))/4;i++) printf("%s  %s%s ",DQ,DQ,substr(ARGS[cur_menu],i,1))
               print("))(undeclare("VIEWER[cur_menu]"))))")
#               }}}
               print("(deffun "VIEWER[cur_menu]"(")
                print(" if not(ref-call-i-quit)(")
                print("  history-edit misc ()")
                print("   insert-ascii I_QUIT")
                print("   beginning-of-line")
                print("   set-counter ref-call-i-quit store-character")
                print("   insert-ascii I_NEXT_PAGE")
                print("   beginning-of-line")
                print("   set-counter ref-call-i-next store-character")
                print("   insert-ascii I_BACK")
                print("   forward-character")
                print("   set-counter ref-call-i-back store-character")
                print("   insert-ascii I_KILL")
                print("   forward-character")
                print("   set-counter ref-call-i-kill store-character")
                print("   newline-and-indent")
                print(" )fi")
                print(" do(")
#                 {{{  call help
                 print("  local(modify-behaviour )( set modify-behaviour ref-class help)")
#                 }}}
                 print("  if not(in-prompt)(")
#                  {{{  complain and return
                  print("   message("COMPLAIN")")
                  print("   show-cursor 15")
                  print("   set ref-call 0")
                  print("   return-from-macro")
#                  }}}
                 print("  )else(")
#                  {{{  menu loop
                  print("   do(")
#                   {{{  menu
                   print("    begin-prompt-macro")
                   print("    set ref-call "MENU_DEF[cur_menu])
                   print("    local(ref-n)(")
                    print("     case")
                    pre_add="                         "
                    for (i=0;i<=length(ARGS[cur_menu]);i++) {
                       if (i!=0) menu=menu " " DQ "  " DQ substr(ARGS[cur_menu],i,1)
                       print("      ("pre_add"=(ref-n 0)(menu-counter ref-call(" menu ")))")
                       if (i==0) pre_add="pre(set ref-n -(ref-n 1))"
                    }
                    print("     esac")
                   print("    )")
                   print("    end-prompt-macro")
#                   }}}
#                   {{{  decode command
                   pre="                               "
                   print("    case")
                    for (i=0;i<MENU_OPS[cur_menu];i++) {
                     printf("     ("pre"=(ref-call 0)(")
                     pre="pre(set ref-call -(ref-call 1))"
                     if (MENU_OP[cur_menu"#"i]=="quit")
                      print("screen-off insert-ascii ref-call-i-quit screen-on set ref-call 1 return-from-macro))")
                     else if (MENU_OP[cur_menu"#"i]=="ret")
                      print("screen-off insert-ascii ref-call-i-quit screen-on return-from-macro))")
                     else if (MENU_OP[cur_menu"#"i]=="next")
                      print(" insert-ascii ref-call-i-next ))")
                     else if (MENU_OP[cur_menu"#"i]=="prev")
                      print(" insert-ascii ref-call-i-back ))")
                     else if (MENU_OP[cur_menu"#"i]=="kill")
                      print(" insert-ascii ref-call-i-kill ))")
                     else
                      print(" insert-ascii ref-call-i-quit set ref-call eval("MENU_OP[cur_menu"#"i]")))")
                    }
                   print("    default(")
                     print("     screen-off insert-ascii ref-call-i-quit screen-on")
                     print("     case")
                     print("      (or(>(ref-call ref-n) =(ref-n 0) <=(ref-call 0))(message("DQ"invalid "DQ"  "DQ"input! )show-cursor 15 return-from-macro))")
                      for (i=1;i<=length(ARGS[cur_menu]);i++) {
                         printf("      (pre(set ref-call -(ref-call 1))=(ref-call 0)")
                         printf("(")
                         printf("@if-using( ")
                         for (u=i;u<=length(ARGS[cur_menu]);u++)
                            printf(VIEWER[cur_menu]"-"u"-USED ")
                         printf(")set ref-call c-" i" @fi)")
                         print(")")
                      }
                     print("     default")
                      print("      (message("DQ"invalid "DQ"  "DQ"input! )show-cursor 15 return-from-macro)")
                     print("     esac")
                     print("     ref-case-fun)")
                    print("    esac")
#                   }}}
                  print("   )while in-prompt")
#                  }}}
                 print("  )fi")
                print(" )while =(ref-call 0)")
               print("))")
               print("@fi")
            }
#            }}}
#            {{{  print case function
#            {{{  init loop
            part=0
            added=0
            end_string=""
            case_no=0
            handled=0
#            }}}
#            {{{  forward complain/extension fun
            print("(forward ref-case-fun-"part")")
            undeclares=undeclares" ref-case-fun-"part
            unload_funs=unload_funs" ref-case-fun-"part
#            }}}
            print("(deffun ref-case-fun(")
            print(" local(ref-class ref-n)(")
            end_string=")))"
#            {{{  print used functions
            if (known_functions>0) {
               print("  case")
               for (i=1;i<=known_functions;i++) {
                  print("   (pre(set ref-call -(ref-call "0-i-added"))=(ref-call 0)(set ref-call eval ("known_f_name[i]")))")
                  added=0-i
                  case_no++
               }
               print("  esac")
            }
#            }}}
            a=0
            handled=0
            i=0
            ifs=" "
            for (x=0;x<known_menu;x++)
               ifs=ifs VIEWER[x]"-"0"-USED "
            print("  @if-using("ifs")set ref-n 0 @fi")
            print("  case")
            end_string="esac "end_string
            while (handled<known_classes) {
               if (i==known_classes) {
#                  {{{  start next loop for next number of sub-trees
                  i=0
                  a++
                  print("  default(local(c-"a")(")
                  for (x=0;x<known_menu;x++)
                     ifs=ifs VIEWER[x]"-"a"-USED "
                  print("   @if-using("ifs")set ref-n "a" @fi")
                  print("  case")
                  end_string="esac))"end_string
#                  }}}
               } else {
                  if (known_class_args[i]==a) {
#                     {{{  print case entry
                     print("   (pre(set ref-call -(ref-call "0+known_class_id[i]-added"))or(0 @if-using(U-C-"known_class_id[i]")=(ref-call 0)@fi)")
                     print("     (@if-using(U-C-"known_class_id[i]")"known_class_sets[i]" set ref-class "known_class_id[i]" "known_class_browser[i] " return-from-macro @use not(U-C-"known_class_id[i]")@fi))")
                     added=known_class_id[i]
                     handled++
                     case_no+=1.1+0.3*a
#                     }}}
#                     {{{  maybe gen new function, to prevent big macros
                     if (case_no>case_entry_lg) {
                        print("  default(ref-case-fun-"part")"end_string)
                        print("(forward ref-case-fun-"part+1")")
                        undeclares=undeclares" ref-case-fun-"part+1
                        unload_funs=unload_funs" ref-case-fun-"part+1
                        print("(deffun ref-case-fun-"part"(")
                        print("  case")
                        end_string="esac))"
                        part++
                        case_no=0
                     }
#                     }}}
                  }
                  i++
               }
            }
            print("  default(ref-case-fun-"part")"end_string)
            print("(deffun ref-case-fun-"part"(message ("COMPLAIN ")set ref-call 0))")
#            }}}
#            {{{  ref-abort-unload
            print("(deffun ref-abort-unload(load-function not("unload_funs)
#            {{{  all needed browsers
            for (cur_menu=0;cur_menu<known_menu;cur_menu++) {
               printf("@if-using( ")
#               {{{  @if-using classes, needing current browser
               for (j=length(ARGS[cur_menu]);j>=0;j--)
                  printf(VIEWER[cur_menu]"-"j"-USED ")
#               }}}
               print(")"VIEWER[cur_menu]" @fi")
            }
#            }}}
            print(")))")
#            }}}
#            {{{  abort-hook-add
            print("@if-using not(ABORT-HOOK-ADD)@use (ABORT-HOOK-ADD)( defmac abort-hook-add ( ) )@fi")
            print("(defmac abort-hook-add-saved(abort-hook-add))(undeclare(abort-hook-add))")
            print("(defmac abort-hook-add(set modify-behaviour 0))(undeclare(abort-hook-add-saved))")
#            }}}
#            {{{  undeclares
            print("(undeclare("undeclares" ref-abort-unload")
#            {{{  all needed browsers
            for (cur_menu=0;cur_menu<known_menu;cur_menu++) {
               printf("@if-using( ")
#               {{{  @if-using classes, needing current browser
               for (j=length(ARGS[cur_menu]);j>=0;j--)
                  printf(VIEWER[cur_menu]"-"j"-USED ")
#               }}}
               print(")"VIEWER[cur_menu]" @fi")
            }
#            }}}
            print("))")
#            }}}
            print("))")
            print(end_tree)
#            {{{  use not all viewer uses
            print("@use not( ")
            for (x=0;x<known_menu;x++) {
               for (i=length(ARGS[x]);i>=0;i--)
                  printf(" "VIEWER[x]"-"i"-USED")
               print("")
            }
            print(")")
#            }}}
         }
#         }}}
   }
   if (ref_error!="" && ref_error!="-") {
      print("@error EOF:" ref_error)
   }
}
HERE
#}}}
#{{{  nroff stuff
cat >>$TMP_DIR/ref.tmp.r.awk <<\HERE
#{{{  copy $i to fi[i] and quote roff critical chars
{ for (i=0;i<=NF;i++) {
      field[i]=""
      for (l=1;l<=length($i);l++) {
         c=substr($i,l,1)
         if (c==".")
            field[i]=field[i]"\\&"c
         else if (c=="\\")
            field[i]=field[i]"\\e"
         else
            field[i]=field[i]c
      }
   }
   if (substr(field[0],1,1)=="'")
      field[0]="\&"field[0]
}
#}}}
#{{{  header
/^@\{\{\{  @ref-header +[^ ]* *$/ {
   header_name=$3
   next
}
header_name!="" {
   if ($1=="@ref-title")
      title[header_name]=substr(field[0],length($1)+2)
   else if ($1=="@ref-author")
      author[header_name]=author[header_name]".AU\n"substr(field[0],length($1)+2)"\n"
   else if ($1=="@}}}")
      header_name=""
   else
      abstract[header_name]=abstract[header_name] field[0] "\n"
   next
}
#}}}
#{{{  flushing text to out
#{{{  start-reference-chapter
ref_chapt_start!="" {
   txt=ref_chapt_start
   txt=".sp\n" new_para "\n" bold ref_chapt_start norm
   if (doc_out==0)
      printf(start_ref,class_name)
   print(txt)
   if (doc_out==0)
      print(end_ref)
   ref_chapt_start=""
}
#}}}
#{{{  end-reference-chapter
ref_chapt_end==1 {
   if (doc_out==0)
      printf(start_ref,class_name)
   print(".br")
   if (doc_out==0)
      print(end_ref)
   ref_chapt_end=0
}
#}}}
#{{{  special line and buffer used -> flush it
/^(@|$)/ && (ref_buffer!="" || (ritem_txt!="\n" && level>0)) {
   if (doc_out==0)
      printf(start_ref,class_name)
   if (picture!=1) {
      print(new_para)
      if (item_level>0)
         new_para=".IP "DQ DQ
      else
         new_para=".LP"
      ritem_txt="\n"
   }
   print(ref_buffer)
   if (doc_out==0)
      print(end_ref)
   ref_buffer=""
}
#}}}
#}}}
#{{{  ref/opp statements
#{{{  tbl-handling
#{{{  start-tbl
/^@ref-start-tbl/ {
   if (tbl_size || picture)
      ref_error="tbl not allowed here"
   else {
#      {{{  get head/tail string for info
      rtbl_head=""
      rtbl_form=""
      x=""
      y=""
      for (of=2;of<NF;)
         if ($of=="@@")
            if (of>2 && of<NF) {
               x=" | l | "
               y=tbl_limiter" "
               of++
            } else {
               ref_error="invalid limiter place"
               next
            }
        else {
           rtbl_lim[tbl_size]=y tbl_limiter
           if (tbl_size>0) {
              rtbl_form=rtbl_form x
              rtbl_head=rtbl_head y tbl_limiter
           }
           rtbl_head=rtbl_head field[of]
           rtbl_form=rtbl_form"l"
           tbl_size++
           x=" | "
           y=""
           of+=2
        }
#      }}}
      if (tbl_size==0)
         ref_error="no tbl parameter given"
      else {
#         {{{  print reference
         if (doc_out==0)
            printf(start_ref,class_name)
         print(".TS")
         print("center box tab("tbl_limiter");")
         print(rtbl_form".")
         print(rtbl_head)
         print("_")
         if (doc_out==0)
            print(end_ref)
#         }}}
      }
   }
   next
}
#}}}
#{{{  end-tbl
/^@ref-end-tbl/ {
   if (tbl_size==0)
      ref_error="no tbl active"
   else {
      tbl_size=0
#      {{{  print reference
      if (doc_out==0)
         printf(start_ref,class_name)
      print(".TE")
      if (doc_out==0)
         print(end_ref)
#      }}}
   }
   next
}
#}}}
#{{{  inside tbl, no commands, other the @use,@if-using,@fi are allowed
/^@[^@ ]/ && tbl_size>0 {
   if ((substr(field[0],1,9)!="@if-using")&&(substr(field[0],1,3)!="@fi")&&(substr(field[0],1,4)!="@use")) {
      ref_error="tbl crashed with "field[0]
      next
   }
}
#}}}
#{{{  text -> format it
/^([^@]|@@|$)/ && tbl_size>0 {
#   {{{  decode and format table data
   rtxt=""
   x=0
   y=""
   for (of=1;of<=NF;of++)
      if (field[of]=="@@") {
         x++
         y=""
         rtxt=rtxt rtbl_lim[x]
      } else {
         rtxt=rtxt y field[of]
         y=" "
      }
#   }}}
#   {{{  print reference
   if (doc_out==0)
      printf(start_ref,class_name)
   print(rtxt)
   if (doc_out==0)
      print(end_ref)
#   }}}
   next
}
#}}}
#}}}
#{{{  @ref-doc-only
/^@ref-doc-only/ {
   doc_out=1
   next
}
#}}}
#{{{  @ref-lib
/^@ref-lib/ { next }
#}}}
#{{{  @ref-menu
/^@ref-menu [0123456789]+( +((quit)|(ret)|(next)|(prev)|(kill)|([^ ()@]+)) +([^ ]+))+ +([^ ]*)$/ {
   next
}
#}}}
#{{{  @ref-see-also
/^@ref-see-also((%%)|(%s)|[^%])*$/ {
   SEE_ALSO=substr(field[0],length("@ref-see-also")+2)
   next
}
#}}}
#{{{  @ref-class-id
/^@ref-class-id/ {
   next
}
#}}}
#{{{  @ref-*-*-box
/^@ref-(top|sub)-(start|end)-box/ {
   next
}
#}}}
#{{{  @ref-start-picture
/^@ref-start-picture *$/ {
   picture=1
   if (doc_out==0)
      printf(start_ref,class_name)
   print(new_para"\n.DS")
   if (doc_out==0)
      print(end_ref)
   new_para=""
   next
}
#}}}
#{{{  @ref-end-picture
/^@ref-end-picture *$/ {
   picture=0
   if (doc_out==0)
      printf(start_ref,class_name)
   print(".DE")
   if (doc_out==0)
      print(end_ref)
   next
}
#}}}
#{{{  @ref-start-item
/^@ref-start-item/ {
   if (picture!=0)
      ref_error="item<->picture conflict"
   else {
      item_level++
      ritem_txt=substr(field[0],17)" "
      for (of=length(ritem_txt);of>0;of--)
         if (substr(ritem_txt,of,1)==DQ)
            ritem_txt=substr(ritem_txt,1,of-1)DQ substr(ritem_txt,of)
      new_para=".IP "DQ ritem_txt DQ " "
      if (item_level>1)
         new_para=".RS\n"new_para
   }
   next
}
#}}}
#{{{  @ref-end-item
/^@ref-end-item/ {
   if (item_level!=0) {
      if (doc_out==0)
         printf(start_ref,class_name)
      if (ritem_txt!="\n")
         print(new_para)
      if (item_level>1)
         print(".RE")
      if (doc_out==0)
         print(end_ref)
      item_level--
      if (item_level>0)
         new_para=".IP "DQ DQ " "
      else
         new_para=".LP"
   } else
      ref_error="no item to leave"
   next
}
#}}}
#{{{  @ref-fun
/^@ref-fun/ {
   next
}
#}}}
/^@[^{}@]/ {
    if (doc_out==0) print(field[0])
    next
}
#}}}
#{{{  start toplevel definition
level==0 && /^@\{\{\{  [^ ]+/ {
   if (NF>=3) {
#      {{{  error
      ref_error="toplevel definition may only use one word as label!"
      next
#      }}}
   }
   level++
#   {{{  init the level
   def[level]=1
   class_name=field[2]
   ref_chapter[1]="1"
   header[level]=substr(field[0],7)
   if (title[$2]=="")
      title[$2]=field[2]
#   }}}
#   {{{  add to list of known
   known_header[field[0]]=known_classes
   known_prt_header[known_classes]=header[level]
   known_top_class[known_classes]=class_name
   known_class_chapter[known_classes]=""
   known_id[level]=known_classes
   known_classes++
#   }}}
#   {{{  print ref header
   if (doc_out==0)
      printf(start_ref,class_name)
   if (ref_spaces>0)
      print(".ad b")
   else
      print(".ad l")
   print(".TL")
   print(title[$2])
   printf("%s",author[$2])
   if (abstract[$2]!="")
      printf(".AB no\n%s.AE\n",abstract[$2])
   if (doc_out==0)
      print(end_ref)
#   }}}
   next
}
#}}}
#{{{  end toplevel definition
level==1 && /^@\}\}\}[ ]*$/ {
   ref_chapt_end=1
   level--
   next
}
#}}}
#{{{  start sub-class
/^@\{\{\{  [^ ]+/  {
#   {{{  not allowed, if not defining
   if (def[level]==0) {
       ref_error="new class not allowed in reused class!"
       next
   }
#   }}}
#   {{{  get name for this entry
   sub_header=substr(field[0],7)
   if (substr(sub_header,1,1)=="@")
      prt_header=substr(sub_header,length(field[2])+2)
   else
      prt_header=sub_header
#   }}}
   level++
#   {{{  x=chapter id
   x="" ref_chapter[1]
   for (i=2;i<level;i++)
      x=x "." ref_chapter[i]
#   }}}
   if ((i=known_header[field[0]])=="") {
      i=known_classes
      def[level]=1
      class_name_used=class_name
#      {{{  add to list of known
      known_header[field[0]]=known_classes
      known_prt_header[known_classes]=prt_header
      known_top_class[known_classes]=class_name
      known_class_chapter[known_classes]=x
      known_id[level]=known_classes
      known_classes++
#      }}}
      header[level]=prt_header
#      {{{  print ref header
      ref_chapter[level]=1
      ref_chapt_start=x " " prt_header
#      }}}
   } else {
      def[level]=0
      class_name_used=known_top_class[i]
#      {{{  print ref header
#      {{{  get text
      if (SEE_ALSO=="")
         y=""
      else {
        if (class_name==class_name_used)
           yy=known_class_chapter[i] " " known_prt_header[i]
         else if (known_class_chapter[i]!="")
           yy=known_top_class[i] " - " known_class_chapter[i] " " known_prt_header[i]
         else
            yy=known_top_class[i]
         y=sprintf(SEE_ALSO,yy)
      }
#      }}}
#      {{{  get see-also string
      if (substr(y,1,1)=="C")
         ref_chapt_start=x " " substr(y,2)
      else {
         if (doc_out==0)
            printf(start_ref,class_name)
         print(new_para"\n"y)
         if (doc_out==0)
            print(end_ref)
      }
#      }}}
#      }}}
   }
   next
}
#}}}
#{{{  end sub-class
/^@\}\}\}[ ]*/  {
    if (def[level])
       ref_chapt_end=1
    level--
    ref_chapter[level]++
    next
}
#}}}
#{{{  store simple line data
{
#   {{{  not allowed, if not defining
   if (def[level]==0) {
       if (field[0]!="@{{{}}}")
          ref_error="new text not allowed in reused class!"
       next
   }
#   }}}
#   {{{  reference data as text
   if (ref_buffer!="") ref_buffer = ref_buffer "\n"
   ref_buffer=ref_buffer field[0]
#   }}}
}
#}}}
END {
   if (ref_error!="" && ref_error!="-")
      print("@error EOF:" ref_error)
}
HERE
#}}}
#{{{  shrink stuff
cat >>$TMP_DIR/ref.tmp.s.awk <<\HERE
BEGIN {
   iflevel=0
   ficount=0
   uses="";useid=1
   refclass="";refend=0
}
#{{{  store @use's
/^@use *(not *)?\([^)]+\) *$/ {
   if (useused[$0]!=useid) {
      uses=uses $0 "\n"
      useused[$0]=useid
   }

  next
}
#}}}
#{{{  start reference text
/^@reference-begin(-class +[^ ]+)? *$/ {
   if (refend==1 && refclass==$0)
      refend=0
   else {
      if (refend==1) {
         print("@reference-end")
         refend=0
      }
      print($0)
      refclass=$0
   }
   next
}
#}}}
#{{{  count reference-end
/^@reference-end *$/ {
   refend=1
   next
}
#}}}
#{{{  switch to other @if
/^@if-using *(not *)?\([^)]+\) *(;.*)?$/ {
   if (ficount>0) {
      if (ifuse[iflevel-ficount]!=$0) {
         if (refend==1) {
            print("@reference-end")
            refclass=""
            refend=0
         }
         if (uses!="") {
            printf("%s",uses)
            uses=""
            useid++
         }
#         awk cannot handle do-while loops in general
         if (ficount>0)
            while (ficount>0) {
               print("@fi")
               iflevel--
               ficount--
            }
         print($0)
         ifuse[iflevel++]=$0
      } else
         ficount--
   } else {
      if (refend==1) {
         print("@reference-end")
         refclass=""
         refend=0
      }
      if (uses!="") {
         printf("%s",uses)
         uses=""
         useid++
      }
      print($0)
      ifuse[iflevel++]=$0
   }
   next
}
#}}}
#{{{  @fi count
/^@fi *$/ {
   ficount++
   next
}
#}}}
#{{{  flush reference-end
refend!=0 {
   print("@reference-end")
   refclass=""
   refend=0
}
#}}}
#{{{  flush fi
ficount>0 {
   if (refend==1) {
      print("@reference-end")
      refend=0
   }
   if (ficount>0)
      while (ficount>0) {
         if (uses!="") {
            printf("%s",uses)
            uses=""
            useid++
         }
         print("@fi")
         iflevel--
         ficount--
      }
}
#}}}
#{{{  print text
{ print }
#}}}
END {
   if (refend==1) {
      print("@reference-end")
      refend=0
   }
   while (ficount-->0)
      print("@fi")
}
HERE
#}}}
#}}}

if test $3x = roffx
then
#   {{{  do roff output
   echo "@ref-doc-only" >$TMP_DIR/ref.tmp.0
   $1 -f $TMP_DIR/ref.tmp.r.awk $TMP_DIR/ref.tmp.0 $2
#   }}}
else
#   {{{  generate ocl-source for reference-file/reference-browser
   if test $3x != x
   then
      settings="$2$3"
   else
      settings="/dev/null"
   fi

   using=`$1 '/^@ref-lib/{printf(" "substr($0,11+length($2)))}' $settings $2`
   files=`$1 'BEGIN{lib[1]=1}/^@ref-lib/{lib[$2]=1}END{for(a in lib)if(a!=1)print(a)}' $settings $2`

   echo "@use($using)" >$TMP_DIR/ref.tmp.0
   echo "@use not($using)" >$TMP_DIR/ref.tmp.1

   ( $1 -f $TMP_DIR/ref.tmp.o.awk $settings $TMP_DIR/ref.tmp.0 $files $settings $2 $TMP_DIR/ref.tmp.1;
     $1 -f $TMP_DIR/ref.tmp.r.awk $settings $TMP_DIR/ref.tmp.0 $files $settings $2 $TMP_DIR/ref.tmp.1
   ) | $1 -f $TMP_DIR/ref.tmp.s.awk
#   }}}
fi
