home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / PCTAG.ZIP / RETROMAC.COM / RETRO.M < prev    next >
Text File  |  1989-10-01  |  48KB  |  1,124 lines

  1. ;
  2. ; ----------------------------------------------
  3. ; PC-TAGS(tm) RETRO Program for the BRIEF Editor
  4. ; ----------------------------------------------
  5. ;
  6. ; BRIEF Macros to Search a PC-TAGS-Generated Tagfile and Retrieve a
  7. ; Function Definition
  8. ;
  9. ; Copyright (C) 1989 by Moderne Software.  All rights reserved.
  10. ; Moderne Software, P.O. Box 3638, Santa Clara, CA 95055-3638
  11. ;
  12. ; Limited permission is given to registered PC-TAGS users to modify this
  13. ; file for their own personal use only.  This file may not be used for any 
  14. ; purpose other than in conjunction with the PC-TAGS software package.
  15. ;
  16. ; Entry Points
  17. ; ------------
  18. ;       _init               -- declare global variables
  19. ;       pctags_auto         -- uses word under cursor for search
  20. ;       pctags_prompt       -- prompts for a word to use in search
  21. ;
  22. ; Support macros
  23. ; --------------
  24. ;       delimiter           -- determines if character is a word delimiter
  25. ;       convert_slashes     -- convert slash characters in string to backslashes
  26. ;       get_tagfile         -- retrieve the next tagfile to search
  27. ;       parse_file_spec     -- break multiple tagfile specifications into
  28. ;                               individual directory/filename parts
  29. ;       dos_shell           -- execute RETROEXEC environment value thru DOS
  30. ;       file_already_loaded -- determine if file is already loaded into buffer
  31. ;       position_line_within_window -- position current line to third line in
  32. ;                               current window, if possible
  33. ;       pctags_main         -- search and retrieval workhorse code
  34. ;
  35. ; History
  36. ; -------
  37. ;  1 Oct 89 -- Version 1.00
  38. ;
  39.  
  40. ;***************************************
  41. ; Global data
  42.  
  43. ; Standard boolean values
  44. #define TRUE                1
  45. #define FALSE               0
  46.  
  47. ; Return values
  48. #define SUCCESSFUL          1
  49. #define UNSUCCESSFUL        0
  50.  
  51. ; Search case sensitivity settings
  52. #define CASE_SENSITIVE      1
  53. #define CASE_INSENSITIVE    0
  54.  
  55. ; Values for pctags_first_call global variable
  56. #define FIRST_CALL          1
  57. #define NOT_FIRST_CALL      0
  58.  
  59. ;***************************************
  60. ; Macro : _init
  61. ; Syntax: ( _init )
  62. ; Entry : None.
  63. ; Exit  : Global variables used by the PC-TAGS macros are declared.
  64. ; Notes : This macro is called by BRIEF automatically upon loading.
  65.  
  66. ( macro _init
  67.     (
  68.  
  69. ; Case-sensitivity setting for tagname search.  You can change the
  70. ; CASE_SENSITIVE setting to CASE_INSENSITIVE if you want the search for a
  71. ; matching tagname to ignore case.
  72.         ( int           pctags_tagname_case )
  73.         ( global        pctags_tagname_case )
  74.         ( = pctags_tagname_case CASE_SENSITIVE )
  75.  
  76. ; Flag for first-call to get_tagfile ( 1=first call, 0=all subsequent calls)
  77.         ( int           pctags_first_call )
  78.  
  79. ; Storage for environment tagfile specifications and current tagfile directory
  80.         ( string        pctags_env_tagfiles )
  81.         ( string        pctags_env_path )
  82.  
  83.  
  84.         ; Make all declared variables global to this file
  85.         ( global pctags_first_call )
  86.         ( global pctags_env_tagfiles )
  87.         ( global pctags_env_path )
  88.  
  89.     )
  90. )   ; macro _init
  91.  
  92. ;***************************************
  93. ; Macro : pctags_auto
  94. ; Syntax: ( pctags_auto )
  95. ; Entry : None.
  96. ; Exit  ; Non-zero if function under cursor is found, file containing function
  97. ;           definition is loaded and cursor is placed at beginning of
  98. ;           definition.
  99. ;         Zero if specified function is not found.
  100. ; Description :
  101. ;         Function under cursor is extracted from line and used to search thru
  102. ;           the tagfile(s).  If a match is found, the file containing the
  103. ;           function's definition is loaded and the cursor is placed at the
  104. ;           start of the definition.
  105.  
  106. ( macro pctags_auto
  107.     (   ; 1
  108.  
  109.         ( int       first_char
  110.                     last_char
  111.                     length
  112.                     row
  113.         )
  114.         ( string    char
  115.                     current_word
  116.         )
  117.  
  118.  
  119.         ; Read cursor character
  120.         ( = char (read 1) )
  121.  
  122.         ; Verify that cursor is under a valid word
  123.         ( if (delimiter char)
  124.             (   ; 2
  125.                 ( error "Invalid word" )
  126.                 ( beep )
  127.                 ( return UNSUCCESSFUL )
  128.             )   ; 2
  129.         )
  130.  
  131.         ; Save current position
  132.         ( save_position )
  133.  
  134.         ; Find the last character in this word
  135.         ; Move to the next character
  136.         ( if (! (next_char))
  137.             (   ; 2a
  138.                 ; At end of file, current position is last char in word
  139.                 ( inq_position row last_char )
  140.             )   ; 2a
  141.         ; else
  142.             (   ; 2b
  143.                 ; Advance through word until delimiter or eof
  144.                 ( while (! (delimiter (read 1)))
  145.                     (   ; 3
  146.                         ; Move to next char
  147.                         ( if (! (next_char))
  148.                             (   ; 4
  149.                                 ; Reached end of file, current position is last
  150.                                 ; character in word
  151.                                 ( inq_position row last_char )
  152.                                 ( break )
  153.                             )   ; 4
  154.                         )
  155.                     )   ; 3
  156.                 )
  157.  
  158.                 ; If last_char != 0, reached eof, else reached delimiter
  159.                 ( if (== last_char 0)
  160.                     (   ; 3
  161.                         ; Previous character is the last char in the word
  162.                         ( prev_char )
  163.                         ( inq_position row last_char )
  164.                     )   ; 3
  165.                 )
  166.             )   ; 2b
  167.         )
  168.  
  169.         ; Restore position to cursor and save again
  170.         ( restore_position )
  171.         ( save_position )
  172.  
  173.         ; Find first character of word
  174.         ; Work your way backwards
  175.         ( if (! (prev_char))
  176.             (   ; 2a
  177.                 ; At start of file, current position is first char in word
  178.                 ( inq_position row first_char )    ; Should be 1
  179.             )   ; 2a
  180.         ; else
  181.             (   ; 2b
  182.                 ; Backtrack thru word until delimiter or start of file
  183.                 ( while (! (delimiter (read 1)))
  184.                     (   ; 3
  185.                         ; Move to previous character
  186.                         ( if (! (prev_char))
  187.                             (   ; 4
  188.                                 ; Reached start of file, current position is
  189.                                 ; first char in word
  190.                                 ( inq_position row first_char )    ; Should be 1
  191.                                 ( break )
  192.                             )   ; 4
  193.                         )
  194.                     )   ; 3
  195.                 )
  196.  
  197.                 ; If first_char != 0, reached beginning of file, else reached
  198.                 ; delimiter
  199.                 ( if (== first_char 0)
  200.                     (   ; 3
  201.                         ; Next character is first char in word
  202.                         ( next_char )
  203.                         ( inq_position row first_char )
  204.                     )   ; 3
  205.                 )
  206.             )   ; 2b
  207.         )
  208.  
  209.         ; We now have index to first and last chars in word and current position
  210.         ; is at the start of the word.
  211.         ; Calculate length of word
  212.         ( = length (+ (- last_char first_char) 1))  ; length = last - first + 1
  213.  
  214.         ; Read word
  215.         ( = current_word (read length) )
  216.  
  217.         ; Append a blank to the word
  218.         ( = current_word (+ current_word " ") )
  219.  
  220.         ; Restore original position in file
  221.         ( restore_position )
  222.  
  223.         ; Perform pctags operation and return SUCCESSFUL or UNSUCCESSFUL
  224.         ( return (pctags_main current_word) )
  225.  
  226.     )   ; 1
  227. ) ; macro pctags_auto
  228.  
  229. ;***************************************
  230. ; Macro : pctags_prompt
  231. ; Syntax: ( pctags_prompt {function_name} )
  232. ; Entry : Function name for which to search and retrieve.
  233. ; Exit  : Non-zero if specified function is found, file containing function
  234. ;           definition is loaded and cursor is placed at beginning of
  235. ;           definition.
  236. ;         Zero if specified function is not found.
  237. ; Description :
  238. ;       User is prompted for the name of a function.  The macro loads the file
  239. ;       containing the function definition and places the cursor on the
  240. ;       definition's line.
  241.  
  242. ( macro pctags_prompt
  243.     (
  244.  
  245.         ( string    function_name )
  246.  
  247.  
  248.         ; Prompt the user for a function name and save in function_name variable
  249.         ( if (! (get_parm 0 function_name "Enter tagname: "))
  250.             (
  251.                 ; User pressed <Esc> key
  252.                 ( message "Command aborted." )
  253.                 ( return UNSUCCESSFUL )
  254.             )
  255.         )
  256.  
  257.         ; If empty string entered, abort
  258.         ( if (== (strlen function_name) 0)
  259.             (
  260.                 ; Simply exit
  261.                 ( return UNSUCCESSFUL );
  262.             )
  263.         )
  264.  
  265.         ; Append a blank to the function name
  266.         ( = function_name (+ function_name " ") )
  267.  
  268.         ; Perform pctags operation and return SUCCESSFUL or UNSUCCESSFUL value
  269.         ( return (pctags_main function_name) )
  270.  
  271.     )
  272. )  ; macro pctags_prompt
  273.  
  274. ;***************************************
  275. ; Macro : delimiter
  276. ; Syntax: ( delimiter char )
  277. ; Entry : char = character to check as a delimiter
  278. ; Exit  : Non-zero if character is a delimiter, else zero.
  279. ; Note  : Character is considered a delimiter if it is not an alphanumeric
  280. ;           or underscore or dot (for Turbo Pascal 5.5 only) character.
  281.  
  282. ( macro delimiter
  283.     (
  284.  
  285. ; Return values
  286. #define DELIMITER       1
  287. #define NOT_DELIMITER   0
  288.  
  289. ; ASCII values
  290. #define DOT             0x2E
  291. #define ASCII_0         0x30
  292. #define ASCII_9         0x39
  293. #define ASCII_A         0x41
  294. #define ASCII_Z         0x5A
  295. #define UNDERSCORE      0x5F
  296.  
  297. ; Miscellaneous
  298. #define GET_ASCII       0
  299.  
  300.         ( int       ascii_value )
  301.         ( string    char )
  302.  
  303.  
  304.         ; Get the character parameter
  305.         ( get_parm 0 char )
  306.  
  307.         ; Convert char to uppercase
  308.         ( = char (upper char) )
  309.  
  310.         ; Convert char to its ASCII value
  311.         ( = ascii_value (atoi char GET_ASCII) )
  312.  
  313.         ; Check for alpha char between 'A' and 'Z', inclusive
  314.         ( if (&& (>= ascii_value ASCII_A) (<= ascii_value ASCII_Z))
  315.             ( return NOT_DELIMITER )
  316.         )
  317.  
  318.         ; Check for numeric character between '1' and '9', inclusive
  319.         ( if (&& (>= ascii_value ASCII_0) (<= ascii_value ASCII_9))
  320.             ( return NOT_DELIMITER )
  321.         )
  322.  
  323.         ; Check for underscore char
  324.         ( if (== ascii_value UNDERSCORE)
  325.             ; Yes, it's an underscore
  326.             ( return NOT_DELIMITER )
  327.         )
  328.  
  329.         ; Check for dot character (for Turbo Pascal 5.5 only)
  330.         ( if (== ascii_value DOT)
  331.             ( return NOT_DELIMITER )
  332.         )
  333.  
  334.         ; Else, it must be a delimiter
  335.         ( return DELIMITER )
  336.  
  337.     )
  338. )   ; macro delimiter
  339.  
  340. ;***************************************
  341. ; Macro : convert_slashes
  342. ; Syntax: ( convert_slashes str )
  343. ; Entry : str is a string which may contain slash characters
  344. ; Exit  : String with all slash characters converted to backslashes
  345.  
  346. ( macro convert_slashes
  347.     (
  348.  
  349.         ( int       pos )
  350.         ( string    str )
  351.  
  352.  
  353.         ; Get argument
  354.         ( get_parm 0 str )
  355.  
  356.         ; Search string for a slash
  357.         ( = pos (index str "/") )
  358.  
  359.         ; While there are still slashes in string, convert them
  360.         ( while pos
  361.             (
  362.                 ;Convert slash to backslash
  363.                 ( = str (+ (+ (substr str 1 (- pos 1)) "\\")
  364.                            (substr str (+ pos 1))) )
  365.  
  366.                 ; Check for more slashes
  367.                 ( = pos (index str "/") )
  368.             )
  369.         )
  370.  
  371.         ; Return converted string
  372.         ( returns str )
  373.  
  374.     )
  375. )   ; macro convert_slashes
  376.  
  377. ;***************************************
  378. ; Macro : get_tagfile
  379. ; Syntax: ( get_tagfile )
  380. ; Entry : None.
  381. ; Exit  : Return tagfile name or empty string if none left.
  382. ;
  383. ; Use of Global Variables:
  384. ;       pctags_first_call       -- access and assign
  385. ;       pctags_env_tagfiles     -- access only
  386. ;       pctags_env_path         -- access only
  387.  
  388. ( macro get_tagfile
  389.     (   ; 1
  390.  
  391.         ( string    file_spec )
  392.  
  393.  
  394.         ; If this is the first call to this macro in this pctags invocation,
  395.         ; get the RETRO environment variable setting, if any
  396.         ( if pctags_first_call
  397.             (   ; 2
  398.                 ; Go thru this code once per pctags invocation
  399.                 ( = pctags_first_call NOT_FIRST_CALL )
  400.  
  401.                 ; Get RETRO environment variable
  402.                 ( = file_spec (inq_environment "RETRO") )
  403.  
  404.                 ; Convert any slashes to backslashes and all chars to lowercase
  405.                 ( = file_spec (lower (convert_slashes file_spec)) )
  406.  
  407.                 ; If no such variable, use the default
  408.                 ( if (== file_spec "")
  409.                     ( = file_spec "*.tag" )
  410.                 )
  411.  
  412.                 ; Parse any multiple file specs into single specs and set
  413.                 ; the file pattern to the first parsed file_spec (may contain
  414.                 ; wildcards).
  415.                 ( parse_file_spec file_spec )
  416.             )   ; 2
  417.         )
  418.  
  419.         ; Get a tagfile name.  If file_spec is empty, check for more tagfile
  420.         ; locations in environment variable setting (pctags_env_tagfiles).
  421.         ( while (! (find_file file_spec))
  422.             (   ; 2
  423.                 ; Any more file specs in pctags_env_tagfiles?
  424.                 ( if (== pctags_env_tagfiles "")
  425.                     ; Nope, this is the end of the road
  426.                     ( break )
  427.                 ; else
  428.                     ; Yes, parse out the next location (sets
  429.                     ; pctags_env_path) and set the file pattern to the
  430.                     ; extracted filespec.
  431.                     ( parse_file_spec pctags_env_tagfiles )
  432.                 )
  433.             )   ; 2
  434.         )
  435.  
  436.         ; Convert filename to lowercase and concatenate any drive:path
  437.         ( if (!= file_spec "")
  438.             (   ; 2
  439.                 ; Filename found, convert to lowercase
  440.                 ( = file_spec (lower file_spec) )
  441.  
  442.                 ; Insert drive:path
  443.                 ( = file_spec (+ pctags_env_path file_spec) )
  444.             )   ; 2
  445.         )
  446.  
  447.         ; Return tagfile name (or empty if none left)
  448.         ( returns file_spec )
  449.  
  450.     )   ; 1
  451. )   ; macro get_tagfile
  452.  
  453. ;***************************************
  454. ; Macro : parse_file_spec
  455. ; Syntax: ( parse_file_spec file_spec )
  456. ; Entry : file_spec = file specification to parse.  May contain wildcards.  May
  457. ;           also contain multiple specs, each separated by a semicolon.  For
  458. ;           example, "c:\*.tag;d:\brief\tagfiles\*.tag;c:\pctags.tag".
  459. ; Exit  : Any drive:path in the first file spec is stored in pctags_env_path.
  460. ;         Any subsequent file specs are stored in pctags_env_tagfiles.
  461. ;         The filename portion of the spec is returned (may contain wildcards).
  462. ;         The search pattern is set for future (find_file) calls.
  463. ;
  464. ; Use of Global Variables:
  465. ;       pctags_env_tagfiles     -- assigns
  466. ;       pctags_env_path         -- assigns
  467.  
  468. ( macro parse_file_spec
  469.     (   ; 1
  470.  
  471.         ( int       last_path_separator
  472.                     last_slash
  473.                     semicolon
  474.         )
  475.         ( string    file_spec )
  476.  
  477.  
  478.         ; Get parameter
  479.         ( get_parm 0 file_spec )
  480.  
  481.         ; Does file_spec contain multiple specs?
  482.         ( if (! (= semicolon (index file_spec ";")))
  483.             ; No, file_spec contains one drive:path.  Clear pctags_env_tagfiles.
  484.             ( = pctags_env_tagfiles "" )
  485.         ; else
  486.             (   ; 2
  487.                 ; Yes, store subsequent specs in pctags_env_tagfiles
  488.                 ( = pctags_env_tagfiles (substr file_spec (+ semicolon 1)) )
  489.  
  490.                 ; Place first spec only in file_spec
  491.                 ( = file_spec (substr file_spec 1 (- semicolon 1)) )
  492.             )   ; 2
  493.         )
  494.  
  495.         ; Set file search pattern for future calls to (find_file)
  496.         ( file_pattern file_spec )
  497.  
  498.         ; Does file_spec contain a drive or path spec?
  499.         ; Find index to last path separator
  500.         ( = last_path_separator (rindex file_spec "\\") )
  501.  
  502.         ; If no path was specified, check for a drive
  503.         ( if (== last_path_separator 0)
  504.             ( = last_path_separator (rindex file_spec ":") )
  505.         )
  506.  
  507.         ; If drive and/or path were specified, extract from file_spec and
  508.         ; store in pctags_env_path.
  509.         ( if (! last_path_separator)
  510.             ; No drive:path specified, clear pctags_env_path.
  511.             ( = pctags_env_path "" )
  512.         ; else
  513.             (
  514.                 ; Extract drive:path, save in pctags_env_path
  515.                 ( = pctags_env_path (substr file_spec 1 last_path_separator) )
  516.             )
  517.         )
  518.  
  519.     )   ; 1
  520. )   ; macro parse_file_spec
  521.  
  522. ;***************************************
  523. ; Macro : dos_shell
  524. ; Syntax: ( dos_shell command_line file_spec )
  525. ; Entry : Command_line is the DOS command line to have the shell execute.  It
  526. ;           may contain special parameters documented below.  Case of the
  527. ;           special parameters is significant.  It may also contain the DOS
  528. ;           standard output redirection characters > or >>, but the command
  529. ;           must then be bracketed with double quotes.  The quotes will be
  530. ;           removed before sending the command line to DOS.
  531. ; Exit  : The command will have been executed.  No return value is sent back.
  532. ; Special command_line parameters:
  533. ;           %s      - entire file specification of desired file (file_spec parm)
  534. ;           %d      - drive of desired file
  535. ;           %p      - path (no drive) of desired file (no terminating (back)slash)
  536. ;           %f      - filename of desired file
  537. ;           %c      - current directory (in drive:path format suitable for CD'ing)
  538. ;           %u      - user-defined substitution string
  539. ;           %%      - single %
  540.  
  541. ( macro dos_shell
  542.     (   ; 1
  543.  
  544.         ( int       last_index
  545.                     parm_index
  546.         )
  547.         ( string    command_line
  548.                     current_dir
  549.                     drive
  550.                     filename
  551.                     file_spec
  552.                     path
  553.                     sub_str
  554.         )
  555.  
  556.  
  557.         ; Get parameters
  558.         ( get_parm 0 command_line )
  559.         ( get_parm 1 file_spec )
  560.  
  561.         ; Remove any leading and trailing whitespace from command line
  562.         ( = command_line (ltrim (trim command_line)) )
  563.  
  564.         ; If command_line is bracketed by double quotes, remove them
  565.         ( if (&& (== (substr command_line 1 1) "\"")
  566.                  (== (substr command_line (strlen command_line)) "\""))
  567.             ; Remove double quotes
  568.             ( = command_line (substr command_line 2 (- (strlen command_line) 2)) )
  569.         )
  570.  
  571.         ; Create special parameter strings
  572.         ; Get drive:path
  573.         ( = path (substr file_spec 1 (rindex file_spec (substr file_spec 3 1))) )
  574.  
  575.         ; If not in root, truncate last "\"
  576.         ( if (> (strlen path) 3)
  577.             ; Truncate last path separator
  578.             ( = path (substr path 1 (- (strlen path) 1)))
  579.         )
  580.  
  581.         ; Break drive:path into separate strings
  582.         ( = drive (substr path 1 2) )       ; %d special parm
  583.         ( = path (substr path 3) )          ; %p special parm
  584.  
  585.         ; Get filename only (%f special parm)
  586.         ( = filename (substr file_spec (+ (rindex file_spec (substr file_spec 3 1)) 1)) )
  587.  
  588.         ; Get current directory
  589.         ( getwd "" current_dir )            ; %c special parm
  590.  
  591.         ; Parse command line, replacing special parameters
  592.         ( = parm_index 1 )
  593.         ( while (&& (= parm_index (+ (- parm_index 1) (index (substr command_line parm_index) "%")))
  594.                     (!= parm_index last_index))
  595.             (   ; 2
  596.                 ; Save current parm_index
  597.                 ( = last_index parm_index )
  598.  
  599.                 ; Get substitution string
  600.                 ( switch (substr command_line (+ parm_index 1) 1)
  601.                     "s"     ; Entire file specification of desired file
  602.                             ( = sub_str file_spec )
  603.                     "d"     ; Drive of desired file
  604.                             ( = sub_str drive )
  605.                     "p"     ; Path (no drive) of desired file
  606.                             ( = sub_str path )
  607.                     "f"     ; Filename of desired file
  608.                             ( = sub_str filename )
  609.                     "c"     ; Current directory
  610.                             ( = sub_str current_dir )
  611.                     "u"     ; User-defined
  612.                             ( if (! (get_parm NULL sub_str "Enter sub string: "))
  613.                                 ; User pressed <Esc> key, use empty string
  614.                                 ( = sub_str "" )
  615.                             )
  616.                     "%"     ; Single percent sign
  617.                             ( = sub_str "%" )
  618.                     ; default
  619.                     NULL    ; Replace with empty string
  620.                             ( = sub_str "" )
  621.                 )
  622.  
  623.                 ; Replace special parameter with substitution string
  624.                 ( = command_line (+ (substr command_line 1 (- parm_index 1))
  625.                          (+ sub_str (substr command_line (+ parm_index 2)))) )
  626.  
  627.                 ; Advance past first char of replacement (in case replacement
  628.                 ; was a single "%")
  629.                 ( ++ parm_index )
  630.  
  631.             )   ; 2
  632.         )
  633.  
  634.         ; If ">&" found in command_line, display message (Brief will not alter
  635.         ; the screen when redirection char (> or >>) are followed by ampersand).
  636.         ( if (index command_line ">&")
  637.             ; Let user know what's going on
  638.             ( message "Executing RETROEXEC command" )
  639.         )
  640.  
  641.         ; Send command line to DOS for execution
  642.         ( dos command_line )
  643.  
  644.     )   ; 1
  645. )   ; macro dos_shell
  646.  
  647. ;***************************************
  648. ; Macro : file_already_loaded
  649. ; Syntax: ( file_already_loaded filename )
  650. ; Entry : filename is the complete name (using backslashes as path separators)
  651. ;           of a file
  652. ; Exit  : TRUE if filename is already loaded into a BRIEF buffer, else FALSE
  653.  
  654. ( macro file_already_loaded
  655.     (
  656.  
  657.         ( int       org_buff_id
  658.                     already_loaded
  659.                     cycle
  660.         )
  661.  
  662.         ( string    filename
  663.                     curr_name
  664.         )
  665.  
  666.  
  667.         ; Get argument
  668.         ( get_parm 0 filename )
  669.  
  670.         ; Save current buffer id
  671.         ( = org_buff_id (inq_buffer) )
  672.  
  673.         ; Set default return value
  674.         ( = already_loaded FALSE )
  675.  
  676.         ; Cycle thru all buffers, looking for our file
  677.         ( = cycle TRUE )
  678.         ( while cycle
  679.             (
  680.                 ; Get the complete name of the file
  681.                 ; associated with the current buffer
  682.                 ( inq_names curr_name )
  683.  
  684.                 ; Convert any slash path separators to backslashes and convert
  685.                 ; chars to lowercase
  686.                 ( = curr_name (lower (convert_slashes curr_name)) )
  687.  
  688.                 ; Compare current filename to the filename we're looking for
  689.                 ( if (== curr_name filename)
  690.                     (
  691.                         ; Set return code to indicate the file is already loaded
  692.                         ( = already_loaded TRUE )
  693.                     )
  694.                 )
  695.  
  696.                 ; Advance to the next buffer
  697.                 ( set_buffer (next_buffer) )
  698.  
  699.                 ; If we've cycled back around to the
  700.                 ; starting buffer, exit while-loop
  701.                 ( if (== org_buff_id (inq_buffer))
  702.                     (
  703.                         ( = cycle FALSE )
  704.                     )
  705.                 )
  706.             )
  707.         )
  708.  
  709.         ; Return already_loaded flag
  710.         ( return already_loaded )
  711.  
  712.     )
  713. )   ; macro file_already_loaded
  714.  
  715. ;***************************************
  716. ; Macro : position_line_within_window
  717. ; Syntax: ( position_line_within_window )
  718. ; Entry : None.
  719. ; Exit  : If current window is at least five lines high, the current line
  720. ;           is positioned on the third line in the window.  If the window
  721. ;           is less than five lines high, no change.
  722.  
  723. ( macro position_line_within_window
  724.     (   ; 1
  725.  
  726.         ( int       row )
  727.  
  728.         ; If possible, position current line on third in window.  Window
  729.         ; must be at least five lines high to do so.
  730.         ; Get the size of the window
  731.         ( inq_window_size row )
  732.         ( if (>= row 5)
  733.             (   ; 2
  734.                 ; Current line must be at least third line in file
  735.                 ( inq_position row )
  736.                 ( if (>= row 3)
  737.                     (   ; 3
  738.                         ; Display current line in third line of window
  739.                         ( set_top_left (- row 2) )
  740.                     )   ; 3
  741.                 )
  742.             )   ; 2
  743.         )
  744.  
  745.     )   ; 1
  746. )   ; macro position_line_within_window
  747.  
  748. ;***************************************
  749. ; Macro : pctags_main
  750. ; Syntax: ( pctags_main function_name )
  751. ; Entry : function_name = function name to locate and retrieve the file in
  752. ;           which it is declared.
  753. ; Exit  : Non-zero value if function definition is found, file containing the
  754. ;           definition is loaded and cursor is placed on the definition's
  755. ;           line.
  756. ;         Else return zero.
  757. ; Description :
  758. ;         RETRO operation is performed.  This requires the following steps:
  759. ;               -- Cycle through all required tagfiles.  Default = *.tag or
  760. ;                       all tagfiles specified in RETRO environment variable
  761. ;                       which may contain multiple file specs, each with
  762. ;                       wildcards, separated by semicolons.  For example,
  763. ;                       SET RETRO=c:\brief\tagfiles\*.tag;c:\prog\*.tag
  764. ;               -- Search each tagfile for the tagname.
  765. ;               -- If not found in any tagfile, display message and quit.
  766. ;               -- If found, get name of file and definition line from tagfile.
  767. ;               -- Close tagfile.
  768. ;               -- Load file for editing.
  769. ;               -- If file cannot be found and environment varible RETROEXEC is
  770. ;                       defined, execute the command line value assigned to it.
  771. ;                       Try to load the file again.
  772. ;               -- Search file for definition line.
  773. ;               -- Place definition line on third line in window (if possible).
  774. ;               -- If any of these operations fail, display appropriate error
  775. ;                       message and quit.
  776. ;
  777. ; Use of Global Variables:
  778. ;       pctags_first_call       -- assign
  779. ;       pctags_tagname_case     -- access
  780.  
  781. ( macro pctags_main
  782.     (   ; 1
  783.  
  784. #define SYSTEM_BUFF         1
  785. #define NONSYSTEM_BUFF      0
  786.  
  787. #define PAUSE               1
  788. #define NO_PAUSE            0
  789.  
  790. #define NO_RE               0
  791. #define REMOVE              0
  792.  
  793.         ( int       buff_id
  794.                     column
  795.                     continue_search
  796.                     decl_start
  797.                     exec_env
  798.                     file_already_in_buffer
  799.                     file_start
  800.                     found_match
  801.                     line_number
  802.                     org_buff_id
  803.                     row
  804.                     special_chars
  805.         )
  806.         ( string    decl_line
  807.                     env_pctagsexec
  808.                     file_spec
  809.                     function_name
  810.                     line
  811.                     tagfile_name
  812.         )
  813.  
  814.  
  815.         ; Get function name we're looking for (passed as a parameter)
  816.         ( get_parm 0 function_name )
  817.  
  818.         ; Save current context
  819.         ( = org_buff_id (inq_buffer) )          ; Save current buffer id
  820.  
  821.         ; Cycle thru all RETRO (or default) tagfiles until done or match found
  822.         ( = found_match FALSE )
  823.         ( = pctags_first_call FIRST_CALL )      ; Global flag for (get_tagfile)
  824.         ( while (&& (! found_match) (!= (= tagfile_name (get_tagfile)) ""))
  825.             (   ; 2
  826.                 ; Create tagfile buffer and make it current
  827. ;( message "main: tagfile=%s" tagfile_name )
  828. ;( while (!= 32 (& (read_char) 0xff)) )
  829.                 ( = buff_id (create_buffer "pctags" tagfile_name SYSTEM_BUFF) )
  830.                 ( set_buffer buff_id )
  831.  
  832.                 ; Set up a loop to search through the tagfile.  Multiple
  833.                 ; searches may be required because a match COULD be found on a
  834.                 ; string in the tagfile other than the function-name portion of
  835.                 ; a line.
  836.                 ; Search tagfile for function name
  837.                 ( message "Searching %s" tagfile_name )
  838.                 ( = continue_search TRUE )
  839.                 ( while continue_search
  840.                     (   ; 3
  841.                         ; Search tagfile for function name
  842.                         ( if (<= (search_fwd function_name NO_RE pctags_tagname_case) 0)
  843.                             (   ; 4a
  844.                                 ; Did not find function name in this tagfile.
  845.                                 ; Set current buffer back to original and remove
  846.                                 ; tagfile from memory.
  847.                                 ( set_buffer org_buff_id )
  848.                                 ( delete_buffer buff_id )
  849.  
  850.                                 ; Stop searching this tagfile, cycle to next one
  851.                                 ( = continue_search FALSE )
  852.                             )   ; 4a
  853.                         ; else
  854.                             (   ; 4b
  855.                                 ; Found a match.
  856.                                 ; The match MUST start in the first column.  If
  857.                                 ; it doesn't then a match was found somewhere
  858.                                 ; other than in the function-name portion of the
  859.                                 ; line.
  860.                                 ( inq_position row column )
  861.                                 ( if (!= column 1)
  862.                                     (   ; 5a
  863.                                         ; Advance buffer position so we don't
  864.                                         ; keep finding the same match.
  865.                                         ( next_char )
  866.                                         ; Continue searching tagfile
  867.                                     )   ; 5a
  868.                                 ; else
  869.                                     (   ; 5b
  870.                                         ; Found a match!
  871.                                         ; Stop searching this and all other
  872.                                         ; tagfiles
  873.                                         ( = continue_search FALSE ) ; This tagfile
  874.                                         ( = found_match TRUE )      ; All tagfiles
  875.  
  876.                                         ; Read matching line, including newline
  877.                                         ( = line (read) )
  878.  
  879.                                         ; Done with tagfile.  Reset buffer id
  880.                                         ; and close it.
  881.                                         ( set_buffer org_buff_id )
  882.                                         ( delete_buffer buff_id )
  883.  
  884.                                         ; Format of line:
  885.                                         ; Column 1: Function name searching for (variable length)
  886.                                         ; Single space terminator
  887.                                         ; Optional RETRO commands (! and/or #)
  888.                                         ; Complete file specification of file containing
  889.                                         ;   definition of preceding function (variable length)
  890.                                         ; Single space terminator
  891.                                         ; Caret (^) character signifying the start of the
  892.                                         ;   definition line
  893.                                         ; Entire line from preceding file that defines the
  894.                                         ;   column-1 function (variable length)
  895.                                         ; End of line is the last character in the definition
  896.                                         ;   line (i.e. newline)
  897.                                         ; As an example:
  898.                                         ; "function c:\dir\file.c ^int function( arg1, arg2)\n"
  899.  
  900.                                         ; Determine starting indices of file spec
  901.                                         ; and definition line
  902.                                         ( = file_start (+ (index line " ") 1) )
  903.                                         ( = decl_start (+ (index (substr line file_start) " ") file_start) )
  904.  
  905.                                         ; Extract file spec and decl line
  906.                                         ( = file_spec (substr line file_start (- (- decl_start file_start) 1)) )
  907.                                         ; Note: Skip leading '^' of decl line
  908.                                         ( = decl_line (substr line (++ decl_start)) )
  909.  
  910.                                         ; Check file_spec for special leading characters
  911.                                         ( = continue_search TRUE )
  912.                                         ( = exec_env FALSE )
  913.                                         ( = line_number FALSE )
  914.                                         ( = special_chars 1 )   ; Base one
  915.                                         ( while continue_search
  916.                                             (   ; 6
  917.                                                 ( switch (substr file_spec special_chars 1)
  918.                                                     "!" (   ; If file_spec not found,
  919.                                                             ; execute RETROEXEC environment
  920.                                                             ; variable command line.  This is
  921.                                                             ; usually used to extract the file
  922.                                                             ; from a source-control library.
  923.                                                             ( = exec_env TRUE )
  924.  
  925.                                                             ; Increment index
  926.                                                             ( ++ special_chars )
  927.                                                         )
  928.  
  929.                                                     "#" (   ; Line number of definition is
  930.                                                             ; stored in tagfile instead of
  931.                                                             ; line contents.
  932.                                                             ( = line_number TRUE )
  933.                                                             ( ++ special_chars )
  934.                                                         )
  935.  
  936.                                                     ; default
  937.                                                     NULL    ; Stop parsing special chars
  938.                                                         ( = continue_search FALSE )
  939.                                                 )
  940.                                             )   ; 6
  941.                                         )
  942.  
  943.                                         ; Remove all leading special chars from file_spec
  944.                                         ( = file_spec (substr file_spec special_chars) )
  945.  
  946.                                         ; Verify that file_spec exists.
  947.                                         ( if (! (exist file_spec))
  948.                                             (   ; 6
  949.                                                 ; If exec_env active, get RETROEXEC value
  950.                                                 ( if exec_env
  951.                                                     (   ; 7
  952.                                                         ( if (!= (= env_pctagsexec (inq_environment "RETROEXEC")) "")
  953.                                                             ; Execute the variable's value
  954.                                                             ( dos_shell env_pctagsexec file_spec )
  955.                                                         )
  956.                                                     )   ; 7
  957.                                                 )
  958.  
  959.                                                 ; Check for file's existence now
  960.                                                 ( if (! (exist file_spec))
  961.                                                     (   ; 7
  962.                                                         ( error "%s does not exist.  Update tagfile."
  963.                                                                 file_spec )
  964.                                                         ( beep )
  965.                                                         ( return UNSUCCESSFUL )
  966.                                                     )   ; 7
  967.                                                 )
  968.                                             )   ; 6
  969.                                         )
  970.  
  971.                                         ; Determine if file is already loaded
  972.                                         ( = file_already_in_buffer (file_already_loaded file_spec) )
  973.  
  974.                                         ; Load the file containing the function definition.
  975.                                         ( edit_file file_spec )
  976.  
  977.                                         ; Get Brief's file-spec format
  978.                                         ( inq_names file_spec )
  979.  
  980.                                         ; Save current position in file in case we have
  981.                                         ; to return to it, force to top of file
  982.                                         ( save_position )
  983.                                         ( top_of_buffer )
  984.  
  985.                                         ; Searching for line contents or line number?
  986.                                         ( if (== line_number TRUE)
  987.                                             (   ; 6a
  988.                                                 ; Goto specified line number in source file
  989.                                                 ( goto_line (atoi decl_line) )
  990.  
  991.                                                 ; Position line
  992.                                                 ( position_line_within_window )
  993.  
  994.                                                 ; Display filename
  995.                                                 ( message "File: %s" file_spec )
  996.  
  997.                                                 ; Discard saved file position from
  998.                                                 ; stack (do not restore).
  999.                                                 ( restore_position REMOVE )
  1000.  
  1001.                                             )   ; 6a
  1002.                                         ; else
  1003.                                             (   ; 6b
  1004.                                                 ; Search for definition line.
  1005.                                                 ( while TRUE
  1006.                                                     (   ; 7
  1007.                                                         ( if (> (search_fwd decl_line
  1008.                                                                  NO_RE      CASE_SENSITIVE) 0)
  1009.                                                             (   ; 8a
  1010.                                                                 ; Found a match
  1011.                                                                 ; Match must be at start of line
  1012.                                                                 ; to be valid.
  1013.                                                                 ( inq_position row column )
  1014.                                                                 ( if (!= column 1)
  1015.                                                                     (   ; 9
  1016.                                                                         ; Invalid match, keep searching
  1017.                                                                         ; Advance buffer position so we
  1018.                                                                         ; won't keep finding the same
  1019.                                                                         ; match.
  1020.                                                                         ( next_char )
  1021.                                                                         ( continue )    ; Back up to while-loop
  1022.                                                                     )   ; 9
  1023.                                                                 )
  1024.  
  1025.                                                                 ; Found function definition!
  1026.                                                                 ( position_line_within_window )
  1027.  
  1028.                                                                 ; Display filename
  1029.                                                                 ( message "File: %s" file_spec )
  1030.  
  1031.                                                                 ; Discard saved file position
  1032.                                                                 ; from stack (do not restore).
  1033.                                                                 ( restore_position REMOVE )
  1034.  
  1035.                                                                 ; Break out of while-loop
  1036.                                                                 ( break )
  1037.  
  1038.                                                             )   ; 8a
  1039.                                                         ; else
  1040.                                                             (   ; 8b
  1041.                                                                 ; Definition line not found in file.
  1042.                                                                 ; Note: Go through this process of
  1043.                                                                 ; constructing the error message to
  1044.                                                                 ; maintain compatibility with previous
  1045.                                                                 ; versions of BRIEF that did not
  1046.                                                                 ; accept more than one string
  1047.                                                                 ; parameter.
  1048.                                                                 ; Construct output string.
  1049.                                                                 ( sprintf line "Update %s with " tagfile_name )
  1050.                                                                 ( = line (+ line file_spec) )
  1051.  
  1052.                                                                 ; Display string
  1053.                                                                 ( error line )
  1054.                                                                 ( beep )
  1055.  
  1056.                                                                 ; Recover by deleting this file
  1057.                                                                 ; and returning to the original
  1058.                                                                 ; context.
  1059.                                                                 ; Get the decl-file's buffer id
  1060.                                                                 ( = buff_id (inq_buffer) )
  1061.  
  1062.                                                                 ; If the decl-file was in the
  1063.                                                                 ; original buffer, do not re-
  1064.                                                                 ; attach as doing so will screw
  1065.                                                                 ; up the top-left corner of the
  1066.                                                                 ; window.
  1067.                                                                 ( if (!= buff_id org_buff_id)
  1068.                                                                     (
  1069.                                                                         ; Attach the original
  1070.                                                                         ; buffer to the current
  1071.                                                                         ; window.
  1072.                                                                         ( attach_buffer org_buff_id )
  1073.  
  1074.                                                                         ; Set original buffer to
  1075.                                                                         ; current buffer.
  1076.                                                                         ( set_buffer org_buff_id )
  1077.                                                                     )
  1078.                                                                 )
  1079.  
  1080.                                                                 ; If file had to be loaded from
  1081.                                                                 ; disk, delete it.
  1082.                                                                 ( if (! file_already_in_buffer)
  1083.                                                                     (
  1084.                                                                         ( delete_buffer buff_id )
  1085.                                                                     )
  1086.                                                                 )
  1087.  
  1088.                                                                 ; Restore original position in file
  1089.                                                                 ( restore_position )
  1090.                                                                 ; Return error code
  1091.                                                                 ( return UNSUCCESSFUL)
  1092.                                                             )   ; 8b
  1093.                                                         )
  1094.                                                     )   ; 7
  1095.                                                 )
  1096.                                             )   ; 6b
  1097.                                         )
  1098.                                     )   ; 5b
  1099.                                 )
  1100.                             )   ; 4b
  1101.                         )
  1102.                     )   ; 3
  1103.                 )
  1104.             )   ; 2
  1105.         )
  1106.  
  1107.         ; If match not found in any tagfile, that's not good...
  1108.         ( if found_match
  1109.             ; Congratulations
  1110.             ( return SUCCESSFUL )
  1111.         ; else
  1112.             (   ; 2
  1113.                 ; Display message
  1114.                 ; Note: function_name ends with a single blank char
  1115.                 ( message "%snot found." function_name )
  1116.                 ( return UNSUCCESSFUL )
  1117.             )   ; 2
  1118.         )
  1119.  
  1120.     )   ;1
  1121. )   ; macro pctags_main
  1122.  
  1123. ;***************************************
  1124.