| 1 | #include "stdafx.h"
 | 
|---|
| 2 | 
 | 
|---|
| 3 | using namespace ActiveBasic::Compiler;
 | 
|---|
| 4 | 
 | 
|---|
| 5 | int DataTableGenerator::lastMadeConstObjectDataTableOffset = 0;
 | 
|---|
| 6 | 
 | 
|---|
| 7 | bool 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 | }
 | 
|---|
| 98 | bool 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 | 
 | 
|---|
| 149 | int 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 |     dataTable.AddString( str );
 | 
|---|
| 181 | 
 | 
|---|
| 182 |     return dataTableOffset;
 | 
|---|
| 183 | }
 | 
|---|
| 184 | 
 | 
|---|
| 185 | bool 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 ¶mStr, 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 = dataTable.AddString( 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 | }
 | 
|---|