| #include "ast.h" |
| |
| #include <android-base/strings.h> |
| #include <cstdarg> |
| #include <iostream> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <string> |
| |
| #include "hidl_language_y.h" |
| #include "logging.h" |
| #include "parser.h" |
| |
| #ifdef _WIN32 |
| int isatty(int fd) |
| { |
| return (fd == 0); |
| } |
| #endif |
| |
| using android::hidl::IoDelegate; |
| using android::base::Join; |
| using android::base::Split; |
| using std::cout; |
| using std::endl; |
| using std::string; |
| using std::unique_ptr; |
| |
| void yylex_init(void **); |
| void yylex_destroy(void *); |
| void yyset_in(FILE *f, void *); |
| int yyparse(Parser*); |
| YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *); |
| void yy_delete_buffer(YY_BUFFER_STATE, void *); |
| |
| |
| Parser *Thing::ps_; |
| Fields *Type::empty_fields_ = new Fields(); |
| |
| Thing::Thing() {} |
| Thing::Thing(string text) : text_(text) {} |
| void Thing::Dump() |
| { |
| std::cout << "Implement Dump for " |
| << TypeName() << endl; |
| } |
| |
| Const::Const(Element *name, Element *value) |
| : name_(name), |
| value_(value) |
| { |
| (void)name_; |
| (void)value_; |
| } |
| |
| void Const::Dump() |
| { |
| cout << "Const: " << name_->GetText() << " = " |
| << value_->GetText() << endl; |
| } |
| |
| Element::Element(const string& text, const string& comments, int Line) |
| : Thing(text), |
| comments_(comments), |
| line_(Line) |
| { |
| } |
| Element::Element(const string& text, int Line) |
| : Thing(text), |
| comments_(""), |
| line_(Line) |
| { |
| } |
| |
| CharElement::CharElement(const string& text, const string& comments, int line) |
| : Element(text, comments, line) |
| {} |
| |
| IntElement::IntElement(const string& text, const string& comments, int line) |
| : Element(text, comments, line) |
| {} |
| |
| NameElement::NameElement(const string& text, const string& comments, int line) |
| : Element(text, comments, line) |
| {} |
| |
| StringElement::StringElement(const string& text, int line) |
| : Element(text, "", line) |
| {} |
| |
| StringElement::StringElement(const string& text, const string& comments, int line) |
| : Element(text, comments, line) |
| {} |
| |
| CommentElement::CommentElement(const string& text, const string& comments, int line) |
| : Element(text, comments, line) |
| {} |
| |
| ErrorElement::ErrorElement(const string& text, const string& comments, int line) |
| : Element(text, comments, line) |
| {} |
| |
| void Element::Dump() |
| { |
| cout << "Element(" << ElementTypename() << "): " << GetText() << endl; |
| } |
| |
| bool NameElement::HasScalarValue() const { |
| return false; // TODO - look up name |
| } |
| bool NameElement::HasIntegerValue() const { |
| return false; // TODO |
| } |
| bool NameElement::IsDefinedType() const |
| { |
| return false; // TODO |
| } |
| long NameElement::GetIntegerValue() const |
| { |
| CHECK(false) << "TODO - find const"; |
| return 0; |
| } |
| long NameElement::GetScalarValue() const |
| { |
| CHECK(false) << "TODO - find const"; |
| return 0; |
| } |
| long Element::GetIntegerValue() const |
| { |
| CHECK(false) << "Bad type for GetIntegerValue: " |
| << ElementTypename(); |
| return 0; |
| } |
| void Element::AddDottedElement(Element *element) { |
| CHECK(false); // TODO |
| } |
| |
| BinaryExpression::BinaryExpression(Element *lhs, Element *rhs, const string& text, const string& comments, int Line) |
| : Element(text, comments, Line), |
| lhs_(lhs), |
| rhs_(rhs) |
| { |
| } |
| BinaryExpression::BinaryExpression(Element *lhs, Element *rhs, const string& text, int Line) |
| : Element(text, Line), |
| lhs_(lhs), |
| rhs_(rhs) |
| { |
| } |
| |
| UnaryExpression::UnaryExpression(Element *rhs, const string& text, const string& comments, int Line) |
| : Element(text, comments, Line), |
| rhs_(rhs) |
| { |
| } |
| UnaryExpression::UnaryExpression(Element *rhs, const string& text, int Line) |
| : Element(text, Line), |
| rhs_(rhs) |
| { |
| } |
| |
| ParenthesizedExpression::ParenthesizedExpression(Element *parenthesized, const string& text, const string& comments, int Line) |
| : Element(text, comments, Line), |
| parenthesized_(parenthesized) |
| { |
| } |
| ParenthesizedExpression::ParenthesizedExpression(Element *parenthesized, const string& text, int Line) |
| : Element(text, Line), |
| parenthesized_(parenthesized) |
| { |
| } |
| |
| CompoundType::CompoundType(Fields *fields) |
| : fields_(fields) |
| {} |
| |
| StructType::StructType(Fields *fields) |
| : CompoundType(fields) |
| {} |
| |
| EnumType::EnumType(Type *type, Fields *fields) |
| : CompoundType(fields), |
| type_(type) |
| {} |
| |
| UnionType::UnionType(Fields *fields) // Undiscriminated |
| : CompoundType(fields), |
| discriminator_(nullptr) |
| { |
| if (HasFixup()) { |
| ps_->Error("Undiscriminated union type cannot have fixups (TODO: Line number)"); |
| } |
| } |
| |
| UnionType::UnionType(Type* type, Fields *fields) // Discriminated |
| : CompoundType(fields), |
| discriminator_(type) |
| {} |
| |
| DerivedType::DerivedType(Type *base) |
| : base_(base) |
| {} |
| |
| VecType::VecType(Type *base) |
| : DerivedType(base) |
| {} |
| |
| RefType::RefType(Type *base) |
| : DerivedType(base) |
| { |
| if (base->HasFixup()) { |
| ps_->Error("Ref types aren't allowed to have fixups (TODO: find Line number - sorry!)"); |
| } |
| } |
| |
| ArrayType::ArrayType(Type *base, Element *dimension) |
| : DerivedType(base), |
| dimension_(dimension) |
| { |
| if (!dimension_->HasIntegerValue()) { |
| ps_->Error(dimension_->Line(), "Array needs integer dimension, not '%s'", |
| dimension_->c_str()); |
| } |
| } |
| |
| NamedType::NamedType(Element *name) |
| : name_(name) |
| { |
| base_ = ps_->GetDeclaredType(name); |
| if (!base_) { |
| ps_->Error(name_->Line(), "'%s' isn't declared as a type", |
| name_->c_str()); |
| base_ = new OpaqueType(); |
| } |
| } |
| |
| ScalarType::ScalarType(Element *name) |
| : name_(name) |
| {} |
| |
| HandleType::HandleType() {} |
| |
| OpaqueType::OpaqueType() {} |
| |
| StringType::StringType() {} |
| |
| TypeDecl::TypeDecl(Element *name, Type *base) |
| : DerivedType(base), |
| name_(name) |
| {} |
| |
| TypedefDecl::TypedefDecl(Element *name, Type *base) |
| : TypeDecl(name, base) |
| {} |
| EnumDecl::EnumDecl(Element *name, Type *base) |
| : TypeDecl(name, base) |
| {} |
| StructDecl::StructDecl(Element *name, Type *base) |
| : TypeDecl(name, base) |
| {} |
| UnionDecl::UnionDecl(Element *name, Type *base) |
| : TypeDecl(name, base) |
| {} |
| ImportDecl::ImportDecl(Element *name) |
| : TypeDecl(name, new ImportType()) |
| {} |
| ImportType::ImportType() |
| {} |
| |
| |
| bool Type::HasFixup() |
| { |
| return HasFdFixup() || HasPtrFixup(); |
| } |
| |
| bool Fields::HasPtrFixup() |
| { |
| for (auto & field : fields_) { |
| if (field->GetType() && field->GetType()->HasPtrFixup()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool Fields::HasFdFixup() |
| { |
| for (auto & field : fields_) { |
| if (field->GetType() && field->GetType()->HasFdFixup()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void StructType::Dump() |
| { |
| cout << "Struct fields:" << endl; |
| fields_->Dump(); |
| } |
| |
| void ImportType::Dump() |
| { |
| cout << "Import type:" << endl; |
| } |
| |
| void EnumType::Dump() |
| { |
| cout << "(Enum_type " << type_->GetText() << "): "; |
| fields_->Dump(); |
| cout << endl; |
| } |
| |
| void UnionType::Dump() |
| { |
| cout << "Union "; |
| if (discriminator_) { |
| cout << " (discriminator "; |
| discriminator_->Dump(); |
| cout << ") "; |
| } |
| cout << " with fields:" << endl; |
| fields_->Dump(); |
| } |
| |
| void VecType::Dump() |
| { |
| cout << "Vec<"; |
| base_->Dump(); |
| cout << "> "; |
| } |
| |
| void RefType::Dump() |
| { |
| cout << "Ref<"; |
| base_->Dump(); |
| cout << "> "; |
| } |
| |
| void ArrayType::Dump() |
| { |
| base_->Dump(); |
| cout << "["; |
| dimension_->Dump(); |
| cout << "] "; |
| } |
| |
| void NamedType::Dump() |
| { |
| cout << "(Type:"; |
| base_->Dump(); |
| cout << ") "; |
| } |
| |
| void ScalarType::Dump() |
| { |
| cout << "Scalar:"; |
| name_->Dump(); |
| } |
| |
| void HandleType::Dump() |
| { |
| cout << "Handle "; |
| } |
| |
| void OpaqueType::Dump() |
| { |
| cout << "Opaque "; |
| } |
| |
| void StringType::Dump() |
| { |
| cout << "String "; |
| } |
| |
| void TypedefDecl::Dump() |
| { |
| cout << "Typedef: "; |
| base_->Dump(); |
| cout << " AS "; |
| name_->Dump(); |
| } |
| |
| void EnumDecl::Dump() |
| { |
| cout << "Enum "; |
| name_->Dump(); |
| cout << " { "; |
| base_->Dump(); |
| cout << " } "; |
| } |
| |
| void StructDecl::Dump() |
| { |
| cout << "Struct "; |
| name_->Dump(); |
| cout << " { "; |
| base_->Dump(); |
| cout << " } "; |
| } |
| |
| void UnionDecl::Dump() |
| { |
| cout << "Union "; |
| name_->Dump(); |
| cout << " { "; |
| base_->Dump(); |
| cout << " } "; |
| } |
| |
| void ImportDecl::Dump() |
| { |
| cout << "Import "; |
| name_->Dump(); |
| } |
| |
| void Thing::SetParser(Parser *ps) {ps_=ps;} |
| |
| void Header::Dump() |
| { |
| cout << endl << endl << "HIDL DUMP" << endl << endl; |
| } |
| |
| void Fields::Dump() |
| { |
| for (auto & field : fields_) { |
| field->Dump(); |
| } |
| } |
| |
| // Used for discriminated union entry (tells what vals select it) |
| Field::Field(Element* name, |
| vector<Element*>* selectors) |
| : name_(name), |
| selectors_(selectors) |
| { |
| } |
| |
| TypedField::TypedField(Type *type, Element* name, |
| vector<Element*>* selectors) |
| : Field(name, selectors), |
| type_(type) |
| { |
| BuildText(); |
| } |
| |
| TypedField::TypedField(Type *type, Element *name) |
| : Field(name), |
| type_(type) |
| { |
| BuildText(); |
| } |
| |
| |
| // Used for scalar that selects a discriminated union |
| Field::Field(Element *name, Element *selected) |
| : name_(name), |
| selected_(selected) |
| { |
| } |
| TypedField::TypedField(Type *type, Element *name, Element *selected) |
| : Field(name, selected), |
| type_(type) |
| { |
| (void)comments_; |
| BuildText(); |
| } |
| |
| Field::Field(Element *name) |
| : name_(name) |
| { |
| } |
| EnumField::EnumField(Element *name) |
| : Field(name) |
| { |
| BuildText(); |
| } |
| |
| EnumValueField::EnumValueField(Element *name, Element *value) |
| : EnumField(name), |
| value_(value) |
| { |
| BuildText(); |
| } |
| |
| void Field::Dump() |
| { |
| cout << "<F>" << text_; |
| } |
| |
| void TypedField::BuildText() |
| { |
| text_ = type_->GetText(); |
| text_.append(" "); |
| text_.append(name_->GetText()); |
| } |
| void EnumField::BuildText() |
| { |
| text_ = name_->GetText(); |
| } |
| void EnumValueField::BuildText() |
| { |
| text_ = name_->GetText(); |
| text_.append("="); |
| text_.append(value_->GetText()); |
| } |
| |
| string NamedType::SubtypeSuffix() const |
| { |
| if (base_->TypeName() == "named_type") { |
| return base_->SubtypeSuffix(); |
| } else { |
| return "_" + base_->TypeName(); |
| } |
| } |
| |
| Annotation::Annotation(Element *name) |
| : name_(name) |
| { |
| } |
| |
| Annotation::Annotation(Element *name, AnnotationValues *values) |
| : name_(name), |
| values_(values) |
| { |
| } |
| |
| Annotation::Annotation(Element *name, |
| AnnotationEntries *entries) |
| : entries_(entries), |
| name_(name) |
| { |
| } |
| |
| AnnotationValue::AnnotationValue(Element *value) |
| : value_(value) |
| { |
| } |
| |
| AnnotationValue::AnnotationValue(Annotation *annotation) |
| : annotation_(annotation) |
| { |
| } |
| |
| void Annotations::Add(Annotation *annotation) |
| { |
| annotations_.push_back(annotation); |
| } |
| |
| Function::Function(Annotations* annotations, |
| bool oneway, |
| Element* name, |
| Fields *fields, |
| Fields *generates) |
| : annotations_(annotations), |
| fields_(fields), |
| generates_(generates), |
| name_(name), |
| oneway_(oneway) |
| { |
| std::map<string, Field*>params; |
| for (auto & f : fields->GetVec()) { |
| if (params.find(f->NameText()) != params.end()) { |
| ps_->Error(f->Line(), |
| "Duplicate param name %s", |
| f->NameText().c_str()); |
| } |
| params[f->NameText()] = f; |
| } |
| for (auto & a : annotations->GetAs()) { |
| if (a->NameText() == "param") { |
| if (!a->Entries()) { |
| ps_->Error(a->Line(), "'param' annotation needs entries including 'name'"); |
| } |
| AnnotationEntries::iterator name_entry = |
| a->Entries()->find("name"); |
| if (name_entry == a->Entries()->end()) { |
| ps_->Error(a->Line(), "'param' annotation needs 'name' entry"); |
| } |
| string name = name_entry->second->front()->GetValue()->NoQuoteText(); |
| std::map<string, Field*>::iterator field_entry = |
| params.find(name); |
| if (field_entry != params.end()) { |
| field_entry->second->SetAnnotation(a); |
| } else { |
| ps_->Error(a->Line(), "Param name '%s' not in function", name.c_str()); |
| } |
| } |
| } |
| } |
| |
| void Function::Dump() |
| { |
| cout << "Function: " << name_->GetText() << " with fields: "; |
| fields_->Dump(); |
| cout << " oneway " << oneway_; |
| annotations_->Dump(); |
| if (generates_) { |
| cout << endl << " generating "; |
| generates_->Dump(); |
| } |
| cout << endl; |
| } |
| |
| void Annotations::Dump() |
| { |
| cout << "TODO: Annotation Dump" << endl; |
| /* if (annotations_->size() > 0) { |
| cout << endl << " annotations: "; |
| for (auto & annotation : *annotations_) { |
| cout << *annotation << ", "; |
| } |
| } else { |
| cout << " no annotations; "; |
| }*/ |
| } |