home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / xref_v1.1.lha / XRef / Tools / source / xrefconvert.c < prev   
Encoding:
C/C++ Source or Header  |  1995-01-09  |  70.2 KB  |  2,300 lines

  1. ;/* execute me to make with SAS 6.x
  2. sc NOSTKCHK CSRC xrefconvert.c OPT IGNORE=73
  3. slink lib:c.o xrefconvert.o //Goodies/extrdargs/extrdargs.o TO /c/xrefconvert SMALLDATA SMALLCODE NOICONS LIB lib:amiga.lib lib:sc.lib /lib/xrefsupport.lib
  4. quit
  5. */
  6.  
  7. /*
  8. ** $PROJECT: XRef-Tools
  9. **
  10. ** $VER: xrefconvert.c 1.16 (03.11.94)
  11. **
  12. ** by
  13. **
  14. ** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
  15. **
  16. ** (C) Copyright 1994
  17. ** All Rights Reserved !
  18. **
  19. ** $HISTORY:
  20. **
  21. ** 03.11.94 : 001.016 :  default icon filename now correct
  22. ** 11.09.94 : 001.015 :  now displays current processing in a status window,
  23. **                       if started from workbench
  24. ** 03.09.94 : 001.014 :  now uses ENTRYA_NodeName for all entries
  25. ** 31.08.94 : 001.013 :  v40 smartwrap test code added
  26. ** 29.08.94 : 001.012 :  unix manpages support added
  27. ** 27.08.94 : 001.011 :  bumped to version 1, TOC uses now columns
  28. ** 27.08.94 : 000.010 :  main node title fixed, now uses XREFA_CategoryParsed
  29. ** 22.07.94 : 000.009 :  some enhancements,bug fixes and optimizations
  30. ** 17.07.94 : 000.008 :  amigaguide filetype added
  31. ** 13.07.94 : 000.007 :  set index added
  32. ** 11.06.94 : 000.006 :  fixed bug struct "Window" -> "Windwo"ToFront(),saveicon ...
  33. ** 29.05.94 : 000.005 :  normal doc support added
  34. ** 21.05.94 : 000.004 :  autodoc "table of contents" support
  35. ** 18.05.94 : 000.003 :  ctrl-c supported
  36. ** 16.05.94 : 000.002 :  autodoc support added
  37. ** 14.05.94 : 000.001 :  initial
  38. **
  39. */
  40.  
  41. /* ------------------------------- includes ------------------------------- */
  42.  
  43. #include "Def.h"
  44.  
  45. #include <ctype.h>
  46.  
  47. #include <libraries/xref.h>
  48. #include <proto/xref.h>
  49.  
  50. #include <debug.h>
  51. #include <register.h>
  52.  
  53. #include "/lib/xrefsupport.h"
  54.  
  55. #include "xrefconvert_rev.h"
  56.  
  57. /* ------------------------------- AutoDoc -------------------------------- */
  58.  
  59. /*FS*/ /*"AutoDoc"*/
  60. /*GB*** XRef-Tools/XRefConvert ***********************************************
  61.  
  62. $VER: XRefConvert.doc
  63.  
  64. NAME
  65.     XRefConvert - converts autodoc or header files to AmigaGuide files
  66.  
  67. TEMPLATE
  68.     FORM/M/A,TO/A,KEYWORDFILE/K,EXCEPTIONFILE/K,STDDELIMITERS/K,
  69.     EXCLUDETYPES/K,INCLUDETYPES/K,INDENT/N/K,TOOLPRI/N/K,NOICON/S,
  70.     NOAMIGAGUIDE/S,NOMAINPAGELINK/S,STATISTIC/S,V40/S,VERBOSE/S
  71.  
  72. FORMAT
  73.     XRefConvert [FROM] file|dir [file2|dir2] [TO] dir [CATEGORY categories]
  74.                 [KEYWORDFILE keyworddef] [EXCEPTIONFILE exceptdef] 
  75.                 [STDDELIMITERS string] [EXCLUDETYPES types]
  76.                 [INCLUDETYPES types] [INDENT number] [TOOLPRI priority]
  77.                 [NOICON] [NOAMIGAGUIDE] [NOMAINPAGELINK] [STATISTIC] [V40]
  78.                 [VERBOSE]
  79.  
  80. FUNCTION
  81.     Files:
  82.     converts a C header file or a autodoc file in a AmigaGuide file.Which type
  83.     a given file is, is determined by the suffix of the filename :
  84.        - ".h" for a C header file
  85.        - ".doc" or ".dok" for a doc file and
  86.        - these suffix with the "TABLE OF CONTENTS" for an autodoc file
  87.     If the switch NOAMIGAGUIDE is on, XRefConvert will generate the appropri-
  88.     ate files with out the headers for an AmigaGuide file.If this is not
  89.     turned on,it generates an AmigaGuide file. Thus you can use the keyword
  90.     format feature also to convert to AmigaGuide or to convert in normal ASCII
  91.     format.
  92.  
  93.     Delimiters:
  94.     This tool separates words by using of a delimiter-string. The default
  95.     string is " \t\n,<>=(){}\":.;*|!". Any of these charaters terminates a
  96.     word. You can specify an other delimiter string by using of the
  97.     STDDELIMITERS option for the command.
  98.  
  99.     Keyword file:
  100.     To specify keywords you must pass a keyword file, which contains keyword
  101.     definitions (see KEYWORDFILE option).XRefConvert loads first the
  102.     "Sys:config/xref/keywords" file is it exists.After this it loads the
  103.     specified keywordfile or it looks for a "keywords" file in the current
  104.     directory.
  105.  
  106.     Icon:
  107.     XRefConvert will use the ENV:sys/def_guide.info icon for each generated
  108.     AmigaGuide database. If this icon doesn't exists it uses a internal icon.
  109.  
  110. INPUTS
  111.     FROM (STRINGS) - specifies input files and/or directories
  112.  
  113.     TO (STRING) - specifies the output directory, in which the generated
  114.         direcotries/files are placed.
  115.  
  116.     CATEGORY (STRING) - category pattern to use for convertion. Only
  117.         xreffiles are parsed, which matches this category pattern.
  118.  
  119.     KEYWORDFILE (STRING) - file, which contains keyword definitions to substi-
  120.         tute such keywords.
  121.         The file must have the following format :
  122.         - First the file format is ASCII-text, which is line orientated.
  123.           Each line is parsed via ReadArgs() function of the dos.library with
  124.           the following template :
  125.           
  126.           KEYWORD/K/A,SUBSTITUTE/K/A,DELIMITERS/K,NEXTWORD/S
  127.  
  128.           if a line matches these template it will be stored and used by the
  129.           convertion.
  130.  
  131.           the format of line is (note in the file, it must be one line !!!) :
  132.  
  133.           KEYWORD keyword SUBSTITUTE substitute-string [DELIMITERS string] \
  134.           [NEXTWORD]
  135.  
  136.           KEYWORD (STRING) - specifies the word to search for, if this is
  137.               AUTODOC, the substitute string is used to substitute all words,
  138.               which matches a AutoDoc description word (f.e. : "NAME",
  139.               "SYNOPSIS",...). To detect such words it must match the
  140.               following : first in the line there can be 
  141.                           INDENT - 2 < n < INDENT + 2
  142.               n spaces, then the word must follow in uppercase letters and 
  143.               after this must be a newline !
  144.           SUBSTITUTE (STRING) - specifies the string to replace the keyword
  145.               in the generated file a "%s" in this string inserts the keyword
  146.               itself (just one time for now).
  147.           DELIMITERS (STRING) - specifies the delimiters for the next word.
  148.               This string is only valid if the NEXTWORD switch is turned on.
  149.           NEXTWORD (BOOLEAN) - indicates, that the next word should replaced,
  150.               instead of the keyword. If you also specify the DELIMITERS, the
  151.               end of the next word is defined by any character in this string.
  152.  
  153.           For the V40 option there exists a special keywordfile named
  154.           keywords.v40 in the config directory. In this file you can specify,
  155.           which text passages are wrapped and which not, using the new
  156.           smartwrap function. If you want a text passage be wrapped define a
  157.           KEYWORD with the description title like "FUNCTION" and use the
  158.           "@{mtext %s}" macro as the SUBSTITUTE string. Thus this text passage
  159.           should be smartwrapped (See also the default keywords.v40 file) !
  160.  
  161.     EXCEPTIONFILE (STRING) - file, which contain names that are only linked,
  162.         if a "()" is at the end of the name, see AD2AG. Each line has only one
  163.         name.The default is $XREFCONFIGDIR/exceptions .
  164.  
  165.     STDDELIMITERS (STRING) - string, which defines the delimiters characters
  166.         the default is : " \t\n,<>=(){}\":.;*|!"
  167.  
  168.     EXCLUDETYPES (STRING) - string, which defines the entrytypes that aren't
  169.         used during convertion. With this option you can subpress links to
  170.         the specified types. Each type in this string is separated by an '|'
  171.         character. For example you don't want links to typedef's and macro's.
  172.         Then you have to specify this : EXCLUDETYPES "typedef|macro" !
  173.         Types available for this option : "generic", "function", "command",
  174.         "include", "macro", "struct", "field", "typedef", "define" !
  175.         Default is "".
  176.  
  177.     INCLUDETYPES (STRING) - string , which defines the entrytypes that are
  178.         only used during convertion. See EXCLUDETYPES for string format and
  179.         available types.
  180.  
  181.     INDENT (NUMBER) - number of spaces, which are inserted before an AutoDoc
  182.         description word (see KEYWORDFILE/KEYWORD above).
  183.  
  184.     PRI (NUMBER) - task priority to use during converting
  185.  
  186.     NOAMIGAGUIDE (BOOLEAN) - indicates, that shouldn't create AmigaGuide 
  187.         headers for each file
  188.  
  189.     NOICON (BOOLEAN) - don't save an icon for the generated amigaguide file
  190.  
  191.     NOMAINPAGELINK (BOOLEAN) - don't generate a TABLE OF CONTENTS link to the
  192.         xref.library dynamic node main page.
  193.  
  194.     STATISTIC (BOOLEAN) - outputs statistics about the generated links to each
  195.         type of entries. Such as include's or functions.
  196.  
  197.     V40 (BOOLEAN) - generate amigaguide files for use with amigaguide.datatype
  198.         V40 or higher. This generates databases, which uses the smartwrap
  199.         option of the V40 version. This option works only with files in the
  200.         autodoc format and perhaps not with all files of this fileformat. So
  201.         convert and take a look at the generated files !
  202.         If this option is specified XRefConvert tries to load also the file
  203.         "Sys:config/xref/keywords.v40" , in which the keywords are defined to
  204.         use smartwrap !
  205.  
  206.     VERBOSE (BOOLEAN) - output informations of the current convertion state
  207.  
  208. EXAMPLE
  209.     XRefConvert include:amiga/ aguide:include/ KEYWORDFILE s:mykeywords \
  210.                 AMIGAGUIDE VERBOSE
  211.  
  212. SEE ALSO
  213.     MakeXRef, LoadXRef, ParseXRef, AGuideXRefV37, AGuideXRefV39, StatXRef,
  214.     XRefAttrs, MakeAGuideIndex
  215.  
  216. COPYRIGHT
  217.     (C) by Stefan Ruppert 1994
  218.  
  219. HISTORY
  220.     XRefConvert 1.14 (3.11.94) :
  221.        - default icon name now correct "Env:Sys/def_guide"
  222.        - time calculation now correct
  223.  
  224.     XRefConvert 1.13 (11.9.94) :
  225.        - workbench support added
  226.        - status window, if started from workbench added
  227.  
  228.     XRefConvert 1.12 (3.9.94) :
  229.         - now gets the nodename from the entry with ENTRYA_NodeName
  230.  
  231.     XRefConvert 1.11 (31.8.94) :
  232.         - added V40 option
  233.  
  234.     XRefConvert 1.10 (29.8.94) :
  235.         - unix manpage support added
  236.  
  237.     XRefConvert 1.9 (27.8.94) :
  238.         - main node title shows now the relative path instead of the first
  239.           path part
  240.         - uses now XREFA_CategoryParsed if a category is specified. This
  241.           speeds up the convertion.
  242.         - for AutoDoc TOC uses now the columns from the xref.library
  243.  
  244.     XRefConvert 1.8 (23.7.94) :
  245.         - added EXCLUDETYPPES,INCLUDETYPES option
  246.  
  247.     XRefConvert 1.7 (22.7.94) :
  248.         - some bug fixed.
  249.         - now can handle <entry>/<entry> pairs
  250.         - the InternXRef list wasn't free'd after convertion of a file
  251.           (this slowed down the convertion of more than one file per call).
  252.           This is fixed and some optimizations by stepping through the list.
  253.         - New statistic display
  254.         - PRI option added
  255.  
  256.     XRefConvert 1.6 (17.7.94) :
  257.         - now it supports amigaguide files to convert ! It tries to link all
  258.           internal @node titles in the text to the node. And links all found
  259.           xref entries.
  260.         - the point is now a special delimiter ! The following sequences are
  261.           now interpreted as a delimiter ". ",".\0",".\t",".\n" !
  262.         - category pattern added
  263.  
  264.     XRefConvert 1.5 (13.7.94) :
  265.         - now tries to set the index array for each xreffile to get the best
  266.           performance (then it uses a binary search algorithm)
  267.  
  268.     XRefConvert 1.4 (11.6.94) :
  269.         - ':','-',';','*' added to STDDELIMITERS default string
  270.         - now tries to load "Sys:config/xref/keywords" every time and then
  271.           tries to load the specified keyword file. If no one is specified
  272.           tries to load the "keywords" file in the current directory.
  273.         - save icon bug fixed , if the source file had an unknown type the
  274.           icon was saved even though. This is fixed.
  275.         - All structures , which have equal autodoc beginnings like , Window
  276.           struct "Window" * -> "Window"ToFront() aren't linked. This is fixed!
  277.  
  278.     XRefConvert 1.3 (29.5.94) :
  279.         - INDENT option added
  280.  
  281. *****************************************************************************/
  282. /*FE*/
  283.  
  284. /* ------------------------------- defines -------------------------------- */
  285.  
  286. /*FS*/ /*"Definitions"*/
  287. #define PATH_LEN              512
  288. #define BUFFER_LEN            1024
  289. #define NAME_LEN              256
  290.  
  291. #define EOS                   '\0'
  292.  
  293. #define PUDDLE_SIZE           2048
  294. #define THRESH_SIZE           PUDDLE_SIZE
  295.  
  296. #define MAX_VARRAY            10
  297. #define LINE_UPDATE           20           /* verbose after n lines */
  298.  
  299. #define IXR(node)             ((struct InternXRef *) (node))
  300.  
  301. #define XREFCT_KEYWORDS       XREFT_MAXTYPES
  302. #define XREFCT_INTERN         XREFT_MAXTYPES + 1
  303.  
  304. #define DISPLAY_TYPES         XREFT_MAXTYPES + 2
  305.  
  306. enum {
  307.    STYLE_UNKNOWN,
  308.    STYLE_UNDERLINED,
  309.    STYLE_BOLD,
  310.    STYLE_MAX,
  311.    };
  312.  
  313. /*FE*/
  314.  
  315. /* ------------------------------ structures ------------------------------ */
  316.  
  317. /*FS*/ /*"Structures"*/
  318. struct Convert
  319. {
  320.    ULONG Number;
  321.  
  322.    ULONG xr_Type;
  323.    STRPTR xr_Name;
  324.    STRPTR xr_File;
  325.    ULONG xr_Line;
  326.    STRPTR xr_NodeName;
  327.    STRPTR xr_Path;
  328. };
  329.  
  330. struct KeyWord
  331. {
  332.    struct Node kw_Node;                /* node to link in a list */
  333.    STRPTR kw_Keyword;                  /* keyword to search for */
  334.    STRPTR kw_Substitute;               /* string to substitute the keyword */
  335.    STRPTR kw_Delimiters;               /* delimiters to use for the nextword */
  336.    BOOL kw_NextWord;                   /* specifies to substitute the next WORD
  337.                                           instead of the keyword */
  338. };
  339.  
  340. struct Exceptions
  341. {
  342.    struct Node e_Node;
  343.    ULONG e_Length;
  344. };
  345.  
  346. struct Stat
  347. {
  348.    ULONG Number[DISPLAY_TYPES];        /* number of linked types */
  349. };
  350.  
  351. struct InternXRef
  352. {
  353.    struct Node ixr_Node;               /* node to link intern xref entries */
  354.    ULONG ixr_Length;                   /* length of the node */
  355.    ULONG ixr_NameLen;                  /* length of the ln_Name string */
  356.    STRPTR ixr_Link;                    /* if name != link , then here stands the link */
  357. };
  358.  
  359. struct GlobalData
  360. {
  361.    STRPTR gd_Ptr;                      /* pointer to the next WORD */
  362.    STRPTR gd_CurrentPtr;               /* pointer to the actual WORD */
  363.  
  364.    APTR gd_Pool;                       /* memory pool for Keyword and Exception lists */
  365.    APTR gd_InternPool;                 /* memory pool for InternXRef list */
  366.    ULONG *gd_Para;                     /* link to the arguments passed via command line */
  367.    BOOL gd_Workbench;                  /* started from workbench ? */
  368.    BOOL gd_Abort;                      /* set to TRUE if the user has canceled */
  369.  
  370.    BPTR gd_ReadFH;                     /* read filehandle */
  371.    BPTR gd_WriteFH;                    /* write filehandle */
  372.    BPTR gd_StartDir;                   /* current directory by program start */
  373.    ULONG gd_FileSize;                  /* length of the actual file */
  374.    ULONG gd_FileType;                  /* type of the file to scan e.g FTYPE_#? */
  375.    STRPTR gd_FileName;                 /* actual filename (may be relative) */
  376.    STRPTR gd_FullPath;                 /* full path for the current file */
  377.    ULONG gd_OpenNodes;                 /* is there a @node without a closing @endnode ? */
  378.    ULONG gd_Line;                      /* counting the lines */
  379.    ULONG gd_ConvertedFiles;            /* number of converted files */
  380.  
  381.  
  382.    UWORD gd_SeeAlso;                   /* SEE ALSO block follow's -> don't use the exceptions */
  383.    ULONG gd_StyleType;                 /* STYLE_#? values */
  384.    BOOL gd_LineBegin;                  /* just read a line */
  385.    BOOL gd_SmartWrapped;               /* is the current paragraph smartwrapped ? */
  386.  
  387.    struct List gd_KeywordList;         /* list of keywords from the keyword file */
  388.    struct List gd_InternXRef;          /* list of the table of contents from an autodoc */
  389.    struct List gd_ExceptionList;       /* list of exceptionfiles */
  390.  
  391.    struct ScanWindow gd_SWin;
  392.    struct ScanStat gd_SStat;
  393.    struct TimeCalc gd_TimeCalc;
  394.  
  395.    struct FileInfoBlock *gd_Fib;       /* global FileInfoBlock */
  396.    struct TagItem gd_Tags[8];          /* global tags for XRefParse() */
  397.    struct Hook gd_Hook;                /* parse hook structure */
  398.    struct Convert gd_Convert;          /* structure passed to the parse hook */
  399.  
  400.    struct Stat gd_GlobalStat;          /* global statistics */
  401.    ULONG gd_Links;                     /* number of links generated */
  402.  
  403.    ULONG gd_ExcTypes[XREFT_MAXTYPES];  /* types to be not converted */
  404.    ULONG gd_IncTypes[XREFT_MAXTYPES];  /* types to be converted */
  405.  
  406.    UBYTE gd_Dest[PATH_LEN];            /* buffer for the filename to write */
  407.    UBYTE gd_LineBuffer[BUFFER_LEN];    /* buffer to hold a line from the file */
  408.    UBYTE gd_WordBuffer[BUFFER_LEN];    /* buffer to hold the current WORD */
  409.    UBYTE gd_TempBuffer[BUFFER_LEN];    /* tempory buffer to do something */
  410.    UBYTE gd_NameBuffer[NAME_LEN];      /* buffer for the autodoc node name */
  411.    UBYTE gd_AutoDocIntro[NAME_LEN];    /* autodoc intro statement substitute buffer */
  412.  
  413.    STRPTR gd_VArray[MAX_VARRAY];       /* buffer for number of %s in a substitute */
  414. };
  415. /*FE*/
  416.  
  417. /* -------------------------- temlate definition -------------------------- */
  418.  
  419. /*FS*/ /*"Templates"*/
  420. #define template "FROM/M/A,TO/A,CATEGORY/K,KEYWORDFILE/K,EXCEPTIONFILE/K," \
  421.                  "STDDELIMITERS/K,EXCLUDETYPES/K,INCLUDETYPES/K,INDENT/N/K," \
  422.                  "TOOLPRI/N/K,NOICON/S,NOAMIGAGUIDE/S,NOMAINPAGELINK/S," \
  423.                  "STATISTIC/S,V40/S,VERBOSE/S"
  424.  
  425. enum {
  426.    ARG_FROM,
  427.    ARG_TO,
  428.    ARG_CATEGORY,
  429.    ARG_KEYWORDFILE,
  430.    ARG_EXCEPTIONFILE,
  431.    ARG_STDDELIMITERS,
  432.    ARG_EXCLUDETYPES,
  433.    ARG_INCLUDETYPES,
  434.    ARG_INDENT,
  435.    ARG_TOOLPRI,
  436.    ARG_NOICON,
  437.    ARG_NOAMIGAGUIDE,
  438.    ARG_NOMAINPAGELINK,
  439.    ARG_STATISTIC,
  440.    ARG_V40,
  441.    ARG_VERBOSE,
  442.    ARG_MAX};
  443.  
  444. #define keywordtemplate   "KEYWORD/K/A,SUBSTITUTE/K/A,DELIMITERS/K,NEXTWORD/S"
  445.  
  446. enum {
  447.    ARG_KEYWORD,
  448.    ARG_SUBSTITUTE,
  449.    ARG_DELIMITERS,
  450.    ARG_NEXTWORD,
  451.    ARG_KEYWORDMAX};
  452.  
  453. /*FE*/
  454.  
  455. /* ------------------------------ prototypes ------------------------------ */
  456.  
  457. /*FS*/ /*"Prototypes"*/
  458.  
  459. void getkeywords(struct GlobalData *gd,STRPTR file);
  460. void getexceptionwords(struct GlobalData *gd,STRPTR file);
  461.  
  462. void parse_typestring(STRPTR typestr,ULONG *typearray);
  463.  
  464. RegCall LONG scan_file(REGA0 struct Hook *hook,REGA2 struct GlobalData *gd,REGA1 struct spMsg *msg);
  465.  
  466. void scan_amigaguide(struct GlobalData *gd);
  467. void scan_header(struct GlobalData *gd);
  468. void scan_autodoc(struct GlobalData *gd);
  469. void scan_doc(struct GlobalData *gd);
  470. void scan_man(struct GlobalData *gd);
  471. void scan_info(struct GlobalData *gd);
  472.  
  473. BOOL check_exception(struct GlobalData *gd);
  474. BOOL check_autodocintro(struct GlobalData *gd,STRPTR line);
  475. BOOL check_keyword(struct GlobalData *gd);
  476. BOOL check_internxref(struct GlobalData *gd);
  477. void check_reference(struct GlobalData *gd);
  478.  
  479. void write_guide_header(struct GlobalData *gd);
  480. void write_link(struct GlobalData *gd);
  481. void write_word(struct GlobalData *gd);
  482.  
  483. STRPTR getword(struct GlobalData *gd,STRPTR delim);
  484.  
  485. void allocinternxref(struct GlobalData *gd,STRPTR name,STRPTR link);
  486. ULONG getmanword(struct GlobalData *gd,STRPTR word,STRPTR buffer);
  487.  
  488. void output_statistic(struct GlobalData *gd,struct Stat *stat);
  489.  
  490. BOOL check_abort(struct GlobalData *gd);
  491.  
  492. void draw_state(struct GlobalData *gd);
  493. void draw_keyword(struct GlobalData *gd);
  494.  
  495. /*FE*/
  496.  
  497. /* ------------------------------ Icon Data ------------------------------- */
  498.  
  499. /*FS*/ /*"Icon Data"*/
  500. static UWORD icon_infoIData[176] = {
  501. /*------ plane # 0: --------*/
  502.         0x0000, 0x0000, 0x0000, 0x0400, 
  503.         0x0000, 0x0000, 0x0000, 0x0C00, 
  504.         0x0000, 0x0000, 0x0000, 0x0C00, 
  505.         0x07FF, 0xFFFF, 0xFFE0, 0x0C00, 
  506.         0x0400, 0x0000, 0x0030, 0x0C00, 
  507.         0x04AB, 0xFA00, 0x0028, 0x0C00, 
  508.         0x0400, 0x0000, 0x0024, 0x0C00, 
  509.         0x04BF, 0xEAAA, 0xAAA2, 0x0C00, 
  510.         0x0400, 0x0000, 0x003F, 0x0C00, 
  511.         0x04AA, 0xAAAA, 0xAAA8, 0x8C00, 
  512.         0x0400, 0x0000, 0x0000, 0x8C00, 
  513.         0x04AA, 0xABFE, 0xAAA8, 0x8C00, 
  514.         0x0400, 0x0000, 0x0000, 0x8C00, 
  515.         0x04AA, 0xAAAA, 0xAAA8, 0x8C00, 
  516.         0x0400, 0x0000, 0x0000, 0x8C00, 
  517.         0x04BF, 0xEAAA, 0xFEA8, 0x8C00, 
  518.         0x0400, 0x0000, 0x0000, 0x8C00, 
  519.         0x0400, 0x0000, 0x0000, 0x8C00, 
  520.         0x07FF, 0xFFFF, 0xFFFF, 0x8C00, 
  521.         0x0000, 0x0000, 0x0000, 0x0C00, 
  522.         0x0000, 0x0000, 0x0000, 0x0C00, 
  523.         0x7FFF, 0xFFFF, 0xFFFF, 0xFC00, 
  524. /*------ plane # 1: --------*/
  525.         0xFFFF, 0xFFFF, 0xFFFF, 0xF800, 
  526.         0xD555, 0x5555, 0x5555, 0x5000, 
  527.         0xD555, 0x5555, 0x5555, 0x5000, 
  528.         0xD000, 0x0000, 0x0015, 0x5000, 
  529.         0xD3FF, 0xFFFF, 0xFFC5, 0x5000, 
  530.         0xD355, 0xF5FF, 0xFFD5, 0x5000, 
  531.         0xD3FF, 0xFFFF, 0xFFD9, 0x5000, 
  532.         0xD35F, 0xD555, 0x555D, 0x5000, 
  533.         0xD3FF, 0xFFFF, 0xFFC0, 0x5000, 
  534.         0xD355, 0x5555, 0x5557, 0x5000, 
  535.         0xD3FF, 0xFFFF, 0xFFFF, 0x5000, 
  536.         0xD355, 0x55FD, 0x5557, 0x5000, 
  537.         0xD3FF, 0xFFFF, 0xFFFF, 0x5000, 
  538.         0xD355, 0x5555, 0x5557, 0x5000, 
  539.         0xD3FF, 0xFFFF, 0xFFFF, 0x5000, 
  540.         0xD35F, 0xD555, 0x7D57, 0x5000, 
  541.         0xD3FF, 0xFFFF, 0xFFFF, 0x5000, 
  542.         0xD3FF, 0xFFFF, 0xFFFF, 0x5000, 
  543.         0xD000, 0x0000, 0x0000, 0x5000, 
  544.         0xD555, 0x5555, 0x5555, 0x5000, 
  545.         0xD555, 0x5555, 0x5555, 0x5000, 
  546.         0x8000, 0x0000, 0x0000, 0x0000, 
  547. };
  548.  
  549. static struct Image icon_infoImg =
  550. {
  551.         0, 0,               /* LeftEdge, TopEdge */
  552.         54, 22, 2,          /* Width, Height, Depth */
  553.         &icon_infoIData[0], /* ImageData */
  554.         0x03, 0x00,         /* PlanePick, PlaneOnOff */
  555.         0L                  /* NextImage */
  556. };
  557.  
  558. struct SaveDefIcon icondef = {
  559.    "Env:Sys/def_guide",
  560.    "Multiview",
  561.    NULL,
  562.    &icon_infoImg};
  563.  
  564. /*FE*/
  565.  
  566. /* ---------------------------- library bases ----------------------------- */
  567.  
  568. extern struct Library *SysBase;
  569. struct Library *XRefBase;
  570.  
  571. /* --------------------------- static constants --------------------------- */
  572.  
  573. /*FS*/ /*"Constants"*/
  574. static const STRPTR version       = VERSTAG;
  575. static const STRPTR prgname       = "XRefConvert";
  576. static const STRPTR toc           = "TABLE OF CONTENTS";
  577. static const STRPTR endnode       = "\n@endnode\n";
  578. static const STRPTR database      = "@database";
  579.  
  580. static const STRPTR xreftype_names[DISPLAY_TYPES] = {
  581.    "generic",
  582.    "function",
  583.    "command",
  584.    "include",
  585.    "macro",
  586.    "struct",
  587.    "field",
  588.    "typedef",
  589.    "define",
  590.    /* xrefconvert display types */
  591.    "keywords",
  592.    "intern"};
  593.  
  594. static const STRPTR style_strings[STYLE_MAX] = {
  595.    "%s",
  596.    "@{u}%s@{uu}",
  597.    "@{b}%s@{ub}"};
  598.  
  599. static const STRPTR displaytexts[] = {
  600.    "Files",
  601.    "Dirs",
  602.    "Source",
  603.    "Dest",
  604.    "Links",
  605.    "Keywords",
  606.    NULL};
  607.  
  608. enum {
  609.    NUM_FILES,
  610.    NUM_DIRS,
  611.    NUM_SOURCE,
  612.    NUM_DEST,
  613.    NUM_LINKS,
  614.    NUM_KEYWORDS,
  615.    NUM_MAX};
  616.  
  617. /*FE*/
  618.  
  619. /* ---------------------------- parsexref hook ---------------------------- */
  620.  
  621. /*FS*//*"ULONG converthook(struct Hook *hook,struct XRefFileNode *xref,struct xrmXRef *msg)"*/
  622. RegCall GetA4 ULONG converthook(REGA0 struct Hook *hook,REGA2 struct XRefFileNode *xref,REGA1 struct xrmXRef *msg)
  623. {
  624.    struct Convert *myconv = (struct Convert *) hook->h_Data;
  625.  
  626.    if(msg->Msg == XRM_XREF)
  627.    {
  628.       struct TagItem *tstate = msg->xref_Attrs;
  629.       struct TagItem *tag;
  630.  
  631.       ULONG tidata;
  632.  
  633.       myconv->Number++;
  634.       myconv->xr_Line = ~0;
  635.  
  636.       while((tag = NextTagItem(&tstate)))
  637.       {
  638.          tidata = tag->ti_Data;
  639.       
  640.          switch(tag->ti_Tag)
  641.          {
  642.          case ENTRYA_Type:
  643.             myconv->xr_Type = tidata;
  644.             break;
  645.          case ENTRYA_File:
  646.             myconv->xr_File = (STRPTR) tidata;
  647.             break;
  648.          case ENTRYA_Name:
  649.             myconv->xr_Name = (STRPTR) tidata;
  650.             break;
  651.          case ENTRYA_Line:
  652.             myconv->xr_Line = tidata;
  653.             break;
  654.          case ENTRYA_NodeName:
  655.             myconv->xr_NodeName = (STRPTR) tidata;
  656.             break;
  657.          case XREFA_Path:
  658.             myconv->xr_Path = (STRPTR) tidata;
  659.             break;
  660.          }
  661.       }
  662.    } else
  663.       Printf ("Not supported hook message : %ld\n",msg->Msg);
  664.  
  665.    return(0);
  666. }
  667. /*FE*/
  668.  
  669. /* --------------------------- main entry point --------------------------- */
  670.  
  671. /*FS*/ /*"int main(int ac,char *av[])"*/
  672. int main(int ac,char *av[])
  673. {
  674.    struct ExtRDArgs eargs = {NULL};
  675.  
  676.    struct GlobalData *gd;
  677.    ULONG para[ARG_MAX];
  678.  
  679.    ULONG retval = RETURN_OK;
  680.    STRPTR obj = prgname;
  681.    LONG err;
  682.    WORD i;
  683.  
  684.    for( i = 0 ; i < ARG_MAX ; i++ )
  685.       para[i] = 0;
  686.  
  687.    /* default values */
  688.    para[ARG_STDDELIMITERS] = (ULONG) " \t\n,<>=(){}\":.;*|!";
  689.  
  690.    eargs.erda_Template      = template;
  691.    eargs.erda_Parameter     = para;
  692.    eargs.erda_FileParameter = ARG_FROM;
  693.  
  694.    if((err = ExtReadArgs(ac,av,&eargs)) == 0)
  695.    {
  696.       obj = "xref.library";
  697.       if(XRefBase = OpenLibrary(obj,0))
  698.       {
  699.          obj = prgname;
  700.          if(gd = AllocVec(sizeof(struct GlobalData),MEMF_CLEAR))
  701.          {
  702.             BYTE oldpri;
  703.  
  704.             if(para[ARG_TOOLPRI])
  705.                oldpri = SetTaskPri(FindTask(NULL),(BYTE) *((ULONG *) para[ARG_TOOLPRI]));
  706.  
  707.             if((gd->gd_Pool = LibCreatePool(MEMF_ANY | MEMF_CLEAR,PUDDLE_SIZE,THRESH_SIZE)))
  708.             {
  709.                BPTR dir;
  710.  
  711.                /* duplicate start directory */
  712.                dir = CurrentDir(NULL);
  713.                gd->gd_StartDir = DupLock(dir);
  714.                CurrentDir(dir);
  715.  
  716.                NewList(&gd->gd_KeywordList);
  717.                NewList(&gd->gd_ExceptionList);
  718.  
  719.                gd->gd_Para = para;
  720.  
  721.                if(para[ARG_INDENT])
  722.                   para[ARG_INDENT] = *((LONG *) para[ARG_INDENT]);
  723.                else
  724.                   para[ARG_INDENT] = 4;
  725.  
  726.                gd->gd_Hook.h_Entry    = (HOOKFUNC) converthook;
  727.                gd->gd_Hook.h_Data     = &gd->gd_Convert;
  728.  
  729.                gd->gd_Tags[0].ti_Tag  = XREFA_Matching;
  730.                gd->gd_Tags[0].ti_Data = XREFMATCH_COMPARE_NUM_CASE;
  731.                gd->gd_Tags[1].ti_Tag  = XREFA_Limit;
  732.                gd->gd_Tags[1].ti_Data = 1;
  733.                gd->gd_Tags[2].ti_Tag  = XREFA_XRefHook;
  734.                gd->gd_Tags[2].ti_Data = (ULONG) &gd->gd_Hook;
  735.                gd->gd_Tags[3].ti_Tag  = TAG_IGNORE;
  736.  
  737.                if(para[ARG_CATEGORY])
  738.                {
  739.                   ULONG length = strlen((STRPTR) para[ARG_CATEGORY]) << 1 + 3;
  740.  
  741.                   if((gd->gd_Tags[3].ti_Data = (ULONG) AllocPooled(gd->gd_Pool,length)))
  742.                      if(ParsePatternNoCase((STRPTR) para[ARG_CATEGORY],(STRPTR) gd->gd_Tags[3].ti_Data,length) >=0)
  743.                         gd->gd_Tags[3].ti_Tag  = XREFA_CategoryParsed;
  744.  
  745.                   if(gd->gd_Tags[3].ti_Tag == XREFA_Category)
  746.                      gd->gd_Tags[3].ti_Data = para[ARG_CATEGORY];
  747.                }
  748.  
  749.                gd->gd_Tags[4].ti_Tag  = TAG_IGNORE;
  750.                gd->gd_Tags[5].ti_Tag  = TAG_IGNORE;
  751.                gd->gd_Tags[6].ti_Tag  = XREFA_AutoLoad;
  752.                gd->gd_Tags[6].ti_Data = FALSE;
  753.                gd->gd_Tags[7].ti_Tag  = TAG_END;
  754.  
  755.  
  756.                gd->gd_ExcTypes[0] = ~0;
  757.                gd->gd_IncTypes[0] = ~0;
  758.                
  759.                if(para[ARG_EXCLUDETYPES])
  760.                {
  761.                   parse_typestring((STRPTR) para[ARG_EXCLUDETYPES],gd->gd_ExcTypes);
  762.                   gd->gd_Tags[4].ti_Tag  = XREFA_RejectTypes;
  763.                   gd->gd_Tags[4].ti_Data = (ULONG) gd->gd_ExcTypes;
  764.                }
  765.  
  766.                if(para[ARG_INCLUDETYPES])
  767.                {
  768.                   parse_typestring((STRPTR) para[ARG_INCLUDETYPES],gd->gd_IncTypes);
  769.                   gd->gd_Tags[5].ti_Tag  = XREFA_AcceptTypes;
  770.                   gd->gd_Tags[5].ti_Data = (ULONG) gd->gd_IncTypes;
  771.                }
  772.  
  773.                for(i = 0 ; i < MAX_VARRAY ; i++)
  774.                   gd->gd_VArray[i] = gd->gd_WordBuffer;
  775.  
  776.                /* set default autodoc keyword substitute */
  777.                strcpy(gd->gd_AutoDocIntro,"@{b}%s@{ub}");
  778.  
  779.                /* allocate a FileInfoBlock for global use */
  780.                if(gd->gd_Fib = AllocDosObject(DOS_FIB,NULL))
  781.                {
  782.                   struct Hook scanfile_hook = {NULL};
  783.                   struct List *list;
  784.                   struct Node *node;
  785.                   BPTR dir;
  786.                   ULONG xrefkey;
  787.  
  788.                   /* try to set the index array for all xreffiles */
  789.                   xrefkey = LockXRefBase(0);
  790.  
  791.                   if(GetXRefBaseAttrs(XREFBA_List,&list,TAG_DONE) == 1)
  792.                      for(node = list->lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  793.                      {
  794.                         DB(("try to set index for %s!\n",node->ln_Name));
  795.                         SetXRefFileAttrs((struct XRefFileNode *) node,XREFA_Index,TRUE,TAG_DONE);
  796.                      }
  797.  
  798.                   UnlockXRefBase(xrefkey);
  799.  
  800.                   DB(("try to get default keywords and exception words !\n"));
  801.  
  802.                   GetXRefConfigDir(gd->gd_TempBuffer,sizeof(gd->gd_TempBuffer));
  803.  
  804.                   DB(("configdir : %s\n",gd->gd_TempBuffer));
  805.  
  806.                   if((dir = Lock(gd->gd_TempBuffer,SHARED_LOCK)))
  807.                   {
  808.                      BPTR old;
  809.  
  810.                      old = CurrentDir(dir);
  811.                      /* load default keywords */
  812.                      getkeywords(gd,"keywords");
  813.                      if(gd->gd_Para[ARG_V40])
  814.                         getkeywords(gd,"keywords.v40");
  815.  
  816.                      getexceptionwords(gd,"exceptions");
  817.  
  818.                      CurrentDir(old);
  819.                      UnLock(dir);
  820.                   }
  821.  
  822.                   DB(("try to load user defined keywords and exception words !\n"));
  823.  
  824.                   /* load user defined keywords */
  825.                   if(para[ARG_KEYWORDFILE])
  826.                      getkeywords(gd,(STRPTR) para[ARG_KEYWORDFILE]);
  827.                   else
  828.                   {
  829.                      /* try to load user defined keywords in the current dir */
  830.                      getkeywords(gd,"keywords");
  831.                      if(gd->gd_Para[ARG_V40])
  832.                         getkeywords(gd,"keywords.v40");
  833.                   }
  834.  
  835.                   /* load user defined exceptionfile */
  836.                   if(para[ARG_EXCEPTIONFILE])
  837.                      getexceptionwords(gd,(STRPTR) para[ARG_EXCEPTIONFILE]);
  838.                   else
  839.                      getexceptionwords(gd,"exceptions");
  840.  
  841.                   DB(("scan stat !\n"));
  842.  
  843.                   scanfile_hook.h_Entry = (HOOKFUNC) scan_file;
  844.  
  845.                   strcpy(gd->gd_Dest, (STRPTR) gd->gd_Para[ARG_TO]);
  846.  
  847.                   time_init(&gd->gd_TimeCalc,LINE_UPDATE);
  848.  
  849.                   if(ac == 0)
  850.                   {
  851.                      gd->gd_Workbench = TRUE;
  852.                      open_scanwindow(&gd->gd_SWin,(STRPTR *) displaytexts,prgname,400);
  853.                      draw_scanwindowstatus(&gd->gd_SWin,"reading filelist ...");
  854.                   }
  855.  
  856.                   /* get total filesize */
  857.                   getscanstat((STRPTR *) para[ARG_FROM],&gd->gd_SStat);
  858.  
  859.                   if(ac == 0)
  860.                      draw_scanwindowstatus(&gd->gd_SWin,"converting ...");
  861.  
  862.                   /* scan and convert all files */
  863.                   err = scan_patterns((STRPTR *) para[ARG_FROM],&scanfile_hook,gd);
  864.  
  865.                   time_calc(&gd->gd_TimeCalc,1,1);
  866.  
  867.                   gd->gd_Abort |= (err == ERROR_BREAK);
  868.  
  869.                   /* close all workbench stuff */
  870.                   close_scanwindow(&gd->gd_SWin,gd->gd_Abort);
  871.  
  872.                   if(!gd->gd_Workbench)
  873.                   {
  874.                      /* display whole statistic */
  875.                      if(para[ARG_STATISTIC])
  876.                      {
  877.                         ULONG i;
  878.  
  879.                         Printf ("\rGlobal Statistic for %ld Files , %ld Directories :\n",
  880.                                 gd->gd_SStat.ss_Files,gd->gd_SStat.ss_Directories);
  881.  
  882.                         for(i = 0 ; i < DISPLAY_TYPES ; i++)
  883.                         {
  884.                            Printf ("%-10s:%8ld ",xreftype_names[i],gd->gd_GlobalStat.Number[i]);
  885.                            if((i % 4) == 3 || i == (DISPLAY_TYPES - 1))
  886.                               PutStr("\n");
  887.                         }
  888.                      }
  889.  
  890.                      Printf ("\rFiles scanned %ld , converted %ld , Time used : %02ld:%02ld%-30s\n",
  891.                              gd->gd_SStat.ss_ActFiles, gd->gd_ConvertedFiles,
  892.                              gd->gd_TimeCalc.tc_Secs[TIME_USED] / 60,
  893.                              gd->gd_TimeCalc.tc_Secs[TIME_USED] % 60,
  894.                              "");
  895.                   }
  896.  
  897.                   FreeDosObject(DOS_FIB,gd->gd_Fib);
  898.                } else
  899.                   err = ERROR_NO_FREE_STORE;
  900.  
  901.                UnLock(gd->gd_StartDir);
  902.  
  903.                DeletePool(gd->gd_Pool);
  904.             }
  905.  
  906.             if(para[ARG_TOOLPRI])
  907.                SetTaskPri(FindTask(NULL),oldpri);
  908.  
  909.             if(gd->gd_Abort)
  910.             {
  911.                err = ERROR_BREAK;
  912.                obj = prgname;
  913.                retval = RETURN_FAIL;
  914.             }
  915.  
  916.             FreeVec(gd);
  917.          }
  918.          CloseLibrary(XRefBase);
  919.       }
  920.    }
  921.    ExtFreeArgs(&eargs);
  922.  
  923.    if(!err)
  924.       err = IoErr();
  925.  
  926.    if(err)
  927.    {
  928.       if(ac == 0)
  929.          showerror(prgname,obj,err);
  930.       else
  931.          PrintFault(err,obj);
  932.  
  933.       if(retval == RETURN_OK)
  934.          retval = RETURN_ERROR;
  935.    }
  936.  
  937.    return(retval);
  938. }
  939. /*FE*/
  940.  
  941. /* ---------------- get the keywords from the config file ----------------- */
  942.  
  943. /*FS*//*"void getkeywords(struct GlobalData *gd,STRPTR file)"*/
  944. void getkeywords(struct GlobalData *gd,STRPTR file)
  945. {
  946.    struct RDArgs *rdargs;
  947.    struct RDArgs *args;
  948.  
  949.    BPTR fh;
  950.  
  951.    if(fh = Open(file,MODE_OLDFILE))
  952.    {
  953.       DB(("def file %s opened\n",file));
  954.  
  955.       while(FGets(fh,gd->gd_TempBuffer,sizeof(gd->gd_TempBuffer) - 1))
  956.       {
  957.          ULONG para[ARG_KEYWORDMAX];
  958.          LONG i;
  959.  
  960.          DB(("line : %s",gd->gd_TempBuffer));
  961.  
  962.          if(rdargs = (struct RDArgs *) AllocDosObject(DOS_RDARGS,NULL))
  963.          {
  964.             rdargs->RDA_Source.CS_Buffer   = gd->gd_TempBuffer;
  965.             rdargs->RDA_Source.CS_Length   = strlen(gd->gd_TempBuffer);
  966.  
  967.             for(i=0 ; i < (sizeof(para)/sizeof(LONG)) ; i++)
  968.                para[i]=0;
  969.  
  970.             DB(("rdargs at : %lx\n",rdargs));
  971.             
  972.             if(args = ReadArgs(keywordtemplate,(LONG *) para,rdargs))
  973.             {
  974.                DB(("args at %lx\n",args));
  975.  
  976.                if(!Stricmp((STRPTR) para[ARG_KEYWORD],"AUTODOC"))
  977.                {
  978.                   strcpy(gd->gd_AutoDocIntro,(STRPTR) para[ARG_SUBSTITUTE]);
  979.                } else
  980.                {
  981.                   struct KeyWord *kwnode;
  982.                   LONG arglen = 1;
  983.  
  984.                   if(para[ARG_DELIMITERS])
  985.                      arglen += strlen((STRPTR) para[ARG_DELIMITERS]);
  986.  
  987.                   if(kwnode = LibAllocPooled(gd->gd_Pool,
  988.                                              sizeof(struct KeyWord) + arglen +
  989.                                              strlen((STRPTR) para[ARG_KEYWORD])    + 1 +
  990.                                              strlen((STRPTR) para[ARG_SUBSTITUTE]) + 1  ))
  991.                   {
  992.                      STRPTR ptr;
  993.                      LONG i;
  994.  
  995.                      kwnode->kw_Keyword = (STRPTR) (kwnode + 1);
  996.                      strcpy(kwnode->kw_Keyword,(STRPTR) para[ARG_KEYWORD]);
  997.                      kwnode->kw_Node.ln_Name = kwnode->kw_Keyword;
  998.  
  999.                      kwnode->kw_Substitute = kwnode->kw_Keyword + strlen(kwnode->kw_Keyword) + 1;
  1000.                      strcpy(kwnode->kw_Substitute,(STRPTR) para[ARG_SUBSTITUTE]);
  1001.  
  1002.                      if(para[ARG_DELIMITERS])
  1003.                      {
  1004.                         kwnode->kw_Delimiters = kwnode->kw_Substitute + strlen(kwnode->kw_Substitute) + 1;
  1005.                         strcpy(kwnode->kw_Delimiters,(STRPTR) para[ARG_DELIMITERS]);
  1006.                      }
  1007.  
  1008.                      kwnode->kw_NextWord = (BOOL) para[ARG_NEXTWORD];
  1009.  
  1010.                      for(ptr = kwnode->kw_Substitute , i = 0 ; *ptr ; ptr++)
  1011.                         if(*ptr == '%' && ptr[1] == 's')
  1012.                            ptr++;
  1013.  
  1014.                      insertbyname(&gd->gd_KeywordList,(struct Node *) kwnode);
  1015.  
  1016.                      if(i > MAX_VARRAY - 1)
  1017.                         Printf ("warning: keyword %s, has more than %ld '%%s'",kwnode->kw_Keyword,
  1018.                                                                                MAX_VARRAY);
  1019.                   }
  1020.                }
  1021.                FreeArgs(args);
  1022.             }
  1023.             FreeDosObject(DOS_RDARGS , rdargs);
  1024.          }
  1025.       }
  1026.       Close(fh);
  1027.    }
  1028. }
  1029. /*FE*/
  1030.  
  1031. /* ------------- get the exception words from the config fle -------------- */
  1032.  
  1033. /*FS*//*"void getexceptionwords(struct GlobalData *gd,STRPTR file)"*/
  1034. void getexceptionwords(struct GlobalData *gd,STRPTR file)
  1035. {
  1036.    BPTR fh;
  1037.  
  1038.    if(fh = Open(file,MODE_OLDFILE))
  1039.    {
  1040.       DB(("def file %s opened\n",gd->gd_Para[ARG_EXCEPTIONFILE]));
  1041.       if(ExamineFH(fh,gd->gd_Fib))
  1042.       {
  1043.          struct Exceptions *except;
  1044.  
  1045.          if((except = LibAllocPooled(gd->gd_Pool,sizeof(struct Exceptions) + gd->gd_Fib->fib_Size)))
  1046.          {
  1047.             except->e_Node.ln_Name = (STRPTR) (except + 1);
  1048.             except->e_Length       = gd->gd_Fib->fib_Size;
  1049.  
  1050.             if(Read(fh,except->e_Node.ln_Name,except->e_Length) == except->e_Length)
  1051.             {
  1052.                STRPTR ptr = except->e_Node.ln_Name;
  1053.                STRPTR end = except->e_Node.ln_Name + except->e_Length;
  1054.  
  1055.                while(ptr < end)
  1056.                {
  1057.                   if(*ptr == '\n')
  1058.                      *ptr = EOS;
  1059.                   ptr++;
  1060.                }
  1061.                AddTail(&gd->gd_ExceptionList,&except->e_Node);
  1062.             } else
  1063.                LibFreePooled(gd->gd_Pool,except,sizeof(struct Exceptions) + gd->gd_Fib->fib_Size);
  1064.          }
  1065.       }
  1066.       Close(fh);
  1067.    }
  1068. }
  1069. /*FE*/
  1070.  
  1071. /* ------------------------- parse types strings -------------------------- */
  1072.  
  1073. /*FS*/ /*"void parse_typestring(STRPTR typestr,ULONG *typearray) "*/
  1074. void parse_typestring(STRPTR typestr,ULONG *typearray)
  1075. {
  1076.    STRPTR end = typestr;
  1077.    STRPTR ptr = typestr;
  1078.    ULONG types = 0;
  1079.    ULONG i;
  1080.  
  1081.    /* convert separator to EOS */
  1082.    while(*end != EOS)
  1083.    {
  1084.       if(*end == '|')
  1085.          *end = EOS;
  1086.       end++;
  1087.    }
  1088.  
  1089.    while(ptr < end)
  1090.    {
  1091.       for(i = 0 ; i < XREFT_MAXTYPES ; i++)
  1092.          if(!Stricmp(ptr,xreftype_names[i]))
  1093.          {
  1094.             DB(("type : %s found -> %ld\n",ptr,i));
  1095.             typearray[types] = i;
  1096.             types++;
  1097.             break;
  1098.          }
  1099.  
  1100.       ptr += strlen(ptr) + 1;
  1101.    }
  1102.  
  1103.    DB(("types : %ld\n",types));
  1104.  
  1105.    typearray[types] = ~0;
  1106. }
  1107. /*FE*/
  1108.  
  1109. /* ----------------- scan the file and determine the type ----------------- */
  1110.  
  1111. /*FS*/ /*"LONG scan_file(struct Hook *hook,struct GlobalData *gd,struct spMsg *msg)"*/
  1112. RegCall LONG scan_file(REGA0 struct Hook *hook,REGA2 struct GlobalData *gd,REGA1 struct spMsg *msg)
  1113. {
  1114.    STRPTR path  = msg->Path;
  1115.    STRPTR gpath = msg->RealPath;
  1116.    ULONG filetype;
  1117.    LONG retval = 0;
  1118.  
  1119.    DB(("Msg   : %ld\n",msg->Msg));
  1120.    DB(("path  : %s\n",msg->Path));
  1121.    DB(("gpath : %s\n",msg->RealPath));
  1122.  
  1123.    switch(msg->Msg)
  1124.    {
  1125.    case SPM_DIR:
  1126.       {
  1127.          BPTR olddir;
  1128.  
  1129.          olddir = CurrentDir(gd->gd_StartDir);
  1130.  
  1131.          /* create destination directory */
  1132.          strcpy(gd->gd_Dest, (STRPTR) gd->gd_Para[ARG_TO]);
  1133.          if(AddPart(gd->gd_Dest,path,sizeof(gd->gd_Dest)))
  1134.          {
  1135.             ULONG len = strlen(gd->gd_Dest);
  1136.             BPTR lock;
  1137.  
  1138.             if(gd->gd_Dest[len-1] == '/')
  1139.                gd->gd_Dest[len-1] = EOS;
  1140.  
  1141.             DB(("try to create : %s\n",gd->gd_Dest));
  1142.             if(!(lock = Lock(gd->gd_Dest,SHARED_LOCK)))
  1143.                lock = CreateDir(gd->gd_Dest);
  1144.  
  1145.             UnLock(lock);
  1146.             DB(("%s created : %lx\n",gd->gd_Dest,lock));
  1147.          }
  1148.  
  1149.          /* update status window */
  1150.          gd->gd_SStat.ss_ActDirectories++;
  1151.  
  1152.          if(gd->gd_Workbench)
  1153.          {
  1154.             sprintf(gd->gd_TempBuffer,"(%3ld/%3ld)",gd->gd_SStat.ss_ActDirectories,gd->gd_SStat.ss_Directories);
  1155.             draw_scanwindowtext(&gd->gd_SWin,NUM_DIRS,gd->gd_TempBuffer);
  1156.  
  1157.          } else if(gd->gd_Para[ARG_VERBOSE])
  1158.             Printf ("\rScanning dir (%3ld/%3ld) : %-40s\n",
  1159.                      gd->gd_SStat.ss_ActDirectories,
  1160.                      gd->gd_SStat.ss_Directories,
  1161.                      gpath);
  1162.  
  1163.          CurrentDir(olddir);
  1164.       }
  1165.       break;
  1166.    case SPM_FILE:
  1167.       gd->gd_SStat.ss_ActFiles++;
  1168.  
  1169.       if(gd->gd_Workbench)
  1170.       {
  1171.          sprintf(gd->gd_TempBuffer,"(%3ld/%3ld)",gd->gd_SStat.ss_ActFiles,gd->gd_SStat.ss_Files);
  1172.          draw_scanwindowtext(&gd->gd_SWin,NUM_FILES    ,gd->gd_TempBuffer);
  1173.       } else if(gd->gd_Para[ARG_VERBOSE])
  1174.          Printf ("\rConverting file (%3ld/%3ld) : %s ",
  1175.                  gd->gd_SStat.ss_ActFiles,
  1176.                  gd->gd_SStat.ss_Files,
  1177.                  path);
  1178.  
  1179.       DB(("scanfile : %s\n",path));
  1180.  
  1181.       if((filetype = getfiletype(msg->FHandle,msg->RealPath)) != FTYPE_UNKNOWN)
  1182.       {
  1183.          gd->gd_ReadFH = msg->FHandle;
  1184.  
  1185.          strcpy(gd->gd_Dest, (STRPTR) gd->gd_Para[ARG_TO]);
  1186.          if(AddPart(gd->gd_Dest,path,sizeof(gd->gd_Dest)))
  1187.          {  
  1188.             convertsuffix(filetype,gd->gd_Dest);
  1189.  
  1190.             DB(("to : \"%s\"\n",gd->gd_Dest));
  1191.  
  1192.             if(gd->gd_Workbench)
  1193.             {
  1194.                /* output the current destination file */
  1195.                sprintf(gd->gd_TempBuffer,"%s (%s)",gpath,ftype[filetype]);
  1196.                draw_scanwindowtext(&gd->gd_SWin,NUM_SOURCE   ,gd->gd_TempBuffer);
  1197.                draw_scanwindowtext(&gd->gd_SWin,NUM_DEST     ,gd->gd_Dest);
  1198.  
  1199.                draw_gauge(&gd->gd_SWin.sw_Actual,0,0);
  1200.             } else if(gd->gd_Para[ARG_VERBOSE])
  1201.                Printf ("(%s)%-30s\n",ftype[filetype],"");
  1202.  
  1203.             if((gd->gd_InternPool = LibCreatePool(MEMF_ANY | MEMF_CLEAR,PUDDLE_SIZE,THRESH_SIZE)))
  1204.             {
  1205.                BOOL noamigaguide;
  1206.                BPTR olddir;
  1207.  
  1208.                /* init new intern xref list */
  1209.                NewList(&gd->gd_InternXRef);
  1210.  
  1211.                gd->gd_FullPath = gpath;
  1212.                gd->gd_FileName = path;
  1213.                gd->gd_FileSize = msg->Fib->fib_Size;
  1214.                gd->gd_FileType = filetype;
  1215.  
  1216.                noamigaguide = gd->gd_Para[ARG_NOAMIGAGUIDE];
  1217.  
  1218.                /* change to start directory to support relative directories */
  1219.                olddir = CurrentDir(gd->gd_StartDir);
  1220.  
  1221.                if((gd->gd_WriteFH = Open(gd->gd_Dest,MODE_NEWFILE)))
  1222.                {
  1223.                   DB(("file %s opened !\n",gd->gd_Dest));
  1224.                   write_guide_header(gd);
  1225.  
  1226.                   /* convert the suffix for filename checking (write_link()) */
  1227.                   convertsuffix(filetype,path);
  1228.  
  1229.                   switch(filetype)
  1230.                   {
  1231.                   case FTYPE_DOC:
  1232.                      scan_doc(gd);              /* convert a normal doc file */
  1233.                      break;
  1234.                   case FTYPE_AUTODOC:
  1235.                      scan_autodoc(gd);          /* convert an autodoc file */
  1236.                      break;
  1237.                   case FTYPE_HEADER:
  1238.                      scan_header(gd);           /* convert a C header file */
  1239.                      break;
  1240.                   case FTYPE_AMIGAGUIDE:
  1241.                      scan_amigaguide(gd);       /* convert a existing amigaguide file */
  1242.                      break;
  1243.                   case FTYPE_MAN:
  1244.                      scan_man(gd);              /* convert a unix manual page file */
  1245.                      break;
  1246.                   case FTYPE_INFO:
  1247.                      scan_info(gd);             /* convert a GNU infoview file */
  1248.                      break;
  1249.                   }
  1250.  
  1251.                   if(gd->gd_Workbench)
  1252.                      draw_gauge(&gd->gd_SWin.sw_Actual,1,1);
  1253.  
  1254.                   if(!gd->gd_Para[ARG_NOAMIGAGUIDE] && gd->gd_OpenNodes)
  1255.                      FPuts(gd->gd_WriteFH,endnode);
  1256.  
  1257.                   gd->gd_ConvertedFiles++;
  1258.  
  1259.                   Close(gd->gd_WriteFH);
  1260.                }
  1261.  
  1262.                /* if the user has abort , just delete the destination */
  1263.                if(gd->gd_Abort)           
  1264.                   DeleteFile(gd->gd_Dest);
  1265.                else if(!gd->gd_Para[ARG_NOICON])
  1266.                   saveicon(gd->gd_Dest,&icondef);
  1267.  
  1268.                CurrentDir(olddir);
  1269.  
  1270.                gd->gd_Para[ARG_NOAMIGAGUIDE] = noamigaguide;
  1271.  
  1272.                /* deletes all memory allocated by this pool (internal xrefs) */
  1273.                LibDeletePool(gd->gd_InternPool);
  1274.             } 
  1275.          }
  1276.  
  1277.          gd->gd_ReadFH = NULL;
  1278.       } else if(!gd->gd_Workbench && gd->gd_Para[ARG_VERBOSE])
  1279.          Printf ("(unknown)%-30s\n","");
  1280.  
  1281.       gd->gd_SStat.ss_ActTotalFileSize += msg->Fib->fib_Size;
  1282.       draw_state(gd);
  1283.       break;
  1284.    }
  1285.  
  1286.    if(check_abort(gd))
  1287.       return(ERROR_BREAK);
  1288.  
  1289.    return(retval);
  1290. }
  1291. /*FE*/
  1292.  
  1293. /* ----------- scan the determined file an write the amigaguide ----------- */
  1294.  
  1295. /*FS*//*"void scan_amigaguide(struct GlobalData *gd)"*/
  1296. void scan_amigaguide(struct GlobalData *gd)
  1297. {
  1298.    STRPTR delim = (STRPTR) gd->gd_Para[ARG_STDDELIMITERS];
  1299.    STRPTR ptr;
  1300.    STRPTR name;
  1301.    STRPTR link;
  1302.  
  1303.    gd->gd_Para[ARG_NOAMIGAGUIDE] = TRUE;
  1304.  
  1305.    while((ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer))) && !check_abort(gd))
  1306.    {
  1307.       if(!Strnicmp(ptr,"@node",5))
  1308.       {
  1309.          link = ptr + 5;
  1310.  
  1311.          getamigaguidenode(&link,&name);
  1312.  
  1313.          allocinternxref(gd,name,link);
  1314.       }
  1315.    }
  1316.  
  1317.    if(!gd->gd_Abort)
  1318.    {
  1319.       Seek(gd->gd_ReadFH,0,OFFSET_BEGINNING);
  1320.  
  1321.       while((gd->gd_Ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer))) && !check_abort(gd))
  1322.       {
  1323.          if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1324.             draw_state(gd);
  1325.  
  1326.          if(*gd->gd_Ptr == '@')
  1327.          {
  1328.             FPuts(gd->gd_WriteFH,gd->gd_Ptr);
  1329.  
  1330.             /* get actual node */
  1331.             if(!Strnicmp(gd->gd_Ptr,"@node",5))
  1332.             {
  1333.                link = gd->gd_Ptr + 5;
  1334.                getamigaguidenode(&link,&name);
  1335.                strcpy(gd->gd_NameBuffer,name);
  1336.             }
  1337.             continue;
  1338.          }
  1339.  
  1340.          while(getword(gd,delim))
  1341.          {
  1342.             /* don't link words, which are in the exception list */
  1343.             if(check_exception(gd))
  1344.                continue;
  1345.  
  1346.             if(!check_internxref(gd))      /* check intern xref for an amigaguide (all @node's) */
  1347.                if(!check_keyword(gd))
  1348.                   check_reference(gd);
  1349.          }
  1350.       }
  1351.    }
  1352. }
  1353. /*FE*/
  1354. /*FS*//*"void scan_header(struct GlobalData *gd)"*/
  1355. void scan_header(struct GlobalData *gd)
  1356. {
  1357.    STRPTR delim = (STRPTR) gd->gd_Para[ARG_STDDELIMITERS];
  1358.    STRPTR ptr;
  1359.  
  1360.    while((gd->gd_Ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer))) && !check_abort(gd))
  1361.    {
  1362.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1363.          draw_state(gd);
  1364.  
  1365.       while(ptr = getword(gd,delim))
  1366.       {
  1367.          /* don't link words, which are in the exception list */
  1368.          if(check_exception(gd))
  1369.             continue;
  1370.  
  1371.          if(!check_keyword(gd))
  1372.             check_reference(gd);
  1373.       }
  1374.    }
  1375. }
  1376. /*FE*/
  1377. /*FS*//*"void scan_autodoc(struct GlobalData *gd)"*/
  1378. void scan_autodoc(struct GlobalData *gd)
  1379. {
  1380.    BPTR wfh = gd->gd_WriteFH;
  1381.  
  1382.    STRPTR wordbuf = gd->gd_WordBuffer;
  1383.    STRPTR delim   = (STRPTR) gd->gd_Para[ARG_STDDELIMITERS];
  1384.    STRPTR ptr;
  1385.  
  1386.    LONG table_of_contents = 0;
  1387.  
  1388.    STRPTR tmpptr;
  1389.    UWORD columns = 2;
  1390.    UWORD actcol  = 0;
  1391.    UWORD linelen = 80;
  1392.    UWORD tabwidth= 40;
  1393.  
  1394.    DB(("dest file : %s\n",gd->gd_Dest));
  1395.    
  1396.    /* try to get the defaults from the library */
  1397.    if(GetXRefBaseAttrs(XREFBA_Columns     ,&columns,
  1398.                        XREFBA_LineLength  ,&linelen,TAG_DONE) == 2)
  1399.    {
  1400.  
  1401.       tabwidth = linelen / columns;
  1402.    }
  1403.  
  1404.    /* amigaguide.datatype prior V40 cannot handle settabs command */
  1405.    if(SysBase->lib_Version < 40)
  1406.       columns = 1;
  1407.  
  1408.    /* set the tabs */
  1409.    if(columns > 1)
  1410.    {
  1411.       ULONG i;
  1412.       ULONG tabs = tabwidth;
  1413.  
  1414.       if(gd->gd_Para[ARG_V40])
  1415.          FPuts(wfh,"@smartwrap\n");
  1416.  
  1417.       FPuts(wfh,"@{settabs");
  1418.       for(i = columns ; i > 1 ; i--)
  1419.       {
  1420.          FPrintf(wfh," %2ld",tabs);
  1421.          tabs += tabwidth;
  1422.       }
  1423.       FPuts(wfh,"}");
  1424.    }
  1425.  
  1426.    gd->gd_SmartWrapped = TRUE;
  1427.  
  1428.    while((ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer))) && !check_abort(gd))
  1429.    {
  1430.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1431.          draw_state(gd);
  1432.  
  1433.       gd->gd_Ptr = ptr;
  1434.  
  1435.       if(gd->gd_Para[ARG_V40])
  1436.       {
  1437.          /* if an empty line is found with the V40 option save to linefeed's */
  1438.          tmpptr = ptr;
  1439.          while(*tmpptr == ' ' || *tmpptr == '\t')
  1440.             tmpptr++;
  1441.  
  1442.          if(*tmpptr == '\n')
  1443.          {
  1444.             FPuts(gd->gd_WriteFH,"\n");
  1445.             continue;
  1446.          }
  1447.       }
  1448.  
  1449.       if(table_of_contents == 0)
  1450.       {
  1451.          if(!strncmp(ptr,toc,strlen(toc)))
  1452.             table_of_contents++;
  1453.          continue;
  1454.       } else if(table_of_contents == 1)
  1455.       {
  1456.          if(*ptr != '\f')
  1457.          {
  1458.             if(*ptr == '\n')
  1459.                continue;
  1460.  
  1461.             if(getword(gd," \n") && *wordbuf != EOS)
  1462.             {
  1463.                STRPTR addparent = NULL;
  1464.                STRPTR entryname = FilePart(wordbuf);
  1465.  
  1466.                if(checkentrytype(entryname) == XREFT_FUNCTION)
  1467.                   addparent = "()";
  1468.  
  1469.                FPrintf(wfh,"@{\" %s%s \" link \"%s%s\"}",entryname,addparent,
  1470.                                                          entryname,addparent);
  1471.  
  1472.                FPutC(wfh,'\t');
  1473.                if(++actcol == columns)
  1474.                {
  1475.                   actcol = 0;
  1476.                   FPutC(wfh,'\n');
  1477.                }
  1478.  
  1479.                sprintf(gd->gd_WordBuffer,"%s%s",entryname,addparent);
  1480.             }
  1481.             continue;
  1482.          } else
  1483.          {
  1484.             table_of_contents++;
  1485.             FPutC(wfh,'\n');
  1486.          }
  1487.       }
  1488.  
  1489.  
  1490.       /* the end of an autodoc entry detected by a formfeed */
  1491.       if(*ptr == '\f')
  1492.       {
  1493.          DB(("formfeed detected\n"));
  1494.          gd->gd_OpenNodes--;
  1495.  
  1496.          if(!gd->gd_Para[ARG_NOAMIGAGUIDE])
  1497.             FPuts(wfh,endnode);
  1498.  
  1499.          ptr++;
  1500.  
  1501.          while(*ptr == ' ' || *ptr == '\t')
  1502.             ptr++;
  1503.  
  1504.          while(ptr && *ptr == '\n')
  1505.             ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer));
  1506.  
  1507.          /* just the end of the file, thus terminate the loop */
  1508.          if(!ptr)
  1509.             break;
  1510.  
  1511.          gd->gd_Ptr = ptr;
  1512.  
  1513.          if(getword(gd," \t\n") && *wordbuf != EOS)
  1514.          {
  1515.             STRPTR addparent = NULL;
  1516.             STRPTR wordptr   = wordbuf;
  1517.  
  1518.             if(strlen(wordptr) > 40)
  1519.                wordptr += (strlen(wordbuf) >> 1);
  1520.  
  1521.             if(checkentrytype(FilePart(wordptr)) == XREFT_FUNCTION && 
  1522.                strcmp(&wordbuf[strlen(wordbuf)-2],"()"))
  1523.                addparent = "()";
  1524.  
  1525.             FPrintf(wfh,"@node \"%s%s\" \"%s%s\"\n",FilePart(wordptr),addparent,
  1526.                                                     wordptr,addparent);
  1527.  
  1528.             sprintf(gd->gd_NameBuffer,"%s%s\0",FilePart(wordptr),addparent);
  1529.  
  1530.             DB(("nodename %s\n",gd->gd_NameBuffer));
  1531.  
  1532.             gd->gd_SmartWrapped = TRUE;
  1533.             gd->gd_OpenNodes++;
  1534.             continue;
  1535.          }
  1536.       }
  1537.  
  1538.       gd->gd_Ptr = ptr;
  1539.  
  1540.       if(check_autodocintro(gd,ptr))
  1541.          continue;
  1542.  
  1543.       gd->gd_LineBegin = TRUE;
  1544.  
  1545.       /* get the next WORD according to the delimiters */
  1546.       while(getword(gd,delim))
  1547.       {
  1548.          /* don't link words, which are in the exception list */
  1549.          if(check_exception(gd))
  1550.             continue;
  1551.  
  1552.          if(!check_keyword(gd))      /* check for any given keyword */
  1553.             check_reference(gd);     /* check for any other reference */
  1554.       }
  1555.    }
  1556. }
  1557. /*FE*/
  1558. /*FS*//*"void scan_doc(struct GlobalData *gd)"*/
  1559. void scan_doc(struct GlobalData *gd)
  1560. {
  1561.    STRPTR delim = (STRPTR) gd->gd_Para[ARG_STDDELIMITERS];
  1562.  
  1563.    UBYTE pagebuf[20];
  1564.    LONG pages = 1;
  1565.  
  1566.    strcpy(gd->gd_NameBuffer,FilePart(gd->gd_Dest));
  1567.    gd->gd_NameBuffer[strlen(gd->gd_NameBuffer) - 6] = EOS;
  1568.  
  1569.    while((gd->gd_Ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer))) && !check_abort(gd))
  1570.    {
  1571.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1572.          draw_state(gd);
  1573.  
  1574.       if(*gd->gd_Ptr == '\f')
  1575.       {
  1576.          STRPTR ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer));
  1577.          STRPTR node;
  1578.          STRPTR name;
  1579.  
  1580.          if(ptr)
  1581.          {
  1582.             while(*ptr == ' ' || *ptr == '\t')
  1583.                ptr++;
  1584.  
  1585.             node = ptr;
  1586.             name = ptr;
  1587.  
  1588.             while(*ptr != EOS)
  1589.             {
  1590.                if(*ptr == ':')
  1591.                {
  1592.                   *ptr = '-';
  1593.                   name = ptr + 1;
  1594.                } else if(*ptr == '\n')
  1595.                   *ptr = EOS;
  1596.  
  1597.                ptr++;
  1598.             }
  1599.  
  1600.             while(*name == ' ' || *name == '\t')
  1601.                name++;
  1602.  
  1603.             ptr[strlen(ptr) - 1] = EOS;
  1604.  
  1605.             if(*node == EOS)
  1606.             {
  1607.                node = pagebuf;
  1608.                sprintf(pagebuf,"Page %ld",++pages);
  1609.             }
  1610.  
  1611.             if(*name == EOS)
  1612.                name = node;
  1613.  
  1614.             if(!gd->gd_Para[ARG_NOAMIGAGUIDE])
  1615.                FPrintf(gd->gd_WriteFH,"@endnode\n"
  1616.                                       "@node \"%s\" \"%s\"\n",node,name);
  1617.          }
  1618.          continue;
  1619.       }
  1620.  
  1621.       if(check_autodocintro(gd,gd->gd_Ptr))
  1622.          continue;
  1623.  
  1624.       while(getword(gd,delim))
  1625.       {
  1626.          /* don't link words, which are in the exception list */
  1627.          if(check_exception(gd))
  1628.             continue;
  1629.          
  1630.          if(!check_keyword(gd))
  1631.             check_reference(gd);
  1632.       }
  1633.    }
  1634. }
  1635. /*FE*/
  1636. /*FS*/ /*"void scan_man(struct GlobalData *gd) "*/
  1637. void scan_man(struct GlobalData *gd)
  1638. {
  1639.    STRPTR delim = (STRPTR) gd->gd_Para[ARG_STDDELIMITERS];
  1640.  
  1641.    strcpy(gd->gd_NameBuffer,"main");
  1642.  
  1643.    while((gd->gd_Ptr = FGets(gd->gd_ReadFH,gd->gd_LineBuffer,sizeof(gd->gd_LineBuffer))) && !check_abort(gd))
  1644.    {
  1645.       if(!(++gd->gd_Line % gd->gd_TimeCalc.tc_Update))
  1646.          draw_state(gd);
  1647.  
  1648.       if(check_autodocintro(gd,gd->gd_TempBuffer))
  1649.          continue;
  1650.  
  1651.       while(getword(gd,delim))
  1652.       {
  1653.          /* don't link words, which are in the exception list */
  1654.          if(check_exception(gd))
  1655.             continue;
  1656.          
  1657.          if(!check_keyword(gd))
  1658.             check_reference(gd);
  1659.       }
  1660.    }
  1661. }
  1662. /*FE*/
  1663. /*FS*/ /*"void scan_info(struct GlobalData *gd) "*/
  1664. void scan_info(struct GlobalData *gd)
  1665. {
  1666. }
  1667. /*FE*/
  1668.  
  1669. /*FS*/ /*"BOOL check_exception(struct GlobalData *gd) "*/
  1670. BOOL check_exception(struct GlobalData *gd)
  1671. {
  1672.    struct Exceptions *except;
  1673.    STRPTR ptr;
  1674.    STRPTR end;
  1675.  
  1676.    for(except = (struct Exceptions *) gd->gd_ExceptionList.lh_Head ;
  1677.        except->e_Node.ln_Succ ;
  1678.        except = (struct Exceptions *) except->e_Node.ln_Succ)
  1679.    {
  1680.       ptr = except->e_Node.ln_Name;
  1681.       end = except->e_Node.ln_Name + except->e_Length;
  1682.  
  1683.       /* check if this is a exception word */
  1684.       while(ptr < end && strcmp(ptr,gd->gd_WordBuffer))
  1685.          ptr += (strlen(ptr) + 1);
  1686.  
  1687.       if(ptr < end && !gd->gd_SeeAlso)
  1688.       {
  1689.          write_word(gd);
  1690.          return(TRUE);
  1691.       }
  1692.    }
  1693.  
  1694.    return(FALSE);
  1695. }
  1696. /*FE*/
  1697. /*FS*//*"BOOL check_autodocintro(struct GlobalData *gd,STRPTR line)"*/
  1698. BOOL check_autodocintro(struct GlobalData *gd,STRPTR line)
  1699. {
  1700.    STRPTR tmpptr = line;
  1701.    STRPTR name;
  1702.  
  1703.    BPTR wfh = gd->gd_WriteFH;
  1704.    LONG i = 0;
  1705.  
  1706.    if(!tmpptr)
  1707.       return(FALSE);
  1708.  
  1709.    while(*tmpptr++ == ' ')
  1710.       i++;
  1711.  
  1712.    name = tmpptr - 1;
  1713.  
  1714.    while(*tmpptr != '\n' && (*tmpptr == ' ' || isupper(*tmpptr)))
  1715.       tmpptr++;
  1716.  
  1717.    if(*tmpptr == '\n' && ((i >= (LONG) (gd->gd_Para[ARG_INDENT] - 2)) &&
  1718.                           (i <= (LONG) (gd->gd_Para[ARG_INDENT] + 2))))
  1719.    {
  1720.       *tmpptr = EOS;
  1721.       DB(("autodoc intro statement found\n",name));
  1722.  
  1723.       if(gd->gd_Para[ARG_V40])
  1724.       {
  1725.          strcpy(gd->gd_WordBuffer,name);
  1726.          /* if the last paragraph wasn't smartwrapped -> overwrite last newline */
  1727.          if(!gd->gd_SmartWrapped)
  1728.          {
  1729.             Flush(gd->gd_WriteFH);
  1730.             Seek(gd->gd_WriteFH,-1,OFFSET_CURRENT);
  1731.          }
  1732.  
  1733.          gd->gd_SmartWrapped = check_keyword(gd);
  1734.       } else
  1735.       {
  1736.          gd->gd_SmartWrapped = FALSE;
  1737.          for(i = gd->gd_Para[ARG_INDENT] ; i ; i--)
  1738.             FPutC(wfh,' ');
  1739.       }
  1740.  
  1741.       if(!gd->gd_SmartWrapped)
  1742.          FPrintf(wfh,gd->gd_AutoDocIntro,name);
  1743.  
  1744.       FPutC(wfh,'\n');
  1745.  
  1746.       draw_keyword(gd);
  1747.  
  1748.       /* see also block follow's , so don't use the exception words */
  1749.       if(!strcmp(name,"SEE ALSO"))
  1750.          gd->gd_SeeAlso = TRUE;
  1751.       else
  1752.          gd->gd_SeeAlso = FALSE;
  1753.  
  1754.       return(TRUE);
  1755.    }
  1756.  
  1757.    return(FALSE);
  1758. }
  1759. /*FE*/
  1760. /*FS*//*"BOOL check_keyword(struct GlobalData *gd)"*/
  1761. BOOL check_keyword(struct GlobalData *gd)
  1762. {
  1763.    struct KeyWord *keyword;
  1764.  
  1765.    BPTR wfh = gd->gd_WriteFH;
  1766.  
  1767.    STRPTR wordbuf = gd->gd_WordBuffer;
  1768.    STRPTR ptr;
  1769.    WORD comp = 1;
  1770.  
  1771.    for(keyword = (struct KeyWord *) gd->gd_KeywordList.lh_Head ; keyword->kw_Node.ln_Succ ;
  1772.        keyword = (struct KeyWord *) keyword->kw_Node.ln_Succ)
  1773.    {
  1774.       if(!(comp = strcmp(keyword->kw_Keyword,wordbuf)))
  1775.       {
  1776.          BOOL link = FALSE;
  1777.          DB(("keyword : %s,%s\n",keyword->kw_Keyword,gd->gd_NameBuffer));
  1778.  
  1779.          /* don't substitute any words, which are in the node itself */
  1780.          if(!Strnicmp(wordbuf,gd->gd_NameBuffer,strlen(wordbuf)))
  1781.          {
  1782.             write_word(gd);
  1783.             break;
  1784.          }
  1785.  
  1786.          if(keyword->kw_NextWord)
  1787.          {
  1788.             STRPTR delim = (keyword->kw_Delimiters) ? keyword->kw_Delimiters :
  1789.                                                       (STRPTR) gd->gd_Para[ARG_STDDELIMITERS];
  1790.  
  1791.             DB(("delim : \"%s\"\n",delim));
  1792.             write_word(gd);
  1793.  
  1794.             if(ptr = getword(gd,delim))
  1795.             {
  1796.                /* handle struct keyword separatly to make a link (reference)
  1797.                ** or a display (definintion)
  1798.                */
  1799.  
  1800.                DB(("word : \"%s\"\n",wordbuf));
  1801.  
  1802.                if(!strcmp(keyword->kw_Keyword,"struct"))
  1803.                {
  1804.                   STRPTR tmpptr = ptr;
  1805.  
  1806.                   while(*tmpptr == ' ' || *tmpptr == '\t')
  1807.                      tmpptr++;
  1808.  
  1809.                   /* don't link the declaration itself */
  1810.                   if(*tmpptr != '{' && *tmpptr != '\n')
  1811.                      link = TRUE;
  1812.                }
  1813.  
  1814.                if(!link)
  1815.                {
  1816.                   /* varray[i] is set to wordbuf, thus i can handle 10 %s */
  1817.                   VFPrintf(wfh,keyword->kw_Substitute,gd->gd_VArray);
  1818.  
  1819.                   draw_keyword(gd);
  1820.                } else
  1821.                {
  1822.                   DB(("check reference\n"));
  1823.                   check_reference(gd);
  1824.                }
  1825.             }
  1826.          } else
  1827.          {
  1828.             /* varray[i] is set to wordbuf, thus i can handle 10 %s */
  1829.             VFPrintf(wfh,keyword->kw_Substitute,gd->gd_VArray);
  1830.  
  1831.             draw_keyword(gd);
  1832.          }
  1833.  
  1834.          break;
  1835.       } else if(comp > 0)
  1836.          break;
  1837.    }
  1838.  
  1839.    return((BOOL) (comp == 0));
  1840. }
  1841. /*FE*/
  1842. /*FS*//*"BOOL check_internxref(struct GlobalData *gd)"*/
  1843. BOOL check_internxref(struct GlobalData *gd)
  1844. {
  1845.    struct Node *node;
  1846.    STRPTR wordbuf = gd->gd_WordBuffer;
  1847.    WORD cmp = 1;
  1848.  
  1849.    for(node = gd->gd_InternXRef.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  1850.        if((cmp = strcmp(node->ln_Name,wordbuf)) >= 0)
  1851.           break;
  1852.  
  1853.    if(cmp)
  1854.    {
  1855.       /* check if the current phrase matches any intern xref (including white spaces) ! */
  1856.       for(node = gd->gd_InternXRef.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  1857.       {
  1858.          if((cmp = strncmp(node->ln_Name,gd->gd_CurrentPtr,IXR(node)->ixr_NameLen)) >= 0)
  1859.          {
  1860.             if(cmp == 0)
  1861.             {
  1862.                gd->gd_Ptr = gd->gd_CurrentPtr + IXR(node)->ixr_NameLen;
  1863.                strcpy(wordbuf,gd->gd_CurrentPtr);
  1864.                wordbuf[IXR(node)->ixr_NameLen] = EOS;
  1865.             }
  1866.             break;
  1867.          }
  1868.       }
  1869.  
  1870.       if(cmp)
  1871.       {
  1872.          STRPTR filepart;
  1873.          ULONG len;
  1874.  
  1875.          /* check if the current phrase matches any intern xref (including white spaces) ! */
  1876.          for(node = gd->gd_InternXRef.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  1877.          {
  1878.             filepart = FilePart(node->ln_Name);
  1879.             len = strlen(filepart);
  1880.  
  1881.             if(strncmp(filepart,gd->gd_CurrentPtr,len) == 0)
  1882.             {
  1883.                gd->gd_Ptr = gd->gd_CurrentPtr + len;
  1884.                strcpy(wordbuf,filepart);
  1885.                cmp = 0;
  1886.                DB(("intern : \"%s\" -> \"%s\" !\n",filepart,gd->gd_CurrentPtr));
  1887.                break;
  1888.             }
  1889.          }
  1890.  
  1891.          /* check if the current WORD matches an intern xref ! */
  1892.          if(cmp)
  1893.          {
  1894.             ULONG len = strlen(wordbuf);
  1895.  
  1896.             for(node = gd->gd_InternXRef.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
  1897.                if((cmp = strncmp(node->ln_Name,wordbuf,len)) >= 0)
  1898.                {
  1899.                   if(!(cmp == 0 && (!strcmp(&node->ln_Name[len],"()") || len == IXR(node)->ixr_NameLen)))
  1900.                      cmp = 1;
  1901.                   break;
  1902.                }
  1903.          }
  1904.       }
  1905.    }
  1906.  
  1907.    if(cmp == 0)
  1908.    {
  1909.       /* don't link any words, which are the same as the filename */
  1910.       if(strncmp(node->ln_Name,gd->gd_NameBuffer,IXR(node)->ixr_NameLen))
  1911.       {
  1912.          gd->gd_GlobalStat.Number[XREFCT_INTERN]++;
  1913.          gd->gd_Links++;
  1914.  
  1915.          if(gd->gd_Workbench)
  1916.          {
  1917.             sprintf(gd->gd_TempBuffer,"%ld",gd->gd_Links);
  1918.             draw_scanwindowtext(&gd->gd_SWin,NUM_LINKS,gd->gd_TempBuffer);
  1919.          }
  1920.  
  1921.          FPrintf(gd->gd_WriteFH,"@{\"%s\" link \"%s\"}",wordbuf,((struct InternXRef *) node)->ixr_Link);
  1922.       } else
  1923.          write_word(gd);
  1924.  
  1925.       return(TRUE);
  1926.    }
  1927.  
  1928.    return(FALSE);
  1929. }
  1930. /*FE*/
  1931. /*FS*//*"void check_reference(struct GlobalData *gd)"*/
  1932. void check_reference(struct GlobalData *gd)
  1933. {
  1934.    STRPTR wordbuf = gd->gd_WordBuffer;
  1935.    struct Convert *conv = &gd->gd_Convert;
  1936.    STRPTR slash;
  1937.  
  1938.    conv->Number = 0;
  1939.  
  1940.    gd->gd_Tags[0].ti_Data = XREFMATCH_COMPARE_CASE;
  1941.  
  1942.    if(ParseXRef(wordbuf,gd->gd_Tags))
  1943.    {
  1944.       if(conv->Number == 0)
  1945.       {
  1946.          if((slash = FilePart(wordbuf)) != wordbuf)
  1947.          {
  1948.             slash[-1] = EOS;
  1949.  
  1950.             /* try to link the PathPart */
  1951.             if(ParseXRef(wordbuf,gd->gd_Tags))
  1952.             {
  1953.                if(conv->Number == 0)
  1954.                {
  1955.                   slash[-1] = '/';
  1956.  
  1957.                   DB(("try to link : %s,%s\n",slash,wordbuf));
  1958.                   /* if no link is made to PathPart try to link th whole path */
  1959.                   if(!ParseXRef(slash,gd->gd_Tags))
  1960.                      conv->Number = 0;
  1961.                   DB(("found number : %ld\n",conv->Number));
  1962.  
  1963.                } else
  1964.                {
  1965.                   /* make link to PathPart */
  1966.                   write_link(gd);
  1967.                   /* write the slash */
  1968.                   FPutC(gd->gd_WriteFH,'/');
  1969.  
  1970.                   strcpy(wordbuf,slash);
  1971.  
  1972.                   /* try to link the FilePart */
  1973.                   if(!ParseXRef(wordbuf,gd->gd_Tags))
  1974.                      conv->Number = 0;
  1975.                }
  1976.             }
  1977.          }
  1978.  
  1979.          if(conv->Number == 0)
  1980.          {
  1981.             gd->gd_Tags[0].ti_Data = XREFMATCH_COMPARE_NUM_CASE;
  1982.  
  1983.             if(ParseXRef(wordbuf,gd->gd_Tags))
  1984.             {
  1985.                /* only use the three types below with COMPARE_NUM */
  1986.                if(conv->Number > 0)
  1987.                   switch(conv->xr_Type)
  1988.                   {
  1989.                   case XREFT_COMMAND:
  1990.                   case XREFT_FUNCTION:
  1991.                   case XREFT_GENERIC:
  1992.                      break;
  1993.                   default:
  1994.                      conv->Number = 0;
  1995.                   }
  1996.             }
  1997.          }
  1998.       }
  1999.  
  2000.       if(conv->Number > 0)
  2001.          write_link(gd);
  2002.       else
  2003.          write_word(gd);
  2004.    } else
  2005.       write_word(gd);
  2006. }
  2007. /*FE*/
  2008.  
  2009. /* ---------------------- amigaguide write functions ---------------------- */
  2010.  
  2011. /*FS*//*"void write_guide_header(struct GlobalData *gd)"*/
  2012. void write_guide_header(struct GlobalData *gd)
  2013. {
  2014.    if(!gd->gd_Para[ARG_NOAMIGAGUIDE])
  2015.    {
  2016.       FPrintf(gd->gd_WriteFH,"@database %s\n"
  2017.                              "@master %s\n",
  2018.                               gd->gd_FileName,gd->gd_FullPath);
  2019.  
  2020.       if(gd->gd_Para[ARG_V40])
  2021.          FPuts(gd->gd_WriteFH,"@macro mtext \"@{lindent 8}@{pari -4}@{par}@{b}$1@{ub}@{body}@{line}\"\n"
  2022.                               "@macro mcode \"@{lindent 8}@{pari -4}@{par}@{code}@{b}$1@{ub}\"\n"
  2023.                               "@smartwrap\n");
  2024.       FPrintf(gd->gd_WriteFH,"@node main \"%s\"\n",gd->gd_FileName);
  2025.  
  2026.       if(!gd->gd_Para[ARG_NOMAINPAGELINK])
  2027.          FPuts(gd->gd_WriteFH,"@toc xref.library_xreffile@main\n");
  2028.  
  2029.       gd->gd_OpenNodes = 1;
  2030.    }
  2031. }
  2032. /*FE*/
  2033. /*FS*/ /*"void write_link(struct GlobalData *gd) "*/
  2034. void write_link(struct GlobalData *gd)
  2035. {     
  2036.    struct Convert *conv = &gd->gd_Convert;
  2037.    BPTR wfh             = gd->gd_WriteFH;
  2038.    ULONG len;
  2039.  
  2040.    if(conv->xr_Type != XREFT_INCLUDE)
  2041.       len = strlen(FilePart(gd->gd_WordBuffer));
  2042.    else
  2043.       len = strlen(gd->gd_WordBuffer);
  2044.  
  2045.    DB(("word node : %s/%s\n",gd->gd_FileName,gd->gd_NameBuffer));
  2046.    DB(("link node : %s/%s\n",conv->xr_File,conv->xr_NodeName));
  2047.  
  2048.    if((strcmp(conv->xr_NodeName,gd->gd_NameBuffer) || strcmp(conv->xr_File,gd->gd_FileName)) &&
  2049.       (len == strlen(conv->xr_Name)                  || !strcmp(&conv->xr_Name[len],"()")))
  2050.    {
  2051.       /* generate extern link, if the filename are nor equal, otherwise it is an internal */
  2052.       if(strcmp(conv->xr_File,gd->gd_FileName))
  2053.          FPrintf(wfh,"@{\"%s\" link \"%s%s/%s\"",
  2054.                      gd->gd_WordBuffer,
  2055.                      conv->xr_Path,
  2056.                      conv->xr_File,
  2057.                      conv->xr_NodeName);
  2058.       else
  2059.          FPrintf(wfh,"@{\"%s\" link \"%s\"",
  2060.                      gd->gd_WordBuffer,
  2061.                      conv->xr_NodeName);
  2062.  
  2063.       if(conv->xr_Line != ~0)
  2064.          FPrintf(wfh," %ld",conv->xr_Line);
  2065.  
  2066.       FPutC(wfh,'}');
  2067.  
  2068.       gd->gd_GlobalStat.Number[conv->xr_Type]++;
  2069.       gd->gd_Links++;
  2070.  
  2071.       if(gd->gd_Workbench)
  2072.       {
  2073.          sprintf(gd->gd_TempBuffer,"%ld",gd->gd_Links);
  2074.          draw_scanwindowtext(&gd->gd_SWin,NUM_LINKS,gd->gd_TempBuffer);
  2075.       }
  2076.    } else
  2077.       write_word(gd);
  2078. }
  2079. /*FE*/
  2080. /*FS*/ /*"void write_word(struct GlobalData *gd) "*/
  2081. void write_word(struct GlobalData *gd)
  2082. {
  2083.    if(*gd->gd_WordBuffer)
  2084.       FPrintf(gd->gd_WriteFH,style_strings[gd->gd_StyleType],gd->gd_WordBuffer);
  2085.    gd->gd_StyleType = STYLE_UNKNOWN;
  2086. }
  2087. /*FE*/
  2088.  
  2089. /* ------------------------ separate the next WORD ------------------------ */
  2090.  
  2091. /*FS*//*"STRPTR getword(struct GlobalData *gd,STRPTR delim)"*/
  2092. STRPTR getword(struct GlobalData *gd,STRPTR delim)
  2093. {
  2094.    STRPTR line = gd->gd_Ptr;
  2095.    STRPTR buf  = gd->gd_WordBuffer;
  2096.    BOOL skipdelim = gd->gd_Para[ARG_V40] && gd->gd_LineBegin;
  2097.    UWORD indent = 0;
  2098.    UWORD skipindent = 2 * gd->gd_Para[ARG_INDENT] - 1;
  2099.  
  2100.    gd->gd_StyleType = STYLE_UNKNOWN;
  2101.  
  2102.    /* skip all delimiters */
  2103.  
  2104.    while(*line && strchr(delim,*line))
  2105.    {
  2106.       if(gd->gd_FileType == FTYPE_MAN)
  2107.          if(line[1] == '\010')
  2108.             line +=2;
  2109.  
  2110.       if(!skipdelim)
  2111.          FPutC(gd->gd_WriteFH,*line);
  2112.       else if(indent == skipindent)
  2113.       {
  2114.          skipdelim = FALSE;
  2115.          if(line[1] && strchr(delim,line[1]) && gd->gd_SmartWrapped)
  2116.             FPuts(gd->gd_WriteFH,"@{line}");
  2117.       } else
  2118.          indent++;
  2119.  
  2120.       line++;
  2121.    }
  2122.  
  2123.    gd->gd_CurrentPtr = line;
  2124.  
  2125.    /* skip all links of an amigaguide file */
  2126.    if(gd->gd_FileType == FTYPE_AMIGAGUIDE)
  2127.       if(*line == '@' && *(line + 1) == '{')
  2128.       {
  2129.          line += 2;
  2130.          while(*line != '}' && *line != EOS)
  2131.             line++;
  2132.  
  2133.          FWrite(gd->gd_WriteFH,gd->gd_CurrentPtr,(line - gd->gd_CurrentPtr),1);
  2134.          gd->gd_CurrentPtr = line;
  2135.       }
  2136.  
  2137.  
  2138.    while(*line)
  2139.    {
  2140.       /* backspace from a manpage ? */
  2141.       if(line[1] == '\010')
  2142.       {
  2143.          if(gd->gd_StyleType == STYLE_UNKNOWN)
  2144.          {
  2145.             if(*line == '_')
  2146.                gd->gd_StyleType = STYLE_UNDERLINED;
  2147.             if(*line == line[2])
  2148.                gd->gd_StyleType = STYLE_BOLD;
  2149.          }
  2150.          line += 2;
  2151.       }
  2152.  
  2153.       /* skip "()" pairs, which normally indicates a system function */
  2154.       if(*line == '(' && line[1] == ')')
  2155.       {
  2156.          *buf++ = *line++;
  2157.          *buf++ = *line++;
  2158.       } else if(*line == '.' && line[1] != ' ' && line[1] != EOS && line[1] != '\t' && line[1] != '\n')
  2159.       {
  2160.          *buf++ = *line++;
  2161.          if(line[1] == '\010')
  2162.             line +=2;
  2163.          *buf++ = *line++;
  2164.       }
  2165.  
  2166.       if(strchr(delim,*line))
  2167.          break;
  2168.  
  2169.       *buf++ = *line++;
  2170.    }
  2171.  
  2172.    *buf   = EOS;
  2173.    gd->gd_Ptr = line;
  2174.    gd->gd_LineBegin = FALSE;
  2175.  
  2176.    if(*line)
  2177.       return(line);
  2178.  
  2179.    return(NULL);
  2180. }
  2181. /*FE*/
  2182.  
  2183. /* -------------------------- support functions --------------------------- */
  2184.  
  2185. /*FS*/ /*"BOOL check_abort(struct GlobalData *gd)"*/
  2186. BOOL check_abort(struct GlobalData *gd)
  2187. {
  2188.    if(gd->gd_SWin.sw_Window)
  2189.    {
  2190.       struct IntuiMessage *msg;
  2191.  
  2192.       while((msg = (struct IntuiMessage *) GetMsg(gd->gd_SWin.sw_Window->UserPort)))
  2193.       {
  2194.          switch(msg->Class)
  2195.          {
  2196.          case IDCMP_CLOSEWINDOW:
  2197.             gd->gd_Abort = TRUE;
  2198.             break;
  2199.          case IDCMP_VANILLAKEY:
  2200.             /* check if ctrl-c or ecs was pressed ? */
  2201.             if(msg->Code == 3 || msg->Code == 27)
  2202.                gd->gd_Abort = TRUE;
  2203.             break;
  2204.          }
  2205.          ReplyMsg((struct Message *) msg);
  2206.       }
  2207.  
  2208.       if(gd->gd_Abort)
  2209.          draw_scanwindowstatus(&gd->gd_SWin,"aborted !");
  2210.  
  2211.    }
  2212.  
  2213.    gd->gd_Abort |= (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C);
  2214.  
  2215.    return(gd->gd_Abort);
  2216. }
  2217. /*FE*/
  2218.  
  2219. /*FS*//*"void allocinternxref(struct GlobalData *gd,STRPTR name,STRPTR link)"*/
  2220. void allocinternxref(struct GlobalData *gd,STRPTR name,STRPTR link)
  2221. {
  2222.    struct InternXRef *ixrnode;
  2223.    ULONG size = sizeof(struct InternXRef) + strlen(name) + 3;
  2224.  
  2225.    if(name != link)
  2226.       size += strlen(link) + 1;
  2227.  
  2228.    if(ixrnode = LibAllocPooled(gd->gd_InternPool,size))
  2229.    {
  2230.       DB(("intern xref : %s\n",name));
  2231.  
  2232.       ixrnode->ixr_Length  = size;
  2233.       ixrnode->ixr_NameLen = strlen(name);
  2234.  
  2235.       ixrnode->ixr_Node.ln_Name = (STRPTR) (ixrnode + 1);
  2236.  
  2237.       strcpy(ixrnode->ixr_Node.ln_Name,name);
  2238.       if(name == link)
  2239.          ixrnode->ixr_Link = ixrnode->ixr_Node.ln_Name;
  2240.       else
  2241.       {
  2242.          ixrnode->ixr_Link = ixrnode->ixr_Node.ln_Name + ixrnode->ixr_NameLen + 1;
  2243.          strcpy(ixrnode->ixr_Link,link);
  2244.       }
  2245.  
  2246.       insertbyname(&gd->gd_InternXRef,(struct Node *) ixrnode);
  2247.    }
  2248. }
  2249. /*FE*/
  2250.  
  2251. /* ---------------------------- draw functions ---------------------------- */
  2252.  
  2253. /*FS*/ /*"void draw_state(struct GlobalData *gd)"*/
  2254. void draw_state(struct GlobalData *gd)
  2255. {
  2256.    if(gd->gd_Workbench || gd->gd_Para[ARG_VERBOSE])
  2257.    {
  2258.       ULONG current; 
  2259.       ULONG acttotal;
  2260.  
  2261.       if(gd->gd_ReadFH)
  2262.          current = Seek(gd->gd_ReadFH,0,OFFSET_CURRENT);
  2263.       else 
  2264.          current = 0;
  2265.       
  2266.       acttotal = gd->gd_SStat.ss_ActTotalFileSize + current;
  2267.  
  2268.       time_calc(&gd->gd_TimeCalc,acttotal,gd->gd_SStat.ss_TotalFileSize);
  2269.  
  2270.       if(gd->gd_Workbench)
  2271.       {
  2272.          draw_gauge(&gd->gd_SWin.sw_Actual,current,gd->gd_FileSize);
  2273.          draw_gauge(&gd->gd_SWin.sw_Total ,acttotal,
  2274.                                            gd->gd_SStat.ss_TotalFileSize);
  2275.  
  2276.          draw_scanwindowtime(&gd->gd_SWin,gd->gd_TimeCalc.tc_Secs);
  2277.       } else
  2278.       {
  2279.          Printf ("\rConverting (%6ld/%6ld) , Time Exp. : %02ld:%02ld , Left : %02ld:%02ld",
  2280.                  current,gd->gd_FileSize,
  2281.                  gd->gd_TimeCalc.tc_Secs[TIME_EXPECTED] / 60,gd->gd_TimeCalc.tc_Secs[TIME_EXPECTED] % 60,
  2282.                  gd->gd_TimeCalc.tc_Secs[TIME_LEFT]     / 60,gd->gd_TimeCalc.tc_Secs[TIME_LEFT]     % 60);
  2283.       }
  2284.    }
  2285. }
  2286. /*FE*/
  2287. /*FS*/ /*"void draw_keyword(struct GlobalData *gd)"*/
  2288. void draw_keyword(struct GlobalData *gd)
  2289. {
  2290.    gd->gd_GlobalStat.Number[XREFCT_KEYWORDS]++;
  2291.  
  2292.    if(gd->gd_Workbench)
  2293.    {
  2294.       sprintf(gd->gd_TempBuffer,"%ld",gd->gd_GlobalStat.Number[XREFCT_KEYWORDS]);
  2295.       draw_scanwindowtext(&gd->gd_SWin,NUM_KEYWORDS,gd->gd_TempBuffer);
  2296.    }
  2297. }
  2298. /*FE*/
  2299.  
  2300.