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

Last change on this file since 824 was 762, checked in by イグトランス (egtra), 16 years ago

#230 Unicodeコンパイル時、文字列リテラルの長さが正しく設定されていない問題を解決。

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