Skip to content
Snippets Groups Projects
wmml_to_html 8.83 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/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;
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    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)
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
        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)
    {
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
      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+">";
    
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    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)
        {
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
          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{
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    	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";
    }
    
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    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=([]);
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    
    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)));
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
        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]);
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
      }
    
      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);
    }
    
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
      string data=Stdio.stdin.read(0x7fffffff);
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
      /* 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 */
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
      data=parse_html(data, ([]) , TAGS);
    
      /* Build index */
    
      string index="<dl>\n";
      foreach(sort(indices(links)), int letter)
      {
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
        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,
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    		     "image":image,
    
    		   ([
    		     "box":box,
    		     "encaps":encaps,
    
    Fredrik Hübinette (Hubbe)'s avatar
    Fredrik Hübinette (Hubbe) committed
    		     "illustration":illustration,