Develop and Download Open Source Software

Browse Subversion Repository

Contents of /base/trunk/src/src/jp/kirikiri/tvp2/utils/KAGParserNI.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 189 - (show annotations) (download) (as text)
Wed Aug 15 12:48:25 2012 UTC (11 years, 8 months ago) by jin1016
File MIME type: text/x-java
File size: 65213 byte(s)
マクロやタグ名で全角大文字が全角小文字に変換されないように対応。
1 /**
2 ******************************************************************************
3 * Copyright (c), Takenori Imoto
4 * 楓 software http://www.kaede-software.com/
5 * All rights reserved.
6 ******************************************************************************
7 * ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満
8 * たす場合に限り、再頒布および使用が許可されます。
9 *
10 * ・ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責
11 * 条項を含めること。
12 * ・バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の
13 * 著作権表示、本条件一覧、および下記免責条項を含めること。
14 * ・書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売
15 * 促進に、組織の名前またはコントリビューターの名前を使用してはならない。
16 *
17 * 本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供
18 * されており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適
19 * 合性に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありませ
20 * ん。著作権者もコントリビューターも、事由のいかんを問わず、損害発生の原因いか
21 * んを問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法
22 * 行為であるかを問わず、仮にそのような損害が発生する可能性を知らされていたとし
23 * ても、本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、
24 * 使用の喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されな
25 * い)直接損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害に
26 * ついて、一切責任を負わないものとします。
27 ******************************************************************************
28 * 本ソフトウェアは、吉里吉里2 ( http://kikyou.info/tvp/ ) のソースコードをJava
29 * に書き換えたものを一部使用しています。
30 * 吉里吉里2 Copyright (C) W.Dee <dee@kikyou.info> and contributors
31 ******************************************************************************
32 */
33 package jp.kirikiri.tvp2.utils;
34
35 import java.lang.ref.WeakReference;
36 import java.util.ArrayList;
37 import java.util.HashMap;
38
39 import jp.kirikiri.tjs2.Error;
40 import jp.kirikiri.tjs2.Interface;
41 import jp.kirikiri.tjs2.CompileException;
42 import jp.kirikiri.tjs2.Dispatch2;
43 import jp.kirikiri.tjs2.Holder;
44 import jp.kirikiri.tjs2.IntVector;
45 import jp.kirikiri.tjs2.IntWrapper;
46 import jp.kirikiri.tjs2.NativeInstanceObject;
47 import jp.kirikiri.tjs2.TJS;
48 import jp.kirikiri.tjs2.TJSException;
49 import jp.kirikiri.tjs2.Variant;
50 import jp.kirikiri.tjs2.VariantClosure;
51 import jp.kirikiri.tjs2.VariantException;
52 import jp.kirikiri.tvp2.TVP;
53 import jp.kirikiri.tvp2.base.ScriptsClass;
54 import jp.kirikiri.tvp2.base.Storage;
55 import jp.kirikiri.tvp2.msg.Message;
56
57 public class KAGParserNI extends NativeInstanceObject {
58 /** none is reported */
59 //private static final int tkdlNone = 0;
60 /** simple report */
61 private static final int tkdlSimple = 1;
62 /** complete report ( verbose ) */
63 private static final int tkdlVerbose = 2;
64
65 /** owner object */
66 private WeakReference<Dispatch2> mOwner;
67
68 /** Dictionary.Clear method pointer */
69 private Dispatch2 mDicClear;
70 /** Dictionary */
71 private Dispatch2 mDicAssign;
72 /** DictionaryObject */
73 private Dispatch2 mDicObj;
74
75 /** Macro Dictionary Object */
76 private Dispatch2 mMacros;
77
78 /** Macro arguments */
79 private ArrayList<Dispatch2> mMacroArgs;
80 private int mMacroArgStackDepth;
81 private int mMacroArgStackBase;
82
83 static class CallStackData {
84 /** caller storage */
85 public String Storage;
86 /** caller nearest label */
87 public String Label;
88 /** line offset from the label */
89 public int Offset;
90 /** original line string */
91 public String OrgLineStr;
92 /** line string (if alive) */
93 public String LineBuffer;
94 public int Pos;
95 /** whether LineBuffer is used or not */
96 public boolean LineBufferUsing;
97 public int MacroArgStackBase;
98 public int MacroArgStackDepth;
99 public IntVector ExcludeLevelStack;
100 public ArrayList<Boolean> IfLevelExecutedStack;
101 public int ExcludeLevel;
102 public int IfLevel;
103
104 public CallStackData( final String storage, final String label,
105 int offset, final String orglinestr, final String linebuffer,
106 int pos, boolean linebufferusing, int macroargstackbase,
107 int macroargstackdepth,
108 final IntVector excludelevelstack, int excludelevel,
109 final ArrayList<Boolean> iflevelexecutedstack, int iflevel) {
110
111 Storage = storage;
112 Label = label;
113 Offset = offset;
114 OrgLineStr = orglinestr;
115 LineBuffer = linebuffer;
116 Pos = pos;
117 LineBufferUsing = linebufferusing;
118 MacroArgStackBase = macroargstackbase;
119 MacroArgStackDepth = macroargstackdepth;
120 ExcludeLevelStack = excludelevelstack;
121 ExcludeLevel = excludelevel;
122 IfLevelExecutedStack = iflevelexecutedstack;
123 IfLevel = iflevel;
124 }
125 @SuppressWarnings("unchecked")
126 public CallStackData( final CallStackData ref ) {
127 Storage = ref.Storage;
128 Label = ref.Label;
129 Offset = ref.Offset;
130 OrgLineStr = ref.OrgLineStr;
131 LineBuffer = ref.LineBuffer;
132 Pos = ref.Pos;
133 LineBufferUsing = ref.LineBufferUsing;
134 MacroArgStackBase = ref.MacroArgStackBase;
135 MacroArgStackDepth = ref.MacroArgStackDepth;
136 ExcludeLevelStack = ref.ExcludeLevelStack.clone();
137 IfLevelExecutedStack = (ArrayList<Boolean>) ref.IfLevelExecutedStack.clone();
138 ExcludeLevel = ref.ExcludeLevel;
139 IfLevel = ref.IfLevel;
140 }
141 @SuppressWarnings("unchecked")
142 public void copy( CallStackData ref ) {
143 Storage = ref.Storage;
144 Label = ref.Label;
145 Offset = ref.Offset;
146 OrgLineStr = ref.OrgLineStr;
147 LineBuffer = ref.LineBuffer;
148 Pos = ref.Pos;
149 LineBufferUsing = ref.LineBufferUsing;
150 MacroArgStackBase = ref.MacroArgStackBase;
151 MacroArgStackDepth = ref.MacroArgStackDepth;
152 ExcludeLevelStack = ref.ExcludeLevelStack.clone();
153 IfLevelExecutedStack = (ArrayList<Boolean>) ref.IfLevelExecutedStack.clone();
154 ExcludeLevel = ref.ExcludeLevel;
155 IfLevel = ref.IfLevel;
156 }
157 }
158 private ArrayList<CallStackData> mCallStack;
159
160 private ScenarioCacheItem mScenario;
161 /** is copied from Scenario */
162 private String[] mLines;
163 /** is copied from Scenario */
164 private int mLineCount;
165
166 private String mStorageName;
167 private String mStorageShortName;
168
169 /** current processing line */
170 private int mCurLine;
171 /** current processing position ( column ) */
172 private int mCurPos;
173 /** current line string */
174 private String mCurLineStr;
175 /** line buffer ( if any macro/emb was expanded ) */
176 private String mLineBuffer;
177 /** */
178 private boolean mLineBufferUsing;
179 /** Current Label */
180 private String mCurLabel;
181 /** Current Page Name */
182 private String mCurPage;
183 /** line number of previous tag */
184 private int mTagLine;
185
186 /** debugging log level */
187 private int mDebugLevel;
188 /** whether to process special tags */
189 private boolean mProcessSpecialTags;
190 /** CR is not interpreted as [r] tag when this is true */
191 private boolean mIgnoreCR;
192 /** マクロ記録状態 */
193 private boolean mRecordingMacro;
194 /** 記録しているマクロの内容 */
195 private StringBuilder mRecordingMacroStr;
196 /** 記録しているマクロ名 */
197 private String mRecordingMacroName;
198 /** テンポラリ文字構築 */
199 private StringBuilder mWorkBuilder;
200
201 private Variant mValueVariant;
202
203 private int mExcludeLevel;
204 private int mIfLevel;
205
206 private IntVector mExcludeLevelStack;
207 private ArrayList<Boolean> mIfLevelExecutedStack;
208
209 private boolean mInterrupted;
210
211 private char[] mWorkChar;
212
213 public KAGParserNI() throws VariantException, TJSException {
214 // 初期値を代入しているものはコメントアウト
215 // mOwner = null;
216 // mScenario = null;
217 // mLines = null;
218 // mCurLineStr = null;
219 mProcessSpecialTags = true;
220 // mIgnoreCR = false;
221 // mDicClear = null;
222 // mDicAssign = null;
223 // mDicObj = null;
224 // mMacros = null;
225 // mRecordingMacro = false;
226 mDebugLevel = tkdlSimple;
227 // mInterrupted = false;
228 // mMacroArgStackDepth = 0;
229 // mMacroArgStackBase = 0;
230
231 mRecordingMacroStr = new StringBuilder();
232 mWorkBuilder = new StringBuilder();
233 mIfLevelExecutedStack = new ArrayList<Boolean>();
234 mExcludeLevelStack = new IntVector();
235 mCallStack = new ArrayList<CallStackData>();
236 mMacroArgs = new ArrayList<Dispatch2>();
237 mValueVariant = new Variant();
238
239 // retrieve DictClear method and DictObj object
240 Holder<Dispatch2> holder = new Holder<Dispatch2>(null);
241 mDicObj = TJS.createDictionaryObject(holder);
242 mMacros = TJS.createDictionaryObject();
243 Dispatch2 dictclass = holder.mValue;
244 holder.mValue = null;
245 try {
246 // retrieve clear method from dictclass
247 Variant val = new Variant();
248 int er = dictclass.propGet( 0, "clear", val, dictclass );
249 if( er < 0 ) Message.throwExceptionMessage(Message.InternalError );
250 mDicClear = val.asObject();
251
252 er = dictclass.propGet( 0, "assign", val, dictclass );
253 if( er < 0 ) Message.throwExceptionMessage(Message.InternalError );
254 mDicAssign = val.asObject();
255 } catch( TJSException e ) {
256 dictclass = null;
257 mDicObj = null;
258 mMacros = null;
259 mDicClear = null;
260 mDicAssign = null;
261 throw e;
262 }
263 dictclass = null;
264 }
265 public int construct( Variant[] param, Dispatch2 tjsObj ) throws VariantException, TJSException {
266 int hr = super.construct( param, tjsObj );
267 if( hr < 0 ) return hr;
268
269 mOwner = new WeakReference<Dispatch2>(tjsObj);
270 return Error.S_OK;
271 }
272 // called before destruction
273 public void invalidate() throws VariantException, TJSException {
274 // invalidate this object
275
276 // release objects
277 mDicAssign = null;
278 mDicClear = null;
279 mDicObj = null;
280 mMacros = null;
281
282 clearMacroArgs();
283 clearBuffer();
284 mOwner.clear();
285 super.invalidate();
286 }
287 @SuppressWarnings("unchecked")
288 public void copy( final KAGParserNI ref ) throws VariantException, TJSException {
289 // copy Macros
290 Variant[] psrc = new Variant[1];
291 {
292 Variant src = new Variant(ref.mMacros, ref.mMacros);
293 psrc[0] = src;
294 mDicAssign.funcCall( 0, null, null, psrc, mMacros );
295 }
296
297 // copy MacroArgs
298 {
299 clearMacroArgs();
300
301 for( int i = 0; i < ref.mMacroArgStackDepth; i++ ) {
302 Dispatch2 dic = TJS.createDictionaryObject();
303 Dispatch2 isrc = ref.mMacroArgs.get(i);
304 Variant src = new Variant(isrc, isrc);
305 psrc[0] = src;
306 mDicAssign.funcCall( 0, null, null, psrc, dic );
307 mMacroArgs.add(dic);
308 }
309 mMacroArgStackDepth = ref.mMacroArgStackDepth;
310 }
311 mMacroArgStackBase = ref.mMacroArgStackBase;
312
313 // copy CallStack
314 int count = ref.mCallStack.size();
315 mCallStack = new ArrayList<CallStackData>(count);
316 for( int i = 0; i < count; i++ ) {
317 mCallStack.add( new CallStackData(ref.mCallStack.get(i)) );
318 }
319
320 // copy StorageName, StorageShortName
321 mStorageName = ref.mStorageName;
322 mStorageShortName = ref.mStorageShortName;
323
324
325 // copy Scenario
326 if( mScenario != ref.mScenario ) {
327 if( mScenario != null ) {
328 mScenario = null;
329 mLines = null;
330 mCurLineStr = null;
331 }
332 mScenario = ref.mScenario;
333 mLines = ref.mLines;
334 mLineCount = ref.mLineCount;
335 }
336
337 // copy CurStorage, CurLine, CurPos
338 mCurLine = ref.mCurLine;
339 mCurPos = ref.mCurPos;
340
341 // copy CurLineStr, LineBuffer, LineBufferUsing
342 mCurLineStr = ref.mCurLineStr;
343 mLineBuffer = ref.mLineBuffer;
344 mLineBufferUsing = ref.mLineBufferUsing;
345
346 // copy CurLabel, CurPage, TagLine
347 mCurLabel = ref.mCurLabel;
348 mCurPage = ref.mCurPage;
349 mTagLine = ref.mTagLine;
350
351 // copy DebugLebel, IgnoreCR
352 mDebugLevel = ref.mDebugLevel;
353 mIgnoreCR = ref.mIgnoreCR;
354
355 // copy RecordingMacro, RecordingMacroStr, RecordingMacroName
356 mRecordingMacro = ref.mRecordingMacro;
357 mRecordingMacroStr.delete(0, mRecordingMacroStr.length() );
358 mRecordingMacroStr.append( ref.mRecordingMacroStr.toString() );
359 mRecordingMacroName = ref.mRecordingMacroName;
360
361 // copy ExcludeLevel, IfLevel
362 mExcludeLevel = ref.mExcludeLevel;
363 mIfLevel = ref.mIfLevel;
364 mExcludeLevelStack = ref.mExcludeLevelStack.clone();
365 mIfLevelExecutedStack = (ArrayList<Boolean>) ref.mIfLevelExecutedStack.clone();
366 }
367
368 public Dispatch2 store() throws TJSException {
369 // store current status into newly created dictionary object
370 // and return the dictionary object.
371 Dispatch2 dic = TJS.createDictionaryObject();
372 try {
373 Variant val = new Variant();
374
375 Variant[] psrc = new Variant[1];
376 // create and assign macro dictionary
377 {
378 Dispatch2 dsp;
379
380 dsp = TJS.createDictionaryObject();
381 Variant tmp = new Variant(dsp, dsp);
382 dic.propSet( Interface.MEMBERENSURE, "macros", tmp, dic );
383
384 Variant src = new Variant(mMacros, mMacros);
385 psrc[0] = src;
386 mDicAssign.funcCall( 0, null, null, psrc, dsp );
387 }
388
389 // create and assign macro arguments
390 {
391 Dispatch2 dsp;
392 dsp = TJS.createArrayObject();
393 Variant tmp = new Variant(dsp, dsp);
394 dic.propSet( Interface.MEMBERENSURE, "macroArgs", tmp, dic );
395
396 for( int i = 0; i < mMacroArgStackDepth; i++ ) {
397 Dispatch2 dic1;
398 dic1 = TJS.createDictionaryObject();
399 tmp.set(dic1, dic1);
400 dsp.propSetByNum( Interface.MEMBERENSURE, i, tmp, dsp );
401
402 Dispatch2 isrc = mMacroArgs.get(i);
403 Variant src = new Variant(isrc, isrc);
404 psrc[0] = src;
405 mDicAssign.funcCall( 0, null, null, psrc, dic1 );
406 }
407 }
408
409
410 // create call stack array and copy call stack status
411 {
412 Dispatch2 dsp;
413 dsp = TJS.createArrayObject();
414 Variant tmp = new Variant(dsp, dsp);
415 dic.propSet( Interface.MEMBERENSURE, "callStack", tmp, dic);
416
417 final int size = mCallStack.size();
418 for( int i = 0; i < size; i++ ) {
419 CallStackData d = mCallStack.get(i);
420
421 Dispatch2 dic1;
422 dic1 = TJS.createDictionaryObject();
423 tmp.set(dic1, dic1);
424 dsp.propSetByNum( Interface.MEMBERENSURE, i, tmp, dsp );
425
426 val.set( d.Storage );
427 dic1.propSet( Interface.MEMBERENSURE, "storage", val, dic1 );
428
429 val.set( d.Label );
430 dic1.propSet( Interface.MEMBERENSURE, "label", val, dic1 );
431 val.set( d.Offset );
432 dic1.propSet( Interface.MEMBERENSURE, "offset", val, dic1);
433 val.set( d.OrgLineStr );
434 dic1.propSet (Interface.MEMBERENSURE, "orgLineStr", val, dic1);
435 val.set( d.LineBuffer );
436 dic1.propSet( Interface.MEMBERENSURE, "lineBuffer", val, dic1);
437 val.set( d.Pos );
438 dic1.propSet( Interface.MEMBERENSURE, "pos", val, dic1);
439 val.set( d.LineBufferUsing ? 1 : 0 );
440 dic1.propSet( Interface.MEMBERENSURE, "lineBufferUsing", val, dic1);
441 val.set( d.MacroArgStackBase );
442 dic1.propSet( Interface.MEMBERENSURE, "macroArgStackBase", val, dic1);
443 val.set( d.MacroArgStackDepth );
444 dic1.propSet( Interface.MEMBERENSURE, "macroArgStackDepth", val, dic1);
445 val.set( d.ExcludeLevel );
446 dic1.propSet( Interface.MEMBERENSURE, "ExcludeLevel", val, dic1);
447 val.set( d.IfLevel );
448 dic1.propSet( Interface.MEMBERENSURE, "IfLevel", val, dic1);
449
450 storeIntStackToDic( dic1, d.ExcludeLevelStack, "ExcludeLevelStack" );
451 storeBoolStackToDic( dic1, d.IfLevelExecutedStack, "IfLevelExecutedStack" );
452 }
453 }
454
455 // store StorageName, StorageShortName ( Buffer is not stored )
456 val.set( mStorageName );
457 dic.propSet( Interface.MEMBERENSURE, "storageName", val, dic);
458 val.set( mStorageShortName );
459 dic.propSet( Interface.MEMBERENSURE, "storageShortName", val, dic);
460
461 // ( Lines and LineCount are not stored )
462
463 // store CurStorage, CurLine, CurPos
464 val.set( mCurLine );
465 dic.propSet( Interface.MEMBERENSURE, "curLine", val, dic);
466 val.set( mCurPos );
467 dic.propSet( Interface.MEMBERENSURE, "curPos", val, dic);
468
469 // ( CurLineStr is not stored )
470
471 // LineBuffer, LineBufferUsing
472 val.set( mLineBuffer );
473 dic.propSet( Interface.MEMBERENSURE, "lineBuffer", val, dic);
474 val.set( mLineBufferUsing ? 1 : 0 );
475 dic.propSet( Interface.MEMBERENSURE, "lineBufferUsing", val, dic);
476
477 // store CurLabel ( CurPage TagLine is not stored )
478 val.set( mCurLabel );
479 dic.propSet( Interface.MEMBERENSURE, "curLabel", val, dic);
480
481 // ( DebugLebel and IgnoreCR are not stored )
482
483 // ( RecordingMacro, RecordingMacroStr, RecordingMacroName are not stored)
484
485
486 // ExcludeLevel, IfLevel, ExcludeLevelStack, IfLevelExecutedStack
487 val.set( mExcludeLevel );
488 dic.propSet( Interface.MEMBERENSURE, "ExcludeLevel", val, dic);
489 val.set( mIfLevel );
490 dic.propSet( Interface.MEMBERENSURE, "IfLevel", val, dic);
491 storeIntStackToDic(dic, mExcludeLevelStack, "ExcludeLevelStack");
492 storeBoolStackToDic(dic, mIfLevelExecutedStack, "IfLevelExecutedStack");
493
494 // store MacroArgStackBase, MacroArgStackDepth
495 val.set( mMacroArgStackBase );
496 dic.propSet( Interface.MEMBERENSURE, "macroArgStackBase", val, dic );
497
498 val.set( mMacroArgStackDepth );
499 dic.propSet( Interface.MEMBERENSURE, "macroArgStackDepth", val, dic );
500 } catch( TJSException e ) {
501 dic = null;
502 throw e;
503 }
504 return dic;
505 }
506
507 private final static String HEX = "0123456789abcdef";
508 private void storeIntStackToDic( Dispatch2 dic, IntVector stack, final String membername ) throws VariantException, TJSException {
509 StringBuilder p = mWorkBuilder;
510 p.delete(0, p.length() );
511 final int count = stack.size();
512 for( int i = 0; i < count; i++ ) {
513 int v = stack.get(i);
514 p.append( HEX.charAt((v >> 28) & 0x000f) );
515 p.append( HEX.charAt((v >> 24) & 0x000f) );
516 p.append( HEX.charAt((v >> 20) & 0x000f) );
517 p.append( HEX.charAt((v >> 16) & 0x000f) );
518 p.append( HEX.charAt((v >> 12) & 0x000f) );
519 p.append( HEX.charAt((v >> 8) & 0x000f) );
520 p.append( HEX.charAt((v >> 4) & 0x000f) );
521 p.append( HEX.charAt((v >> 0) & 0x000f) );
522 }
523 Variant val = new Variant( p.toString() );
524 p = null;
525 dic.propSet(Interface.MEMBERENSURE, membername, val, dic);
526 }
527 private void restoreIntStackFromStr( IntVector stack, final String str ) {
528 stack.clear();
529 final int len = str.length() / 8;
530 for( int i = 0; i < len; ++i ) {
531 stack.add(
532 (((str.charAt( 0 ) <= '9') ? (str.charAt( 0 ) - '0') : (str.charAt( 0 ) - 'a' + 10)) << 28) |
533 (((str.charAt( 1 ) <= '9') ? (str.charAt( 1 ) - '0') : (str.charAt( 1 ) - 'a' + 10)) << 24) |
534 (((str.charAt( 2 ) <= '9') ? (str.charAt( 2 ) - '0') : (str.charAt( 2 ) - 'a' + 10)) << 20) |
535 (((str.charAt( 3 ) <= '9') ? (str.charAt( 3 ) - '0') : (str.charAt( 3 ) - 'a' + 10)) << 16) |
536 (((str.charAt( 4 ) <= '9') ? (str.charAt( 4 ) - '0') : (str.charAt( 4 ) - 'a' + 10)) << 12) |
537 (((str.charAt( 5 ) <= '9') ? (str.charAt( 5 ) - '0') : (str.charAt( 5 ) - 'a' + 10)) << 8) |
538 (((str.charAt( 6 ) <= '9') ? (str.charAt( 6 ) - '0') : (str.charAt( 6 ) - 'a' + 10)) << 4) |
539 (((str.charAt( 7 ) <= '9') ? (str.charAt( 7 ) - '0') : (str.charAt( 7 ) - 'a' + 10)) << 0)
540 );
541 }
542 }
543 private void restoreBoolStackFromStr( ArrayList<Boolean> stack, final String str ) {
544 stack.clear();
545 int len = str.length();
546 for( int i = 0; i < len; ++i ) {
547 stack.add( str.charAt(i) == '1');
548 }
549 }
550
551 static final private String BIT = "01";
552 private void storeBoolStackToDic( Dispatch2 dic, ArrayList<Boolean> stack, final String membername ) throws VariantException, TJSException {
553 final int count = stack.size();
554 StringBuilder builder = mWorkBuilder;
555 builder.delete(0,builder.length());
556 for( int i = 0; i < count; i++ ) {
557 builder.append( BIT.charAt( stack.get(i).booleanValue() ? 1 : 0) );
558 }
559 Variant val = new Variant(builder.toString());
560 builder = null;
561 dic.propSet( Interface.MEMBERENSURE, membername, val, dic );
562 }
563 public void restore( Dispatch2 dic ) throws VariantException, TJSException {
564 // restore status from "dic"
565 Variant val = new Variant();
566 Variant v = new Variant();
567 Variant[] psrc = new Variant[1];
568
569 // restore macros
570 {
571 //val.clear();
572 dic.propGet(0, "macros", val, dic);
573 if( val.isVoid() != true ) {
574 psrc[0] = val;
575 mDicAssign.funcCall(0, null, null, psrc, mMacros );
576 }
577 }
578
579 {
580 // restore macro args
581 mMacroArgStackDepth = 0;
582
583 val.clear();
584 dic.propGet(0, "macroArgs", val, dic );
585 if( val.isVoid() != true ) {
586 VariantClosure clo = val.asObjectClosure();
587 int count = 0;
588 clo.propGet(0, "count", v, null );
589 count = v.asInteger();
590
591 clearMacroArgs();
592
593 val.clear();
594 dic.propGet(0, "macroArgStackDepth", val, dic );
595 if( val.isVoid() != true ) mMacroArgStackDepth = val.asInteger();
596
597 for( int i = 0; i < count; i++ ) {
598 Dispatch2 dsp = TJS.createDictionaryObject();
599 // Variant val1 = new Variant(dsp, dsp); TODO 使われていないようだけど……
600
601 clo.propGetByNum(0, i, v, null);
602 psrc[0] = v;
603 mDicAssign.funcCall(0, null, null, psrc, dsp );
604
605 mMacroArgs.add(dsp);
606 }
607 }
608
609 if(mMacroArgStackDepth != mMacroArgs.size())
610 Message.throwExceptionMessage(Message.KAGMalformedSaveData);
611
612 mMacroArgStackBase = mMacroArgs.size(); // later reset to MacroArgStackBase
613
614 // restore call stack
615 val.clear();
616 dic.propGet(0, "callStack", val, dic);
617 if( val.isVoid() != true ) {
618 VariantClosure clo = val.asObjectClosure();
619 int count = 0;
620 v.clear();
621 clo.propGet(0, "count", v, null );
622 count = v.asInteger();
623
624 mCallStack.clear();
625
626 for( int i = 0; i < count; i++ ) {
627 String Storage;
628 String Label;
629 int Offset;
630 String OrgLineStr;
631 String LineBuffer;
632 int Pos;
633 boolean LineBufferUsing;
634 int MacroArgStackBase;
635 int MacroArgStackDepth;
636 int ExcludeLevel;
637 int IfLevel;
638 IntVector ExcludeLevelStack = new IntVector();
639 ArrayList<Boolean> IfLevelExecutedStack = new ArrayList<Boolean>();
640
641 clo.propGetByNum(0, i, v, null);
642 VariantClosure dic1 = v.asObjectClosure();
643 dic1.propGet(0, "storage", val, null );
644 Storage = val.asString();
645 dic1.propGet(0, "label", val, null );
646 Label = val.asString();
647 dic1.propGet(0, "offset", val, null );
648 Offset = val.asInteger();
649 dic1.propGet(0, "orgLineStr", val, null );
650 OrgLineStr = val.asString();
651 dic1.propGet(0, "lineBuffer", val, null );
652 LineBuffer = val.asString();
653 dic1.propGet(0, "pos", val, null );
654 Pos = val.asInteger();
655 dic1.propGet(0, "lineBufferUsing", val, null );
656 LineBufferUsing = val.asBoolean();
657 dic1.propGet(0, "macroArgStackBase", val, null );
658 MacroArgStackBase = val.asInteger();
659 dic1.propGet(0, "macroArgStackDepth", val, null );
660 MacroArgStackDepth = val.asInteger();
661 dic1.propGet(0, "ExcludeLevel", val, null );
662 ExcludeLevel = val.asInteger();
663 dic1.propGet(0, "IfLevel", val, null );
664 IfLevel = val.asInteger();
665
666 String stack_str;
667 dic1.propGet(0, "ExcludeLevelStack", val, null );
668 stack_str = val.asString();
669 restoreIntStackFromStr( ExcludeLevelStack, stack_str );
670
671 dic1.propGet(0, "IfLevelExecutedStack", val, null );
672 stack_str = val.asString();
673 restoreBoolStackFromStr(IfLevelExecutedStack, stack_str);
674
675 mCallStack.add( new CallStackData(
676 Storage, Label, Offset, OrgLineStr, LineBuffer, Pos,
677 LineBufferUsing, MacroArgStackBase, MacroArgStackDepth,
678 ExcludeLevelStack, ExcludeLevel, IfLevelExecutedStack, IfLevel) );
679 }
680 }
681
682 // restore StorageName, StorageShortName, CurStorage, CurLabel
683 val.clear();
684 dic.propGet(0, "storageName", val, dic);
685 if(val.isVoid() != true ) mStorageName = val.asString();
686 val.clear();
687 dic.propGet(0, "storageShortName", val, dic);
688 if(val.isVoid() != true) mStorageShortName = val.asString();
689 val.clear();
690 dic.propGet(0, "curLabel", val, dic);
691 if(val.isVoid() != true ) mCurLabel = val.asString();
692
693 // load scenario
694 String storage = mStorageName;
695 String label = mCurLabel;
696 clearBuffer(); // ensure re-loading the scenario
697 loadScenario(storage);
698 goToLabel(label);
699
700 // ExcludeLevel, IfLevel
701 val.clear();
702 dic.propGet(0, "ExcludeLevel", val, dic);
703 if(val.isVoid() != true ) mExcludeLevel = val.asInteger();
704 val.clear();
705 dic.propGet(0, "IfLevel", val, dic);
706 if(val.isVoid() != true ) mIfLevel = val.asInteger();
707
708 // ExcludeLevelStack, IfLevelExecutedStack
709 val.clear();
710 dic.propGet(0, "ExcludeLevelStack", val, dic);
711 if( val.isVoid() != true ) {
712 String stack_str;
713 stack_str = val.asString();
714 restoreIntStackFromStr(mExcludeLevelStack, stack_str);
715 }
716
717 val.clear();
718 dic.propGet(0, "IfLevelExecutedStack", val, dic);
719 if( val.isVoid() != true ) {
720 String stack_str;
721 stack_str = val.asString();
722 restoreBoolStackFromStr(mIfLevelExecutedStack, stack_str);
723 }
724
725
726 // restore MacroArgStackBase
727 val.clear();
728 dic.propGet(0, "macroArgStackBase", val, dic);
729 if(val.isVoid() != true ) mMacroArgStackBase = val.asInteger();
730 }
731 }
732 public void loadScenario( final String name ) throws VariantException, TJSException {
733 // load scenario to buffer
734
735 breakConditionAndMacro();
736
737 if( mStorageName != null && mStorageName.equals(name) ) {
738 // avoid re-loading
739 rewind();
740 } else {
741 clearBuffer();
742
743 // fire onScenarioLoad
744 Variant param = new Variant(name);
745 Variant[] pparam = {param};
746 Variant result = new Variant();
747 Dispatch2 owner = mOwner.get();
748 int status = owner.funcCall(0, EV_ON_SCENARIO_LOAD, result, pparam, owner );
749
750 if( status == Error.S_OK && result.isString() ) {
751 // when onScenarioLoad returns string;
752 // assumes the string is scenario
753 mScenario = TVP.ScnearioCache.getScenario( result.getString(), true );
754 } else {
755 // else load from file
756 mScenario = TVP.ScnearioCache.getScenario(name, false);
757 }
758
759 mLines = mScenario.getLines();
760 mLineCount = mScenario.getLineCount();
761
762 rewind();
763
764 mStorageName = name;
765 mStorageShortName = Storage.extractStorageName(name);
766 if( mDebugLevel >= tkdlSimple ) {
767 DebugClass.addLog("================================================================================");
768 DebugClass.addLog( "Scenario loaded : " + name );
769 }
770 }
771
772 Dispatch2 owner = mOwner.get();
773 if( owner != null ) {
774 Variant param = new Variant(mStorageName);
775 Variant[] pparam = {param};
776 owner.funcCall(0, EV_ON_SCENARIO_LOADED, null, pparam, owner );
777 }
778 }
779 public void clear() {
780 // clear all states
781 TVP.ScnearioCache.clearScnearioCache(); // also invalidates the scenario cache
782 clearBuffer();
783 clearMacroArgs();
784 clearCallStack();
785 }
786 private void clearBuffer() {
787 // clear internal buffer
788 if( mScenario != null ) {
789 mScenario = null;
790 mLines = null;
791 mCurLineStr = null;
792 }
793 mStorageName = null;
794 mStorageShortName = null;
795 breakConditionAndMacro();
796 }
797 private void rewind() {
798 // set current position to first
799 mCurLine = 0;
800 mCurPos = 0;
801 mCurLineStr = mLines[0];
802 mLineBufferUsing = false;
803 breakConditionAndMacro();
804 }
805 private void breakConditionAndMacro() {
806 // break condition state and macro recording
807 mRecordingMacro = false;
808 mExcludeLevel = -1;
809 mExcludeLevelStack.clear();
810 mIfLevelExecutedStack.clear();
811 mIfLevel = 0;
812 popMacroArgsTo(mMacroArgStackBase);
813 // clear macro argument down to current base stack position
814 }
815 public void goToLabel( final String name ) throws TJSException {
816 // search label and set current position
817 // parameter "name" must start with '*'
818 if( name == null || name.length() == 0 ) return;
819
820 mScenario.ensureLabelCache();
821
822 ScenarioCacheItem.LabelCacheData newline;
823
824 newline = mScenario.getLabelCache().get(name);
825
826 if( newline != null ) {
827 // found the label in cache
828 int vl = mLines[newline.Line].indexOf('|');
829
830 mCurLabel = mScenario.getLabelAliasFromLine(newline.Line);
831 if(vl!=-1) mCurPage = mLines[newline.Line].substring(vl+1);
832 else mCurPage = null;
833 mCurLine = newline.Line;
834 mCurPos = 0;
835 mLineBufferUsing = false;
836 } else {
837 // not found
838 Message.throwExceptionMessage( Message.KAGLabelNotFound, mStorageName, name);
839 }
840
841 if( mDebugLevel >= tkdlSimple ) {
842 DebugClass.addLog("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
843 DebugClass.addLog( mStorageShortName + " : jumped to : " + name);
844 }
845
846 breakConditionAndMacro();
847 }
848 public void goToStorageAndLabel( final String storage, final String label) throws TJSException {
849 if(storage != null && storage.length() != 0) loadScenario(storage);
850 if(label != null && label.length() != 0) goToLabel(label);
851 }
852 public void callLabel( final String name ) throws TJSException {
853 pushCallStack();
854 goToLabel(name);
855 }
856 /**
857 * skip comment or label, and go to next line.
858 * fire OnScript event if [script] thru [endscript] ( or @script thru @endscript ) is found.
859 * @return
860 * @throws TJSException
861 */
862 private boolean skipCommentOrLabel() throws TJSException {
863 mScenario.ensureLabelCache();
864
865 mCurPos = 0;
866 if(mCurLine >= mLineCount) return false;
867 for(; mCurLine < mLineCount; mCurLine++) {
868 if(mLines == null) return false; // in this loop, Lines can be null when onScript does so.
869
870 String p = mLines[mCurLine];
871
872 char c0 = 0;
873 if( p != null && p.length() > 0 ) {
874 c0 = p.charAt(0);
875 }
876
877 if( c0 == ';' )
878 continue; // comment
879
880 if( c0 == '*' ) {
881 // label
882 if( mRecordingMacro )
883 Message.throwExceptionMessage(Message.LabelOrScriptInMacro);
884
885 int vl = p.indexOf('|');
886 boolean pagename;
887 if(vl != -1) {
888 mCurLabel = mScenario.getLabelAliasFromLine(mCurLine);
889 mCurPage = p.substring(vl + 1);
890 pagename = true;
891 } else {
892 mCurLabel = mScenario.getLabelAliasFromLine(mCurLine);
893 mCurPage = null;
894 pagename = false;
895 }
896
897 // fire onLabel callback event
898 Dispatch2 owner = mOwner.get();
899 if(owner!=null) {
900 Variant[] pparam = new Variant[2];
901 pparam[0] = new Variant(mCurLabel);
902 if(pagename) pparam[1] = new Variant(mCurPage);
903 else pparam[1] = new Variant();
904 owner.funcCall(0, EV_ON_LABEL, null, pparam, owner);
905 }
906 continue;
907 }
908
909 if( c0 == '[' && ("[iscript]".equals(p) || "[iscript]\\".equals(p) ) ||
910 c0 == '@' && "@iscript".equals(p) ) {
911 // inline TJS script
912 if(mRecordingMacro)
913 Message.throwExceptionMessage(Message.LabelOrScriptInMacro);
914
915 StringBuilder script = mWorkBuilder;
916 script.delete( 0, script.length() );
917 mCurLine++;
918
919 int script_start = mCurLine;
920
921 for(;mCurLine < mLineCount; mCurLine++) {
922 p = mLines[mCurLine];
923 if( p != null && p.length() > 0 ) {
924 c0 = p.charAt(0);
925 if( c0 == '[' && ( "[endscript]".equals(p) || "[endscript]\\".equals(p) )||
926 c0 == '@' && "@endscript".equals(p) ) {
927 break;
928 }
929 if(mExcludeLevel == -1) {
930 script.append( p );
931 script.append( "\r\n" );
932 }
933 } else {
934 script.append( "\r\n" );
935 }
936 }
937
938 if( mCurLine == mLineCount )
939 Message.throwExceptionMessage(Message.KAGInlineScriptNotEnd);
940
941 // fire onScript callback event
942 if(mExcludeLevel == -1) {
943 Dispatch2 owner = mOwner.get();
944 if(owner != null ) {
945 Variant[] pparam = { new Variant(script.toString()), new Variant(mStorageShortName), new Variant(script_start) };
946 script = null;
947 owner.funcCall(0, EV_ON_SCRIPT, null, pparam, owner );
948 }
949 }
950 continue;
951 }
952 break;
953 }
954
955 if(mCurLine >= mLineCount) return false;
956
957 mCurLineStr = mLines[mCurLine];
958 mLineBufferUsing = false;
959
960 if(mDebugLevel >= tkdlVerbose) {
961 DebugClass.addLog( mStorageShortName + " : " + mCurLineStr );
962 }
963 return true;
964 }
965 private void pushMacroArgs( Dispatch2 args ) throws VariantException, TJSException {
966 Dispatch2 dsp;
967 if(mMacroArgs.size() > mMacroArgStackDepth) {
968 dsp = mMacroArgs.get(mMacroArgStackDepth);
969 } else {
970 if( mMacroArgStackDepth > mMacroArgs.size())
971 Message.throwExceptionMessage(Message.InternalError);
972 dsp = TJS.createDictionaryObject();
973 mMacroArgs.add(dsp);
974 }
975 mMacroArgStackDepth++;
976
977 // copy arguments from args to dsp
978 Variant src = new Variant(args, args);
979 Variant[] psrc = new Variant[1];
980 psrc[0] = src;
981 mDicAssign.funcCall(0, null, null, psrc, dsp );
982 }
983 public void popMacroArgs() throws TJSException {
984 if(mMacroArgStackDepth == 0) Message.throwExceptionMessage(Message.KAGSyntaxError);
985 mMacroArgStackDepth--;
986 }
987 private void clearMacroArgs() {
988 mMacroArgs.clear();
989 mMacroArgStackDepth = 0;
990 }
991 private void popMacroArgsTo(int base) {
992 mMacroArgStackDepth = base;
993 }
994 /**
995 * find nearest label which be pleced before "start".
996 * "labelline" is to be the label's line number (0-based), and
997 * "labelname" is to be its label name.
998 * "labelline" will be -1 and "labelname" be empty if the label is not found.
999 * @param start
1000 * @param labelline 見付かったラベル番号
1001 * @return 見付かったラベル名
1002 * @throws TJSException
1003 */
1004 private String findNearestLabel( int start, IntWrapper labelline ) throws TJSException {
1005 mScenario.ensureLabelCache();
1006
1007 String labelname = null;
1008 start--;
1009 while(start >= 0) {
1010 String line = mLines[start];
1011 if( line.length() > 0 && line.charAt(0) == '*' ) {
1012 // label found
1013 labelname = mScenario.getLabelAliasFromLine(start);
1014 break;
1015 }
1016 start--;
1017 }
1018 labelline.value = start;
1019 if(labelline.value == -1) labelname = null;
1020 return labelname;
1021 }
1022 private void pushCallStack() throws TJSException {
1023 // push current position information
1024 if( mDebugLevel >= tkdlVerbose)
1025 {
1026 DebugClass.addLog( mStorageShortName + " : call stack depth before calling : "
1027 + String.valueOf(mCallStack.size()) );
1028 }
1029
1030 IntWrapper labelline = new IntWrapper(0);
1031 String labelname;
1032 labelname = findNearestLabel( mCurLine, labelline);
1033 if(labelline.value < 0) labelline.value = 0;
1034
1035 String curline_content;
1036 if( mLines != null && mCurLine < mLineCount )
1037 curline_content = mLines[mCurLine];
1038 else
1039 curline_content = "";
1040
1041 mCallStack.add( new CallStackData(mStorageName, labelname, mCurLine - labelline.value,
1042 curline_content,
1043 mLineBuffer, mCurPos, mLineBufferUsing, mMacroArgStackBase, mMacroArgStackDepth,
1044 mExcludeLevelStack, mExcludeLevel, mIfLevelExecutedStack, mIfLevel));
1045 mMacroArgStackBase = mMacroArgStackDepth;
1046 }
1047 private void popCallStack( final String storage, final String label ) throws VariantException, TJSException {
1048 // pop call stack information
1049 if(mCallStack.size() == 0)
1050 Message.throwExceptionMessage(Message.KAGCallStackUnderflow);
1051
1052 // pop macro argument information
1053 CallStackData data = mCallStack.get( mCallStack.size()-1 );
1054 mMacroArgStackBase = data.MacroArgStackDepth; // later reset to MacroArgStackBase
1055 popMacroArgsTo(data.MacroArgStackDepth);
1056
1057 // goto label or previous position
1058 if( (storage != null && storage.length() != 0) || ( label != null && label.length() != 0) ) {
1059 // return to specified position
1060 goToStorageAndLabel(storage, label);
1061 } else {
1062 // return to previous calling position
1063 loadScenario(data.Storage);
1064 if( data.Label != null && data.Label.length() != 0 ) goToLabel(data.Label);
1065 mCurLine += data.Offset;
1066 if(mCurLine > mLineCount)
1067 Message.throwExceptionMessage(Message.KAGReturnLostSync);
1068 /* CurLine == LineCount is OK (at end of file) */
1069 if(mCurLine < mLineCount) {
1070 if(data.OrgLineStr != mLines[mCurLine]) { // check original line information
1071 if( data.OrgLineStr == null || mLines[mCurLine] == null )
1072 Message.throwExceptionMessage(Message.KAGReturnLostSync);
1073 else if( data.OrgLineStr.equals(mLines[mCurLine]) == false )
1074 Message.throwExceptionMessage(Message.KAGReturnLostSync);
1075 }
1076 }
1077
1078 if(data.LineBufferUsing) {
1079 mLineBuffer = data.LineBuffer;
1080 mCurLineStr = mLineBuffer;
1081 mLineBufferUsing = true;
1082 } else {
1083 if(mCurLine < mLineCount) {
1084 mCurLineStr = mLines[mCurLine];
1085 mLineBufferUsing = false;
1086 }
1087 }
1088 mCurPos = data.Pos;
1089
1090 mExcludeLevelStack = data.ExcludeLevelStack;
1091 mExcludeLevel = data.ExcludeLevel;
1092 mIfLevelExecutedStack = data.IfLevelExecutedStack;
1093 mIfLevel = data.IfLevel;
1094
1095 if( mDebugLevel >= tkdlSimple ) {
1096 String label1;
1097 if( data.Label == null || data.Label.length() ==0 ) label1 = "(start)";
1098 else label1 = data.Label;
1099 StringBuilder builder = mWorkBuilder;
1100 builder.delete(0, builder.length());
1101 builder.append(mStorageShortName);
1102 builder.append(" : returned to : ");
1103 builder.append(label1);
1104 builder.append(" line offset ");
1105 builder.append(data.Offset);
1106 DebugClass.addLog( builder.toString() );
1107 builder = null;
1108 }
1109 }
1110
1111 // reset MacroArgStackBase
1112 mMacroArgStackBase = data.MacroArgStackBase;
1113
1114 // pop casll stack
1115 mCallStack.remove( mCallStack.size() -1 );
1116
1117 // call function back
1118 Dispatch2 owner = mOwner.get();
1119 if( owner != null ) {
1120 Variant[] arg = new Variant[0];
1121 owner.funcCall(0, EV_ON_AFTERETURN, null, arg, owner);
1122 }
1123
1124 if( mDebugLevel >= tkdlVerbose ) {
1125 StringBuilder builder = mWorkBuilder;
1126 builder.delete(0, builder.length());
1127 builder.append(mStorageShortName);
1128 builder.append(" : call stack depth after returning : ");
1129 builder.append(mCallStack.size());
1130 DebugClass.addLog( builder.toString() );
1131 builder = null;
1132 }
1133 }
1134 public void clearCallStack() {
1135 mCallStack.clear();
1136 popMacroArgsTo(mMacroArgStackBase = 0); // macro arguments are also cleared
1137 }
1138
1139 /**
1140 * is white space ?
1141 * @param ch
1142 * @return
1143 */
1144 static private final boolean isWS( char ch ) {
1145 return (ch == ' ' || ch == '\t');
1146 }
1147 /**
1148 * 組み込みタグ
1149 *
1150 */
1151 enum SpecialTags {
1152 tag_other,
1153 tag_if,
1154 tag_else,
1155 tag_elsif,
1156 tag_ignore,
1157 tag_endif,
1158 tag_endignore,
1159 tag_emb,
1160 tag_macro,
1161 tag_endmacro,
1162 tag_macropop,
1163 tag_erasemacro,
1164 tag_jump,
1165 tag_call,
1166 tag_return
1167 };
1168 static private String __tag_name;
1169 static private String __eol_name;
1170 static private String __storage_name;
1171 static private String __target_name;
1172 static private String __exp_name;
1173
1174 static private String STR_TEXT;
1175
1176 static private String EV_ON_JUMP;
1177 static private String EV_ON_CALL;
1178 static private String EV_ON_RETURN;
1179 static private String EV_ON_AFTERETURN;
1180 static private String EV_ON_LABEL;
1181 static private String EV_ON_SCENARIO_LOAD;
1182 static private String EV_ON_SCENARIO_LOADED;
1183 static private String EV_ON_SCRIPT;
1184
1185 static private Variant TAG_INTERRUPT;
1186 static private Variant TAG_R;
1187 static private Variant TAG_CH;
1188
1189 static private Variant VAL_TRUE;
1190
1191 static private HashMap<String, SpecialTags> special_tags_hash;
1192 static public void initialize() {
1193 __tag_name = TJS.mapGlobalStringMap("tagname");
1194 __eol_name = TJS.mapGlobalStringMap("eol");
1195 __storage_name = TJS.mapGlobalStringMap("storage");
1196 __target_name = TJS.mapGlobalStringMap("target");
1197 __exp_name = TJS.mapGlobalStringMap("exp");
1198
1199 STR_TEXT = TJS.mapGlobalStringMap("text");
1200
1201 EV_ON_JUMP = TJS.mapGlobalStringMap("onJump");
1202 EV_ON_CALL = TJS.mapGlobalStringMap("onCall");
1203 EV_ON_RETURN = TJS.mapGlobalStringMap("onReturn");
1204 EV_ON_AFTERETURN = TJS.mapGlobalStringMap("onAfterReturn");
1205 EV_ON_LABEL = TJS.mapGlobalStringMap("onLabel");
1206 EV_ON_SCENARIO_LOAD = TJS.mapGlobalStringMap("onScenarioLoad");
1207 EV_ON_SCENARIO_LOADED = TJS.mapGlobalStringMap("onScenarioLoaded");
1208 EV_ON_SCRIPT = TJS.mapGlobalStringMap("onScript");
1209
1210 TAG_INTERRUPT = new Variant("interrupt");
1211 TAG_R = new Variant( "r" );
1212 TAG_CH = new Variant("ch");
1213
1214 VAL_TRUE = new Variant( "true" );
1215
1216 special_tags_hash = new HashMap<String, SpecialTags>();
1217 special_tags_hash.put( "if", SpecialTags.tag_if );
1218 special_tags_hash.put( "ignore", SpecialTags.tag_ignore);
1219 special_tags_hash.put( "endif", SpecialTags.tag_endif);
1220 special_tags_hash.put( "endignore", SpecialTags.tag_endignore);
1221 special_tags_hash.put( "else", SpecialTags.tag_else);
1222 special_tags_hash.put( "elsif", SpecialTags.tag_elsif);
1223 special_tags_hash.put( "emb", SpecialTags.tag_emb);
1224 special_tags_hash.put( "macro", SpecialTags.tag_macro);
1225 special_tags_hash.put( "endmacro", SpecialTags.tag_endmacro);
1226 special_tags_hash.put( "macropop", SpecialTags.tag_macropop);
1227 special_tags_hash.put( "erasemacro",SpecialTags.tag_erasemacro);
1228 special_tags_hash.put( "jump", SpecialTags.tag_jump);
1229 special_tags_hash.put( "call", SpecialTags.tag_call);
1230 special_tags_hash.put( "return", SpecialTags.tag_return);
1231
1232 }
1233 private final char getC() {
1234 if( mCurPos >= mCurLineStr.length() ) return 0;
1235 return mCurLineStr.charAt(mCurPos);
1236 }
1237 /**
1238 * get next tag and return information dictionary object.
1239 * return null if the tag not found.
1240 * normal characters are interpreted as a "ch" tag.
1241 * CR code is interpreted as a "r" tag.
1242 * returned tag's line number is stored to TagLine.
1243 * tag paremeters are stored into return value.
1244 * tag name is also stored into return value, naemd "__tag".
1245 * @return
1246 * @throws CompileException
1247 * @throws TJSException
1248 * @throws VariantException
1249 */
1250 public Dispatch2 getNextTag() throws VariantException, TJSException, CompileException {
1251 // pretty a nasty code.
1252 all_nest:
1253 while(true){ parse_start: {
1254
1255 if( mCurLine >= mLineCount ) return null;
1256 if( mLines == null ) return null;
1257
1258 char c = 0;
1259 while( true ) {
1260 mDicClear.funcCall(0, null, null, TJS.NULL_ARG, mDicObj); // clear dictionary object
1261
1262 if( mInterrupted ) {
1263 // interrupt current parsing return as "interrupted" tag
1264 mDicObj.propSet(Interface.MEMBERENSURE, __tag_name, TAG_INTERRUPT, mDicObj);
1265 mInterrupted = false;
1266 return mDicObj;
1267 }
1268
1269 if( mCurLine >= mLineCount ) break all_nest; // all of scenario was decoded
1270
1271 int tagstartpos = mCurPos;
1272
1273 if(!mLineBufferUsing && mCurPos == 0)
1274 if(!skipCommentOrLabel()) return null;
1275
1276 c = getC();
1277 if(!mIgnoreCR) { // 改行を無視しない時
1278 if( (c == '\\' && mCurLineStr.length() == (mCurPos+1)) ||
1279 (mCurLineStr.length() == mCurPos && mCurPos >= 3 && mCurLineStr.startsWith( "[p]", mCurPos-3 )) ) {
1280 // 行が [p] で終わっているか、\で終わっている場合
1281 mCurLine++;
1282 mCurPos = 0;
1283 mLineBufferUsing = false;
1284 continue;
1285 }
1286
1287 if( mCurLineStr.length() == mCurPos ) { // 行が終わっている時
1288 mTagLine = mCurLine;
1289 mDicObj.propSet( Interface.MEMBERENSURE, __tag_name, TAG_R, mDicObj);
1290 mDicObj.propSet( Interface.MEMBERENSURE, __eol_name, VAL_TRUE, mDicObj);
1291 if(mRecordingMacro) mRecordingMacroStr.append( "[r eol=true]" );
1292 mCurLine++;
1293 mCurPos = 0;
1294 mLineBufferUsing = false;
1295 if(!mRecordingMacro && mExcludeLevel == -1) { return mDicObj; }
1296 continue;
1297 }
1298 }
1299
1300 char ldelim; // last delimiter
1301 if( !mLineBufferUsing && mCurPos == 0 && c == '@' ) {
1302 // @始まり ( line command mode )
1303 ldelim = 0; // tag last delimiter is a null terminater
1304 } else {
1305 if( c != '[' || mCurLineStr.startsWith( "[[", mCurPos ) ) {
1306 // 通常の文字
1307 char ch = c;
1308 mTagLine = mCurLine;
1309
1310 if( ch == 0 ) {
1311 // line ended
1312 mCurLine++;
1313 mCurPos = 0;
1314 mLineBufferUsing = false;
1315 continue;
1316 } else if(ch == '\t' ) {
1317 mCurPos++;
1318 continue;
1319 } else if( ch != '\n' ) {
1320 mDicObj.propSet( Interface.MEMBERENSURE, __tag_name, TAG_CH, mDicObj );
1321 Variant ch_val = new Variant( mCurLineStr.substring(mCurPos, mCurPos+1) );
1322 mDicObj.propSet( Interface.MEMBERENSURE, STR_TEXT, ch_val, mDicObj );
1323
1324 if( mRecordingMacro ) {
1325 if(ch == '[' )
1326 mRecordingMacroStr.append( "[[" );
1327 else
1328 mRecordingMacroStr.append( ch );
1329 }
1330 } else { // \n ( reline )
1331 mDicObj.propSet( Interface.MEMBERENSURE, __tag_name, TAG_R, mDicObj );
1332 if( mRecordingMacro ) mRecordingMacroStr.append( "[r]" );
1333 }
1334
1335 c = getC();
1336 if( c == '[' ) mCurPos++;
1337 mCurPos++;
1338
1339 if(!mRecordingMacro && mExcludeLevel == -1) {
1340 return mDicObj;
1341 }
1342 continue;
1343 }
1344 ldelim = ']';
1345 }
1346
1347 // タグの解析開始
1348 boolean condition = true;
1349 mTagLine = mCurLine;
1350 int tagstart = mCurPos;
1351 mCurPos++;
1352
1353 if( mCurLineStr.length() <= mCurPos ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1354
1355 // タグ名の解析 - start -----------------------------------------------------
1356 while( mCurPos < mCurLineStr.length() && isWS(getC()) ) mCurPos++; // skip white space
1357 if( mCurLineStr.length() <= mCurPos ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1358
1359 int tagnamestart = mCurPos;
1360 while( mCurPos < mCurLineStr.length() && !isWS(getC()) && getC() != ldelim)
1361 mCurPos++;
1362
1363 if( tagnamestart == mCurPos )
1364 Message.throwExceptionMessage(Message.KAGSyntaxError);
1365
1366 String tagname = mCurLineStr.substring(tagnamestart, mCurPos);
1367 tagname = toLowerCaseHalf(tagname);
1368 {
1369 Variant tag_val = new Variant(tagname);
1370 mDicObj.propSet( Interface.MEMBERENSURE, __tag_name, tag_val, mDicObj);
1371 }
1372 // タグ名の解析 - end -----------------------------------------------------
1373 // 組み込みタグチェック
1374 SpecialTags tagkind;
1375 SpecialTags tag = special_tags_hash.get(tagname);
1376 if( mProcessSpecialTags )
1377 tagkind = (tag != null) ? tag : SpecialTags.tag_other;
1378 else
1379 tagkind = SpecialTags.tag_other;
1380
1381 if(tagkind == SpecialTags.tag_macro) mRecordingMacroName = null;
1382
1383 // 属性の解析
1384 // tag attributes
1385 while( true ) {
1386 while( isWS(getC()) ) mCurPos++;
1387
1388 if( getC() == ldelim ) {
1389 // tag ended
1390
1391 boolean ismacro = false;
1392 String macrocontent = "";
1393
1394 if( condition && mExcludeLevel == -1 ) {
1395 if( tagkind == SpecialTags.tag_endmacro ) {
1396 // macro recording ended endmacro
1397 if( !mRecordingMacro ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1398 mRecordingMacro = false;
1399 if( mDebugLevel >= tkdlVerbose ) {
1400 DebugClass.addLog("macro : " + mRecordingMacroName + " : " + mRecordingMacroStr.toString() );
1401 }
1402
1403 mRecordingMacroStr.append( "[macropop]" ); // ensure macro arguments are to be popped
1404
1405 // register macro
1406 Variant macrocontent1 = new Variant(mRecordingMacroStr.toString());
1407 mMacros.propSet( Interface.MEMBERENSURE, mRecordingMacroName, macrocontent1, mMacros );
1408 }
1409
1410 // record macro
1411 if( mRecordingMacro ) {
1412 if( ldelim != 0 ) {
1413 // normal tag
1414 mRecordingMacroStr.append(mCurLineStr.substring( tagstart, mCurPos + 1 ) );
1415 } else {
1416 // line command
1417 if( mCurPos - tagstart >= 1 ) {
1418 mRecordingMacroStr.append('[');
1419 //mRecordingMacroStr.append(mCurLineStr.substring( tagstart +1, mCurPos - 1));
1420 mRecordingMacroStr.append(mCurLineStr.substring( tagstart +1, mCurPos));
1421 mRecordingMacroStr.append(']');
1422 }
1423 }
1424 if(ldelim == 0) {
1425 mCurLine++;
1426 mCurPos = 0;
1427 mLineBufferUsing = false;
1428 } else {
1429 mCurPos++;
1430 }
1431 break; // break
1432 }
1433
1434 // is macro ?
1435 Variant macroval = new Variant();
1436 int hr = mMacros.propGet( 0, tagname, macroval, mMacros );
1437 ismacro = hr >= 0;
1438 if(ismacro) ismacro = macroval.isVoid() != true;
1439 if(ismacro) macrocontent = macroval.asString();
1440 }
1441
1442 // tag-specific processing
1443 if( tagkind == SpecialTags.tag_other && !ismacro ) {
1444 // not a control tag
1445 if(ldelim == 0) {
1446 mCurLine++;
1447 mCurPos = 0;
1448 mLineBufferUsing = false;
1449 } else {
1450 mCurPos++;
1451 }
1452 if(condition && mExcludeLevel == -1) {
1453 return mDicObj;
1454 }
1455 break;
1456 }
1457
1458 // if/ignore
1459 if(tagkind == SpecialTags.tag_if || tagkind == SpecialTags.tag_ignore) {
1460 mIfLevel++;
1461 mIfLevelExecutedStack.add(false);
1462 mExcludeLevelStack.add(mExcludeLevel);
1463
1464 if( mExcludeLevel == -1 ) {
1465 Variant val = new Variant();
1466 mDicObj.propGet(0, __exp_name, val, mDicObj);
1467 String exp = val.asString();
1468 if( exp.length() == 0 )
1469 Message.throwExceptionMessage(Message.KAGSyntaxError);
1470 Dispatch2 owner = mOwner.get();
1471 ScriptsClass.executeExpression( exp, owner, val );
1472
1473 boolean cond = val.asBoolean();
1474 if(tagkind == SpecialTags.tag_ignore) cond = ! cond;
1475
1476 mIfLevelExecutedStack.set(mIfLevelExecutedStack.size()-1, cond );
1477 if(!cond) {
1478 mExcludeLevel = mIfLevel;
1479 }
1480 }
1481 }
1482
1483 // elsif
1484 if( tagkind == SpecialTags.tag_elsif ) {
1485 if( mIfLevelExecutedStack.isEmpty() ) {
1486 // no preceded if/ignore tag.
1487 // should throw an exception?
1488 } else if( mIfLevelExecutedStack.get(mIfLevelExecutedStack.size()-1) ) {
1489 mExcludeLevel = mIfLevel;
1490 } else if( mIfLevel == mExcludeLevel ) {
1491 Variant val = new Variant();
1492 String exp;
1493 mDicObj.propGet(0, __exp_name, val, mDicObj);
1494 exp = val.asString();
1495 if( exp.length() == 0 ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1496 Dispatch2 owner = mOwner.get();
1497 ScriptsClass.executeExpression(exp, owner, val);
1498
1499 boolean cond = val.asBoolean();
1500 if(cond) {
1501 mIfLevelExecutedStack.set( mIfLevelExecutedStack.size()-1, true );
1502 mExcludeLevel = -1;
1503 }
1504 }
1505 }
1506
1507 // else
1508 if( tagkind == SpecialTags.tag_else ) {
1509 if( mIfLevelExecutedStack.isEmpty() ) {
1510 // no preceded if/ignore tag.
1511 // should throw an exception?
1512 } else if( mIfLevelExecutedStack.get(mIfLevelExecutedStack.size()-1) ) {
1513 mExcludeLevel = mIfLevel;
1514 } else if( mIfLevel == mExcludeLevel ) {
1515 mIfLevelExecutedStack.set( mIfLevelExecutedStack.size()-1, true );
1516 mExcludeLevel = -1;
1517 }
1518 }
1519
1520 // endif/endignore
1521 if( tagkind == SpecialTags.tag_endif || tagkind == SpecialTags.tag_endignore ) {
1522 // endif
1523 if(!mExcludeLevelStack.isEmpty() ) {
1524 mExcludeLevel = mExcludeLevelStack.get(mExcludeLevelStack.size()-1);
1525 mExcludeLevelStack.remove( mExcludeLevelStack.size()-1);
1526 }
1527 if(!mIfLevelExecutedStack.isEmpty())
1528 mIfLevelExecutedStack.remove(mIfLevelExecutedStack.size()-1);
1529
1530 mIfLevel--;
1531 if(mIfLevel < 0) mIfLevel = 0;
1532
1533 if(ldelim == 0) {
1534 mCurLine++;
1535 mCurPos = 0;
1536 mLineBufferUsing = false;
1537 } else {
1538 mCurPos++;
1539 }
1540
1541 break; // break
1542 }
1543
1544
1545 if( condition && mExcludeLevel == -1 ) {
1546 if(tagkind == SpecialTags.tag_emb || (ismacro && tagkind==SpecialTags.tag_other)) {
1547 // embed string
1548 // insert string to current position
1549 if(ldelim != 0) mCurPos++;
1550
1551 if(!ismacro) {
1552 // execute expression
1553 Variant val = new Variant();
1554 mDicObj.propGet(0, __exp_name, val, mDicObj);
1555 String exp = val.asString();
1556 if( exp.length() == 0 )
1557 Message.throwExceptionMessage(Message.KAGSyntaxError);
1558 Dispatch2 owner = mOwner.get();
1559 ScriptsClass.executeExpression(exp, owner, val);
1560 exp = val.asString();
1561
1562 // count '['
1563 char[] p = exp.toCharArray();
1564 int r_count = 0;
1565 for( int i = 0; i < p.length; i++ ) {
1566 if( p[i] == '[' ) r_count++;
1567 r_count++;
1568 }
1569
1570 int curposlen = mCurLineStr.length() - mCurPos;
1571 int finallen = r_count + tagstartpos + curposlen;
1572
1573 if(ldelim == 0 && !mIgnoreCR) finallen++;
1574
1575 StringBuilder d = mWorkBuilder;
1576 d.delete(0,d.length());
1577 if( tagstartpos > 0 ) {
1578 d.append( mCurLineStr.substring(0, tagstartpos) );
1579 }
1580 //d += tagstartpos;
1581
1582 // escape '['
1583 for( int i = 0; i < p.length; i++ ) {
1584 if( p[i] == '[' ) {
1585 d.append( '[' );
1586 d.append( '[' );
1587 } else {
1588 d.append( p[i]);
1589 }
1590 }
1591 if( mCurPos < mCurLineStr.length() ) {
1592 d.append( mCurLineStr.substring(mCurPos) );
1593 }
1594
1595 if( ldelim == 0 && !mIgnoreCR ) {
1596 d.append( '\\' );
1597 }
1598 mLineBuffer = d.toString();
1599 d = null;
1600 } else {
1601 int maclen = macrocontent.length();
1602 int curposlen = mCurLineStr.length() - mCurPos;
1603 int finallen = tagstartpos + maclen + curposlen;
1604
1605 if(ldelim == 0 && !mIgnoreCR) finallen++;
1606
1607 StringBuilder d = mWorkBuilder;
1608 d.delete(0,d.length());
1609 if( tagstartpos > 0 ) {
1610 d.append( mCurLineStr.substring(0,tagstartpos) );
1611 }
1612 d.append( macrocontent );
1613 if( mCurPos < mCurLineStr.length() ) {
1614 d.append( mCurLineStr.substring(mCurPos) );
1615 }
1616 if( ldelim == 0 && !mIgnoreCR ) {
1617 d.append( '\\' );
1618 }
1619 mLineBuffer = d.toString();
1620 d = null;
1621 }
1622
1623 mCurLineStr = mLineBuffer;
1624 mCurPos = tagstartpos;
1625
1626 mLineBufferUsing = true;
1627
1628 // push macro arguments
1629 if(ismacro) pushMacroArgs(mDicObj);
1630 break;
1631 } else if( tagkind == SpecialTags.tag_jump ) {
1632 // jump tag
1633 Variant val = new Variant();
1634 mDicObj.propGet(0, __storage_name, val, mDicObj );
1635 String attrib_storage = val.asString();
1636 mDicObj.propGet(0, __target_name, val, mDicObj );
1637 String attrib_target = val.asString();
1638
1639
1640 // fire onJump event
1641 boolean process = true;
1642 Dispatch2 owner = mOwner.get();
1643 if( owner!=null ) {
1644 Variant param = new Variant(mDicObj, mDicObj);
1645 Variant[] pparam = {param};
1646 Variant res = new Variant();
1647 int er = owner.funcCall(0, EV_ON_JUMP, res, pparam, owner );
1648 if( er == Error.S_OK ) process = res.asBoolean();
1649 }
1650
1651 if(process) {
1652 goToStorageAndLabel( attrib_storage, attrib_target );
1653 break parse_start; // re-start parsing TODO
1654 }
1655 } else if( tagkind == SpecialTags.tag_call ) {
1656 // call tag
1657 Variant val = new Variant();
1658 mDicObj.propGet(0, __storage_name, val, mDicObj );
1659 String attrib_storage = val.asString();
1660 mDicObj.propGet(0, __target_name, val, mDicObj );
1661 String attrib_target = val.asString();
1662
1663 // fire onCall event
1664 boolean process = true;
1665 Dispatch2 owner = mOwner.get();
1666 if( owner != null ) {
1667 Variant param = new Variant(mDicObj, mDicObj);
1668 Variant[] pparam = {param};
1669 Variant res = new Variant();
1670 int er = owner.funcCall(0, EV_ON_CALL, res, pparam, owner);
1671 if(er == Error.S_OK) process = res.asBoolean();
1672 }
1673
1674 if( process ) {
1675 if(ldelim == 0) {
1676 mCurLine++;
1677 mCurPos = 0;
1678 mLineBufferUsing = false;
1679 } else {
1680 mCurPos++;
1681 }
1682
1683 pushCallStack();
1684 goToStorageAndLabel(attrib_storage, attrib_target);
1685 break parse_start; //TODO
1686 }
1687 } else if(tagkind == SpecialTags.tag_return) {
1688 // return tag
1689 Variant val = new Variant();
1690 mDicObj.propGet(0, __storage_name, val, mDicObj);
1691 String attrib_storage = val.asString();
1692 mDicObj.propGet(0, __target_name, val, mDicObj );
1693 String attrib_target = val.asString();
1694
1695 // fire onReturn event
1696 boolean process = true;
1697 Dispatch2 owner = mOwner.get();
1698 if( owner!=null ) {
1699 Variant param = new Variant(mDicObj, mDicObj);
1700 Variant[] pparam = {param};
1701 Variant res = new Variant();
1702 int er = owner.funcCall(0, EV_ON_RETURN, res, pparam, owner);
1703 if(er == Error.S_OK) process = res.asBoolean();
1704 }
1705
1706 if(process) {
1707 popCallStack(attrib_storage, attrib_target);
1708 break parse_start; //TODO
1709 }
1710 } else {
1711 if( tagkind == SpecialTags.tag_macro ) {
1712 Variant val = new Variant();
1713 mDicObj.propGet( 0, "name", val, mDicObj );
1714 mRecordingMacroName = val.asString();
1715 mRecordingMacroName = toLowerCaseHalf(mRecordingMacroName); // 全角は変換しない toLowerCase
1716 if( mRecordingMacroName.length() == 0 )
1717 Message.throwExceptionMessage(Message.KAGSyntaxError);
1718 // missing macro name
1719 mRecordingMacro = true; // start recording macro
1720 mRecordingMacroStr.delete(0, mRecordingMacroStr.length());
1721 } else if(tagkind == SpecialTags.tag_macropop ) {
1722 // pop macro arguments
1723 popMacroArgs();
1724 } else if(tagkind == SpecialTags.tag_erasemacro) {
1725 Variant val = new Variant();
1726 mDicObj.propGet(0, "name", val, mDicObj);
1727 String macroname = val.asString();
1728 int hr = mMacros.deleteMember(0, macroname, mMacros);
1729 if( hr < 0 )
1730 Message.throwExceptionMessage(Message.UnknownMacroName, macroname);
1731 }
1732 }
1733 }
1734
1735 if(ldelim == 0) {
1736 mCurLine++;
1737 mCurPos = 0;
1738 mLineBufferUsing = false;
1739 } else {
1740 mCurPos++;
1741 }
1742 break;
1743 }
1744
1745 if(getC() == 0)
1746 Message.throwExceptionMessage(Message.KAGSyntaxError);
1747
1748 // attrib name
1749 if( getC() == '*' ) {
1750 // macro entity all
1751 if(!mRecordingMacro) {
1752 Dispatch2 dsp = getMacroTop();
1753 if( dsp!=null ) {
1754 // assign macro arguments to current arguments
1755 Variant src =new Variant(dsp, dsp);
1756 Variant[] psrc = {src};
1757 mDicAssign.funcCall(0, null, null, psrc, mDicObj);
1758 }
1759 Variant tag_val = new Variant(tagname);
1760 mDicObj.propSet( Interface.MEMBERENSURE, __tag_name, tag_val, mDicObj );
1761 // reset tag_name
1762 }
1763
1764 mCurPos++;
1765 while(mCurPos < mCurLineStr.length() && isWS(getC())) mCurPos++;
1766 continue;
1767 }
1768
1769 int attribnamestart = mCurPos;
1770 while(mCurPos < mCurLineStr.length() && !isWS(getC()) &&
1771 getC() != '=' && getC() != ldelim)
1772 mCurPos++;
1773
1774 int attribnameend = mCurPos;
1775
1776 String attribname = mCurLineStr.substring(attribnamestart, attribnameend);
1777 attribname = toLowerCaseHalf(attribname);
1778
1779 // =
1780 while( mCurPos < mCurLineStr.length() && isWS(getC()) ) mCurPos++;
1781
1782 boolean entity = false;
1783 boolean macroarg = false;
1784 String value;
1785
1786 if( getC() != '=' ) {
1787 // arrtibute value omitted
1788 value = "true"; // always true
1789 } else {
1790 if( mCurLineStr.length() <= mCurPos ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1791 mCurPos++;
1792 if( mCurLineStr.length() <= mCurPos ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1793 while( mCurLineStr.length() > mCurPos && isWS(getC())) mCurPos++;
1794 if( mCurLineStr.length() <= mCurPos ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1795
1796 // attrib value
1797 char vdelim = 0; // value delimiter
1798
1799 if(getC() == '&' ) {
1800 entity = true;
1801 mCurPos++;
1802 } else if(getC() == '%' ) {
1803 macroarg = true;
1804 mCurPos++;
1805 }
1806
1807 if( getC() == '\"' || getC() == '\'' ) {
1808 vdelim = getC();
1809 mCurPos++;
1810 }
1811
1812 int valuestart = mCurPos;
1813 while( mCurLineStr.length() > mCurPos &&
1814 (vdelim != 0 ? (getC() != vdelim) :
1815 (getC() != ldelim &&
1816 !isWS(getC())) ) )
1817 {
1818 if( getC() == '`' ) {
1819 // escaped with '`'
1820 mCurPos++;
1821 if( mCurLineStr.length() <= mCurPos ) Message.throwExceptionMessage(Message.KAGSyntaxError);
1822 }
1823 mCurPos++;
1824 }
1825
1826 if(ldelim != 0 && mCurLineStr.length() <= mCurPos)
1827 Message.throwExceptionMessage(Message.KAGSyntaxError);
1828 int valueend = mCurPos;
1829
1830 if(vdelim!=0) mCurPos++;
1831
1832 // unescape ` character of value
1833 value = mCurLineStr.substring(valuestart, valueend);
1834 if( valueend != valuestart ) {
1835 // value has at least one character
1836 final int count = value.length();
1837 StringBuilder v = mWorkBuilder;
1838 v.delete( 0, v.length() );
1839 int vp = 0;
1840 if( !entity && vp < count && value.charAt(vp) == '&') {
1841 entity = true;
1842 vp++;
1843 }
1844 if( !macroarg && vp < count && value.charAt(vp) == '%') {
1845 macroarg = true;
1846 vp++;
1847 }
1848
1849 while( vp < count ) {
1850 if( value.charAt(vp) == '`' ) {
1851 vp++;
1852 if( vp >= count ) break;
1853 }
1854 v.append( value.charAt(vp) );
1855 vp++;
1856 }
1857 value = v.toString();
1858 v = null;
1859 }
1860 }
1861
1862 // special attibute processing
1863 boolean store = true;
1864 if((!mRecordingMacro && mExcludeLevel == -1) || tagkind == SpecialTags.tag_elsif) {
1865 // process expression entity or macro argument
1866 if(entity) {
1867 Dispatch2 owner = mOwner.get();
1868 ScriptsClass.executeExpression(value, owner, mValueVariant);
1869 if(mValueVariant.isVoid() != true) mValueVariant.toString();
1870 } else if(macroarg) {
1871 Dispatch2 args = getMacroTop();
1872 if(args!=null) {
1873 int vp = value.indexOf('|');
1874 if( vp != -1 ) {
1875 String name = value.substring( 0, vp );
1876 args.propGet(0, name, mValueVariant, args);
1877 if( mValueVariant.isVoid() )
1878 mValueVariant.set( value.substring(vp+1) );
1879 } else {
1880 args.propGet( 0, value, mValueVariant, args );
1881 }
1882 } else {
1883 mValueVariant.set( value );
1884 }
1885 } else {
1886 mValueVariant.set( value );
1887 }
1888
1889 if( "cond".equals(attribname) ) {
1890 // condition
1891 Variant val = new Variant();
1892 Dispatch2 owner = mOwner.get();
1893 ScriptsClass.executeExpression( mValueVariant.asString(), owner, val );
1894 condition = val.asBoolean();
1895 store = false;
1896 }
1897 }
1898
1899 // store value into the dictionary object
1900 if(store)
1901 mDicObj.propSet(Interface.MEMBERENSURE, attribname, mValueVariant, mDicObj );
1902 }
1903 }
1904 }} // parse_start:
1905
1906 return null;
1907 }
1908
1909 public Dispatch2 getMacroTop() {
1910 if(mMacroArgStackDepth == 0) return null;
1911 return mMacroArgs.get(mMacroArgStackDepth - 1);
1912 }
1913
1914 public final String getStorageName() { return mStorageName; }
1915 public final void interrupt() { mInterrupted = true; };
1916 public final void resetInterrupt() { mInterrupted = false; };
1917
1918 public final String getCurLabel() { return mCurLabel; }
1919 public final int getCurLine() { return mCurLine; }
1920 public final int getCurPos() { return mCurPos; }
1921 public final String getCurLineStr() { return mCurLineStr; }
1922
1923 public final void setProcessSpecialTags(boolean b) { mProcessSpecialTags = b; }
1924 public final boolean getProcessSpecialTags() { return mProcessSpecialTags; }
1925
1926 public final void setIgnoreCR(boolean b) { mIgnoreCR = b; }
1927 public final boolean getIgnoreCR() { return mIgnoreCR; }
1928
1929 public final void setDebugLevel( int level) { mDebugLevel = level; }
1930 public final int getDebugLevel() { return mDebugLevel; }
1931
1932 public final Dispatch2 getMacros() { return mMacros; }
1933
1934 public int getCallStackDepth() { return mCallStack.size(); }
1935 public void assign(KAGParserNI src) throws VariantException, TJSException {
1936 copy( src );
1937 }
1938
1939 /**
1940 * 半角大文字英字のみを小文字にする
1941 * @param str 入力文字列
1942 * @return 変換後文字列
1943 */
1944 private String toLowerCaseHalf( String str ) {
1945 final int count = str.length();
1946 if( mWorkChar == null || mWorkChar.length < count ) {
1947 mWorkChar = str.toCharArray();
1948 } else {
1949 str.getChars( 0, count, mWorkChar, 0 );
1950 }
1951 char[] tmp = mWorkChar;
1952 boolean ischange = false;
1953 for( int i = 0; i < count; i++ ) {
1954 char ch = tmp[i];
1955 if( ch >= 'A' && ch <= 'Z' ) {
1956 ch += 'a'-'A';
1957 tmp[i] = ch;
1958 ischange = true;
1959 }
1960 }
1961 if( ischange ) {
1962 return new String(tmp);
1963 } else {
1964 return str;
1965 }
1966 }
1967 }
1968

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26