source: trunk/SOURCE_TOOLS/sortfig.pl

Last change on this file was 18168, checked in by westram, 5 years ago
  • Property svn:executable set to *
File size: 6.1 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6my $reg_key = qr/^([0-9\.-]+\s+){13}(.*)$/o;
7my $reg_isLabel = qr/^(\$)?(to:)?([XY]+:)?/o;
8
9sub defEmpty($) {
10  my ($whatever) = @_;
11  defined $whatever ? $whatever : "";
12}
13sub ifdef($) {
14  my ($whatever) = @_;
15  defined $whatever ? 1 : 0;
16}
17
18my $ASCII1 = chr(1);
19
20sub lessKey($$) {
21  my ($a,$b) = @_;
22
23  my ($ato,$aIsLab,$aXY,$arest) = ('',0,'',$a);
24  my ($bto,$bIsLab,$bXY,$brest) = ('',0,'',$b);
25  if ($a =~ $reg_isLabel) { ($ato,$aIsLab,$aXY,$arest) = (defEmpty($2),ifdef($1),$3,$'); }
26  if ($b =~ $reg_isLabel) { ($bto,$bIsLab,$bXY,$brest) = (defEmpty($2),ifdef($1),$3,$'); }
27
28  $arest =~ s/($ASCII1|\\001)x*$//;
29  $brest =~ s/($ASCII1|\\001)x*$//;
30
31  my ($atxt,$btxt) = (lc($arest),lc($brest));
32  $atxt =~ s/[^a-z0-9]//go;
33  $btxt =~ s/[^a-z0-9]//go;
34
35  my $cmp = 0;
36  if ($aIsLab != $bIsLab) {
37    my $prefixLen = 3; # reduce to make stable
38    my ($apre,$bpre) = (substr($atxt,0,$prefixLen),substr($btxt,0,$prefixLen));
39    if ($apre eq $bpre) {
40      $cmp = $aIsLab <=> $bIsLab;
41    }
42    else {
43      $cmp = $apre cmp $bpre;
44    }
45  }
46  else {
47    $cmp = $atxt cmp $btxt;
48    if ($cmp==0) {
49      $cmp = $ato cmp $bto;
50      if ($cmp==0) {
51        $cmp = length($a) <=> length($b);
52        if ($cmp==0) {
53          $cmp = $a cmp $b;
54        }
55      }
56    }
57  }
58  if ($cmp==0) { die "no order defined ($a,$b)"; }
59  $cmp;
60}
61
62my $formatDetected = undef;
63
64sub sort4(\@) {
65  my ($lines_r) = @_;
66
67  my %keyedLines = ();
68
69  foreach my $line (@$lines_r) {
70    if ($line =~ $reg_key) {
71      my $key = $2;
72      while (exists $keyedLines{$key}) { $key .= 'x'; } # avoid overwriting keys
73      $keyedLines{$key} = $line;
74      if (not defined $formatDetected) {
75        if ($key =~ /$ASCII1/) { $formatDetected = 'old'; }
76        if ($key =~ /\\001/o) { $formatDetected = 'new'; }
77      }
78    }
79    else {
80      die "unexpected line '$line'";
81    }
82  }
83
84  my @sortedKeys = sort { lessKey($a,$b); } keys %keyedLines;
85  my @sortedLines = map { $keyedLines{$_}; } @sortedKeys;
86
87  my $countIn  = scalar(@$lines_r);
88  my $countOut = scalar(@sortedLines);
89  if ($countOut != $countIn) {
90    die "size changed in sort4 ($countIn -> $countOut)\n";
91  }
92
93  my $differs = 0;
94  for (my $i=0; $i<$countIn and $differs==0; ++$i) {
95    if ($sortedLines[$i] ne $$lines_r[$i]) {
96      $differs = 1;
97    }
98  }
99
100  if ($differs) {
101    @$lines_r = @sortedLines;
102  }
103  return $differs;
104}
105
106sub warnUnwantedItems($$$$) {
107  my ($fig,$item_line,$item_count,$description) = @_;
108  if ($item_count>0) {
109    print "$fig:$item_line: Warning: seen $item_count $description".($item_count>1 ? 's' : '')."\n";
110  }
111}
112
113sub sortFig($) {
114  my ($fig) = @_;
115
116  $formatDetected = undef;
117
118  eval {
119    my $changes = 0;
120    my $HEADERSIZE = 10;
121
122    my @out = ();
123    my @in4 = ();
124
125    my @item_count = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
126    my @item_line  = @item_count;
127
128    open(FIG,'<'.$fig) || die "cannot read '$fig' (Reason: $!)";
129    my $line;
130    my $linenr = 0;
131    while (defined($line=<FIG>)) {
132      ++$linenr;
133      my $num = -1;
134      if ($linenr>=$HEADERSIZE) {
135        if ($line =~ /^([0-9])\s/o) {
136          $num = $1;
137        }
138        elsif ($line =~ /^-([0-9])/o) {
139          $num = $1 + 10;
140        }
141
142        # log which item types are used in xfig:
143        ++$item_count[$num];
144        $item_line[$num] = $linenr;
145
146        if ($num == 4) {
147          push @in4, $line;
148        }
149        else {
150          if (scalar(@in4)) { $changes += sort4(@in4); push @out,@in4; @in4=(); }
151          push @out, $line;
152        }
153      }
154      else {
155        if ($line =~ /^#FIG\s2/o) { $HEADERSIZE = 2; } # older format -> shorter header
156        push @out, $line;
157      }
158    }
159    if (scalar(@in4)) { $changes += sort4(@in4); push @out,@in4; @in4=(); }
160    close(FIG);
161
162    warnUnwantedItems($fig,$item_line[0],$item_count[0],"useless color definition");
163    warnUnwantedItems($fig,$item_line[1],$item_count[1],"ignored ellipse");
164    warnUnwantedItems($fig,$item_line[3],$item_count[3],"ignored spline");
165    warnUnwantedItems($fig,$item_line[5],$item_count[5],"ignored arc");
166    warnUnwantedItems($fig,$item_line[6],$item_count[6],"(probably) forgotten compound");
167
168    if ($formatDetected eq 'old') {
169      print "$fig:0: Warning: ancient fig format detected\n";
170    }
171
172    if ($changes>0) {
173      print "Sorted changed fig '$fig'\n";
174      open(OUT,'>'.$fig) || die "cannot write to '$fig' (Reason: $!)";
175      foreach (@out) {
176        print OUT $_;
177      }
178      close(OUT);
179    }
180  };
181  if ($@) {
182    die "$@ (while sorting '$fig')";
183  }
184}
185
186sub getModtime($) {
187  my ($fileOrDir) = @_;
188  my $modtime = (stat($fileOrDir))[9];
189  return $modtime;
190}
191
192sub checkFigsNewerThan($$);
193sub checkFigsNewerThan($$) {
194  my ($figdir,$checkAfter) = @_;
195
196  my @sub = ();
197
198  opendir(DIR, $figdir) || die "cannot read directory '$figdir' (Reason: $!)";
199  foreach (readdir(DIR)) {
200    if ($_ ne '.' and $_ ne '..') {
201      my $full = $figdir.'/'.$_;
202      if (-d $full) {
203        push @sub, $full;
204      }
205      elsif (-f $full) {
206        if ($_ =~ /\.fig$/) {
207          my $mod = getModtime($full);
208          if ($mod>$checkAfter) {
209            sortFig($full);
210          }
211        }
212      }
213    }
214  }
215  closedir(DIR);
216
217  foreach (@sub) {
218    checkFigsNewerThan($_,$checkAfter);
219  }
220}
221
222sub main() {
223  my $topdir = $ENV{ARBHOME};
224
225  my $srctools = $topdir.'/SOURCE_TOOLS';
226  my $figbase  = $topdir.'/lib/pictures';
227
228  my $last_check_stamp = $srctools.'/sortfig.stamp';
229  unlink($last_check_stamp); # uncomment to force resort of all figs
230  # `touch $figbase/ad_branch.fig`;
231
232  if (not -d $srctools) {
233    die "No such directory '$srctools'\n ";
234  }
235  else {
236    my $checkAfter = 0;
237    if (-f $last_check_stamp) {
238      $checkAfter = getModtime($last_check_stamp)-5;
239    }
240
241    `touch $last_check_stamp`;
242    checkFigsNewerThan($figbase,$checkAfter);
243  }
244}
245
246# ----------------------------------------
247
248my $args = scalar(@ARGV);
249my $done = 0;
250if ($args==1) {
251  my $arg = shift @ARGV;
252  if ($arg eq 'doit') {
253    main();
254    $done = 1;
255  }
256}
257if (not $done) {
258  print "Usage: sortfig.pl doit\n";
259  print "Sorts some contents of .fig files, avoiding random useless changes between commits.\n";
260}
261
Note: See TracBrowser for help on using the repository browser.