Source

Website Meta Language / src / wml_aux / freetable / freetable.src

Full commit
Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 










Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 







Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 















Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 




Shlomi Fish 70148ee 








































































































shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 










shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 


shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 

Shlomi Fish 70148ee 

































shl...@7081e830-… c3ccf86 

Shlomi Fish 70148ee 



shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 











shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 





















shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 








shl...@7081e830-… c3ccf86 



Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 




shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 

Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 



Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 







Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 


















Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 



shl...@7081e830-… c3ccf86 





Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 







Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 



Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 








Shlomi Fish 70148ee 





























































shl...@7081e830-… c3ccf86 

Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 







Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 








Shlomi Fish 70148ee 

shl...@7081e830-… c3ccf86 














Shlomi Fish 70148ee 






shl...@7081e830-… c3ccf86 

Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 


Shlomi Fish 70148ee 
shl...@7081e830-… c3ccf86 
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
#!@PATH_PERL@ -w
eval 'exec @PATH_PERL@ -w -S $0 ${1+"$@"}'
    if $running_under_some_shell;

# Freetable html tables generator
# Copyright (c) 1999, 2000, 2001 Tomasz Wegrzanowski <taw@users.sourceforge.net>
#
# Freetable is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Thanks to Denis Barbier <barbier@imacs.polytechnique.fr> for contribution
#
# On Debian GNU/Linux systems, the complete text of the GNU General
# Public License can be found in `/usr/share/common-licenses/GPL'.

$version = '2.3';

$warning =
'<!-- WARNING: The following table was produced by freetable.               -->
<!--          Unless know what you are doing, you should not edit it here,  -->
<!--          but edit sources and then run freetable to rebuild this table -->

';

$help =
'Usage: freetable [options] filename

Options:
  -h, --help             Print this message
  -V, --version          Just print version information and exit
  -c, --comment          Do comment before every cell to point its location
  -b, --no-nbsp          Do not insert &nbsp; to empty cells to make lowered
                         3D apperance
  -w, --warning          Print a warning before each generated table that you
                         should not change generated file, but source.
  -l, --location         Location tags substitution
  -m, --macro [program]  Use macro processor for cells content (default: m4)
';

use Getopt::Long;
$Getopt::Long::bundling=1;
my (@opts) = ("b|no-nbsp","c|comment","w|warning","h|help","V|version","m|macro:s","l|location");
$opt_h=$opt_V=$opt_b=$opt_c=$opt_w=$opt_m=$opt_l=0;
GetOptions(@opts);
if ($opt_m eq "") { $opt_m = 'm4' }
if ($opt_h) { print $help; exit 0 }
if ($opt_V) { print "Freetable $version\n"; exit 0 }
$defaultcell = ($opt_b)?'':'&nbsp;';
($min_row,$min_col) = (1,1);
$tablewarn   = ($opt_w)?$warning:'';

while (<>)  { if ( /<wwwtable(.*)>/i ) { table_parse($1,0) } else { print } }

sub table_parse {
    my ( $table_open_data, $level ) = @_;
    my ( $table_close_data, $table_started ) = ( '', 0 );
    my ( %cell,%entry );
    my @Seq_data = (1,1,1,1); # max_row, max_col, cur_row, cur_col

    while (<>) {
	if ( /<wwwtable(.*)>/i )
	    { table_entry_content_append_block (\%entry,table_parse($1, $level+1)); }
        elsif ( /<\/wwwtable(.*)>/i )
	    { $table_close_data = $1; last }
	elsif ( /^\s*\(\(\s*\{(.*?)\}\s*,\s*\{(.*?)\}\s*\)\)(.*)$/ )
	    { table_entry_new (\%entry,\@Seq_data, $1,$2,$3,'c',1); $table_started = 1; }
	elsif ( /^\s*\(\(\s*(.*?)\s*;\s*(.*?)\s*\)\)(.*)$/ )
	    { table_entry_new (\%entry,\@Seq_data,$1,$2,$3,'r',1); $table_started = 1; }
	elsif ( /^\s*\(\(\s*(.*?)\s*,\s*(.*?)\s*\)\)(.*)$/ )
	    { table_entry_new (\%entry,\@Seq_data,$1,$2,$3,'t',1); $table_started = 1; }
	elsif ( /^\s*\(\s*\{(.*?)\}\s*,\s*\{(.*?)\}\s*\)(.*)$/ )
	    { table_entry_new (\%entry,\@Seq_data,$1,$2,$3,'c',0); $table_started = 1; }
	elsif ( /^\s*\(\s*(.*?)\s*;\s*(.*?)\s*\)(.*)$/ )
	    { table_entry_new (\%entry,\@Seq_data,$1,$2,$3,'r',0); $table_started = 1; }
	elsif ( /^\s*\(\s*(.*?)\s*,\s*(.*?)\s*\)(.*)$/ )
	    { table_entry_new (\%entry,\@Seq_data,$1,$2,$3,'t',0); $table_started = 1; }
	elsif ( $table_started )
	    { table_entry_content_append_line (\%entry,$_) }
	else
	    { print }
    }
    expand_rx (\%entry, $Seq_data[0], $Seq_data[1]);
    entries2table  (\%entry,\%cell,$Seq_data[0],$Seq_data[1]);
    complete_table (\%cell,$Seq_data[0],$Seq_data[1]);
    return table_render ($level,\%cell,$Seq_data[0],$Seq_data[1],$table_open_data,$table_close_data);
}

sub early_seq {
    my ($str, $addr_type, $max, $cur) = @_;
    my (@a, %h);
    if ($str eq '*') {
	$address = '.*';
	$addr_type='x';
    } elsif ($str eq '=' or $str eq '')  {
	$address = [$cur];
	$addr_type='a';
    } elsif ($str =~ /^([\+-])(\d*)$/) {
	$cur += ((($1 eq '+')?1:-1) * (($2 eq '')?1:$2));
	$address = [$cur];
	$addr_type='a';
    } elsif ($addr_type eq 'c') {
	eval "\@a=($str)";
	$cur = $a[-1];
	@h{@a} = 1;
	@a = sort {$a <=> $b} keys %h;
	$address = \@a;
	$addr_type = 'a'
    } elsif ($addr_type eq 'r') {
	foreach my $r(split /\s*,\s*/,$str)
	{
	    if ($r =~ /(\d+)-(\d+)/) { push @a, $1..$2 }
	    else { push @a, $r }
	}
	$cur = $a[-1];
	@h{@a} = 1;
	@a = sort {$a <=> $b} keys %h;
	$address = \@a;
	$addr_type = 'a'
    } elsif ($str =~ /^\d+$/) {
	$cur = $str;
	$address = [$cur];
	$addr_type = 'a';
    } else {
	$address = $str;
	$addr_type = 'x';
    }
    if ($addr_type eq 'a' and $address->[-1] > $max) {
	$max = $address->[-1]
    }

#   $addr_type.in  ::= 't', 'r', 'c'
#   $addr_type.out ::= 'x', 'a'
    return ($addr_type, $address, $max, $cur);
}

sub expand_rx {
    my %entries = %{$_[0]};
    my ($max_row, $max_col) = ($_[1], $_[2]);
    my $len = $#{$entries{head}};
    for $entrynr(0..$len) {
	if ( ${$entries{at_c}}[$entrynr] eq 'x' ) {
	    my $rx = '^'.${$entries{col}}[$entrynr].'$';
	    $rx = qr/$rx/;
	    my @a = grep { /$rx/ } 1..$max_col;
	    ${$entries{col}}[$entrynr] = \@a;
	    ${$entries{at_c}}[$entrynr] = 'a';
	}
	if ( ${$entries{at_r}}[$entrynr] eq 'x' ) {
	    my $rx = '^'.${$entries{row}}[$entrynr].'$';
	    $rx = qr/$rx/;
	    my @a = grep { /$rx/ } 1..$max_row;
	    ${$entries{row}}[$entrynr] = \@a;
	    ${$entries{at_r}}[$entrynr] = 'a';
	}
    }
}

sub table_entry_new {
    my ($entry,$Seq_data,$row,$col,$data,$addr_type,$is_header) = @_;
    my ($at_r, $ar, $at_c, $ac);
    ($at_r, $ar, $Seq_data->[0], $Seq_data->[2]) = early_seq($row, $addr_type, $Seq_data->[0], $Seq_data->[2]);
    ($at_c, $ac, $Seq_data->[1], $Seq_data->[3]) = early_seq($col, $addr_type, $Seq_data->[1], $Seq_data->[3]);
    push @{$$entry{at_r}},$at_r;
    push @{$$entry{at_c}},$at_c;
    push @{$$entry{row}},$ar;
    push @{$$entry{col}},$ac;
    push @{$$entry{head}},$data;
    push @{$$entry{is_h}},$is_header;
    push @{$$entry{cont}},'';
}

sub table_entry_content_append_line {
    my ( $entry, $data ) = @_;
    $data =~ /^\s*(.*)$/;
    $$entry{cont}[-1] .= (($$entry{cont}[-1] and $1)?"\n":'').$1;
}

sub table_entry_content_append_block {
    my ( $entry, $data ) = @_;
    $$entry{cont}[-1] .= "\n".$data;
}

sub table_render {
    my ( $level,$cell,$max_row,$max_col,$table_open_data,$table_close_data ) = @_;
    my ( $table_text,$processed_text );
    $table_text .= $tablewarn;
    $table_text .= "<table$table_open_data>\n";
    foreach my $row ($min_row..$max_row) {
	$table_text .= "  <tr>\n";
	foreach my $col ($min_col..$max_col) {
	    $table_text .= "    <!-- cell ($row,$col) -->\n" if ($opt_c);
	    location_tags_substitute (\$$cell{content}[$row][$col],$row,$col) if ($opt_l);
	    $table_text .= "    <t$$cell{type}[$row][$col]$$cell{header}[$row][$col]>$$cell{content}[$row][$col]</t$$cell{type}[$row][$col]>\n" unless ($$cell{void}[$row][$col])
	}
	$table_text .= "  </tr>\n"
    }
    $table_text.= "</table$table_close_data>\n";
    if ( $opt_m ) {
	if ( $level ) {
	    use IPC::Open2;
	    pipe MACROR,MACROW;
	    open2 \*MACROR,\*MACROW,$opt_m;
	    print MACROW $table_text;
	    close MACROW;
	    foreach (<MACROR>) { $processed_text.=$_ }
	    close MACROR;
	    return $processed_text;
	} else {
	    open MACROW,"|$opt_m";
	    print MACROW $table_text;
	    close MACROW;
	}
    } else {
	if ( $level ) { return $table_text }
	else { print $table_text }
    }
}

sub location_tags_substitute {
    my ( $cell,$row,$col ) = @_;
    $$cell =~ s/<row>/$row/gi;
    $$cell =~ s/<col>/$col/gi;
}

sub entries2table {
    my ($entryref,$cellref,$max_row,$max_col) = @_;
    my %entry = %$entryref;
    my $len = $#{$entry{head}};; ## row-P ?
    foreach my $entrynr (0..$len) {
	my @rowmask = @{${$entry{row}}[$entrynr]};
	my @colmask = @{${$entry{col}}[$entrynr]};
	foreach my $row (@rowmask) {
	    foreach my $col (@colmask) {
	        complete_cell ($entryref,$cellref,$row,$col,$entrynr)
	    }
	}
    }
}

sub complete_cell {
    my ( $entry,$cell,$row,$col,$entrynr ) = @_;
    my ( $colspan,$rowspan ) = (0,0);

    $$cell{header} [$row][$col] .= $$entry{head}[$entrynr];
    $$cell{content}[$row][$col] .= (($$cell{content}[$row][$col] and $$entry{cont}[$entrynr])?' ':'').$$entry{cont}[$entrynr];
    $$cell{type}   [$row][$col]  = $$entry{is_h}[$entrynr];
    $colspan = $1 if ($$entry{head}[$entrynr] =~ /colspan\s*=\s*(\S+)/i);
    $rowspan = $1 if ($$entry{head}[$entrynr] =~ /rowspan\s*=\s*(\S+)/i);

    if ($colspan) {
	if ($rowspan) {
	        foreach my $void_col(($col+1)..($col+$colspan-1))
		{$$cell{void}[$row][$void_col] = 1}
	    foreach my $void_row(($row+1)..($row+$rowspan-1)) {
	        foreach my $void_col(($col)..($col+$colspan-1))
		{ $$cell{void}[$void_row][$void_col] = 1 }
	    }
	} else {
	    foreach my $void_col(($col+1)..($col+$colspan-1))
		{ $$cell{void}[$row][$void_col] = 1 }
	}
    } elsif ($rowspan) {
	    foreach my $void_row(($row+1)..($row+$rowspan-1))
		{ $$cell{void}[$void_row][$col] = 1 }
    }
}

sub complete_table {
    my ( $cell,$max_row,$max_col ) = @_;
    foreach my $row ($min_row..$max_row) {
	foreach my $col ($min_col..$max_col) {
	    $$cell{type}[$row][$col] = $$cell{type} [$row][$col] ? 'h':'d'; # header-set-once or overwrite ?
	    $$cell{header}[$row][$col] = ''            unless ($$cell{header}[$row][$col]);
	    $$cell{content}[$row][$col] = $defaultcell unless ($$cell{content}[$row][$col]);
	}
    }

}

=head1 NAME

B<freetable> - tool for making HTML tables generation easier

=head1 VERSION

This manpage describes version 2.3 of B<freetable>.

It might be not 100% accurate if you use different version.

=head1 SYNOPSIS

B<freetable> I<[options]> I<filename>

or

B<freetable> I<[options]>

Possible options are :

I<-h>, I<--help>     Print usage info and exit

I<-V>, I<--version>  Print version information and exit

I<-c>, I<--comment>  Insert comment before every cell to point its location

I<-b>, I<--no-nbsp>  Do not insert I<&nbsp;> to empty cells for lowered-3D apperance

I<-w>, I<--warning>  Print a warning before each generated table
that you should not change it. You should change its source.

I<-l>, I<--location> Substitute I<E<lt>rowE<gt>> and I<E<lt>colE<gt>> flags
inside table with correct cell's location

I<-m>, I<--macro> I<[program]>
               Use macro procesor to proces cells content (default: B<m4>)

=head1 WARNING

 DO NOT USE MACRO PROCESSOR OVER UNSURE SOURCE
 M4 MAY BE USED TO COMPROMISE YOUR SECURITY
 FOR MORE INFORMATION ON THIS EXEC :

I<info m4 'UNIX commands' syscmd>

=head1 DESCRIPTION

This is free replacement of B<wwwtable>

HTML is great language, but have one horrible flaw :
tables. I spent many hours looking at HTML source I just written
and trying to guess which cell in source is which in browser.

If this also describes you, then read this manpage and your
pain will stop.

Program read HTML source from either I<stdin> or file. Then it
searches for line starting table:

    <wwwtable [options]>

Then it analyzes table, put correct HTML table in this place and
continue searching for the next table.

=head1 TABLE SYNTAX

It is very easy:

    wwwtable :
    <wwwtable [wwwtable_options]>
    [preamble]
    [cell]
    [cell]
    ...
    </wwwtable>

wwwtable_options will be passed to I<E<lt>tableE<gt>> tags. There is
no magic inside preamble. It can be any HTML text. It will be simply
put in front of table.

cell is either normal_cell (I<E<lt>tdE<gt>> tag) or
header_cell (I<E<lt>thE<gt>> tag).
At least it was this way in freetable 1.x.
See the next section for alternative cell address syntax.

    normal_cell :
    (row,col) cell_options
    cell_content

    header_cell :
    ((row,col)) cell_options
    cell_content

cell_options will be passed to cell tag. There is magic inside
I<colspan> and I<rowspan> keys are parsed to make correct table.

cell_content can be anything. It may contain text, tags, and
even nested wwwtables.

If you use I<-m> (or I<--macro>) option, it will be passed thru m4(1),
with <row> and <col> set to adress of curent cell

row and col are either numbers locating cells, expressions relative to previous cell
or regular expresions to match few of them. Unlike B<wwwtable>, B<freetable> can use regular
expresions for header cells. Also I<*> can be used, and it mean I<.*> really.

Relative expressions are :

I<=> or empty means : the same as previous

I<+> or I<+X> means : one and X more than previous

I<-> or I<-X> means : one and X less than previous

If many definisions adress the same cell all options and contents are
concatenated in order of apperance.

If you want to use only regular expresions you must tell
program about the last cell :

    <wwwtable>
    (*,1)
    these are colums 1
    (1,*)
    these are rows 1
    (4,4)
    </wwwtable>

=head1 ALTERNATIVE CELL ADDRESS SYNTAX

It is inconvenient to specify cell address as regular expression.
So in B<freetable> 2.0 two new methods were introduced.
Both can be used to either normal or header cells.

Full bakward compatibility is preserved.
To preserve it, new syntax had to be introduced.
Unfortunatelly, you can't specify row
address using one method, and column address using another.
To come around this, both new methods are very liberal
and allow you to use I<=>, I<+>, I<->, I<+X> I<-X> and null
string with the same meaning as they have in old addressing
method.

Unlike regular expression method,
new methods will find out the last cell automatically.

=head2 EXPLICIT RANGES

    (rowrange;colrange) cell_options
    cell_content

Syntax for both rowrange and colrange is like: 1-2,4-7,9,12.
Duplicates will be eliminated. For purpose of relative addresses
last given number is used. So if you write

    (1-100,32;1)
    foo
    (+,)
    bar

Cell (33,1) will contain `foobar' and all others only `foo'.

=head2 ARBITRARY PERL CODE

    ({code for rows},{code for tables}) cell_options
    cell_content

You can use arbitrary Perl one-liner as long as it matches our
not very intelligent regular expressions and evaluates to list.
Unfortunatelly there isn't any regular expression for Perl code,
but as long as it doesn't contain I<},{> and I<})> it should work.
Example:

    <wwwtable>
    ({grep {$_%3 == 1} 1..100},{1..2,4})
    foo
    </wwwtable>

Will evaluate to 100 rows x 4 columns table with `foo' in
every 1st, 2nd and 4th column of every row with number equal 1 modulo 3.

If you want to use "arbitrary code" in one part of address and
explicit range in the other, change I<-> into I<..> in defenition of
range, and put in between I<{> and I<}>.

If you want to use "arbitrary code" in one part of address and
regular expression in the other, you have to write
I<{grep {/expression/} from..to}>.
Unfortunatelly, in this case you have to specify size of the table explicitely.

=head1 INCOMPATIBILITIES WITH WWWTABLE

If you was formerly user of B<wwwtable> and want to change your tool, you
should read this. Most of this is about regexps handling.
Notice also that B<wwwtable> couldnt do location tags substitution nor macroprocesing.

Option I<-w> has completely oposite meaning. We dont print warnings by default,
and I<-w> or I<--warning> is used to force warnings.

Table header fields can be specified by regexps ex :

    ((1,*))

It was impossible in B<wwwtable>.

Axis counters are 100% orthogonal. This mean that code :

    (*,1) width=30
    (*,2) width=35
    (*,3) width=40
    (=,=)
    Foo

Foo will appear in 3rd column. If you wanted it to be in 1st
you should write :

    (*,1) width=30
    (*,2) width=35
    (*,3) width=40
    (=,1)
    Foo

or

    (*,) width=30
    (*,+) width=35
    (*,+) width=40
    (=,1)
    Foo

In B<freetable> 2.0 two new methods o specifying cell address
were introduced. They are completely incompatible with B<wwwtable>.

=head1 BUGS

"Arbitrary Perl Code" cell address will fail on very complex Perl code.

=head1 SEE ALSO

B<m4(1)>

=head1 AUTHOR

Tomasz Wegrzanowski <taw@users.sourceforge.net>

=cut