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: