Contents 
 Index 
 "Perl Program Reference" 
 < Previous 
 Next > 

find_extract.pl

Go to the documentation of this file.
00001 // This file has been modified on-the-fly with an input filter
00002 // to change it from Perl syntax to C++ strictly for the purposes
00003 // of faking out Doxygen. Modifications include:
00004 
00005 // - changing local() definitions to C++ #define statements.
00006 // - commenting out undef statements.
00007 // - changing $globe'... variable names to $globe_...
00008 // - changing sub statements to look like C++ functions.
00009 // - changing # comments to C++ comments.
00010 // - ...
00011 
00012 // If you see other strangeness in the HTML version of the Perl file,
00013 // it comes from getting it to look more C++ like.
00014 
00015 
00016 // #!/usr/#define/bin/perl
00017 package xhelp;
00018 //#############################################################################
00019 /** @file
00020  ** @brief Generates a file with command definitions and doxygen comments,
00021  ** intended as input to Doxgyen without as much noise.
00022  ** 
00023  ** xhelp_gen.pl input_scope_package root_path_to_files output_file
00024  **
00025  ** @param input_scope_package A file path and name to a perl package that has the 
00026  ** 2-b-included and 2-b-excluded xhelp commands.
00027  **
00028  ** @param root_path_to_files must be terminated with a forward (\/) slash.
00029  ** If output file does not have a forward slash (\/) -- an indication
00030  ** of a path --, then the <root path to files> is assumed.
00031  **
00032  ** @param output_file name of the first output file. This plus another file
00033  ** with a leading underscore are generated. 
00034  ** The file without the underscore is intended as the input to Doxygen.
00035  **
00036  ** The input scope package is required to have:<ul>
00037  **
00038  ** <li>The xscope package definition.</li>
00039  ** <li>Routine: <ul>
00040  **    <li>declare_variable.</li>
00041  **    <li>Routine: memory_clean_up.</li>
00042  ** </ul></li>
00043  ** <li>Array: <ul>
00044  **    <li>x_names, which contains all prefixes that could be of interest.</li>
00045  **    <li>needed_in, which contains a list of xhelp commands that are
00046  ** absolutely needed-to-be-in.</li>
00047  **    <li>needed_out, which contains a list of commands that we don't
00048  ** want to expose at all if they happen to come through.</li>
00049  **    <li>include_f_type, which are file types that should be viewed.</li>
00050  ** </ul></li>
00051  ** </ul>
00052  **
00053  ** The definitions of "clues" in the xscope file is the key to the success
00054  ** of this tool. It needs a hint on what to look for.
00055  **
00056  ** @note The @ingroup designation was the most useful tag for this tool
00057  ** when standards in Doxygen comments were followed.
00058  **
00059  ** The intent is that different projects can define their own files that have
00060  ** the xscope definitions of what to look for.
00061  **
00062  ** This program does divide and conquor. <ol>
00063  **
00064  ** <li>Using the prefix list, it greps through the code looking at the file
00065  ** types of interest.</li>
00066  ** <li>Using the command list, it greps through the code looking at the file
00067  ** types of interest.</li>
00068  ** <li>The temporary file with grep results is stripped of interesting entries.</li>
00069  ** <li>A file hash is created that is a hash of hashes. <br>
00070  ** <pre>$file_hash {$src_file} {$code_item} {r} {$return_type} = unimportant number </pre>
00071  ** <pre>$file_hash {$src_file} {$code_item} {p} {$prototype} = doxygen </pre>
00072  ** It contains:<ul>
00073  ** <li>{$src_file} the source code files where items of interest were found.</li>
00074  ** <li>{$code_item} code items of interest, each associated with a source file.</li>
00075  ** <li>{r} {$return_type} a hash of return types for each code item; supports
00076  ** overloading.</li>
00077  ** <li>{p} {$prototype} a hash of code definitions for each code item; supports
00078  ** overloading. It contains to the doxygen comment block.</li>
00079  ** </ul></li>
00080  ** <li>The source files from the hash are opened and searched for their respective
00081  ** code item definitions.</li>
00082  ** <li>The source files are searched for comment blocks associated with
00083  ** the code item definitions.</li>
00084  ** <li>The file hash is fleshed out for the prototype definitions and 
00085  ** their respective comment blocks.</li>
00086  ** <li>The file hash is stepped through and output to generated files.
00087  ** The generated files are intended for input to doxygen.
00088  ** <ol>
00089  ** <li>_list_<name>.gen file is for accountability and lists all code items and 
00090  ** whether or not they were accompanied by a doxygen template. This is
00091  ** sorted by source file name. Intended to communicate what is in and out.</li>
00092  ** <li><name>.gen contains a fake function definition with the associated 
00093  ** doxygen template. This list is sorted by code item. Intended for xhelp.
00094  ** <li>class_<name>.gen file contains a fake class definition with the associated doxygen 
00095  ** template. This list is sorted by class name. Intended for APIs implemented
00096  ** through classes (e.g., DSP drivers). Generated when $xscope::sapi==0.</li>
00097  ** <li>dox_template_<name> contains just the associated doxygen template. The
00098  ** list is sorted based on the @fn code item name. Intented for SAPI in conjunction
00099  ** with the vproto.gen that has the function prototypes. Generated when
00100  ** $xscope::sapi==1; this is set in the sapi.pm file.</li>
00101  ** </ol></li>
00102  ** </ol>
00103  **
00104  ** @ingroup tp_tools tp_xhelp
00105  **
00106  ** @author Glenn C. Maxey
00107  **/
00108 // #
00109 //#    $Id: find_extract.pl,v 1.1 2002/12/24 15:05:51 gmaxe Exp $
00110 //#
00111 //# Copyright 2002 Created by Voyant Technologies, Inc., Westminster, Colorado, USA.
00112 //#
00113 //# Revision Information:
00114 //#
00115 //# $Log: find_extract.pl,v $
00116 //# Revision 1.1  2002/12/24 15:05:51  gmaxe
00117 //# New name and tweaks to add full paths.
00118 //#
00119 //# Revision 1.13  2002/11/20 15:23:10  gmaxe
00120 // //# Added exit codes so that wrapper scripts can catch errors properly.
00121 //#
00122 //# Revision 1.12  2002/07/29 22:46:07  gmaxe
00123 //# Enhanced list output to support _TBD_.
00124 //#
00125 //# Revision 1.11  2002/07/26 18:56:15  gmaxe
00126 //# Got rid of old definitions and migrated new structures into all;
00127 //# enhanced xhelp output file names and format; now everything is
00128 //# alphebetized.
00129 //#
00130 //# Revision 1.9  2002/06/10 21:45:05  gmaxe
00131 //# Updated output to alphebetize things when possible.
00132 //# PTR#: 1-09T1
00133 //#
00134 //# Revision 1.8  2002/04/24 00:08:57  gmaxe
00135 //# Improved how items are excluded from xhelp_gen.pl, because
00136 //# they were creeping back in when file got processed.
00137 //#
00138 //# Revision 1.7  2002/04/12 18:01:17  gmaxe
00139 //# Various tweaks; work on tag extraction and change_nav;
00140 //# more exclused special perl characters from indexer;
00141 //# improved support for sapi group pm files in xhelp.
00142 //# spider tool now works regularly and as expected.
00143 //#
00144 //# Revision 1.6  2002/03/28 21:20:51  gmaxe
00145 //# Added support for ingroup extraction.
00146 //#
00147 //# Revision 1.5  2002/03/25 22:50:09  gmaxe
00148 //# Fixed another perl special character problem in index;
00149 //# Fixed a naming problem in xhelp gen.
00150 //#
00151 //# Revision 1.4  2002/03/21 23:26:49  gmaxe
00152 //# Minor doc changes to indexer;
00153 //# xhelp enhanced s.t. it generates class files when needed.
00154 //#
00155 //# Revision 1.3  2002/02/21 19:54:09  gmaxe
00156 //# Improved comments and reliability.
00157 //#
00158 //# Revision 1.2  2002/02/21 01:39:00  gmaxe
00159 //# Working version of xhelp command extractor and prototype generator.
00160 //#
00161 //#############################################################################
00162 
00163 //#############################################################################
00164 /** @fn int BEGIN
00165  ** @brief Code to execute when first entered.
00166  **
00167  ** @param None. 
00168  **
00169  ** @return None.
00170  **
00171  ** @lim None
00172  ** @ingroup tp_xhelp
00173  **/
00174 // #############################################################################
00175 int BEGIN  ( ) {
00176 //    print "\n============  Starting xhelp_gen.pl ==================================\n";
00177    $_file_list = "_file_list";
00178    $in_file = "";
00179    $root_path = "./";
00180    $scope_pm = "";
00181    $no_scope_file = 0;
00182    $xscope::sapi = 0; //  This is set in the generated sapi.pm; When needed, will be overwritten by pm file.
00183    
00184    push (@INC, `pwd`);
00185    push (@INC, '../perl');
00186    if (0){
00187 //       print (@INC, "\n");
00188    }
00189    
00190    //  Get scope files if there is one.
00191    if (@ARGV > 0) {
00192       $scope_pm = @ARGV[0];
00193       
00194       unless (open ( IN_LIST, $scope_pm)) {
00195          push (@file_errors, "Cannot open file \"$scope_pm\"\n");
00196          $no_scope_file++;
00197       }
00198 //       close (IN_LIST);
00199       push (@INC, $scope_pm);
00200       
00201       if (!@file_errors) {
00202          // ####
00203          //  All global variables are defined in the following file
00204          // ####
00205          require $scope_pm;
00206    
00207          if (&xscope::declare_variables()) {
00208 //             print "Variables initialized from $scope_pm.\n";
00209          } else {
00210             push (@file_errors, "Could not initialize variables from $scope_pm.\n");
00211          }
00212       } //  if not @file_errors
00213    } else {
00214       push (@file_errors, "Need to provide a scope file as first argument.\n");
00215    } //  if 1 or more arguments
00216 
00217    //  Get path to code files 
00218    if (@ARGV > 1) {
00219       $root_path = @ARGV[1];
00220       if ($root_path =~ /\/$/) {
00221 //          print "The path specified is $root_path\n";
00222       } else {
00223          push (@file_errors, "The input argument \"$root_path\" requires a forward slash (\/) at the end.\n");
00224       }
00225    } //  if 1 or more arguments
00226 
00227    if (@ARGV > 2) {
00228       $gen_proto = @ARGV[2];
00229       if ($gen_proto !~ /\//) {
00230          //  if the output file does not have a path, then
00231          //  put it in the root location
00232          if (1) {
00233             @chunk = split (/\./, $gen_proto);
00234             $last = pop (@chunk);
00235             $all = join ("\.", @chunk);
00236             $gen_list = join ("", $root_path, $all, "_list.", $last);
00237             $gen_class = join ("", $root_path, $all, "_class.", $last);
00238             $gen_template = join ("", $root_path, $all, "_dox_template.", $last);
00239             $gen_proto = "$root_path$gen_proto";
00240          }
00241       } else {
00242          if (1) {
00243             @chunk = split (/\./, $gen_proto);
00244             $last = pop (@chunk);
00245             $all = join ("\.", @chunk);
00246             $gen_list = join ("", $all, "_list.", $last);
00247             $gen_class = join ("", $all, "_class.", $last);
00248             $gen_template = join ("", $all, "_dox_template.", $last);
00249          }
00250       }
00251 //       print "Potential output files are: \n";
00252 //       print "\tlist: \t$gen_list\n";
00253 //       print "\tproto:\t$gen_proto\n";
00254 //       print "\tclass:\t$gen_class\n";
00255 //       print "\tdox:  \t$gen_template\n";
00256    } else {
00257       push (@file_errors, "Need to have the output prototype file.\n");
00258    } //  if 3 or more arguments
00259 
00260 } //  BEGIN
00261    
00262    
00263    
00264 
00265 //#############################################################################
00266 /** @fn int main
00267  ** @brief The main program.
00268  **
00269  ** @param file_errors If file errors are encountered before the main
00270 //  ** routine is hit, it prints them out and exits. 
00271  **
00272  ** @return None.
00273  **
00274  ** Controls the program flow. It creates a temporary file with the
00275  ** grep results, processes the temporary file, creates a file hash
00276  ** with source code targets, then outputs files needed for Doxgyen.
00277  **
00278  ** @lim None
00279  ** @ingroup tp_xhelp
00280  **/
00281 // #############################################################################
00282 // sub main {
00283 {
00284    // #############################################################################
00285    // # Start of Main Program
00286    // #############################################################################
00287    if (@file_errors) {
00288       //  Makes no sense to go on if input parameters are off.
00289 //       print "\n============  Summary of errors ==================================\n";
00290       for ($i=0; $i<@file_errors; $i++){
00291 //          print "$i = $file_errors[$i]\n";
00292       }
00293       &xhelp::using_xhelp();
00294 //       exit(1);
00295    }
00296 
00297    $_file_list = $root_path . "_eraseme";
00298    if (1){
00299       if (&create_xhelp_grep_results($_file_list) == 0) {
00300          &create_xhelp_hash($_file_list);
00301       } else {
00302 //          print "Cannot create file list\n";
00303 //          exit(0);
00304       }
00305    } //  if test
00306 
00307    $_file_list = $root_path . "_eraseme2";
00308    if (1){
00309       if (&create_ingroup_grep_results($_file_list) == 0) {
00310          &create_ingroup_hash($_file_list);
00311       } else {
00312 //          print "Cannot create file list\n";
00313 //          exit(0);
00314       }
00315    } //  if test
00316 
00317    if (1) {
00318       &process_ingroup_hash();
00319    }
00320    
00321    &process_file_hash();
00322    if (1) {
00323       &write_output_list("$gen_list");
00324    }
00325    if (1) {
00326       if ($xscope::sapi) {
00327          //  This will generate the file only having doxygen templates
00328          //  and no fake function prototypes.
00329          &write_output_class("$gen_template");
00330       } else {
00331          //  This will generate a file with fake class and member 
00332          //  function prototypes with associated doxygen templates.
00333          &write_output_class("$gen_class");
00334       }
00335    }
00336    if (1) {
00337       if ($xscope::sapi) {
00338          //  The output file is not meaningful for SAPI, because
00339          //  it has class member functions.
00340       } else {
00341          &write_output_file($gen_proto);
00342       }
00343       
00344    }
00345    
00346    // #############################################################################
00347    // # Spit out errors
00348    // #############################################################################
00349    if (@file_errors) {
00350 //       print "\n============  Summary of errors ==================================\n";
00351       for ($i=0; $i<@file_errors; $i++){
00352 //          print "$i = $file_errors[$i]\n";
00353       }
00354    }
00355 
00356    // #############################################################################
00357    // # End of most of work
00358    // #############################################################################
00359 //    exit(0);
00360 }
00361 
00362 //#############################################################################
00363 /** @fn int create_xhelp_grep_results
00364  ** @brief Creates a temporary file that contains the grep results.
00365  **
00366  ** @param _file_list A temporary file created from the grep calls.
00367  **
00368  ** @return The file is created in the directory given by the first input
00369  ** parameter to the program.
00370  **
00371  ** The xscope::x_names and xscope::needed_in arrays are used to trigger
00372  ** the grep, which starts from the $root_path (input argument) directory.
00373  **
00374  ** @lim This routine is really snow due to the number of system grep
00375  ** calls it makes.
00376  **
00377  ** @ingroup tp_xhelp
00378  **/
00379 // #############################################################################
00380 int create_xhelp_grep_results  ( ) {
00381    #define $in_file_list  $_[0]
00382 
00383    system ("echo \"\n\" > $in_file_list");
00384 
00385    if ((1) && (@xscope::x_names)) {
00386       //  Greps for the prefix names over the supported file types.
00387 //       print "Grepping for prefix names in code...\n";
00388       foreach $xword (@xscope::x_names){
00389          foreach $f_type (@xscope::include_f_type) {
00390             if (0) {
00391 //                print "xword=$xword $f_type in $root_path\n";
00392             }
00393 //             print ("grep \"$xword\" \`find $root_path -name \"\*\.$f_type\" -print\`  >> $in_file_list\n");
00394 //             system ("grep \"$xword\" \`find $root_path -name \"\*\.$f_type\" -print\`  >> $in_file_list");
00395          } //  foreach $f_type 
00396       } //  foreach $xword
00397    } //  if (0)
00398    if ((1) && (@xscope::needed_in)) {
00399       //  Greps for explicit command names that are needed over the supported file types.
00400 //       print "Grepping for command names in code...\n";
00401       foreach $xword (@xscope::needed_in){
00402          foreach $f_type (@xscope::include_f_type) {
00403             if (0) {
00404 //                print "xword=$xword $f_type in $root_path\n";
00405             }
00406 //             print ("grep \"$xword\" \`find $root_path -name \"\*\.$f_type\" -print\`  >> $in_file_list\n");
00407 //             system ("grep \"$xword\" \`find $root_path -name \"\*\.$f_type\" -print\`  >> $in_file_list");
00408          } //  foreach $f_type 
00409       } //  foreach $xword
00410    } //  if (0)
00411    
00412    return (0);
00413 } //  create_xhelp_grep_results
00414 
00415 
00416 
00417 //#############################################################################
00418 /** @fn int create_xhelp_hash
00419  ** @brief Creates a hash of hashes from the grep results that #defineize
00420  ** target source files and code items to look for in those files.
00421  **
00422  ** @param _file_list A temporary file created from the grep calls.
00423  **
00424  ** @return The $file_hash, a hash of hashes, is created.
00425  ** $file_hash {$src_file} {$code_item} {r} {$return_type} = unimportant number
00426  ** $file_hash {$src_file} {$code_item} {p} {$prototype} = doxygen
00427  **
00428  ** Although a simpler structure could be created, this has the advantage
00429  ** that when a source file is opened, we know exactly what code items to
00430  ** search for in that file.
00431  **
00432  ** The {r} and {p} hash layer helps separate return type definitions from
00433  ** prototype definitions. Moreover, the subsequent hashes for {$return_type}
00434  ** and {$prototype} support overloading.
00435  **
00436  ** This routine steps through the output file created by the grep calls.
00437  ** It strips out uninteresting things that grep finds, like hits within
00438  ** comments.
00439  **
00440  ** @lim This routine fills in the {$return_type} hash, which gets used later
00441  ** to help locate commands in code. The {$prototype} hashes get filled in
00442  ** later.
00443  **
00444  ** @ingroup tp_xhelp
00445  **/
00446 // #############################################################################
00447 int create_xhelp_hash  ( ) {
00448    #define $in_file_list  $_[0]
00449 //    print "Creating command hash from grep results...\n";
00450 
00451    unless (open ( IN_LIST, $in_file_list)) {
00452 //       print "Cannot open file \"$in_file_list\"\n";
00453       push (@file_errors, "Cannot open file \"$in_file_list\"\n");
00454 //       exit(1);
00455    }
00456    
00457    $_cnt=0;
00458    $_xcnt=0;
00459    X_INCOMING:   while (<IN_LIST>){    //  read a line from file into $_
00460       if ((/^\n/) || (!/\S+/)){
00461          //  get rid of blank lines
00462          next X_INCOMING;
00463       }
00464       if ($_cnt > 4) {
00465 //          exit(1);
00466       }
00467       @line_chunk = split (/\:/, $_, 2);
00468       if (0) {
00469 //          print "[0]==$line_chunk[0]\n";
00470 //          print "[1]==$line_chunk[1]\n";
00471          $_cnt++;
00472 //          //  exit(1);
00473       }
00474       // ####
00475       //  Get rid of comment lines so they don't give us a spurious hit.
00476       // ###
00477       if (($line_chunk[1] =~ /^\/\//) || ($line_chunk[1] =~ /\*\*/)) {
00478          //  get rid of comment lines
00479          if (0) {
00480 //             print "trashing==$line_chunk[1]";
00481          }
00482          next X_INCOMING;
00483       }
00484       // ####
00485       //  Get rid of things known to be code specific and not prototypes
00486       //  or definitions.
00487       //  6/10/2002 added /[\s]*\)[\s]*\:/ test
00488       // ###
00489       if (($line_chunk[1] =~ /switch/) 
00490 //          || ($line_chunk[1] =~ /printf/) 
00491          || ($line_chunk[1] =~ /\;[\s]*$/) 
00492          || ($line_chunk[1] =~ /[\s]*\=[\s]*/) 
00493          || ($line_chunk[1] =~ /[\s]+if[\s]*\(/) 
00494          || ($line_chunk[1] =~ /^[\s]*return/) 
00495          || ($line_chunk[1] =~ /[\s]*\)[\s]*\:/) 
00496          || ($line_chunk[1] =~ /^\// /)) {
00497          //  get rid of program lines
00498          if (0) {
00499 //             print "trashing==$line_chunk[1]";
00500          }
00501          next X_INCOMING;
00502       }
00503       @code_chunk = split (/\(/, $line_chunk[1], 2);
00504       if ($// code_chunk > 0) {
00505          foreach $exclude (@xscope::needed_out) {
00506             if (0) {
00507 //                print "exclude me: $exclude\n";
00508             }
00509             //  Jump over any commands that we are told to specifically exclude.
00510             if ($code_chunk[0] =~ /$exclude/) {
00511                if (0) {
00512 //                   print "exclude me \"$exclude\" from $code_chunk[0]\n";
00513                }
00514                next X_INCOMING;
00515             }
00516          }
00517          if (0) {
00518 //             //  print "$line_chunk[1]";
00519 //             //  print "$_";
00520 //             print "nnn $code_chunk[0]\n";
00521          }
00522          if ($code_chunk[0] =~ /[\S+]/){
00523             @ode_name = split (/\s/, $code_chunk[0]);
00524             $_name = $ode_name[$// ode_name];
00525             if (0){
00526 //                print "ooo $_xcnt\:\:$code_chunk[0]>>> $_name\n";
00527             }
00528          } else {
00529             if (0){
00530 //                print "ooo2 $_xcnt\:\:$code_chunk[0]\n";
00531             }
00532          }
00533          // ####
00534          //  If we made it this far without doing a "next X_INCOMING" then
00535          //  [1]  $line_chunk[0] contains the file of interest;
00536          //  [2]  $code_chunk[0] contains the return type and item name.
00537          //  [3]  $_name is the item name.
00538          //  Let's put the code items into the file hash to speed up our process.
00539          // 
00540          //  Need to handle function overloading, so
00541          // 
00542          //  $file_hash {files} {code items} {r} {return types}
00543          // 
00544          //  We don't care about what it points to.
00545          // ####
00546          $file_hash{$line_chunk[0]}{$_name}{r}{$code_chunk[0]} = $_xcnt;
00547          
00548          $_xcnt++;
00549       } //  if ($#code_chunk > 0)
00550    } //  while X_INCOMING
00551 
00552 
00553    // #####
00554    //  What is or will be in file hash
00555    //  $file_hash{$src_file}{$code_item}{r}{$return_type} = number
00556    //  $file_hash{$src_file}{$code_item}{p}{$prototype} = doxygen
00557    // #####
00558 
00559    if (0){ //  
00560       foreach $src_file (sort keys %file_hash){
00561          foreach $code_item (sort keys %{$file_hash{$src_file}} ){
00562             foreach $return_type (sort keys %{$file_hash{$src_file}{$code_item}{r}} ) {
00563 //                //  print "$code_item :: $return_type :: $src_file\n";
00564 //                print "$code_item\n";
00565             }
00566          }
00567       }
00568       if (0){
00569 //          exit(1);
00570       }
00571    } //  if test
00572    return (1);
00573 
00574 } //  create_xhelp_hash
00575 
00576 
00577 //#############################################################################
00578 /** @fn int process_file_hash
00579  ** @brief Steps through each source file looking for the code items to
00580  ** be extracted.
00581  **
00582  ** @return Fleshes out the file hash with information about the prototype.
00583  **
00584  **  $file_hash {$src_file} {$code_item} {r} {$return_type} = number
00585  **  $file_hash {$src_file} {$code_item} {p} {$prototype} = doxygen
00586  **  
00587  ** {$src_file}  the file of interest;
00588  ** {$code_item}  the item name within the file of interest.
00589  ** {r} flag for return types.
00590  ** {r} {$return_type} hash of return types associated with code item, to
00591  ** handle overloaded functions.
00592  ** {p} flag for prototypes.
00593  ** {p} {$prototype} hash of prototypes associated with code item and handles
00594  ** overloaded functions. It points to associated doxygen comments.
00595  **
00596  ** The routine opens each source file and reads it into $src_content. 
00597  ** For each {$src_file} {$code_item}, split on the item's {$return_type}.
00598  ** Determine whether it is a definition (ok) or prototype (ignore).
00599  ** Extract the prototype definition.
00600  ** Look for Doxygen comments right before split.
00601  ** Divide and conquor; keep splitting the halves until there are no more
00602  ** {$return_type} in.
00603  ** Create a {p} {$prototype} hash entry that points to the doxygen comments.
00604  **
00605  ** @lim When this reads in the source file, it changes //! style comments
00606  ** into /** ... */ comment blocks. Also, straight comment lines beginning
00607  ** with // are outright ignored.
00608  **
00609  ** @ingroup tp_xhelp
00610  **/
00611 // #############################################################################
00612 int process_file_hash  ( ) {
00613    #define $src_content  ""
00614    
00615    if (0){ //  
00616       foreach $src_file (sort keys %file_hash){
00617          foreach $code_item (sort keys %{$file_hash{$src_file}} ){
00618             foreach $return_type (sort keys %{$file_hash{$src_file}{$code_item}{r}} ) {
00619 //                print "ppp $file_hash{$src_file}{$code_item}{r}{$return_type} :: $src_file + $code_item\n";
00620             }
00621          }
00622       }
00623       if (0){
00624 //          exit(1);
00625       }
00626    } //  if test
00627 
00628    
00629    SRC_IN: foreach $src_file (sort keys %file_hash){
00630       //  for each file that has a code item of interest
00631       unless (open ( IN_SRC, $src_file)) {
00632 //          print "Cannot open file \"$src_file\"\n";
00633          push (@file_errors, "Cannot open file \"$src_file\"\n");
00634          next SRC_IN;
00635       }
00636       if (0) {
00637 //          print "Source file is: $src_file\n";
00638       }
00639 
00640       // undef ($src_content);  //  start fresh
00641       //  read file into memory
00642       while (<IN_SRC>) {
00643          // ######## 
00644          //  Read in the source file, but change Doxygen comment syntax
00645          //  so that it is consistent throughout whole file.
00646          //  Begin replacement of //! comments with /** ... **/ comments
00647          // ######## 
00648          if (/^\/\/\!/) {
00649             if ($comment_count == 0){
00650                //  first line of a comment block
00651                $comment_count++;
00652                $_ =~ s/\/\/\!/\/\*\*/;
00653             } else {
00654                //  Some line in the middle of a comment block.
00655                $comment_count++;
00656                // ##
00657                //  Changed to have middle stuff with no asterix.
00658                //  $_ =~ s/\/\/\!/ \*\*/;
00659                // ##
00660                $_ =~ s/\/\/\!//;
00661             }
00662          } elsif ($comment_count > 0){
00663             //  We were in a comment block; need to terminate it.
00664             $comment_count = 0;
00665             $_ = " \*\*\/\n" . $_ ;
00666          }
00667          // ######## End Comment style change.
00668          
00669          // ########
00670          //  Trash all lines beginning with a comment.
00671          // ########
00672          if (/^\/\//) {
00673             //  Don't mess with comment lines.
00674          } elsif ((/^\/\*/) && (/\*\/$/)) {
00675             //  Don't mess with lines that begin and end as a coment
00676          } else {
00677             //  Remember everything else
00678             $src_content .= $_;
00679          }
00680 
00681       } //  reading in source file
00682       
00683       //  for each code item of interest within the file
00684       CODE_ITEM: foreach $code_item (sort keys %{$file_hash{$src_file}}) {
00685          OVERLOAD_ITEM: foreach $return_type (sort keys %{$file_hash{$src_file}{$code_item}{r}}) {
00686             //  for each overloaded return code item
00687       
00688             $split_string = $return_type;
00689             
00690             if (0) { //  06/10/2002 attempt to filter split_string
00691               //  Attempt to get rid of bogus characters that will screw with pattern
00692               //  matching.
00693               if ($split_string =~ /\)/) {
00694                 //  if it has a closing ), then it has to
00695                 //  have an opening (, otherwise it is of no
00696                 //  interest and will mess with us later.
00697                 if ($split_string !~ /\(/) {
00698                    next OVERLOAD_ITEM;
00699                 }
00700               }
00701             } //  attempt to filter split_string
00702          
00703             $search_chunk = $src_content;
00704             $prototype = "NEXT_ONE";
00705             $prot_cnt = 0;
00706          
00707             //  Handle overloaded or multiple occurrences.
00708             SOME_ITEM: while ($search_chunk =~ /$split_string/) {
00709                @file_piece = split (/$split_string/, $search_chunk, 2);
00710   
00711                $prototype = &inside_parenthesis ($file_piece[1]);
00712                $search_chunk = $file_piece[1];
00713                if ($prototype =~ /NEXT_ONE/) {
00714                   //  what we have is the prototype and not 
00715                   //  the desired definition
00716                } else {
00717                   // #####
00718                   //  this is the desired definition
00719                   // #####
00720 
00721                   $prototype = "$split_string$prototype";
00722 
00723                   // ####
00724                   //  4/23/2002 Noticed that excluded items were creeping back in.
00725                   //  This tests for them again and removes them.
00726                   // ####
00727                   foreach $exclude (@xscope::needed_out) {
00728                      //  Jump over any commands that we are told to specifically exclude.
00729                      if ($prototype =~ $exclude) {
00730                         if (0) {
00731 //                            print "==============\nExclude key \"$exclude\" of $prototype\n+++++++\n";
00732                         }
00733                         next SOME_ITEM;
00734                      }
00735                   }
00736                   
00737                   $prototype .= "\n\{\n   \/\/ Generated prototypes.\n\}\n";
00738                   if (0) {
00739 //                      print "The definition:\n$prototype=====\n";
00740                   }
00741 
00742                   // #####
00743                   //  Find the doxygen comments immediately prior to definition
00744                   //  Note that file_piece[0] is not necessarily the first half of
00745                   //  the file; it is from either the beginning of the file or
00746                   //  the first prototype.
00747                   // #####
00748                   $doxygen = &find_doxygen ($file_piece[0]);
00749                   if ($doxygen =~ /NO_DOX_COMMENT/) {
00750                      $doxygen = "\/\/ $doxygen\n";
00751                   } 
00752                   $file_hash{$src_file}{$code_item}{p}{$prototype} = $doxygen;
00753 
00754                } //  NEXT_ONE
00755                
00756             } //  while $search_chunk;  there is still something that looks interesting
00757  
00758             if (0) {
00759 //                //  print "split=$split_string\n";
00760 //                print "prototype=\n$prototype\n";
00761 //                print "doxygen=\n$doxygen\n";
00762             }
00763          } //  foreach OVERLOAD_ITEM 
00764       } //  foreach CODE_ITEM 
00765 //       close (SRC_IN);
00766    } //  foreach SRC_IN
00767 } //  process_file_hash
00768 
00769 //#############################################################################
00770 /** @fn int create_ingroup_grep_results
00771  ** @brief Creates a temporary file that contains the grep results.
00772  **
00773  ** @param _file_list A temporary file created from the grep calls.
00774  **
00775  ** @return The file is created in the directory given by the first input
00776  ** parameter to the program.
00777  **
00778  ** The xscope::x_names and xscope::needed_in arrays are used to trigger
00779  ** the grep, which starts from the $root_path (input argument) directory.
00780  **
00781  ** @lim This routine is really snow due to the number of system grep
00782  ** calls it makes.
00783  **
00784  ** @ingroup tp_xhelp
00785  **/
00786 // #############################################################################
00787 int create_ingroup_grep_results  ( ) {
00788    #define $in_file_list  $_[0]
00789 
00790    system ("echo \"\n\" > $in_file_list");
00791 
00792    if ((1) && (@xscope::ingroup)) {
00793       //  Greps for the prefix names over the supported file types.
00794 //       print "Grepping for prefix names in code...\n";
00795       foreach $xword (@xscope::ingroup){
00796          foreach $f_type (@xscope::include_f_type) {
00797             if (0) {
00798 //                print "xword=$xword $f_type in $root_path\n";
00799             }
00800 //             print ("grep \"$xword\" \`find $root_path -name \"\*\.$f_type\" -print\`  >> $in_file_list\n");
00801 //             system ("grep \"$xword\" \`find $root_path -name \"\*\.$f_type\" -print\`  >> $in_file_list");
00802          } //  foreach $f_type 
00803       } //  foreach $xword
00804    } //  if (0)
00805    return (0);
00806 } //  create_ingroup_grep_results
00807 
00808 
00809 //#############################################################################
00810 /** @fn int create_ingroup_hash
00811  ** @brief Creates a hash of hashes from the grep results that #defineize
00812  ** target source files and code items to look for in those files.
00813  **
00814  ** @param _file_list A temporary file created from the grep calls.
00815  **
00816  ** @return The $file_hash, a hash of hashes, is created.
00817  ** $file_hash {$src_file} {$code_item} {r} {$return_type} = unimportant number
00818  ** $file_hash {$src_file} {$code_item} {p} {$prototype} = doxygen
00819  **
00820  ** This looks for @ingroup places in the code comments.
00821  **
00822  ** Although a simpler structure could be created, this has the advantage
00823  ** that when a source file is opened, we know exactly what code items to
00824  ** search for in that file.
00825  **
00826  ** The {r} and {p} hash layer helps separate return type definitions from
00827  ** prototype definitions. Moreover, the subsequent hashes for {$return_type}
00828  ** and {$prototype} support overloading.
00829  **
00830  ** This routine steps through the output file created by the grep calls.
00831  ** It strips out uninteresting things that grep finds, like hits within
00832  ** comments.
00833  **
00834  ** @lim This routine fills in the {$return_type} hash, which gets used later
00835  ** to help locate commands in code. The {$prototype} hashes get filled in
00836  ** later.
00837  **
00838  ** @ingroup tp_xhelp
00839  **/
00840 // #############################################################################
00841 int create_ingroup_hash  ( ) {
00842    #define $in_file_list  $_[0]
00843 //    print "Creating command hash from grep results...\n";
00844 
00845    unless (open ( IN_LIST, $in_file_list)) {
00846 //       print "Cannot open file \"$in_file_list\"\n";
00847       push (@file_errors, "Cannot open file \"$in_file_list\"\n");
00848 //       exit(1);
00849    }
00850    
00851    $_cnt=0;
00852    $_xcnt=0;
00853    X_INCOMING:   while (<IN_LIST>){    //  read a line from file into $_
00854       if ((/^\n/) || (!/\S+/)){
00855          //  get rid of blank lines
00856          next X_INCOMING;
00857       }
00858       if ($_cnt > 4) {
00859 //          exit(1);
00860       }
00861       @line_chunk = split (/\:/, $_, 2);
00862       if (0) {
00863 //          print "[0]==$line_chunk[0]\n";
00864 //          print "[1]==$line_chunk[1]\n";
00865          $_cnt++;
00866 //          //  exit(1);
00867       }
00868       // ####
00869       //  Get rid of all non-comment lines so they don't give us a spurious hit.
00870       // ###
00871       if (($line_chunk[1] =~ /^\/\//) || ($line_chunk[1] =~ /\*\*/)) {
00872          //  These are the ones we want.
00873          if (0) {
00874 //             print "keep1==$line_chunk[1]";
00875          }
00876       } else {
00877          //  get rid of non-comment lines
00878          if (0) {
00879 //             print "trashing1==$line_chunk[1]";
00880          }
00881          next X_INCOMING;
00882       }
00883       // ####
00884       //  Get rid of things known to be code specific and not comments
00885       //  containing the @ingroup designation
00886       // ###
00887       if ($line_chunk[1] =~ /\@ingroup/) {
00888          //  These are the ones we want.
00889          if (0) {
00890 //             print "keep2==$line_chunk[1]";
00891          }
00892       } else {
00893          //  get rid of program lines
00894          if (0) {
00895 //             print "trashing2==$line_chunk[1]";
00896          }
00897          next X_INCOMING;
00898       }
00899       //  Remove things from the line of no interest
00900       $line_chunk[1] =~ s/\/\/\![\s+]\@ingroup[\s+]//;
00901       if (0) {
00902 //          print "keep3==$line_chunk[1]";
00903       }
00904 
00905       //  Get the groups
00906       
00907       @group_chunk = split (/\s/, $line_chunk[1]);
00908       foreach $group (@group_chunk){
00909          // ####
00910          //  If we made it this far without doing a "next X_INCOMING" then
00911          //  [1]  $line_chunk[0] contains the file of interest;
00912          //  Let's put the code items into the file hash to speed up our process.
00913          // 
00914          // 
00915          //  $ingroup_hash {$files} {$group}
00916          // ####
00917          if ($group =~ /\*/) {
00918             //  /** style doxgyen comments could mess this up, as in
00919             //  ** @ingroup blah
00920             $group =~ s/\*//g;
00921          }
00922          if (0) {
00923 //             print "$_xcnt group==$group\n";
00924          }
00925          foreach $desired_group (@xscope::ingroup){
00926             if (0) {
00927 //                print "$_xcnt desired group==$desired_group\n";
00928             }
00929             if (($desired_group =~ /$group/i) && ($group =~ /$desired_group/i)){
00930                //  double testing assures that I'm not triggering on part of the
00931                //  group name.
00932                if (0) {
00933 //                   print "found==$group ;desired == $desired_group\n";
00934                }
00935                if (exists ($group_hash{$line_chunk[0]}{$group})) {
00936                   $group_hash{$line_chunk[0]}{$group} .= "\; $_xcnt";
00937                } else {
00938                   $group_hash{$line_chunk[0]}{$group} = "\; $_xcnt";
00939                }
00940                $_xcnt++;
00941             }
00942          }
00943       } //  $group
00944    } //  while X_INCOMING
00945 
00946    // #####
00947    //  What is or will be in group hash
00948    //  $group_hash{$src_file}{$group} = number
00949    // #####
00950 
00951    if (0){ //  
00952       foreach $src_file (sort keys %group_hash){
00953          foreach $group_item (sort keys %{$group_hash{$src_file}} ){
00954 //             print "$group_item :: $src_file :: $group_hash{$src_file}{$group_item}\n";
00955          }
00956       }
00957       if (0){
00958 //          exit(1);
00959       }
00960    } //  if test
00961    return (1);
00962 
00963 } //  create_ingroup_hash
00964 
00965 
00966 
00967 //#############################################################################
00968 /** @fn int process_ingroup_hash
00969  ** @brief Steps through each source file looking for the group items to
00970  ** be extracted.
00971  **
00972  ** @return Adds things to the file hash for later processing.
00973  **
00974  **  $file_hash {$src_file} {$code_item} {r} {$return_type} = number
00975  **  
00976  ** {$src_file}  the file of interest;
00977  ** {$code_item}  the item name within the file of interest.
00978  ** {r} flag for return types.
00979  ** {r} {$return_type} hash of return types associated with code item, to
00980  ** handle overloaded functions.
00981  **
00982  ** The routine opens each source file and reads it into $src_content. 
00983  ** For each {$src_file} {$group_item}, split on the item's @ingroup.
00984  **
00985  ** Find the code definition and get it into the file_hash.
00986  **
00987  ** @lim When this reads in the source file, it changes //! style comments
00988  ** into /** ... */ comment blocks. Also, straight comment lines beginning
00989  ** with // are outright ignored.
00990  **
00991  ** @ingroup tp_xhelp
00992  **/
00993 // #############################################################################
00994 int process_ingroup_hash  ( ) {
00995    #define $src_content  ""
00996    
00997    if (0){ //  
00998       foreach $src_file (sort keys %group_hash){
00999          foreach $group_item (sort keys %{$group_hash{$src_file}} ){
01000 //             print "$group_item :: $src_file :: $group_hash{$src_file}{$group_item}\n";
01001          }
01002       }
01003       if (0){
01004 //          exit(1);
01005       }
01006    } //  if test
01007 
01008    
01009    SRC_IN: foreach $src_file (sort keys %group_hash){
01010       //  for each file that has a code item of interest
01011       unless (open ( IN_SRC, $src_file)) {
01012 //          print "Cannot open file \"$src_file\"\n";
01013          push (@file_errors, "Cannot open file \"$src_file\"\n");
01014          next SRC_IN;
01015       }
01016       if (0) {
01017 //          print "Source file is: $src_file\n";
01018       }
01019       // undef ($src_content);  //  start fresh
01020       //  read file into memory
01021       while (<IN_SRC>) {
01022          // ######## 
01023          //  Read in the source file, but change Doxygen comment syntax
01024          //  so that it is consistent throughout whole file.
01025          //  Begin replacement of //! comments with /** ... **/ comments
01026          // ######## 
01027          if (/^\/\/\!/) {
01028             if ($comment_count == 0){
01029                //  first line of a comment block
01030                $comment_count++;
01031                $_ =~ s/\/\/\!/\/\*\*/;
01032             } else {
01033                //  Some line in the middle of a comment block.
01034                $comment_count++;
01035                // ##
01036                //  Changed to have middle stuff with no asterix.
01037                //  $_ =~ s/\/\/\!/ \*\*/;
01038                // ##
01039                $_ =~ s/\/\/\!//;
01040             }
01041          } elsif ($comment_count > 0){
01042             //  We were in a comment block; need to terminate it.
01043             $comment_count = 0;
01044             if (/^\/\//) {
01045                //  Don't mess with comment lines.
01046                $_ = " \*\*\/\n" ;
01047             } else {
01048                //  Not a comment lines.
01049                $_ = " \*\*\/\n" . $_ ;
01050             }
01051          }
01052          // ######## End Comment style change.
01053          
01054          // ########
01055          //  Trash all lines beginning with a comment.
01056          // ########
01057          if (/^\/\//) {
01058             //  Don't mess with comment lines.
01059          } elsif ((/^\/\*/) && (/\*\/$/)) {
01060             //  Don't mess with lines that begin and end as a comment
01061          } else {
01062             //  Remember everything else
01063             $src_content .= $_;
01064          }
01065 
01066       } //  reading in source file
01067       if (0){
01068 //          print $src_content;
01069 //          exit(1);
01070       }
01071       
01072       //  for each @ingroup within the file, find the return value.
01073       
01074       if ($src_content =~ /\@ingroup/){
01075          @dox_ingroup1 = split (/\@ingroup/, $src_content);
01076          DOX_INCOMING: foreach ($i = 1; $i <= $// dox_ingroup1; $i++) {
01077             //  purposely don't look at the first chunk, because it'll be
01078             //  uninteresting. Hopefully there's not an off-by-one error.
01079             //  Split out the rest of the comments.
01080             @dox_ingroup2 = split (/\*\//, $dox_ingroup1[$i], 2);
01081             //  dox_ingroup2[0] is remainder of comment
01082             //  dox_ingroup2[1] is code stuff
01083             $process_g_flag = 0;
01084             foreach $desired_group (@xscope::ingroup){
01085                if ($dox_ingroup2[0] =~ /$desired_group/) {
01086                   //  This dox_group needs to be parsed for its return value
01087                   $process_g_flag = 1;
01088                }
01089             } //  $desired_group
01090             
01091             if ($process_g_flag) {
01092                //  Get the return value and code item name from the 
01093                //  code chunk and build up the file_hash.
01094                //  dox_ingroup2[1] is code stuff
01095                @code_chunk1 = split (/\{/, $dox_ingroup2[1], 2);
01096                //  $code_chunk1[0] is without implementation
01097                @code_chunk2 = split (/\(/, $code_chunk1[0], 2);
01098                if ($// code_chunk2 > 0) {
01099                   if (1) {
01100                      // ####
01101                      //  4/23/2002 Notice that the excluded elements were creeping back
01102                      //  in when the actual source code file was processed.
01103                      //  Seeing if we have to exclude them later,
01104                      //  figured might as well not test here to save some time.
01105                      // ####
01106                      foreach $exclude (@xscope::needed_out) {
01107                         //  Jump over any commands that we are told to specifically exclude.
01108                         if ($code_chunk2[0] =~ $exclude) {
01109                            next DOX_INCOMING;
01110                         }
01111                      }
01112                   }
01113                   //  Get rid of any leading carriage returns and slashes
01114                   $code_chunk2[0] =~ s/^\s*\n+//;
01115                   if (0) {
01116 //                      print "nnn $code_chunk2[0]\n";
01117                   }
01118                   if ($code_chunk2[0] =~ /[\S+]/){
01119                      @ode_name = split (/\s/, $code_chunk2[0]);
01120                      $_name = $ode_name[$// ode_name];
01121                      $_name =~ s/^\*//;
01122                      if (0){
01123 //                         print "ooo $_xcnt\:\:$code_chunk2[0]>>> $_name\n";
01124                      }
01125                   } else {
01126                      if (0){
01127 //                         print "ooo2 $_xcnt\:\:$code_chunk2[0]\n";
01128                      }
01129                   }
01130                   // ####
01131                   //  If we made it this far without doing a "next D_INCOMING" then
01132                   //  [1]  $src_file contains the file of interest;
01133                   //  [2]  $code_chunk2[0] contains the return type and item name.
01134                   //  [3]  $_name is the item name.
01135                   //  Let's put the code items into the file hash to speed up our process.
01136                   // 
01137                   //  Need to handle function overloading, so
01138                   // 
01139                   //  $file_hash {files} {code items} {r} {return types}
01140                   // 
01141                   //  We don't care about what it points to.
01142                   // ####
01143                   if (exists ($file_hash{$src_file}{$_name}{r}{$code_chunk2[0]})) {
01144                      $file_hash{$src_file}{$_name}{r}{$code_chunk2[0]} .= "; gp $_xcnt";
01145                   } else {
01146                      $file_hash{$src_file}{$_name}{r}{$code_chunk2[0]} = "gp $_xcnt";
01147                   }
01148          
01149                   $_xcnt++;
01150                } //  ($#code_chunk2 > 0)
01151             } //  DOX_INCOMING
01152          } //  $dox_chunk
01153       } //  ($src_content =~ /\@ingroup/)
01154 
01155 //       close (SRC_IN);
01156    } //  foreach SRC_IN
01157 
01158    // #####
01159    //  What is or will be in file hash
01160    //  $file_hash{$src_file}{$code_item}{r}{$return_type} = number
01161    // #####
01162 
01163    if (0){ //  
01164       $j=0;
01165       foreach $src_file (sort keys %file_hash){
01166          foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01167             foreach $return_type (sort keys %{$file_hash{$src_file}{$code_item}{r}} ) {
01168                $j++;
01169 //                //  print "$j $code_item :: $return_type :: $src_file\n";
01170 //                print "$j $code_item :: $return_type\n";
01171             }
01172          }
01173       }
01174       if (1){
01175 //          print "stopping here...";
01176 //          exit(1);
01177       }
01178    } //  if test
01179       if (0){
01180 //          print "stopping here...";
01181 //          exit(1);
01182       }
01183 
01184 } //  process_ingroup_hash
01185 
01186 
01187 //#############################################################################
01188 /** @fn int inside_parenthesis
01189  ** @brief Grabs what's inside the first set of parenthesis and takes into
01190  ** consideration nested parenthesis.
01191  **
01192  ** @param in_text has a piece of text that has a set of parenthesis 
01193  ** near its beginning.
01194  **
01195  ** @return If the first non-white space character after the top-level 
01196  ** parenthesis is an open curly brace ({), then the parenthesis are associated
01197  ** with a definition; return everything inside the first set of parenthesis 
01198  ** including the parenthesis. 
01199  **
01200  ** This handles nested parenthesis within the first set of parentheis.
01201  **
01202  ** @lim This forces us to determine whether it was a prototype or definition,
01203  ** rather than being generic for returning whatever was in the first set of
01204  ** parenthesis.
01205  **
01206  ** @ingroup tp_xhelp
01207  **/
01208 // #############################################################################
01209 int inside_parenthesis  ( ) {
01210    #define $in_text  $_[0]
01211    // undef (@in_array);
01212    // undef (@out_array);
01213    #define $nest_cnt  0
01214    #define $have_it  0
01215    
01216    
01217    @in_array = split (//, $in_text);
01218    if (0) {
01219 //       //  print "GCMin:$#in_array:$in_text\n";
01220 //       print "begin:$begin\n";
01221 //       print "end:$end\n======\n";
01222       for ($i=0; $i<200; $i++){
01223 //          print "$in_array[$i]";
01224       }
01225 //       print "\nhey======\n";
01226 //       //  exit(1);
01227    }
01228    NEXT_CHAR: foreach $cchar (@in_array) {
01229       //  put together an array that contains the prototype
01230       //  and handles nested parenthesis with the prototype.
01231       if ($have_it) {
01232          //  If this is set, we have the parenthesis,
01233          //  but keep checking it until we have either a semicolon (;)
01234          //  or an opening curly brace ({);
01235          if ($cchar =~ /\;/) {
01236             //  If a semicolon follows what was in parenthesis,
01237             //  then we've snagged the prototype which is not of interest.
01238             //  get out of here
01239             if (0) {
01240 //                print "Z1no$nest_cnt:$cchar\n";
01241             }
01242             return ("NEXT_ONE");
01243          } elsif ($cchar =~ /\{/) {
01244             //  If an open curly brace follows what was in parenthesis,
01245             //  then we've snagged the real code item that is of interest.
01246             if (0) {
01247 //                print "Z2yes$nest_cnt:$cchar\n";
01248             }
01249             goto REALLY_HAVE;
01250          } else {
01251             if (0) {
01252 //                print "Z3notyet$nest_cnt:$cchar\n";
01253             }
01254             next NEXT_CHAR;
01255          }
01256       } elsif (($nest_cnt == 0) && ($cchar =~ /\(/)) {
01257          if (0) {
01258 //             print "A$nest_cnt:$cchar\n";
01259          }
01260          push (@out_array, $cchar);
01261          $nest_cnt++;
01262          next NEXT_CHAR;
01263       } elsif (($nest_cnt != 0) && ($cchar =~ /\(/)) {
01264          if (0) {
01265 //             print "B$nest_cnt:$cchar\n";
01266          }
01267          push (@out_array, $cchar);
01268          $nest_cnt++;
01269          next NEXT_CHAR;
01270       } elsif (($nest_cnt != 0) && ($cchar =~ /\)/)) {
01271          push (@out_array, $cchar);
01272          $nest_cnt--;
01273          if (0) {
01274 //             print "C$nest_cnt:$cchar\n";
01275          }
01276          if ($nest_cnt == 0){
01277             //  Mark that we really have it;
01278             $have_it = 1;
01279          } 
01280          next NEXT_CHAR;
01281          
01282       } elsif (($nest_cnt == 0) && ($cchar !~ /\(/)) {
01283          if (0) {
01284 //             print "D$nest_cnt:$cchar\n";
01285          }
01286          push (@out_array, $cchar);
01287          next NEXT_CHAR;
01288       } elsif ($nest_cnt != 0) {
01289          if (0) {
01290 //             print "E$nest_cnt:$cchar\n";
01291          }
01292          push (@out_array, $cchar);
01293          next NEXT_CHAR;
01294       } //  nest_cnt loop
01295    } //  foreach $cchar
01296    
01297    REALLY_HAVE:
01298    $out = join ("", @out_array);
01299    // undef (@in_array);
01300    // undef (@out_array);
01301    if (0) {
01302 //       print "what's coming out=\n$out\n======\n";
01303 //       //  exit(1);
01304    }
01305    return ($out);
01306 } //  inside_parenthesis
01307 
01308 
01309 //#############################################################################
01310 /** @fn int find_doxygen
01311  ** @brief Looks for doxygen comments in test passed in.
01312  **
01313  ** @param piece_to_search a chunk of text that may have zero or more
01314  ** doxygen comment blocks.
01315  **
01316  ** @return The last doxygen comment block if it exists and doesn't have
01317  ** code in between the block and the very end. If there is code inbetween
01318  ** the block and the end or if there are no doxygen comment blocks, it
01319  ** returns NO_DOX_COMMENT.
01320  **
01321  ** Code between the comment block is spotted by open parenthesis "(" or
01322  ** open curly braces "{" or semicolons ";". 
01323  ** It means the comment block found doesn't belong with the code item in
01324  ** question, otherwise it'd be the last thing.
01325  ** 
01326  ** @lim This assumes the the Doxgyen comments have been flagged with 
01327  ** a leading /**.
01328  **
01329  ** @ingroup tp_xhelp
01330  **/
01331 // #############################################################################
01332 int find_doxygen  ( ) {
01333    #define $piece_to_search  $_[0]
01334    #define $dox_flag_b  "\/\*\*"
01335    #define $dox_flag_e  "\*\/"
01336    #define $out  ""
01337    
01338    if ($piece_to_search =~ /\/\*\*/) {
01339       //  Doxygen in piece that could potentially be processed
01340       @dox_pieces = split ( /\/\*\*/, $piece_to_search);
01341       if (0) {
01342 //          print "Maybe there is some doxygen (\/\*\*) ($// dox_pieces) to process.\n";
01343 //          print "\/\*\*$dox_pieces[$// dox_pieces]";
01344       }
01345       //  reduce to just doxygen stuff
01346       @dox_pieces2 = split (/\*\//, $dox_pieces[$// dox_pieces], 2);
01347       
01348       //  ERROR CHECKING
01349       //  The leftover piece $dox_pieces2[1] is between the doxygen comment
01350       //  and the code definition.
01351       //  If there are parenthesis "(" or curly braces in the left over piece,
01352       //  then the doxygen comment does not belong with this code item.
01353       if (($dox_pieces2[1] =~ /\(/) || ($dox_pieces2[1] =~ /\{/) || ($dox_pieces2[1] =~ /\;/)) {
01354          $out = "NO_DOX_COMMENT";
01355       } else {
01356          $out = "\/\*\*";
01357          $out .= $dox_pieces2[0];
01358          $out .= "\*\/";
01359       }
01360    } else {
01361       if (0) {
01362 //          print "No doxygen to process.\n";
01363       }
01364       $out = "NO_DOX_COMMENT";
01365    }
01366    return ($out);
01367    
01368 } //  find_doxygen
01369 
01370 
01371 //#############################################################################
01372 /** @fn int write_output_file
01373  ** @brief Creates a file that has a doxygen comment block, code definition,
01374  ** and empty body for each item of interest from the file hash.
01375  **
01376  ** @param file_out the path and filename of the output file.
01377  **
01378  ** @return The generated output file.
01379  **
01380  ** This routine steps through the file hash and writes to the file_out
01381  ** all relevant information, in addition to a header and white space.
01382  **
01383  ** The file hash has already been established:
01384  **
01385  **  $file_hash {$src_file} {$code_item} {p} {$prototype} = doxygen
01386  **  
01387  ** {$src_file}  the file of interest;
01388  ** {$code_item}  the item name within the file of interest.
01389  ** {p} flag for prototypes.
01390  ** {p} {$prototype} hash of prototypes associated with code item and handles
01391  ** overloaded functions. It points to associated doxygen comments.
01392  **
01393  ** @ingroup tp_xhelp
01394  **/
01395 // #############################################################################
01396 int write_output_file  ( ) {
01397    $file_out = $_[0];
01398    // undef (%s_code_item);   //  sorted hash for code item
01399 //    print "Writing the $file_out output file.\n";
01400    
01401    unless (open ( OUT_FILE, ">$file_out")) {
01402       push (@file_errors, "Cannot open file \"$file_out\"\n");
01403 //       print "Cannot open file \"$file_out\"\n";
01404    }
01405 //    print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01406    if (1) {
01407       //  Non-doxygen disclaimer at top of file.
01408 //       print (OUT_FILE "\/\/ Generated file with the appropriate commands.\n");
01409 //       print (OUT_FILE "\/\/ \n\/\/ Contains blank function declaration that\n");
01410 //       print (OUT_FILE "\/\/ are preceded by their appropriate Doxygen comments\n");
01411 //       print (OUT_FILE "\/\/ if they exist.\n");
01412 //       print (OUT_FILE "\/\/ \n\/\/ Its purpose is to reduce what Doxygen looks at\n");
01413 //       print (OUT_FILE "\/\/ to get rid of the noise in the output.\n");
01414 //       print (OUT_FILE "\/\/ \n\/\/ THIS FILE IS GENERATED!!!\n");
01415    } else {
01416 //       print (OUT_FILE "\/\/\! \@file\n");
01417 //       print (OUT_FILE "\/\/\! \@brief Generated file with the appropriate commands.\n");
01418 //       print (OUT_FILE "\/\/\! \n\/\/\! Contains blank function declaration that\n");
01419 //       print (OUT_FILE "\/\/\! are preceded by their appropriate Doxygen comments\n");
01420 //       print (OUT_FILE "\/\/\! if they exist.\n");
01421 //       print (OUT_FILE "\/\/\! \n\/\/\! Its purpose is to reduce what Doxygen looks at\n");
01422 //       print (OUT_FILE "\/\/\! to get rid of the noise in the output.\n");
01423 //       print (OUT_FILE "\/\/\! \n\/\/\! THIS FILE IS GENERATED!!!\n");
01424 //       //  print (OUT_FILE "\/\/\! \n\/\/\! \@ingroup xhelp\n");
01425    }
01426 //    print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01427 //    print (OUT_FILE "\n\n\n");
01428 
01429 
01430 if (1) { //  new way of doing it so that it gets sorted
01431    foreach $src_file (sort keys %file_hash){
01432       if (0) {
01433 //          print "$src_file is source file\n";
01434       }
01435       foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01436          if (0) {
01437 //             print "$code_item is code item\n";
01438          }
01439          PPROTO: foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01440             if (0) {
01441 //                print "$prototype\n";
01442             }
01443             $process_g_flag = 1;
01444             // ####
01445             //  Exclude certain doxygen comment blocks;
01446             //  In particular, if the block is the file header, it may
01447             //  be of no interest.
01448             // ####
01449             foreach $undesired_tag (@xscope::dox_exclude){
01450                if ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /$undesired_tag/) {
01451                   //  This item does not belong in the output
01452                   if (1) {
01453 //                      print"\"$code_item\" not in output because of \"$undesired_tag\"\n";
01454                   }
01455                   $process_g_flag = 0;
01456                }
01457             } //  $undesired_tag
01458 
01459             if ($process_g_flag) {
01460                if ($xscope::sapi) {    //  This is set in the generated sapi.pm
01461                   $command_name = &get_sapi_name ($file_hash{$src_file}{$code_item}{p}{$prototype});
01462                   if (0) {
01463 //                      print "debug:> $code_item\n";
01464 //                      //  print "before the call with $src_file, $code_item, $prototype\n";
01465 //                      //  print "$file_hash{$src_file}{$code_item}{p}{$prototype}\n";
01466 //                      print "c_name:> $command_name\n";
01467                   }
01468                   if ($command_name =~ /_NONE_/) {
01469                      //  if we don't have a command name, no sense putting anything out.
01470                      next PPROTO;
01471                   }
01472                } else {  //  for non-SAPI commands, like xhelp
01473                   $command_name = $code_item;
01474                }
01475                if (0) {
01476 //                   print "debug:> $code_item\n";
01477 //                   print "c_name:> $command_name\n";
01478                }
01479                if (exists ($s_code_item{$code_item})) {
01480                   $temp_string = "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
01481                   $temp_string .= "$file_hash{$src_file}{$code_item}{p}{$prototype}\n";
01482                   $temp_string .= "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
01483                   $temp_string .= "$prototype\n\n";
01484                   //  if it exists, append this information to it.
01485                   $s_code_item{$command_name} .= $temp_string;
01486                } else {
01487                   $temp_string = "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
01488                   $temp_string .= "$file_hash{$src_file}{$code_item}{p}{$prototype}\n";
01489                   $temp_string .= "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
01490                   $temp_string .= "$prototype\n\n";
01491                   //  if it doesn't exists, write this information to it.
01492                   $s_code_item{$command_name} = $temp_string;
01493                }
01494             }  //  $process_g_flag
01495          }
01496       }
01497    }
01498    if (0) {
01499 //       print "\n\nHi Glenn\n=====\n";
01500       foreach $command_name (sort keys %s_code_item){
01501 //          print "$command_name\n";
01502 //          //  print "$s_code_item{$command_name}";
01503       }
01504    }
01505   
01506    foreach $command_name (sort keys %s_code_item){
01507 //       print (OUT_FILE "$s_code_item{$command_name}");
01508    }
01509    
01510    // undef (%s_code_item);
01511 } //  if (1) # new way of doing it so that it gets sorted
01512 
01513 
01514 
01515 
01516 if (0) { //  old way of doing it
01517    foreach $src_file (sort keys %file_hash){
01518       foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01519          foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01520             $process_g_flag = 1;
01521             // ####
01522             //  Exclude certain doxygen comment blocks;
01523             //  In particular, if the block is the file header, it may
01524             //  be of no interest.
01525             // ####
01526             foreach $undesired_tag (@xscope::dox_exclude){
01527                if ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /$undesired_tag/) {
01528                   //  This item does not belong in the output
01529                   $process_g_flag = 0;
01530                }
01531             } //  $undesired_tag
01532 
01533             if ($process_g_flag) {
01534 //                print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01535 //                print (OUT_FILE "$file_hash{$src_file}{$code_item}{p}{$prototype}\n");
01536 //                print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01537 //                print (OUT_FILE "$prototype\n\n");
01538             }
01539          }
01540       }
01541    }
01542 } //  if (0) { # old way of doing it, no sorting done
01543 //    close (OUT_FILE);
01544 } //  write_output_file
01545 
01546 //#############################################################################
01547 /** @fn int get_sapi_name
01548  ** @brief parses out the name of the sapi or bapi function from the doxygen
01549  ** comments.
01550  ** 
01551  ** @param $src_file
01552  ** @param $code_item
01553  **
01554  ** @return The name of the command (with arguments) or _NONE_.
01555  **
01556  **/
01557 // #############################################################################
01558 int get_sapi_name   ( ) {
01559    #define $all_doc  $_[0]
01560    #define @all_line
01561    if (0) {
01562 //       print "you are here with:) \n$all_doc\n";
01563    }
01564    
01565    @all_line = split (/\n/, $all_doc);
01566    
01567    DOCLINE: foreach $line (@all_line) {
01568      if ($line =~ /\@fn/){
01569         @fn_chunk = split (/\@fn[\s]*/, $line, 2);
01570         @rtn_chunk = split (/[\s]+/, $fn_chunk[1]);
01571         if (0) {
01572 //            print "returning with \"$rtn_chunk[1]\"\n";
01573         }
01574         return ($rtn_chunk[1]);  //  this contains the sapi function name
01575         break;
01576      }
01577    } //  foreach $line
01578    if (0) {
01579 //      print "returning with \"_NONE_\"\n";
01580    }
01581    return ("_NONE_");
01582    
01583 } //  get_sapi_name
01584 
01585 //#############################################################################
01586 /** @fn int write_output_list
01587  ** @brief Creates a file that has a list of commands found, their location
01588  ** found in the source code, and an indication of existing doxygen comments.
01589  **
01590  ** @param file_out the path and filename of the output file.
01591  **
01592  ** @return The generated output file.
01593  **
01594  ** This routine steps through the file hash and writes to the file_out
01595  ** all relevant information, in addition to a header and white space.
01596  **
01597  ** The file hash has already been established:
01598  **
01599  **  $file_hash {$src_file} {$code_item} {p} {$prototype} = doxygen
01600  **  
01601  ** {$src_file}  the file of interest;
01602  ** {$code_item}  the item name within the file of interest.
01603  ** {p} flag for prototypes.
01604  ** {p} {$prototype} hash of prototypes associated with code item and handles
01605  ** overloaded functions. It points to associated doxygen comments.
01606  **
01607  ** @ingroup tp_xhelp
01608  **/
01609 // #############################################################################
01610 int write_output_list  ( ) {
01611    $file_out = $_[0];
01612 //    print "Writing the $file_out output file.\n";
01613    
01614    unless (open ( OUT_FILE, ">$file_out")) {
01615       push (@file_errors, "Cannot open file \"$file_out\"\n");
01616 //       print "Cannot open file \"$file_out\"\n";
01617    }
01618 //    print (OUT_FILE "This file contains a list of the commands\n");
01619 //    print (OUT_FILE "and their location.\n");
01620 //    print (OUT_FILE "The letter in parenthesis refers to existing Doxygen comments.\n");
01621 //    print (OUT_FILE "(n) has no comment block.\n");
01622 //    print (OUT_FILE "(y) has a comment block filled in.\n");
01623 //    print (OUT_FILE "(_TBD_) has a comment block still needing information.\n");
01624 //    print (OUT_FILE "==============================================================\n\n");
01625 
01626    foreach $src_file (sort keys %file_hash){
01627       foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01628          foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01629             if ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /NO_DOX_COMMENT/) {
01630 //                print (OUT_FILE "\(n\) $code_item :: $src_file\n");
01631             } elsif ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /_TBD_/) {
01632 //                print (OUT_FILE "\(_TBD_\) $code_item :: $src_file\n");
01633             } else {
01634 //                print (OUT_FILE "\(y\) $code_item :: $src_file\n");
01635             }
01636          }
01637       }
01638    }
01639 //    close (OUT_FILE);
01640    
01641    if (0) {
01642       foreach $src_file (sort keys %file_hash){
01643          foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01644 //             print "$code_item\n";
01645          }
01646       }
01647 //       print "hola glenn\n";
01648 //       exit(1);
01649    }
01650    if (0) {
01651       foreach $src_file (sort keys %file_hash){
01652          foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01653             foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01654 //                print "$prototype";
01655             }
01656          }
01657       }
01658 //       print "hola glenn\n";
01659 //       exit(1);
01660    }
01661 } //  write_output_list
01662 
01663 //#############################################################################
01664 /** @fn int write_output_class
01665  ** @brief Creates a file that has a list of commands found, their location
01666  ** found in the source code, and an indication of existing doxygen comments.
01667  **
01668  ** @param file_out the path and filename of the output file.
01669  **
01670  ** @return The generated output file.
01671  **
01672  **
01673  ** @ingroup tp_xhelp
01674  **/
01675 // #############################################################################
01676 int write_output_class  ( ) {
01677    $file_out = $_[0];
01678 //    print "Writing the $file_out output file.\n";
01679    
01680    unless (open ( OUT_FILE, ">$file_out")) {
01681       push (@file_errors, "Cannot open file \"$file_out\"\n");
01682 //       print "Cannot open file \"$file_out\"\n";
01683    }
01684 
01685 //    print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01686    if (1) {
01687 //       print (OUT_FILE "\/\/ brief Generated file with the appropriate commands.\n");
01688 //       print (OUT_FILE "\/\/ \n\/\/ Contains blank function declaration that\n");
01689 //       print (OUT_FILE "\/\/ are preceded by their appropriate Doxygen comments\n");
01690 //       print (OUT_FILE "\/\/ if they exist.\n");
01691 //       print (OUT_FILE "\/\/ \n\/\/ Its purpose is to reduce what Doxygen looks at\n");
01692 //       print (OUT_FILE "\/\/ to get rid of the noise in the output.\n");
01693 //       print (OUT_FILE "\/\/ \n\/\/ THIS FILE IS GENERATED!!!\n");
01694    } else {
01695 //       print (OUT_FILE "\/\/\! \@file\n");
01696 //       print (OUT_FILE "\/\/\! \@brief Generated file with the appropriate commands.\n");
01697 //       print (OUT_FILE "\/\/\! \n\/\/\! Contains blank function declaration that\n");
01698 //       print (OUT_FILE "\/\/\! are preceded by their appropriate Doxygen comments\n");
01699 //       print (OUT_FILE "\/\/\! if they exist.\n");
01700 //       print (OUT_FILE "\/\/\! \n\/\/\! Its purpose is to reduce what Doxygen looks at\n");
01701 //       print (OUT_FILE "\/\/\! to get rid of the noise in the output.\n");
01702 //       print (OUT_FILE "\/\/\! \n\/\/\! THIS FILE IS GENERATED!!!\n");
01703 //       //  print (OUT_FILE "\/\/\! \n\/\/\! \@ingroup xhelp\n");
01704    }
01705 //    print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01706 //    print (OUT_FILE "\n\n\n");
01707    
01708    // ####
01709    //  Sort the output by actual code item
01710    //  We just need keys into the other structure; we don't need all of the data
01711    //  of the other structure.
01712    // ####
01713    // undef (%list_of_items);
01714    if ($xscope::sapi) {  //  This is set in the generated sapi.pm
01715       //  Then the list of $xscope::sapi_names is available
01716       //  We still need to step through and match things up from the doxygen comment
01717       foreach $src_file (sort keys %file_hash){
01718          S_CODE: foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01719             S_PROTO: foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01720                @sm_dox = split (/\n/, $file_hash{$src_file}{$code_item}{p}{$prototype});
01721                for ($i=0; $i <= $// sm_dox; $i++) {
01722                   if ($sm_dox[$i] =~ /\@fn/) {
01723                      $match_line = $sm_dox[$i];
01724                      if (0) {
01725 //                         print "match:$match_line\n";
01726                      }
01727                      break;   //  get out of this inner most loop
01728                   }
01729                }
01730                S_NAME: foreach $names (@xscope::sapi_names){
01731                   // ###
01732                   //  This is intended to match our sapi.pm generated list of names
01733                   //  with prototypes that are near the beginning of the doxygen comment.
01734                   // ###
01735                   //  if ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /$names[\s]*\(/ ) {
01736                   if ($match_line =~ /$names[\s]*\(/ ) {
01737                      //  something like "@fn int bogus_name ( blah, blah)" 
01738                      push ( @{$list_of_items{$names}{src}}, $src_file);
01739                      push ( @{$list_of_items{$names}{code}}, $code_item);
01740                      push ( @{$list_of_items{$names}{proto}}, $prototype);
01741                      next S_PROTO;
01742                   }
01743                }
01744             }
01745          }
01746       }
01747       
01748    } else { //  if ($xscope::sapi)
01749       //  Then the $file_hash{$src_file}{$code_items} are the names we need
01750       foreach $src_file (sort keys %file_hash){
01751          foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01752             foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01753                push ( @{$list_of_items{$code_item}{src}}, $src_file);
01754                //  duplicates it, but allows for a parallel structure as above
01755                //  which gives us the needed keys into the original structure
01756                push ( @{$list_of_items{$code_item}{code}}, $code_item);
01757                push ( @{$list_of_items{$code_item}{proto}}, $prototype);
01758             }
01759          }
01760       }
01761    } //  if ($xscope::sapi)
01762    
01763    if (0) { //  Debug
01764       foreach $item (sort keys %list_of_items) {
01765          for ($i=0; $i <= $// {$list_of_items{$item}{src}}; $i++) {
01766 //             //  print "$i\=\=$item\t\=\=$list_of_items{$item}{src}[$i]\n";
01767 //             print "$i\=\=$item\t\=\=$list_of_items{$item}{code}[$i]\n";
01768          }
01769       }
01770       if (0) {
01771 //          print "hola glenn\n";
01772 //          exit(1);
01773       }
01774    } 
01775    
01776 
01777    // ####
01778    //  The problem this solves is that doxygen's output is organized
01779    //  in the order that it receives it.
01780    //  I end up sorting all temporary files before running
01781    //  them through doxygen. Then my HTML will be organized.
01782    // ####
01783    
01784    // ####
01785    //  We remove the following, which is the old access method and unsorted.
01786    //  It is replaced with what is sorted.
01787    //  We need to match braces.
01788    // ####
01789    //  foreach $src_file (sort keys %file_hash){
01790    //     foreach $code_item (sort keys %{$file_hash{$src_file}} ){
01791    //        foreach $prototype (sort keys %{$file_hash{$src_file}{$code_item}{p}} ){
01792    // ####
01793    foreach $item (sort keys %list_of_items) {
01794       for ($i=0; $i <= $// {$list_of_items{$item}{src}}; $i++) {
01795          $src_file = $list_of_items{$item}{src}[$i];
01796          $code_item = $list_of_items{$item}{code}[$i];
01797          $prototype = $list_of_items{$item}{proto}[$i];
01798             
01799          { //  $prototype matching parenthesis
01800    // ####
01801    //  Replacement loop above
01802    // ####
01803 
01804             $process_g_flag = 1;
01805             // ####
01806             //  Exclude certain doxygen comment blocks;
01807             //  In particular, if the block is the file header, it may
01808             //  be of no interest.
01809             // ####
01810             foreach $undesired_tag (@xscope::dox_exclude) {
01811                if ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /$undesired_tag/) {
01812                   //  This item does not belong in the output
01813                   $process_g_flag = 0;
01814                }
01815             } //  $undesired_tag
01816 
01817             if ($process_g_flag) {
01818                //  if ($prototype =~ /\"\)\;\}/){
01819                if ($prototype =~ /\"/){
01820                   //  The construct above is giving us problems in the output,
01821                   //  so let's not put it in the output.
01822                   delete ($file_hash{$src_file}{$code_item}{p}{$prototype});
01823                } elsif ($prototype =~ /\:\:/){
01824                   @sm_proto = split (/\{/, $prototype);
01825                   $sm_proto[0] =~ s/\n//g;
01826                
01827                   @class_ch1 = split (/\:\:/, $prototype);
01828                   @class_ch2 = split (/[\s+]/, @class_ch1[0]);
01829                   if (exists ($class_hash{$class_ch2[$// class_ch2]})) {
01830                      //  $class_hash{$class_ch2[$#class_ch2]} .= "      virtual $sm_proto[0]\;\n";
01831                      //  $class_hash{$class_ch2[$#class_ch2]} .= "      $sm_proto[0]\;\n";
01832                   } else {
01833                      //  $class_hash{$class_ch2[$#class_ch2]} = "      virtual $sm_proto[0]\;\n";
01834                      //  $class_hash{$class_ch2[$#class_ch2]} = "      $sm_proto[0]\;\n";
01835                      $class_hash{$class_ch2[$// class_ch2]} = "   \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n";
01836                   }
01837                   // ####
01838                   //  code prototype is $prototype while
01839                   //  doxygen template is in $file_hash{$src_file}{$code_item}{p}{$prototype}
01840                   // ####
01841                   if (!($xscope::sapi)) {  //  This is set in the generated sapi.pm
01842                      //  Means we're working on something that wants to have
01843                      //  the class definitions come through.
01844                      //  We need the class definition.
01845                      $class_hash{$class_ch2[$// class_ch2]} .= "   \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
01846                      $class_hash{$class_ch2[$// class_ch2]} .= "$file_hash{$src_file}{$code_item}{p}{$prototype}\n";
01847                      $class_hash{$class_ch2[$// class_ch2]} .= "   \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n";
01848                      $class_hash{$class_ch2[$// class_ch2]} .= "      $sm_proto[0]\;\n";
01849                   } else { //  $xscope::sapi
01850                      //  when working on sapi, we don't need to be so anal about
01851                      //  creating class stuff; 
01852                      //  we just need the doxygen comment output so that
01853                      //  the @fn can map to the sapi_gen prototypes later.
01854                      if ($file_hash{$src_file}{$code_item}{p}{$prototype} =~ /\@fn/) {
01855                         //  only output a sapi @fn doxygen template;
01856 //                         print (OUT_FILE  "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01857 //                         print (OUT_FILE  "$file_hash{$src_file}{$code_item}{p}{$prototype}\n");
01858                      }
01859                   } //  $xscope::sapi
01860                }
01861             } //  if process flag
01862          } //  $prototype matching parenthesis
01863       } //  $i
01864    } //  $item
01865 
01866    if (!($xscope::sapi)) {  //  This is set in the generated sapi.pm
01867       //  Means we're working on something that wants to have
01868       //  the class definitions come through.
01869       //  We need the class definition.
01870       foreach $class (sort keys %class_hash){
01871 //          print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01872 //          print (OUT_FILE "\/\/ begin $class\n");
01873 //          print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01874 //          print (OUT_FILE "class $class\n");
01875 //          print (OUT_FILE "{\n");
01876 //          print (OUT_FILE "   public\:\n");
01877 //          print (OUT_FILE "$class_hash{$class}\n");
01878 //          print (OUT_FILE "}\;\n");
01879 //          print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01880 //          print (OUT_FILE "\/\/ end $class\n");
01881 //          print (OUT_FILE "\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n");
01882 //          print (OUT_FILE "\n\n\n\n");
01883       }
01884    }
01885 //    close (OUT_FILE);
01886 } //  write_output_class
01887 
01888 
01889 //#############################################################################
01890 /** @fn int using_xhlp_bapi
01891  ** @brief What to do when no arguments are given.
01892  ** @param None
01893  ** @return None
01894  ** 
01895  ** @lim None
01896  ** @ingroup tp_xhelp
01897  **/
01898 // #############################################################################
01899 int using_xhelp  ( ) {
01900 //    print "============  Syntax  ==================================\n";
01901 //    print "xhelp_gen.pl <input scope package> <root path to files> <output file path \& name> \n\n";
01902 //    print "- <input scope package> is file path and name to a perl package that ";
01903 //    print "has lists of functions to be included and to be excluded.\n\n";
01904 //    print "- <root path to files> is the code location to start looking ";
01905 //    print "and must be terminated with a forward (\/) slash. ";
01906 //    print "If output file does not have a forward slash (\/) -- an indication ";
01907 //    print "of a path --, then the <root path to files> is assumed.\n\n";
01908 //    print "- <output file path \& name> plus another file ";
01909 //    print "with a leading underscore are generated. ";
01910 //    print "The file without the underscore is intended as the input to Doxygen.\n\n";
01911 //    print "============  Terminate  ==================================\n";
01912 //    print "Terminating xhelp_gen.pl without doing anything.\n";
01913    return(1);
01914 }
01915 
01916 
01917 //#############################################################################
01918 /** @fn int END
01919  ** @brief Code to execute when terminated nicely.
01920  **
01921  ** @param None. 
01922  **
01923  ** @return None.
01924  **
01925  ** @lim None
01926  ** @ingroup tp_xhelp
01927  **/
01928 // #############################################################################
01929 int END  ( ) {
01930    // undef ($_file_list); //  "_file_list";
01931    // undef ($in_file ); //   "";
01932    // undef ($root_path ); //   "./";
01933    // undef (%file_hash);
01934 
01935    
01936    // #############################################################################
01937    // # Memory clean-up.
01938    // # Perform this if it was defined.
01939    // #############################################################################
01940    if ($no_scope_file > 0){
01941       &xscope::memory_clean_up();
01942    }
01943    
01944 //    print "\n============  Finished xhelp_gen.pl ==================================\n";
01945 } //  END
01946 


 "Perl Program Reference" 
 < Previous 
 Next > 


Open-Source tools compliments of Voyant Technologies, Inc. and Glenn C. Maxey.
01/13/2003

TP Tools v2-00-0a

# tpt-perl-hcr-02