戻る 目次へ
§5.1.16 refer.cc
戻る 目次へ

  1: /******************************************************************************
  2:   ezht - Copyright (C) 2004 Tradcrafts
  3:   This file is part of the ezht.
  4:                                                                        
  5:   ezht is free software; you can redistribute it and/or modify
  6:   it under the terms of the GNU General Public License as published by the 
  7:   Free Software Foundation;   either version 2 of the License,  or (at your 
  8:   option) any later version.
  9: 
 10:   ezht is distributed in the hope that it will be useful, but 
 11:   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 12:   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 13:   more details.
 14: 
 15:   You should have received a copy of the GNU General Public License along with
 16:   this program; see the file COPYING.  If not, write to the Free Software 
 17:   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 18: ******************************************************************************/
 19: 
 20: #include "error.h"
 21: #include "refer.h"
 22: 
 23: #include <map>
 24: 
 25: static std::map<std::string,std::string> references;
 26: 
 27: static void regist_reference_href(std::string name,std::string href)
 28: {
 29:   std::map<std::string,std::string>::iterator p = references.find(name);
 30:   if( p != references.end() ){
 31:     error("@refer: duplicate identifier `%s'",name.c_str()); 
 32:     return;
 33:   }
 34:   
 35:   references[name] = href;
 36: }
 37: 
 38: void cmd_mark(std::vector<std::string> &args, VFile *out,std::string fname, std::string aname)
 39: {
 40:   if( ! out ){
 41:     error("misplaced @mark");
 42:     return;
 43:   }
 44:   if( args.size() > 3 ){
 45:     error("@mark: too many arguments");
 46:     return;
 47:   }
 48:   if( args.size() == 1 ){
 49:     error("@mark: identifier required");
 50:     return;
 51:   }
 52: 
 53:   std::string ident = args[1];
 54: 
 55:   if( args.size() == 2 ){
 56:     regist_reference_href(ident,fname+'#'+aname);
 57:   }else{ // args.size() == 3
 58:     if( args[2] != "here" ){
 59:       error("@mark: unknown option `%s'",args[2].c_str());
 60:       return;
 61:     }
 62:     static int id=0;
 63:     char mk[16];
 64:     sprintf(mk,"mark%d",id++);
 65:     char tmp[64];
 66:     sprintf(tmp,"<a name=\"%s\"></a>",mk);
 67:     out->puts(tmp);
 68:     regist_reference_href(ident,fname+'#'+mk);
 69:   }
 70: }
 71: 
 72: #define REFHEAD "\xff\xffrfhd-"
 73: 
 74: void cmd_refer(std::vector<std::string> &args, std::string &ret)
 75: {
 76:   if( args.size() < 3 ){
 77:     error("@refer: too few arguments");
 78:     return;
 79:   }
 80:   if( args.size() > 4 ){
 81:     error("@refer: too many arguments");
 82:     return;
 83:   }
 84: 
 85:   std::string ident = args[1];
 86:   std::string anchor= args[2];
 87:   std::string attrs;
 88:   if( args.size()==4 )
 89:     attrs = args[3];
 90:   
 91:   char len_s[8]; sprintf(len_s,"%d:",ident.length());
 92:   ret = (std::string)"<a href=\"" + REFHEAD + len_s + ident + "\" " + attrs + '>' + anchor + "</a>";
 93:   
 94: }
 95: 
 96: 
 97: static bool find_reference_callback(VFile *vf, const char *line, std::string &modified_line_r, std::string*)
 98: {
 99:   modified_line_r = "";
100: 
101:   bool found=  false;
102:   const char *s;
103:   while( NULL != (s=strstr(line,REFHEAD)) ){
104:     found = true;
105:     int len = s - line;
106:     char *tmp = new char[len+1];
107:     memcpy(tmp,line,len);
108:     tmp[len] = '\0';
109:     modified_line_r += tmp;
110:     delete tmp;
111:     
112:     s += strlen(REFHEAD);
113:     int ident_len = atoi(s);
114:     while( isdigit(*s) ){
115:       s++;
116:     }
117:     s++;
118:     tmp = new char[ident_len+1];
119:     memcpy(tmp,s,ident_len);
120:     tmp[ident_len] = '\0';
121: 
122:     std::map<std::string,std::string>::iterator result = references.find(tmp);
123:     if( result == references.end() ){
124:       fprintf(stderr,"could not find the identifier `%s'\n",tmp);
125:       exit(-1);
126:     }
127:     delete tmp;
128:     
129:     modified_line_r += result->second;
130:     line = s + ident_len;
131:   }
132:   
133:   if( found ){
134:     modified_line_r += line;
135:     vf->chomp(); // 直前の行の改行を落とす
136:   }
137: 
138:   return found;
139: }
140: 
141: void fixate_references()
142: {
143:   vf_each(find_reference_callback);
144: }
145: 




Copyright 2004 Tradcrafts. ALL RIGHTS RESERVED.