戻る 目次へ
§5.1.11 include.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 "reader.h"
 22: #include "stack.h"
 23: #include "vfile.h"
 24: #include <map>
 25: 
 26: #define SPSYMBOL "%file%"
 27: 
 28: static std::string filename_insert(const char *cmdline,const char *fname)
 29: {
 30:   const char *inspnt = strstr(cmdline,SPSYMBOL);
 31:   if( ! inspnt ){
 32:     error("@insert: incorrect include-filter `%s': symbol %s not found",cmdline,SPSYMBOL);
 33:     return "";
 34:   }
 35: 
 36:   char *tmp = new char[strlen(cmdline)+strlen(fname)]; // これで必要十分な文字列長となる
 37:   memcpy(tmp,cmdline,inspnt-cmdline);
 38:   tmp[inspnt-cmdline] = '\0';
 39:   strcat(tmp,fname);
 40:   strcat(tmp,inspnt+strlen(SPSYMBOL));
 41:   std::string ret = tmp;
 42:   delete tmp;
 43:   
 44:   return ret;
 45: }
 46: 
 47: void cmd_include(std::vector<std::string> &args)
 48: {
 49: 
 50:   if( args.size() == 1 ){
 51:     error("@include: no include file specified"); return;
 52:   }
 53: 
 54:   if( args.size() > 3 ){
 55:     error("@include: too many arguments"); return;
 56:   }
 57: 
 58:   int include_opt = 0;
 59:   
 60:   if( args.size() == 3 ) {
 61:     if( args[2] == "html" )
 62:       include_opt = READOPT_INCLUDE_HTML;
 63:     else if( args[2] == "numbered" )
 64:       include_opt = READOPT_INCLUDE_NUMBERED;
 65:     else if( args[2] == "text" )
 66:       include_opt = READOPT_INCLUDE_TEXT;
 67:     else{
 68:       error("@include: Unknown option `%s'",args[2].c_str()); return;
 69:     }
 70:   }
 71: 
 72:   std::string fname;
 73:   std::string filter = INCLUDE_FILTER;
 74:   std::string filter_cmd;
 75:   bool use_filter=false;
 76: 
 77:   
 78:   fname = args[1];
 79:   
 80:   if( filter != "" ){
 81:     // フィルタが設定されている場合
 82:     filter_cmd = filename_insert(filter.c_str(),fname.c_str());
 83:     use_filter = true;
 84:   }
 85: 
 86:   if( ! reader.open(fname.c_str(),include_opt,(use_filter?filter_cmd.c_str():NULL)) ){
 87:     error("@include: Unable to open `%s' ",fname.c_str());
 88:   }
 89:   
 90:   reader.set_current_header( INCLUDE_HEADER );
 91:   reader.set_current_footer( INCLUDE_FOOTER );
 92:   reader.set_textmode();
 93: }
 94: 
 95: 
 96: static std::map< std::string , std::map<int,std::string*> > line_indexes;
 97: static std::map< std::string , std::string > fname_table;
 98: 
 99: static bool _make_line_indexes_callback(VFile *vf, const char *line, std::string &modified_line_r, std::string *ref)
100: {
101:   static bool now_indexing = false;
102:   static std::map<int,std::string*> *curmap = NULL;
103:   static int curline = 0;
104: 
105:   if( now_indexing ){
106:     if( 0 == strcmp(line,READER_INCLUDE_END) ){
107:       now_indexing = false;
108:       modified_line_r = "";
109:       return true;
110:     }else{
111:       (*curmap)[curline++] = ref;
112:       return false;
113:     }
114:   }
115:   
116:   // ELSE
117: 
118:   
119:   if( line == strstr(line,READER_INCLUDE_BEGIN) ){
120:     const char *fname = line + strlen(READER_INCLUDE_BEGIN);
121:     //fprintf(stdout,"INC=[%s]\n",fname);
122:     curmap = &line_indexes[fname];
123:     curmap->clear();
124:     curline = 1;
125:     now_indexing = true;
126:     
127:     fname_table[fname] = vf->get_filename();
128: 
129:     modified_line_r = "";
130:     return true;
131:   }else
132:     return false;
133:   
134: }
135: 
136: static void make_line_indexes()
137: {
138:   vf_each(_make_line_indexes_callback);
139: }
140: 
141: 
142: 
143: 
144: struct jumpstruct_t
145: {
146:   int linenum;
147:   std::string fname;
148:   std::string attrs;
149:   std::string anchor;
150: };
151: 
152: #define JUMPMARK "\xff\xff@JMP\xff\xff"
153: 
154: void cmd_jump(std::vector<std::string> &args, std::string &ret)
155: {
156:   if( args.size() < 4 ){
157:     error("@jump: too few argument(s)");
158:     return;
159:   }else if( args.size() > 5 ){
160:     error("@jump: too many arguments");
161:     return;
162:   }
163: 
164:   std::string fname = args[1];
165:   int  linenum = atoi(args[2].c_str());
166:   std::string anchor = args[3];
167: 
168:   std::string attrs;
169:   if( args.size() == 5 )
170:     attrs = args[4];
171: 
172:   jumpstruct_t *struc = new jumpstruct_t;
173:   struc->fname = fname;
174:   struc->linenum = linenum;
175:   struc->attrs = attrs;
176:   struc->anchor = anchor;
177: 
178:   char tmp[64];
179:   sprintf(tmp,"%s%p:",JUMPMARK,struc);
180:   ret = tmp;
181:   
182: }
183: 
184: 
185: static bool _fixate_jump_callback(VFile *vf, const char *line, std::string &modified_line_r, std::string*)
186: {
187:   bool found = false;
188:   const char *s = line;
189:   const char *sub;
190: 
191:   while( NULL != (sub=strstr(s,JUMPMARK)) ){
192:     found = true;
193:     s = sub + strlen(JUMPMARK);
194: 
195:     jumpstruct_t *struc;
196:     sscanf(s,"%p",&struc);
197: 
198:     while( *s != ':' ) // skip
199:       s++;
200:     s++;
201: 
202:     std::map< std::string , std::map<int,std::string*> >::iterator p;
203:     p = line_indexes.find(struc->fname);
204:     if( p == line_indexes.end() ){
205:       error("@jump: unknown file `%s'",struc->fname.c_str());
206:       return false;
207:     }
208:     
209:     std::map<int,std::string*>::iterator result = p->second.find(struc->linenum);
210:     if( result == p->second.end() ){
211:       error("@jump: `%s' illegal line number [%d]: out of range",struc->fname.c_str(),struc->linenum);
212:       return false;
213:     }
214:     
215:     std::string *line_linked = result->second; 
216:     
217:     static int id=0;
218:     char aname[16];
219:     sprintf(aname,"jmp%d",id++);
220:     // 先頭にタブを付けることに注意。また,元々の行の行頭からはタブを取り除いて結合
221:     *line_linked = (std::string)"\t<a name=\"" + aname + "\"></a>" + (line_linked->c_str()+1);
222:     
223:     modified_line_r += "<a href=\"" + fname_table[struc->fname] + '#' + aname + "\" " + struc->attrs + '>' + struc->anchor + "</a>";
224:   }
225: 
226:   if( found ){
227:     modified_line_r += s; // 残りをくっつける
228:     vf->chomp();
229:     return true;
230:   }else
231:     return false;
232: }
233: 
234: void fixate_jumps()
235: {
236:   make_line_indexes();
237:   vf_each(_fixate_jump_callback);
238: }




Copyright 2004 Tradcrafts. ALL RIGHTS RESERVED.