static void
ConsumeIdentToken(RangedPtr<const char16_t>& aIter,
                  const char16_t* const aEnd,
                  nsAString& aResult)
{
  aResult.Truncate();

  // Check if it starts with an identifier.
  if (!IsIdentStart(aIter, aEnd)) {
    return;
  }

  // Start to consume.
  while (aIter != aEnd) {
    if (IsNameCode(*aIter)) {
      aResult.Append(*aIter);
    } else if (*aIter == '\\') {
      const RangedPtr<const char16_t> secondChar = aIter + 1;
      if (secondChar == aEnd || !IsValidEscape(*aIter, *secondChar)) {
        break;
      }
      // Consume '\\' and append the character following this '\\'.
      ++aIter;
      aResult.Append(*aIter);
    } else {
      break;
    }
    ++aIter;
  }
}
Beispiel #2
0
static bool
IsIdentContent(int c)
{
    if (IsIdentStart(c) || (c >= '0' && c <= '9') || c == '$')
        return true;

    return false;
}
Beispiel #3
0
/**
 * @brief Parse function expression
 */
ParsedFunction
ParseFunction(const char *value, bool argistype)
{
    int					i;
    ParsedFunction		ret;
    char			   *buf;
    const char		   *nextp;
    bool				done = false;
    List			   *names;
    ListCell		   *l;
    int					nargs;
    FuncCandidateList	candidates;
    FuncCandidateList	find = NULL;
    int					ncandidates = 0;
    HeapTuple			ftup;
    Form_pg_proc		pp;
    AclResult			aclresult;

    buf = palloc(strlen(value) + 1);

    /* parse function name */
    nextp = value;
    do
    {
        if (*nextp == '\"')
        {
            /* Quoted name */
            for (;;)
            {
                nextp = strchr(nextp + 1, '\"');

                /* mismatched quotes */
                if (nextp == NULL)
                    ereport(ERROR,
                            (errcode(ERRCODE_SYNTAX_ERROR),
                             errmsg("function call syntax error: %s", value)));

                if (nextp[1] != '\"')
                    break;		/* found end of quoted name */
            }

            /* nextp now points at the terminating quote */
            nextp = nextp + 1;
        }
        else if (IsIdentStart((unsigned char) *nextp))
        {
            /* Unquoted name */
            nextp++;
            while (IsIdentContent((unsigned char) *nextp))
                nextp++;
        }
        else
        {
            /* invalid syntax */
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("function call syntax error: %s", value)));
        }

        while (isspace((unsigned char) *nextp))
            nextp++;			/* skip trailing whitespace */

        if (*nextp == '.')
        {
            nextp++;
            while (isspace((unsigned char) *nextp))
                nextp++;		/* skip leading whitespace for next */
            /* we expect another name, so done remains false */
        }
        else if (*nextp == '\0' || *nextp == '(')
            done = true;
        else
        {
            /* invalid syntax */
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("function call syntax error: %s", value)));
        }

        /* Loop back if we didn't reach end of function name */
    } while (!done);

    strncpy(buf, value, nextp - value);
    buf[nextp - value] = '\0';

    names = stringToQualifiedNameList(buf);
    pfree(buf);

    if (*nextp == '\0')
    {
        if (!argistype)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("function call syntax error: %s", value)));

        nargs = -1;

        /* Get list of possible candidates from namespace search */
        candidates = FuncnameGetCandidates(names, nargs, NIL, false, false);
    }
    else
    {
        /* parse function arguments */
        nargs = 0;
        while (GetNextArgument(nextp, &ret.args[nargs], &ret.argtypes[nargs], &nextp, value, argistype))
        {
            nargs++;
            if (nargs > FUNC_MAX_ARGS)
                ereport(ERROR,
                        (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
                         errmsg("functions cannot have more than %d arguments", FUNC_MAX_ARGS)));
        }

        /* Get list of possible candidates from namespace search */
        candidates = FuncnameGetCandidates(names, nargs, NIL, true, true);
    }


    /* so now try to match up candidates */
    if (!argistype)
    {
        FuncCandidateList current_candidates;

        ncandidates = func_match_argtypes(nargs,
                                          ret.argtypes,
                                          candidates,
                                          &current_candidates);

        /* one match only? then run with it... */
        if (ncandidates == 1)
            find = current_candidates;

        /* multiple candidates? then better decide or throw an error... */
        else if (ncandidates > 1)
        {
            find = func_select_candidate(nargs, ret.argtypes,
                                         current_candidates);
        }
    }
    else if (nargs > 0)
    {
        /* Quickly check if there is an exact match to the input datatypes */
        for (find = candidates; find; find = find->next)
        {
            if (memcmp(find->args, ret.argtypes, nargs * sizeof(Oid)) == 0)
            {
                ncandidates = 1;
                break;
            }
        }
    }
    else
    {
        FuncCandidateList c;
        for (c = candidates; c; c = c->next)
            ncandidates++;
        find = candidates;
    }

    if (ncandidates == 0)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_FUNCTION),
                 errmsg("function %s does not exist",
                        func_signature_string(names, nargs, NIL, ret.argtypes)),
                 errhint("No function matches the given name and argument types.")));

    /*
     * If we were able to choose a best candidate, we're done.
     * Otherwise, ambiguous function call.
     */
    if (ncandidates > 1 || !OidIsValid(find->oid))
        ereport(ERROR,
                (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
                 errmsg("function %s is not unique",
                        func_signature_string(names, nargs, NIL,
                                              ret.argtypes)),
                 errhint("Could not choose a best candidate function.")));

    foreach (l, names)
    {
        Value  *v = lfirst(l);

        pfree(strVal(v));
        pfree(v);
    }
Beispiel #4
0
static inline PRBool
StartsIdent(PRInt32 aFirstChar, PRInt32 aSecondChar)
{
  return IsIdentStart(aFirstChar) ||
    (aFirstChar == '-' && IsIdentStart(aSecondChar));
}
Beispiel #5
0
/**
 * True if the two-character sequence aFirstChar+aSecondChar begins an
 * identifier.
 */
static inline bool
StartsIdent(int32_t aFirstChar, int32_t aSecondChar)
{
  return IsIdentStart(aFirstChar) ||
    (aFirstChar == '-' && IsIdentStart(aSecondChar));
}