From fee798eda451d56fc8be6c478243d4f8f8cd1880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Mon, 25 Aug 1997 15:57:35 -0700 Subject: [PATCH] new files (new wmml->html converter) Rev: tutorial/Html.pmod:1.1 Rev: tutorial/Sgml.pmod:1.1 Rev: tutorial/Wmml.pmod:1.1 Rev: tutorial/html.pike:1.1 Rev: tutorial/html_onepage.pike:1.1 Rev: tutorial/types.h:1.1 Rev: tutorial/wmmltohtml2:1.1 --- tutorial/Html.pmod | 62 +++ tutorial/Sgml.pmod | 190 +++++++++ tutorial/Wmml.pmod | 673 ++++++++++++++++++++++++++++++++ tutorial/html.pike | 775 +++++++++++++++++++++++++++++++++++++ tutorial/html_onepage.pike | 4 + tutorial/types.h | 4 + tutorial/wmmltohtml2 | 29 ++ 7 files changed, 1737 insertions(+) create mode 100644 tutorial/Html.pmod create mode 100644 tutorial/Sgml.pmod create mode 100644 tutorial/Wmml.pmod create mode 100644 tutorial/html.pike create mode 100644 tutorial/html_onepage.pike create mode 100644 tutorial/types.h create mode 100755 tutorial/wmmltohtml2 diff --git a/tutorial/Html.pmod b/tutorial/Html.pmod new file mode 100644 index 0000000000..dbc7f62417 --- /dev/null +++ b/tutorial/Html.pmod @@ -0,0 +1,62 @@ +string *quote_from; +string *quote_to; +string *unquote_from; +string *unquote_to; + +void create() +{ + quote_from=quote_to=unquote_from=unquote_to=({}); + for(int e=0;e<256;e++) + { + switch(e) + { + case 'a'..'z': + case 'A'..'Z': + case '0'..'9': + case 'å': case 'ä': case 'ö': + case 'Å': case 'Ä': case 'Ö': + case 'ü': case 'Ü': + case '!': + case '#': + case '$': + case '&': + case '/': + case '(': + case ')': + case '=': + case '-': + case '_': + case '+': + case '?': + case '~': + case '*': + case ',': + case '.': + case ';': + case ':': + break; + + default: + quote_from+=({sprintf("%c",e)}); + quote_to+=({sprintf("%%%02x",e)}); + } + unquote_from+=({sprintf("%%%02x",e)}); + unquote_to+=({sprintf("%c",e)}); + } +} + +string quote_param(string s) { return replace(s,quote_from,quote_to); } +string unquote_param(string s) { return replace(s,unquote_from,unquote_to); } + +string mktag(string tag, mapping params) +{ + string ret="<"+tag; + foreach(indices(params),string i) + { + ret+=" "+quote_param(i); + + if(stringp(params[i])) + ret+="='"+quote_param(params[i])+"'"; + } + return ret+">"; +} diff --git a/tutorial/Sgml.pmod b/tutorial/Sgml.pmod new file mode 100644 index 0000000000..4694c9df56 --- /dev/null +++ b/tutorial/Sgml.pmod @@ -0,0 +1,190 @@ +string *from=({" ","&","<",">"}); +string *to=({" ","&","<",">"}); + +string unquote(string x) { return replace(x,from,to); } +string quote(string x) { return replace(x,to,from); } + +class Tag +{ + string tag; + int pos; + mapping(string:mixed) params=([]); +// array(Tag) data; + array(object) data; + + varargs void create(string t, mapping p, int po, array(object) d) + { + tag=t; pos=po; params=p||([]); data=d; + } +}; + +#define TAG object(Tag)|string +#define SGML array(TAG) + +SGML lex(string data) +{ + mixed foo=data/"<"; + SGML ret=({ unquote(foo[0]) }); + int pos=strlen(foo[0]); + for(int e=1;e<sizeof(foo);e++) + { + string tag; + string s=foo[e]; + pos++; + + if(s[0..2]=="!--") + { + pos+=strlen(foo[e]); + while(sscanf(s,"%*s-->%s",s)!=2) + { + e++; + s+="<"+foo[e]; + pos+=strlen(foo[e])+1; + } + ret[-1]+=unquote(s); + continue; + } + + if(sscanf(s,"%[^ \t\n\r>]%s",tag,s)!=2) + werror(sprintf("Missing end > (around pos %d)\n",pos)); + + tag=lower_case(tag); + mapping params=([]); + + while(1) + { + sscanf(s,"%*[ \t\r\n]%s",s); + if(!strlen(s)) + { + write(sprintf("Missing end > (around pos %d)\n",pos)); + break; + } + if(s[0]=='>') + { + s=s[1..]; + break; + } + + if(sscanf(s,"%[^ \t\r\n>=]%s",string key,s) && strlen(key)) + { + key=lower_case(key); + if(s[0]=='=') + { + string val; + switch(s[1]) + { + case '\'': + while(sscanf(s,"='%s'%s",val,s)!=2) + { + e++; + s+="<"+foo[e]; + pos+=strlen(foo[e])+1; + } + break; + case '\"': + while(sscanf(s,"=\"%s\"%s",val,s)!=2) + { + e++; + s+="<"+foo[e]; + pos+=strlen(foo[e])+1; + } + break; + default: + sscanf(s,"=%[^ \t\r\n>]%s",val,s); + break; + } + if(!val) + { + werror("Missing end quote parameter\n"); + } + params[key]=val; + }else{ + params[key]=1; + } + } + } + + ret+=({ Tag(tag,params,pos), unquote(s) }); + pos+=sizeof(foo[e]); + } + + return ret; +} + + +SGML group(SGML data) +{ + SGML ret=({}); + foreach(data,TAG foo) + { + if(objectp(foo)) + { + if(strlen(foo->tag) && foo->tag[0]=='/') + { + string tag=foo->tag[1..]; + for(int d=sizeof(ret)-1;d>=0;d--) + { + if(objectp(ret[d]) && !ret[d]->data && ret[d]->tag==tag) + { + ret[d]->data=ret[d+1..]; + ret=ret[..d]; + break; + } + } + if(d>=0) continue; + } + } + ret+=({foo}); + } + return ret; +} + + +string generate(SGML data) +{ + string ret=""; + foreach(data, TAG foo) + { + if(stringp(foo)) + { + ret+=quote(foo); + }else{ + ret+="<"+foo->tag; + foreach(indices(foo->params), string name) + ret+=" "+name+"="+foo->params[name]; + + ret+=">"; + if(foo->data) + { + ret+=generate(foo->data); + ret+="</"+foo->tag+">"; + } + } + } + + return ret; +} + +SGML copy(SGML data) +{ + if(!data) return 0; + SGML ret=({}); + foreach(data,TAG t) + { + if(stringp(t)) + { + ret+=({t}); + }else{ + ret+=({Tag(t->tag,t->params+([]),t->pos,copy(t->data))}); + } + } + return ret; +} + + +#ifdef TEST +int main() +{ + write(sprintf("%O\n",group(lex(Stdio.read_file("tutorial.wmml"))))); +} +#endif diff --git a/tutorial/Wmml.pmod b/tutorial/Wmml.pmod new file mode 100644 index 0000000000..58254fe7c7 --- /dev/null +++ b/tutorial/Wmml.pmod @@ -0,0 +1,673 @@ +#include "types.h" + +static private int verify_any(SGML data, string in) +{ + int i=1; + foreach(data,mixed x) + { + if(objectp(x)) + { + if(strlen(x->tag) && x->tag[0]=='/') + { + werror("Unmatched "+x->tag+" near pos "+x->pos+"\n"); + werror(in); + i=0; + continue; + } + switch(x->tag) + { + default: + werror("Unknown tag "+x->tag+" near pos "+x->pos+".\n"); + werror(in); + i=0; + break; + + case "font": + case "firstpage": + case "preface": + case "introduction": + + case "chapter": + case "appendix": + case "i": + case "b": + case "a": + case "anchor": + case "tt": + case "pre": + case "tr": + case "td": + case "table": + case "box": + case "h1": + case "h2": + case "h3": + case "dl": + case "ul": + case "section": + case "center": + case "ol": + case "encaps": + case "th": + case "illustration": + case "strong": + case "link": + + case "ex_identifier": + case "ex_keyword": + case "ex_string": + case "ex_comment": + case "example": + if(!x->data) + { + werror("Tag "+x->tag+" not closed near pos "+x->pos+".\n"); + werror(in); + i=0; + } + + break; + + case "ex_indent": + case "ex_br": + case "dt": + case "dd": + case "li": + case "ref": + case "hr": + case "br": + case "img": + case "image": + case "table-of-contents": + case "index": + if(x->data) + { + werror("Tag "+x->tag+" should not be closed near pos "+x->pos+"\n"); + werror(in); + i=0; + } + case "p": + } + + if(x->data) + if(!verify_any(x->data," In tag "+x->tag+" near pos "+x->pos+"\n"+in)) + i=0; + } + } + return i; +} + +int verify(SGML data) +{ + return verify_any(data,""); +} + +int islink(string tag) +{ + switch(tag) + { + case "anchor": + case "chapter": + case "preface": + case "introduction": + case "section": + case "table": + case "appendix": + case "image": + case "illustration": + return 1; + } +} + +INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken) +{ + if(!index) index=([]); + if(!taken) taken=([]); + + foreach(data,TAG data) + { + if(objectp(data)) + { + if(islink(data->tag)) + { + if(string real_name=data->params->name) + { + string new_name=real_name; + + if(taken[new_name]) + { + int n=2; + werror("Warning, duplicate "+real_name+" near pos "+data->pos+".\n"); + while(taken[new_name+"_"+n]) n++; + new_name+="_"+n; + } + taken[new_name]++; + data->params->name=new_name; + + if(index[real_name]) + { + index[real_name]+=({new_name}); + }else{ + index[real_name]=({new_name}); + } + } + } + if(data->data) + collect_index(data->data,index,taken); + } + } + return index; +} + +INDEX newind; +INDEX_DATA index; + +static private void build_index(string from, string fullname) +{ + mapping m=newind; + + if(string *to=index[fullname]) + { + foreach(from/".",string tmp) + { + if(mapping m2=m[tmp]) + m=m2; + else + m=m[tmp]=([]); + } + if(!m[0]) m[0]=([]); + m[0][fullname]=to; + } +} + +INDEX group_index(INDEX_DATA i) +{ + newind=([]); + index=i; + foreach(indices(index),string real_name) + { + string *to=index[real_name]; + build_index(real_name,real_name); + string *from=real_name/"."; + for(int e=1;e<sizeof(from);e++) + build_index(from[e], from[..e]*"."); + } + index=0; + return newind; +} + +INDEX group_index_by_character(INDEX i) +{ + mapping m=([]); + foreach(indices(i),string key) + { + int c; + sscanf(lower_case(key),"%*[_ ]%c",c); + string char=upper_case(sprintf("%c",c)); +// werror(char +" : "+key+"\n"); + if(!m[char]) m[char]=([]); + m[char][key]=i[key]; + } + return m; +} + +multiset reserved_pike = +(< + "array","break","case","catch","continue","default","do","else","float", + "for","foreach","function","gauge","if","inherit","inline","int","lambda", + "mapping","mixed","multiset","nomask","object","predef","private","program", + "protected","public","return","sscanf","static","string","switch","typeof", + "varargs","void","while" +>); + +multiset reserved_c = +(< + "break","case","continue","default","do","else","float","double", + "for","if","int","char","short","unsigned","long", + "public","return","static","switch", + "void","while" +>); + +object(Sgml.Tag) parse_pike_code(string x, int pos, multiset(string) reserved) +{ + int p,e; + SGML ret=({ "" }); + +// werror("'"+x+"'"); + /* Strip leading newlines */ + while(e<strlen(x) && x[e]=='\n') e++; + +// werror("e="+e+"\n"); + int tabindented; + if(x[e]=='\t') + { + tabindented=1; + e++; + } + +// werror("tabindented="+tabindented+"\n"); + + for(;e<strlen(x);e++) + { + switch(x[e]) + { + case '_': + case 'a'..'z': + case 'A'..'Z': + { + p=e; + + while(1) + { + switch(x[++e]) + { + case '_': + case 'a'..'z': + case 'A'..'Z': + case '0'..'9': + continue; + } + break; + } + + string id=x[p..--e]; + if(reserved[id]) + ret+=({ Sgml.Tag("ex_keyword",([]), pos+e, ({ id }) ) }); + else + ret+=({ Sgml.Tag("ex_identifier",([]), pos+e, ({ id }) ) }); + break; + } + + + case '\'': + p=e; + while(x[++e]!='\'') + if(x[e]=='\\') + e++; + ret+=({ Sgml.Tag("ex_string",([]), pos+e, ({ x[p..e]}) ) }); + break; + + case '"': + p=e; + while(x[++e]!='"') + if(x[e]=='\\') + e++; + + ret+=({ Sgml.Tag("ex_string",([]), pos+e, ({ x[p..e] }) ) }); + break; + + case '\n': + ret+=({ Sgml.Tag("ex_br", ([]), pos+e) }); + + if(tabindented) + { + for(int y=1;y<9;y++) + { + switch(x[e+y..e+y]) + { + case " ": continue; + case "\t": e+=y; + default: + } + break; + } + } + + while(x[e+1..e+1]=="\t") + { + ret+=({ + Sgml.Tag("ex_indent", ([]), pos+e), + Sgml.Tag("ex_indent", ([]), pos+e), + Sgml.Tag("ex_indent", ([]), pos+e), + Sgml.Tag("ex_indent", ([]), pos+e), + }); + e++; + } + + while(x[e+1..e+2]==" ") + { + ret+=({ Sgml.Tag("ex_indent", ([]), pos+e) }); + e+=2; + } + break; + + case '/': + if(x[e+1..e+1]=="/") + { + p=e++; + while(x[e]!='\n') e++; + e--; + ret+=({ Sgml.Tag("ex_comment",([]), pos+e, ({ x[p..e]}) ) }); + break; + } + + if(x[e+1..e+1]=="*") + { + p=e++; + while(x[e..e+1]!="*/") e++; + e++; + ret+=({ Sgml.Tag("ex_comment",([]), pos+e, ({ x[p..e]}) ) }); + break; + } + + default: + ret[-1]+=x[e..e]; + continue; + } + ret+=({ "" }); + } + + return Sgml.Tag("example",([]),pos,ret); +} + +SGML handle_include(SGML data) +{ + if(!data) return 0; + for(int e=0;e<sizeof(data);e++) + { + if(!stringp(data[e])) + { + switch(data[e]->tag) + { + case "include": + data= + data[..e-1]+ + Sgml.group(Sgml.lex(Stdio.read_file(data[e]->params->file)))+ + data[e+1..]; + e--; + continue; + + case "example": + switch(data[e]->params->language) + { + case "pike": + data[e]=parse_pike_code(data[e]->data[0], + data[e]->pos, + reserved_pike); + break; + + case "c": + data[e]=parse_pike_code(data[e]->data[0], + data[e]->pos, + reserved_c); + break; + } + } + data[e]->data=handle_include(data[e]->data); + } + } + return data; +} + +void save_image_cache(); + +int gifnum; +mapping gifcache=([]); + +string mkgif(object o) +{ + string g=o->togif(); + int key=hash(g); + + foreach(gifcache[key]||({}),string file) + { + if(Stdio.read_file(file)==g) + { + werror("Cache hit in mkgif: "+file+"\n"); + return file; + } + } + + gifnum++; + string gifname="illustration"+gifnum+".gif"; + rm(gifname); + werror("Writing "+gifname+".\n"); + Stdio.write_file(gifname,g); + + if(gifcache[key]) + gifcache[key]+=({gifname}); + else + gifcache[key]=({gifname}); + + return gifname; +} + + +object render_illustration(string pike_code, mapping params, float dpi) +{ + werror("Rendering "); + string src=params->src; + object img=Image.image(); + + if(params->dpi) dpi=(float)params->dpi; + if(params->scale) dpi/=(float)params->scale; + float scale=75.0/dpi; + + if(params->src) img=img->fromppm(Process.popen("anytopnm 2>/dev/null "+src)); + if(scale!=1.0) img=img->scale(scale); + return compile_string("object `()(object src){ "+pike_code+" ; }")()(img); +} + +private static string mkkey(mapping params, mixed ... other) +{ + params+=([]); + m_delete(params,"align"); + m_delete(params,"alt"); + if(params->src) + if(mixed x=file_stat(params->src)) + params->mtime=(string)(x[3]); + string *keys=indices(params); + string *values=values(params); + sort(keys,values); + + return encode_value( ({keys,values,other}) ); +} + +mapping illustration_cache=([]); +string illustration_to_gif(TAG data, float dpi) +{ + mapping params=data->params; + string pike_code=data->data[0]; + string key=mkkey(params,pike_code,dpi); + + string ret=illustration_cache[key]; + if(!ret) + { + ret=mkgif(render_illustration(pike_code,params, dpi)); + illustration_cache[key]=ret; + save_image_cache(); + } + return ret; +} + +string image_to_gif(TAG data, float dpi) +{ + mapping params=data->params; + if(params->xfig) + params->src=params->xfig+".fig"; + + string key=mkkey(params,dpi); + + string ret=illustration_cache[key]; + if(!ret) + { + if(!params->src) + { + werror("Image without source near pos "+data->pos+".\n"); + return ""; + } + string ext=reverse(params->src); + sscanf(ext,"%s.",ext); + switch(reverse(ext)) + { + case "fig": + werror("Converting "); + Process.system("fig2dev -L ps "+params->src+" ___tmp.ps;echo showpage >>___tmp.ps"); + Process.system("gs -q -sDEVICE=pbmraw -r225 -g2500x2500 -sOutputFile=___tmp.ppm ___tmp.ps </dev/null >/dev/null"); + object o=Image.image()->fromppm(Stdio.read_file("___tmp.ppm"))->autocrop()->scale(1.0/3)->rotate(-90); + o=Image.image(o->xsize()+40, o->ysize()+40, 255,255,255)->paste(o,20,20); + rm("___tmp.ps"); + rm("___tmp.ppm"); + ret=mkgif(o); + break; + + default: + ret=mkgif(render_illustration("return src",params,dpi)); + break; + } + + illustration_cache[key]=ret; + save_image_cache(); + } + return ret; +} + +void save_image_cache() +{ + rm("illustration_cache"); + Stdio.write_file("illustration_cache", + encode_value(([ + "gifnum":gifnum, + "gifcache":gifcache, + "illustration_cache":illustration_cache, + ]))); +} + +void create() +{ + if(file_stat("illustration_cache")) + { + mixed x=decode_value(Stdio.read_file("illustration_cache")); + gifnum=x->gifnum; + gifcache=x->gifcache; + illustration_cache=x->illustration_cache; + } +} + +int chapters; +int appendices; + +static private SGML low_collect_toc(mixed *data, + string prefix, + int *current) +{ + SGML ret=({}); + + foreach(data, TAG t) + { + if(objectp(t)) + { + switch(t->tag) + { + case "section": + t->params->number=prefix+(string)current[-1]; + + ret+=({ + Sgml.Tag("section_toc", + t->params, + t->pos, + low_collect_toc(t->data, + t->params->number+".", + current+({1}))) + }); ; + current[-1]++; + break; + + case "chapter": + if(current) + werror("Chapter inside chapter/appendix near "+t->pos+".\n"); + t->params->number=(string)chapters; + + ret+=({ + Sgml.Tag("chapter_toc", + t->params, + t->pos, + low_collect_toc(t->data, + t->params->number+".", + ({1}))) + }); + chapters++; + break; + + case "appendix": + if(current) + werror("Appendix inside chapter/appendix near "+t->pos+".\n"); + + t->params->number=sprintf("%c",appendices); + + ret+=({ + Sgml.Tag("appendix_toc", + t->params, + t->pos, + low_collect_toc(t->data, + t->params->number+".", + ({1}))), + }); + appendices++; + break; + + case "preface": + if(current) + werror("Preface inside chapter/appendix near "+t->pos+".\n"); + + t->params->number="preface"; + + ret+=({ + Sgml.Tag("preface_toc", + t->params, + t->pos, + low_collect_toc(t->data, + t->params->number+".", + ({1}))), + }); + break; + + case "introduction": + if(current) + werror("Introduction inside chapter/appendix near "+t->pos+".\n"); + + t->params->number="introduction"; + + ret+=({ + Sgml.Tag("introduction_toc", + t->params, + t->pos, + low_collect_toc(t->data, + t->params->number+".", + ({1}))), + }); + break; + + case "index": + case "table-of-contents": + t->params->number=t->tag; + ret+=({ + Sgml.Tag(t->tag+"_toc", + t->params, + t->pos) + }); + break; + + + default: + if(t->data) + ret+=low_collect_toc(t->data,prefix,current); + } + } + } + return ret; +} + +SGML sort_toc(SGML toc) +{ + // Assume correct order + return toc; +} + +SGML collect_toc(SGML data) +{ + SGML toc; + chapters=1; + appendices='A'; + toc=low_collect_toc(data,"",0); + return sort_toc(toc); +} diff --git a/tutorial/html.pike b/tutorial/html.pike new file mode 100644 index 0000000000..1e8ea49cf9 --- /dev/null +++ b/tutorial/html.pike @@ -0,0 +1,775 @@ +#include "types.h" +inherit Stdio.File : out; + +SGML html_toc; +SGML html_index; +mapping(string:SGML) sections=([]); +mapping(string:string) link_to_page=([]); +string basename; + +string mkfilename(string section) +{ + if(section=="") return basename+".html"; + return basename+"_"+section+".html"; +} + + +TAG mkimgtag(string file, mapping params) +{ + mapping p=([]); + p->src=file; + if(params->align) p->align=params->align; + if(params->alt) p->align=params->alt; + return Sgml.Tag("img",p,0); +} + +string *srt(string *x) +{ + string *y=allocate(sizeof(x)); + for(int e=0;e<sizeof(y);e++) + { + y[e]=lower_case(x[e]); + sscanf(y[e],"%*[ ,./_]%s",y[e]); + } + sort(y,x); + return x; +} + +void add_target_to_links(SGML foo, string target) +{ + foreach(foo, TAG t) + { + if(objectp(t)) + { + switch(t->tag) + { + case "link": + case "ref": + case "a": + if(!t->params->target) + t->params->target=target; + } + + if(t->data) + add_target_to_links(t->data,target); + } + } +} + +varargs SGML low_toc_to_wmml(SGML toc) +{ + int app; + SGML ret=({}); + + foreach(toc, TAG t) + { + string name; + string link; + string title; + + switch(t->tag) + { + case "chapters_toc": + ret+=low_toc_to_wmml(t->data); + continue; + + case "index_toc": + case "table-of-contents_toc": + case "preface_toc": + case "introduction_toc": + name=0; + title=t->params->title; + sscanf(t->tag,"%s_toc",link); + break; + + case "chapter_toc": + case "section_toc": + name=t->params->number; + link=t->params->number; + title=t->params->title; + switch( (name/".")[0] ) + { + case "introduction": + case "preface": + name=""; + break; + } + break; + + case "appendices_toc": + name=0; + link=0; + title="Appendices"; + break; + + case "appendix_toc": + name="Appendix "+t->params->number; + link=t->params->number; + title=t->params->title; + break; + + default: + werror("Error in generated TOC structure.\n"); + } + + mixed tmp=({ " "+title }); + if(name) + tmp=({ Sgml.Tag("b",([]),t->pos,({name})) }) + tmp; + + if(link) + tmp=({ Sgml.Tag("link",(["to":link]), t->pos, tmp) }); + + ret+=({Sgml.Tag("dt",([]),t->pos) })+ + tmp+ + ({"\n"}); + + if(t->data) + { + ret+=({ + Sgml.Tag("dd",([]),t->pos), + Sgml.Tag("dl",([]),t->pos, + low_toc_to_wmml(t->data)), + "\n" + }); + } + } + return ret; +} + +SGML toc_to_wmml(SGML toc) +{ + return ({ + Sgml.Tag("dl",([]),0, low_toc_to_wmml(toc)) + }); +} + +SGML low_index_to_wmml(INDEX data, string prefix) +{ + SGML ret=({}); + foreach(srt(indices(data)-({0})),string key) + { + ret+=({Sgml.Tag("dt")}); + + if(data[key][0]) + { + if(data[key][0][prefix+key]) + { + ret+=({ + // FIXME: show all links + Sgml.Tag("link",(["to":data[key][0][prefix+key][0] ]),0, ({key})), + "\n" + }); + }else{ + ret+=({key+"\n"}); + } + + foreach(srt(indices(data[key][0])), string key2) + { + if(key2==prefix+key) continue; + ret+=({ + Sgml.Tag("dd"), + // FIXME: show all links + Sgml.Tag("link",([ "to":data[key][0][key2][0] ]),0,({key2})), + "\n" + }); + } + + }else{ + ret+=({key+"\n"}); + } + + if(sizeof(data[key]) > !!data[key][0]) + { + ret+=({ + Sgml.Tag("dd"), + "\n", + Sgml.Tag("dl",([]),0,low_index_to_wmml( + data[key], + prefix+key+"." + )), + "\n", + }); + } + } + + return ret; +} + +SGML index_to_wmml(INDEX data) +{ + SGML ret=({}); + foreach(srt(indices(data)-({0})),string key) + { + if(sizeof(data[key]) > !!data[key][0]) + { + ret+=({ + Sgml.Tag("dt"), + Sgml.Tag("h2",([]),0,({key})), + "\n", + Sgml.Tag("dd"), + Sgml.Tag("dl",([]),0,low_index_to_wmml(data[key],"")), + }); + } + } + + return ({ + Sgml.Tag("dl",([]),0, ret) + }); +} + +int cpos; + +SGML wmml_to_html(SGML data); + +/* Partially destructive! */ +SGML convert(SGML data) +{ + if(!data) return 0; + SGML ret=({}); + foreach(data,TAG data) + { + if(stringp(data)) + { + ret+=({data}); + } + else + { + cpos=data->pos; + switch(data->tag) + { + case "hr": + data->params->noshade=1; + data->params->size="1"; + break; + + case "link": + { + data->tag="a"; + string to=data->params->to; + m_delete(data->params,"to"); + if(!link_to_page[to]) + { +// werror("Warning: Cannot find link "+to+" (near pos "+data->pos+")\n"); + } + data->params->href=mkfilename(link_to_page[to])+"#"+to; + break; + } + + case "anchor": data->tag="a"; break; +// case "ref": + + case "ex_identifier": + case "ex_string": + case "ex_commend": + ret+=convert(data->data); + continue; + + case "example": data->tag="blockquote";break; + case "ex_keyword": data->tag="b";break; + case "ex_br": data->tag="br"; break; + + case "ex_indent": + ret+=({" "}); + continue; + + case "table-of-contents": + { + SGML tmp=html_toc; + if(data->params->target) + { + werror("(targeting)"); + tmp=Sgml.copy(tmp); + add_target_to_links(tmp,data->params->target); + } + ret+=({ + Sgml.Tag("h1",([]),data->pos, + ({ + data->title || "Table of contents", + })) + + })+convert(tmp); + continue; + } + + case "index": + ret+=({ + Sgml.Tag("h1",([]),data->pos, + ({ + data->title || "Index", + })) + + })+convert(html_index); + continue; + + case "preface": + case "introduction": + ret+= + ({ + Sgml.Tag("h1",([]),data->pos, + ({ + data->params->title, + })), + "\n", + })+ + convert(data->data); + continue; + + case "chapter": + ret+= + ({ + Sgml.Tag("h1",([]),data->pos, + ({ + "Chapter ", + data->params->number, + ", ", + data->params->title, + })), + "\n", + })+ + convert(data->data); + continue; + + case "appendix": + ret+=({ + Sgml.Tag("h1",([]),data->pos, + ({ + "Appendix ", + data->params->number, + ", ", + data->params->title, + })), + "\n" + })+ + convert(data->data) + ; + continue; + + case "section": + { + string *tmp=data->params->number/"."; + int level=sizeof(tmp); + switch(tmp[0]) + { + case "introduction": + case "preface": + ret+=({ + Sgml.Tag("h"+level,([]),data->pos, + ({ + data->params->title, + })), + "\n" + })+ + convert(data->data) + ; + continue; + + default: + ret+=({ + Sgml.Tag("h"+level,([]),data->pos, + ({ + data->params->number, + " ", + data->params->title, + })), + "\n" + })+ + convert(data->data) + ; + continue; + } + } + + case "encaps": + { + SGML t=({}); + + foreach(data->data[0]/" "-({""}),string tmp) + { + t+=({ + Sgml.Tag("font",(["size":"+1"]),data->pos,({tmp[0..0]})), + Sgml.Tag("font",(["size":"-1"]),data->pos,({tmp[1..]})), + " " + }); + } + + ret+=({ Sgml.Tag("b",([]),data->pos,t) }); + continue; + } + + case "illustration": + ret+=({ mkimgtag(Wmml.illustration_to_gif(data,75.0),data->params) }); + continue; + + case "image": + ret+=({ mkimgtag(Wmml.image_to_gif(data,75.0),data->params) }); + continue; + + case "box": + ret+=({ + Sgml.Tag("table", + (["cellpadding":"10", + "width":"100%", + "border":"1", + "cellspacing":"0"]),data->pos, + ({ + "\n", + Sgml.Tag("tr",([]),data->pos, + ({ + Sgml.Tag("td",([]),data->pos, + convert(data->data)) + })) + })), + "\n", + }); + continue; + } + data->data=convert(data->data); + ret+=({data}); + } + } + return ret; +} + +SGML wmml_to_html(SGML data) +{ + SGML ret=convert(data); + if(!(objectp(data[0]) && (data[0]->tag=="body" || data[0]->tag=="frameset"))) + { + ret=({ + Sgml.Tag("body", + ([ + "bgcolor":"#A0E0C0", + "text":"#000000", + "link":"blue", + "vlink":"purple", + ]),0, + ret), + }); + } + + return ({ + Sgml.Tag("html",([]),0, + ({ + "\n", + Sgml.Tag("head",([]),0, + ({ + Sgml.Tag("title",([]),0, + ({ + "Pike Manual", + })), + "\n" + })), + })+ + ret), + "\n", + }); +} + +SGML low_split(SGML data) +{ + SGML current=({}); + foreach(data, TAG t) + { + if(objectp(t)) + { + switch(t->tag) + { + case "preface": + if(!sections->introduction) + sections->introduction=({t}); + else + sections->introduction+= + ({ + t, + Sgml.Tag("hr") + })+ + sections->introduction; + continue; + + case "introduction": + if(!sections->introduction) + sections->introduction=({}); + else + sections->introduction+= + ({ + Sgml.Tag("hr",(["size":"1","noshade":1]),0) + }); + + + sections->introduction+=({ + t + }); + continue; + + case "index": + case "chapter": + case "appendix": + sections[t->params->number]=({ t }); + continue; + + case "firstpage": + current+= + t->data+ + ({ + Sgml.Tag("hr",(["size":"1","noshade":1]),0) + }); + + sections->firstpage=({ + t, + }); + continue; + + case "table-of-contents": + sections->frame=({ + Sgml.Tag("frameset",(["cols":"30%,*"]),0, + ({ + "\n", + Sgml.Tag("frame",(["src":mkfilename("toc_frame"),"name":"toc"])), + "\n", + + Sgml.Tag("frame",(["src":mkfilename("firstpage"),"name":"display"])), + "\n", + + })), + "\n", + }); + + sections->toc_frame=Sgml.copy(({ t })); + sections->toc_frame[0]->params->target="display"; + sections->toc_frame[0]->params->name="toc_frame"; + break; + + default: + if(t->data) + t->data=low_split(t->data); + } + } + current+=({t}); + } + + return current; +} + +void de_abstract_anchors(SGML data) +{ + for(int e=0;e<sizeof(data);e++) + { + TAG t=data[e]; + if(objectp(t)) + { + if(Wmml.islink(t->tag)) + { + if(string tmp=t->params->name) + data[e]=Sgml.Tag("anchor",(["name":tmp]),t->pos,({data[e]})); + + if(string tmp=t->params->number) + data[e]=Sgml.Tag("anchor",(["name":tmp]),t->pos,({data[e]})); + }else{ + switch(t->tag) + { + case "index": + case "preface": + case "introduction": + case "table-of-contents": + data[e]=Sgml.Tag("anchor", + ([ + "name":t->namet || t->tag + ]),t->pos,({data[e]})); + } + } + + if(t->data) + de_abstract_anchors(t->data); + } + } +} + + +void low_collect_links(SGML data, string file) +{ + foreach(data,TAG t) + { + if(objectp(t)) + { + if(Wmml.islink(t->tag)) + { + if(t->params->name) + link_to_page[t->params->name]=file; + if(t->params->number) + link_to_page[t->params->number]=file; + } + switch(t->tag) + { + case "index": + case "introduction": + case "preface": + case "table-of-contents": + link_to_page[t->params->name || t->tag]=file; + } + + if(t->data) + low_collect_links(t->data,file); + } + } +} + +string nextify(string num) +{ + if(!num) return "aslkdjf;alskdjfl;asdjfbasm,dbfa,msdfhkl"; + + string *tmp=num/"."; + if((int)tmp[-1]) + { + tmp[-1]=(string)(1+(int)tmp[-1]); + }else{ + tmp[-1]=sprintf("%c",tmp[-1][0]+1); + } + return tmp*"."; +} + +string prevify(string num) +{ + if(!num) return "aslkdjf;alskdjfl;asdjfbasm,dbfa,msdfhkl"; + string *tmp=num/"."; + if((int)tmp[-1]) + { + tmp[-1]=(string)(((int)tmp[-1])-1); + }else{ + tmp[-1]=sprintf("%c",tmp[-1][0]-1); + } + return tmp*"."; +} + +void output(string base, SGML data, SGML toc, INDEX_DATA index_data) +{ + basename=base; + + werror("Splitting "); + sections=([]); + sections[""]=low_split(data); + + werror("Finding links "); + foreach(indices(sections), string file) + low_collect_links(sections[file], file); + + werror("linking "); + foreach(indices(sections), string file) + { + SGML data=sections[file]; + SGML links=({}); + string tmp1; + if(sizeof(data)>0 && objectp(data[0])) + { + switch(data[0]->tag) + { + string name; + string to; + + case "preface": + case "index": + case "chapter": + case "appendix": + case "section": + case "introduction": + tmp1=data[0]->params->number; + + + if(sections[to=prevify(tmp1)]) + { + name="Previous "+data[0]->tag; + } + + if(name && sections[to]) + { + links+=({ Sgml.Tag("a",(["href":mkfilename(to)]),0, + ({ + Sgml.Tag("img",(["src":"left.gif", + "border":"0"])), + name, + })), + "\n", + }); + } + name=0; + + links+=({ Sgml.Tag("a",(["href":mkfilename("")]),0, + ({ + Sgml.Tag("img",(["src":"up.gif", + "border":"0"])), + "To contents", + })), + "\n", + }); + name=0; + + + + if(sections[to=nextify(tmp1)]) + { + name="Next "+data[0]->tag; + }else{ + switch(data[0]->tag) + { + case "chapter": name="To appendices"; to="A"; break; + case "appendix": name="To index"; to="index"; break; + case "introduction": + case "preface": + name="To chapter one"; to="1"; + break; + } + } + + if(name && sections[to]) + { + links+=({ Sgml.Tag("a",(["href":mkfilename(to)]),0, + ({ + Sgml.Tag("img",(["src":"right.gif", + "border":"0"])), + name, + })), + "\n", + }); + } + name=0; + + links+=({ + Sgml.Tag("br"), + "\n", + }); + + + sections[file]=links+ + ({Sgml.Tag("hr")})+ + data+ + ({Sgml.Tag("hr")})+ + links; + } + } + } + + + werror("Converting TOC to WMML\n"); + html_toc=toc_to_wmml(toc); + + werror("Converting index to WMML\n"); + INDEX index=Wmml.group_index(index_data); + index=Wmml.group_index_by_character(index); + html_index=index_to_wmml(index); + index=0; + + foreach(indices(sections),string file) + { + string filename=mkfilename(file); + werror("Anchoring "); + de_abstract_anchors(sections[file]); + werror(filename+": WMML->HTML"); + data=wmml_to_html(sections[file]); + werror("->String"); + string data=Sgml.generate(data); + werror("->disk"); + out::open(filename,"wct"); + out::write(data); + out::close(); + werror(" done\n"); + } +} diff --git a/tutorial/html_onepage.pike b/tutorial/html_onepage.pike new file mode 100644 index 0000000000..1041d80426 --- /dev/null +++ b/tutorial/html_onepage.pike @@ -0,0 +1,4 @@ +#include "types.h" +inherit "html"; + +SGML low_split(SGML data) { return data; } diff --git a/tutorial/types.h b/tutorial/types.h new file mode 100644 index 0000000000..3139be3547 --- /dev/null +++ b/tutorial/types.h @@ -0,0 +1,4 @@ +#define TAG string|object(Sgml.Tag) +#define SGML array(TAG) +#define INDEX_DATA mapping(string:array(string)) +#define INDEX mapping(string:mapping|array(string)) diff --git a/tutorial/wmmltohtml2 b/tutorial/wmmltohtml2 new file mode 100755 index 0000000000..a14f3f641d --- /dev/null +++ b/tutorial/wmmltohtml2 @@ -0,0 +1,29 @@ +#!/usr/local/bin/pike + +import Stdio; + +#include "types.h" + +int main(int argc, string *argv) +{ + program output=(program)argv[1]; + werror("Reading "); + mixed data=stdin->read(0x7fffffff); + werror("Lexing "); + data=Sgml.lex(data); + werror("Grouping "); + data=Sgml.group(data); + werror("Including "); + data=Wmml.handle_include(data); + werror("Verifying\n"); + Wmml.verify(data); + werror("Collecting TOC "); + SGML toc=Wmml.collect_toc(data); + werror("index "); + INDEX_DATA index=Wmml.collect_index(data); + // write(sprintf("%O\n",Wmml.group_index(Wmml.collect_index(data)))); + werror("\nWriting output\n"); + output()->output(argv[2],data,toc,index); + write("Ok\n"); + exit(0); +} -- GitLab