home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / C.PEL < prev    next >
Text File  |  1995-04-04  |  32KB  |  978 lines

  1. # $Header:   P:\source\wmacros\c.pev   1.14   04 Apr 1995 09:28:24   WALKER  $
  2. ## $Tabs:4 7$
  3.  
  4. ##############################################################################
  5. #
  6. #       Compuware Corporation
  7. #         31440 Northwestern Highway
  8. #           Farmington Hills, Michigan 48334-2564
  9. #
  10. #   This source code listing contains information that is
  11. #   proprietary to Compuware Corporation and may not be copied
  12. #   duplicated, translated, transmitted, stored, retrieved
  13. #   or in any manner or by any method conveyed or disclosed
  14. #   to a third party or parties without express written
  15. #   permission from Compuware Corporation.
  16. #
  17. #  
  18. ##############################################################################
  19.  
  20. #### $Workfile:   c.pel  $: C support functions
  21. local make_extra_files = 0
  22.  
  23. # This is a list of lines to skip when doing ctags processing
  24. # this list should be configurable in the future
  25. local skipList
  26.  
  27.  
  28. local function ctags_init_skiplist()
  29. {
  30.    local counter = 0
  31.  
  32.    skipList[++counter] = "#include"
  33.    skipList[++counter] = "declare"
  34.    skipList[++counter] = "public:"
  35.    skipList[++counter] = "private:"
  36.    skipList[++counter] = "protected:"
  37.  
  38.    return counter;
  39. }
  40.  
  41. global function do_c_routines(dhTemp, allBuffers)
  42. {
  43.    local found_routine = 0
  44.    local i
  45.    local found_array[]
  46.    local temp[]
  47.    local fun_name
  48.  
  49.    process_background( DISABLE_FOREGROUND )
  50.    # Since the format of C-like files vary from person to person, we have to 
  51.    # come up with a better way of finding functions in a file.  The easiest
  52.    # way to do that is to just use the ctags_add function of the ctags_make.
  53.    # By doing this, we are assured that we will find all available functions,
  54.    # that is, assuming the ctags_make finds all functions
  55.    found_array = ctags_add(0)
  56.    for (i in found_array) 
  57.    {
  58.       split( found_array[i], temp, SUBSEP )
  59.       current_line  = temp[2]
  60.    
  61.       if ( allBuffers )
  62.          fun_name   = buffer_filename " : " temp[2] " : " temp[1]
  63.       else
  64.          fun_name   = temp[2] " : " temp[1]
  65.  
  66.       add_item_to_list( dhTemp, fun_name,   \
  67.                         buffer_filename, current_line, 0, -1 )
  68.    
  69.       found_routine = 1
  70.    }
  71.  
  72.    process_background( END_BACKGROUND )
  73.    return found_routine
  74. }
  75.  
  76. ############################### C tags support ############################
  77.  
  78. # temp array used to store symbols during ctags_make
  79. local tagsArray
  80. local classArray
  81. #local miscArray
  82. local definesArray
  83. local headerArray
  84. local IDD_TAGS_PROGRESS          = 1629
  85. local IDB_TAGS_STOP              = 1630
  86. local IDT_TAGS_FILES_PROCESSED   = 1631
  87. local IDT_TAGS_TAGS_PROCESSED    = 1632
  88. local IDT_TAGS_CURRENT_FILE      = 1633
  89. local IDT_TAGS_PERCENT           = 1634
  90.  
  91. local tags_temp_buffer
  92. local tags_extensions = "*.c *.h *.cpp *.hpp *.cxx *.hxx"
  93. local tags_file = "ctags.tag"
  94. local tags_buffer
  95. local tags_make_successful
  96. local tags_remake_all = FALSE
  97. global function ctags_make_background()
  98. {
  99.    local j
  100.    local source_file
  101.    local wildcard
  102.    local filespecs[]
  103.    local file_count
  104.    local full_spec
  105.  
  106.    tags_make_successful = FALSE
  107.  
  108.    split( tags_extensions, filespecs )
  109.  
  110.    making_tags_dialog()
  111.    set_tags_files_processed( 0 )
  112.    set_tags_tags_processed( 0 )
  113.    set_tags_message( "Building " tags_file " - Please wait..." )
  114.  
  115.    # scan the source files for "interesting" symbols
  116.    for ( j in filespecs )
  117.    {
  118.       wildcard = buildpath( filespecs[ j ] )
  119.  
  120.       if ( (source_file = findfirst( wildcard )) )
  121.       {
  122.          do
  123.          {
  124.             full_spec = buildpath( getcwd() source_file )
  125.  
  126.             source_file = tolower( path_path( wildcard ) source_file )
  127.  
  128.             set_tags_current_file( source_file )
  129.  
  130.             if ( !tags_remake_all &&
  131.                   filetime(source_file) == get_timestamp(full_spec) )
  132.                continue
  133.  
  134.             # open the buffer as a system buffer
  135.             current_buffer = tags_temp_buffer = create_buffer( "", 
  136.                                                             source_file, 
  137.                                                             BUFFER_SYSTEM + 
  138.                                                             BUFFER_NO_UNDO )
  139.  
  140.             # build the tags array
  141.             ctags_add( 1 )
  142.  
  143.             # DWM--combine these two lines to fool the compiler
  144.             # into generating only one debug_step for both 
  145.             # operations.  If the user breaks out of the make it
  146.             # is important that the tags_temp_buffer be null if
  147.             # the buffer has been deleted.
  148.             delete_buffer(); tags_temp_buffer = 0
  149.  
  150.             ctags_support( tagsArray, tags_buffer, tags_file, source_file )
  151.  
  152.             file_count++
  153.             set_tags_files_processed( file_count )
  154.             update_timestamp( source_file )
  155.  
  156.          } while (( source_file = findnext()))
  157.       }
  158.    }
  159.  
  160.    tags_make_successful = TRUE
  161. }
  162.  
  163. local function ctags_setup( file_extensions, output_tags_file )
  164. {
  165.    local success = FALSE
  166.  
  167.    tags_extensions = file_extensions
  168.    tags_file = output_tags_file
  169.  
  170.    # If the tag file has been deleted,
  171.    # remake all of the tags.
  172.    if ( filemode(tags_file) == -1 )
  173.       tags_remake_all = TRUE
  174.    else
  175.       tags_remake_all = FALSE
  176.       
  177.    # create a system buffer for the tags info
  178.    tags_buffer = create_buffer( tags_file, tags_file, BUFFER_SYSTEM + BUFFER_NO_UNDO )
  179.  
  180.    if ( tags_buffer )
  181.    {
  182.       init_timestamp( path_path(tags_file) path_fname(tags_file) ".dat" )
  183.       success = TRUE
  184.    }
  185.    else
  186.       warning( "invalid tags filename " tags_file )
  187.  
  188.    return success
  189. }
  190.  
  191. local function ctags_cleanup( outFileName )
  192. {
  193.    local response
  194.  
  195.    current_window = current_window
  196.  
  197.    cleanup_timestamp()
  198.  
  199.    current_buffer = tags_buffer
  200.    # only write it if it has been updated
  201.    if ( and(buffer_flags, BUFFER_MODIFIED) )
  202.    {
  203.       if ( !tags_make_successful )
  204.       {
  205.          response = confirm( "Save tags file " tags_file "? [yn]", "yYnN" )
  206.    
  207.          if ( tolower(response) == "y" )
  208.             write_buffer()
  209.       }
  210.       else
  211.          write_buffer()
  212.    }
  213.  
  214.    # If the background process did not 
  215.    # clean up after itself, do so now.
  216.    if ( tags_temp_buffer )
  217.       delete_buffer( tags_temp_buffer )
  218.  
  219.    if ( tags_dlg )
  220.       delete_tags_dialog()
  221.  
  222.    set_tags_message( outFileName " complete."  )
  223.  
  224.    set_tags_percent( outFileName )
  225.  
  226.    # save the new tags file
  227.    current_buffer = tags_buffer
  228.    delete_buffer( tags_buffer )
  229. }
  230.  
  231. ## ctags_make() - builds a "ctags.tag" data file for all obvious functions,
  232. #                 structure definitions, and #defined macros.  You will be 
  233. #                 prompted for a list of C source files to process.
  234. #
  235. global function ctags_make( file_extensions, output_tags_file )
  236. {
  237.    local priorBuffer = current_buffer
  238.  
  239.    if ( argcount() < 2 )
  240.    {
  241.       warning( "ctags_make syntax:  ctags_make( files_extensions, tags_file )" )
  242.       return FALSE
  243.    }
  244.  
  245.    if ( ctags_setup(file_extensions, output_tags_file) )
  246.    {
  247.       process_background( DISABLE_FOREGROUND, function_id("ctags_make_background") )
  248.    
  249.       # save the new tags file
  250.       ctags_cleanup( output_tags_file )
  251.    }
  252.  
  253.    current_buffer = priorBuffer
  254.  
  255.    return tags_make_successful
  256. }
  257.  
  258. global function making_tags_callback()
  259. {
  260.    local ret = DRC_MSG_PROCESSED
  261.  
  262.    if ( callback_msg == DM_CANCEL || callback_msg == DM_CLOSE )
  263.    {
  264.       process_background( STOP_BACKGROUND )
  265.    }
  266.    else if ( callback_msg == DM_CLICK || callback_msg == DM_DOUBLE_CLICK )
  267.    {
  268.       if ( callback_index == IDB_TAGS_STOP )
  269.       {
  270. #        set_dialog_window( callback_dialog_handle, DWC_HIDE )
  271.          beep()
  272.          process_background( STOP_BACKGROUND )
  273.       }
  274.    }
  275.  
  276.    return ret
  277. }
  278.  
  279. local tags_dlg = 0
  280. local function set_tags_current_file( file )
  281. {
  282.    if ( tags_dlg )
  283.    {
  284.       set_dialog_item( tags_dlg, IDT_TAGS_CURRENT_FILE, DAC_TEXT, file )
  285.       set_tags_percent( 0 )
  286.    }
  287. }
  288.  
  289. local function set_tags_percent( percent )
  290. {
  291.    if ( tags_dlg )
  292.       set_dialog_item( tags_dlg, IDT_TAGS_PERCENT, DAC_TEXT, "%" percent "" )
  293. }
  294.  
  295. local function set_tags_files_processed( processed )
  296. {
  297.    if ( tags_dlg )
  298.       set_dialog_item( tags_dlg, IDT_TAGS_FILES_PROCESSED, DAC_TEXT, processed "" )
  299. }
  300.  
  301. local function set_tags_tags_processed( processed )
  302. {
  303.    if ( tags_dlg )
  304.       set_dialog_item( tags_dlg, IDT_TAGS_TAGS_PROCESSED, DAC_TEXT, processed "" )
  305. }
  306.  
  307. local function increment_tags_processed()
  308. {
  309.    local count
  310.  
  311.    if ( tags_dlg )
  312.    {
  313.       count = query_dialog_item( tags_dlg, IDT_TAGS_TAGS_PROCESSED, DAC_TEXT )
  314.       set_dialog_item( tags_dlg, IDT_TAGS_TAGS_PROCESSED, DAC_TEXT, (count + 1) "" )
  315.    }
  316. }
  317.  
  318. local function set_tags_message( msg )
  319. {
  320.    if ( tags_dlg )
  321.       set_dialog_window( tags_dlg, DWC_STATUSBARTEXT, msg "" )
  322. }
  323.  
  324. local function delete_tags_dialog()
  325. {
  326.    if ( tags_dlg )
  327.    {
  328.       delete_dialog( tags_dlg )
  329.       tags_dlg = 0
  330.    }
  331. }
  332.  
  333. global function making_tags_dialog()
  334. {
  335.    tags_dlg = create_mdialog( function_id("making_tags_callback"), mdi_mode == 2 ? -1 : 0, IDD_TAGS_PROGRESS )
  336.  
  337.    set_dialog_window( tags_dlg, DWC_STATUSBAR, TRUE )
  338.  
  339.    begin_dialog( tags_dlg )
  340. }
  341.  
  342. local function ctags_support( array, buffer_id, outFileName, srcFile )
  343. {
  344.    local i, found
  345.  
  346.    # remove obsolete entries for this file
  347.    current_buffer = buffer_id
  348.    save_position()
  349.    goto_buffer_top()
  350.    found = 0
  351.  
  352. #   if ( and( status_bar_flags, STB_MESSAGES ) )
  353.    set_tags_message( "Removing old entries from " buffer_filename "..." )
  354.  
  355.    while ( search( " " srcFile, SEARCH_FORWARD ))
  356.    {
  357.       #cvdebug("***removing obsolete source entries")
  358.       found = 1
  359.       goto_bol()
  360.       delete_line()
  361.    }
  362.  
  363.    # insert the name, source filename, and
  364.    # search pattern into the buffer
  365.    restore_position( !found )
  366.  
  367. #   if ( and( status_bar_flags, STB_MESSAGES ) )
  368.    set_tags_message( "Adding new entries to " buffer_filename "..." )
  369.  
  370.    for ( i in array )
  371.    {
  372.       insert_string( i " " srcFile " ^" array[ i ] )
  373.       insert_newline()
  374.    }
  375.    delete array
  376. }
  377.  
  378. local function add_tag( index, element )
  379. {
  380.    tagsArray[ index ] = element
  381.    increment_tags_processed()
  382. }
  383.  
  384. ## ctags_add
  385. #
  386. # Extract "interesting symbols" from the current buffer, assuming it
  387. # is C source code.  NOTE: This is a "quick and dirty" algorithm - symbols
  388. # can easily be overlooked, or included when they aren't supposed to be.
  389. # No effort is made to deal with #if and #ifdef preprocessor code.
  390. #
  391. # this is also used by the optional routines function 
  392. #
  393. global function ctags_add( makingTags, ctags_string, ctags_multiline )
  394. {
  395.    local nlines = buffer_last_line
  396.    local thisLine    = 0
  397.    local firstLine   = 0
  398.    local i           = 0;
  399.    local currLine    = 0
  400.    local symbol       
  401.    local blank        
  402.    local fname, cname;
  403.    local found_prototype;
  404.    local oldthisLine, oldLine, secondLine, trimmedThisLine
  405.  
  406.    goto_buffer_top()
  407.  
  408.    if (!makingTags)
  409.       delete(tagsArray);
  410.       
  411.    for ( ; current_line < nlines; current_line++ )
  412.    {
  413. #      idle()
  414.  
  415.       # Skip over blank lines
  416.       if ( !current_line_length )
  417.       {
  418. #         #cvdebug("skipping blank lines line(%d)", current_line)
  419.          continue
  420.       }  #end if current_line
  421.  
  422.       oldthisLine = ""
  423.  
  424.       # read the text of the line
  425.       current_column = 1
  426.       thisLine = read_buffer()
  427.       trimmedThisLine = ltrim( thisLine )
  428.  
  429.       if ( ctags_skip_line( thisLine ) )
  430.       {
  431.          continue
  432.       }
  433.  
  434.       # Skip over obvious procedure bodies
  435.       else if ( ctags_skip_proc( thisLine ) )
  436.       {
  437.          continue
  438.       } #end if skip_proc
  439.  
  440.       oldLine = current_line
  441.       ++current_line
  442.       secondLine = read_buffer()
  443.       current_line = oldLine
  444.  
  445.       # check for multi-line definitions like the following
  446.       #
  447.       # void
  448.       # foo
  449.       # ( int arg1 )
  450.       #
  451.       if ( match( secondLine, /^[ ]*\([^;]*$/ ) )
  452.       {
  453.          oldthisLine = thisLine
  454.          thisLine = thisLine secondLine
  455.          #cvdebug("  thisline changed");
  456.       } #end if match
  457.  
  458.       # Preprocessor "#defines"
  459.       if ( substr(trimmedThisLine,1,1) == "#" )
  460.       {
  461.          if ( match( thisLine, /#define[ \t]+/ ))
  462.          {
  463.             # get text past the "define" keyword
  464.             symbol = substr( thisLine, RSTART+RLENGTH )
  465.             if ( match( symbol, /[ \t(]+|$/ ))
  466.             {
  467.                # ..and before the next delimiter
  468.                if ( makingTags )
  469.                {
  470.                   add_tag( substr(symbol, 1, RSTART-1), thisLine )
  471.  
  472.                   if ( make_extra_files )
  473.                      definesArray[ substr( symbol, 1, RSTART-1 ) ] = thisLine
  474.                } #end if making tags
  475.             } #end if match symbol
  476.  
  477.             #cvdebug("matched a define line(%d)", current_line)
  478.             # if this is a macro, step over function body
  479.             while ( thisLine ~ /\\$/ && current_line != nlines )
  480.             {
  481.                #cvdebug(" finding end of macro line(%d)", current_line)
  482.                current_line++
  483.                current_column = 1
  484.                thisLine = read_buffer()
  485.             } #end while
  486.  
  487.          #cvdebug("skipping after macro found line(%d)", current_line)
  488.          continue
  489.          } #end if matched thisline
  490.        } #end if substr trimmedThisLine
  491.  
  492.       # Structure and class definitions
  493.       else if ( match( thisLine, /(enum|struct|class)[ \t]+[a-zA-Z0-9_]+[ \t]*([\{\:\/]|$)/ ) )
  494.       {
  495.          match( thisLine, /(enum|struct|class)[ \t]+/ )
  496.  
  497.          # get text past the "struct" or "class" keyword
  498.          symbol = substr( thisLine, RSTART+RLENGTH )
  499.  
  500.          if ( match( symbol, /[ \t]*([\{\:\/]|$)/ ) > 1 )
  501.          {
  502.             # ..and before the "{" or ":" or "/"
  503.             if ( makingTags )
  504.             {
  505.                if ( make_extra_files )
  506.                   headerArray[ substr( symbol, 1, RSTART-1 ) ] = thisLine
  507.  
  508.                   add_tag( substr(symbol, 1, RSTART-1), thisLine )
  509.  
  510.             } #end if makingtags
  511.  
  512.             # if we matched a class, find brace and skip over it
  513.             # so we can find functions defined w/in class definition
  514.             if ( match( thisLine, /class/ )  )
  515.             {
  516.                search( /\{/, SEARCH_FORWARD )
  517.                current_line++
  518.                #cvdebug(" jumping pass brace line(%d)", current_line)
  519.                continue
  520.             } # end if match symbol
  521.             
  522.          } #end if match symbol
  523.       } #end else-if match thisLine
  524.  
  525.       # A function definition begins in column one and is followed
  526.       # by a parenthesized list not followed by a semi-colon.
  527.       # If you use a different convention for function definitions
  528.       # you will have to change this.
  529.  
  530.       # A function definition may also be preceeded by types, linkage
  531.       # information and extern "C" declarations.
  532.       else if ( match( thisLine, /^[^;\/]+\([^;]*$/ ) )
  533.       {
  534.          # strip off the argument list
  535.          symbol = trim( substr( thisLine, 1, index(thisLine,"(") - 1 ))
  536.          
  537.          if (symbol ~ /\"/)
  538.          {
  539.             if ( !(symbol ~ /extern[ \t]*\"[C|c]\"/ ))
  540.             {
  541.                # Skip strings
  542.                #cvdebug("skipping extern C line(%d)", current_line)
  543.                continue
  544.             }
  545.          }
  546.          else if (symbol ~ /[=+-|!%\[\]\}<>.];/ )
  547.          {
  548.             #cvdebug("skipping expressions line(%d)", current_line)
  549.             # Skip assignments and other expressions
  550.             # However, references (&) and pointers (*) are OK
  551.             continue
  552.          }
  553.  
  554.          # get the last keyword before the "("
  555.          if ( symbol ~ /[ \t]*::[ \t]*/ )
  556.          {
  557.             # parse a C++ class::function name.
  558.             if ( match( symbol, /[a-zA-Z0-9_~]+$/ ))
  559.             {
  560.                # strip off the function name
  561.                fname  = trim( substr( symbol, RSTART ))
  562.                symbol = trim( substr( symbol, 1, RSTART - 1 ), " \t:" )
  563.  
  564.                if ( match( symbol, /[a-zA-Z0-9_~]+$/ ))
  565.                {
  566.                   cname  = trim( substr( symbol, RSTART ))
  567.                   symbol = cname "::" fname
  568.                }
  569.                else
  570.                   symbol = fname
  571.                #cvdebug("matched C++ name line(%d)", current_line)
  572.             }
  573.             else if ( match( symbol, /[^ \t]+$/ ))
  574.             {
  575.                # strip off the function name
  576.                fname  = trim( substr( symbol, RSTART ))
  577.                symbol = trim( substr( symbol, 1, RSTART - 1 ), " \t:" )
  578.  
  579.                if ( match( symbol, /[^ \t]+$/ ))
  580.                {
  581.                   cname  = trim( substr( symbol, RSTART ))
  582.                   symbol = cname "::" fname
  583.                }
  584.                else
  585.                   symbol = fname
  586.                #cvdebug("matched other function line(%d)", current_line)
  587.             }
  588.             else
  589.             {
  590.                #cvdebug("just skipping line(%d)", current_line)
  591.                continue
  592.             }
  593.          }
  594.  
  595.          # check for multi-line definitions like the following
  596.          #
  597.          # void
  598.          # foo CALL_CONV   
  599.          # ( int arg1 )
  600.          #
  601.          # where CALL_CONV is know to be valid and is passed into
  602.          # ctags_make()
  603.          #
  604.          else if ( match( symbol, "[ ]+" ctags_string "$" ))
  605.          {
  606.             #cvdebug("match w/ctags string line(%d)", current_line)
  607.             #cvdebug(" string before(%s)", symbol )
  608.             # remove the offending string
  609.             symbol = trim( substr( symbol, 1, RSTART-1 ))
  610.  
  611.             # pull out the function name
  612.             if ( match( symbol, /[a-zA-Z0-9_~&*]+$/ ))
  613.                symbol = trim( substr( symbol, RSTART ))
  614.             #cvdebug(" string after(%s)", symbol )
  615.          }
  616.          else if ( match( symbol, /[a-zA-Z0-9_~&*=+-><()\[\]]+$/ ))
  617.          {
  618.             #cvdebug("match multi line 2 line(%d)", current_line)
  619.             #cvdebug(" string before(%s)", symbol )
  620.             symbol = trim( substr( symbol, RSTART ))
  621.             symbol = ltrim( symbol, "*&" )
  622.             #cvdebug(" string before(%s)", symbol )
  623.          }
  624.          else
  625.          {
  626.             #cvdebug("skipping multi line 1 line(%d)", current_line)
  627.             continue
  628.          }
  629.  
  630.          if ( symbol == "if"    || symbol == "do"     ||
  631.               symbol == "while" || symbol == "switch" ||
  632.               symbol == "for"   || symbol == "return" )
  633.          {
  634.             #cvdebug("skipping if, while line(%d)", current_line)
  635.             continue
  636.          }
  637.  
  638.          if ( length( symbol ))
  639.          {
  640.             firstLine = oldthisLine ? oldthisLine : thisLine
  641.  
  642.             # save current line before we go to end of definition
  643.             currLine = current_line;
  644.             
  645.             # find the end of the definition
  646.             found_prototype = FALSE
  647.             while (  thisLine !~ /\{/ && !found_prototype && 
  648.                      current_line != nlines )
  649.             {
  650.                if ( thisLine ~ /;/ )
  651.                   found_prototype = TRUE
  652.                #cvdebug(" finding end of definition line(%d)", current_line)
  653.                current_line++
  654.                current_column = 1
  655.                thisLine = read_buffer()
  656.             }
  657.  
  658.             if ( found_prototype)
  659.             {
  660.                #cvdebug(" skipping prototypes line(%d)", current_line)
  661.                continue    # skip prototypes.
  662.             }
  663.  
  664.             if (makingTags)
  665.             {
  666.                #cvdebug("### Adding(%s) to tags array line(%d)", symbol, current_line)
  667.                add_tag( symbol, firstLine )
  668.  
  669.                if ( make_extra_files )
  670.                   classArray[ symbol ] = firstLine
  671.  
  672.                # Add a second entry in the tags file for the function
  673.                # without the class name (as tags_auto will not pick up
  674.                # the class name since it is rarely specified when called)
  675.  
  676.                match( symbol, /::/ )
  677.                if ( RSTART && RLENGTH )
  678.                {
  679.                   add_tag( substr(symbol, RSTART + RLENGTH), firstLine )
  680.  
  681.                   if ( make_extra_files )
  682.                      classArray[ substr( symbol, RSTART + RLENGTH) ] = firstLine
  683.                }
  684.             }
  685.             else 
  686.                add_tag( i, symbol SUBSEP currLine )
  687.  
  688.             ++i
  689.             if ( !makingTags && and( status_bar_flags, STB_MESSAGES ) )
  690.                message( "Searching file %s...(%d%%)", \
  691.                          buffer_filename, current_line * 100 / nlines )
  692.  
  693.             set_tags_percent( current_line * 100 / nlines )
  694.  
  695.             # Skip over the procedure body (if any)
  696.             if ( ctags_skip_proc( thisLine ) )
  697.             {
  698.                continue
  699.             }
  700.          }
  701.       }
  702.    #cvdebug("line not processed line(%d)", current_line)
  703.    }
  704.    
  705.    return tagsArray;
  706. }
  707.  
  708. # Utility function used by ctags_add to jump over a line
  709. #
  710. local function ctags_skip_line( thisLine )
  711. {
  712.    local skippedOne = FALSE
  713.    local trimmedThisLine = ltrim( thisLine )
  714.    local maxItems = ctags_init_skiplist()
  715.    local i;
  716.  
  717.    # Skip over blank lines
  718.    if ( !trimmedThisLine )
  719.    {
  720. #     #cvdebug("skipping null lines line(%d)", current_line)
  721.       skippedOne = TRUE
  722.    } #end if trimmedThisLine
  723.    
  724.    # Skip over obvious comment blocks
  725.    else if ( substr(trimmedThisLine,1,2) == "//" )
  726.    {
  727. #     #cvdebug("skipping line comments line(%d)", current_line)
  728.       skippedOne = TRUE
  729.    } #end if substr
  730.  
  731.    else if ( substr(trimmedThisLine,1,2) == "/*" )
  732.    {
  733. #     old_line = current_line
  734.       search( "*/", SEARCH_FORWARD )
  735. #     #cvdebug("skipping comment blocks old(%d) line(%d)", 
  736. #     old_line, current_line)
  737.       skippedOne = TRUE
  738.    } #end if substr
  739.  
  740. #  # skip prototypes or statements
  741. #  else if ( thisLine ~ /;/ )
  742. #  {
  743. #     #cvdebug("skipping prototypes in skip line line(%d)", current_line)
  744. #     skippedOne = TRUE
  745. #  }
  746.  
  747.    else for ( i = 1; i <= maxItems; i++ )
  748.    {
  749.       if ( (i in skipList ) && trimmedThisLine ~ skipList[ i ] )
  750.       {
  751.          #cvdebug("skipping line line(%d)", current_line )
  752.          skippedOne = TRUE
  753.  
  754.       }
  755.    }
  756.  
  757.  
  758.    return skippedOne
  759. }
  760.  
  761. # Utility function used by ctags_add to jump over procedure bodies
  762. #
  763. local function ctags_skip_proc( thisLine )
  764. {
  765.    local old_col, old_line;
  766.    local skippedOne = FALSE
  767.  
  768.    # Skip over the procedure body (if any)
  769.    # until read_buffer() expands tabs, we'll have to do a 
  770.    # search() instead of the much easier goto_pos() and match()
  771.    #
  772. #  if ( match( thisLine, /\{/ ) && thisLine !~ /\}/ )
  773.    if ( thisLine ~ /\{/ && thisLine !~ /\}/ )
  774.    {
  775.       skippedOne = TRUE
  776.       old_line = current_line
  777.       old_col = current_column
  778. #     search( /\{/, SEARCH_FORWARD + SEARCH_REGEX )
  779. #     goto_pos( current_line, RSTART )
  780.       search( "{", SEARCH_FORWARD )
  781.       goto_matching( "", TRUE )
  782.       #cvdebug("skipping procedure bodies RSTART(%d) start(%d,%d) end(%d,%d)",  RSTART, old_col, old_line, current_column, current_line)
  783.    }
  784.  
  785.    return skippedOne
  786. }
  787.  
  788. function setup_C_template()
  789. {
  790.    local OB, EB, EB2 # open and closed braces
  791.    local OC, MC, EC  # open, middle, end comment markers
  792.    local BLOCK, NBLOCK
  793.  
  794.    OB  = electric_symbol.open_brace
  795.    EB  = electric_symbol.end_brace 
  796.    EB2 = electric_symbol.end_brace2
  797.  
  798.    OC = electric_symbol.open_comment
  799.    MC = electric_symbol.middle_comment
  800.    EC = electric_symbol.end_comment
  801.  
  802.    NBLOCK = electric_symbol.new_block 
  803.    BLOCK  = electric_symbol.block     
  804.    
  805.    delete( language_template );    # delete last template and start over
  806.  
  807.    ELEC_LANG = "c"
  808.  
  809.    language_template[ "#d" ] = "#define `constant-1`"
  810.    language_template[ "#i" ] = "#include <`filename-1`>"
  811.    language_template[ "#p" ] = "#pragma `char-sequence-1`"
  812.    language_template[ "#u" ] = "#undef `constant-1`"
  813.    language_template[ "(" ] = "( `expression-1` )"
  814.    language_template[ "/*" ] = "/*\n** `comment-1`\n*/"
  815.    language_template[ "/" ] = "/* `comment-1` */"
  816.    language_template[ "[" ] = "[ `index-1` ]"
  817.    language_template[ "{" ] = BLOCK
  818.    language_template[ "_m" ] = "_makepath(@,,,,);"
  819.    language_template[ "_s" ] = "_splitpath(@,,,,);"
  820.    language_template[ "ac" ] = "access(\"@\",);"
  821.    language_template[ "br" ] = "break;\n@"
  822.    language_template[ "ca" ] = "case `constant-expr-1`:\n\t`statement-1`\nbreak;\n"
  823.    language_template[ "cl" ] = "close(`filename-1`);"
  824.    language_template[ "co" ] = "continue;\n@"
  825.    language_template[ "do" ] = "do \n" BLOCK " while ( `expr-1` );\n"
  826.    language_template[ "fe" ] = "free( `storage-1` );"
  827.    language_template[ "fo" ] = "for (`expr-1`;`expr-2`;`expr-3` ) \n" BLOCK OC " end for " EC "\n"
  828.    language_template[ "fp" ] = "fprintf(`filename-1`,\"`format-string-1`\",`var-list-1`);"
  829.    language_template[ "fr" ] = "fread(`buffer-1`,`size-1`,`count-1`,`stream-1`);"
  830.    language_template[ "fs" ] = "fscanf(`filename-1`,\"`format-string-1`\");"
  831.    language_template[ "ft" ] = "ftell(`stream-1`);"
  832.    language_template[ "fw" ] = "fwrite(`buffer-1`,`size-1`,`count-1`,`stream-1`);"
  833.    language_template[ "gc" ] = "getc(`stream-1`);"
  834.    language_template[ "gh" ] = "getchar();"
  835.    language_template[ "go" ] = "goto `identifier-1`;    " OC " `PLEASE EXPLAIN` " EC
  836.    language_template[ "gs" ] = "gets(`buffer-1`);"
  837.    language_template[ "gw" ] = "getw(`buffer-1`);"
  838.    language_template[ "fu" ] = "function `funct-name-1`( `param-list-1` )\n" NBLOCK
  839.    language_template[ "if" ] = "if ( `expr-1` ) \n" BLOCK OC " end if " EC "\n"
  840.    language_template[ "el" ] = "else \n" BLOCK OC " end else" EC " \n"
  841.    language_template[ "ei" ] = "else " language_template["if"]
  842.    language_template[ "ie" ] = language_template["if"] "\n" language_template["el"]
  843.    language_template[ "ls" ] = "lseek(@,,SEEK_);"
  844.    language_template[ "ma" ] = "malloc(`size-1`);"
  845.    language_template[ "op" ] = "open(\"@\",,);"
  846.    language_template[ "pc" ] = "putc(`int-1`,`stdout-1`);"
  847.    language_template[ "ph" ] = "putchar(`int-1`);"
  848.    language_template[ "pr" ] = "printf(\"`format-string-1`\", `var-list-1`);"
  849.    language_template[ "ps" ] = "puts(\"`string-1`\");"
  850.    language_template[ "pw" ] = "putw(@,);"
  851.    language_template[ "re" ] = "read(@,,);"
  852.    language_template[ "rn" ] = "rename(\"`old-name-1`\", \"`new-name-1`\");"
  853.    language_template[ "rt" ] = "return `expr-1`;"
  854.    language_template[ "sc" ] = "scanf(`filename-1`, \"`format-string-1`\", `var-list-1`);"
  855.    language_template[ "sp" ] = "sprintf(`var-name-1`, \"`format-string-1`\", `var-list-1`);"
  856.    language_template[ "ss" ] = "sscanf(`buffer-1`, \"`format-string-1`\", `var-list-1`);"
  857.    language_template[ "st" ] = "static `var-name-1`;"
  858.    language_template[ "sw" ] = "switch (`expr-1`) \n" OB "\n\tdefault:\n\t`statement-2`\n" EB2 OC " end switch " EC "\n"
  859.    language_template[ "ts" ] = "typedef struct \n" BLOCK " `struct-name-1`;\n"
  860.    language_template[ "tu" ] = "typedef union \n" BLOCK " `union-name-1`;\n"
  861.    language_template[ "ty" ] = "typedef `name-1`"
  862.    language_template[ "un" ] = "unlink(\"`filename-1`\");"
  863.    language_template[ "vf" ] = "vfprintf(`file-1`,\"`format-string-1`\",`var-list-1`);"
  864.    language_template[ "vp" ] = "vprintf(\"`format-string-1`\",`var-list-1`);"
  865.    language_template[ "vs" ] = "vsprintf(`buffer-1`,\"`format-string-1`\",`var-list-1`);"
  866.    language_template[ "wh" ] = "while (`condition-1`) \n" BLOCK OC " end while " EC "\n"
  867.    language_template[ "wr" ] = "write(@,,);"
  868. }
  869.  
  870. #
  871. # Language-specific macros.  The following ("__") macros are called in turn 
  872. # whenever a file with the corresponding (".") extension is edited and
  873. # electric is enabled.  
  874. #
  875.  
  876. function __c()
  877. {
  878.    electric_symbol.open_comment   = "/*"
  879.    electric_symbol.middle_comment = "**"
  880.    electric_symbol.end_comment    = "*/"
  881. }
  882.  
  883. #function __h() # .h same as .c
  884. #{
  885. #   __c()
  886. #}
  887. #
  888. #function __cpp() # C++ same as C
  889. #{
  890. #   __c()
  891. #}
  892. #
  893. #function __hpp() # C++ same as C
  894. #{
  895. #   __c()
  896. #}
  897. #
  898. #function __cxx() # C++ same as C
  899. #{
  900. #   __c()
  901. #}
  902. #
  903. #function __hxx() # C++ same as C
  904. #{
  905. #   __c()
  906. #}
  907.  
  908. global function load_factory_c_syntax()
  909. {
  910.    local type = "c";
  911.  
  912.    set_factory_categories(type);
  913.  
  914.    add_syntax_item(type, KEYWORD, "void", CATEGORY_TYPE)
  915.    add_syntax_item(type, KEYWORD, "int", CATEGORY_TYPE)
  916.    add_syntax_item(type, KEYWORD, "long", CATEGORY_TYPE)
  917.    add_syntax_item(type, KEYWORD, "short", CATEGORY_TYPE)
  918.    add_syntax_item(type, KEYWORD, "unsigned", CATEGORY_TYPE)
  919.    add_syntax_item(type, KEYWORD, "float", CATEGORY_TYPE)
  920.    add_syntax_item(type, KEYWORD, "double", CATEGORY_TYPE)
  921.    add_syntax_item(type, KEYWORD, "char", CATEGORY_TYPE)
  922.    add_syntax_item(type, KEYWORD, "struct", CATEGORY_TYPE)
  923.    add_syntax_item(type, KEYWORD, "union", CATEGORY_TYPE)
  924.    add_syntax_item(type, KEYWORD, "class", CATEGORY_TYPE)
  925.    add_syntax_item(type, KEYWORD, "const", CATEGORY_TYPE)
  926.    add_syntax_item(type, KEYWORD, "local", CATEGORY_TYPE)
  927.    add_syntax_item(type, KEYWORD, "global", CATEGORY_TYPE)
  928.    add_syntax_item(type, KEYWORD, "far", CATEGORY_TYPE)
  929.    add_syntax_item(type, KEYWORD, "static", CATEGORY_TYPE)
  930.  
  931.    add_syntax_item(type, KEYWORD, "#if", CATEGORY_DIRECTIVE)
  932.    add_syntax_item(type, KEYWORD, "#ifdef", CATEGORY_DIRECTIVE)
  933.    add_syntax_item(type, KEYWORD, "#ifndef", CATEGORY_DIRECTIVE)
  934.    add_syntax_item(type, KEYWORD, "#endif", CATEGORY_DIRECTIVE)
  935.    add_syntax_item(type, KEYWORD, "#else", CATEGORY_DIRECTIVE)
  936.    add_syntax_item(type, KEYWORD, "#elif", CATEGORY_DIRECTIVE)
  937.    add_syntax_item(type, KEYWORD, "#include", CATEGORY_DIRECTIVE)
  938.    add_syntax_item(type, KEYWORD, "#define", CATEGORY_DIRECTIVE)
  939.    add_syntax_item(type, KEYWORD, "#undef", CATEGORY_DIRECTIVE)
  940.    add_syntax_item(type, KEYWORD, "defined", CATEGORY_DIRECTIVE)
  941.  
  942.    add_syntax_item(type, KEYWORD, "while", CATEGORY_RESERVED)
  943.    add_syntax_item(type, KEYWORD, "if", CATEGORY_RESERVED)
  944.    add_syntax_item(type, KEYWORD, "else", CATEGORY_RESERVED)
  945.    add_syntax_item(type, KEYWORD, "for", CATEGORY_RESERVED)
  946.    add_syntax_item(type, KEYWORD, "do", CATEGORY_RESERVED)
  947.    add_syntax_item(type, KEYWORD, "continue", CATEGORY_RESERVED)
  948.    add_syntax_item(type, KEYWORD, "typedef", CATEGORY_RESERVED)
  949.    add_syntax_item(type, KEYWORD, "enum", CATEGORY_RESERVED)
  950.    add_syntax_item(type, KEYWORD, "virtual", CATEGORY_RESERVED)
  951.    add_syntax_item(type, KEYWORD, "private", CATEGORY_RESERVED)
  952.    add_syntax_item(type, KEYWORD, "public", CATEGORY_RESERVED)
  953.    add_syntax_item(type, KEYWORD, "protected", CATEGORY_RESERVED)
  954.  
  955.    add_syntax_item(type, KEYWORD, "return", CATEGORY_RESERVED)
  956.    add_syntax_item(type, KEYWORD, "switch", CATEGORY_RESERVED)
  957.    add_syntax_item(type, KEYWORD, "case", CATEGORY_RESERVED)
  958.    add_syntax_item(type, KEYWORD, "break", CATEGORY_RESERVED)
  959.    add_syntax_item(type, KEYWORD, "new", CATEGORY_RESERVED)
  960.    add_syntax_item(type, KEYWORD, "delete", CATEGORY_RESERVED)
  961.    add_syntax_item(type, KEYWORD, "default", CATEGORY_RESERVED)
  962.    add_syntax_item(type, KEYWORD, "this", CATEGORY_RESERVED)
  963.  
  964.    add_syntax_item(type, KEYWORD, "extern", CATEGORY_RESERVED)
  965.  
  966.    add_syntax_item(type, KEYWORD, "NULL", CATEGORY_CONSTANT)
  967.  
  968.    add_syntax_item(type, KEYWORD, "{", CATEGORY_RESERVED)
  969.    add_syntax_item(type, KEYWORD, "}", CATEGORY_RESERVED)
  970.  
  971.    add_syntax_item(type, BLOCK, "/* */", CATEGORY_COMMENT)
  972.    add_syntax_item(type, LINE, "//", CATEGORY_COMMENT)
  973.    add_syntax_item(type, LINE, "\" \"", 0x010000 + CATEGORY_LITERAL)
  974.  
  975.    set_style_delimiters(type, "()[];:,=");
  976.    set_escape_character(type, "\\");
  977. }
  978.