home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w055 / 4.ddi / SOURCES.LIF / ERRORFIX.PEL < prev    next >
Encoding:
Text File  |  1990-09-27  |  32.7 KB  |  1,202 lines

  1. # $Header:   P:/source/ppee/macros/errorfix.pev   1.85   26 Sep 1990 17:08:52   skipr  $
  2.  
  3. ##############################################################################
  4. #
  5. #           Sage Software - POLYTRON Division
  6. #             1700 NW 167th Place
  7. #               Beaverton, OR 97006
  8. #
  9. #   Copyright 1990, Sage Software, Inc.
  10. #
  11. #   Permission is hereby granted for licensed users of Sage Professional
  12. #   Editor and PolyAwk to copy and modify this source code for their own
  13. #   personal use.  These derivative works may be distributed only to other
  14. #   licensed Sage Professional Editor and PolyAwk users.  All other usage
  15. #   is prohibited without express written permission from Sage Software.
  16. #
  17. ##############################################################################
  18.  
  19. #### $Workfile:   errorfix.pel  $: Compiling and Error locating utilities
  20.  
  21.  
  22. ## Overview of compile/errorfix language support
  23. ##
  24. ## The two most essential global functions defined here are 
  25. ## "compile_buffer()" and "goto_next_error()".  Compile_buffer uses the 
  26. ## name of the current buffer to determine what language is being used, 
  27. ## and then issues a command line to the shell invoking the appropriate 
  28. ## compiler.  Upon completion of the shell process, the captured error 
  29. ## output is passed on to the goto_next_error() function.  
  30. ## goto_next_error() knows the syntax of the error messages produced by 
  31. ## each compiler, and uses that information to find the name of the 
  32. ## source file where the error occurred, and the location within that 
  33. ## file.  The goto_next_error() function may also be invoked again 
  34. ## independently from the keyboard, where it will scan forward in the 
  35. ## error listing for the next error encountered.
  36. ##
  37. ## To add support for a new compiler, the arrays "compiler_cmd_array" 
  38. ## and "compiler_err_array" must be augmented and, depending on the 
  39. ## error message syntax of the new compiler, a new compiler-specific 
  40. ## error message parsing function may have to be added.  The function 
  41. ## add_compiler() can be used to update the compiler arrays.  It may be 
  42. ## called from within the user's local_setup() function, or from within 
  43. ## the sageedit.cfg file.  For more information on adding a new error 
  44. ## message function, see the comments in function errorInfo() near the 
  45. ## end of this file.
  46. ##
  47. ## ---------------------------------------------------------------------
  48.  
  49. ##    Clipper & FORCE compiler support enhancements provided by
  50. ##    Pedro P. Polakoff III of 3P Software, Inc.
  51.  
  52.  
  53. ## The following arrays contain compiler specific information:
  54. global    compiler_err_array
  55. global    compiler_cmd_array
  56.  
  57. local    searchFlag = 0x0034    # ignore case | regex | forward
  58.  
  59. global    errorSrcName
  60. local    errorLine
  61. local    errorColumn
  62. local    errorText
  63. local    errorCompleteText
  64. local    errorsFound
  65.  
  66. local    errorBuffer
  67. local    originalBuffer
  68. local    switchedBuffer
  69. local    errorInfoPrefix
  70.  
  71. ## init_compilers()
  72. #
  73. # define lists of known compilers, file extensions and compiler command lines
  74. #
  75. global function init_compilers(){
  76.     local    ext
  77.     local    aeName
  78.  
  79.     ## Two arrays are initialized here:
  80.     ##
  81.     ##
  82.     ## The first array, compiler_cmd_array, defines the command line to 
  83.     ## use for each filename extension type.  Each command line is a 
  84.     ## string which will be executed by the shell after macro 
  85.     ## substititions have been performed.  Valid command line macros are
  86.     ## as follows:
  87.     ##
  88.     ## $< - expands to complete name of source file
  89.     ## $r - expands to root (basename) of source file, less extension
  90.     ## $e - expands to extension of source file, excluding "."
  91.     ## $p - expands to drive and path of source file (ends in "\")
  92.     ##
  93.     ## for example, given the file "c:\hork\file.ext" :
  94.     ##    $< == "c:\hork\file.ext"
  95.     ##    $r == "file"
  96.     ##    $e == "ext"
  97.     ##    $p == "c:\hork\"
  98.     ##
  99.     ##
  100.     ## The second array, compiler_err_array, defines the filename 
  101.     ## extensions used by each language.  The array subscripts are the 
  102.     ## valid extensions associated with a given language.  The value of 
  103.     ## the array element is the compiler type string, which is used to 
  104.     ## determine which error message parsing function to use.  This 
  105.     ## string is will become the base filename of the error message 
  106.     ## file.  The compiler type string may be up to 8 characters in 
  107.     ## length, and must be a valid base filename.
  108.     ##
  109.     ## -----------------------------------------------------------------
  110.  
  111.     if ( compiler_cmd_array ){
  112.         return        # already initialized
  113.     }
  114.  
  115.     ## Sage/POLYTRON Pel compiler
  116.     ext = ".pel"
  117.     compiler_err_array[ ext ] = "pel"    # use "pelErrorInfo" function
  118.     # find the full name of the current sageedit.ae file
  119.     if ( (aeName = locate_sageedit_file( SAGEEDIT_FILE_AE ))) {
  120.         aeName = " -o " aeName
  121.     }
  122.     compiler_cmd_array[ ext ] = "pel" aeName " -aisv $<"    # shell cmd
  123.  
  124.     ## Sage/POLYTRON Awk Toolkit compiler
  125.     ext = ".awk"
  126.     compiler_err_array[ ext ] = "none"    # no error info function is available
  127.     compiler_cmd_array[ ext ] = "awkc $<"
  128.  
  129.     ## Sage PolyMake
  130.     ext = ".mak"
  131.     compiler_err_array[ ext ] = "polymake"    # use "genericErrorInfo()"
  132.     compiler_cmd_array[ ext ] = "make -f $<"
  133.  
  134.     ## Microsoft C
  135.     ext = ".c"
  136.     compiler_err_array[ ext ] = \
  137.     compiler_err_array[ ".h" ]= "c"        # use "genericErrorInfo()"
  138.     # following command outputs to NUL to check syntax only
  139.     compiler_cmd_array[ ext ] = "cl -c -Fonul $<"
  140.  
  141.     ## Zortech C
  142.     #ext = ".c"
  143.     #compiler_err_array[ ext ] = \
  144.     #compiler_err_array[ ".h" ]= "zortech"    # use "zortechErrorInfo()"
  145.     #compiler_cmd_array[ ext ] = "ztc -c -r $<"
  146.  
  147.     ## Zortech C++
  148.     ext = ".cpp"
  149.     compiler_err_array[ ext ] = "zortech"    # use "zortechErrorInfo()"
  150.     compiler_cmd_array[ ext ] = "ztc -c -cpp -r $<"
  151.  
  152.     ## Turbo C
  153.     ext = ".c"
  154.     #compiler_err_array[ ext ] = \
  155.     #compiler_err_array[ ".h" ]= "turboc"    # use "turbocErrorInfo()"
  156.     #compiler_cmd_array[ ext ] = "tcc -c -w $<"
  157.  
  158.     ## Turbo C++
  159.     ext = ".cpp"
  160.     #compiler_err_array[ ext ] = "turboc"    # use "turbocErrorInfo()"
  161.     #compiler_cmd_array[ ext ] = "cpp $<"
  162.  
  163.     ## Microsoft Masm
  164.     ext = ".asm"
  165.     compiler_err_array[ ext ] = "asm"    # use "genericErrorInfo()"
  166.     compiler_cmd_array[ ext ] = "masm $<,nul,asm.err;"
  167.  
  168.     ## Turbo Pascal
  169.     ext = ".pas"
  170.     compiler_err_array[ ext ] = "pas"    # use "genericErrorInfo()"
  171.     compiler_cmd_array[ ext ] = "tpc $<"
  172.  
  173.     ## Advantage ADA
  174.     ext = ".ada"
  175.     compiler_err_array[ ext ] = "ada"    # use "adaErrorInfo()"
  176.     compiler_cmd_array[ ext ] = "ada $<"
  177.  
  178.     ## Microsoft Quick BASIC
  179.     ext = ".bas"
  180.     compiler_err_array[ ext ] = "bas"    # use "genericErrorInfo()"
  181.     compiler_cmd_array[ ext ] = "qb $<"
  182.  
  183.     ## Lahey FORTRAN 77
  184.     ext = ".for"
  185.     compiler_err_array[ ext ]= "lahey"    # use "laheyErrorInfo()"
  186.     compiler_cmd_array[ ext ]= "f77l $<"
  187.     ext = ".f"
  188.     compiler_err_array[ ext ]= "lahey"
  189.     compiler_cmd_array[ ext ]= "f77l $<"
  190.  
  191.     ## COBOL
  192.     ext = ".cbl"
  193.     compiler_err_array[ ext ] = "none"    # no error info function is available
  194.     compiler_cmd_array[ ext ] = "cobol $<"
  195.  
  196.     ## dBASE dialect compilers
  197.     #
  198.     if ( D_DIALECT != "clipper87"    \
  199.       && D_DIALECT != "clipper50"    \
  200.       && D_DIALECT != "force" ) {
  201.         D_DIALECT = "clipper50"    # default if none defined
  202.     }
  203.     ext = ".prg"
  204.     if ( D_DIALECT == "clipper87" ) {        # Clipper Summer 87
  205.         # use "clipper87ErrorInfo()"
  206.         compiler_err_array[ ext ]    = \
  207.         compiler_err_array[ ".pre" ]    = "clipper87"
  208.         # compile with Clipper Summer 87 compiler or preprocessor
  209.         # depending on the filename extension
  210.         compiler_cmd_array[ ext ]    = "clipper $< -m -s"
  211.         compiler_cmd_array[ ".pre" ]    = "pre $<"
  212.  
  213.     } else if ( D_DIALECT == "clipper50" ) {    # Clipper 5.0
  214.         # use "clipper5ErrorInfo()" and version 5.0 compiler
  215.         compiler_err_array[ ext ]    = \
  216.         compiler_err_array[ ".ch" ]    = \
  217.         compiler_err_array[ ".ppo" ]    = "clipper5"
  218.         compiler_cmd_array[ ext ]    = "clipper $< /s /w /m"
  219.  
  220.     } else if ( D_DIALECT == "force" ) {        # FORCE compiler
  221.         compiler_err_array[ ext ]    = \
  222.         compiler_err_array[ ".hdr" ]    = "force"
  223.         compiler_cmd_array[ ext ]    = "force $<"
  224.     }
  225. }
  226.  
  227.  
  228. ## reset_compilers()
  229. #
  230. #  forces a rebuild of the compiler_cmd_array & compiler_err_array
  231. #  required to change compilers from buffer to buffer or within
  232. #  an editing session.
  233. #
  234. global function reset_compilers(){
  235.     # init electric file extension list
  236.     if ( !extensions_initialized ) {
  237.         initialize_extensions()
  238.     }
  239.  
  240.     # prompt for dBase dialect
  241.     if ( buffer_filename ~ file_extensions[ "dbase" ]    \
  242.       || buffer_filename ~ file_extensions[ "clipper87" ]    \
  243.       || buffer_filename ~ file_extensions[ "clipper50" ]    \
  244.       || buffer_filename ~ file_extensions[ "force" ] ) {
  245.         dBaseDialect()
  246.     }
  247.  
  248.     # re-init compilers
  249.     delete compiler_err_array
  250.     delete compiler_cmd_array
  251.     init_compilers()
  252. }
  253.  
  254.  
  255. ## edit_compiler()
  256. #
  257. # edits a compiler command string
  258. #
  259. global function edit_compiler( ext ) {
  260.     local    cmd
  261.  
  262.     init_compilers()
  263.  
  264.     if ( ext ) {
  265.         ext = tolower( ext )
  266.         if ( substr( ext, 1, 1 ) != "." ){
  267.             ext = "." ext    # prefix with "." if necessary
  268.         }
  269.         if ( length(ext) <= 1 || length(ext) > 4 ) {
  270.             return ""
  271.         }
  272.     } else {
  273.         # default is filename extension of current buffer
  274.         ext = path_ext( buffer_filename )
  275.     }
  276.  
  277.     # prompt for compiler command string
  278.     if ( ext in compiler_cmd_array ){
  279.         cmd = compiler_cmd_array[ ext ]
  280.     }
  281.     cmd = factory_prompt( \
  282.         "Enter compiler command (\"$<\" == current buffer_filename)",
  283.         "COMPILE",
  284.         "cmd: ",
  285.         cmd )
  286.  
  287.     # update the compiler command array
  288.     if ( cmd ) {
  289.         compiler_cmd_array[ ext ] = cmd
  290.     }
  291.     return cmd
  292. }
  293.  
  294.  
  295. ## add_compiler()                        #PUBLIC
  296. #
  297. # adds information about a compiler to that defined in init_compilers()
  298. #
  299. global function add_compiler( ext_list, cmd_line, error_ruleset ){
  300.     local    tmp_array
  301.     local    ext
  302.     local    status = 0
  303.     local    i
  304.  
  305.     # check required arguments
  306.     if ( !ext_list || !cmd_line ){
  307.         warning( "missing argument in call to add_compiler" )
  308.     }
  309.  
  310.     init_compilers()
  311.  
  312.     # process list of source filename extensions
  313.     gsub( /[ \t,]+/, " ", ext_list )    # change delimiters to spaces
  314.     split( ext_list, tmp_array, " " )
  315.     for ( i in tmp_array ){
  316.         ext = tolower( tmp_array[ i ] )
  317.         if ( substr( ext, 1, 1 ) != "." ){
  318.             ext = "." ext    # prefix with "." if necessary
  319.         }
  320.         if ( length(ext) > 1 && length(ext) <= 4 ) {
  321.             if ( !status ) {
  322.                 # add command line for first extension listed
  323.                 status = 1
  324.                 compiler_cmd_array[ ext ] = cmd_line
  325.             }
  326.  
  327.             # add source filename extension
  328.             if ( error_ruleset ) {
  329.                 compiler_err_array[ ext ] =
  330.                         tolower( error_ruleset )
  331.             }
  332.         }
  333.     }
  334. }
  335.  
  336.  
  337. ## compile_buffer()                        #PUBLIC
  338. #
  339. # compile the current buffer
  340. #
  341. global function compile_buffer() {
  342.     local    cmd
  343.     local    ext
  344.     local    outfile
  345.     local    status = -1
  346.  
  347.     # make sure the compile buffer system is initialized
  348.     init_compilers()
  349.  
  350.     ## use the filename extension to decide which compiler to use
  351.  
  352.     ext = path_ext( buffer_filename )
  353.     if ( !ext ){
  354.         # treat the name "makefile" with no extension as if it has
  355.         # a ".mak" extension
  356.         if ( path_fname( buffer_filename ) == "makefile" ) {
  357.             ext = ".mak"
  358.         } else {
  359.             ext = "NULL_ext"
  360.         }
  361.     }
  362.  
  363.     if ( ext in compiler_cmd_array ){
  364.  
  365.         # expand compiler command line macros
  366.         cmd = compiler_cmd_array[ ext ]
  367.         gsub( /\$\</, buffer_filename, cmd )
  368.         gsub( /\$r/, path_fname(buffer_filename), cmd )
  369.         gsub( /\$e/, substr( path_ext(buffer_filename), 2 ), cmd )
  370.         gsub( /\$p/, path_path(buffer_filename), cmd )
  371.  
  372.         # define the error output file
  373.         if ( ext in compiler_err_array ) {
  374.             outfile    = compiler_err_array[ ext ]
  375.         }
  376.         if ( outfile == "" || outfile == "none" ) {
  377.             outfile    = substr( ext, 2 )
  378.         }
  379.         outfile = outfile ".err"
  380.  
  381.     } else {
  382.         warning( "Don't know how to compile %s files.", ext )
  383.         return status
  384.     }
  385.  
  386.     cmd = factory_prompt( \
  387.             "preparing to issue system command : <Enter> to proceed, <Esc> to cancel",
  388.             "COMPILE",
  389.             "cmd: ",
  390.             cmd )
  391.  
  392.     if ( cmd ) {
  393.         # write current buffer to disk if modified
  394.         write_buffer_key()
  395.  
  396.         # make sure there is no old error buffer to confuse us
  397.         if ( errorBuffer ) {
  398.             closeErrorFile()
  399.         }
  400.  
  401.         # invoke the compiler
  402.         status = system_window_command( cmd, outfile )
  403.         if ( outfile ){
  404.             # parse first error message
  405.             goto_next_error( outfile )
  406.             unlink( outfile )
  407.         }
  408.         if ( status < 0 ) {
  409.             message( "Command returned error code %d.", status )
  410.         }
  411.     }
  412.     return status
  413. }
  414.  
  415. # ---------------------------------------------------------------------------
  416.  
  417. ## display_errors()                        #PUBLIC
  418. #
  419. # put up a window containing the error message file
  420. #
  421. global function display_errors( errorFileName, suppressNextError ) {
  422.     local    scanCode, keyCode
  423.     local    prevLine = -1
  424.     local    priorWindow = current_window
  425.     local    w
  426.  
  427.     # create a system buffer containing the error file
  428.     if ( !openErrorFile( errorFileName ) ) {
  429.         return
  430.     }
  431.  
  432.     # create a view for the error list display
  433.     w = create_factory_window( 5, 2, 70, 20,    \
  434.             WINDOW_MENU + WINDOW_SB_RIGHT )
  435.     if ( !w ) {
  436.         return
  437.     }
  438.  
  439.     current_window = w
  440.     current_buffer = errorBuffer
  441.     attach_window_buffer( current_window, errorBuffer )
  442.  
  443.     # check the size of the error buffer for at least one complete line
  444.     if (buffer_size < 3) {
  445.         delete_window()
  446.         if ( priorWindow ) {
  447.             current_window = priorWindow
  448.         }
  449.         notify( "No errors." )
  450.         return
  451.     }
  452.  
  453.     # record line number of current error message in case of Esc key
  454.     save_position()
  455.  
  456.     # start with the error message centered in the display
  457.     center_cursor()
  458.  
  459.     # display instructions in the dialog window
  460.     if ( 0+suppressNextError ){
  461.         message( "Move cursor, <Enter> or <Esc> to exit" )
  462.     } else {
  463.         message( "Move cursor, <Enter> to select, <Esc> to exit" )
  464.     }
  465.  
  466.     # error list command loop
  467.     while ( 1 ) {
  468.         # get the buffer list command
  469.         if ( prevLine != current_line ) {
  470.             raise_anchor()
  471.             drop_anchor( LINE_SELECTION )
  472.             prevLine = current_line
  473.         }
  474.         display_update()
  475.         keyCode = getkey()
  476.         scanCode = shiftr( keyCode, 8 )
  477.  
  478.         # process cursor motion keys
  479.         if ( !keypad_motion( scanCode )) {
  480.             if (keyCode == KEYCODE_ENTER) {
  481.                 break
  482.             }
  483.             if (keyCode == KEYCODE_ESC ) {
  484.                 suppressNextError = 1
  485.                 break
  486.             }
  487.         }
  488.     }
  489.  
  490.     raise_anchor()
  491.  
  492.     if ( suppressNextError ){
  493.         # leave the position in the error file unchanged
  494.         restore_position( 1 )
  495.     } else {
  496.         # move to the start of the current error message
  497.         goto_bol()
  498.         restore_position( 0 )
  499.     }
  500.  
  501.     # remove the window
  502.     delete_window()
  503.     if ( priorWindow ) {
  504.         current_window = priorWindow
  505.     }
  506.  
  507.     # clear the message line
  508.     message( "" )
  509.  
  510.     if ( !suppressNextError ){
  511.         # look up the source of the current error message
  512.         goto_next_error( "", 1 )
  513.     }
  514. }
  515.  
  516.  
  517. ## goto_next_error()                        #PUBLIC
  518. #
  519. # display an individual error message
  520. #
  521.  
  522. global function goto_next_error( errorFileName, suppressDisplayErrors ) {
  523.     local    priorBuffer = current_buffer
  524.     local    dialogWindowToggled
  525.     local    errorLevel
  526.  
  527.     # create a system buffer containing the error file
  528.     if ( !openErrorFile( errorFileName ) ) {
  529.         return 0
  530.     }
  531.  
  532.     # locate the next appropriate error message in the Error list buffer
  533.  
  534.     current_buffer = errorBuffer
  535.     errorLevel = errorInfo()
  536.  
  537.     # move the cursor to the context of the error message
  538.  
  539.     if ( errorLevel > 0 ) {
  540.         errorsFound = TRUE
  541.  
  542.         if ( filemode(errorSrcName) != -1 ) {
  543.             switchedBuffer = current_buffer =    \
  544.                     create_buffer(        \
  545.                         buildpath(errorSrcName), \
  546.                         errorSrcName,    \
  547.                         0 )
  548.             goto_old_line( errorLine )
  549.             current_column = errorColumn
  550.             if ( !errorColumn ) {
  551.                 search( "[^ \t]|$", searchFlag )
  552.             }
  553.             center_cursor()
  554.         } else {
  555.             current_buffer = originalBuffer
  556.             errorText = errorCompleteText
  557.         }
  558.  
  559.         # Display the current error or warning text in the
  560.         # dialog window.
  561.  
  562.         if ( !dialog_window ) {
  563.             dialogWindowToggled = 1
  564.             toggle_dialog( 1 )
  565.         }
  566.  
  567.         if ( errorLevel == 2 ) {
  568.             warning( "%s", errorText )
  569.         } else {
  570.             notify( "%s", errorText )
  571.         }
  572.  
  573.         # take down the dialog window if we had to create one
  574.         if ( dialogWindowToggled ) {
  575.             display_update()
  576.             while( !keyboard_input_pending ) {
  577.                 # wait...
  578.             }
  579.             toggle_dialog( 0 )
  580.         }
  581.  
  582.     } else {
  583.         current_buffer = priorBuffer
  584.         if ( errorLevel == 0 ) {
  585.             # end of error file
  586.             notify( errorsFound            \
  587.                     ? "No more errors"    \
  588.                     : "No errors." )
  589.             if ( emulation_mode == "brief" ) {
  590.                 current_buffer = errorBuffer
  591.                 goto_buffer_top()
  592.                 current_buffer = priorBuffer
  593.             }
  594.         } else if ( !(0+suppressDisplayErrors) ) {
  595.             # extension type is unknown
  596.             display_errors( "", 1 )
  597.         }
  598.         # closeErrorFile()
  599.     }
  600.  
  601.     return errorLevel
  602. }
  603.  
  604.  
  605. ## openErrorFile()
  606. #
  607. # Create a system buffer containing the error list file.  Do nothing if
  608. # one already exists.  Also define a variable, errorInfoPrefix, to define
  609. # which xxxErrorInfo function to use.
  610. #
  611.  
  612. local function openErrorFile( errorFileName ){
  613.     local    ext
  614.     local    sourcefile_ext
  615.     local    prevEol
  616.  
  617.     # make sure the compile buffer system is initialized
  618.     init_compilers()
  619.  
  620.     # The errorFileName argument is optional - if the filename for
  621.     # the error file was specifed, use it.
  622.     #
  623.     if ( errorFileName ) {
  624.         if ( errorBuffer ) {
  625.             closeErrorFile()
  626.         }
  627.         if ( filemode(errorFileName) == -1 ) {
  628.             warning( "Cannot open %s", errorFileName )
  629.             return 0
  630.         }
  631.         sourcefile_ext = "." path_fname( errorFileName )
  632.     } else {
  633.  
  634.         # is the corresponding error file buffer already present?
  635.         if ( errorBuffer ) {
  636.             if ( (current_buffer == originalBuffer) ||    \
  637.                     (current_buffer == switchedBuffer) ) {
  638.                 # already present, just return
  639.                 return 1
  640.             }
  641.             closeErrorFile()
  642.         }
  643.  
  644.         # use the current file basename to find the error file
  645.         ext = path_ext( buffer_filename )
  646.         if ( ext == ".err" ) {
  647.             # if the current buffer is an error file, use it.
  648.             errorFileName = buffer_filename
  649.             sourcefile_ext = "." path_fname( buffer_filename )
  650.         } else {
  651.             # otherwise use current basename with .err extension
  652.             errorFileName = path_fname(buffer_filename) ".err"
  653.             if ( ext == "" && errorFileName == "makefile.err" ) {
  654.                 # use ".mak" rules for "makefile"
  655.                 sourcefile_ext = ".mak"
  656.             } else {
  657.                 sourcefile_ext = ext
  658.             }
  659.         }
  660.  
  661.         # if that doesn't work, try again using the filename extension
  662.         if ( filemode(errorFileName) == -1 ) {
  663.  
  664.             if ( length( ext ) > 1 ) {
  665.                 sourcefile_ext = ext
  666.                 errorFileName = substr( ext, 2 ) ".err"
  667.  
  668.                 if ( filemode(errorFileName) == -1 &&
  669.                         ext in compiler_err_array ) {
  670.                     errorFileName =                \
  671.                         compiler_err_array[ ext ]    \
  672.                         ".err"
  673.                 }
  674.             }
  675.  
  676.             if ( filemode(errorFileName) == -1 ) {
  677.                 warning( "Cannot open %s", errorFileName )
  678.                 return 0
  679.             }
  680.         }
  681.     }
  682.  
  683.     # find error file type given source filename extension
  684.     if ( sourcefile_ext in compiler_err_array ) {
  685.         errorInfoPrefix = compiler_err_array[ sourcefile_ext ]
  686.     } else {
  687.         errorInfoPrefix = substr( sourcefile_ext, 2 )
  688.     }
  689.  
  690.     # create a new system buffer for the error file
  691.  
  692.     originalBuffer = current_buffer
  693.     switchedBuffer = 0
  694.     prevEol = default_buffer_eol_string
  695.     default_buffer_eol_string = "\r\n"
  696.  
  697.     errorBuffer = create_buffer(    \
  698.             "Error File",    \
  699.             errorFileName,    \
  700.             BUFFER_SYSTEM + BUFFER_NO_UNDO )
  701.  
  702.     default_buffer_eol_string = prevEol
  703.  
  704.     errorsFound = FALSE
  705.  
  706.     return 1
  707. }
  708.  
  709.  
  710. ## closeErrorFile()
  711. #
  712. # Remove the system buffer associated with the error list file.
  713. #
  714.  
  715. local function closeErrorFile(){
  716.     delete_buffer( errorBuffer )
  717.     errorBuffer = 0
  718. }
  719.  
  720.  
  721. ## errorInfo()
  722. #
  723. # Calls the appropriate compiler specific xxxErrorInfo function to find
  724. # error and warning messages in the error file and extract salient
  725. # information.  Additional functions may be added here, if desired, to
  726. # support different compilers.  Each new function should have a name which
  727. # consists of the compiler type, as defined in the init_compilers() function,
  728. # followed by "ErrorInfo".  Each new ErrorInfo function should set
  729. # the following variables:
  730. #
  731. #
  732. #    errorSrcName -    the name of the source filename appearing in the
  733. #            error message
  734. #
  735. #    errorLine -    the line number in the current source file where the
  736. #            error occurred.
  737. #
  738. #    errorColumn -    the column where the error occurred (or 0 if unknown)
  739. #
  740. #    errorText -    the text of the message to be displayed in the
  741. #            dialog window.
  742. #
  743. #
  744. # In addition, the variable errorCompleteText will be displayed if the file
  745. # named in errorSrcName cannot be located.
  746. #
  747. #
  748. # The function return value should be as follows:
  749. #    0 - if no more error or warning messages could be found,
  750. #    1 - if the message is for a non-fatal error or warning,
  751. #    2 - if the message is for a severe error.
  752. #
  753.  
  754. local function errorInfo(){
  755.     local    functionId
  756.  
  757.     # initialize
  758.     errorSrcName    = ""
  759.     errorLine    = 0
  760.     errorColumn    = 0
  761.     errorText    = ""
  762.  
  763.     # Determine which xxxErrorInfo function to use.  Known compiler
  764.     # types and source file extensions are listed in the function
  765.     # "init_compilers()".
  766.  
  767.     if ( errorInfoPrefix == "none" ) {
  768.         # no errorInfo function exists for this compiler
  769.         return -1
  770.     }
  771.  
  772.     # Append the name "ErrorInfo" to the compiler type and
  773.     # use it if a function by that name exists.
  774.     functionId = function_id( errorInfoPrefix "ErrorInfo" )
  775.     if ( functionId ) {
  776.         return execute_function( functionId )
  777.     } else {
  778.         # otherwise use the default errorfix routine
  779.         return genericErrorInfo()
  780.     }
  781. }
  782.  
  783. # ------------------- Generic ErrorInfo function ----------------------------
  784.  
  785. global function genericErrorInfo(){
  786.  
  787.     #====================================================================
  788.     # This function is invoked whenever no explicit xxxErrorInfo()
  789.     # function has been defined for the current compiler.  It supports
  790.     # the error message syntax for several compilers, for example:
  791.     #
  792.     # Microsoft C and MASM:
  793.     # <sourcefile>(<line number>): "error"|"warning" <errno>: <message>
  794.     #
  795.     # Lattice C:
  796.     # <sourcefile> <line number> "Error"|"Warning" <errno>: <message>
  797.     #
  798.     # Borland Turbo Pascal:
  799.     # <sourcefile>(<line number>): "Error"|"Warning" <errno>: <message>
  800.     #
  801.     # FORCE:
  802.     # <sourcefile>(<line number>) : "Error"(<errno>) : <message>
  803.     #
  804.     #====================================================================
  805.  
  806.     local    errorLevel
  807.     local    searchFor = "[ \t(]+\\c[0-9].*(<error|<warning)[ \t(].*:"
  808.  
  809.     # scan the error file for the next appropriate message
  810.     if ( !search( searchFor, searchFlag ) ) {
  811.         return 0    # no more applicable messages
  812.     }
  813.  
  814.     # save the complete text of the error message
  815.     save_position()
  816.     goto_bol()
  817.     errorCompleteText = read_buffer()
  818.     restore_position(1)
  819.  
  820.     # get the source filename
  821.     match( errorCompleteText, /[^( \t]+/ )
  822.     errorSrcName = substr( errorCompleteText, RSTART, RLENGTH )
  823.  
  824.     # get the line and column position of the error
  825.     errorLine = atoi( read_buffer(10) )
  826.  
  827.     # determine the severity of the error
  828.     search( "<error>|<warning>", searchFlag )
  829.     errorLevel = (tolower(read_buffer(5)) == "error") ? 2 : 1
  830.  
  831.     # get the text of the message
  832.     search( ":\\c", searchFlag )
  833.     search( "<", searchFlag )
  834.     errorText = ltrim(read_buffer())
  835.  
  836.     return errorLevel
  837. }
  838.  
  839. # ------------------- ErrorInfo function for PEL ----------------------------
  840.  
  841. global function pelErrorInfo(){
  842.  
  843.     #====================================================================
  844.     #
  845.     # error message syntax for Sage - POLYTRON Pel compiler:
  846.     #
  847.     # <sourcefile>(<line number>):"[fatal] error"|"warning":
  848.     # <space>|<newline> <message>
  849.     #
  850.     #====================================================================
  851.  
  852.     local    errorLevel
  853.     local    searchFor = ":.*(error|warning).*:\\c"
  854.     local    delimit
  855.  
  856.     # scan the error file for the next appropriate message
  857.     if ( !search( searchFor, searchFlag ) ) {
  858.         return 0    # no more applicable messages
  859.     }
  860.  
  861.     # save the complete text of the error message
  862.     delimit = current_column
  863.     save_position()
  864.     goto_bol()
  865.     errorCompleteText = read_buffer( delimit )
  866.     restore_position(1)
  867.  
  868.     # get the source filename
  869.     match( errorCompleteText, /[^( ]+/ )
  870.     errorSrcName = substr( errorCompleteText, RSTART, RLENGTH )
  871.  
  872.     # get the line and column position of the error
  873.     if ( substr( errorCompleteText, RSTART+RLENGTH, 1 ) == "(" ) {
  874.         errorLine = atoi( substr( errorCompleteText, RSTART+RLENGTH+1 ))
  875.     }
  876.  
  877.     # determine the severity of the error
  878.     errorLevel = (errorCompleteText ~ /warning:/) ? 1 : 2
  879.  
  880.     # get the text of the message
  881.     search( "<", searchFlag )
  882.     errorText = read_buffer()
  883.     errorCompleteText = errorCompleteText errorText
  884.  
  885.     return errorLevel
  886. }
  887.  
  888. # ------------------- ErrorInfo function for Turbo C ------------------------
  889.  
  890. global function turbocErrorInfo(){
  891.  
  892.     #====================================================================
  893.     #
  894.     # error message syntax for Borland Turbo C (Version 2.0):
  895.     #
  896.     # "Error"|"Warning" <sourcefile> <line number>: <message>
  897.     #
  898.     #====================================================================
  899.  
  900.     local    errorLevel
  901.     local    searchFor = "^(Error|Warning).* \\c[0-9]+:"
  902.  
  903.     # scan the error file for the next appropriate message
  904.     if ( !search( searchFor, searchFlag ) ) {
  905.         return 0    # no more applicable messages
  906.     }
  907.  
  908.     # save the complete text of the error message
  909.     save_position()
  910.     goto_bol()
  911.     errorCompleteText = read_buffer()
  912.  
  913.     # get the source filename
  914.     match( errorCompleteText, / [^ ]+ / )
  915.     errorSrcName = substr( errorCompleteText, RSTART+1, RLENGTH-2 )
  916.  
  917.     # determine the severity of the error
  918.     errorLevel = (errorCompleteText ~ /^Error/) ? 2 : 1
  919.  
  920.     # get the line and column position of the error
  921.     restore_position(1)
  922.     errorLine = atoi( read_buffer(10) )
  923.     errorColumn = 0
  924.  
  925.     # get the text of the message
  926.     search( ":\\c", searchFlag )
  927.     errorText = ltrim(read_buffer())
  928.  
  929.     return errorLevel
  930. }
  931.  
  932. # ------------------- ErrorInfo function for Zortech C and C++ --------------
  933.  
  934. global function zortechErrorInfo(){
  935.  
  936.     #====================================================================
  937.     #
  938.     # error message syntax for Zortech C and C++
  939.     #
  940.     # Zortech C and C++:
  941.     # "<sourcefile>" line <line number>: "warning"|"syntax error"|
  942.     #    "preprocessor error"|"fatal error"|"lexical error": <message>
  943.     #
  944.     #====================================================================
  945.  
  946.     local    errorLevel
  947.     local    searchFor = "(^\".*\",? line \\c[0-9]*[ :]*(warning|(syntax|preprocessor|fatal|lexical) error):?)" \
  948.             "|\\c(Global Optimizer|Intermediate file|Fatal|Syntax|Preprocessor|lexical) error:+"
  949.     local    fnameline
  950.  
  951.     # scan the error file for the next appropriate message
  952.     if ( !search( searchFor, searchFlag )) {
  953.         return 0    # no more applicable messages
  954.     }
  955.  
  956.     # save the complete text of the error message
  957.     save_position()
  958.     goto_bol()
  959.     errorCompleteText = read_buffer()
  960.  
  961.     # get the source filename
  962.     errorSrcName = substr( errorCompleteText, 2,
  963.             cindex( substr( errorCompleteText, 2 ), "\"" ) - 1)
  964.  
  965.     # determine the severity of the error
  966.     errorLevel = (errorCompleteText ~ /warning:/) ? 1 : 2
  967.  
  968.     # get the line and column position of the error
  969.     restore_position(1)
  970.     errorLine = atoi( read_buffer(10) )
  971.     errorColumn = 0
  972.  
  973.     # get the text of the message
  974.     search( "(warning|error):\\c", searchFlag )
  975.     errorText = ltrim(read_buffer())
  976.  
  977.     return errorLevel
  978. }
  979.  
  980. # ------------------- ErrorInfo function for Lahey FORTRAN ------------------
  981.  
  982. global function laheyErrorInfo(){
  983.  
  984.     #====================================================================
  985.     #
  986.     # error message syntax for Lahey FORTRAN 77
  987.     #
  988.     # Lahey FORTRAN 77:
  989.     # "Compiling line    : <line num>"    This is only shown one time
  990.     # "File <source file name>, line    <line num>: <copy of program line>
  991.     #        <'^' pointer to Column position of Error>
  992.     # "(FATAL|WARNING) - <message>
  993.     #
  994.     #====================================================================
  995.  
  996.     local    errorLevel
  997.     local    searchFor = "^(FATAL|WARNING)[ \t]* -\\c"
  998.     local    fnameline
  999.  
  1000.     # scan the error file for the next appropriate message
  1001.     if ( !search( searchFor, searchFlag )) {
  1002.         return 0    # no more applicable messages
  1003.     }
  1004.  
  1005.     # save the complete text of the error message
  1006.     save_position()
  1007.     goto_bol()
  1008.     errorCompleteText = read_buffer()
  1009.     # the error message could span a couple of lines
  1010.     while (errorCompleteText !~ /\.$/){
  1011.         if (!down())
  1012.             break;
  1013.         goto_bol();
  1014.         errorCompleteText = errorCompleteText read_buffer();
  1015.     }
  1016.  
  1017.  
  1018.     # get the source filename
  1019.     if (match( errorCompleteText, "File .*, line[ \t]+[0-9]+\\.")) {
  1020.         # The line number and file name are on the same line.
  1021.         fnameline = substr( errorCompleteText, RSTART+5 );
  1022.  
  1023.         errorSrcName = trim(ltrim(substr( fnameline, 1,
  1024.                 cindex( fnameline, "," ) - 1 )))
  1025.         
  1026.         match( fnameline, "line[ \t]+[0-9]" )
  1027.         fnameline = ltrim(substr( fnameline, RSTART + 4 ));
  1028.  
  1029.         # get the line and column position of the error
  1030.         errorLine = atoi( fnameline )
  1031.         errorColumn = 0
  1032.  
  1033.     } else {
  1034.         # The line number and file name are on a different line.
  1035.         if (!search( "^File[ \t]+.* line +\\c[0-9]*", \
  1036.                 SEARCH_BACKWARD+SEARCH_REGEX+SEARCH_IGNORE_CASE )){
  1037.             restore_position(1)
  1038.             return 0;
  1039.         }
  1040.         save_position();
  1041.         current_column = 6;
  1042.         fnameline = read_buffer()
  1043.         match( fnameline, "," )
  1044.         errorSrcName = substr( fnameline, 1, RSTART - 1 )
  1045.  
  1046.         # get the line and column position of the error
  1047.         restore_position(1)
  1048.         errorLine = atoi( read_buffer(10) )
  1049.         errorColumn = 0
  1050.     }
  1051.  
  1052.     # determine the severity of the error
  1053.     errorLevel = (errorCompleteText ~ /^WARNING/) ? 1 : 2
  1054.  
  1055.     # get the text of the message
  1056.     restore_position(1)
  1057.     errorText = ltrim(read_buffer())
  1058.  
  1059.     return errorLevel
  1060. }
  1061.  
  1062. # ------------------- ErrorInfo function for Advantage ADA ------------------
  1063.  
  1064. global function adaErrorInfo(){
  1065.  
  1066.     #====================================================================
  1067.     #
  1068.     # error message syntax for Advantage ADA
  1069.     #
  1070.     # "<filename>", <line num>: <message>
  1071.     #
  1072.     #====================================================================
  1073.  
  1074.     local    errorLevel
  1075.     local    searchFor = "^\".*\", \\c[0-9]*:"
  1076.  
  1077.     # scan the error file for the next appropriate message
  1078.     if ( !search( searchFor, searchFlag ) ) {
  1079.         return 0    # no more applicable messages
  1080.     }
  1081.  
  1082.     # save the complete text of the error message
  1083.     save_position()
  1084.     goto_bol()
  1085.     errorCompleteText = read_buffer()
  1086.  
  1087.     # get the source filename
  1088.     errorSrcName = substr( errorCompleteText, 2,
  1089.             cindex( substr( errorCompleteText, 2 ), "\"" ) - 1)
  1090.  
  1091.     # determine the severity of the error
  1092.     errorLevel = (errorCompleteText ~ /error/) ? 2 : 1
  1093.  
  1094.     # get the line and column position of the error
  1095.     restore_position(1)
  1096.     errorLine = atoi( read_buffer(10) )
  1097.     errorColumn = 0
  1098.  
  1099.     # get the text of the message
  1100.     search( ":\\c", searchFlag )
  1101.     errorText = ltrim(read_buffer())
  1102.  
  1103.     return errorLevel
  1104. }
  1105.  
  1106. # ------------------- ErrorInfo functions for Clipper -----------------------
  1107.  
  1108. global function clipper87ErrorInfo(){
  1109.  
  1110.     #====================================================================
  1111.     #
  1112.     # error message syntax for Nantucket Clipper Summer87
  1113.     #
  1114.     # "Compiling <file>"    (This is only shown one time)
  1115.     # "line <line>:  <message>"
  1116.     # <copy of program line>
  1117.     #        <'^' pointer to Column position of Error>
  1118.     #
  1119.     #
  1120.     # Clipper Support added by P. Polakoff III, 3P Software, Inc.
  1121.     #
  1122.     #====================================================================
  1123.  
  1124.     local    errorLevel
  1125.     local    searchFor = "^line \\c[0-9]+:"
  1126.     local    fnameline
  1127.  
  1128.     # scan the error file for the next appropriate message
  1129.     if ( !search( searchFor, searchFlag ) ) {
  1130.         return 0    # no more applicable messages
  1131.     }
  1132.  
  1133.     # save the complete text of the error message
  1134.     save_position()
  1135.     goto_bol()
  1136.     errorCompleteText = read_buffer()
  1137.  
  1138.     # get the source filename
  1139.     do {
  1140.         goto_pos( current_line-1, 0 )
  1141.         fnameline = read_buffer()
  1142.     } while( substr(fnameline,1,9) != "Compiling" )
  1143.     errorSrcName = ltrim( trim( substr( fnameline, 10 )))
  1144.  
  1145.     # Clipper errors are always fatal
  1146.     errorLevel = 2
  1147.  
  1148.     # get the line and column position of the error
  1149.     restore_position(1)
  1150.     errorLine = atoi( read_buffer(10) )
  1151.     goto_pos( current_line+2, 1 )
  1152.     errorColumn = match( read_buffer(), "\\^" )
  1153.  
  1154.     # get the text of the message
  1155.     errorText = trim( substr(        \
  1156.             errorCompleteText,    \
  1157.             match( errorCompleteText, ":" ) + 1 ))
  1158.  
  1159.     return errorLevel
  1160. }
  1161.  
  1162. global function clipper5ErrorInfo(){
  1163.  
  1164.     #====================================================================
  1165.     #
  1166.     # error message syntax for Nantucket Clipper 5.0 (B93)
  1167.     #
  1168.     # <sourcefile>(<line number>) "Error"|"Warning" <errno>  <message>
  1169.     #
  1170.     #====================================================================
  1171.  
  1172.     local    errorLevel
  1173.     local    searchFor = "\\(\\c[0-9]+\\) +(Error|Warning)"
  1174.  
  1175.     # scan the error file for the next appropriate message
  1176.     if ( !search( searchFor, searchFlag ) ) {
  1177.         return 0    # no more applicable messages
  1178.     }
  1179.  
  1180.     # save the complete text of the error message
  1181.     save_position()
  1182.     goto_bol()
  1183.     errorCompleteText = read_buffer()
  1184.     restore_position(1)
  1185.  
  1186.     # get the source filename
  1187.     match( errorCompleteText, /[^( \t]+/ )
  1188.     errorSrcName = substr( errorCompleteText, RSTART, RLENGTH )
  1189.  
  1190.     # get the line and column position of the error
  1191.     errorLine = atoi( read_buffer(10) )
  1192.  
  1193.     # determine the severity of the error
  1194.     search( "<error>|<warning>", searchFlag )
  1195.     errorLevel = (tolower(read_buffer(5)) == "error") ? 2 : 1
  1196.  
  1197.     # get the text of the message
  1198.     errorText = read_buffer()
  1199.  
  1200.     return errorLevel
  1201. }
  1202.