Home | History | Annotate | Download | only in slang
      1 /*
      2  * Copyright 2012, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <sys/stat.h>
     18 
     19 #include <cstdarg>
     20 #include <cctype>
     21 
     22 #include <algorithm>
     23 #include <limits>
     24 #include <sstream>
     25 #include <string>
     26 #include <utility>
     27 
     28 #include "os_sep.h"
     29 #include "slang_rs_context.h"
     30 #include "slang_rs_export_var.h"
     31 #include "slang_rs_export_foreach.h"
     32 #include "slang_rs_export_func.h"
     33 #include "slang_rs_reflect_utils.h"
     34 #include "slang_version.h"
     35 #include "slang_utils.h"
     36 
     37 #include "slang_rs_reflection_base.h"
     38 
     39 
     40 
     41 using namespace std;
     42 
     43 namespace slang {
     44 
     45 static const char *const gApacheLicenseNote =
     46 "/*\n"
     47 " * Copyright (C) 2012 The Android Open Source Project\n"
     48 " *\n"
     49 " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
     50 " * you may not use this file except in compliance with the License.\n"
     51 " * You may obtain a copy of the License at\n"
     52 " *\n"
     53 " *      http://www.apache.org/licenses/LICENSE-2.0\n"
     54 " *\n"
     55 " * Unless required by applicable law or agreed to in writing, software\n"
     56 " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
     57 " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
     58 " * See the License for the specific language governing permissions and\n"
     59 " * limitations under the License.\n"
     60 " */\n"
     61 "\n";
     62 
     63 
     64 RSReflectionBase::RSReflectionBase(const RSContext *con)
     65   : mVerbose(true) {
     66   mRSContext = con;
     67   mLicenseNote = gApacheLicenseNote;
     68 
     69 }
     70 
     71 RSReflectionBase::~RSReflectionBase() {
     72 
     73 }
     74 
     75 /*
     76 bool RSReflectionBase::openFile(const string &name, string &errorMsg) {
     77     if(!mUseStdout) {
     78         mOF.clear();
     79         if(!SlangUtils::CreateDirectoryWithParents(mOutputPath, &errorMsg)) {
     80             return false;
     81         }
     82 
     83         string cf(mOutputPath + OS_PATH_SEPARATOR_STR + name);
     84         mOF.open(cf.c_str());
     85         if(!mOF.good()) {
     86             errorMsg = "failed to open file '" + cf + "' for write";
     87             return false;
     88         }
     89     }
     90     return true;
     91 }
     92 */
     93 
     94 void RSReflectionBase::startFile(const string &filename) {
     95   if(mVerbose) {
     96     printf("Generating %s\n", filename.c_str());
     97   }
     98 
     99   // License
    100   write(mLicenseNote);
    101 
    102   // Notice of generated file
    103   write("/*");
    104   write(" * This file is auto-generated. DO NOT MODIFY!");
    105   write(" * The source Renderscript file: " + mInputFileName);
    106   write(" */");
    107   write("");
    108 }
    109 
    110 // remove path plus .rs from filename to generate class name
    111 string RSReflectionBase::stripRS(const string &s) const {
    112   string tmp(s);
    113   size_t pos = tmp.rfind(".rs");
    114   if(pos != string::npos) {
    115     tmp.erase(pos);
    116   }
    117   pos = tmp.rfind("/");
    118   if (pos != string::npos) {
    119     tmp.erase(0, pos+1);
    120   }
    121   return tmp;
    122 }
    123 
    124 void RSReflectionBase::write(const std::string &t) {
    125   //printf("%s%s\n", mIndent.c_str(), t.c_str());
    126   mText.push_back(mIndent + t);
    127 }
    128 
    129 void RSReflectionBase::write(const std::stringstream &t) {
    130   mText.push_back(mIndent + t.str());
    131 }
    132 
    133 
    134 void RSReflectionBase::incIndent() {
    135   mIndent.append("    ");
    136 }
    137 
    138 void RSReflectionBase::decIndent() {
    139   mIndent.erase(0, 4);
    140 }
    141 
    142 bool RSReflectionBase::writeFile(const string &filename, const vector< string > &txt) {
    143   FILE *pfin = fopen((mOutputPath + filename).c_str(), "wt");
    144   if (pfin == NULL) {
    145     fprintf(stderr, "Error: could not write file %s\n", filename.c_str());
    146     return false;
    147   }
    148 
    149   for(size_t ct=0; ct < txt.size(); ct++) {
    150     fprintf(pfin, "%s\n", txt[ct].c_str());
    151   }
    152   fclose(pfin);
    153   return true;
    154 }
    155 
    156 
    157 string RSReflectionBase::genInitValue(const clang::APValue &Val, bool asBool) {
    158   stringstream tmp;
    159   switch (Val.getKind()) {
    160     case clang::APValue::Int: {
    161       llvm::APInt api = Val.getInt();
    162       if(asBool) {
    163         tmp << ((api.getSExtValue() == 0) ? "false" : "true");
    164       } else {
    165         // TODO: Handle unsigned possibly for C++ API.
    166         tmp << api.getSExtValue();
    167         if (api.getBitWidth() > 32) {
    168           tmp << "L";
    169         }
    170       }
    171       break;
    172     }
    173 
    174     case clang::APValue::Float: {
    175       llvm::APFloat apf = Val.getFloat();
    176       llvm::SmallString<30> s;
    177       apf.toString(s);
    178       tmp << s.c_str();
    179       if (&apf.getSemantics() == &llvm::APFloat::IEEEsingle) {
    180         if (s.count('.') == 0) {
    181           tmp << ".f";
    182         } else {
    183           tmp << "f";
    184         }
    185       }
    186       break;
    187     }
    188 
    189     case clang::APValue::ComplexInt:
    190     case clang::APValue::ComplexFloat:
    191     case clang::APValue::LValue:
    192     case clang::APValue::Vector: {
    193       slangAssert(false && "Primitive type cannot have such kind of initializer");
    194       break;
    195     }
    196 
    197     default: {
    198       slangAssert(false && "Unknown kind of initializer");
    199     }
    200   }
    201   return tmp.str();
    202 }
    203 
    204 bool RSReflectionBase::addTypeNameForElement(
    205     const std::string &TypeName) {
    206   if (mTypesToCheck.find(TypeName) == mTypesToCheck.end()) {
    207     mTypesToCheck.insert(TypeName);
    208     return true;
    209   } else {
    210     return false;
    211   }
    212 }
    213 
    214 const char *RSReflectionBase::getVectorAccessor(unsigned Index) {
    215   static const char *VectorAccessorMap[] = {
    216     /* 0 */ "x",
    217     /* 1 */ "y",
    218     /* 2 */ "z",
    219     /* 3 */ "w",
    220   };
    221 
    222   slangAssert((Index < (sizeof(VectorAccessorMap) / sizeof(const char*))) &&
    223               "Out-of-bound index to access vector member");
    224 
    225   return VectorAccessorMap[Index];
    226 }
    227 
    228 }
    229