dblib.pl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:10k
源码类别:

通讯编程

开发平台:

Visual C++

  1. #!/home/johnh/BIN/perl5
  2. #
  3. # dblib.pl
  4. # Copyright (C) 1991-1998 by John Heidemann <johnh@isi.edu>
  5. # $Id: dblib.pl,v 1.2 2005/09/16 04:41:55 tomh Exp $
  6. #
  7. # This program is distributed under terms of the GNU general
  8. # public license, version 2.  See the file COPYING
  9. # in $dblibdir for details.
  10. # The copyright of this module includes the following
  11. # linking-with-specific-other-licenses addition:
  12. # In addition, as a special exception, the copyright holders of
  13. # this module give you permission to combine (via static or
  14. # dynamic linking) this module with free software programs or
  15. # libraries that are released under the GNU LGPL and with code
  16. # included in the standard release of ns-2 under the Apache 2.0
  17. # license or under otherwise-compatible licenses with advertising
  18. # requirements (or modified versions of such code, with unchanged
  19. # license).  You may copy and distribute such a system following the
  20. # terms of the GNU GPL for this module and the licenses of the
  21. # other code concerned, provided that you include the source code of
  22. # that other code when and as the GNU GPL requires distribution of
  23. # source code.
  24. # Note that people who make modified versions of this module
  25. # are not obligated to grant this special exception for their
  26. # modified versions; it is their choice whether to do so.  The GNU
  27. # General Public License gives permission to release a modified
  28. # version without this exception; this exception also makes it
  29. # possible to release a modified version which carries forward this
  30. # exception.
  31. #
  32. $col_headertag = "#h";
  33. $list_headertag = "#L";
  34. $headertag_regexp = "#[hL]";
  35. $fs_code = 'D';
  36. $header_fsre = "[ tn]+";
  37. $fsre = "[ tn]+";
  38. $outfs = "t";
  39. $header_outfs = " ";
  40. $codify_code = "";
  41. $default_format = "%.5g";
  42. sub col_mapping {
  43.     local ($key, $n) = @_;
  44.     die("dblib col_mapping: column name ``$key'' cannot begin with underscore.n")
  45.      if ($key =~ /^_/);
  46.     die("dblib col_mapping: duplicate column name ``$key''n")
  47.      if (defined($colnametonum{$key}));
  48.     die ("dblib col_mapping: bad n.n") if (!defined($n));
  49.     $colnames[$n] = $key;
  50.     $colnametonum{$key} = $n;
  51.     $colnametonum{"_$key"} = $n;
  52.     $colnametonum{"$n"} = $n;   # numeric synonyms
  53. }
  54. sub col_unmapping {
  55.     local ($key) = @_;
  56.     local ($n);
  57.     $n = $colnametonum{$key};
  58.     $colnames[$n] = undef if (defined($n));
  59.     delete $colnametonum{$key};
  60.     delete $colnametonum{"_$key"};
  61. }
  62. # Create a new column.
  63. # Insert it before column $desired_n.
  64. sub col_create {
  65.     local ($key, $desired_n) = @_;
  66.     local ($n, $i);
  67.     die ("dblib col_create: called with duplicate column name ``$key''.n")
  68.      if (defined($colnametonum{$key}));
  69.     if (defined($desired_n)) {
  70.      # Shift columns over as necessary.
  71.      $n = $colnametonum{$desired_n};
  72. for ($i = $#colnames; $i >= $n; $i--) {
  73.     $tmp_key = $colnames[$i];
  74.     &col_unmapping($tmp_key);
  75.     &col_mapping($tmp_key, $i+1);
  76. };
  77.     } else {
  78.      $n = $#colnames+1;
  79.     };
  80.     $colnames[$n] = $key;
  81.     &col_mapping ($colnames[$n], $n);
  82.     return $n;
  83. }
  84. sub fs_code_to_fsre_outfs {
  85.     my($value) = @_;
  86.     my($fsre, $outfs);
  87.     if (!defined($value) || $value eq 'D') {  # default
  88. $fsre = "[ tn]+";
  89. $outfs = "t";
  90.     } elsif ($value eq 'S') {   # double space
  91. $fsre = 'ss+';
  92. $outfs = "  ";
  93.     } elsif ($value eq 't') {   # single tab
  94. $fsre = "t";
  95. $outfs = "t";
  96.     } else {   # anything else
  97. $value = eval "qq{$value}";  # handle backslash expansion
  98. $fsre = "[$value]+";
  99. $outfs = $value;
  100.     }
  101.     return ($fsre, $outfs);
  102. }
  103. sub process_header {
  104.     my($line, $headertag) = @_;
  105.     $regexp = (defined($headertag) ? $headertag : $headertag_regexp);
  106.     die ("dblib process_header: undefined header.n")
  107. if (!defined($line));
  108.     die ("dblib process_header: invalid header format: ``$line''.n")
  109.         if ($line !~ /^$regexp/);
  110.     @colnames = split(/$header_fsre/, $line);
  111.     shift @colnames;   # toss headertag
  112.     @coloptions = ();
  113.     #
  114.     # handle options
  115.     #
  116.     while ($#colnames >= 0 && $colnames[0] =~ /^-(.)(.*)/) {
  117. push(@coloptions, shift @colnames);
  118. my($key, $value) = ($1, $2);
  119. if ($key eq 'F') {
  120.     ($fsre, $outfs) = fs_code_to_fsre_outfs($value);
  121.     $fs_code = $value;
  122. };
  123.     };
  124.     %colnametonum = ();
  125.     foreach $i (0..$#colnames) {
  126.      &col_mapping ($colnames[$i], $i);
  127.     };
  128. }
  129. sub readprocess_header {
  130.     my($headertag) = @_;
  131.     my($line);
  132.     $line = <STDIN>;
  133.     &process_header($line, $headertag);
  134. }
  135. sub write_header {
  136.     my(@cols) = @_;
  137.     @cols = @colnames if ($#cols == -1);
  138.     print "$col_headertag$header_outfs" .
  139. ($#coloptions != -1 ? join($header_outfs, @coloptions, '') : "") .
  140. join($header_outfs, @cols) .
  141. "n";
  142. }
  143. # listized
  144. sub write_list_header {
  145.     local (@cols) = @_;
  146.     @cols = @colnames if ($#cols == -1);
  147.     print "$list_headertag $outfs" .
  148. join($outfs, @cols) .
  149. "n";
  150. }
  151. sub escape_blanks {
  152.     my($line) = @_;
  153.     $line =~ s/[ t]/_/g;
  154.     return $line;
  155. }
  156. sub unescape_blanks {
  157.     my($line) = @_;
  158.     $line =~ s/_/ /g;
  159.     return $line;
  160. }
  161. #
  162. # codify:  convert db-code into perl code
  163. #
  164. # The conversion is a rename of all _foo's into
  165. # database fields.
  166. # For more perverse needs, _foo(N) means the Nth field after _foo.
  167. # To convert we eval $codify_code.
  168. #
  169. # NEEDSWORK:  Should make some attempt to catch misspellings of column
  170. # names.
  171. #
  172. sub codify {
  173.     if ($codify_code eq "") {
  174.         foreach (@colnames) {
  175.     $codify_code .= '$f =~ s/b_' . quotemeta($_) . '((.*))/$f[' . $colnametonum{$_} . '+$1]/g;' . "n";
  176.     $codify_code .= '$f =~ s/b_' . quotemeta($_) . 'b/$f[' . $colnametonum{$_} . ']/g;' . "n";
  177.         };
  178.     };
  179.     local($f) = join(";", @_);
  180.     eval $codify_code;
  181.     return $f;
  182. }
  183. #
  184. # code_prettify:  Convert db-code into "pretty code".
  185. #
  186. sub code_prettify {
  187.     local($prettycode) = join(";", @_);
  188.     $prettycode =~ s/n/ /g;   # newlines will break commenting
  189.     return $prettycode;
  190. }
  191. sub is_comment {
  192.     return ($_ =~ /^#/) || ($_ =~ /^s*$/);
  193. }
  194. sub pass_comments {
  195.     if (&is_comment) {
  196. print $_;
  197. return 1;
  198.     };
  199.     return 0;
  200. }
  201. sub delayed_pass_comments {
  202.     if (&is_comment) {
  203. $delayed_comments = (!defined($delayed_comments) ? '' : $delayed_comments) . $_;
  204. return 1;
  205.     };
  206.     return 0;
  207. }
  208. sub delayed_flush_comments {
  209.     print $delayed_comments if (defined($delayed_comments));
  210.     $delayed_comments = undef;
  211. }
  212. sub split_cols {
  213.     chomp $_;
  214.     @f = split(/$fsre/, $_);
  215. }
  216. sub write_cols {
  217.     print join($outfs, @f), "n";
  218. };
  219. sub write_these_cols {
  220.     print join($outfs, @_), "n";
  221. };
  222. #
  223. # output compare/entry code based on ARGV
  224. # first entry is a sub:
  225. # sub row_col_fn {
  226. #     my($row, $colname, $n) = @_;
  227. #     # row is either a or b which we're comparing, or i for entries
  228. #     # colname is the user-given column name
  229. #     # n is 0..N of the cols to be sorted
  230. # }
  231. # See the code in dbjoin and dbsort for implementations.
  232. #
  233. sub generate_compare_code {
  234.     my($compare_function_name) = shift @_;
  235.     my($row_col_fn) = shift @_;
  236.     my(@args) = @_;
  237.     my ($compare_code, $enter_code, $reverse, $numeric, $i);
  238.     $compare_code = "sub $compare_function_name {n";
  239.     $enter_code = "";
  240.     $reverse = 0;
  241.     $numeric = 0;
  242.     $i = 0;
  243.     foreach (@args) {
  244.         if (/^-/) {
  245.     s/^-//;
  246.     my($options) = $_;
  247.     while ($options ne '') {
  248. $options =~ s/(.)//;
  249. ($ch) = $1;
  250.         if ($ch eq 'r') { $reverse = 1; }
  251.         elsif ($ch eq 'R') { $reverse = 0; }
  252.         elsif ($ch eq 'n') { $numeric = 1; }
  253.         elsif ($ch eq 'N') { $numeric = 0; }
  254.         else { die "dblib generate_compare_code: unknown option $ch.n"; };
  255.     };
  256.     next;
  257.         };
  258. die ("dblib generate_compare_code: unknown column $_.n") if (!defined($colnametonum{$_}));
  259. if ($reverse) {
  260.             $first = 'b';   $second = 'a';
  261.         } else {
  262.             $first = 'a';   $second = 'b';
  263.         };
  264.         $compare_code .= '$r = (' . &$row_col_fn($first, $_, $i) . ' ' . 
  265.               ($numeric ? "<=>" : "cmp") .
  266.     ' ' . &$row_col_fn($second, $_, $i) . '); ' . 
  267.     'return $r if ($r);' . 
  268.     " # $_" .
  269. ($reverse && $numeric ? " (reversed, numeric)" :
  270. $reverse ? " (reversed)" :
  271. $numeric ? " (numeric)" :
  272. "") .
  273.     "n";
  274.         $enter_code .= &$row_col_fn('i', $_, $i) . 
  275.             ' = $f[' . $colnametonum{$_} . '];' . "n";
  276. $i++;
  277.     }
  278.     $compare_code .= "return 0;n}";
  279.     # Create the comparison function.
  280.     eval $compare_code;
  281.     $@ && die("dblib generate_compare_code: error ``$@ in'' eval of compare_code.n$compare_code");
  282.     return ($compare_code, $enter_code, $i-1);
  283. }
  284. sub abs {
  285.     return $_[0] > 0 ? $_[0] : -$_[0];
  286. }
  287. sub progname {
  288.     my($prog) = ($0);
  289.     $prog =~ s@^.*/@@g;
  290.     return $prog;
  291. }
  292. sub force_numeric {
  293.     my($value, $ignore_non_numeric) = @_;
  294.     if ($value =~ /^[-+]?[0-9]+(.[0-9]+)?(e[-+0-9]+)?$/) {
  295.         return $value + 0.0;   # force numeric
  296.     } else {
  297. if ($ignore_non_numeric) {
  298.     return undef;
  299.     next;
  300. } else {
  301.     return 0.0;
  302. };
  303.     };
  304. }
  305. my($tmpfile_counter) = 0;
  306. my(@tmpfiles) = ();
  307. # call as tmpfile(FH)
  308. sub db_tmpfile {
  309.     my($fh) = @_;
  310.     my($i) = $tmpfile_counter++;
  311.     my($fn) = &db_tmpdir . "/$$.$i";
  312.     push(@tmpfiles, $fn);
  313.     open($fh, "+>$fn") || die "$0: tmpfile open failed.n";
  314.     chmod 0600, $fn || die "$0: tmpfile chmod failed.n";
  315.     return $fn;
  316. }
  317. sub db_tmpdir {
  318.     $ENV{'TMPDIR'} = '/tmp' if (!defined($ENV{'TMPDIR'}));
  319.     return $ENV{'TMPDIR'};
  320. }
  321. my($dblib_date_inited) = undef;
  322. sub dblib_date_init {
  323.     eval "use HTTP::Date; use POSIX";
  324. }
  325. sub date_to_epoch {
  326.     my($date) = @_;
  327.     &dblib_date_init if (!$dblib_date_inited);
  328.     return str2time($date);
  329. }
  330. sub epoch_to_date {
  331.     my($epoch) = @_;
  332.     &dblib_date_init if (!$dblib_date_inited);
  333.     my($d) = strftime("%d-%b-%y", gmtime($epoch));
  334.     $d =~ s/^0//;
  335.     return $d;
  336. }
  337. sub epoch_to_fractional_year {
  338.     my($epoch) = @_;
  339.     &dblib_date_init if (!$dblib_date_inited);
  340.     my($year) = strftime("%Y", gmtime($epoch));
  341.     my($year_beg_epoch) = date_to_epoch("${year}0101");
  342.     my($year_end_epoch) = date_to_epoch(($year+1) . "0101");
  343.     my($year_secs) = $year_end_epoch - $year_beg_epoch;
  344.     my($fraction) = ($epoch - $year_beg_epoch) / (1.0 * $year_secs);
  345.     $fraction =~ s/^0//;
  346.     return "$year$fraction";
  347. }
  348. sub END {
  349.     foreach (@tmpfiles) {
  350. unlink($_) if (-f $_);
  351.     };
  352. }
  353. 1;