#!/usr/local/bin/perl -w use Text::ParseWords; use Text::Tabs; use vars qw($qq); require "ctime.pl"; $progname = 'htm1-pp'; $sl = '.htm1' ; $inc = '.ht' ; # See Documentation now! # - the keys are case-sensitive (html isn't) %Tags = (); %UniTags = (); %Funcs = ( "raw" => \&unescape, "exec" => \&execute, "html-tag2" => \&add_html_tag2, "html-tag1" => \&add_html_tag1, "use" => \&useFile, "include" => \&includeFile, "html-def" => \&add_html_def, "html-esc" => \&html_add_esc, "html-undef" => \&undefineTag, "x" => \&html_direct, ); # shall we add all simple html-tags here? the default is to treat # unknown tags as html-def2: implicitly. The bad-hashes here # make the warning-message occur only once. %badBiTag = (); %badUniTag = (); %Vars = ( ); %ArgReplace = ( "top" => "valign=top", "middle" => "valign=middle", # td "bottom" => "valign=bottom", "left" => "align=left", # textual "center" => "align=center", "right" => "align=right", "justify" => "align=justify", "square" => "type=square", # ul "circle" => "type=circle", "disc" => "type=disc", "noborder" => "border=0", # img table "nounder" => "style=text-decoration:none", # links "nocellspacing" => "cellspacing=0", "nocellpadding" => "cellpadding=0", "nospacing" => "cellspacing=0", "nopadding" => "cellpadding=0", "bgcolor2" => 'bgcolor=$(bgcolor2)', "fgcolor2" => 'color=$Vars{"fgcolor2"}', "bginvers" => 'bgcolor=$Vars{"fgcolor2"}', "fginvers" => 'color=$Vars{"bgcolor2"}', "100%" => 'width=100%', "80%" => 'width=80%', "60%" => 'width=60%', "50%" => 'width=50%', "40%" => 'width=40%', "20%" => 'width=20%', ); %ArgShorthand = ( "w" => "width", "h" => "height", "bg" => "bgcolor", "a" => "alt", "n" => "name", "s" => "src", "ls" => "lowsrc", "ce" => "center", "re" => "right", "le" => "left", "b" => "border", "b0" => "noborder", "u0" => "nounder", "b2" => "bgcolor2", "f2" => "fgcolor2", "bx" => "bginvers", "fx" => "fginvers", "cs" => "cellspacing", "cp" => "cellpadding", ); @PostGeneration = (); $NOW = `date`; chop $NOW; $Text::Tabs::tabstop = 4; $MaxDate = 0; $Infile = "(unknown file)"; # Standard includes: try reading those config files $dotfix = "."; # change for a FAT file system ... for my $p ("/usr/etc/", "/usr/html/etc/", "$ENV{HOME}/etc/", "$ENV{HOME}/$dotfix", "./etc/", "$dotfix") { for my $i ("",1,2,3,4,5,6,7,8,9) { useFile ("$p$progname$inc$i") if -f "$p$progname$inc$i" ; my $file = "$p$progname.pl$i"; if (-f "$file") { print STDERR "imports $file\n"; unless ($return = do "$file") { warn "couldn't parse $file: $@" if $@; warn "couldn't do $file: $!" unless defined $return; warn "couldn't run $file" unless $return; } } } #old# useFile ("$p$progname$sl") if -f "$p$progname$sl" ; } $parse_body = 0; # some functions will produce different output # depending on context $silent = 1; # may suppress output in some functions # usually all tags like "x-tag-like" will suppress # warnings/errors about redefinition $line_replace = 1; # some functions differentiate on this # 0 - block replace e.g. {note: this text} # 1 - header line e.g. Content-Type: text\n.. # 2 - body line foreach $File (@ARGV) { if ($File !~ /$sl$/i) { warn "Skipping $File (no $sl extension)"; next; } if ($File =~ m#(.*)/#) { $Extras = $1; } else { $Extras = "."; } $Header = $Extras . "/.header"; $Footer = $Extras . "/.footer"; if (-f $Header) { open(H, "$Header") or die; $HeaderText = join ("", ); close (H); } else { $HeaderText = ""; } if (-f $Footer) { open(H, "$Footer") or die; $FooterText = join ("", ); close (H); } else { $FooterText = ""; } $Infile = $Title = $File; $Title =""; open (F, "$File") or die "Cannot open $File: $!"; $MaxDate = (stat $Infile)[9]; $File =~ s/$sl$/\.html/i; # !!!!!!!! open (O, ">" . $File) or die "Cannot open output $File: $!"; $_ = join("", expand()); $currentFile = $Infile; m/^( (?:[^\n]*\n (?!\s*\n))* (?:[^\n]*\n) ) (\s*\n) (.*) $/sx; $head = $1; $body = $3; $head = parseHead($head); $body = parseBody($HeaderText . $body . $FooterText); # print O "\n"; print O "$Title\n" ; print O "\n"; print O $head; print O "\n\n\n"; print O $body; print O "\n\n"; close (O); close (F); undef $head; # Let's do a bit checking foreach (@PostGeneration) { &$_(); } # print STDERR "Date is $Date - ", scalar(localtime($Date)), "\n"; utime $MaxDate,$MaxDate, $File or die "Oops: $!"; printf STDERR ("%-40s => $File (%d bytes)\n", $Infile, -s $Infile); } sub parseText { $_ = $_[0]; m/^( (?:[^\n]*\n (?!\s*\n))* (?:[^\n]*\n) ) (\s*\n) (.*) $/sx; $head = $1; $body = $3; $head = parseHead($head); $body = parseBody($body); } sub parseHead { $_ = $OriginalString = $_[0]; $parse_body = 0; # Escaped characters turn into \ooo, then are turned back later # s/\\(.)/exists $SpecialEscapes{$1} ? $SpecialEscapes{$1} : sprintf("\\%03o", ord($1))/egs; s/\\([^\w])/sprintf("\\%03o", ord($1))/egs; unless ($Special) { # These must be escaped FIRST! s/&/&/g; # Escape special characters foreach $c (sort keys %Escapes) { s/$c/$Escapes{$c}/g; } } # scan for implicit html-def -gud) s/^\[([\w\+\-\/\=\#]+)\:\](.*)$/&add_implicit_html_def($1,$2)/mge; # Non greedy match to the first paren OR # match until first leftparen, non-greedy match to matching right paren # and then non-greed match to the next paren # Note: this one does multiline matching # Note: We skip spaces, but note NEWLINES near {} foreach $qq (0..2) { # ... \ntag:(args) text\n - this is the version without '#' in names while ( s/(^)([\w\+\-\/][\w\+\-\/\=]*): (\([^)]*\))? [ ]* (.*(?:\n\s.*)*) /&parseArgs($3); $1 . &x_line_replace_head($2,$4)/mgex ) {} # .. {tag:(args) text} - expand those em'brace'd texts while( s/{([\w\+\-\/][\#\w\+\-\=]*): (\([^)]*\))? [ ]* ([^{}]*) [ ]* }/&parseArgs($2); &x_block_replace($1,$3)/sgex ) {} # ... \ntag:(args) text\n - this is the version *with* '#' in names while ( s/(^)([\w\+\-\/][\#\w\+\-\/\=]*): (\([^)]*\))? [ ]* (.*(?:\n\s.*)*) /&parseArgs($3); $1 . &x_line_replace_head($2,$4)/mgex ) {} # Magic functions (e.g. make table of contents, but can embed any perl wanted) s/~~(.*?)~~/eval "$1" or die "Embedded evaulation failed: $@"/seg; } # Unescape escaped characters s/\\(\d{3})/chr(oct($1))/ge; # cut multiplied newlines in the header s(\n+)(\n)sg ; return $_; } sub parseBody { my $parse = 2; $_ = $OriginalString = $_[0]; $parse_body = 1; # Escaped characters turn into \ooo, then are turned back later # s/\\(.)/exists $SpecialEscapes{$1} ? $SpecialEscapes{$1} : sprintf("\\%03o", ord($1))/egs; s/\\([^\w])/sprintf("\\%03o", ord($1))/egs; unless ($Special) { s/(^)(\<)(.*)$/$1x: $2$3/mg ; # These must be escaped FIRST! s/&/&/sg; s/\/>/sg ; # Escape special characters foreach $c (sort keys %Escapes) { s/$c/$Escapes{$c}/g; } } # Turn newlines into (soft)

s/^\s*$/

/mg; # scan for implicit html-def -gud) s/^\[([\w\+\-\/\.\=\#]+)\:\](.*)$/&add_implicit_html_def($1,$2)/mge; # for the mails s/(^)(\>\;)(.*)/ $1 > $3<\/i>/mg; # Non greedy match to the first paren OR # match until first leftparen, non-greedy match to matching right paren # and then non-greed match to the next paren # per document parse depth - choose with care if (exists $Vars{"parse"}) { $parse = $Vars{"parse"}; } while ($parse) { $parse -= 1; # print STDERR "parse=$parse\n"; # ... \ntag: (args) text\n - this is the version without '#' in names while ( s/(^)([\*\w\+\-\/\=][\w\+\-\/\.\=]*): (\([^)]*\))? [ ]* (.*) /&parseArgs($3); $1 . &x_line_replace($2,$4)/mgex ) {} # . word[tag:args] - expand words, marked by following bracket-tag while( s/ (^|\s) ([\w\+\-\/\.\'\@\&\%\$]*) \[ ([^\[\]]*) \] /$1.&x_block_bracket_word($3,$2)/mgex ) {} # . {text}[tag:args] - expand em'brace'd texts, marked by following bracket-tag while( s/ { ([^{}]*) } \[ ([^\[\]]*) \] /&x_block_bracket($2,$1)/sgex ) {} # . {tag:(args) text} - expand em'brace'd texts while( s/{([\w\+\-\/][\#\w\+\-\/\.\=]*):(\([^)]*\))? [ ]* ([^{}]*) [ ]* }/&parseArgs($2); &x_block_replace($1,$3)/sgex ) {} # ... \ntag: (args) text\n - this is the version *with '#' in names while ( s/(^)([\*\w\+\-\/\=][\#\w\+\-\/\.\=]*): (\([^)]*\))? [ ]* (.*) /&parseArgs($3); $1 . &x_line_replace($2,$4)/mgex ) {} # scan for simple brace-pairs not being a {tag: ...} if ( s/(\{(?![\w\+\-\/][\#\w\+\-\/\.\=]*:))([^\}]*)(\}(?!\[))/\&lb\;$2\&rb\;/sg ){ $parse += 1; } # Magic functions (e.g. make table of contents, but can embed any perl wanted) s/~~(.*?)~~/eval "$1" or die "Embedded evaulation failed: $@"/seg; } # multiple soft breaks to one real break s/()([\n\s]*
*)*/\n$1$2/sg; # bracelets to normal s/\&lb\;/\{/sg ; s/\&rb\;/\}/sg ; s/\&lp\;/\(/sg ; s/\&rp\;/\)/sg ; s/\&lk\;/\[/sg ; s/\&rk\;/\]/sg ; s/\"\;/\"/sg ; # Unescape escaped characters s/\\(\d{3})/chr(oct($1))/ge; return $_; } sub includeFile { my ($fname, $old,$text,@lines,$prepend,$append) = @_; die "Cannot open $fname: $!" unless open(I, $fname); $prepend = $append = ""; print STDERR "include $fname\n"; $old = $currentFile; $currentFile = $fname; @lines = ; if (exists $Args{prepend}) { $prepend = "$Args{prepend} "; $prepend =~ s/%/\@/g; } if (exists $Args{append}) { $append = " $Args{append} "; $append = ~s/%/\@/g; } $text = $prepend . join($prepend, @lines); $text =~ s/\n/\n$append/g; $text .= $append; # Ensure a file gets a modification date that depends on all the # files it has included $NewDate = (stat $fname)[9]; $MaxDate = $NewDate if $NewDate > $MaxDate; $Infile = $fname; $res = parseText($text); close (I); $currentFile = $old; return $res; } sub useFile { push @SpecialStack, $Special; $Special = 1; &includeFile($_[0]); $Special = pop @SpecialStack; } # (arg1,arg2) sub parseArgs { my ($args, $arg, $keyword, $value) = @_; my $var; undef %Args; if (defined($args)) { $args =~ s/^\s*\((.*)\)\s*$/$1/; # spill enclosing whitespace foreach $arg (split(' ',$args)) { ($keyword, $value) = split("=" ,$arg); if ($keyword =~ m/^\s*$/) { next; } if ($keyword =~ m/^\w\w?$/) { if (exists $ArgShorthand{$keyword}) { $keyword = $ArgShorthand{$keyword} ; } } if (!defined($value)) { if (exists $ArgReplace{$keyword}) { ($keyword, $value) = split("=", $ArgReplace{$keyword}); if (!defined($value)) { $value = 1; } } else { $value = 1; } } foreach $var (keys %Args) { $value =~ s/\$\($var\)/$Args{$var}/g; } foreach $var (keys %Vars) { $value =~ s/\$\($var\)/$Vars{$var}/g; } $value =~ s/^ *\"(.*)\" *$/$1/sg; # cut out superfluous quotings $Args{$keyword} = $value; } } } # Return currently set args in a form of URL string, i.e. value="something" sub getArgs { my ($arg, $s); $s = ""; foreach $arg (keys %Args) { if ($Args{$arg} =~ /^\d+$/) { $s .= " $arg=$Args{$arg}"; } else { $s .= " $arg=\"$Args{$arg}\""; } } # print "Returning: $s\n" if length($s); return $s; } # *un* escape escaped characters sub unescape { my ($text) = @_; foreach $c (keys %Escapes) { $text =~ s/$Escapes{$c}/$c/g; } $text =~ s/&/&/g; return $text; } sub x_no_block_bracket { return "\&lb;$_[1]\&rb;\[$_[0]\]"; } sub x_block_bracket { my $text = $_[1]; $_ = $_[0]; if (/^\s*([^\?\:]*):/) { # colon-style, a tradition s/^\s*([^\?\:]*):([^)]*)?/&parseArgs($2); &x_block_replace($1,$text)/sgex ; return $_; } else { if (/^[\/\%\=]/ or /[\/\%\=]$/ or /^[^\w]$/) { undef %Args; return &x_block_replace($_,$text); }else{ # print "huh?".&x_no_block_bracket(@_)."\n"; return &x_no_block_bracket(@_); } } } sub x_no_block_bracket_word { return "$_[1]\&lk\;$_[0]\&rk\;"; } sub x_block_bracket_word { my $text = $_[1]; $_ = $_[0]; if (/^\s*([^\?\:]*):/) { # colon-style, a tradition s/^\s*([^\?\:]*):([^)]*)?/&parseArgs($2); &x_block_replace($1,$text)/sgex ; return $_; } else { if (/^[\/\%\=]/ or /[\/\%\=]$/ or /^[^\w]$/) { undef %Args; return &x_block_replace($_,$text); }else{ # print "huh?".&x_no_block_bracket_word(@_)."\n"; return &x_no_block_bracket_word(@_); } } } sub x_block_replace { ($tag, $text, $fun,$rep) = @_; $line_replace = 0; if ($tag =~ /^[xX]-(.*)/) { # suppress warning $tag =~ s/^[xX]-// ; $silent = 1; }else{ $silent = 0; } if (exists $Funcs{$tag}) { $fun = $Funcs{$tag}; $rep =&$fun($text); } elsif (exists $Tags{$tag}) { $rep = "<$Tags{$tag}" . &getArgs() . ">$text<$End{$tag}>"; } elsif (exists $Defines{$tag}) { $rep = $Defines{$tag}; # $(*) or $() -> $text and $(.) -> $args $rep =~ s/\$\(\*?\)/$text/g ; $rep =~ s/\$\(\.\)/&getArgs()/ge; foreach $arg (keys %Args) { $rep =~ s/\$\($arg\)/$Args{$arg}/g; } foreach $arg (keys %Vars) { $rep =~ s/\$\($arg\)/$Vars{$arg}/g; } $rep =~ s/\$\((\w+)\)/ $1 /sg ; $rep =~ s/\$\((\w+)-(\w+)\)/ $1 $2 /sg ; } else { if ($tag =~ /^\/\w/) { # treat as implicit html-def2 my ($_tag, $_end); $_tag = $_end = $tag; $_tag =~ s/^\///; $_tag =~ s/_/ /g; $_end =~ s/^(\/[A-Za-z0-9]+).*/$1/; return "<$_tag".&getArgs().">$text<$_end>"; } elsif ($tag =~ /^\w+\/$/) { # treat as implicit html-def1 my $_tag = $tag; $_tag =~ s/\/$//; $_tag =~ s/_/ /g; return "<$_tag".&getArgs()."$text>"; } elsif (!exists $badBiTag{$tag}) { printf "unknown tag: {$tag: ...} in $Infile\n"; $badBiTag{$tag} = $tag; } if ( $text eq "") { $rep = "<$tag>" ; } else { $rep = "<$tag> $text " ; # easy yet powerful } } # unless ($Special) { print STDERR "\n{$tag($text)} => $rep\n"; } return $rep; } sub x_line_replace_head { ($tag, $text, $rep) = @_; $line_replace = 1; if ($tag =~ /^[xX]-(.*)/) { # will supress generation $tag =~ s/^[xX]-// ; # of meta-tag if unknown $silent = 1; }else{ $silent = 0; } $Vars{$tag} = $text; # overwrites if necessary if (exists $Funcs{$tag}) { $fun = $Funcs{$tag}; $rep =&$fun($text); } elsif (exists $UniTags{$tag}) { $rep = "<$UniTags{$tag}" . &getArgs() . ">$text"; } elsif (exists $Tags{$tag}) { $rep = "<$Tags{$tag}" . &getArgs() . ">$text<$End{$tag}>"; } elsif (exists $Defines{$tag}) { $rep = $Defines{$tag}; # $(*) or $() -> $text and $(.) -> $args $rep =~ s/\$\(\*?\)/$text/g ; $rep =~ s/\$\(\.\)/&getArgs()/ge; foreach $arg (keys %Args) { $rep =~ s/\$\($arg\)/$Args{$arg}/g; } foreach $arg (keys %Vars) { $rep =~ s/\$\($arg\)/$Vars{$arg}/g; } $rep =~ s/\$\((\w+)\)/ $1 /sg ; $rep =~ s/\$\((\w+)-(\w+)\)/ $1 $2 /sg ; } else { if ($tag =~ /^\/\w/) { # treat as implicit html-def2 my ($_tag, $_end); $_tag = $_end = $tag; $_tag =~ s/^\///; $_tag =~ s/_/ /g; $_end =~ s/^(\/[A-Za-z0-9]+).*/$1/; return "<$_tag".&getArgs().">$text<$_end>"; } elsif ($tag =~ /^\w+\/$/) { # treat as implicit html-def1 my $_tag = $tag; $_tag =~ s/\/$//; $_tag =~ s/_/ /g; return "<$_tag".&getArgs()."$text>"; } elsif ($silent) { $rep = ""; } else { $tag =~ s/^\s+//sg; $tag =~ s/\s+$//sg; # chop surrounding $text =~ s/^\s+//sg; $text =~ s/\s+$//sg; # whitespaces if ( $text eq "") { $rep = "" ; } else { $rep = "" ; } } } # unless ($Special) { print STDERR "\n^$tag($text) => $rep\n"; } return $rep; } sub x_line_replace { ($tag, $text, $rep) = @_; $line_replace = 2; if ($tag =~ /^[xX]-(.*)/) { # will supress a warning if the tag $tag =~ s/^[xX]-// ; # had been prepended with X- $silent = 1; }else{ $silent = 0; } $Vars{$tag} = $text; # overwrites if necessary if (exists $Funcs{$tag}) { $fun = $Funcs{$tag}; $rep =&$fun($text); } elsif (exists $UniTags{$tag}) { $rep = "<$UniTags{$tag}" . &getArgs() . ">$text"; } elsif (exists $Tags{$tag}) { $rep = "<$Tags{$tag}" . &getArgs() . ">$text<$End{$tag}>"; } elsif (exists $Defines{$tag}) { $rep = $Defines{$tag}; # $(*) or $() -> $text and $(.) -> $args $rep =~ s/\$\(\*?\)/$text/g ; $rep =~ s/\$\(\.\)/&getArgs()/ge; foreach $arg (keys %Args) { $rep =~ s/\$\($arg\)/$Args{$arg}/g; } foreach $arg (keys %Vars) { $rep =~ s/\$\($arg\)/$Vars{$arg}/g; } $rep =~ s/\$\((\w+)\)/ $1 /sg ; $rep =~ s/\$\((\w+)-(\w+)\)/ $1 $2 /sg ; } else { if ($tag =~ /^\/\w/) { # treat as implicit html-def2 my ($_tag, $_end); $_tag = $_end = $tag; $_tag =~ s/^\///; $_tag =~ s/_/ /g; $_end =~ s/^(\/[A-Za-z0-9]+).*/$1/; return "<$_tag".&getArgs().">$text<$_end>"; } elsif ($tag =~ /^\w+\/$/) { # treat as implicit html-def1 my $_tag = $tag; $_tag =~ s/\/$//; $_tag =~ s/_/ /g; return "<$_tag".&getArgs()."$text>"; } elsif (!exists $badUniTag{$tag}) { printf "unknown tag: ^$tag: ...^ in $Infile\n" if ! $silent; $badUniTag{$tag} = $tag; } $rep = "
$tag: $text"; # just keep it } # print STDERR "\n$tag($text) \n=> \n$rep\n"; return $rep; } sub execute { my ($program, $out, $ignoreError) = @_; $ignoreError = 1 if $program =~ s/^-//; $out = qx/$program/; die "Error executing $program: $?" if !$ignoreError and $?; chomp $out; return $out; } sub undefineTag { my $tag; foreach $tag (split(",", $_[0])) { delete $Tags{$tag} if exists $Tags{$tag}; delete $End{$tag} if exists $End{$tag}; delete $UniTags{$tag} if exists $UniTags{$tag}; delete $Defines{$tag} if exists $Defines{$tag} } } sub add_html_tag2 { my ($tag, $repl, $end) = ($_[0] =~ /^(\S+)\s+"(.*?)"(?:\s*"(.*)")?/); if (!defined $repl) { $tag = $_[0]; $tag =~ s/^(\S+)/$1/; $repl = $tag; } die "Duplicate tag $tag ($currentFile:$.)" if exists $Tags{$tag} and !$silent; die "You must supply a replacement ($currentFile:$.)" unless length $repl; $Tags{$tag} = $repl; if (defined($end)) { $End{$tag} = $end; } else { $end = $repl; $end =~ s/^\s*(.*)$/$1/s ; # kill prefix-spaces $end =~ s/\s.*//sg; # chop off everything past the first whitespace $End{$tag} = "/$end"; } return ""; } sub add_html_tag1 { my ($tag, $repl) = ($_[0] =~ /^(\S+)\s+"(.*)"/); # die "Already define as bitag ($currentFile:$.)" if exists $Tags{$tag}; die "Duplicate tag $tag ($currentFile:$.)" if exists $UniTags{$tag} and !$silent; die "You must supply a replacement ($currentFile:$.)" unless length $repl; $UniTags{$tag} = $repl; return ""; } # Parse some well known escape codes sub parseEscapeCodes { my ($s) = @_; $s =~ s/\\n/\n/; # print STDERR "define = $s\n"; return $s; } sub add_html_def { my ($tag, $repl) = ($_[0] =~ /^(\S+)\s+(.*)/) or die "Invalid line: $_[0]\n"; $repl =~ s/^\"(.*)\"/$1/g; # chop off surrounding quotes die "Already define as bitag ($currentFile:$.)" if exists $Tags{$tag} and !$silent; die "Already defined as unitag $tag ($currentFile:$.)" if exists $UniTags{$tag} and !$silent; die "You must supply a replacement ($currentFile:$.)" unless length $repl; $Defines{$tag} = &html_direct (&parseEscapeCodes($repl)); return ""; } sub add_implicit_html_def { my ($tag, $repl) = @_ ; $tag =~ s/^\s+//sg; $tag =~ s/\s+$//sg; # chop surrounding $repl =~ s/^\s+//sg; $text =~ s/\s+$//sg; # whitespaces $repl =~ s/^\"(.*)\"$/$1/g; # chop off surrounding quotes die "Already defined as bitag ($currentFile:$.)" if exists $Tags{$tag} and !$silent; die "Already defined as unitag $tag ($currentFile:$.)" if exists $UniTags{$tag} and !$silent; die "You must supply a replacement ($currentFile:$.)" unless length $repl; $Defines{$tag} = &html_direct (&parseEscapeCodes($repl)); return ""; } sub html_add_esc { my ($tag, $repl) = ($_[0] =~ /^(\S+)\s+(.*)/) or die "Invalid escape: $_[0]"; die "Already defined: $1" if $Escapes{$1}; $Escapes{$1} = "&$2;"; } sub html_direct { my $rep = $_[0]; $rep =~ s/</\/sg; $rep =~ s/&/&/sg; $rep =~ s/"/\"/sg ; return $rep; }