1219820Sjeffeval '(exit $?0)' &&
2219820Sjeff  eval 'exec perl -S $0 ${1+"$@"}' &&
3219820Sjeff  eval 'exec perl -S $0 $argv:q'
4219820Sjeff  if 0;
5219820Sjeff
6219820Sjeff#!/usr/bin/perl -W
7219820Sjeff#
8219820Sjeff# Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
9219820Sjeff# Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
10219820Sjeff# Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
11219820Sjeff#
12219820Sjeff# This software is available to you under a choice of one of two
13219820Sjeff# licenses.  You may choose to be licensed under the terms of the GNU
14219820Sjeff# General Public License (GPL) Version 2, available from the file
15219820Sjeff# COPYING in the main directory of this source tree, or the
16219820Sjeff# OpenIB.org BSD license below:
17219820Sjeff#
18219820Sjeff#     Redistribution and use in source and binary forms, with or
19219820Sjeff#     without modification, are permitted provided that the following
20219820Sjeff#     conditions are met:
21219820Sjeff#
22219820Sjeff#      - Redistributions of source code must retain the above
23219820Sjeff#        copyright notice, this list of conditions and the following
24219820Sjeff#        disclaimer.
25219820Sjeff#
26219820Sjeff#      - Redistributions in binary form must reproduce the above
27219820Sjeff#        copyright notice, this list of conditions and the following
28219820Sjeff#        disclaimer in the documentation and/or other materials
29219820Sjeff#        provided with the distribution.
30219820Sjeff#
31219820Sjeff# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32219820Sjeff# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33219820Sjeff# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34219820Sjeff# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
35219820Sjeff# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
36219820Sjeff# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
37219820Sjeff# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38219820Sjeff# SOFTWARE.
39219820Sjeff#
40219820Sjeff#########################################################################
41219820Sjeff#
42219820Sjeff#  Abstract:
43219820Sjeff#     Perl script for simple source code error checking and fixing
44219820Sjeff#
45219820Sjeff#  Environment:
46219820Sjeff#     Linux User Mode
47219820Sjeff#
48219820Sjeff#  Author:
49219820Sjeff#     Eitan Zahavi, Mellanox Technologies LTD Yokneam Israel.
50219820Sjeff#
51219820Sjeff#  $Revision: 1.4 $
52219820Sjeff#
53219820Sjeff#
54219820Sjeff#
55219820Sjeff# DESCRIPTION:
56219820Sjeff#
57219820Sjeff# This script performs some simple conformance checks on the
58219820Sjeff# OpenSM source code.  It does NOT attempt to act like a full
59219820Sjeff# blown 'C' language parser, so it can be fooled.  Something
60219820Sjeff# is better than nothing.
61219820Sjeff#
62219820Sjeff# The script starts by running the 'osm_indent' script on teh given files.
63219820Sjeff#
64219820Sjeff# We use an extra file for tracking error codes used by each file.
65219820Sjeff# The name is osm_errors_codes.
66219820Sjeff#
67219820Sjeff# The following checks are performed:
68219820Sjeff# 1) Verify that the function name provided in a log statement
69219820Sjeff#    matches the name of the current function.
70219820Sjeff#
71219820Sjeff# 2) Verify that log statements are in the form that this script
72219820Sjeff#    can readily parse.  Improvements to the regular expressions
73219820Sjeff#    might make this unnecessary.
74219820Sjeff#
75219820Sjeff# 3) Verify that lower two digits of the error codes used in log
76219820Sjeff#    statements are unique within that file.
77219820Sjeff#
78219820Sjeff# 4) Verify that upper two digits of the error codes used in log
79219820Sjeff#    statements are not used by any other module.
80219820Sjeff#
81219820Sjeff# 5) Verify the lines do not have extra spaces.
82219820Sjeff#
83219820Sjeff# USAGE:
84219820Sjeff#
85219820Sjeff# In the OpenSM source directory, type:
86219820Sjeff# osm_check_n_fix -f *.c
87219820Sjeff#
88219820Sjeff#########################################################################
89219820Sjeff
90219820Sjeff# Do necessary upfront initialization
91219820Sjeff$verbose = 0;
92219820Sjeff$in_c_comment = 0;
93219820Sjeff$fix_mode = 0;
94219820Sjeff$confirm_mode = 0;
95219820Sjeff$re_assign_err_prefix = 0;
96219820Sjeff
97219820Sjeffif( !scalar(@ARGV) )
98219820Sjeff{
99219820Sjeff    print "ERROR: You must specify the files on which to operate, such as '*.c'\n";
100219820Sjeff    osm_check_usage();
101219820Sjeff    exit;
102219820Sjeff}
103219820Sjeff
104219820Sjeff# loop through all the command line options
105219820Sjeffdo
106219820Sjeff{
107219820Sjeff    $doing_params = 0;
108219820Sjeff
109219820Sjeff    # First, look for command line options.
110219820Sjeff    if( $ARGV[0] =~ /-[v|V]/ )
111219820Sjeff    {
112219820Sjeff        $verbose += 1;
113219820Sjeff        shift;
114219820Sjeff        print "Verbose mode on, level = $verbose.\n";
115219820Sjeff        $doing_params = 1;
116219820Sjeff    }
117219820Sjeff
118219820Sjeff    if( $ARGV[0] =~ /(-f|--fix)/ )
119219820Sjeff    {
120219820Sjeff        $fix_mode += 1;
121219820Sjeff        shift;
122219820Sjeff        print "Fix mode on.\n";
123219820Sjeff        $doing_params = 1;
124219820Sjeff    }
125219820Sjeff
126219820Sjeff    if( $ARGV[0] =~ /(-c|--confirm)/ )
127219820Sjeff    {
128219820Sjeff        $confirm_mode += 1;
129219820Sjeff        shift;
130219820Sjeff        print "Confirm mode on.\n";
131219820Sjeff        $doing_params = 1;
132219820Sjeff    }
133219820Sjeff
134219820Sjeff    if( $ARGV[0] =~ /(-r|--re-assign-mod-err-prefix)/ )
135219820Sjeff    {
136219820Sjeff        $re_assign_err_prefix += 1;
137219820Sjeff        shift;
138219820Sjeff        print "Allow Re-Assignment of Module Err Prefixes.\n";
139219820Sjeff        $doing_params = 1;
140219820Sjeff    }
141219820Sjeff
142219820Sjeff    if( !scalar(@ARGV))
143219820Sjeff    {
144219820Sjeff        print "ERROR: You must specify the files on which to operate, such as '*.c'\n";
145219820Sjeff        osm_check_usage();
146219820Sjeff        exit;
147219820Sjeff    }
148219820Sjeff} while( $doing_params == 1 );
149219820Sjeff
150219820Sjeff# parse the osm_error_codes file and define:
151219820Sjeff# module_by_prefix
152219820Sjeff# module_err_prefixes
153219820Sjeff# module_last_err_used
154219820Sjeffif (open(ERRS, "<osm_error_codes")) {
155219820Sjeff  @ERR_DEFS = <ERRS>;
156219820Sjeff  close(ERRS);
157219820Sjeff  foreach $errDef (@ERR_DEFS) {
158219820Sjeff    # the format should be <file name> <err prefix> <last err>
159219820Sjeff    if ($errDef =~ m/^(\S+)\s+(\S+)\s+([0-9]+)$/) {
160219820Sjeff      ($file_name,$mod_prefix,$last_err) = ($1,$2,$3);
161219820Sjeff      if (defined($module_by_prefix{$mod_prefix})) {
162219820Sjeff        print "ERROR: Double module prefix:$mod_prefix on:$module_by_prefix($mod_prefix) and $file_name\n";
163219820Sjeff        exit 3;
164219820Sjeff      }
165219820Sjeff      $module_by_prefix{$mod_prefix} = $file_name;
166219820Sjeff      $module_err_prefixes{$file_name} = $mod_prefix;
167219820Sjeff      $module_last_err_used{$file_name} = $last_err;
168219820Sjeff    } else {
169219820Sjeff      print "ERROR: Fail to parse sm_error_codes: $errDef\n";
170219820Sjeff      exit 3;
171219820Sjeff    }
172219820Sjeff  }
173219820Sjeff}
174219820Sjeff
175219820Sjeff# do a file by file read into memory so we can tweek it:
176219820Sjeffforeach $file_name (@ARGV) {
177219820Sjeff	print "- $file_name ----------------------------------------------------\n";
178219820Sjeff   # first step is to run indent
179219820Sjeff	 $res=`osm_indent $file_name`;
180219820Sjeff
181219820Sjeff    open(INFILE, "<$file_name") || die("Fail to open $file_name");
182219820Sjeff    @LINES = <INFILE>;
183219820Sjeff    close(INFILE);
184219820Sjeff    $any_fix = 0;
185219820Sjeff    $needed_fixing = 0;
186219820Sjeff    $need_indentation = 0;
187219820Sjeff
188219820Sjeff  LINE: for ($line_num = 0; $line_num <scalar(@LINES); $line_num++) {
189219820Sjeff      $line = $LINES[$line_num];
190219820Sjeff      $_ = $line;
191219820Sjeff
192219820Sjeff      # Skip C single line C style comments
193219820Sjeff      # This line must come before the multi-line C comment check!
194219820Sjeff      if( /\/\*.*\*\// )
195219820Sjeff      {
196219820Sjeff          $in_c_comment = 0;
197219820Sjeff          next LINE;
198219820Sjeff      }
199219820Sjeff
200219820Sjeff      # skip multi-line C style comments
201219820Sjeff      if( /\/\*/ )
202219820Sjeff      {
203219820Sjeff          $in_c_comment = 1;
204219820Sjeff          next LINE;
205219820Sjeff      }
206219820Sjeff
207219820Sjeff      # end skipping of multi-line C style comments
208219820Sjeff      if( /\*\// )
209219820Sjeff      {
210219820Sjeff          $in_c_comment = 0;
211219820Sjeff          next LINE;
212219820Sjeff      }
213219820Sjeff
214219820Sjeff      # We're still in a C comment, so ignore input
215219820Sjeff      if( $in_c_comment == 1 )
216219820Sjeff      {
217219820Sjeff        next LINE;
218219820Sjeff      }
219219820Sjeff
220219820Sjeff
221219820Sjeff      # Error on C++ style comment lines
222219820Sjeff      if( /\/\// )
223219820Sjeff      {
224219820Sjeff        print "C++ style comment on $file_name $line_num\n";
225219820Sjeff        $needed_fixing++;
226219820Sjeff        if ($fix_mode) {
227219820Sjeff          $line =~ s=\/\/(.*)$=/* \1 */=;
228219820Sjeff          if (confirm_change($line, $LINES[$line_num])) {
229219820Sjeff            $LINES[$line_num] = $line;
230219820Sjeff            $any_fix++;
231219820Sjeff          }
232219820Sjeff          $any_fix++;
233219820Sjeff        }
234219820Sjeff      }
235219820Sjeff
236219820Sjeff      # check for lines with trailing spaces:
237219820Sjeff      if (/[ \t]+$/) {
238219820Sjeff        $needed_fixing++;
239219820Sjeff        if ($fix_mode) {
240219820Sjeff          $line =~ s/\s+$/\n/;
241219820Sjeff          if (confirm_change($line, $LINES[$line_num])) {
242219820Sjeff            $LINES[$line_num] = $line;
243219820Sjeff            $any_fix++;
244219820Sjeff          }
245219820Sjeff          $any_fix++;
246219820Sjeff        }
247219820Sjeff      }
248219820Sjeff
249219820Sjeff      # check for bad PRIx64 usage
250219820Sjeff      # It's a common mistake to forget the % before the PRIx64
251219820Sjeff      if (/[^%0-9][0-9]*\"\s*PRIx64/ ) {
252219820Sjeff        $needed_fixing++;
253219820Sjeff        print "No % sign before PRx64!!: $file_name $line_num\n";
254219820Sjeff        if ($fix_mode) {
255219820Sjeff          $line =~ s/([0-9]*)\"\s*PRIx64/%$1\" PRIx64/;
256219820Sjeff          if (confirm_change($line, $LINES[$line_num])) {
257219820Sjeff            $LINES[$line_num] = $line;
258219820Sjeff            $any_fix++;
259219820Sjeff          }
260219820Sjeff        }
261219820Sjeff      }
262219820Sjeff
263219820Sjeff      # This simple script doesn't handle checking PRIx64 usage
264219820Sjeff      # when PRIx64 starts the line.  Just give a warning.
265219820Sjeff      if( /^\s*PRIx64/ )
266219820Sjeff      {
267219820Sjeff        $needed_fixing++;
268219820Sjeff        print "Warning: PRIx64 at start of line.  $file_name $line_num\n";
269219820Sjeff#        if ($fix_mode) {
270219820Sjeff#          print "Fatal: can not auto fix\n";
271219820Sjeff#          exit 1;
272219820Sjeff#        }
273219820Sjeff      }
274219820Sjeff
275219820Sjeff      # Attempt to locate function names.
276219820Sjeff      # Function names must start on the beginning of the line.
277219820Sjeff      if( /^(\w+)\s*\(/ )
278219820Sjeff      {
279219820Sjeff        $current_func = $1;
280219820Sjeff        if( $verbose == 1 )
281219820Sjeff          {
282219820Sjeff            print "Processing $file_name: $current_func\n";
283219820Sjeff          }
284219820Sjeff      }
285219820Sjeff
286219820Sjeff      # Attempt to find OSM_LOG_ENTER entries.
287219820Sjeff      # When found, verify that the function name provided matches
288219820Sjeff      # the actual function.
289219820Sjeff      if( /OSM_LOG_ENTER\s*\(\s*([\-\.\>\w]+)\s*,\s*(\w+)\s*\)/ ) {
290219820Sjeff        $log_func = $2;
291219820Sjeff        if( $current_func ne $log_func ) {
292219820Sjeff          printf "MISMATCH!! $file_name $line_num: $current_func != $log_func\n";
293219820Sjeff          $needed_fixing++;
294219820Sjeff          if ($fix_mode) {
295219820Sjeff            $line =~
296219820Sjeff              s/OSM_LOG_ENTER\s*\(\s*([\-\.\>\w]+)\s*,\s*(\w+)\s*\)/OSM_LOG_ENTER( $1, $current_func )/;
297219820Sjeff            if (confirm_change($line, $LINES[$line_num])) {
298219820Sjeff              $LINES[$line_num] = $line;
299219820Sjeff              $any_fix++;
300219820Sjeff            }
301219820Sjeff          }
302219820Sjeff        }
303219820Sjeff      }
304219820Sjeff
305219820Sjeff      # Check for non-conforming log statements.
306219820Sjeff      # Log statements must not start the log string on the same line
307219820Sjeff      # as the osm_log function itself.
308219820Sjeff      # Watch out for the #include "osm_log.h" statement as a false positive.
309219820Sjeff      if (/osm_log\s*\(.*OSM_.*\"/ ) {
310219820Sjeff        if (/Format Waved/) {
311219820Sjeff          print "Skipping log format waiver at $file_name $line_num\n";
312219820Sjeff        } else {
313219820Sjeff          print "NON-CONFORMING LOG STATEMENT!! $file_name $line_num\n";
314219820Sjeff          $needed_fixing++;
315219820Sjeff          if ($fix_mode) {
316219820Sjeff            print "Fatal: can not auto fix\n";
317219820Sjeff            exit 1;
318219820Sjeff          }
319219820Sjeff        }
320219820Sjeff      }
321219820Sjeff
322219820Sjeff      # Attempt to find osm_log entries.
323219820Sjeff      if( /^\s*\"(\w+):/ )
324219820Sjeff      {
325219820Sjeff          $log_func = $1;
326219820Sjeff          if( $current_func ne $log_func )
327219820Sjeff          {
328219820Sjeff              print "MISMATCHED LOG FUNCTION!! $file_name $line_num: $current_func != $log_func\n";
329219820Sjeff              $needed_fixing++;
330219820Sjeff              if ($fix_mode) {
331219820Sjeff                  $line =~
332219820Sjeff                      s/^(\s*)\"(\w+):/$1\"$current_func:/;
333219820Sjeff                  if (confirm_change($line, $LINES[$line_num])) {
334219820Sjeff                      $LINES[$line_num] = $line;
335219820Sjeff                      $any_fix++;
336219820Sjeff                  }
337219820Sjeff              }
338219820Sjeff          }
339219820Sjeff      }
340219820Sjeff
341219820Sjeff      # Error logging must look like 'ERR 1234:'
342219820Sjeff      # The upper two digits are error range assigned to that module.
343219820Sjeff      # The lower two digits are the error code itself.
344219820Sjeff      # Error codes are in hexadecimal.
345219820Sjeff      if( /ERR(\s+)([0-9a-fA-F]{2})([0-9a-fA-F]{2})(..)/ )
346219820Sjeff      {
347219820Sjeff          # track any error for this exp:
348219820Sjeff          $exp_err = 0;
349219820Sjeff
350219820Sjeff          # the parsed prefix and err code:
351219820Sjeff          ($found_prefix,$found_code) = ($2,$3);
352219820Sjeff
353219820Sjeff          # Check if we already established the error prefix for this module
354219820Sjeff          $err_prefix = $module_err_prefixes{$file_name};
355219820Sjeff
356219820Sjeff          # err prefix is not available for this file
357219820Sjeff          if ( ! $err_prefix ) {
358219820Sjeff            # make sure no other file uses this prefix:
359219820Sjeff            if ($module_by_prefix{$found_prefix}) {
360219820Sjeff              # some other file uses that prefix:
361219820Sjeff
362219820Sjeff              # two modes: either use a new one or abort
363219820Sjeff              if ($re_assign_err_prefix) {
364219820Sjeff                # scan the available module prefixes for an empty one:
365219820Sjeff                $found = 0;
366219820Sjeff                for ($new_prefix_idx = 1; $found == 0; $new_prefix_idx++) {
367219820Sjeff                  $prefix = sprintf("%02X", $new_prefix_idx);
368219820Sjeff                  if (!defined($module_by_prefix{$prefix})) {
369219820Sjeff                    $module_err_prefixes{$file_name} = $prefix;
370219820Sjeff                    $module_by_prefix{$prefix} = $file_name;
371219820Sjeff                    $found = 1;
372219820Sjeff                  }
373219820Sjeff                  $exp_err = 1;
374219820Sjeff                }
375219820Sjeff              } else {
376219820Sjeff                print "Fatal: File $module_by_prefix{$2} already uses same prefix:$2 used by: $file_name (line=$line_num)\n";
377219820Sjeff                exit 1;
378219820Sjeff              }
379219820Sjeff            } else {
380219820Sjeff              # the prefix found is unused:
381219820Sjeff
382219820Sjeff              # Create a new prefix for this module.
383219820Sjeff              $module_err_prefixes{$file_name} = $found_prefix;
384219820Sjeff              $module_by_prefix{$found_prefix} = $file_name;
385219820Sjeff              $err_prefix = $found_prefix;
386219820Sjeff            }
387219820Sjeff          } else {
388219820Sjeff            # we already have a prefix for this file
389219820Sjeff
390219820Sjeff            if( $err_prefix ne $found_prefix )
391219820Sjeff            {
392219820Sjeff              $needed_fixing++;
393219820Sjeff              print "BAD ERR RANGE IN LOG ENTRY!! $file_name $line_num: $current_func\n";
394219820Sjeff              print "\tExpected $err_prefix but found $found_prefix\n";
395219820Sjeff              $exp_err = 1;
396219820Sjeff            }
397219820Sjeff          }
398219820Sjeff
399219820Sjeff          # now check for code duplicates
400219820Sjeff          $err_base = $module_err_bases{$found_code};
401219820Sjeff          if( $err_base ) {
402219820Sjeff            $needed_fixing++;
403219820Sjeff            print "DUPLICATE ERR NUMBER IN LOG ENTRY!! $file_name $line_num: $current_func: $3\n";
404219820Sjeff            print "\tPrevious use on line $err_base.\n";
405219820Sjeff
406219820Sjeff            # use the last error code for this module:
407219820Sjeff            $module_last_err_used{$file_name}++;
408219820Sjeff            $err_code = sprintf("%02X", $module_last_err_used{$file_name});
409219820Sjeff            print "\tUsing new err code:0x$err_code ($module_last_err_used{$file_name})\n";
410219820Sjeff            $module_err_bases{$err_code} = $line_num;
411219820Sjeff            $exp_err = 1;
412219820Sjeff          } else {
413219820Sjeff            # Add this error code to the list used by this module
414219820Sjeff            # The data stored in the line number on which it is used.
415219820Sjeff            $module_err_bases{$found_code} = $line_num;
416219820Sjeff            # track the last code used
417219820Sjeff            $err_code_num = eval("0x$found_code");
418219820Sjeff            if ($module_last_err_used{$file_name} < $err_code_num) {
419219820Sjeff              $module_last_err_used{$file_name} = $err_code_num;
420219820Sjeff            }
421219820Sjeff            $err_code = $found_code;
422219820Sjeff
423219820Sjeff            if( $verbose > 1 ) {
424219820Sjeff              print "Adding new error: $err_prefix$found_code in $file_name.\n";
425219820Sjeff            }
426219820Sjeff          }
427219820Sjeff
428219820Sjeff          if( $4 ne ": " ) {
429219820Sjeff            $needed_fixing++;
430219820Sjeff            print "MALFORMED LOG STATEMENT!!  NEEDS ': ' $file_name $line_num\n";
431219820Sjeff            $exp_err = 1;
432219820Sjeff          }
433219820Sjeff
434219820Sjeff          if( $1 ne " " )
435219820Sjeff          {
436219820Sjeff            $needed_fixing++;
437219820Sjeff            print "USE ONLY 1 SPACE AFTER ERR!! $file_name $line_num\n";
438219820Sjeff            $exp_err = 1;
439219820Sjeff          }
440219820Sjeff
441219820Sjeff          if ($exp_err && $fix_mode) {
442219820Sjeff              $line =~
443219820Sjeff                  s/ERR(\s+)([0-9a-fA-F]{2})([0-9a-fA-F]{2})([^\"]*\")/ERR ${err_prefix}$err_code: \" /;
444219820Sjeff              if (confirm_change($line, $LINES[$line_num])) {
445219820Sjeff                  $LINES[$line_num] = $line;
446219820Sjeff                  $any_fix++;
447219820Sjeff              }
448219820Sjeff          }
449219820Sjeff      }
450219820Sjeff
451219820Sjeff      # verify expected use of sizeof() with pointers
452219820Sjeff      if( /sizeof\s*\(\s*[h|p]_[^-]+\)/ )
453219820Sjeff      {
454219820Sjeff          print "SUSPICIOUS USE OF SIZEOF(), DO YOU NEED AN '*' $file_name $line_num\n";
455219820Sjeff          $needed_fixing++;
456219820Sjeff          if ($fix_mode) {
457219820Sjeff              $line =~
458219820Sjeff                  s/sizeof\s*\(\s*([h|p])_/sizeof \(*$1_/;
459219820Sjeff              if (confirm_change($line, $LINES[$line_num])) {
460219820Sjeff                  $LINES[$line_num] = $line;
461219820Sjeff                  $any_fix++;
462219820Sjeff              }
463219820Sjeff          }
464219820Sjeff      }
465219820Sjeff   }
466219820Sjeff
467219820Sjeff    # reset the base error value, since each module can
468219820Sjeff    # repeat this range.
469219820Sjeff    %module_err_bases = ();
470219820Sjeff
471219820Sjeff    # if any fix write out the fixed file:
472219820Sjeff    if ($any_fix) {
473219820Sjeff      open(OF,">$file_name.fix");
474219820Sjeff      print OF @LINES;
475219820Sjeff      close(OF);
476219820Sjeff    } elsif ($needed_fixing) {
477219820Sjeff      print "Found $needed_fixing Errors on file: $file_name\n";
478219820Sjeff    }
479219820Sjeff}
480219820Sjeff
481219820Sjeff# write out the error codes.
482219820Sjeff# module_by_prefix
483219820Sjeff# module_err_prefixes
484219820Sjeff# module_last_err_used
485219820Sjeffopen(ERRS,">osm_error_codes");
486219820Sjeffforeach $fn (sort(keys(%module_err_prefixes))) {
487219820Sjeff  print ERRS "$fn $module_err_prefixes{$fn} $module_last_err_used{$fn}\n";
488219820Sjeff}
489219820Sjeffclose(ERRS);
490219820Sjeff
491219820Sjeffsub osm_check_usage
492219820Sjeff{
493219820Sjeff    print "Usage:\n";
494219820Sjeff    print "osm_check.pl [-v|V] [-f|--fix] [-c|--confirm] [-r|--re-assign-mod-err-prefix] <file list>\n";
495219820Sjeff    print "[-v|V] - enable verbose mode.\n";
496219820Sjeff    print "[-f|--fix] - enable auto fix mode.\n";
497219820Sjeff    print "[-c|--confirm] - enable manual confirmation mode.\n";
498219820Sjeff    print "[-r|--re-assign-mod-err-prefix] - enables re-assign error prefixes if the file does not have one.\n";
499219820Sjeff}
500219820Sjeff
501219820Sjeffsub confirm_change {
502219820Sjeff    local ($line, $orig_line) = @_;
503219820Sjeff    if ($confirm_mode) {
504219820Sjeff	print "In Line:".($line_num + 1)."\n";
505219820Sjeff        print "From: ${orig_line}To:   ${line}Ok [y] ?";
506219820Sjeff        $| = 1;
507219820Sjeff        $ans = <STDIN>;
508219820Sjeff        chomp $ans;
509219820Sjeff
510219820Sjeff        if ($ans && $ans ne "y") {
511219820Sjeff            return 0;
512219820Sjeff        }
513219820Sjeff    } else {
514219820Sjeff        print "From: ${orig_line}To:   ${line}";
515219820Sjeff    }
516219820Sjeff    return 1;
517219820Sjeff}
518