nsCSSPseudoClasses::lang == pseudo)) {
nsCSSPseudoClasses::lang == pseudo || nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname == pseudo)) {
CSSParserImpl::ParsePseudoSelector(PRInt32&       aDataMask,                                   nsCSSSelector& aSelector,                                   nsresult&      aErrorCode,                                   PRBool         aIsNegated){  if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof    REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);    return eSelectorParsingStatus_Error;  }  // First, find out whether we are parsing a CSS3 pseudo-element  PRBool parsingPseudoElement = PR_FALSE;  if (mToken.IsSymbol(':')) {    parsingPseudoElement = PR_TRUE;    if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof      REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);      return eSelectorParsingStatus_Error;    }  }  // Do some sanity-checking on the token  if (eCSSToken_Ident != mToken.mType && eCSSToken_Function != mToken.mType) {    // malformed selector    REPORT_UNEXPECTED_TOKEN(PEPseudoSelBadName);    UngetToken();    return eSelectorParsingStatus_Error;  }  // OK, now we know we have an mIdent.  Atomize it.  All the atoms, for  // pseudo-classes as well as pseudo-elements, start with a single ':'.  nsAutoString buffer;  buffer.Append(PRUnichar(':'));  buffer.Append(mToken.mIdent);  ToLowerCase(buffer);  nsCOMPtr<nsIAtom> pseudo = do_GetAtom(buffer);  // stash away some info about this pseudo so we only have to get it once.#ifdef MOZ_XUL  // If a tree pseudo-element is using the function syntax, it will  // get isTree set here and will pass the check below that only  // allows functions if they are in our list of things allowed to be  // functions.  If it is _not_ using the function syntax, isTree will  // be false, and it will still pass that check.  So the tree  // pseudo-elements are allowed to be either functions or not, as  // desired.  PRBool isTree = (eCSSToken_Function == mToken.mType) &&                  IsTreePseudoElement(pseudo);#endif  PRBool isPseudoElement = nsCSSPseudoElements::IsPseudoElement(pseudo);  PRBool isAnonBox = nsCSSAnonBoxes::IsAnonBox(pseudo);  PRBool isPseudoClass = nsCSSPseudoClasses::IsPseudoClass(pseudo);  if (!isPseudoClass && !isPseudoElement && !isAnonBox) {    // Not a pseudo-class, not a pseudo-element.... forget it    REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);    UngetToken();    return eSelectorParsingStatus_Error;  }  // If it's a function token, it better be on our "ok" list, and if the name  // is that of a function pseudo it better be a function token  if ((eCSSToken_Function == mToken.mType) !=      (#ifdef MOZ_XUL       isTree ||#endif       nsCSSPseudoClasses::notPseudo == pseudo ||       nsCSSPseudoClasses::lang == pseudo)) { // There are no other function pseudos    REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);    UngetToken();    return eSelectorParsingStatus_Error;  }    // If it starts with "::", it better be a pseudo-element  if (parsingPseudoElement &&      !isPseudoElement &&      !isAnonBox) {    REPORT_UNEXPECTED_TOKEN(PEPseudoSelNotPE);    UngetToken();    return eSelectorParsingStatus_Error;  }  if (!parsingPseudoElement && nsCSSPseudoClasses::notPseudo == pseudo) {    if (aIsNegated) { // :not() can't be itself negated      REPORT_UNEXPECTED_TOKEN(PEPseudoSelDoubleNot);      UngetToken();      return eSelectorParsingStatus_Error;    }    // CSS 3 Negation pseudo-class takes one simple selector as argument    nsSelectorParsingStatus parsingStatus =      ParseNegatedSimpleSelector(aDataMask, aSelector, aErrorCode);    if (eSelectorParsingStatus_Continue != parsingStatus) {      return parsingStatus;    }  }      else if (!parsingPseudoElement && isPseudoClass) {    aDataMask |= SEL_MASK_PCLASS;    if (nsCSSPseudoClasses::lang == pseudo) {      nsSelectorParsingStatus parsingStatus = ParseLangSelector(aSelector, aErrorCode);      if (eSelectorParsingStatus_Continue != parsingStatus) {        return parsingStatus;      }    }    // XXX are there more pseudo classes which accept arguments ?    else {      aSelector.AddPseudoClass(pseudo);    }  }  else if (isPseudoElement || isAnonBox) {    // Pseudo-element.  Make some more sanity checks.        if (aIsNegated) { // pseudo-elements can't be negated      REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);      UngetToken();      return eSelectorParsingStatus_Error;    }    // CSS2 pseudo-elements and -moz-tree-* pseudo-elements are allowed    // to have a single ':' on them.  Others (CSS3+ pseudo-elements and    // various -moz-* pseudo-elements) must have |parsingPseudoElement|    // set.    if (!parsingPseudoElement &&        !nsCSSPseudoElements::IsCSS2PseudoElement(pseudo)#ifdef MOZ_XUL        && !IsTreePseudoElement(pseudo)#endif        ) {      REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);      UngetToken();      return eSelectorParsingStatus_Error;    }    if (0 == (aDataMask & SEL_MASK_PELEM)) {      aDataMask |= SEL_MASK_PELEM;      aSelector.AddPseudoClass(pseudo); // store it here, it gets pulled later#ifdef MOZ_XUL      if (isTree) {        // We have encountered a pseudoelement of the form        // -moz-tree-xxxx(a,b,c).  We parse (a,b,c) and add each        // item in the list to the pseudoclass list.  They will be pulled        // from the list later along with the pseudo-element.        if (!ParseTreePseudoElement(aErrorCode, aSelector)) {          return eSelectorParsingStatus_Error;        }      }#endif      // ensure selector ends here, must be followed by EOF, space, '{' or ','      if (GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)        if ((eCSSToken_WhiteSpace == mToken.mType) ||             (mToken.IsSymbol('{') || mToken.IsSymbol(','))) {          UngetToken();          return eSelectorParsingStatus_Done;        }        REPORT_UNEXPECTED_TOKEN(PEPseudoSelTrailing);        UngetToken();        return eSelectorParsingStatus_Error;      }    }    else {  // multiple pseudo elements, not legal      REPORT_UNEXPECTED_TOKEN(PEPseudoSelMultiplePE);      UngetToken();      return eSelectorParsingStatus_Error;    }  }#ifdef DEBUG  else {    // We should never end up here.  Indeed, if we ended up here, we know (from    // the current if/else cascade) that !isPseudoElement and !isAnonBox.  But    // then due to our earlier check we know that isPseudoClass.  Since we    // didn't fall into the isPseudoClass case in this cascade, we must have    // parsingPseudoElement.  But we've already checked the    // parsingPseudoElement && !isPseudoClass && !isAnonBox case and bailed if    // it's happened.    NS_NOTREACHED("How did this happen?");  }#endif  return eSelectorParsingStatus_Continue;}