/* Convert all autodoc files to hypertext files */

#include "global.h"
#include "misc.h"
#include "readdir.h"
#include "incfile.h"
#include "adfile.h"
#include "shortad.h"
#include "convertad.h"

/***********************************************/

static BOOL ConvertContents(void)

{
   BOOL FirstLine;
   struct AutodocNode *AutodocNode;
   char *Temp;

   do
      {
         if (!ReadLine(FALSE,FALSE)) return(FALSE);
      }
   while (Stricmp(Buffer,"TABLE OF CONTENTS"));
   FirstLine=TRUE;
   do
      {
         if (!ReadLine(FALSE,FALSE)) return(FALSE);
         if (Buffer[0]!='\x0c' && Buffer[0])
            {
               if (FirstLine && !WriteSomething("@NODE Main \x22")) return(FALSE);
               for (Temp=Buffer; *Temp && *Temp!='/'; Temp++)
                  {
                     if (FirstLine && !WriteSomething("%lc",*Temp)) return(FALSE);
                  }
               if (FirstLine && !WriteSomething("\x22\n")) return(FALSE);
               if (!*Temp)
                  {
                     WriteError("Error: Missing '/' in file %s, line %ld\n"
                                "       Operation aborted.\n",CurrentSource,CurrentLine);
                     return(FALSE);
                  }
               FirstLine=FALSE;
               if (!(AutodocNode=(struct AutodocNode *)SearchNameCase(AutodocArray,Buffer)))
                  {
                     WriteError("Error: File %s changed.\n"
                                "       Operation aborted.\n",CurrentSource);
                     return(FALSE);
                  }
               if (AutodocNode->Type==1)
                  {
                     if (!WriteSomething("    @{\x22 %s() \x22 LINK \x22%s\x22}\n",AutodocNode->Node.Name,FindSlash(AutodocNode->Node.Name)+1)) return(FALSE);
                  }
               else
                  {
                     if (!WriteSomething("    @{\x22 %s \x22 LINK \x22%s\x22}\n",AutodocNode->Node.Name,FindSlash(AutodocNode->Node.Name)+1)) return(FALSE);
                  }
            }
      }
   while (Buffer[0]!='\x0c');
   if (!WriteSomething("@ENDNODE\n\n")) return(FALSE);
   return(TRUE);
}

/***********************************************/

static BOOL ConvertNode(void)

{
   int Index;
   int OldBufferIndex;
   struct AnyNode *AnyNode;
   char *Temp;
   int Periods;
   int Slashes;
   long Character;
   int UppercaseLetters;
   int Underscores;
   BOOL StructMode;
   int SeeAlsoMode;

   StructMode=FALSE;
   SeeAlsoMode=0;
   Temp=FindSlash(Buffer);
   if (!*Temp)
      {
         WriteError("Error: Missing '/' in file %s, line $ld\n"
                    "       Operation aborted.",CurrentSource,CurrentLine);
         return(FALSE);
      }
   *Temp='\0';
   stpcpy(CurrentUnit,Buffer);
   *Temp='/';
   do
      {
         Temp++;
      }
   while (*Temp && *Temp!=' ' && *Temp!='\t' && *Temp!='/');
   if (*Temp=='/')
      {
         WriteError("Error: Missing space or tab in file %s, line %ld\n"
                    "       Operation aborted.\n",CurrentSource,CurrentLine);
         return(FALSE);
      }
   *Temp='\0';
   if (!(AnyNode=SearchNameCase(AutodocArray,Buffer)))
      {
         WriteError("Error: Node %s not present in table of contents.\n"
                    "       File: %s\n"
                    "       Operation aborted.\n",Buffer,CurrentSource);
         return(FALSE);
      }
   CurrentAutodocNode=(struct AutodocNode *)AnyNode;
   if (CurrentAutodocNode->Type==1)
      {
         if (!WriteSomething("@NODE \x22%s\x22 \x22%s()\x22\n",FindSlash(CurrentAutodocNode->Node.Name)+1,CurrentAutodocNode->Node.Name)) return(FALSE);
      }
   else
      {
         if (!WriteSomething("@NODE \x22%s\x22 \x22%s\x22\n",FindSlash(CurrentAutodocNode->Node.Name)+1,CurrentAutodocNode->Node.Name)) return(FALSE);
      }
   BufferIndex=0;
   Buffer[0]='\0';
   while (TRUE)
      {
         if (Break()) return(FALSE);
         OldBufferIndex=BufferIndex;
         Character=fgetc();
         WordBuffer[0]='\0';
         if ((Character>='a' && Character<='z') || (Character>='A' && Character<='Z'))
            {
               Underscores=0;
               UppercaseLetters=0;
               Index=0;
               Periods=0;
               Slashes=0;
               while ((Character>='a' && Character<='z') ||
                      (Character>='A' && Character<='Z') ||
                      (Character>='0' && Character<='9') ||
                      (Character=='_') || 
                      (Character=='/') ||
                      (Character=='.'))
                  {
                     WordBuffer[Index++]=Character;
                     if (Index==MAX_LEN)
                        {
                           WriteError("Error, line %ld: line is too long.\n"
                                      "       Operation aborted.\n",CurrentLine);
                           return(FALSE);
                        }
                     if (Character=='.')
                        {
                           Periods++;
                        }
                     else if (Character=='/')
                        {
                           Slashes++;
                        }
                     else if (Character=='_')
                        {
                           Underscores++;
                        }
                     else if ((Character>='A' && Character<='Z') || (Character>='0' && Character<='9'))
                        {
                           UppercaseLetters++;
                        }
                     Character=fgetc();
                  }
               if (WordBuffer[Index-1]=='.')
                  {
                     Index--;
                     BufferIndex--;
                     Character='.';
                  }
               if (Character=='(')
                  {
                     StructMode=FALSE;
                  }
               WordBuffer[Index]='\0';
               if (StructMode)
                  {
                     if (AnyNode=(struct AnyNode *)SearchNameCase(StructArray,WordBuffer))
LinkStructure:          {
                           if (!WriteSomething("@{\x22%s\x22 LINK \x22%s/MAIN\x22 %ld}",WordBuffer,((struct StructNode *)AnyNode)->File,((struct StructNode *)AnyNode)->Line)) return(FALSE);
                           IncludeLinks++;
                           WordBuffer[0]='\0';
                           Index=0;
                        }
                     StructMode=FALSE;
                  }
               if (Index>=2)
                  {
                     if (!strcmp(WordBuffer,"struct"))
                        {
                           StructMode=TRUE;
                           if (SeeAlsoMode==1) SeeAlsoMode=0;
                        }
                     else if (!Stricmp(WordBuffer+Index-2,".h"))
                        {
                           if (SeeAlsoMode==1) SeeAlsoMode=0;
                           if (AnyNode=(struct AnyNode *)SearchNameNoCase(IncludeFileArray,WordBuffer))
                              {
                                 if (!WriteSomething("@{\x22%s\x22 LINK \x22%s/MAIN\x22 0}",WordBuffer,((struct FileNode *)AnyNode)->Node.Name)) return(FALSE);
                                 IncludeLinks++;
                                 WordBuffer[0]='\0';
                              }
                        }
                     else if (Periods==1 && Slashes==1)
                        {
                           if (SeeAlsoMode==1) SeeAlsoMode=0;
                           if (AnyNode=SearchNameCase(AutodocArray,WordBuffer))
LinkAutodoc:                  {
                                 if (CurrentAutodocNode!=(struct AutodocNode *)AnyNode)
                                    {
                                       if (!(Temp=FindSlash(((struct AutodocNode *)AnyNode)->Node.Name)))
                                          {
                                             WriteError("INTERNAL ERROR #1\n");
                                             return(FALSE);
                                          }
                                       if (Character=='(')
                                          {
                                             if (fgetc()==')')
                                                {
                                                   WordBuffer[Index++]='(';
                                                   WordBuffer[Index++]=')';
                                                   WordBuffer[Index]='\0';
                                                   Character=-2;
                                                }
                                             else
                                                {
                                                   BufferIndex--;
                                                }
                                          }
                                       if (!strcmp(HypertextFilename,((struct AutodocNode *)AnyNode)->File))
                                          {
                                             if (!WriteSomething("@{\x22%s\x22 LINK \x22%s\x22 0}",WordBuffer,Temp+1)) return(FALSE);
                                             InternalLinks++;
                                             WordBuffer[0]='\0';
                                          }
                                       else
                                          {
                                             if (!WriteSomething("@{\x22%s\x22 LINK \x22%s%s\x22 0}",WordBuffer,((struct AutodocNode *)AnyNode)->File,Temp)) return(FALSE);
                                             ExternalLinks++;
                                             WordBuffer[0]='\0';
                                          }
                                    }
                              }
                        }
                     else if (!strcmp(WordBuffer,"SEE") && !SeeAlsoMode)
                        {
                           SeeAlsoMode=1;
                        }
                     else if (SeeAlsoMode==1)
                        {
                           if (!strcmp(WordBuffer,"ALSO"))
                              {
                                 SeeAlsoMode=2;
                              }
                           else
                              {
                                 SeeAlsoMode=0;
                              }
                        }
                     else if (Character=='(' || UppercaseLetters+Underscores>1)
                        {
                           if (AnyNode=(struct AnyNode *)SearchShortAutodoc(WordBuffer))
                              {
                                 goto LinkAutodoc;
                              }
                           if (AnyNode=(struct AnyNode *)SearchNameCase(StructArray,WordBuffer))
                              {
                                 goto LinkStructure;
                              }
                           if (AnyNode=(struct AnyNode *)SearchNameCase(TypedefArray,WordBuffer))
                              {
                                 goto LinkStructure;
                              }
                        }
                     else if (SeeAlsoMode==2)
                        {
                           if ((AnyNode=(struct AnyNode *)SearchShortAutodoc(WordBuffer)) && AnyNode!=(struct AnyNode *)CurrentAutodocNode)
                              {
                                 goto LinkAutodoc;
                              }
                        }
                  }
            }
         if (WordBuffer[0] && !WriteSomething("%s",WordBuffer)) return(FALSE);
         switch(Character)
            {
               case -1:     return(FALSE);

               case '\x0c': return(WriteSomething("@ENDNODE\n\n"));

               case '\n':   for (Index=0; Index<BufferIndex-1; Index++)
                               {
                                  if (Buffer[Index]!=' ' && Buffer[Index]!='\t')
                                     {
                                        goto HandleSpace;
                                     }
                               }
                            SeeAlsoMode=0;
                            goto HandleSpace;

               default:     StructMode=FALSE;
                            if (SeeAlsoMode==1) SeeAlsoMode=0;
HandleSpace:   case ' ':
               case '\t':   if (Character!=-2 && !WriteSomething("%lc",Character)) return(FALSE);
                            break;
            }
      }
}

/***********************************************/

static BOOL ConvertAutodoc(void)

{
   char *AutodocName;
   long AutodocNameLen;

   CurrentLine=0;
   AutodocNameLen=500;
   while (TRUE)
      {
         if (AutodocName=AllocVec(AutodocNameLen,0))
            {
               if (NameFromFH(CurrentFile,AutodocName,AutodocNameLen))
                  {
                     break;
                  }
               FreeVec(AutodocName);
               if (IoErr()==ERROR_LINE_TOO_LONG)
                  {
                     AutodocNameLen<<=1;
                  }
               else
                  {
                     PrintFault(IoErr(),CurrentSource);
                     return(FALSE);
                  }
            }
         else
            {
               PrintFault(ERROR_NO_FREE_STORE,NULL);
               return(FALSE);
            }
      }
   AutodocNameLen=WriteSomething("@DATABASE \x22%s\x22\n"
                                 "@MASTER \x22%s\x22\n"
                                 "@REMARK created by ADtoHT © 1993 Christian Stieber\n\n",HypertextFilename,AutodocName);
   FreeVec(AutodocName);
   if (AutodocNameLen)
      {
         if (!ConvertContents())
            {
               return(FALSE);
            }
         ExternalLinks=0;
         IncludeLinks=0;
         InternalLinks=0;
         while (TRUE)
            {
               do
                  {
                     if (!ReadLine(TRUE,FALSE))
                        {
                           if (IoErr())
                              {
                                 return(FALSE);
                              }
                           else
                              {
                                 printf("         %ld links were created.\n"
                                        "            %ld links within the database\n"
                                        "            %ld links to other databases\n"
                                        "            %ld links to include files\n",InternalLinks+ExternalLinks+IncludeLinks,InternalLinks,ExternalLinks,IncludeLinks);
                                 return(TRUE);
                              }
                        }
                     if (Buffer[0]=='\x0c')
                        {
                           WriteError("Error: Unexpected FormFeed in file %s\n"
                                      "       Operation aborted.\n",CurrentSource);
                           return(FALSE);
                        }
                  }
               while (!Buffer[0]);
               if (!ConvertNode()) return(FALSE);
            }
      }
   else
      {
         return(FALSE);
      }
}

/***********************************************/

BOOL ConvertAutodocs(void)

{
   BPTR OldCurrentDir;
   struct FileNode *NextNode;
   int Length;
   BOOL Success;

   Success=TRUE;
   while (AutodocFileList && Success)
      {
         CurrentSource=AutodocFileList->Node.Name;
         Length=strlen(CurrentSource)-4;
         if (HypertextFilename=AllocVec(Length+strlen(Arguments.Extension)+1,0))
            {
               __builtin_memcpy(HypertextFilename,CurrentSource,Length);
               stpcpy(HypertextFilename+Length,Arguments.Extension);
               printf("      Converting %s to %s\n",CurrentSource,HypertextFilename);
               OldCurrentDir=CurrentDir(HypertextDir);
               if (HypertextFile=CreateFile(HypertextFilename))
                  {
                     CurrentDir(AutodocDir);
                     if (CurrentFile=Open(CurrentSource,MODE_OLDFILE))
                        {
                           Success=ConvertAutodoc();
                           Close(CurrentFile);
                        }
                     else
                        {
                           PrintFault(IoErr(),CurrentSource);
                           Success=FALSE;
                        }
                     Close(HypertextFile);
                  }
               else
                  {
                     PrintFault(IoErr(),HypertextFilename);
                     Success=FALSE;
                  }
               CurrentDir(OldCurrentDir);
               FreeVec(HypertextFilename);
               NextNode=(struct FileNode *)(AutodocFileList->Node.Next);
               FreeVec(AutodocFileList);
               AutodocFileList=NextNode;
            }
         else
            {
               PrintFault(ERROR_NO_FREE_STORE,NULL);
               Success=FALSE;
            }
      }
   return(Success);
}
