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

Last change on this file since 591 was 591, checked in by dai_9181, 15 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.