blob: e94ae8e8f944efacf779d61c40b82170738972bb [file] [log] [blame]
#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; ";
}*/
}