home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / sonstiges / tools / GuideML / GuideML.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  37.6 KB  |  1,167 lines

  1. /***************************************************************
  2. **                                                            **
  3. **      GuideML -- Converts AmigaGuide into HTML              **
  4. **                                                            **
  5. ***************************************************************/
  6. /*
  7. **  Copyright (C) 1997-98 Richard Körber  --  All Rights Reserved
  8. **    E-Mail: shred@eratosthenes.starfleet.de
  9. **    URL:    http://shredzone.home.pages.de
  10. **
  11. ***************************************************************/
  12. /*
  13. **  This program is free software; you can redistribute it and/or modify
  14. **  it under the terms of the GNU General Public License as published by
  15. **  the Free Software Foundation; either version 2 of the License, or
  16. **  any later version.
  17. **
  18. **  This program is distributed in the hope that it will be useful,
  19. **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. **  GNU General Public License for more details.
  22. **
  23. **  You should have received a copy of the GNU General Public License
  24. **  along with this program; if not, write to the Free Software
  25. **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26. **
  27. **  The author (Richard Körber) reserves the right to revoke the
  28. **  GNU General Public License whenever he feels that it is necessary,
  29. **  especially when he found out that the licence has been abused,
  30. **  ignored or violated, and without prior notice.
  31. **
  32. **  You must not use this source code to gain profit of any kind!
  33. **
  34. ***************************************************************/
  35. /*
  36. ** If you use an editor that is capable of text folding, use
  37. ** "//>" and "//<" as begin and end fold markers, respectively.
  38. */
  39.  
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <clib/alib_protos.h>
  43. #include <clib/exec_protos.h>
  44. #include <clib/dos_protos.h>
  45. #include <pragmas/exec_pragmas.h>
  46. #include <pragmas/dos_pragmas.h>
  47. #include <exec/lists.h>
  48. #include <exec/nodes.h>
  49. #include <exec/memory.h>
  50. #include <dos/dos.h>
  51. #include <libraries/dos.h>
  52.  
  53. #define VERSIONSTR "V1.6"                 /* Version Nr */
  54. #define VERSIONDATE "26.04.98"            /* Version Date */
  55. #define LINELEN (1024)                    /* Maximum length of a line */
  56.  
  57. extern struct Library *DOSBase;
  58.  
  59. char VerStr[] = "\0$VER: GuideML "VERSIONSTR" ("VERSIONDATE")";
  60.  
  61. struct Parameter                          /* Structure of Shell parameters */
  62. {
  63.   STRPTR from;
  64.   STRPTR to;
  65.   STRPTR homeurl;
  66.   STRPTR prev;
  67.   STRPTR next;
  68.   STRPTR index;
  69.   STRPTR toc;
  70.   STRPTR home;
  71.   STRPTR bar;
  72.   STRPTR bodyext;
  73.   LONG   verbatim;
  74.   LONG   images;
  75.   LONG   footer;
  76.   LONG   nolink;
  77.   LONG   noemail;
  78.   LONG   nowarn;
  79.   LONG   msdos;
  80. }param = {NULL};
  81.  
  82. struct Entry                              /* List of all nodes and links */
  83. {
  84.   struct MinNode link;
  85.   ULONG Count;
  86.   char Node[100];
  87.   char Prev[100];
  88.   char Next[100];
  89.   char TOC[100];
  90. };
  91. struct MinList entries;
  92.  
  93. struct LinkStr                            /* Link bar alternative texts */
  94. {
  95.   char Prev[100];
  96.   char Next[100];
  97.   char Index[100];
  98.   char Toc[100];
  99.   char Home[100];
  100. };
  101.  
  102. char Index[100];                          /* Index page name */
  103.  
  104. //> UBYTE Img#?[] = {...};
  105. /*
  106. **  This are the navigation bar images, in GIF format
  107. */
  108. UBYTE ImgHome[] =
  109. {
  110.   0x47,0x49,0x46,0x38,0x39,0x61,0x19,0x00,0x1B,0x00,0x82,0x00,0x00,0x9E,0x9E,0x9E,
  111.   0x00,0x00,0x00,0xF0,0xF0,0xF0,0x50,0x70,0xA0,0x90,0x90,0x90,0xB0,0xB0,0xB0,0xB0,
  112.   0xA0,0x90,0xF0,0xB0,0xA0,0x21,0xF9,0x04,0x01,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,
  113.   0x00,0x00,0x19,0x00,0x1B,0x00,0x00,0x03,0xA5,0x18,0xBA,0xDC,0xBE,0x20,0x88,0x49,
  114.   0xAB,0xBD,0x25,0x44,0x51,0xBA,0xFF,0x20,0x48,0x68,0x52,0xD8,0x8D,0x84,0x79,0x92,
  115.   0x9C,0xB7,0x8C,0x0A,0x91,0x86,0xE3,0xF6,0x05,0xC3,0x22,0xC4,0xF3,0x57,0x97,0xAE,
  116.   0x9C,0x64,0xC2,0x13,0xB1,0x6E,0x0A,0x4B,0xD1,0xF3,0x6B,0x15,0x60,0x97,0x5D,0x40,
  117.   0xC6,0x3C,0x3E,0x93,0x51,0x29,0xF5,0x6A,0xCB,0x48,0x18,0xD2,0x64,0xB1,0xE9,0xDA,
  118.   0x19,0x0C,0xDF,0xC3,0xE1,0x2B,0x4B,0x91,0x3B,0xDF,0x73,0x7A,0xBD,0xEB,0xBD,0x33,
  119.   0x66,0x74,0x98,0x5D,0xED,0xE2,0x03,0x72,0x17,0x53,0x7D,0x40,0x5E,0x0F,0x0C,0x76,
  120.   0x56,0x27,0x6D,0x8C,0x8D,0x84,0x4E,0x2A,0x91,0x3F,0x4F,0x8D,0x95,0x96,0x32,0x24,
  121.   0x87,0x9A,0x0E,0x00,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,0x1A,0x11,0x9D,0x0A,0xA6,0x9E,
  122.   0x99,0xA7,0x9F,0xA4,0x24,0xA8,0xA7,0xB0,0xA2,0x11,0x10,0xAD,0xA5,0xAE,0x10,0xA0,
  123.   0xB5,0xBA,0xA9,0xA5,0xA3,0xA8,0xB3,0xBF,0xB6,0xB8,0xB2,0xC4,0xC4,0x09,0x00,0x3B
  124. };
  125. #define LEN_IMGHOME (0xE0)
  126.  
  127. UBYTE ImgIndex[] =
  128. {
  129.   0x47,0x49,0x46,0x38,0x39,0x61,0x19,0x00,0x1B,0x00,0x82,0x00,0x00,0x9E,0x9E,0x9E,
  130.   0x00,0x00,0x00,0xF0,0xF0,0xF0,0x50,0x70,0xA0,0x90,0x90,0x90,0xB0,0xB0,0xB0,0xB0,
  131.   0xA0,0x90,0xF0,0xB0,0xA0,0x21,0xF9,0x04,0x01,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,
  132.   0x00,0x00,0x19,0x00,0x1B,0x00,0x00,0x03,0xA7,0x18,0xBA,0xDC,0xBE,0x20,0x88,0x49,
  133.   0xAB,0xBD,0x25,0x44,0x51,0xBA,0xFF,0x20,0x48,0x68,0x52,0xD8,0x05,0xE6,0x37,0x6E,
  134.   0x67,0x73,0x38,0x22,0xC9,0x65,0x03,0x31,0x04,0x47,0x1E,0xD4,0x37,0xA1,0xCA,0x27,
  135.   0x1B,0x2E,0xA7,0xAB,0x05,0x7C,0x9E,0x55,0x89,0x36,0x72,0x08,0x91,0x1D,0xE5,0xEC,
  136.   0xC8,0xB3,0x59,0x8D,0xD0,0x82,0xF4,0x54,0xE5,0x3D,0x50,0x5A,0x60,0xE6,0x6A,0x95,
  137.   0x58,0x8E,0x61,0x16,0xB3,0x2B,0x19,0x8D,0x04,0xE8,0xED,0xB8,0xFB,0x3E,0xFB,0xE4,
  138.   0x3B,0xF2,0x0D,0xEE,0xE6,0xA7,0x97,0x5F,0x66,0x15,0x71,0x62,0x5A,0x04,0x87,0x88,
  139.   0x5F,0x77,0x85,0x29,0x88,0x8E,0x8B,0x6A,0x29,0x92,0x7F,0x86,0x8F,0x96,0x97,0x4A,
  140.   0x81,0x9A,0x0C,0x00,0x9D,0x9E,0x9F,0xA0,0xA1,0xA2,0x24,0x9D,0x24,0x1A,0x11,0x10,
  141.   0xA7,0xA7,0x9E,0xA6,0x11,0xAE,0xA4,0x9F,0xB0,0xAC,0xAF,0xA4,0xA6,0xAB,0x0A,0xA1,
  142.   0xB0,0xB5,0xAE,0xB3,0xAB,0xBD,0xA5,0xA8,0xA5,0xA9,0xC0,0xA2,0xC5,0xC6,0x9E,0x09,
  143.   0x00,0x3B
  144. };
  145. #define LEN_IMGINDEX (0xE2)
  146.  
  147. UBYTE ImgNext[] =
  148. {
  149.   0x47,0x49,0x46,0x38,0x39,0x61,0x19,0x00,0x1B,0x00,0x82,0x00,0x00,0x9E,0x9E,0x9E,
  150.   0x00,0x00,0x00,0xF0,0xF0,0xF0,0x50,0x70,0xA0,0x90,0x90,0x90,0xB0,0xB0,0xB0,0xB0,
  151.   0xA0,0x90,0xF0,0xB0,0xA0,0x21,0xF9,0x04,0x01,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,
  152.   0x00,0x00,0x19,0x00,0x1B,0x00,0x00,0x03,0x94,0x18,0xBA,0xDC,0xBE,0x20,0x88,0x49,
  153.   0xAB,0xBD,0x25,0x44,0x51,0xBA,0xFF,0x20,0x48,0x68,0x52,0x68,0x9A,0xE3,0x76,0x7A,
  154.   0x01,0x81,0x92,0xDC,0x9A,0xB5,0x61,0x5A,0xCA,0x12,0xFD,0xD9,0x71,0xF7,0x04,0x07,
  155.   0x81,0xAE,0xC3,0xFB,0x48,0x2E,0x87,0xE0,0xB0,0xC8,0x12,0x24,0x9F,0x50,0xA1,0xAB,
  156.   0xC0,0xF4,0x19,0xAE,0xD8,0xEB,0xC1,0xD0,0x9A,0x56,0x67,0x8E,0x6B,0xD7,0xF3,0xA5,
  157.   0x12,0xCE,0xE7,0x00,0xF7,0xBC,0x83,0xC9,0x66,0xEC,0xB6,0x0A,0x17,0x97,0xDF,0x64,
  158.   0x53,0x91,0xFB,0x7D,0x2A,0xF3,0xC9,0x24,0x66,0x68,0x83,0x84,0x85,0x36,0x3F,0x88,
  159.   0x0E,0x00,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x1A,0x11,0x11,0x10,0x92,0x24,0x0C,0x8E,
  160.   0x0A,0x93,0x92,0x8C,0x24,0x9D,0x91,0x94,0x94,0x9C,0x9A,0x9F,0x8F,0x96,0x93,0x9F,
  161.   0x9C,0xA8,0x99,0x8B,0x97,0x9A,0xA7,0xAD,0x90,0xB2,0xB3,0x8F,0x09,0x00,0x3B
  162. };
  163. #define LEN_IMGNEXT (0xCE)
  164.  
  165. UBYTE ImgPrev[] =
  166. {
  167.   0x47,0x49,0x46,0x38,0x39,0x61,0x19,0x00,0x1B,0x00,0x82,0x00,0x00,0x9E,0x9E,0x9E,
  168.   0x00,0x00,0x00,0xF0,0xF0,0xF0,0x50,0x70,0xA0,0x90,0x90,0x90,0xB0,0xB0,0xB0,0xB0,
  169.   0xA0,0x90,0xF0,0xB0,0xA0,0x21,0xF9,0x04,0x01,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,
  170.   0x00,0x00,0x19,0x00,0x1B,0x00,0x00,0x03,0x94,0x18,0xBA,0xDC,0xBE,0x20,0x88,0x49,
  171.   0xAB,0xBD,0x25,0x44,0x51,0xBA,0xFF,0x20,0x48,0x68,0x52,0x68,0x9A,0xE3,0x86,0x06,
  172.   0xA7,0x97,0x96,0xA2,0x42,0xB4,0xC5,0xCB,0x7D,0xA3,0x10,0xCC,0xAD,0x8D,0x4B,0x87,
  173.   0x07,0xCB,0x45,0xBA,0xD5,0x80,0x87,0x8B,0x61,0x47,0x54,0x1D,0x05,0x87,0xA8,0x54,
  174.   0xBA,0xE4,0x1D,0x9D,0x47,0xC3,0xC1,0xC0,0xED,0x72,0x99,0x1D,0x1F,0xF1,0xFB,0xB0,
  175.   0x8A,0xC7,0x3B,0x82,0x7A,0x6D,0x2E,0x86,0x46,0xE0,0xD3,0xF9,0x67,0x5D,0x61,0xDF,
  176.   0xB4,0x39,0xED,0xED,0xDE,0xCB,0x49,0x35,0x6C,0x82,0x83,0x82,0x24,0x42,0x87,0x0E,
  177.   0x00,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x10,0x11,0x0A,0x8A,0x0C,0x11,0x8B,0x1A,0x8C,
  178.   0x98,0x24,0x94,0x96,0x97,0x9E,0x99,0x93,0x92,0x9A,0xA1,0x98,0x9D,0x9F,0x9C,0x96,
  179.   0xA5,0x9C,0xAA,0xA8,0xA8,0x86,0xA1,0xA6,0x8F,0xB2,0xB3,0x8B,0x09,0x00,0x3B
  180. };
  181. #define LEN_IMGPREV (0xCE)
  182.  
  183. UBYTE ImgTOC[] =
  184. {
  185.   0x47,0x49,0x46,0x38,0x39,0x61,0x19,0x00,0x1B,0x00,0x82,0x00,0x00,0x9E,0x9E,0x9E,
  186.   0x00,0x00,0x00,0xF0,0xF0,0xF0,0x50,0x70,0xA0,0x90,0x90,0x90,0xB0,0xB0,0xB0,0xB0,
  187.   0xA0,0x90,0xF0,0xB0,0xA0,0x21,0xF9,0x04,0x01,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,
  188.   0x00,0x00,0x19,0x00,0x1B,0x00,0x00,0x03,0x93,0x18,0xBA,0xDC,0xBE,0x20,0x88,0x49,
  189.   0xAB,0xBD,0x25,0x44,0x51,0xBA,0xFF,0x20,0x48,0x68,0x52,0xE8,0x11,0xE6,0x49,0x72,
  190.   0xE6,0x88,0xA6,0xE3,0xD6,0x4A,0x01,0xF1,0x8A,0x6B,0x38,0x0A,0x87,0x51,0xDF,0x2A,
  191.   0xD9,0x67,0x77,0x28,0xFA,0x6C,0x38,0x61,0x87,0x68,0x34,0x1C,0x81,0xB1,0x92,0x87,
  192.   0xC1,0xF3,0x2D,0x90,0xCB,0x5C,0x48,0xD2,0xFB,0xD9,0x6E,0x51,0x16,0x88,0x7B,0x9C,
  193.   0x29,0x3F,0xE4,0x9A,0x59,0x3A,0xAE,0xAA,0x75,0xDA,0x76,0x17,0x18,0x64,0xA3,0x19,
  194.   0xF4,0xEC,0x79,0xF8,0xCD,0x17,0xC2,0x29,0x81,0x75,0x7F,0x7D,0x85,0x86,0x85,0x24,
  195.   0x0F,0x8A,0x8A,0x00,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x11,0x1A,0x8D,0x0A,0x96,0x98,
  196.   0x0D,0x90,0x95,0x24,0x99,0x9D,0x98,0x91,0x95,0xA0,0x9D,0x97,0xA0,0x9B,0x8F,0x9C,
  197.   0x11,0xA6,0xA2,0x9B,0xA5,0xAE,0xAB,0x93,0xB1,0xB2,0x8E,0x09,0x00,0x3B
  198. };
  199. #define LEN_IMGTOC (0xCD)
  200. //<
  201.  
  202. //> STRPTR entity[96] = {...};
  203. /*
  204. ** This are the full names of all HTML entities
  205. */
  206. STRPTR entity[96] =
  207. {
  208.   "nbsp","iexcl","cent","pound","curren","yen","brvbar","sect","uml",
  209.   "copy","ordf","laquo","not","shy","reg","macr","deg","plusmn","sup2",
  210.   "sup3","acute","micro","para","middot","cedil","sup1","ordm","raquo",
  211.   "frac14","frac12","frac34","iquest","Agrave","Aacute","Acirc","Atilde",
  212.   "Auml","Aring","AElig","Ccedil","Egrave","Eacute","Ecirc","Euml","Igrave",
  213.   "Iacute","Icirc","Iuml","ETH","Ntilde","Ograve","Oacute","Ocirc","Otilde",
  214.   "Ouml","times","Oslash","Ugrave","Uacute","Ucirc","Uuml","Yacute","THORN",
  215.   "szlig","agrave","aacute","acirc","atilde","auml","aring","aelig","ccedil",
  216.   "egrave","eacute","ecirc","euml","igrave","iacute","acirc","iuml","eth",
  217.   "ntilde","ograve","oacute","ocirc","otilde","ouml","divide","oslash",
  218.   "ugrave","uacute","ucirc","uuml","yacute","thorn","yuml"
  219. };
  220. //<
  221. //> STRPTR agpens[] , htmlpens[]
  222. /*
  223. ** This are the pen names in AmigaGuide documents
  224. */
  225. STRPTR agpens[] =
  226. {
  227.   "text}","shine}","shadow}","fill}","filltext}","background}","highlight}",
  228.   NULL
  229. };
  230.  
  231. /*
  232. ** And this are the appropriate HTML colors
  233. */
  234. STRPTR htmlpens[] =
  235. {
  236.   "#000000","#ffffff","#000000","#3864a0","#000000","#949494","#ffffff"
  237. };
  238. //<
  239.  
  240. //> SaveImg()
  241. /*------------------------------------------------------------*
  242. *   SaveImg()        Saves one image                          *
  243. *     -> file File Name                                       *
  244. *     -> data Data buffer                                     *
  245. *     -> len  Length                                          *
  246. *     <-      Success                                         *
  247. */
  248. LONG SaveImg(STRPTR file, UBYTE *data, ULONG len)
  249. {
  250.   BPTR lock;
  251.  
  252.   if(lock = Lock(file,ACCESS_READ))       // Already existing?
  253.   {
  254.     UnLock(lock);
  255.     return(1);                            // then leave with success
  256.   }
  257.  
  258.   if(param.verbatim) Printf("Creating image '%s'\n",file);  // Report
  259.  
  260.   if(lock = Open(file,MODE_NEWFILE))      // Open the image file
  261.   {
  262.     if(-1 == Write(lock,data,len))        // Write the image
  263.     {
  264.       Close(lock);                        // Write failed, so
  265.       return(0);                          // return without success
  266.     }
  267.     Close(lock);                          // Write succeeded, so
  268.     return(1);                            // return with success
  269.   }
  270.   return(0);                              // No lock, no success
  271. }
  272. //<
  273. //> SaveImages()
  274. /*------------------------------------------------------------*
  275. *   SaveImages()     Saves all required images                *
  276. *     <-      Success                                         *
  277. */
  278. LONG SaveImages(void)
  279. {
  280.   for(;;)
  281.   {
  282.     if(param.homeurl)
  283.       if(!SaveImg("home.gif" ,ImgHome ,LEN_IMGHOME )) break;
  284.  
  285.     if(*Index)
  286.       if(!SaveImg("index.gif",ImgIndex,LEN_IMGINDEX)) break;
  287.  
  288.     if(!SaveImg("next.gif" ,ImgNext ,LEN_IMGNEXT )) break;
  289.     if(!SaveImg("prev.gif" ,ImgPrev ,LEN_IMGPREV )) break;
  290.     if(!SaveImg("toc.gif"  ,ImgTOC  ,LEN_IMGTOC  )) break;
  291.     return(1);
  292.   }
  293.   return(0);
  294. }
  295. //<
  296.  
  297. //> CopyLink()
  298. /*------------------------------------------------------------*
  299. *   CopyLink()       Copies a link file name into a variable  *
  300. *     -> link Link                                            *
  301. *     -> var  String-Var                                      *
  302. */
  303. void CopyLink(STRPTR link, STRPTR var)
  304. {
  305.   char ch;
  306.  
  307.   var[0] = '\0';                          // Init
  308.  
  309.   while(*link && *link==' ') link++;      // Suppress spaces
  310.   if(!*link) return;                      //   there were only spaces!
  311.  
  312.   if(*link != '\"')
  313.   {                                       // Quick Mode
  314.     while((ch = *link++)!=' ' && ch!='\n')
  315.     {
  316.       if(ch==':') ch='_';
  317.       if(ch>='A' && ch<='Z') ch+=32;
  318.       *var++ = ch;
  319.     }
  320.   }
  321.   else
  322.   {                                       // Quote Mode
  323.     link++;                               //   we had a leading quote
  324.     if(!*link) return;
  325.     while((ch = *link++)!='\"' && ch!='\n')
  326.     {
  327.       if(ch==' ' || ch==':') ch = '_';
  328.       if(ch>='A' && ch<='Z') ch+=32;
  329.       *var++ = ch;
  330.     }
  331.   }
  332.  
  333.   *var++ = '.';                           // Add html suffix
  334.   *var++ = 'h';
  335.   *var++ = 't';
  336.   *var++ = 'm';
  337.   if(!param.msdos) *var++ = 'l';
  338.   *var = '\0';
  339. }
  340. //<
  341. //> MyPutCh()
  342. /*------------------------------------------------------------*
  343. *   MyPutCh()       Writes single chars into HTML             *
  344. *     -> fh   output file handle                              *
  345. *     -> ch   Amiga char to be written                        *
  346. *     <-      -1 for failure                                  *
  347. */
  348. LONG MyPutCh(BPTR fh, unsigned char ch)
  349. {
  350.   if(ch<' ' && ch!='\n')                // Is it a control char?
  351.   {
  352.     return FPrintf(fh,"&#%03ld;",ch);   //   yes: return them as number
  353.   }
  354.   else if(ch < 128)                     // Is it an ASCII char?
  355.   {
  356.     if(ch=='\"') return FPuts(fh,""");     // Convert some exceptions
  357.     else if(ch=='&') return FPuts(fh,"&");
  358.     else if(ch=='<') return FPuts(fh,"<");
  359.     else if(ch=='>') return FPuts(fh,">");
  360.     else return FPutC(fh,ch);                   // else put char directly
  361.   }
  362.   else                                  // Chars >127 ?
  363.   {
  364.     if(ch>=160)                         // Do we have an entity name?
  365.       return FPrintf(fh,"&%s;",entity[ch-160]); // yes: use this one
  366.     else
  367.       return FPrintf(fh,"&#%03ld;",ch);         // no: use it's number
  368.   }
  369. }
  370. //<
  371. //> MyPuts()
  372. /*------------------------------------------------------------*
  373. *   MyPuts()        Writes a string into HTML                 *
  374. *     -> fh   Output file handle                              *
  375. *     -> str  String to be output                             *
  376. *     <-      -1 for failure                                  *
  377. */
  378. LONG MyPuts(BPTR fh, STRPTR str)
  379. {
  380.   unsigned char ch;
  381.  
  382.   while(ch = *str++)                        // go through the string
  383.   {
  384.     if(ch=='\"' || ch=='<' || ch=='>')      // do NOT convert them
  385.     {                                       //  since they are also used
  386.       if(-1 == FPutC(fh,ch)) return(-1);    //  in HTML tags
  387.     }
  388.     else
  389.     {
  390.       if(-1 == MyPutCh(fh,ch)) return(-1);
  391.     }
  392.   }
  393.   return(0);
  394. }
  395. //<
  396. //> ConvLine()
  397. /*------------------------------------------------------------*
  398. *   ConvLine()      Converts an AmigaGuide line               *
  399. *     -> fh   output file handle                              *
  400. *     -> buf  Source buffer                                   *
  401. *     -> linenr line number                                   *
  402. *     <-      Success                                         *
  403. */
  404. LONG ConvLine(BPTR fh, STRPTR buf, ULONG linenr)
  405. {
  406.   unsigned char ch;
  407.   char linkstr[100];
  408.   register UWORD dolink  = !param.nolink;
  409.   register UWORD doemail = !param.noemail;
  410.  
  411.   while(ch = *buf++)                      // while chars available
  412.   {
  413.     if('\\'==ch)                          //   backslash escape character?
  414.     {
  415.       switch(*buf)
  416.       {
  417.         case '\\':                        // '\\' -> '\'
  418.         case '@':                         // '\@' -> '@'
  419.           if(-1 == MyPutCh(fh,*buf)) return(0);
  420.           buf++;
  421.           break;
  422.       }
  423.       continue;
  424.     }
  425.  
  426.     if(doemail)                           // email recognition activated?
  427.     {
  428.       if(  (ch>='a' && ch<='z')           // Could this be a valid email?
  429.          ||(ch>='A' && ch<='Z')
  430.          ||(ch>='0' && ch<='9'))
  431.       {
  432.         UWORD length   = 0;   // length of the email string
  433.         UWORD atfound  = 0;   // how many '@' were found?
  434.         UWORD charcnt  = 0;   // how many characters in total?
  435.         UWORD dotfound = 0;   // how many dots?
  436.         UWORD atdot    = 0;   // how many dots after the '@'?
  437.         UWORD chardot  = 0;   // how many chars after the last dot?
  438.         STRPTR index   = --buf;
  439.         UWORD i;
  440.         unsigned char ech;
  441.  
  442.         while(ech = *index++)
  443.         {
  444.           if(   !(ech>='a' && ech<='z')   // still a valid email char?
  445.              && !(ech>='A' && ech<='Z')
  446.              && !(ech>='0' && ech<='9')
  447.              && !(ech=='@' || ech=='.' || ech=='_' || ech=='-')) break;
  448.           length++;
  449.           if(ech=='@')                    // count '@'
  450.           {
  451.             if(*index=='{')               // is it an AmigaGuide attribute?
  452.             {
  453.               length--;                   //   exclude the '@'
  454.               break;                      //   the address is finished
  455.             }
  456.             atfound++;
  457.             atdot = 0;
  458.             continue;
  459.           }
  460.           if(ech=='.')                    // count '.'
  461.           {
  462.             dotfound++;
  463.             atdot++;
  464.             chardot = 0;
  465.             continue;
  466.           }
  467.           charcnt++;                      // one more char
  468.           chardot++;
  469.         }
  470.         if(   atfound==1                  // exactly one '@'
  471.            && dotfound>0                  // at least one '.' (domain.country)
  472.            && atdot>0                     //   this dot must be after the '@'
  473.            && chardot>=2 && chardot<=3    // domain must have two or three chars
  474.            && charcnt>6)                  // and we have also some chars
  475.         {
  476.           if(-1 == FPuts(fh,"<a href=\"mailto:")) return(0);  // Generate email link
  477.           for(i=0;i<length;i++)
  478.           {
  479.             if(-1 == FPutC(fh,buf[i])) return(0);
  480.           }
  481.           if(-1 == FPuts(fh,"\">")) return(0);
  482.           for(;length;length--)
  483.           {
  484.             if(-1 == FPutC(fh,*buf++)) return(0);
  485.           }
  486.           if(-1 == FPuts(fh,"</a>")) return(0);
  487.           continue;
  488.         }
  489.         buf++;
  490.       }
  491.     }
  492.  
  493.     if(dolink)                            // internet link recognition
  494.     {
  495.       if(  (!strnicmp(buf-1,"ftp://"  ,6))    // ftp://... - Link ?
  496.          ||(!strnicmp(buf-1,"gopher:" ,7))    // gopher:... - Link ?
  497.          ||(!strnicmp(buf-1,"http://" ,7))    // http://... - Link ?
  498.          ||(!strnicmp(buf-1,"https://",8))    // https://... - Link ?
  499.          ||(!strnicmp(buf-1,"mailto:" ,7))    // mailto:... - Link ?
  500.          ||(!strnicmp(buf-1,"news:"   ,5))    // news:... - Link ?
  501.          ||(!strnicmp(buf-1,"nntp:"   ,5))    // nntp:... - Link ?
  502.          ||(!strnicmp(buf-1,"telnet:" ,7))    // telnet:... - Link ?
  503.          ||(!strnicmp(buf-1,"www."    ,4)))   // www. - Link?
  504.       {
  505.         STRPTR bufstart;
  506.  
  507.         if(-1 == FPuts(fh,"<a href=\"")) return(0);
  508.  
  509.         if(!strnicmp(buf-1,"www.",4))
  510.           if(-1 == FPuts(fh,"http://")) return(0);
  511.  
  512.         bufstart = --buf;
  513.         while(ch = *buf++)
  514.         {
  515.           if(' '==ch || '\n'==ch || ')'==ch || ('@'==ch && '{'==*buf)) break;
  516.           if(-1 == FPutC(fh,ch)) return(0);
  517.         }
  518.         if(-1 == FPuts(fh,"\">")) return(0);
  519.         for(;bufstart<buf-1;bufstart++)     // followed by a verbatim copy
  520.         {
  521.           if(-1 == FPutC(fh,*bufstart)) return(0);
  522.         }
  523.         if(-1 == FPuts(fh,"</a>")) return(0);
  524.       }
  525.     }
  526.  
  527.     if('@'==ch && '{'==*buf)              // AmigaGuide command?
  528.     {
  529.       buf++;                              // read the command?
  530.       for(;;)
  531.       {
  532.         if('\"' == *buf)                  // is it a link?
  533.         {
  534.           STRPTR link;
  535.           UWORD  linkpos=0;
  536.           BOOL   linkquot=0;
  537.  
  538.           buf++;                          // skip the quotation marks
  539.           link = buf;
  540.           while(*link && *link!='\"') link++;
  541.           if(!*link) return(0);
  542.           link++;
  543.           while(*link && (*link==' ' || *link==',' || *link=='\t')) link++;
  544.           if(!*link) return(0);
  545.           if(strnicmp(link,"link",4))
  546.           {                               // this is NO link command!
  547.             if(-1 == FPuts(fh,"<u>")) return(0);
  548.             while((ch = *buf++) != '\"')
  549.               if(-1 == MyPutCh(fh,ch)) return(0);
  550.             if(-1 == FPuts(fh,"</u>")) return(0);
  551.             buf = link;
  552.             while(*buf && *buf!=' ') buf++;
  553.             *buf++ = '\0';
  554.             if(!param.nowarn) Printf("Line %ld: WARNING: '%s' command skipped!\n",linenr,link);
  555.             while(*buf && *buf!='}') buf++;
  556.             if(*buf =='}') buf++;
  557.             break;
  558.           }
  559.           link+=4;
  560.           while(*link && *link==' ') link++;
  561.           if(!*link) return(0);
  562.           if(*link == '\"')
  563.           {
  564.             link++;
  565.             linkquot=1;
  566.           }
  567.           while(*link && *link!='}')
  568.           {
  569.             ch = *link++;
  570.             if(ch=='\"' && linkquot) break;
  571.             if(ch>='A' && ch<='Z') ch+=32;
  572.             linkstr[linkpos++] = (ch==' ' || ch==':' ? '_' : ch);
  573.           }
  574.           while(*link && *link!='}') link++;
  575.           while(linkpos>0 && linkstr[linkpos-1] == '_') linkpos--;
  576.           if(linkstr[linkpos-1] == '\"') linkpos--;
  577.           linkstr[linkpos] = '\0';
  578.           if(!*link) return(0);
  579.           link++;
  580.           if(-1 == FPuts(fh,"<a href=\"")) return(0);
  581.           if(-1 == FPuts(fh,linkstr)) return(0);
  582.           if(param.msdos)
  583.           {
  584.             if(-1 == FPuts(fh,".htm\">")) return(0);
  585.           }
  586.           else
  587.           {
  588.             if(-1 == FPuts(fh,".html\">")) return(0);
  589.           }
  590.           while((ch = *buf++) != '\"')
  591.             if(-1 == MyPutCh(fh,ch)) return(0);
  592.           if(-1 == FPuts(fh,"</a>")) return(0);
  593.           buf = link;
  594.           break;
  595.         }
  596.  
  597.         if(!strnicmp(buf,"b}",2))         // @{B}
  598.         {
  599.           if(-1 == FPuts(fh,"<b>")) return(0);
  600.           buf += 2;
  601.           break;
  602.         }
  603.         if(!strnicmp(buf,"ub}",3))        // @{UB}
  604.         {
  605.           if(-1 == FPuts(fh,"</b>")) return(0);
  606.           buf += 3;
  607.           break;
  608.         }
  609.  
  610.         if(!strnicmp(buf,"i}",2))         // @{I}
  611.         {
  612.           if(-1 == FPuts(fh,"<i>")) return(0);
  613.           buf += 2;
  614.           break;
  615.         }
  616.         if(!strnicmp(buf,"ui}",3))        // @{UI}
  617.         {
  618.           if(-1 == FPuts(fh,"</i>")) return(0);
  619.           buf += 3;
  620.           break;
  621.         }
  622.  
  623.         if(!strnicmp(buf,"u}",2))         // @{U}
  624.         {
  625.           if(-1 == FPuts(fh,"<u>")) return(0);
  626.           buf += 2;
  627.           break;
  628.         }
  629.         if(!strnicmp(buf,"uu}",3))        // @{UU}
  630.         {
  631.           if(-1 == FPuts(fh,"</u>")) return(0);
  632.           buf += 3;
  633.           break;
  634.         }
  635.  
  636.         if(!strnicmp(buf,"fg ",3))        // @{FG ...}
  637.         {
  638.           UWORD i=0;
  639.           buf += 3;
  640.  
  641.           while(*buf == ' ') buf++;
  642.  
  643.           while(agpens[i])
  644.           {
  645.             if(!strnicmp(buf,agpens[i],strlen(agpens[i])))
  646.             {
  647.               if(-1 == FPrintf(fh,"<font color=\"%s\">",htmlpens[i])) return(0);
  648.               buf += strlen(agpens[i]);
  649.               break;
  650.             }
  651.             i++;
  652.           }
  653.           if(agpens[i]) break;
  654.         }
  655.  
  656.         while(*buf && *buf!='}') buf++;   // Skip an unknown command!
  657.         buf++;
  658.         break;
  659.       }
  660.     }
  661.     else
  662.       if(-1 == MyPutCh(fh,ch)) return(0); // Error!
  663.   }
  664.   return(1);
  665. }
  666. //<
  667.  
  668. //> NavBar()
  669. /*------------------------------------------------------------*
  670. *   NavBar()        Produces the navigation bar               *
  671. *     -> tfh   output file handle                             *
  672. *     -> enode node with link data                            *
  673. *     <-      Success                                         *
  674. */
  675. LONG NavBar(BPTR tfh, struct Entry *enode)
  676. {
  677.   short before = 0;
  678.  
  679.   for(;;)
  680.   {
  681.     if(enode->Count)            // main page does not have a TOC link
  682.     {
  683.       if(param.msdos)
  684.       {
  685.         if(-1 == FPrintf(tfh,"<a href=\"%s\">",(*enode->TOC ? enode->TOC : "main.htm"))) break;
  686.       }
  687.       else
  688.       {
  689.         if(-1 == FPrintf(tfh,"<a href=\"%s\">",(*enode->TOC ? enode->TOC : "main.html"))) break;
  690.       }
  691.       if(-1 == MyPuts(tfh,param.toc)) break;
  692.       if(-1 == FPuts(tfh,"</a>")) break;
  693.       before = 1;
  694.     }
  695.  
  696.     if(*Index)
  697.     {
  698.       if(before) if(-1 == MyPuts(tfh,param.bar)) break;
  699.       if(-1 == FPrintf(tfh,"<a href=\"%s\">",Index)) break;
  700.       if(-1 == MyPuts(tfh,param.index)) break;
  701.       if(-1 == FPuts(tfh,"</a>")) break;
  702.       before = 1;
  703.     }
  704.  
  705.     if(*enode->Prev)
  706.     {
  707.       if(before) if(-1 == MyPuts(tfh,param.bar)) break;
  708.       if(-1 == FPrintf(tfh,"<a href=\"%s\">",enode->Prev)) break;
  709.       if(-1 == MyPuts(tfh,param.prev)) break;
  710.       if(-1 == FPuts(tfh,"</a>")) break;
  711.       before = 1;
  712.     }
  713.     else
  714.     {
  715.       struct Entry *pred = (struct Entry *)enode->link.mln_Pred;
  716.       if(pred->link.mln_Pred)
  717.       {
  718.         if(before) if(-1 == MyPuts(tfh,param.bar)) break;
  719.         if(-1 == FPrintf(tfh,"<a href=\"%s\">",pred->Node)) break;
  720.         if(-1 == MyPuts(tfh,param.prev)) break;
  721.         if(-1 == FPuts(tfh,"</a>")) break;
  722.         before = 1;
  723.       }
  724.     }
  725.  
  726.     if(*enode->Next)
  727.     {
  728.       if(before) if(-1 == MyPuts(tfh,param.bar)) break;
  729.       if(-1 == FPrintf(tfh,"<a href=\"%s\">",enode->Next)) break;
  730.       if(-1 == MyPuts(tfh,param.next)) break;
  731.       if(-1 == FPuts(tfh,"</a>")) break;
  732.       before = 1;
  733.     }
  734.     else
  735.     {
  736.       struct Entry *next = (struct Entry *)enode->link.mln_Succ;
  737.       if(next->link.mln_Succ)
  738.       {
  739.         if(before) if(-1 == MyPuts(tfh,param.bar)) break;
  740.         if(-1 == FPrintf(tfh,"<a href=\"%s\">",next->Node)) break;
  741.         if(-1 == MyPuts(tfh,param.next)) break;
  742.         if(-1 == FPuts(tfh,"</a>")) break;
  743.         before = 1;
  744.       }
  745.     }
  746.  
  747.     if(param.homeurl)
  748.     {
  749.       if(before) if(-1 == MyPuts(tfh,param.bar)) break;
  750.       if(-1 == FPrintf(tfh,"<a href=\"%s\">",param.homeurl)) break;
  751.       if(-1 == MyPuts(tfh,param.home)) break;
  752.       if(-1 == FPuts(tfh,"</a>")) break;
  753.     }
  754.  
  755.     if(-1 == FPutC(tfh,'\n')) break;
  756.     return(1);                            // ALL OK
  757.   }
  758.   return(0);                              // ERROR
  759. }
  760. //<
  761.  
  762. //> Convert()
  763. /*------------------------------------------------------------*
  764. *   Convert()       Reads guide and creates HTML files        *
  765. *     -> fh   input file handle                               *
  766. *     <-      Success                                         *
  767. */
  768. LONG Convert(BPTR fh)
  769. {
  770.   STRPTR buffer = AllocVec(LINELEN,MEMF_ANY);     // allocate line buffer
  771.   STRPTR node, title, line;
  772.   char nodename[100];
  773.   BPTR tfh = NULL;
  774.   ULONG linenr = 0;
  775.   short firstpage = 1;
  776.   struct Entry *enode = (struct Entry *)entries.mlh_Head;
  777.  
  778.   if(!buffer) return(0);
  779.  
  780.   PutStr("Converting into HTML\n");
  781.  
  782.    /* search for @node */
  783.   do
  784.   {
  785.     linenr++;
  786.     if(FGets(fh,buffer,LINELEN) == NULL) goto Done;
  787.   }
  788.   while(strnicmp(buffer,"@node ",strlen("@node ")));
  789.  
  790.    /* and go... */
  791.   for(;;)
  792.   {
  793.     if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto ErrorBrk;
  794.  
  795.      /* search the node name */
  796.     node = buffer+strlen("@node ");
  797.     while(*node == ' ') node++;     // skip leading spaces
  798.     if(*node == '\"')
  799.     {                               // Quote Mode
  800.       node++;
  801.       line = node;
  802.       while(*line!='\"' && *line!='\n')
  803.       {
  804.         if(*line==' ' || *line==':') *line='_';  // space -> '_'
  805.         line++;
  806.       }
  807.       *line++ = '\0';
  808.     }
  809.     else
  810.     {
  811.       line = node;
  812.       while(*line!=' ' && *line!='\n')
  813.       {
  814.         if(*line==':') *line='_';               // ':' -> '_'
  815.         line++;
  816.       }
  817.       *line++ = '\0';
  818.     }
  819.  
  820.      /* search node title */
  821.     if(*line == '\0')
  822.       title = line;                 // Node does not have a title
  823.     else
  824.     {
  825.       while(*line == ' ') line++;   // Skip spaces
  826.       if(*line == '\"') line++;     // Skip quotation mark
  827.       title = line;
  828.       while(*line != '\n') line++;  // search EOL
  829.       do line--; while(*line==' '); // skip trailing spaces
  830.       if(*line == '\"') line--;     // skip trailing quotation mark
  831.       *++line = '\0';               // terminate the line
  832.     }
  833.  
  834.     strlwr(node);                   // node name to lowercase
  835.     strcpy(nodename,node);
  836.     if(param.msdos)
  837.     {
  838.       strcat(nodename,".htm");
  839.     }
  840.     else
  841.     {
  842.       strcat(nodename,".html");
  843.     }
  844.  
  845.     if(tfh = Open(nodename,MODE_NEWFILE))
  846.     {
  847.       if(param.verbatim) Printf("Creating page '%s' (Title: '%s')\n",nodename,title);
  848.       if(-1 == FPuts(tfh,"<html>\n<head>\n  <title>")) goto ErrorFile;
  849.       if(-1 == MyPuts(tfh,title)) goto ErrorFile;
  850.       if(-1 == FPuts(tfh,"</title>\n"
  851.                          "  <meta name=\"Generator\" content=\"GuideML " VERSIONSTR "\">\n"
  852.                          "  <meta http-equiv=\"Content-Type\" content=\"text/html\">\n"
  853.                          "</head>\n<body")) goto ErrorFile;
  854.       if(param.bodyext)
  855.       {
  856.         if(-1 == FPutC(tfh,' ')) goto ErrorFile;
  857.         if(-1 == MyPuts(tfh,param.bodyext)) goto ErrorFile;
  858.       }
  859.       if(-1 == FPuts(tfh,">\n")) goto ErrorFile;
  860.       if(!NavBar(tfh,enode)) goto ErrorFile;
  861.       if(-1 == FPuts(tfh,"<hr>\n<pre>\n")) goto ErrorFile;
  862.  
  863.       for(;;)
  864.       {
  865.         linenr++;
  866.         if(FGets(fh,buffer,LINELEN) == NULL) goto ErrorEOF;
  867.  
  868.         if(buffer[0]=='@' && buffer[1]!='{')    // is it an AmigaGuide command
  869.         {
  870.           if(!strnicmp(buffer,"@node ",strlen("@node "))) break;
  871.           if(!strnicmp(buffer,"@endnode",strlen("@endnode"))) break;
  872.           continue;                           // unknown command
  873.         }
  874.  
  875.         if(!ConvLine(tfh,buffer,linenr))
  876.         {
  877.           Printf("Line %ld: Couldn't convert!\n",linenr);
  878.           goto Error;
  879.         }
  880.       }
  881.  
  882.       if(-1 == FPuts(tfh,"</pre>\n")) goto ErrorFile;
  883.       if(param.footer)
  884.       {
  885.         if(-1 == FPuts(tfh,"<hr>\n")) goto ErrorFile;
  886.         if(!NavBar(tfh,enode)) goto ErrorFile;
  887.       }
  888.       if(firstpage)
  889.       {
  890.         firstpage = 0;
  891.         if(-1 == FPuts(tfh,"<hr>\n<address>Converted using <tt>GuideML</tt> "VERSIONSTR", a converter written by Richard Körber <<a href=\"mailto:shred@chessy.aworld.de\">shred@chessy.aworld.de</a>></address>\n")) goto ErrorFile;
  892.       }
  893.       if(-1 == FPuts(tfh,"</body>\n</html>\n")) goto ErrorFile;
  894.       enode = (struct Entry *)enode->link.mln_Succ;
  895.       Close(tfh);
  896.       tfh = NULL;
  897.     }
  898.     else
  899.     {
  900.       Printf("Line %ld: Couldn't open %s for writing!\n",linenr,nodename);
  901.       goto Error;
  902.     }
  903.  
  904.     while(strnicmp(buffer,"@node ",strlen("@node ")))
  905.     {
  906.       linenr++;
  907.       if(FGets(fh,buffer,LINELEN) == NULL) goto Done;
  908.     }
  909.   }
  910.  
  911. Done:
  912.   FreeVec(buffer);
  913.   return(1);
  914.  
  915. ErrorBrk:
  916.   Printf("Line %ld: <CTRL-C> pressed!\n",linenr);
  917.   goto Error;
  918. ErrorFile:
  919.   Printf("Line %ld: Error writing file!\n",linenr);
  920.   goto Error;
  921. ErrorEOF:
  922.   Printf("Line %ld: Unexpected EOF!\n",linenr);
  923. Error:
  924.   if(tfh) Close(tfh);
  925.   FreeVec(buffer);
  926.   return(0);
  927. }
  928. //<
  929. //> PreScan()
  930. /*------------------------------------------------------------*
  931. *   PreScan()       Scans the AmigaGuide file                 *
  932. *     -> fh   input file handle                               *
  933. *     <-      Success                                         *
  934. */
  935. LONG PreScan(BPTR fh)
  936. {
  937.   STRPTR buffer = AllocVec(LINELEN,MEMF_ANY);     // allocate line buffer
  938.   STRPTR parse;
  939.   ULONG linenr  = 0;
  940.   ULONG nodectr = 0;
  941.   struct Entry *currentry = NULL;
  942.  
  943.   if(!buffer) return(0);
  944.  
  945.   PutStr("Scanning AmigaGuide document\n");
  946.    /* Is it an AmigaGuide document ? */
  947.   linenr++;
  948.   if(NULL == FGets(fh,buffer,LINELEN)) goto ErrorEOF;
  949.   if(strnicmp(buffer,"@database",strlen("@database")))
  950.   {
  951.     PutStr("This is no valid AmigaGuide file!\n");
  952.     goto Error;
  953.   }
  954.  
  955.    /* Search for commands */
  956.   for(;;)
  957.   {
  958.     if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto ErrorBrk;
  959.     linenr++;
  960.     if(!FGets(fh,buffer,LINELEN)) break;      // Scan all lines
  961.     if(buffer[0]!='@') continue;              // no command line
  962.     if(buffer[1]=='{') continue;              // a text command at first column?
  963.  
  964.     parse = buffer+1;
  965.  
  966.     if(!strnicmp(parse,"index ",strlen("index ")))    // @index <index>
  967.     {
  968.       CopyLink(parse+strlen("index "), Index);
  969.     }
  970.  
  971.     if(!strnicmp(parse,"node ",strlen("node ")))      // @node <name>
  972.     {
  973.       if(currentry) AddTail((struct List *)&entries,(struct Node *)currentry);
  974.       currentry = AllocVec(sizeof(struct Entry),MEMF_ANY|MEMF_CLEAR);
  975.       if(!currentry) goto ErrorMem;
  976.       currentry->Count = nodectr++;
  977.       CopyLink(parse+strlen("node "), currentry->Node);
  978.     }
  979.  
  980.     if(!strnicmp(parse,"prev ",strlen("prev ")))      // @prev <name>
  981.     {
  982.       if(currentry)
  983.       {
  984.         CopyLink(parse+strlen("prev "), currentry->Prev);
  985.       }
  986.     }
  987.  
  988.     if(!strnicmp(parse,"next ",strlen("next ")))      // @next <name>
  989.     {
  990.       if(currentry)
  991.       {
  992.         CopyLink(parse+strlen("next "), currentry->Next);
  993.       }
  994.     }
  995.  
  996.     if(!strnicmp(parse,"toc ",strlen("toc ")))        // @toc <name>
  997.     {
  998.       if(currentry)
  999.       {
  1000.         CopyLink(parse+strlen("toc "), currentry->TOC);
  1001.       }
  1002.     }
  1003.  
  1004.     if(!strnicmp(parse,"endnode",strlen("endnode")))  // @endnode
  1005.     {
  1006.       if(currentry)
  1007.       {
  1008.         AddTail((struct List *)&entries,(struct Node *)currentry);
  1009.         currentry = NULL;
  1010.       }
  1011.     }
  1012.   }
  1013.   if(currentry)
  1014.   {
  1015.     AddTail((struct List *)&entries,(struct Node *)currentry);
  1016.     if(!param.nowarn) Printf("Line %ld: WARNING: No closing @endnode found!\n",linenr);
  1017. //*    currentry = NULL;
  1018.   }
  1019.  
  1020.   FreeVec(buffer);
  1021.   return(1);
  1022.  
  1023. ErrorMem:
  1024.   Printf("Line %ld: Not enough memory!\n",linenr);
  1025.   goto Error;
  1026. ErrorBrk:
  1027.   Printf("Line %ld: <CTRL-C> pressed!\n",linenr);
  1028.   goto Error;
  1029. ErrorEOF:
  1030.   Printf("Line %ld: Unexpected EOF!\n",linenr);
  1031. Error:
  1032.   FreeVec(buffer);
  1033.   return(0);
  1034. }
  1035. //<
  1036.  
  1037. //> main()
  1038. /*------------------------------------------------------------*
  1039. *   main()          M A I N   P R O G R A M                   *
  1040. */
  1041. int main(void)
  1042. {
  1043.   struct RDArgs *args;
  1044.   static char template[] = "FILE/A,TO/K,URL=HOMEURL/K,PREV/K,NEXT/K,INDEX/K,TOC/K,HOME/K,BAR/K,BODY/K,VER=VERBATIM/S,IMG=IMAGES/S,FTR=FOOTER/S,NL=NOLINKS/S,NE=NOEMAIL/S,NW=NOWARN/S,MSDOS/S";
  1045.   static unsigned char defbar[] = " | ";
  1046.   BPTR fh;
  1047.   BPTR oldlock = NULL;
  1048.   struct Entry *node, *next;
  1049.   struct LinkStr *lstr = NULL;
  1050.  
  1051.   NewList((struct List *)&entries);
  1052.   param.prev  = "PREV";
  1053.   param.next  = "NEXT";
  1054.   param.index = "INDEX";
  1055.   param.toc   = "CONTENTS";
  1056.   param.home  = "HOME";
  1057.   param.bar   = defbar;
  1058.  
  1059.   if(args = (struct RDArgs *)ReadArgs(template,(LONG *)¶m,NULL))
  1060.   {
  1061.     PutStr("GuideML "VERSIONSTR"\n");
  1062.  
  1063.     if(param.images)
  1064.     {
  1065.       lstr = AllocVec(sizeof(struct LinkStr),MEMF_ANY);
  1066.       if(!lstr)
  1067.       {
  1068.         PutStr("**ERROR: Out of memory.\n");
  1069.         goto Flush;
  1070.       }
  1071.  
  1072.       sprintf(lstr->Prev ,"<img src=\"prev.gif\" alt=\"%s\" border=0>" ,param.prev );
  1073.       sprintf(lstr->Next ,"<img src=\"next.gif\" alt=\"%s\" border=0>" ,param.next );
  1074.       sprintf(lstr->Index,"<img src=\"index.gif\" alt=\"%s\" border=0>",param.index);
  1075.       sprintf(lstr->Toc  ,"<img src=\"toc.gif\" alt=\"%s\" border=0>"  ,param.toc  );
  1076.       sprintf(lstr->Home ,"<img src=\"home.gif\" alt=\"%s\" border=0>" ,param.home );
  1077.       param.prev  = lstr->Prev;
  1078.       param.next  = lstr->Next;
  1079.       param.index = lstr->Index;
  1080.       param.toc   = lstr->Toc;
  1081.       param.home  = lstr->Home;
  1082.       if(param.bar == defbar) param.bar = "";
  1083.     }
  1084.  
  1085.     if(fh = Open(param.from,MODE_OLDFILE))
  1086.     {
  1087.       if(param.to)
  1088.       {
  1089.         BPTR destlock;
  1090.         destlock = Lock(param.to,ACCESS_READ);
  1091.         if(!destlock)
  1092.         {
  1093.           PutStr("**ERROR: Couldn't lock destination drawer.\n");
  1094.           Close(fh);
  1095.           goto Flush;
  1096.         }
  1097.         oldlock = CurrentDir(destlock);
  1098.       }
  1099.  
  1100.       if(!PreScan(fh))
  1101.       {
  1102.         PutStr("**ERROR: Scanning failed.\n");
  1103.         Close(fh);
  1104.         goto Flush;
  1105.       }
  1106.       Seek(fh,0,OFFSET_BEGINNING);
  1107.       if(!Convert(fh))
  1108.       {
  1109.         PutStr("**ERROR: Conversion failed.\n");
  1110.         Close(fh);
  1111.         goto Flush;
  1112.       }
  1113.       Close(fh);
  1114.     }
  1115.     else
  1116.       Printf("**ERROR: couldn't open file %s!\n",param.from);
  1117.  
  1118.     if(param.images)
  1119.     {
  1120.       PutStr("Saveing images\n");
  1121.       if(!SaveImages())
  1122.         PutStr("**ERROR: couldn't save image files\n");
  1123.     }
  1124.  
  1125. Flush:
  1126.     for (node = (struct Entry *)entries.mlh_Head;
  1127.          next = (struct Entry *)node->link.mln_Succ;
  1128.          node = next)
  1129.     {
  1130.       Remove((struct Node *)node);
  1131.       FreeVec(node);
  1132.     }
  1133.  
  1134.     if(lstr) FreeVec(lstr);
  1135.  
  1136.     if(oldlock) UnLock(CurrentDir(oldlock));
  1137.  
  1138.     FreeArgs(args);
  1139.   }
  1140.   else
  1141.     PutStr("GuideML "VERSIONSTR"\n"
  1142.            "© 1997-98 by Richard Körber <shred@eratosthenes.starfleet.de>\n"
  1143.            "Yet Another (tm) AmigaGuide to HTML Converter!\n\n"
  1144.            "USAGE:\tFILE/A\t\tAmigaGuide file to be converted\n"
  1145.            "\tTO/K\t\tDestination drawer for the html pages\n"
  1146.            "\tURL=HOMEURL/K\tURL accessed by the 'HOME' button\n"
  1147.            "\tPREV/K\t\t'PREV' button text/image\n"
  1148.            "\tNEXT/K\t\t'NEXT' button text/image\n"
  1149.            "\tINDEX/K\t\t'INDEX' button text/image\n"
  1150.            "\tTOC/K\t\t'CONTENTS' button text/image\n"
  1151.            "\tHOME/K\t\t'HOME' button text/image\n"
  1152.            "\tBAR/K\t\tBar text between navigation buttons\n"
  1153.            "\tBODY/K\t\tAddition to the body tag of every page\n"
  1154.            "\tVER=VERBATIM/S\tList of created files\n"
  1155.            "\tIMG=IMAGES/S\tCreate image navigation bar\n"
  1156.            "\tFTR=FOOTER/S\tNavigation bar also at end of page\n"
  1157.            "\tNL=NOLINKS/S\tIgnore internet links\n"
  1158.            "\tNE=NOEMAIL/S\tIgnore e-mail addresses\n"
  1159.            "\tNW=NOWARN/S\tDon't show warnings\n"
  1160.            "\tMSDOS/S\t\tCreate MS-DOS filenames (*.htm)\n"
  1161.            "\n");
  1162.   return(0);
  1163. }
  1164. //<
  1165.  
  1166. /**************************************************************/
  1167.