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

Last change on this file since 745 was 745, checked in by dai, 15 years ago
  • Compiler::AddStringToDataTableメソッドを実装。
  • ToWStringメソッドの内部予備バッファを増やした。
File size: 7.9 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    compiler.AddStringToDataTable( str );
181
182    return dataTableOffset;
183}
184
185bool DataTableGenerator::MakeLiteralArrayBuffer( DataTable &dataTable, const char *expression, const Type &baseType, int &dataTableOffset )
186{
187    if( !baseType.IsPointer() ){
188        compiler.errorMessenger.Output(1,NULL,cp);
189        return false;
190    }
191    Type tempBaseType( baseType );
192    tempBaseType.PtrLevelDown();
193
194    char *buffer = (char *)malloc( lstrlen( expression ) + 1 );
195    lstrcpy( buffer, expression );
196    RemoveStringBracket( buffer );
197
198    Jenga::Common::Strings parameters;
199    SplitParameter( buffer, parameters );
200
201    // アラインメント
202    dataTable.AddAlignment( tempBaseType.GetSize() );
203
204    // データテーブルに空間を確保
205    dataTableOffset = dataTable.AddSpace( static_cast<int>(tempBaseType.GetSize() * parameters.size()) );
206
207    bool isSuccessful = true;
208    int i = 0;
209    BOOST_FOREACH( const std::string &paramStr, parameters )
210    {
211        if( paramStr.size() == 0 )
212        {
213            throw;
214        }
215        if( paramStr[0] == '\"' )
216        {
217            // 文字列
218            std::string tempParamStr = paramStr;
219            if( !RemoveStringQuotes( tempParamStr ) )
220            {
221                compiler.errorMessenger.OutputFatalError();
222            }
223
224            // 文字列を追加
225            _int64 strOffset;
226            if( tempBaseType.IsStringClass() )
227            {
228                // Stringクラス
229                strOffset = MakeConstStringObjectToProcessStaticBuffer( dataTable, tempParamStr.c_str() );
230            }
231            else
232            {
233                // Charポインタ
234                strOffset = compiler.AddStringToDataTable( tempParamStr );
235            }
236
237            // ポインタ値を上書き
238            int tempOffset = dataTableOffset + i * tempBaseType.GetSize();
239            dataTable.OverwriteBinary( tempOffset, &strOffset, tempBaseType.GetSize() );
240
241            // DataTableスケジュール
242            dataTable.schedules.push_back( Schedule( Schedule::DataTable, tempOffset  ) );
243        }
244        else
245        {
246            // 数値
247            Type resultType;
248            _int64 i64data;
249            if( !StaticCalculation( true, paramStr.c_str(), tempBaseType.GetBasicType(), &i64data, resultType ) ){
250                isSuccessful = false;
251                break;
252            }
253            if( !resultType.IsWhole() ){
254                // TODO: 実数に未対応
255                compiler.errorMessenger.OutputFatalError();
256                isSuccessful = false;
257                break;
258            }
259
260            // 上書き
261            dataTable.OverwriteBinary( dataTableOffset + i * tempBaseType.GetSize(), &i64data, tempBaseType.GetSize() );
262        }
263
264        i++;
265    }
266
267    free( buffer );
268
269    return isSuccessful;
270}
Note: See TracBrowser for help on using the repository browser.