1 /*
2 * Copyright (C) 2011 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 "TypeFactory.h"
17
18 #include "Parser.h"
19 #include "VarType.h"
20 #include "strUtils.h"
21
22 #include <map>
23 #include <string>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27
28
29 TypeFactory * TypeFactory::m_instance = NULL;
30
31 typedef std::map<std::string, VarType> TypeMap;
32 static TypeMap g_varMap;
33 static bool g_initialized = false;
34 static int g_typeId = 0;
35
36
37 #define ADD_TYPE(name, size, printformat,ispointer) \
38 g_varMap.insert(std::pair<std::string, VarType>(name, VarType(g_typeId++, name, (size + 7) >> 3, printformat , ispointer)));
39
initBaseTypes()40 void TypeFactory::initBaseTypes()
41 {
42 g_initialized = true;
43 ADD_TYPE("UNKNOWN", 0, "0x%x", false);
44 ADD_TYPE("void", 0, "0x%x", false);
45 ADD_TYPE("char", 8, "%c", false);
46 ADD_TYPE("int", 32, "%d", false);
47 ADD_TYPE("float", 32, "%d", false);
48 ADD_TYPE("short", 16, "%d", false);
49 }
50
initFromFile(const std::string & filename)51 int TypeFactory::initFromFile(const std::string &filename)
52 {
53 if (!g_initialized) {
54 initBaseTypes();
55 }
56
57 FILE *fp = fopen(filename.c_str(), "rt");
58 if (fp == NULL) {
59 perror(filename.c_str());
60 return -1;
61 }
62 char line[1000];
63 int lc = 0;
64 while(fgets(line, sizeof(line), fp) != NULL) {
65 lc++;
66 std::string str = trim(line);
67 if (str.size() == 0 || str.at(0) == '#') {
68 continue;
69 }
70 size_t pos = 0, last;
71 std::string name;
72 name = getNextToken(str, pos, &last, WHITESPACE);
73 name = normalizeTypeDeclaration(name);
74 if (name.size() == 0) {
75 fprintf(stderr, "Error: %d : missing type name\n", lc);
76 return -2;
77 }
78 pos = last + 1;
79 std::string size;
80 size = getNextToken(str, pos, &last, WHITESPACE);
81 if (size.size() == 0) {
82 fprintf(stderr, "Error: %d : missing type width\n", lc);
83 return -2;
84 }
85 pos = last + 1;
86 std::string printString;
87 printString = getNextToken(str, pos, &last, WHITESPACE);
88 if (printString.size() == 0) {
89 fprintf(stderr, "Error: %d : missing print-string\n", lc);
90 return -2;
91 }
92
93 // The ispointer definition is optional since we can just
94 // look at the type name, and determine it is a pointer if
95 // it ends with '*'.
96 bool isPointer = (name[name.size() - 1U] == '*');
97
98 pos = last + 1;
99 std::string pointerDef;
100 pointerDef = getNextToken(str, pos, &last, WHITESPACE);
101 if (pointerDef.size() != 0) {
102 // Just a little sanity check.
103 if (std::string("true")==pointerDef) {
104 if (!isPointer) {
105 fprintf(stderr, "Error: %d: invalid isPointer definition: 'true' but name does not end with '*'!\n", lc);
106 return -2;
107 }
108 } else if (std::string("false")==pointerDef) {
109 if (isPointer) {
110 fprintf(stderr, "Error: %d: invalid isPointer definition: 'false' but name does end with '*'!\n", lc);
111 return -2;
112 }
113 } else {
114 fprintf(stderr, "Error: %d : invalid isPointer definition, must be either \"true\" or \"false\"\n", lc);
115 return -2;
116 }
117 }
118
119 size_t bitSize = atoi(size.c_str());
120 size_t byteSize = (bitSize + 7) >> 3;
121
122 if (getVarTypeByName(name)->id() != 0) {
123 fprintf(stderr,
124 "Warining: %d : type %s is already known, definition in line %d is taken\n",
125 lc, name.c_str(), lc);
126 }
127 g_varMap.insert(std::pair<std::string, VarType>(
128 name, VarType(g_typeId++,
129 name,
130 byteSize,
131 printString,
132 isPointer)));
133 std::string constName = "const " + name;
134 g_varMap.insert(std::pair<std::string, VarType>(
135 constName, VarType(g_typeId++,
136 constName,
137 byteSize,
138 printString,
139 isPointer))); //add a const type
140 }
141 g_initialized = true;
142 return 0;
143 }
144
145
getVarTypeByName(const std::string & type)146 const VarType * TypeFactory::getVarTypeByName(const std::string & type)
147 {
148 if (!g_initialized) {
149 initBaseTypes();
150 }
151 TypeMap::iterator i = g_varMap.find(type);
152 if (i == g_varMap.end()) {
153 i = g_varMap.find("UNKNOWN");
154 }
155 return &(i->second);
156 }
157
158