source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/DataTableGenerator.cpp@ 648

Last change on this file since 648 was 591, checked in by dai_9181, 16 years ago

DataTable::AddWStringメソッドを追加。

File size: 8.2 KB
Line 
1#include "stdafx.h"
2
3using namespace ActiveBasic::Compiler;
4
5int DataTableGenerator::lastMadeConstObjectDataTableOffset = 0;
6
7bool DataTableGenerator::MakeConstObjectToProcessStaticBuffer( DataTable &dataTable, const CClass &objClass, const Jenga::Common::Strings &initMemberValues, int &dataTableOffset )
8{
9 // クラスに必要なバッファサイズを取得
10 int size = objClass.GetSize();
11
12 // クラスのバッファイメージを作成
13 BYTE *buffer = (BYTE *)calloc( size, 1 );
14
15 // クラスのバッファイメージをデータ領域へ追加
16 dataTableOffset = dataTable.AddBinary( buffer, size );
17
18 DataTableGenerator::lastMadeConstObjectDataTableOffset = dataTableOffset;
19
20 // com_vtblスケジュール
21 dataTable.schedules.push_back( Schedule( Schedule::ComVtbl, &objClass, dataTableOffset ) );
22
23 // vtblスケジュール
24 dataTable.schedules.push_back( Schedule( Schedule::Vtbl, &objClass, dataTableOffset + PTR_SIZE ) );
25
26 // TypeInfoスケジュール
27 int offsetForTypeInfo = objClass.GetMemberOffset( "_system_object_member_typeInfo" );
28 //dataTable.schedules.push_back( Schedule( Schedule::TypeInfo, &objClass, dataTableOffset + offsetForTypeInfo ) );
29
30 BOOST_FOREACH( const std::string &initMemberValue, initMemberValues )
31 {
32 int i = 0;
33
34 // メンバ名
35 char memberName[VN_SIZE];
36 for( i=0; ; i++ )
37 {
38 if( initMemberValue[i] == '\0' )
39 {
40 // エラー
41 compiler.errorMessenger.OutputFatalError();
42 return false;
43 }
44 if( initMemberValue[i] == '=' )
45 {
46 memberName[i] = 0;
47 break;
48 }
49 memberName[i] = initMemberValue[i];
50 }
51
52 // 初期値
53 const char *initValue = initMemberValue.c_str() + i + 1;
54
55 // メンバを取得
56 const Member *member = objClass.FindDynamicMember( memberName );
57
58 // メンバオフセットを取得
59 int memberOffset = objClass.GetMemberOffset( member->GetName().c_str() );
60
61 if( member->GetType().IsPointer() && initValue[0] == '[' )
62 {
63 // ポインタ型でバッファ指定のとき
64 int memberDataTableOffset;
65 if( !MakeLiteralArrayBuffer( dataTable, initValue, member->GetType(),memberDataTableOffset ) )
66 {
67 return false;
68 }
69
70 dataTable.Overwrite( dataTableOffset + memberOffset, memberDataTableOffset );
71 dataTable.schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + memberOffset ) );
72 }
73 else if( member->GetType().IsWhole() )
74 {
75 // 整数
76 Type resultType;
77 _int64 i64data;
78 if( !StaticCalculation( true, initValue, member->GetType().GetBasicType(), &i64data, resultType ) ){
79 return false;
80 }
81
82 dataTable.Overwrite( dataTableOffset + memberOffset, static_cast<long>(i64data) );
83 }
84 else if( member->GetType().IsStringClass() )
85 {
86 // 文字列型
87 char temporary[VN_SIZE];
88 lstrcpy( temporary, initValue );
89 RemoveStringQuotes( temporary );
90 int memberDataTableOffset = MakeConstStringObjectToProcessStaticBuffer( dataTable, temporary );
91 dataTable.Overwrite( dataTableOffset + memberOffset, memberDataTableOffset );
92 dataTable.schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + memberOffset ) );
93 }
94 }
95
96 return true;
97}
98bool DataTableGenerator::MakeConstObjectToProcessStaticBuffer( DataTable &dataTable, const char *expression, Type &resultType, int &dataTableOffset )
99{
100 char CreateParameter[VN_SIZE];
101 int i,i2;
102
103 i=0;
104
105 // クラス名を取得
106 char typeName[VN_SIZE];
107 for(i2=0;;i++,i2++){
108 if(expression[i]=='['){
109 typeName[i2]=0;
110
111 // メンバの初期値を取得
112 i2=GetStringInBracket(CreateParameter,expression+i);
113 RemoveStringBracket(CreateParameter);
114 i+=i2;
115 if(expression[i]!='\0'){
116 compiler.errorMessenger.Output(42,NULL,cp);
117 return false;
118 }
119 break;
120 }
121 typeName[i2]=expression[i];
122 if(expression[i]=='\0'){
123 CreateParameter[0]=0;
124 break;
125 }
126 }
127
128 // パラメータを取得
129 Jenga::Common::Strings initMemberValues;
130 SplitParameter( CreateParameter, initMemberValues );
131
132 if( !compiler.StringToType( typeName, resultType ) ){
133 compiler.errorMessenger.Output(3,typeName,cp);
134 return false;
135 }
136
137 if( !resultType.IsObject() ){
138 ////////////////////////
139 // 通常のデータ型の場合
140 ////////////////////////
141
142 compiler.errorMessenger.Output(121,NULL,cp);
143 return false;
144 }
145
146 return MakeConstObjectToProcessStaticBuffer( dataTable, resultType.GetClass(), initMemberValues, dataTableOffset );
147}
148
149int DataTableGenerator::MakeConstStringObjectToProcessStaticBuffer( DataTable &dataTable, const char *str )
150{
151 const CClass &strClass = *compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr();
152 const CClass &objClass = strClass.GetSuperClass();
153
154 // クラスに必要なバッファサイズを取得
155 int size = strClass.GetSize();
156
157 // メンバ位置を取得
158 int offsetForTypeInfo = strClass.GetMemberOffset( "_system_object_member_typeInfo" );
159 int offsetForLength = strClass.GetMemberOffset( "m_Length" );
160 int offsetForChars = strClass.GetMemberOffset( "Chars" );
161
162 // 現在のデータ領域のヘッダ位置を取得
163 int headOffset = dataTable.GetSize();
164
165 // クラスのバッファイメージを作成
166 BYTE *buffer = (BYTE *)calloc( size, 1 );
167 *(long *)(buffer + offsetForLength) = lstrlen( str );
168 *(LONG_PTR *)(buffer + offsetForChars) = headOffset + size;
169
170 // クラスのバッファイメージをデータ領域へ追加
171 int dataTableOffset = dataTable.AddBinary( buffer, size );
172
173 // スケジューリング
174 dataTable.schedules.push_back( Schedule( Schedule::ComVtbl, &strClass, headOffset ) );
175 dataTable.schedules.push_back( Schedule( Schedule::Vtbl, &strClass, headOffset + PTR_SIZE ) );
176 dataTable.schedules.push_back( Schedule( Schedule::TypeInfo, &strClass, headOffset + offsetForTypeInfo ) );
177 dataTable.schedules.push_back( Schedule( Schedule::DataTable, headOffset + offsetForChars ) );
178
179 // 文字列バッファをデータ領域へ追加
180 if( compiler.IsUnicode() )
181 {
182 dataTable.AddWString( Jenga::Common::ToWString( str ) );
183 }
184 else
185 {
186 dataTable.AddString( str );
187 }
188
189 return dataTableOffset;
190}
191
192bool DataTableGenerator::MakeLiteralArrayBuffer( DataTable &dataTable, const char *expression, const Type &baseType, int &dataTableOffset )
193{
194 if( !baseType.IsPointer() ){
195 compiler.errorMessenger.Output(1,NULL,cp);
196 return false;
197 }
198 Type tempBaseType( baseType );
199 tempBaseType.PtrLevelDown();
200
201 char *buffer = (char *)malloc( lstrlen( expression ) + 1 );
202 lstrcpy( buffer, expression );
203 RemoveStringBracket( buffer );
204
205 Jenga::Common::Strings parameters;
206 SplitParameter( buffer, parameters );
207
208 // アラインメント
209 dataTable.AddAlignment( tempBaseType.GetSize() );
210
211 // データテーブルに空間を確保
212 dataTableOffset = dataTable.AddSpace( static_cast<int>(tempBaseType.GetSize() * parameters.size()) );
213
214 bool isSuccessful = true;
215 int i = 0;
216 BOOST_FOREACH( const std::string &paramStr, parameters )
217 {
218 if( paramStr.size() == 0 )
219 {
220 throw;
221 }
222 if( paramStr[0] == '\"' )
223 {
224 // 文字列
225 std::string tempParamStr = paramStr;
226 if( !RemoveStringQuotes( tempParamStr ) )
227 {
228 compiler.errorMessenger.OutputFatalError();
229 }
230
231 // 文字列を追加
232 _int64 strOffset;
233 if( tempBaseType.IsStringClass() )
234 {
235 // Stringクラス
236 strOffset = MakeConstStringObjectToProcessStaticBuffer( dataTable, tempParamStr.c_str() );
237 }
238 else
239 {
240 // Charポインタ
241 if( compiler.IsUnicode() )
242 {
243 strOffset = dataTable.AddWString( Jenga::Common::ToWString( tempParamStr ) );
244 }
245 else
246 {
247 strOffset = dataTable.AddString( tempParamStr );
248 }
249 }
250
251 // ポインタ値を上書き
252 int tempOffset = dataTableOffset + i * tempBaseType.GetSize();
253 dataTable.OverwriteBinary( tempOffset, &strOffset, tempBaseType.GetSize() );
254
255 // DataTableスケジュール
256 dataTable.schedules.push_back( Schedule( Schedule::DataTable, tempOffset ) );
257 }
258 else
259 {
260 // 数値
261 Type resultType;
262 _int64 i64data;
263 if( !StaticCalculation( true, paramStr.c_str(), tempBaseType.GetBasicType(), &i64data, resultType ) ){
264 isSuccessful = false;
265 break;
266 }
267 if( !resultType.IsWhole() ){
268 // TODO: 実数に未対応
269 compiler.errorMessenger.OutputFatalError();
270 isSuccessful = false;
271 break;
272 }
273
274 // 上書き
275 dataTable.OverwriteBinary( dataTableOffset + i * tempBaseType.GetSize(), &i64data, tempBaseType.GetSize() );
276 }
277
278 i++;
279 }
280
281 free( buffer );
282
283 return isSuccessful;
284}
Note: See TracBrowser for help on using the repository browser.