1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Copyright 2010, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_pragma_recorder.h"
18462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
219ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Basic/TokenKinds.h"
22462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
239ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/Preprocessor.h"
246315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "clang/Lex/Token.h"
25462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
26e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
27462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
289ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool PragmaRecorder::GetPragmaNameFromToken(const clang::Token &Token,
299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                            std::string &PragmaName) {
309ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (Token.isLiteral())
319ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PragmaName.assign(Token.getLiteralData(), Token.getLength());
329ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else if (Token.is(clang::tok::identifier))
339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PragmaName.assign(Token.getIdentifierInfo()->getNameStart(),
349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                      Token.getIdentifierInfo()->getLength());
359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else
369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return false;
379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return true;
38462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
39462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaobool PragmaRecorder::GetPragmaValueFromToken(const clang::Token &Token,
419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                             std::string &PragmaValue) {
429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Same as the GetPragmaName()
436315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  if (Token.is(clang::tok::r_paren))
449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PragmaValue.clear();
459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  else
469ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return GetPragmaNameFromToken(Token, PragmaValue);
479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  return true;
48462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
49462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
503fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen HinesPragmaRecorder::PragmaRecorder(PragmaList *Pragmas)
516315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    : PragmaHandler(),
526315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      mPragmas(Pragmas) {
531ebc0ca6ffa7effb875883d18205ed4943ab8fc2Shih-wei Liao}
54462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid PragmaRecorder::HandlePragma(clang::Preprocessor &PP,
56df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                                  clang::PragmaIntroducerKind Introducer,
579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                  clang::Token &FirstToken) {
589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  clang::Token &CurrentToken = FirstToken;
599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  std::string PragmaName, PragmaValue = "";
609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Pragma in ACC should be a name/value pair
61462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (GetPragmaNameFromToken(FirstToken, PragmaName)) {
63f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines    // start parsing the value '(' PragmaValue ')', if we have one.
649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    const clang::Token* NextToken = &PP.LookAhead(0);
65462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (NextToken->is(clang::tok::l_paren))
679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      PP.LexUnexpandedToken(CurrentToken);
689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    else
699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      goto end_parsing_pragma_value;
70462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    NextToken = &PP.LookAhead(0);
72f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines    if (GetPragmaValueFromToken(*NextToken, PragmaValue)) {
739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      PP.Lex(CurrentToken);
74f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines    } else {
75f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines      PP.LexUnexpandedToken(CurrentToken);
76f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines      PP.Diag(NextToken->getLocation(),
77f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines              PP.getDiagnostics().getCustomDiagID(
78f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                  clang::DiagnosticsEngine::Error,
79f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                  "expected value after '#pragma %0('")) << PragmaName;
80f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines      return;
81f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines    }
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (!NextToken->is(clang::tok::r_paren)) {
849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      NextToken = &PP.LookAhead(0);
85f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines      if (NextToken->is(clang::tok::r_paren)) {
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        PP.LexUnexpandedToken(CurrentToken);
87f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines      } else {
88f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines        PP.LexUnexpandedToken(CurrentToken);
89f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines        PP.Diag(NextToken->getLocation(),
90f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                PP.getDiagnostics().getCustomDiagID(
91f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                    clang::DiagnosticsEngine::Error,
92f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                    "missing ')' after '#pragma %0(%1'"))
93f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines            << PragmaName << PragmaValue;
94f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines        return;
95f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines      }
96462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    }
97f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines  } else {
98f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines    PP.Diag(FirstToken.getLocation(),
99f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines            PP.getDiagnostics().getCustomDiagID(
100f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                clang::DiagnosticsEngine::Error,
101f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines                "no pragma name or value"));
102f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines    return;
1039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
1049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1056315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr end_parsing_pragma_value:
106f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines
107f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines  // PragmaValue may be an empty string.
108f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines  mPragmas->push_back(make_pair(PragmaName, PragmaValue));
109f4ea4fd843acd4eacbc89973fedf8bcf692fe73cStephen Hines
1103fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines  // Inform lex to eat the token
1119ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(CurrentToken);
112462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
113e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
114e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
115