Specification.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. /*
  2. * Copyright (C) 2013 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. #include <stdio.h>
  17. #include <cctype>
  18. #include <cstdlib>
  19. #include <fstream>
  20. #include <functional>
  21. #include <iostream>
  22. #include <memory>
  23. #include <sstream>
  24. #include <strings.h>
  25. #include "Generator.h"
  26. #include "Scanner.h"
  27. #include "Specification.h"
  28. #include "Utilities.h"
  29. using namespace std;
  30. // API level when RenderScript was added.
  31. const unsigned int MIN_API_LEVEL = 9;
  32. const NumericalType TYPES[] = {
  33. {"f16", "FLOAT_16", "half", "short", FLOATING_POINT, 11, 5},
  34. {"f32", "FLOAT_32", "float", "float", FLOATING_POINT, 24, 8},
  35. {"f64", "FLOAT_64", "double", "double", FLOATING_POINT, 53, 11},
  36. {"i8", "SIGNED_8", "char", "byte", SIGNED_INTEGER, 7, 0},
  37. {"u8", "UNSIGNED_8", "uchar", "byte", UNSIGNED_INTEGER, 8, 0},
  38. {"i16", "SIGNED_16", "short", "short", SIGNED_INTEGER, 15, 0},
  39. {"u16", "UNSIGNED_16", "ushort", "short", UNSIGNED_INTEGER, 16, 0},
  40. {"i32", "SIGNED_32", "int", "int", SIGNED_INTEGER, 31, 0},
  41. {"u32", "UNSIGNED_32", "uint", "int", UNSIGNED_INTEGER, 32, 0},
  42. {"i64", "SIGNED_64", "long", "long", SIGNED_INTEGER, 63, 0},
  43. {"u64", "UNSIGNED_64", "ulong", "long", UNSIGNED_INTEGER, 64, 0},
  44. };
  45. const int NUM_TYPES = sizeof(TYPES) / sizeof(TYPES[0]);
  46. static const char kTagUnreleased[] = "UNRELEASED";
  47. // Patterns that get substituted with C type or RS Data type names in function
  48. // names, arguments, return types, and inlines.
  49. static const string kCTypePatterns[] = {"#1", "#2", "#3", "#4"};
  50. static const string kRSTypePatterns[] = {"#RST_1", "#RST_2", "#RST_3", "#RST_4"};
  51. // The singleton of the collected information of all the spec files.
  52. SystemSpecification systemSpecification;
  53. // Returns the index in TYPES for the provided cType
  54. static int findCType(const string& cType) {
  55. for (int i = 0; i < NUM_TYPES; i++) {
  56. if (cType == TYPES[i].cType) {
  57. return i;
  58. }
  59. }
  60. return -1;
  61. }
  62. /* Converts a string like "u8, u16" to a vector of "ushort", "uint".
  63. * For non-numerical types, we don't need to convert the abbreviation.
  64. */
  65. static vector<string> convertToTypeVector(const string& input) {
  66. // First convert the string to an array of strings.
  67. vector<string> entries;
  68. stringstream stream(input);
  69. string entry;
  70. while (getline(stream, entry, ',')) {
  71. trimSpaces(&entry);
  72. entries.push_back(entry);
  73. }
  74. /* Second, we look for present numerical types. We do it this way
  75. * so the order of numerical types is always the same, no matter
  76. * how specified in the spec file.
  77. */
  78. vector<string> result;
  79. for (auto t : TYPES) {
  80. for (auto i = entries.begin(); i != entries.end(); ++i) {
  81. if (*i == t.specType) {
  82. result.push_back(t.cType);
  83. entries.erase(i);
  84. break;
  85. }
  86. }
  87. }
  88. // Add the remaining; they are not numerical types.
  89. for (auto s : entries) {
  90. result.push_back(s);
  91. }
  92. return result;
  93. }
  94. // Returns true if each entry in typeVector is an RS numerical type
  95. static bool isRSTValid(const vector<string> &typeVector) {
  96. for (auto type: typeVector) {
  97. if (findCType(type) == -1)
  98. return false;
  99. }
  100. return true;
  101. }
  102. void getVectorSizeAndBaseType(const string& type, string& vectorSize, string& baseType) {
  103. vectorSize = "1";
  104. baseType = type;
  105. /* If it's a vector type, we need to split the base type from the size.
  106. * We know that's it's a vector type if the last character is a digit and
  107. * the rest is an actual base type. We used to only verify the first part,
  108. * which created a problem with rs_matrix2x2.
  109. */
  110. const int last = type.size() - 1;
  111. const char lastChar = type[last];
  112. if (lastChar >= '0' && lastChar <= '9') {
  113. const string trimmed = type.substr(0, last);
  114. int i = findCType(trimmed);
  115. if (i >= 0) {
  116. baseType = trimmed;
  117. vectorSize = lastChar;
  118. }
  119. }
  120. }
  121. void ParameterDefinition::parseParameterDefinition(const string& type, const string& name,
  122. const string& testOption, int lineNumber,
  123. bool isReturn, Scanner* scanner) {
  124. rsType = type;
  125. specName = name;
  126. // Determine if this is an output.
  127. isOutParameter = isReturn || charRemoved('*', &rsType);
  128. getVectorSizeAndBaseType(rsType, mVectorSize, rsBaseType);
  129. typeIndex = findCType(rsBaseType);
  130. if (mVectorSize == "3") {
  131. vectorWidth = "4";
  132. } else {
  133. vectorWidth = mVectorSize;
  134. }
  135. /* Create variable names to be used in the java and .rs files. Because x and
  136. * y are reserved in .rs files, we prefix variable names with "in" or "out".
  137. */
  138. if (isOutParameter) {
  139. variableName = "out";
  140. if (!specName.empty()) {
  141. variableName += capitalize(specName);
  142. } else if (!isReturn) {
  143. scanner->error(lineNumber) << "Should have a name.\n";
  144. }
  145. doubleVariableName = variableName + "Double";
  146. } else {
  147. variableName = "in";
  148. if (specName.empty()) {
  149. scanner->error(lineNumber) << "Should have a name.\n";
  150. }
  151. variableName += capitalize(specName);
  152. doubleVariableName = variableName + "Double";
  153. }
  154. rsAllocName = "gAlloc" + capitalize(variableName);
  155. javaAllocName = variableName;
  156. javaArrayName = "array" + capitalize(javaAllocName);
  157. // Process the option.
  158. undefinedIfOutIsNan = false;
  159. compatibleTypeIndex = -1;
  160. if (!testOption.empty()) {
  161. if (testOption.compare(0, 6, "range(") == 0) {
  162. size_t pComma = testOption.find(',');
  163. size_t pParen = testOption.find(')');
  164. if (pComma == string::npos || pParen == string::npos) {
  165. scanner->error(lineNumber) << "Incorrect range " << testOption << "\n";
  166. } else {
  167. minValue = testOption.substr(6, pComma - 6);
  168. maxValue = testOption.substr(pComma + 1, pParen - pComma - 1);
  169. }
  170. } else if (testOption.compare(0, 6, "above(") == 0) {
  171. size_t pParen = testOption.find(')');
  172. if (pParen == string::npos) {
  173. scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
  174. } else {
  175. smallerParameter = testOption.substr(6, pParen - 6);
  176. }
  177. } else if (testOption.compare(0, 11, "compatible(") == 0) {
  178. size_t pParen = testOption.find(')');
  179. if (pParen == string::npos) {
  180. scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
  181. } else {
  182. compatibleTypeIndex = findCType(testOption.substr(11, pParen - 11));
  183. }
  184. } else if (testOption.compare(0, 11, "conditional") == 0) {
  185. undefinedIfOutIsNan = true;
  186. } else {
  187. scanner->error(lineNumber) << "Unrecognized testOption " << testOption << "\n";
  188. }
  189. }
  190. isFloatType = false;
  191. if (typeIndex >= 0) {
  192. javaBaseType = TYPES[typeIndex].javaType;
  193. specType = TYPES[typeIndex].specType;
  194. isFloatType = TYPES[typeIndex].exponentBits > 0;
  195. }
  196. if (!minValue.empty()) {
  197. if (typeIndex < 0 || TYPES[typeIndex].kind != FLOATING_POINT) {
  198. scanner->error(lineNumber) << "range(,) is only supported for floating point\n";
  199. }
  200. }
  201. }
  202. bool VersionInfo::scan(Scanner* scanner, unsigned int maxApiLevel) {
  203. if (scanner->findOptionalTag("version:")) {
  204. const string s = scanner->getValue();
  205. if (s.compare(0, sizeof(kTagUnreleased), kTagUnreleased) == 0) {
  206. // The API is still under development and does not have
  207. // an official version number.
  208. minVersion = maxVersion = kUnreleasedVersion;
  209. } else {
  210. sscanf(s.c_str(), "%u %u", &minVersion, &maxVersion);
  211. if (minVersion && minVersion < MIN_API_LEVEL) {
  212. scanner->error() << "Minimum version must >= 9\n";
  213. }
  214. if (minVersion == MIN_API_LEVEL) {
  215. minVersion = 0;
  216. }
  217. if (maxVersion && maxVersion < MIN_API_LEVEL) {
  218. scanner->error() << "Maximum version must >= 9\n";
  219. }
  220. }
  221. }
  222. if (scanner->findOptionalTag("size:")) {
  223. sscanf(scanner->getValue().c_str(), "%i", &intSize);
  224. }
  225. if (maxVersion > maxApiLevel) {
  226. maxVersion = maxApiLevel;
  227. }
  228. return minVersion == 0 || minVersion <= maxApiLevel;
  229. }
  230. Definition::Definition(const std::string& name)
  231. : mName(name), mDeprecatedApiLevel(0), mHidden(false), mFinalVersion(-1) {
  232. }
  233. void Definition::updateFinalVersion(const VersionInfo& info) {
  234. /* We set it if:
  235. * - We have never set mFinalVersion before, or
  236. * - The max version is 0, which means we have not expired this API, or
  237. * - We have a max that's later than what we currently have.
  238. */
  239. if (mFinalVersion < 0 || info.maxVersion == 0 ||
  240. (mFinalVersion > 0 &&
  241. static_cast<int>(info.maxVersion) > mFinalVersion)) {
  242. mFinalVersion = info.maxVersion;
  243. }
  244. }
  245. void Definition::scanDocumentationTags(Scanner* scanner, bool firstOccurence,
  246. const SpecFile* specFile) {
  247. if (scanner->findOptionalTag("hidden:")) {
  248. scanner->checkNoValue();
  249. mHidden = true;
  250. }
  251. if (scanner->findOptionalTag("deprecated:")) {
  252. string value = scanner->getValue();
  253. size_t pComma = value.find(", ");
  254. if (pComma != string::npos) {
  255. mDeprecatedMessage = value.substr(pComma + 2);
  256. value.erase(pComma);
  257. }
  258. sscanf(value.c_str(), "%i", &mDeprecatedApiLevel);
  259. if (mDeprecatedApiLevel <= 0) {
  260. scanner->error() << "deprecated entries should have a level > 0\n";
  261. }
  262. }
  263. if (firstOccurence) {
  264. if (scanner->findTag("summary:")) {
  265. mSummary = scanner->getValue();
  266. }
  267. if (scanner->findTag("description:")) {
  268. scanner->checkNoValue();
  269. while (scanner->findOptionalTag("")) {
  270. mDescription.push_back(scanner->getValue());
  271. }
  272. }
  273. mUrl = specFile->getDetailedDocumentationUrl() + "#android_rs:" + mName;
  274. } else if (scanner->findOptionalTag("summary:")) {
  275. scanner->error() << "Only the first specification should have a summary.\n";
  276. }
  277. }
  278. Constant::~Constant() {
  279. for (auto i : mSpecifications) {
  280. delete i;
  281. }
  282. }
  283. Type::~Type() {
  284. for (auto i : mSpecifications) {
  285. delete i;
  286. }
  287. }
  288. Function::Function(const string& name) : Definition(name) {
  289. mCapitalizedName = capitalize(mName);
  290. }
  291. Function::~Function() {
  292. for (auto i : mSpecifications) {
  293. delete i;
  294. }
  295. }
  296. bool Function::someParametersAreDocumented() const {
  297. for (auto p : mParameters) {
  298. if (!p->documentation.empty()) {
  299. return true;
  300. }
  301. }
  302. return false;
  303. }
  304. void Function::addParameter(ParameterEntry* entry, Scanner* scanner) {
  305. for (auto i : mParameters) {
  306. if (i->name == entry->name) {
  307. // It's a duplicate.
  308. if (!entry->documentation.empty()) {
  309. scanner->error(entry->lineNumber)
  310. << "Only the first occurence of an arg should have the "
  311. "documentation.\n";
  312. }
  313. return;
  314. }
  315. }
  316. mParameters.push_back(entry);
  317. }
  318. void Function::addReturn(ParameterEntry* entry, Scanner* scanner) {
  319. if (entry->documentation.empty()) {
  320. return;
  321. }
  322. if (!mReturnDocumentation.empty()) {
  323. scanner->error() << "ret: should be documented only for the first variant\n";
  324. }
  325. mReturnDocumentation = entry->documentation;
  326. }
  327. void ConstantSpecification::scanConstantSpecification(Scanner* scanner, SpecFile* specFile,
  328. unsigned int maxApiLevel) {
  329. string name = scanner->getValue();
  330. VersionInfo info;
  331. if (!info.scan(scanner, maxApiLevel)) {
  332. cout << "Skipping some " << name << " definitions.\n";
  333. scanner->skipUntilTag("end:");
  334. return;
  335. }
  336. bool created = false;
  337. Constant* constant = systemSpecification.findOrCreateConstant(name, &created);
  338. ConstantSpecification* spec = new ConstantSpecification(constant);
  339. constant->addSpecification(spec);
  340. constant->updateFinalVersion(info);
  341. specFile->addConstantSpecification(spec, created);
  342. spec->mVersionInfo = info;
  343. if (scanner->findTag("value:")) {
  344. spec->mValue = scanner->getValue();
  345. }
  346. if (scanner->findTag("type:")) {
  347. spec->mType = scanner->getValue();
  348. }
  349. constant->scanDocumentationTags(scanner, created, specFile);
  350. scanner->findTag("end:");
  351. }
  352. void TypeSpecification::scanTypeSpecification(Scanner* scanner, SpecFile* specFile,
  353. unsigned int maxApiLevel) {
  354. string name = scanner->getValue();
  355. VersionInfo info;
  356. if (!info.scan(scanner, maxApiLevel)) {
  357. cout << "Skipping some " << name << " definitions.\n";
  358. scanner->skipUntilTag("end:");
  359. return;
  360. }
  361. bool created = false;
  362. Type* type = systemSpecification.findOrCreateType(name, &created);
  363. TypeSpecification* spec = new TypeSpecification(type);
  364. type->addSpecification(spec);
  365. type->updateFinalVersion(info);
  366. specFile->addTypeSpecification(spec, created);
  367. spec->mVersionInfo = info;
  368. if (scanner->findOptionalTag("simple:")) {
  369. spec->mKind = SIMPLE;
  370. spec->mSimpleType = scanner->getValue();
  371. }
  372. if (scanner->findOptionalTag("rs_object:")) {
  373. spec->mKind = RS_OBJECT;
  374. }
  375. if (scanner->findOptionalTag("struct:")) {
  376. spec->mKind = STRUCT;
  377. spec->mStructName = scanner->getValue();
  378. while (scanner->findOptionalTag("field:")) {
  379. string s = scanner->getValue();
  380. string comment;
  381. scanner->parseDocumentation(&s, &comment);
  382. spec->mFields.push_back(s);
  383. spec->mFieldComments.push_back(comment);
  384. }
  385. }
  386. if (scanner->findOptionalTag("enum:")) {
  387. spec->mKind = ENUM;
  388. spec->mEnumName = scanner->getValue();
  389. while (scanner->findOptionalTag("value:")) {
  390. string s = scanner->getValue();
  391. string comment;
  392. scanner->parseDocumentation(&s, &comment);
  393. spec->mValues.push_back(s);
  394. spec->mValueComments.push_back(comment);
  395. }
  396. }
  397. if (scanner->findOptionalTag("attrib:")) {
  398. spec->mAttribute = scanner->getValue();
  399. }
  400. type->scanDocumentationTags(scanner, created, specFile);
  401. scanner->findTag("end:");
  402. }
  403. FunctionSpecification::~FunctionSpecification() {
  404. for (auto i : mParameters) {
  405. delete i;
  406. }
  407. delete mReturn;
  408. for (auto i : mPermutations) {
  409. delete i;
  410. }
  411. }
  412. string FunctionSpecification::expandRSTypeInString(const string &s,
  413. const string &pattern,
  414. const string &cTypeStr) const {
  415. // Find index of numerical type corresponding to cTypeStr. The case where
  416. // pattern is found in s but cTypeStr is not a numerical type is checked in
  417. // checkRSTPatternValidity.
  418. int typeIdx = findCType(cTypeStr);
  419. if (typeIdx == -1) {
  420. return s;
  421. }
  422. // If index exists, perform replacement.
  423. return stringReplace(s, pattern, TYPES[typeIdx].rsDataType);
  424. }
  425. string FunctionSpecification::expandString(string s,
  426. int replacementIndexes[MAX_REPLACEABLES]) const {
  427. for (unsigned idx = 0; idx < mReplaceables.size(); idx ++) {
  428. string toString = mReplaceables[idx][replacementIndexes[idx]];
  429. // replace #RST_i patterns with RS datatype corresponding to toString
  430. s = expandRSTypeInString(s, kRSTypePatterns[idx], toString);
  431. // replace #i patterns with C type from mReplaceables
  432. s = stringReplace(s, kCTypePatterns[idx], toString);
  433. }
  434. return s;
  435. }
  436. void FunctionSpecification::expandStringVector(const vector<string>& in,
  437. int replacementIndexes[MAX_REPLACEABLES],
  438. vector<string>* out) const {
  439. out->clear();
  440. for (vector<string>::const_iterator iter = in.begin(); iter != in.end(); iter++) {
  441. out->push_back(expandString(*iter, replacementIndexes));
  442. }
  443. }
  444. void FunctionSpecification::createPermutations(Function* function, Scanner* scanner) {
  445. int start[MAX_REPLACEABLES];
  446. int end[MAX_REPLACEABLES];
  447. for (int i = 0; i < MAX_REPLACEABLES; i++) {
  448. if (i < (int)mReplaceables.size()) {
  449. start[i] = 0;
  450. end[i] = mReplaceables[i].size();
  451. } else {
  452. start[i] = -1;
  453. end[i] = 0;
  454. }
  455. }
  456. int replacementIndexes[MAX_REPLACEABLES];
  457. // TODO: These loops assume that MAX_REPLACEABLES is 4.
  458. for (replacementIndexes[3] = start[3]; replacementIndexes[3] < end[3];
  459. replacementIndexes[3]++) {
  460. for (replacementIndexes[2] = start[2]; replacementIndexes[2] < end[2];
  461. replacementIndexes[2]++) {
  462. for (replacementIndexes[1] = start[1]; replacementIndexes[1] < end[1];
  463. replacementIndexes[1]++) {
  464. for (replacementIndexes[0] = start[0]; replacementIndexes[0] < end[0];
  465. replacementIndexes[0]++) {
  466. auto p = new FunctionPermutation(function, this, replacementIndexes, scanner);
  467. mPermutations.push_back(p);
  468. }
  469. }
  470. }
  471. }
  472. }
  473. string FunctionSpecification::getName(int replacementIndexes[MAX_REPLACEABLES]) const {
  474. return expandString(mUnexpandedName, replacementIndexes);
  475. }
  476. void FunctionSpecification::getReturn(int replacementIndexes[MAX_REPLACEABLES],
  477. std::string* retType, int* lineNumber) const {
  478. *retType = expandString(mReturn->type, replacementIndexes);
  479. *lineNumber = mReturn->lineNumber;
  480. }
  481. void FunctionSpecification::getParam(size_t index, int replacementIndexes[MAX_REPLACEABLES],
  482. std::string* type, std::string* name, std::string* testOption,
  483. int* lineNumber) const {
  484. ParameterEntry* p = mParameters[index];
  485. *type = expandString(p->type, replacementIndexes);
  486. *name = p->name;
  487. *testOption = expandString(p->testOption, replacementIndexes);
  488. *lineNumber = p->lineNumber;
  489. }
  490. void FunctionSpecification::getInlines(int replacementIndexes[MAX_REPLACEABLES],
  491. std::vector<std::string>* inlines) const {
  492. expandStringVector(mInline, replacementIndexes, inlines);
  493. }
  494. void FunctionSpecification::parseTest(Scanner* scanner) {
  495. const string value = scanner->getValue();
  496. if (value == "scalar" || value == "vector" || value == "noverify" || value == "custom" ||
  497. value == "none") {
  498. mTest = value;
  499. } else if (value.compare(0, 7, "limited") == 0) {
  500. mTest = "limited";
  501. if (value.compare(7, 1, "(") == 0) {
  502. size_t pParen = value.find(')');
  503. if (pParen == string::npos) {
  504. scanner->error() << "Incorrect test: \"" << value << "\"\n";
  505. } else {
  506. mPrecisionLimit = value.substr(8, pParen - 8);
  507. }
  508. }
  509. } else {
  510. scanner->error() << "Unrecognized test option: \"" << value << "\"\n";
  511. }
  512. }
  513. bool FunctionSpecification::hasTests(unsigned int versionOfTestFiles) const {
  514. if (mVersionInfo.maxVersion != 0 && mVersionInfo.maxVersion < versionOfTestFiles) {
  515. return false;
  516. }
  517. if (mTest == "none") {
  518. return false;
  519. }
  520. return true;
  521. }
  522. void FunctionSpecification::checkRSTPatternValidity(const string &inlineStr, bool allow,
  523. Scanner *scanner) {
  524. for (int i = 0; i < MAX_REPLACEABLES; i ++) {
  525. bool patternFound = inlineStr.find(kRSTypePatterns[i]) != string::npos;
  526. if (patternFound) {
  527. if (!allow) {
  528. scanner->error() << "RST_i pattern not allowed here\n";
  529. }
  530. else if (mIsRSTAllowed[i] == false) {
  531. scanner->error() << "Found pattern \"" << kRSTypePatterns[i]
  532. << "\" in spec. But some entry in the corresponding"
  533. << " parameter list cannot be translated to an RS type\n";
  534. }
  535. }
  536. }
  537. }
  538. void FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile* specFile,
  539. unsigned int maxApiLevel) {
  540. // Some functions like convert have # part of the name. Truncate at that point.
  541. const string& unexpandedName = scanner->getValue();
  542. string name = unexpandedName;
  543. size_t p = name.find('#');
  544. if (p != string::npos) {
  545. if (p > 0 && name[p - 1] == '_') {
  546. p--;
  547. }
  548. name.erase(p);
  549. }
  550. VersionInfo info;
  551. if (!info.scan(scanner, maxApiLevel)) {
  552. cout << "Skipping some " << name << " definitions.\n";
  553. scanner->skipUntilTag("end:");
  554. return;
  555. }
  556. bool created = false;
  557. Function* function = systemSpecification.findOrCreateFunction(name, &created);
  558. FunctionSpecification* spec = new FunctionSpecification(function);
  559. function->addSpecification(spec);
  560. function->updateFinalVersion(info);
  561. specFile->addFunctionSpecification(spec, created);
  562. spec->mUnexpandedName = unexpandedName;
  563. spec->mTest = "scalar"; // default
  564. spec->mVersionInfo = info;
  565. if (scanner->findOptionalTag("internal:")) {
  566. spec->mInternal = (scanner->getValue() == "true");
  567. }
  568. if (scanner->findOptionalTag("intrinsic:")) {
  569. spec->mIntrinsic = (scanner->getValue() == "true");
  570. }
  571. if (scanner->findOptionalTag("attrib:")) {
  572. spec->mAttribute = scanner->getValue();
  573. }
  574. if (scanner->findOptionalTag("w:")) {
  575. vector<string> t;
  576. if (scanner->getValue().find("1") != string::npos) {
  577. t.push_back("");
  578. }
  579. if (scanner->getValue().find("2") != string::npos) {
  580. t.push_back("2");
  581. }
  582. if (scanner->getValue().find("3") != string::npos) {
  583. t.push_back("3");
  584. }
  585. if (scanner->getValue().find("4") != string::npos) {
  586. t.push_back("4");
  587. }
  588. spec->mReplaceables.push_back(t);
  589. // RST_i pattern not applicable for width.
  590. spec->mIsRSTAllowed.push_back(false);
  591. }
  592. while (scanner->findOptionalTag("t:")) {
  593. spec->mReplaceables.push_back(convertToTypeVector(scanner->getValue()));
  594. spec->mIsRSTAllowed.push_back(isRSTValid(spec->mReplaceables.back()));
  595. }
  596. // Disallow RST_* pattern in function name
  597. // FIXME the line number for this error would be wrong
  598. spec->checkRSTPatternValidity(unexpandedName, false, scanner);
  599. if (scanner->findTag("ret:")) {
  600. ParameterEntry* p = scanner->parseArgString(true);
  601. function->addReturn(p, scanner);
  602. spec->mReturn = p;
  603. // Disallow RST_* pattern in return type
  604. spec->checkRSTPatternValidity(p->type, false, scanner);
  605. }
  606. while (scanner->findOptionalTag("arg:")) {
  607. ParameterEntry* p = scanner->parseArgString(false);
  608. function->addParameter(p, scanner);
  609. spec->mParameters.push_back(p);
  610. // Disallow RST_* pattern in parameter type or testOption
  611. spec->checkRSTPatternValidity(p->type, false, scanner);
  612. spec->checkRSTPatternValidity(p->testOption, false, scanner);
  613. }
  614. function->scanDocumentationTags(scanner, created, specFile);
  615. if (scanner->findOptionalTag("inline:")) {
  616. scanner->checkNoValue();
  617. while (scanner->findOptionalTag("")) {
  618. spec->mInline.push_back(scanner->getValue());
  619. // Allow RST_* pattern in inline definitions
  620. spec->checkRSTPatternValidity(spec->mInline.back(), true, scanner);
  621. }
  622. }
  623. if (scanner->findOptionalTag("test:")) {
  624. spec->parseTest(scanner);
  625. }
  626. scanner->findTag("end:");
  627. spec->createPermutations(function, scanner);
  628. }
  629. FunctionPermutation::FunctionPermutation(Function* func, FunctionSpecification* spec,
  630. int replacementIndexes[MAX_REPLACEABLES], Scanner* scanner)
  631. : mReturn(nullptr), mInputCount(0), mOutputCount(0) {
  632. // We expand the strings now to make capitalization easier. The previous code preserved
  633. // the #n
  634. // markers just before emitting, which made capitalization difficult.
  635. mName = spec->getName(replacementIndexes);
  636. mNameTrunk = func->getName();
  637. mTest = spec->getTest();
  638. mPrecisionLimit = spec->getPrecisionLimit();
  639. spec->getInlines(replacementIndexes, &mInline);
  640. mHasFloatAnswers = false;
  641. for (size_t i = 0; i < spec->getNumberOfParams(); i++) {
  642. string type, name, testOption;
  643. int lineNumber = 0;
  644. spec->getParam(i, replacementIndexes, &type, &name, &testOption, &lineNumber);
  645. ParameterDefinition* def = new ParameterDefinition();
  646. def->parseParameterDefinition(type, name, testOption, lineNumber, false, scanner);
  647. if (def->isOutParameter) {
  648. mOutputCount++;
  649. } else {
  650. mInputCount++;
  651. }
  652. if (def->typeIndex < 0 && mTest != "none") {
  653. scanner->error(lineNumber)
  654. << "Could not find " << def->rsBaseType
  655. << " while generating automated tests. Use test: none if not needed.\n";
  656. }
  657. if (def->isOutParameter && def->isFloatType) {
  658. mHasFloatAnswers = true;
  659. }
  660. mParams.push_back(def);
  661. }
  662. string retType;
  663. int lineNumber = 0;
  664. spec->getReturn(replacementIndexes, &retType, &lineNumber);
  665. if (!retType.empty()) {
  666. mReturn = new ParameterDefinition();
  667. mReturn->parseParameterDefinition(retType, "", "", lineNumber, true, scanner);
  668. if (mReturn->isFloatType) {
  669. mHasFloatAnswers = true;
  670. }
  671. mOutputCount++;
  672. }
  673. }
  674. FunctionPermutation::~FunctionPermutation() {
  675. for (auto i : mParams) {
  676. delete i;
  677. }
  678. delete mReturn;
  679. }
  680. SpecFile::SpecFile(const string& specFileName) : mSpecFileName(specFileName) {
  681. string core = mSpecFileName;
  682. // Remove .spec
  683. size_t l = core.length();
  684. const char SPEC[] = ".spec";
  685. const int SPEC_SIZE = sizeof(SPEC) - 1;
  686. const int start = l - SPEC_SIZE;
  687. if (start >= 0 && core.compare(start, SPEC_SIZE, SPEC) == 0) {
  688. core.erase(start);
  689. }
  690. // The header file name should have the same base but with a ".rsh" extension.
  691. mHeaderFileName = core + ".rsh";
  692. mDetailedDocumentationUrl = core + ".html";
  693. }
  694. void SpecFile::addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation) {
  695. mConstantSpecificationsList.push_back(spec);
  696. if (hasDocumentation) {
  697. Constant* constant = spec->getConstant();
  698. mDocumentedConstants.insert(pair<string, Constant*>(constant->getName(), constant));
  699. }
  700. }
  701. void SpecFile::addTypeSpecification(TypeSpecification* spec, bool hasDocumentation) {
  702. mTypeSpecificationsList.push_back(spec);
  703. if (hasDocumentation) {
  704. Type* type = spec->getType();
  705. mDocumentedTypes.insert(pair<string, Type*>(type->getName(), type));
  706. }
  707. }
  708. void SpecFile::addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation) {
  709. mFunctionSpecificationsList.push_back(spec);
  710. if (hasDocumentation) {
  711. Function* function = spec->getFunction();
  712. mDocumentedFunctions.insert(pair<string, Function*>(function->getName(), function));
  713. }
  714. }
  715. // Read the specification, adding the definitions to the global functions map.
  716. bool SpecFile::readSpecFile(unsigned int maxApiLevel) {
  717. FILE* specFile = fopen(mSpecFileName.c_str(), "rte");
  718. if (!specFile) {
  719. cerr << "Error opening input file: " << mSpecFileName << "\n";
  720. return false;
  721. }
  722. Scanner scanner(mSpecFileName, specFile);
  723. // Scan the header that should start the file.
  724. scanner.skipBlankEntries();
  725. if (scanner.findTag("header:")) {
  726. if (scanner.findTag("summary:")) {
  727. mBriefDescription = scanner.getValue();
  728. }
  729. if (scanner.findTag("description:")) {
  730. scanner.checkNoValue();
  731. while (scanner.findOptionalTag("")) {
  732. mFullDescription.push_back(scanner.getValue());
  733. }
  734. }
  735. if (scanner.findOptionalTag("include:")) {
  736. scanner.checkNoValue();
  737. while (scanner.findOptionalTag("")) {
  738. mVerbatimInclude.push_back(scanner.getValue());
  739. }
  740. }
  741. scanner.findTag("end:");
  742. }
  743. while (1) {
  744. scanner.skipBlankEntries();
  745. if (scanner.atEnd()) {
  746. break;
  747. }
  748. const string tag = scanner.getNextTag();
  749. if (tag == "function:") {
  750. FunctionSpecification::scanFunctionSpecification(&scanner, this, maxApiLevel);
  751. } else if (tag == "type:") {
  752. TypeSpecification::scanTypeSpecification(&scanner, this, maxApiLevel);
  753. } else if (tag == "constant:") {
  754. ConstantSpecification::scanConstantSpecification(&scanner, this, maxApiLevel);
  755. } else {
  756. scanner.error() << "Expected function:, type:, or constant:. Found: " << tag << "\n";
  757. return false;
  758. }
  759. }
  760. fclose(specFile);
  761. return scanner.getErrorCount() == 0;
  762. }
  763. SystemSpecification::~SystemSpecification() {
  764. for (auto i : mConstants) {
  765. delete i.second;
  766. }
  767. for (auto i : mTypes) {
  768. delete i.second;
  769. }
  770. for (auto i : mFunctions) {
  771. delete i.second;
  772. }
  773. for (auto i : mSpecFiles) {
  774. delete i;
  775. }
  776. }
  777. // Returns the named entry in the map. Creates it if it's not there.
  778. template <class T>
  779. T* findOrCreate(const string& name, map<string, T*>* map, bool* created) {
  780. auto iter = map->find(name);
  781. if (iter != map->end()) {
  782. *created = false;
  783. return iter->second;
  784. }
  785. *created = true;
  786. T* f = new T(name);
  787. map->insert(pair<string, T*>(name, f));
  788. return f;
  789. }
  790. Constant* SystemSpecification::findOrCreateConstant(const string& name, bool* created) {
  791. return findOrCreate<Constant>(name, &mConstants, created);
  792. }
  793. Type* SystemSpecification::findOrCreateType(const string& name, bool* created) {
  794. return findOrCreate<Type>(name, &mTypes, created);
  795. }
  796. Function* SystemSpecification::findOrCreateFunction(const string& name, bool* created) {
  797. return findOrCreate<Function>(name, &mFunctions, created);
  798. }
  799. bool SystemSpecification::readSpecFile(const string& fileName, unsigned int maxApiLevel) {
  800. SpecFile* spec = new SpecFile(fileName);
  801. if (!spec->readSpecFile(maxApiLevel)) {
  802. cerr << fileName << ": Failed to parse.\n";
  803. return false;
  804. }
  805. mSpecFiles.push_back(spec);
  806. return true;
  807. }
  808. static void updateMaxApiLevel(const VersionInfo& info, unsigned int* maxApiLevel) {
  809. if (info.minVersion == VersionInfo::kUnreleasedVersion) {
  810. // Ignore development API level in consideration of max API level.
  811. return;
  812. }
  813. *maxApiLevel = max(*maxApiLevel, max(info.minVersion, info.maxVersion));
  814. }
  815. unsigned int SystemSpecification::getMaximumApiLevel() {
  816. unsigned int maxApiLevel = 0;
  817. for (auto i : mConstants) {
  818. for (auto j: i.second->getSpecifications()) {
  819. updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
  820. }
  821. }
  822. for (auto i : mTypes) {
  823. for (auto j: i.second->getSpecifications()) {
  824. updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
  825. }
  826. }
  827. for (auto i : mFunctions) {
  828. for (auto j: i.second->getSpecifications()) {
  829. updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
  830. }
  831. }
  832. return maxApiLevel;
  833. }
  834. bool SystemSpecification::generateFiles(unsigned int maxApiLevel) const {
  835. bool success = generateHeaderFiles("include") &&
  836. generateDocumentation("docs") &&
  837. generateTestFiles("test", maxApiLevel) &&
  838. generateStubsWhiteList("slangtest", maxApiLevel);
  839. if (success) {
  840. cout << "Successfully processed " << mTypes.size() << " types, " << mConstants.size()
  841. << " constants, and " << mFunctions.size() << " functions.\n";
  842. }
  843. return success;
  844. }
  845. string SystemSpecification::getHtmlAnchor(const string& name) const {
  846. Definition* d = nullptr;
  847. auto c = mConstants.find(name);
  848. if (c != mConstants.end()) {
  849. d = c->second;
  850. } else {
  851. auto t = mTypes.find(name);
  852. if (t != mTypes.end()) {
  853. d = t->second;
  854. } else {
  855. auto f = mFunctions.find(name);
  856. if (f != mFunctions.end()) {
  857. d = f->second;
  858. } else {
  859. return string();
  860. }
  861. }
  862. }
  863. ostringstream stream;
  864. stream << "<a href='" << d->getUrl() << "'>" << name << "</a>";
  865. return stream.str();
  866. }