Select Git revision
module_magic.h
-
Marcus Comstedt authored
Rev: src/module_magic.h:1.9
Marcus Comstedt authoredRev: src/module_magic.h:1.9
wmml_to_html 8.83 KiB
#!/usr/local/bin/pike
import Stdio;
import spider;
import Array;
mapping(int:mapping) links=([]);
string p1(string data);
/* Note: destructive ! */
string *srt(string *foo)
{
sort(map(foo,lower_case),foo);
return foo;
}
string quote_param(string s)
{
string ret="";
while(sscanf(s,"%[-a-zA-Z0-9/()*,.]%c%s",string a, int c,s)==3)
ret+=sprintf("%s%%02x",a,c);
return ret+s;
}
string unquote_param(string s)
{
string *tmp=s/"%";
for(int e=1;e<sizeof(tmp);e++)
if(sscanf(tmp[e],"%2x%s",int x, string rest))
tmp[e]=sprintf("%c%s",x,rest);
return tmp*"";
}
string code_params(mapping s)
{
string ret="";
foreach(indices(s), string data)
ret+=" "+data+"="+quote_param(s[data]);
return ret;
}
/* Index handling */
void _add_to(mapping foo, string bar, string full)
{
mapping m;
if(!bar)
{
if(foo[0])
{
foo[0]|=({full});
}else{
foo[0]=({full});
}
return;
}
sscanf(bar,"%s.%s",bar,string rest);
if(!(m=foo[bar])) m=foo[bar]=([]);
_add_to(m, rest,full);
}
void add_to(string bar, string full)
{
sscanf(lower_case(unquote_param(bar)),"%*[_ ]%c",int c);
mapping m;
if(!(m=links[c])) m=links[c]=([]);
_add_to(m, bar, full);
}
string anchor(mixed a, mixed b, mixed c)
{
if(b->name)
{
if(c[strlen(c)-10..]=="<!--END-->")
werror("Warning: Anchor not ended "+b->name+".\n");
add_to(b->name, b->name);
string *foo=b->name/".";
for(int e=1;e<sizeof(foo);e++)
add_to(foo[e], foo[..e]*".");
}
if (a=="anchor")
return "<a name="+b->name+">"+c+"</a name="+b->name+">";
return 0;
}
string mklink(string lnk) { return "<a href=#"+lnk+">"+unquote_param(lnk)+"</a>"; }
string genindex(mapping m, string prefix)
{
string ret="<dl>\n";
if(m[0])
{
foreach(srt(m[0]), string lnk)
ret+="<dt>"+mklink(lnk)+"\n";
}
m_delete(m,0);
foreach(srt(indices(m)), string ind)
{
if(m[ind][0] &&
sizeof(m[ind])==1 &&
sizeof(m[ind][0])==1 &&
m[ind][0][0]==prefix+ind)
{
foreach(srt(m[ind][0]), string lnk)
ret+="<dt>"+mklink(lnk)+"\n";
}else{
ret+="<dt>"+unquote_param(prefix+ind)+"\n"+
"<dd>\n"+
genindex(m[ind], prefix+ind+".");
}
}
ret+="</dl>\n";
return ret;
}
/* chapter handling */
mixed *tod=({});
string prefix="";
string chapter(string tag, mapping params, string data);
string section(string tag, mapping params, string data);
string appendix(string tag, mapping params, string data);
string appendixes(string tag, mapping params, string data);
#define TAGS \
(["chapter":chapter,"section":section,\
"appendix":appendix,"appendixes":appendixes])
mapping aliases=([]);
string rtag(string name,
string title,
string outtitle,
string xlink,
string sectionname,
mapping params,
string data)
{
if(data[strlen(data)-10..]=="<!--END-->")
werror("Warning: "+name+" tag not ended "+title+".\n");
string *save=tod;
string save_prefix=prefix;
tod=({});
prefix+=xlink+".";
data+="\n<!--END-->";
data=parse_html(data,([]),TAGS);
prefix=save_prefix;
tod=save+({prefix+xlink,sectionname||(prefix+xlink),title,tod});
if(params->alias)
{
aliases[params->alias]=
({
prefix+xlink,
sectionname || ( name + " " + prefix+xlink )
})
;
}
if(data[strlen(data)-10..]=="<!--END-->")
data=data[..strlen(data)-11];
string tmp;
switch(sizeof(prefix/"."))
{
case 0:
case 1: tmp="h1"; break;
case 2: tmp="h2"; break;
case 3:
default: tmp="h3"; break;
}
return
"<a name="+ prefix+xlink +">\n"+
"<"+tmp+">"+outtitle+"</"+tmp+">"+
data+"\n"+
"</a> <!-- "+name+" "+prefix+xlink+" -->\n"+
"<p>\n";
}
string section(string tag, mapping params, string data)
{
int c = sizeof(tod)/4 +1;
return rtag("section",
params->title,
prefix+c+" "+params->title,
(string)c,
0,
params,
data);
}
string chapter(string tag, mapping params, string data)
{
int c = sizeof(tod)/4+1;
return rtag("chapter",
params->title,
"Chapter "+prefix+c+", "+params->title,
(string)c,
0,
params,
data);
}
string appendixes(string tag, mapping params, string data)
{
return rtag("appendixes",
"",
"Appendixes",
"Appendix",
"Appendixes",
params,
data);
}
int appnum = 'A';
string appendix(string tag, mapping params, string data)
{
string c=sprintf("%c",appnum++);
return rtag("appendix",
params->title,
"Appendix "+c+", "+params->title,
c,
"Appendix "+c,
params,
data);
}
string gencontents(mixed *tod)
{
if(!sizeof(tod)) return "";
string ret="<dl>\n";
for(int e;e<sizeof(tod);e+=4)
{
ret+="<dt><b><a href=#"+tod[e]+">"+tod[e+1]+"</b> "+tod[e+2]+"</a>\n";
string tmp=gencontents(tod[e+3]);
if(strlen(tmp)) ret+="<dd>\n"+tmp;
}
ret+="</dl>";
return ret;
}
/* Stage 2 */
mapping replacements=([]);
string do_replace(string what)
{
return replacements[lower_case(what)];
}
string encaps1(string word)
{
return "<font size=+1>"+word[0..0]+"</font><font size=-1>"+word[1..]+"</font>";
}
string encaps(string tag, mapping params, string data)
{
return "<b>"+map((data/" ")-({""}),encaps1)*" "+"</b>";
}
string link(string tag, mapping params, string data)
{
mixed tmp=aliases[params->to];
if(!tmp)
{
werror("Unresolved <link> :"+params->to+"\n");
return 0;
}
return "<a href=#"+tmp[0]+">"+tmp[1]+"</a>";
}
string box(string tag, mapping params, string data)
{
return "<center><table border=1>\n"+
data+
"</table></center>\n";
}
string do_include(string tag, mapping params, string data)
{
return Stdio.read_file(params->file);
}
string end_img_tag(string ret, mapping params)
{
if(params->align) ret+=" align="+quote_param(params->align);
if(params->alt) ret+=" alt="+quote_param(params->align);
return ret+">";
}
int gifnum;
mapping gifcache=([]);
string mkgif(object o)
{
string g=o->togif();
if(gifcache[g]) return gifcache[g];
gifnum++;
string gifname="illustration"+gifnum+".gif";
rm(gifname);
write_file(gifname,g);
gifcache[g]=gifname;
return gifname;
}
mapping gifcache2=([]);
mapping srccache=([]);
string illustration(string tag, mapping params, string data)
{
string src=params->src;
object img=Image.image();
float dpi=75.0;
if(params->dpi) dpi=(float)params->dpi;
if(params->scale) dpi/=(float)params->scale;
float scale=75.0/dpi;
string key=encode_value(({src,scale,data}));
string file;
if(!(file=gifcache2[key]))
{
mixed e;
if(params->src)
img=srccache[src] ||
(srccache[src]=img->fromppm(Process.popen("anytopnm "+src)));
if(scale!=1.0) img=img->scale(scale);
if (e=catch
{
img=compile_string("import Image;\n"
"object `()(object src){ "+data+" ; }")()(img);
file=mkgif(img);
gifcache2[key]=file;
})
{
werror("error while compiling and running\n"+data+"\n");
if (params->__from__)
werror("from "+params->__from__+":\n");
werror(master()->describe_backtrace(e)+"\n");
return "<!-- failed to illustrate -->";
}
params-=(["__from__":0]);
}
return end_img_tag("<img src="+file,params);
}
string image(string tag, mapping params, string data)
{
string ret;
if(params->xfig)
{
Process.system("fig2dev -L ps "+params->xfig+".fig ___tmp.ps;echo showpage >>___tmp.ps");
object o=Image.image()->fromppm(
Process.popen("gs -q -sDEVICE=pbmraw -r225 -g2500x2500 -sOutputFile=- ___tmp.ps"));
o=o->autocrop()->scale(1.0/3)->rotate(-90);
o=Image.image(o->xsize()+40, o->ysize()+40, 255,255,255)->paste(o,20,20);
string gifname=mkgif(o);
rm("___tmp.ps");
ret="<img src="+quote_param(gifname);
}
else if(params->src)
{
return illustration(tag,params,"return src");
}
else
{
return "";
werror("Unknown image type\n");
}
return end_img_tag(ret,params);
}
int main()
{
string data=Stdio.stdin.read(0x7fffffff);
data+="\n<!--END-->";
/* Preprocess */
data=parse_html(data,(["include":do_include]),([]));
/* Pass 1, find links for the index */
data=parse_html(data, ([]) , (["a":anchor,"anchor":anchor]));
/* Pass 2, parse chapters and sections */
data=parse_html(data, ([]) , TAGS);
/* Build index */
string index="<dl>\n";
foreach(sort(indices(links)), int letter)
{
index+="<dt><font size=+2>"+
(letter=='`'?"Operators": upper_case(sprintf("%c",letter)))+
"</font>\n"+
"<dd>\n"+
genindex(links[letter],"");
}
index+="</dl>\n";
replacements->index=index;
/* Build table of contents */
replacements["table-of-contents"]=gencontents(tod);
/* Pass 3, insert generated data */
write(parse_html(data,
([
"index":do_replace,
"table-of-contents":do_replace,
"link":link,
"image":image,
]),
([
"box":box,
"encaps":encaps,
"illustration":illustration,
])));
}