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 "reader.h"
21: #include "stack.h"
22: #include "error.h"
23:
24: #include <string.h>
25: #include <deque>
26: #include <map>
27: #include <string>
28:
29:
30: typedef std::map< std::string , std::deque<std::string> > stack_t;
31: static stack_t stacks;
32:
33: typedef std::map< std::string , void (*)(const char*) > checkstack_t;
34: static checkstack_t stack_checkers;
35:
36: static void charset_checker(const char *charset)
37: {
38: if( strcasecmp(charset,"EUC-JP")==0 ||
39: strcasecmp(charset,"Shift_JIS")==0 ){
40: return;
41: }
42:
43: error("stack `charset' doesn't allowed the value `%s'",charset);
44: }
45:
46: static void filename_rule_checker(const char *rule)
47: {
48: if( strcmp(rule,"line")==0 ||
49: strcmp(rule,"serial")==0 ||
50: strcmp(rule,"section")==0
51: ){
52: return;
53: }
54:
55: error("stack `rule' doesn't allowed the value `%s'",rule);
56: }
57:
58:
59: void stack_init()
60: {
61: stacks[STACKNAME_LANG];
62:
63: stacks[STACKNAME_CHARSET];
64: stack_checkers[STACKNAME_CHARSET] = charset_checker;
65:
66: stacks[STACKNAME_DOCNAME];
67:
68: stacks[STACKNAME_HT_HEAD];
69:
70: stacks[STACKNAME_BODY_HEADER];
71:
72: stacks[STACKNAME_BODY_FOOTER];
73:
74: stacks[STACKNAME_BODY_ATTRIBUTES];
75:
76: stacks[STACKNAME_INDEXFILE_INTRODUCTION];
77:
78: stacks[STACKNAME_SECTION_BAR_COLOR];
79:
80: stacks[STACKNAME_SECTION_MARK];
81:
82: stacks[STACKNAME_NUMBER_SEPARATOR];
83:
84: stacks[STACKNAME_TEXT_INDEX];
85:
86: stacks[STACKNAME_TEXT_RELATION];
87:
88: stacks[STACKNAME_TEXT_SECTION_DISJOINED];
89:
90: stacks[STACKNAME_ANCHOR_INDEX];
91:
92: stacks[STACKNAME_ANCHOR_UP];
93:
94: stacks[STACKNAME_ANCHOR_PREV];
95:
96: stacks[STACKNAME_ANCHOR_NEXT];
97:
98: stacks[STACKNAME_ANCHOR_BACK];
99:
100: stacks[STACKNAME_INDEXFILE];
101:
102: stacks[STACKNAME_FILENAME_PREFIX];
103:
104: stacks[STACKNAME_FILENAME_SUFFIX];
105:
106: stacks[STACKNAME_FILENAME_RULE];
107: stack_checkers[STACKNAME_FILENAME_RULE] = filename_rule_checker;
108:
109: stacks[STACKNAME_INCLUDE_FILTER];
110:
111: stacks[STACKNAME_INCLUDE_HEADER];
112:
113: stacks[STACKNAME_INCLUDE_FOOTER];
114:
115: stacks[STACKNAME_TAB_SPACES];
116:
117: }
118:
119: void stack_push(const char *stackname, const char *body)
120: {
121: stack_t::iterator p = stacks.find(stackname);
122: if( p == stacks.end() ){
123: error("stack `%s' doesn't exists",stackname);
124: return ; // Not found.
125: }
126:
127: p->second.push_front( body );
128: }
129:
130: void stack_pop(const char *stackname)
131: {
132: stack_t::iterator p = stacks.find(stackname);
133: if( p != stacks.end() ){
134: if( p->second.size() == 0 ){
135: error("stack `%s' is already empty",stackname); return;
136: }
137: p->second.pop_front();
138: }else{
139: error("stack `%s' doesn't exists",stackname); return;
140: }
141: }
142:
143: const char *stack_peep(const char *elementname,const char *default_body)
144: {
145: stack_t::iterator p = stacks.find(elementname);
146: if( p != stacks.end() ){
147: if( p->second.size() > 0 )
148: return p->second[0].c_str();
149: else
150: return default_body;
151: }else{
152: error("internal error! %s",elementname);
153: return NULL;
154: }
155: }
156:
157:
158: static void check_stack_value(const char *stackname,const char *value)
159: {
160: checkstack_t::iterator checker = stack_checkers.find(stackname);
161: if( checker != stack_checkers.end() )
162: (*checker->second)(value);
163: }
164:
165: void cmd_push(std::vector<std::string> &args)
166: {
167: if( args.size() > 3 ){
168: error("@push: too many parameters");
169: return;
170: }
171:
172: if( args.size()==1 ){
173: error("@push: element not specified");
174: return;
175: }
176:
177: if( args.size()==3 ){
178: check_stack_value(args[1].c_str(),args[2].c_str());
179: stack_push(args[1].c_str() ,args[2].c_str());
180: }else if( args.size() == 2 ){
181:
182: std::string body;
183: const char *line;
184: while( NULL != (line=getline(true)) ){
185: if( 0 == strcmp(line,"@end") )
186: break;
187: body += line;
188: }
189: if( line == NULL ){
190: error("@push: unexpected end of file"); return;
191: }
192: check_stack_value(args[1].c_str(),body.c_str());
193: stack_push(args[1].c_str() ,body.c_str());
194: }
195:
196: }
197:
198: void cmd_pop(std::vector<std::string> &args)
199: {
200: if( args.size() == 1 ){
201: error("@pop: no stack specified"); return;
202: }
203:
204: int end = args.size();
205: for(int i=1; i<end; i++)
206: stack_pop(args[i].c_str());
207: }
208:
209: void cmd_autopop(std::list<std::string> &autopop_list, std::vector<std::string> &args)
210: {
211: if( args.size() == 1 ){
212: warn("@autopop: no stack specified");
213: return;
214: }
215:
216: int n = (int)args.size();
217: for(int i=1; i<n; i++){
218: if( stacks.end() != stacks.find(args[i]) )
219: autopop_list.push_back(args[i]);
220: else
221: error("@autopop: unknown stack `%s'",args[i].c_str());
222: }
223: }