Beispiel #1
0
void
gram_error(char *s)
{
    lex_error(0, s);
}
Beispiel #2
0
static BOOL parse_numeric_literal(parser_ctx_t *ctx, double *ret)
{
    HRESULT hres;

    if(*ctx->ptr == '0') {
        LONG d, l = 0;

        ctx->ptr++;

        if(*ctx->ptr == 'x' || *ctx->ptr == 'X') {
            if(++ctx->ptr == ctx->end) {
                ERR("unexpected end of file\n");
                return FALSE;
            }

            while(ctx->ptr < ctx->end && (d = hex_to_int(*ctx->ptr)) != -1) {
                l = l*16 + d;
                ctx->ptr++;
            }

            if(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) {
                WARN("unexpected identifier char\n");
                lex_error(ctx, JS_E_MISSING_SEMICOLON);
                return FALSE;
            }

            *ret = l;
            return TRUE;
        }

        if(isdigitW(*ctx->ptr)) {
            unsigned base = 8;
            const WCHAR *ptr;
            double val = 0;

            for(ptr = ctx->ptr; ptr < ctx->end && isdigitW(*ptr); ptr++) {
                if(*ptr > '7') {
                    base = 10;
                    break;
                }
            }

            do {
                val = val*base + *ctx->ptr-'0';
            }while(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr));

            /* FIXME: Do we need it here? */
            if(ctx->ptr < ctx->end && (is_identifier_char(*ctx->ptr) || *ctx->ptr == '.')) {
                WARN("wrong char after octal literal: '%c'\n", *ctx->ptr);
                lex_error(ctx, JS_E_MISSING_SEMICOLON);
                return FALSE;
            }

            *ret = val;
            return TRUE;
        }

        if(is_identifier_char(*ctx->ptr)) {
            WARN("wrong char after zero\n");
            lex_error(ctx, JS_E_MISSING_SEMICOLON);
            return FALSE;
        }
    }

    hres = parse_decimal(&ctx->ptr, ctx->end, ret);
    if(FAILED(hres)) {
        lex_error(ctx, hres);
        return FALSE;
    }

    return TRUE;
}
Beispiel #3
0
static int next_token(parser_ctx_t *ctx, void *lval)
{
    do {
        if(!skip_spaces(ctx))
            return tEOF;
    }while(skip_comment(ctx) || skip_html_comment(ctx));

    if(ctx->implicit_nl_semicolon) {
        if(ctx->nl)
            return ';';
        ctx->implicit_nl_semicolon = FALSE;
    }

    if(isalphaW(*ctx->ptr)) {
        int ret = check_keywords(ctx, lval);
        if(ret)
            return ret;

        return parse_identifier(ctx, lval);
    }

    if(isdigitW(*ctx->ptr)) {
        double n;

        if(!parse_numeric_literal(ctx, &n))
            return -1;

        *(literal_t**)lval = new_double_literal(ctx, n);
        return tNumericLiteral;
    }

    switch(*ctx->ptr) {
    case '{':
    case '(':
    case ')':
    case '[':
    case ']':
    case ';':
    case ',':
    case '~':
    case '?':
        return *ctx->ptr++;

    case '}':
        *(const WCHAR**)lval = ctx->ptr++;
        return '}';

    case '.':
        if(ctx->ptr+1 < ctx->end && isdigitW(ctx->ptr[1])) {
            double n;
            HRESULT hres;
            hres = parse_decimal(&ctx->ptr, ctx->end, &n);
            if(FAILED(hres)) {
                lex_error(ctx, hres);
                return -1;
            }
            *(literal_t**)lval = new_double_literal(ctx, n);
            return tNumericLiteral;
        }
        ctx->ptr++;
        return '.';

    case '<':
        if(++ctx->ptr == ctx->end) {
            *(int*)lval = EXPR_LESS;
            return tRelOper;
        }

        switch(*ctx->ptr) {
        case '=':  /* <= */
            ctx->ptr++;
            *(int*)lval = EXPR_LESSEQ;
            return tRelOper;
        case '<':  /* << */
            if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* <<= */
                ctx->ptr++;
                *(int*)lval = EXPR_ASSIGNLSHIFT;
                return tAssignOper;
            }
            *(int*)lval = EXPR_LSHIFT;
            return tShiftOper;
        default: /* < */
            *(int*)lval = EXPR_LESS;
            return tRelOper;
        }

    case '>':
        if(++ctx->ptr == ctx->end) { /* > */
            *(int*)lval = EXPR_GREATER;
            return tRelOper;
        }

        switch(*ctx->ptr) {
        case '=':  /* >= */
            ctx->ptr++;
            *(int*)lval = EXPR_GREATEREQ;
            return tRelOper;
        case '>':  /* >> */
            if(++ctx->ptr < ctx->end) {
                if(*ctx->ptr == '=') {  /* >>= */
                    ctx->ptr++;
                    *(int*)lval = EXPR_ASSIGNRSHIFT;
                    return tAssignOper;
                }
                if(*ctx->ptr == '>') {  /* >>> */
                    if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* >>>= */
                        ctx->ptr++;
                        *(int*)lval = EXPR_ASSIGNRRSHIFT;
                        return tAssignOper;
                    }
                    *(int*)lval = EXPR_RRSHIFT;
                    return tRelOper;
                }
            }
            *(int*)lval = EXPR_RSHIFT;
            return tShiftOper;
        default:
            *(int*)lval = EXPR_GREATER;
            return tRelOper;
        }

    case '+':
        ctx->ptr++;
        if(ctx->ptr < ctx->end) {
            switch(*ctx->ptr) {
            case '+':  /* ++ */
                ctx->ptr++;
                return tINC;
            case '=':  /* += */
                ctx->ptr++;
                *(int*)lval = EXPR_ASSIGNADD;
                return tAssignOper;
            }
        }
        return '+';

    case '-':
        ctx->ptr++;
        if(ctx->ptr < ctx->end) {
            switch(*ctx->ptr) {
            case '-':  /* -- or --> */
                ctx->ptr++;
                if(ctx->is_html && ctx->nl && ctx->ptr < ctx->end && *ctx->ptr == '>') {
                    ctx->ptr++;
                    return tHTMLCOMMENT;
                }
                return tDEC;
            case '=':  /* -= */
                ctx->ptr++;
                *(int*)lval = EXPR_ASSIGNSUB;
                return tAssignOper;
            }
        }
        return '-';

    case '*':
        if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* *= */
            ctx->ptr++;
            *(int*)lval = EXPR_ASSIGNMUL;
            return tAssignOper;
        }
        return '*';

    case '%':
        if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* %= */
            ctx->ptr++;
            *(int*)lval = EXPR_ASSIGNMOD;
            return tAssignOper;
        }
        return '%';

    case '&':
        if(++ctx->ptr < ctx->end) {
            switch(*ctx->ptr) {
            case '=':  /* &= */
                ctx->ptr++;
                *(int*)lval = EXPR_ASSIGNAND;
                return tAssignOper;
            case '&':  /* && */
                ctx->ptr++;
                return tANDAND;
            }
        }
        return '&';

    case '|':
        if(++ctx->ptr < ctx->end) {
            switch(*ctx->ptr) {
            case '=':  /* |= */
                ctx->ptr++;
                *(int*)lval = EXPR_ASSIGNOR;
                return tAssignOper;
            case '|':  /* || */
                ctx->ptr++;
                return tOROR;
            }
        }
        return '|';

    case '^':
        if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* ^= */
            ctx->ptr++;
            *(int*)lval = EXPR_ASSIGNXOR;
            return tAssignOper;
        }
        return '^';

    case '!':
        if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* != */
            if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* !== */
                ctx->ptr++;
                *(int*)lval = EXPR_NOTEQEQ;
                return tEqOper;
            }
            *(int*)lval = EXPR_NOTEQ;
            return tEqOper;
        }
        return '!';

    case '=':
        if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* == */
            if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* === */
                ctx->ptr++;
                *(int*)lval = EXPR_EQEQ;
                return tEqOper;
            }
            *(int*)lval = EXPR_EQ;
            return tEqOper;
        }
        return '=';

    case '/':
        if(++ctx->ptr < ctx->end) {
            if(*ctx->ptr == '=') {  /* /= */
                ctx->ptr++;
                *(int*)lval = EXPR_ASSIGNDIV;
                return kDIVEQ;
            }
        }
        return '/';

    case ':':
        if(++ctx->ptr < ctx->end && *ctx->ptr == ':') {
            ctx->ptr++;
            return kDCOL;
        }
        return ':';

    case '\"':
    case '\'':
        return parse_string_literal(ctx, lval, *ctx->ptr);

    case '_':
    case '$':
        return parse_identifier(ctx, lval);

    case '@':
        return '@';
    }

    WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr);
    return 0;
}
Beispiel #4
0
Datei: lex.c Projekt: ALutzG/ovs
/* Initializes 'token' and parses the first token from the beginning of
 * null-terminated string 'p' into 'token'.  Stores a pointer to the start of
 * the token (after skipping white space and comments, if any) into '*startp'.
 * Returns the character position at which to begin parsing the next token. */
const char *
lex_token_parse(struct lex_token *token, const char *p, const char **startp)
{
    lex_token_init(token);

next:
    *startp = p;
    switch (*p) {
    case '\0':
        token->type = LEX_T_END;
        return p;

    case ' ': case '\t': case '\n': case '\r':
        p++;
        goto next;

    case '/':
        p++;
        if (*p == '/') {
            do {
                p++;
            } while (*p != '\0' && *p != '\n');
            goto next;
        } else if (*p == '*') {
            p++;
            for (;;) {
                if (*p == '*' && p[1] == '/') {
                    p += 2;
                    goto next;
                } else if (*p == '\0' || *p == '\n') {
                    lex_error(token, "`/*' without matching `*/'.");
                    return p;
                } else {
                    p++;
                }
            }
            goto next;
        } else {
            lex_error(token,
                      "`/' is only valid as part of `//' or `/*'.");
        }
        break;

    case '(':
        token->type = LEX_T_LPAREN;
        p++;
        break;

    case ')':
        token->type = LEX_T_RPAREN;
        p++;
        break;

    case '{':
        token->type = LEX_T_LCURLY;
        p++;
        break;

    case '}':
        token->type = LEX_T_RCURLY;
        p++;
        break;

    case '[':
        token->type = LEX_T_LSQUARE;
        p++;
        break;

    case ']':
        token->type = LEX_T_RSQUARE;
        p++;
        break;

    case '=':
        p++;
        if (*p == '=') {
            token->type = LEX_T_EQ;
            p++;
        } else {
            token->type = LEX_T_EQUALS;
        }
        break;

    case '!':
        p++;
        if (*p == '=') {
            token->type = LEX_T_NE;
            p++;
        } else {
            token->type = LEX_T_LOG_NOT;
        }
        break;

    case '&':
        p++;
        if (*p == '&') {
            token->type = LEX_T_LOG_AND;
            p++;
        } else {
            lex_error(token, "`&' is only valid as part of `&&'.");
        }
        break;

    case '|':
        p++;
        if (*p == '|') {
            token->type = LEX_T_LOG_OR;
            p++;
        } else {
            lex_error(token, "`|' is only valid as part of `||'.");
        }
        break;

    case '<':
        p++;
        if (*p == '=') {
            token->type = LEX_T_LE;
            p++;
        } else if (*p == '-' && p[1] == '>') {
            token->type = LEX_T_EXCHANGE;
            p += 2;
        } else {
            token->type = LEX_T_LT;
        }
        break;

    case '>':
        p++;
        if (*p == '=') {
            token->type = LEX_T_GE;
            p++;
        } else {
            token->type = LEX_T_GT;
        }
        break;

    case '.':
        p++;
        if (*p == '.') {
            token->type = LEX_T_ELLIPSIS;
            p++;
        } else {
            lex_error(token, "`.' is only valid as part of `..' or a number.");
        }
        break;

    case ',':
        p++;
        token->type = LEX_T_COMMA;
        break;

    case ';':
        p++;
        token->type = LEX_T_SEMICOLON;
        break;

    case '-':
        p++;
        if (*p == '-') {
            token->type = LEX_T_DECREMENT;
            p++;
        } else {
            lex_error(token, "`-' is only valid as part of `--'.");
        }
        break;

    case '$':
        p = lex_parse_macro(p, token);
        break;

    case ':':
        if (p[1] != ':') {
            token->type = LEX_T_COLON;
            p++;
            break;
        }
        /* IPv6 address beginning with "::".  Fall through. */
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
        p = lex_parse_integer(p, token);
        break;

    case '"':
        p = lex_parse_string(p, token);
        break;

    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        /* We need to distinguish an Ethernet address or IPv6 address from an
         * identifier.  Fortunately, Ethernet addresses and IPv6 addresses that
         * are ambiguous based on the first character, always start with hex
         * digits followed by a colon, but identifiers never do. */
        p = (p[strspn(p, "0123456789abcdefABCDEF")] == ':'
             ? lex_parse_integer(p, token)
             : lex_parse_id(p, LEX_T_ID, token));
        break;

    default:
        if (lex_is_id1(*p)) {
            p = lex_parse_id(p, LEX_T_ID, token);
        } else {
            if (isprint((unsigned char) *p)) {
                lex_error(token, "Invalid character `%c' in input.", *p);
            } else {
                lex_error(token, "Invalid byte 0x%d in input.", *p);
            }
            p++;
        }
        break;
    }

    return p;
}
Beispiel #5
0
static int cc_token(parser_ctx_t *ctx, void *lval)
{
    unsigned id_len = 0;
    cc_var_t *var;

    static const WCHAR cc_onW[] = {'c','c','_','o','n',0};
    static const WCHAR setW[] = {'s','e','t',0};

    ctx->ptr++;

    if(!check_keyword(ctx, cc_onW, NULL))
        return init_cc(ctx) ? 0 : -1;

    if(!check_keyword(ctx, setW, NULL)) {
        const WCHAR *ident;
        unsigned ident_len;
        cc_var_t *var;

        if(!init_cc(ctx))
            return -1;

        if(!skip_spaces(ctx))
            return lex_error(ctx, JS_E_EXPECTED_AT);

        if(!parse_cc_identifier(ctx, &ident, &ident_len))
            return -1;

        if(!skip_spaces(ctx) || *ctx->ptr != '=')
            return lex_error(ctx, JS_E_EXPECTED_ASSIGN);
        ctx->ptr++;

        if(!parse_cc_expr(ctx)) {
            WARN("parsing CC expression failed\n");
            return -1;
        }

        var = find_cc_var(ctx->script->cc, ident, ident_len);
        if(var) {
            var->val = ctx->ccval;
        }else {
            if(!new_cc_var(ctx->script->cc, ident, ident_len, ctx->ccval))
                return lex_error(ctx, E_OUTOFMEMORY);
        }

        return 0;
    }

    if(!check_keyword(ctx, ifW, NULL)) {
        if(!init_cc(ctx))
            return -1;

        if(!skip_spaces(ctx) || *ctx->ptr != '(')
            return lex_error(ctx, JS_E_MISSING_LBRACKET);

        if(!parse_cc_expr(ctx))
            return -1;

        if(get_ccbool(ctx->ccval)) {
            /* continue parsing block inside if */
            ctx->cc_if_depth++;
            return 0;
        }

        return skip_code(ctx, TRUE);
    }

    if(!check_keyword(ctx, elifW, NULL) || !check_keyword(ctx, elseW, NULL)) {
        if(!ctx->cc_if_depth)
            return lex_error(ctx, JS_E_SYNTAX);

        return skip_code(ctx, FALSE);
    }

    if(!check_keyword(ctx, endW, NULL)) {
        if(!ctx->cc_if_depth)
            return lex_error(ctx, JS_E_SYNTAX);

        ctx->cc_if_depth--;
        return 0;
    }

    if(!ctx->script->cc)
        return lex_error(ctx, JS_E_DISABLED_CC);

    while(ctx->ptr+id_len < ctx->end && is_identifier_char(ctx->ptr[id_len]))
        id_len++;
    if(!id_len)
        return '@';

    TRACE("var %s\n", debugstr_wn(ctx->ptr, id_len));

    var = find_cc_var(ctx->script->cc, ctx->ptr, id_len);
    ctx->ptr += id_len;
    if(!var || var->val.is_num) {
        *(literal_t**)lval = new_double_literal(ctx, var ? var->val.u.n : NAN);
        return tNumericLiteral;
    }

    *(literal_t**)lval = new_boolean_literal(ctx, var->val.u.b);
    return tBooleanLiteral;
}
Beispiel #6
0
/* Parses the whole DO REPEAT command specification.
   Returns success. */
static bool
parse_specification (struct lexer *lexer, struct dictionary *dict,
                     struct hmap *dummies)
{
  struct dummy_var *first_dv = NULL;

  hmap_init (dummies);
  do
    {
      struct dummy_var *dv;
      const char *name;
      bool ok;

      /* Get a stand-in variable name and make sure it's unique. */
      if (!lex_force_id (lexer))
	goto error;
      name = lex_tokcstr (lexer);
      if (dict_lookup_var (dict, name))
        msg (SW, _("Dummy variable name `%s' hides dictionary variable `%s'."),
             name, name);
      if (find_dummy_var (dummies, name, strlen (name)))
        {
          msg (SE, _("Dummy variable name `%s' is given twice."), name);
          goto error;
        }

      /* Make a new macro. */
      dv = xmalloc (sizeof *dv);
      dv->name = xstrdup (name);
      dv->values = NULL;
      dv->n_values = 0;
      hmap_insert (dummies, &dv->hmap_node, hash_dummy (name, strlen (name)));

      /* Skip equals sign. */
      lex_get (lexer);
      if (!lex_force_match (lexer, T_EQUALS))
	goto error;

      /* Get the details of the variable's possible values. */
      if (lex_token (lexer) == T_ID || lex_token (lexer) == T_ALL)
	ok = parse_ids (lexer, dict, dv);
      else if (lex_is_number (lexer))
	ok = parse_numbers (lexer, dv);
      else if (lex_is_string (lexer))
	ok = parse_strings (lexer, dv);
      else
	{
	  lex_error (lexer, NULL);
	  goto error;
	}
      if (!ok)
	goto error;
      assert (dv->n_values > 0);
      if (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD)
        {
          lex_error (lexer, NULL);
          goto error;
        }

      /* If this is the first variable then it defines how many replacements
	 there must be; otherwise enforce this number of replacements. */
      if (first_dv == NULL)
        first_dv = dv;
      else if (first_dv->n_values != dv->n_values)
	{
	  msg (SE, _("Dummy variable `%s' had %zu substitutions, so `%s' must "
                     "also, but %zu were specified."),
               first_dv->name, first_dv->n_values,
               dv->name, dv->n_values);
	  goto error;
	}

      lex_match (lexer, T_SLASH);
    }
  while (!lex_match (lexer, T_ENDCMD));

  while (lex_match (lexer, T_ENDCMD))
    continue;

  return true;

error:
  destroy_dummies (dummies);
  return false;
}
Beispiel #7
0
Datei: lex.c Projekt: ALutzG/ovs
static const char *
lex_parse_integer__(const char *p, struct lex_token *token)
{
    lex_token_init(token);
    token->type = LEX_T_INTEGER;
    memset(&token->value, 0, sizeof token->value);

    /* Find the extent of an "integer" token, which can be in decimal or
     * hexadecimal, or an Ethernet address or IPv4 or IPv6 address, as 'start'
     * through 'end'.
     *
     * Special cases we handle here are:
     *
     *     - The ellipsis token "..", used as e.g. 123..456.  A doubled dot
     *       is never valid syntax as part of an "integer", so we stop if
     *       we encounter two dots in a row.
     *
     *     - Syntax like 1.2.3.4:1234 to indicate an IPv4 address followed by a
     *       port number should be considered three tokens: 1.2.3.4 : 1234.
     *       The obvious approach is to allow just dots or just colons within a
     *       given integer, but that would disallow IPv4-mapped IPv6 addresses,
     *       e.g. ::ffff:192.0.2.128.  However, even in those addresses, a
     *       colon never follows a dot, so we stop if we encounter a colon
     *       after a dot.
     *
     *       (There is no corresponding way to parse an IPv6 address followed
     *       by a port number: ::1:2:3:4:1234 is unavoidably ambiguous.)
     */
    const char *start = p;
    const char *end = start;
    bool saw_dot = false;
    while (isalnum((unsigned char) *end)
           || (*end == ':' && !saw_dot)
           || (*end == '.' && end[1] != '.')) {
        if (*end == '.') {
            saw_dot = true;
        }
        end++;
    }
    size_t len = end - start;

    int n;
    struct eth_addr mac;

    if (!len) {
        lex_error(token, "Integer constant expected.");
    } else if (len == 17
               && ovs_scan(start, ETH_ADDR_SCAN_FMT"%n",
                           ETH_ADDR_SCAN_ARGS(mac), &n)
               && n == len) {
        token->value.mac = mac;
        token->format = LEX_F_ETHERNET;
    } else if (start + strspn(start, "0123456789") == end) {
        if (p[0] == '0' && len > 1) {
            lex_error(token, "Decimal constants must not have leading zeros.");
        } else {
            unsigned long long int integer;
            char *tail;

            errno = 0;
            integer = strtoull(p, &tail, 10);
            if (tail != end || errno == ERANGE) {
                lex_error(token, "Decimal constants must be less than 2**64.");
            } else {
                token->value.integer = htonll(integer);
                token->format = LEX_F_DECIMAL;
            }
        }
    } else if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
        if (len > 2) {
            lex_parse_hex_integer(start + 2, len - 2, token);
        } else {
            lex_error(token, "Hex digits expected following 0%c.", p[1]);
        }
    } else if (len < INET6_ADDRSTRLEN) {
        char copy[INET6_ADDRSTRLEN];
        memcpy(copy, p, len);
        copy[len] = '\0';

        if (ip_parse(copy, &token->value.ipv4)) {
            token->format = LEX_F_IPV4;
        } else if (ipv6_parse(copy, &token->value.ipv6)) {
            token->format = LEX_F_IPV6;
        } else {
            lex_error(token, "Invalid numeric constant.");
        }
    } else {
        lex_error(token, "Invalid numeric constant.");
    }

    ovs_assert(token->type == LEX_T_INTEGER || token->type == LEX_T_ERROR);
    return end;
}
Beispiel #8
0
static int
combine_files (enum comb_command_type command,
               struct lexer *lexer, struct dataset *ds)
{
  struct comb_proc proc;

  bool saw_by = false;
  bool saw_sort = false;
  struct casereader *active_file = NULL;

  char *first_name = NULL;
  char *last_name = NULL;

  struct taint *taint = NULL;

  size_t n_tables = 0;
  size_t allocated_files = 0;

  size_t i;

  proc.files = NULL;
  proc.n_files = 0;
  proc.dict = dict_create (get_default_encoding ());
  proc.output = NULL;
  proc.matcher = NULL;
  subcase_init_empty (&proc.by_vars);
  proc.first = NULL;
  proc.last = NULL;
  proc.buffered_case = NULL;
  proc.prev_BY = NULL;

  dict_set_case_limit (proc.dict, dict_get_case_limit (dataset_dict (ds)));

  lex_match (lexer, T_SLASH);
  for (;;)
    {
      struct comb_file *file;
      enum comb_file_type type;

      if (lex_match_id (lexer, "FILE"))
        type = COMB_FILE;
      else if (command == COMB_MATCH && lex_match_id (lexer, "TABLE"))
        {
          type = COMB_TABLE;
          n_tables++;
        }
      else
        break;
      lex_match (lexer, T_EQUALS);

      if (proc.n_files >= allocated_files)
        proc.files = x2nrealloc (proc.files, &allocated_files,
                                sizeof *proc.files);
      file = &proc.files[proc.n_files++];
      file->type = type;
      subcase_init_empty (&file->by_vars);
      subcase_init_empty (&file->src);
      subcase_init_empty (&file->dst);
      file->mv = NULL;
      file->handle = NULL;
      file->dict = NULL;
      file->reader = NULL;
      file->data = NULL;
      file->is_sorted = true;
      file->in_name = NULL;
      file->in_var = NULL;

      if (lex_match (lexer, T_ASTERISK))
        {
          if (!dataset_has_source (ds))
            {
              msg (SE, _("Cannot specify the active dataset since none "
                         "has been defined."));
              goto error;
            }

          if (proc_make_temporary_transformations_permanent (ds))
            msg (SE, _("This command may not be used after TEMPORARY when "
                       "the active dataset is an input source.  "
                       "Temporary transformations will be made permanent."));

          file->dict = dict_clone (dataset_dict (ds));
        }
      else
        {
          file->handle = fh_parse (lexer, FH_REF_FILE, dataset_session (ds));
          if (file->handle == NULL)
            goto error;

          file->reader = any_reader_open (file->handle, NULL, &file->dict);
          if (file->reader == NULL)
            goto error;
        }

      while (lex_match (lexer, T_SLASH))
        if (lex_match_id (lexer, "RENAME"))
          {
            if (!parse_dict_rename (lexer, file->dict))
              goto error;
          }
        else if (lex_match_id (lexer, "IN"))
          {
            lex_match (lexer, T_EQUALS);
            if (lex_token (lexer) != T_ID)
              {
                lex_error (lexer, NULL);
                goto error;
              }

            if (file->in_name)
              {
                msg (SE, _("Multiple IN subcommands for a single FILE or "
                           "TABLE."));
                goto error;
              }
            file->in_name = xstrdup (lex_tokcstr (lexer));
            lex_get (lexer);
          }
        else if (lex_match_id (lexer, "SORT"))
          {
            file->is_sorted = false;
            saw_sort = true;
          }

      if (!merge_dictionary (proc.dict, file))
        goto error;
    }

  while (lex_token (lexer) != T_ENDCMD)
    {
      if (lex_match (lexer, T_BY))
	{
          const struct variable **by_vars;
          size_t i;
          bool ok;

	  if (saw_by)
	    {
              lex_sbc_only_once ("BY");
	      goto error;
	    }
          saw_by = true;

	  lex_match (lexer, T_EQUALS);
          if (!parse_sort_criteria (lexer, proc.dict, &proc.by_vars,
                                    &by_vars, NULL))
	    goto error;

          ok = true;
          for (i = 0; i < proc.n_files; i++)
            {
              struct comb_file *file = &proc.files[i];
              size_t j;

              for (j = 0; j < subcase_get_n_fields (&proc.by_vars); j++)
                {
                  const char *name = var_get_name (by_vars[j]);
                  struct variable *var = dict_lookup_var (file->dict, name);
                  if (var != NULL)
                    subcase_add_var (&file->by_vars, var,
                                     subcase_get_direction (&proc.by_vars, j));
                  else
                    {
                      if (file->handle != NULL)
                        msg (SE, _("File %s lacks BY variable %s."),
                             fh_get_name (file->handle), name);
                      else
                        msg (SE, _("Active dataset lacks BY variable %s."),
                             name);
                      ok = false;
                    }
                }
              assert (!ok || subcase_conformable (&file->by_vars,
                                                  &proc.files[0].by_vars));
            }
          free (by_vars);

          if (!ok)
            goto error;
	}
      else if (command != COMB_UPDATE && lex_match_id (lexer, "FIRST"))
        {
          if (first_name != NULL)
            {
              lex_sbc_only_once ("FIRST");
              goto error;
            }

	  lex_match (lexer, T_EQUALS);
          if (!lex_force_id (lexer))
            goto error;
          first_name = xstrdup (lex_tokcstr (lexer));
          lex_get (lexer);
        }
      else if (command != COMB_UPDATE && lex_match_id (lexer, "LAST"))
        {
          if (last_name != NULL)
            {
              lex_sbc_only_once ("LAST");
              goto error;
            }

	  lex_match (lexer, T_EQUALS);
          if (!lex_force_id (lexer))
            goto error;
          last_name = xstrdup (lex_tokcstr (lexer));
          lex_get (lexer);
        }
      else if (lex_match_id (lexer, "MAP"))
	{
	  /* FIXME. */
	}
      else if (lex_match_id (lexer, "DROP"))
        {
          if (!parse_dict_drop (lexer, proc.dict))
            goto error;
        }
      else if (lex_match_id (lexer, "KEEP"))
        {
          if (!parse_dict_keep (lexer, proc.dict))
            goto error;
        }
      else
	{
	  lex_error (lexer, NULL);
	  goto error;
	}

      if (!lex_match (lexer, T_SLASH) && lex_token (lexer) != T_ENDCMD)
        {
          lex_end_of_command (lexer);
          goto error;
        }
    }

  if (!saw_by)
    {
      if (command == COMB_UPDATE)
        {
          lex_sbc_missing ("BY");
          goto error;
        }
      if (n_tables)
        {
          msg (SE, _("BY is required when %s is specified."), "TABLE");
          goto error;
        }
      if (saw_sort)
        {
          msg (SE, _("BY is required when %s is specified."), "SORT");
          goto error;
        }
    }

  /* Add IN, FIRST, and LAST variables to master dictionary. */
  for (i = 0; i < proc.n_files; i++)
    {
      struct comb_file *file = &proc.files[i];
      if (!create_flag_var ("IN", file->in_name, proc.dict, &file->in_var))
        goto error;
    }
  if (!create_flag_var ("FIRST", first_name, proc.dict, &proc.first)
      || !create_flag_var ("LAST", last_name, proc.dict, &proc.last))
    goto error;

  dict_delete_scratch_vars (proc.dict);
  dict_compact_values (proc.dict);

  /* Set up mapping from each file's variables to master
     variables. */
  for (i = 0; i < proc.n_files; i++)
    {
      struct comb_file *file = &proc.files[i];
      size_t src_var_cnt = dict_get_var_cnt (file->dict);
      size_t j;

      file->mv = xnmalloc (src_var_cnt, sizeof *file->mv);
      for (j = 0; j < src_var_cnt; j++)
        {
          struct variable *src_var = dict_get_var (file->dict, j);
          struct variable *dst_var = dict_lookup_var (proc.dict,
                                                      var_get_name (src_var));
          if (dst_var != NULL)
            {
              size_t n = subcase_get_n_fields (&file->src);
              file->mv[n] = var_get_missing_values (src_var);
              subcase_add_var (&file->src, src_var, SC_ASCEND);
              subcase_add_var (&file->dst, dst_var, SC_ASCEND);
            }
        }
    }

  proc.output = autopaging_writer_create (dict_get_proto (proc.dict));
  taint = taint_clone (casewriter_get_taint (proc.output));

  /* Set up case matcher. */
  proc.matcher = case_matcher_create ();
  for (i = 0; i < proc.n_files; i++)
    {
      struct comb_file *file = &proc.files[i];
      if (file->reader == NULL)
        {
          if (active_file == NULL)
            {
              proc_discard_output (ds);
              file->reader = active_file = proc_open_filtering (ds, false);
            }
          else
            file->reader = casereader_clone (active_file);
        }
      if (!file->is_sorted)
        file->reader = sort_execute (file->reader, &file->by_vars);
      taint_propagate (casereader_get_taint (file->reader), taint);
      file->data = casereader_read (file->reader);
      if (file->type == COMB_FILE)
        case_matcher_add_input (proc.matcher, &file->by_vars,
                                &file->data, &file->is_minimal);
    }

  if (command == COMB_ADD)
    execute_add_files (&proc);
  else if (command == COMB_MATCH)
    execute_match_files (&proc);
  else if (command == COMB_UPDATE)
    execute_update (&proc);
  else
    NOT_REACHED ();

  case_matcher_destroy (proc.matcher);
  proc.matcher = NULL;
  close_all_comb_files (&proc);
  if (active_file != NULL)
    proc_commit (ds);

  dataset_set_dict (ds, proc.dict);
  dataset_set_source (ds, casewriter_make_reader (proc.output));
  proc.dict = NULL;
  proc.output = NULL;

  free_comb_proc (&proc);

  free (first_name);
  free (last_name);

  return taint_destroy (taint) ? CMD_SUCCESS : CMD_CASCADING_FAILURE;

 error:
  if (active_file != NULL)
    proc_commit (ds);
  free_comb_proc (&proc);
  taint_destroy (taint);
  free (first_name);
  free (last_name);
  return CMD_CASCADING_FAILURE;
}
Beispiel #9
0
int get_token(int lookup_flag = 0)
{
  for (;;) {
    int c = get_char();
    while (c == ' ' || c == '\n')
      c = get_char();
    switch (c) {
    case EOF:
      {
	add_context("end of input");
      }
      return 0;
    case '"':
      {
	int quoted = 0;
	token_buffer.clear();
	for (;;) {
	  c = get_char();
	  if (c == EOF) {
	    lex_error("missing \"");
	    break;
	  }
	  else if (c == '\n') {
	    lex_error("newline before end of quoted text");
	    break;
	  }
	  else if (c == '"') {
	    if (!quoted)
	      break;
	    token_buffer[token_buffer.length() - 1] = '"';
	    quoted = 0;
	  }
	  else {
	    token_buffer += c;
	    quoted = quoted ? 0 : c == '\\';
	  }
	}
      }
      add_quoted_context(token_buffer);
      return QUOTED_TEXT;
    case '{':
    case '}':
    case '^':
    case '~':
    case '\t':
      add_context(c);
      return c;
    default:
      {
	int break_flag = 0;
	int quoted = 0;
	token_buffer.clear();
	if (c == '\\')
	  quoted = 1;
	else
	  token_buffer += c;
	int done = 0;
	while (!done) {
	  c = peek_char();
	  if (!quoted && lookup_flag != 0 && c == '(') {
	    token_buffer += '\0';
	    definition *def = macro_table.lookup(token_buffer.contents());
	    if (def && def->is_macro && !def->is_simple) {
	      (void)get_char();	// skip initial '('
	      interpolate_macro_with_args(def->contents);
	      break_flag = 1;
	      break;
	    }
	    token_buffer.set_length(token_buffer.length() - 1);
	  }
	  if (quoted) {
	    quoted = 0;
	    switch (c) {
	    case EOF:
	      lex_error("`\\' ignored at end of equation");
	      done = 1;
	      break;
	    case '\n':
	      lex_error("`\\' ignored because followed by newline");
	      done = 1;
	      break;
	    case '\t':
	      lex_error("`\\' ignored because followed by tab");
	      done = 1;
	      break;
	    case '"':
	      (void)get_char();
	      token_buffer += '"';
	      break;
	    default:
	      (void)get_char();
	      token_buffer += '\\';
	      token_buffer += c;
	      break;
	    }
	  }
	  else {
	    switch (c) {
	    case EOF:
	    case '{':
	    case '}':
	    case '^':
	    case '~':
	    case '"':
	    case ' ':
	    case '\t':
	    case '\n':
	      done = 1;
	      break;
	    case '\\':
	      (void)get_char();
	      quoted = 1;
	      break;
	    default:
	      (void)get_char();
	      token_buffer += char(c);
	      break;
	    }
	  }
	}
	if (break_flag || token_buffer.length() == 0)
	  break;
	if (lookup_flag != 0) {
	  token_buffer += '\0';
	  definition *def = macro_table.lookup(token_buffer.contents());
	  token_buffer.set_length(token_buffer.length() - 1);
	  if (def) {
	    if (def->is_macro) {
	      current_input = new macro_input(def->contents, current_input);
	      break;
	    }
	    else if (lookup_flag == 1) {
	      add_context(token_buffer);
	      return def->tok;
	    }
	  }
	}
	add_context(token_buffer);
	return TEXT;
      }
    }
  }
}
Beispiel #10
0
token lex() {
    int state = 0;  

    // remove last token from buffer.
    int n = BUFFER_SIZE - forward;
    strncpy(buffer, buffer+forward, n);
    buffer[n] = '\0';     
    lexeme_beginning = 0;
    forward = 0;

    int buffer_end = strlen(buffer);

    if (!end_reached) {
        // fill buffer
        while (buffer_end < BUFFER_SIZE - 1) {
            char c = getchar();
            if (!feof(stdin)) {
                buffer[buffer_end++] = c;
            } else {
                end_reached = 1;
                // EOF marker.
                buffer[buffer_end++] = EOF_MARKER;
                break;
            }
        }      
        buffer[buffer_end] = '\0';    
    }

    while (1) {
        char c = buffer[forward++];
        switch(state) {
            case 0: if (c == ' ' || c == '\t' || c == '\n') {
                state = 0;
                lexeme_beginning++;
            } else {
                switch(c) {
                    case ';': return SEMICOLON;
                    case ')': return CLOSE_BRACKET;
                    case '(': return OPEN_BRACKET; 
                    case '=': return EQUALS;
                    case EOF_MARKER: return EOF;
                    default: if (isalpha(c)) { state = 1; }
                             else if (isdigit(c)) { state = 2; }
                             else { lex_error(); }
                             break;
                }
            } break;
            case 1: if (isdigit(c) || isalpha(c)) {
                state = 1;
            } else {
                // retract forward pointer.
                forward--;
                int n = forward - lexeme_beginning;

                strncpy(token_value_str, buffer+lexeme_beginning, n);
                token_value_str[n] = '\0';

                symtable_record_ptr rec = symtable_get(token_value_str);
                if (rec) {
                    return rec->token;
                } else {
                    return ID;
                }
            } break;
            case 2: if (isdigit(c)) {
                state = 2;
            } else {
                // retract forward pointer.
                forward--;
                int n = forward - lexeme_beginning;

                strncpy(token_value_str, buffer+lexeme_beginning, n);
                token_value_str[n] = '\0';

                token_value = atoi(token_value_str);
                return NUM;
            } break;
            default: lex_error();
        }
    }
}
Beispiel #11
0
int
cmd_t_test (struct lexer *lexer, struct dataset *ds)
{
  bool ok;
  const struct dictionary *dict = dataset_dict (ds);
  struct tt tt;
  int mode_count = 0;

  /* Variables pertaining to the paired mode */
  const struct variable **v1 = NULL;
  size_t n_v1;
  const struct variable **v2 = NULL;
  size_t n_v2;
	  
  size_t n_pairs = 0;
  vp *pairs = NULL;


  /* One sample mode */
  double testval = SYSMIS;

  /* Independent samples mode */
  const struct variable *gvar;
  union value gval0;
  union value gval1;
  bool cut = false;

  tt.wv = dict_get_weight (dict);
  tt.dict = dict;
  tt.confidence = 0.95;
  tt.exclude = MV_ANY;
  tt.missing_type = MISS_ANALYSIS;
  tt.n_vars = 0;
  tt.vars = NULL;
  tt.mode = MODE_undef;

  lex_match (lexer, T_EQUALS);

  for (; lex_token (lexer) != T_ENDCMD; )
    {
      lex_match (lexer, T_SLASH);
      if (lex_match_id (lexer, "TESTVAL"))
	{
	  mode_count++;
	  tt.mode = MODE_SINGLE;
	  lex_match (lexer, T_EQUALS);
	  lex_force_num (lexer);
	  testval = lex_number (lexer);
	  lex_get (lexer);
	}
      else if (lex_match_id (lexer, "GROUPS"))
	{
	  mode_count++;
	  cut = false;
	  tt.mode = MODE_INDEP;
	  lex_match (lexer, T_EQUALS);

	  if (NULL == (gvar = parse_variable (lexer, dict)))
	    goto parse_failed;
      
	  if (lex_match (lexer, T_LPAREN))
	    {

	      value_init (&gval0, var_get_width (gvar));
	      parse_value (lexer, &gval0, gvar);
	      cut = true;
	      if (lex_match (lexer, T_COMMA))
		{
		  value_init (&gval1, var_get_width (gvar));
		  parse_value (lexer, &gval1, gvar);
		  cut = false;
		}

	      lex_force_match (lexer, T_RPAREN);
	    }
	  else
	    {
	      value_init (&gval0, 0);
	      value_init (&gval1, 0);
	      gval0.f = 1.0;
	      gval1.f = 2.0;
	      cut = false;
	    }

	  if ( cut == true && var_is_alpha (gvar))
	    {
	      msg (SE, _("When applying %s to a string variable, two "
			 "values must be specified."), "GROUPS");
	      goto parse_failed;
	    }
	}
      else if (lex_match_id (lexer, "PAIRS"))
	{
	  bool with = false;
	  bool paired = false;

	  if (tt.n_vars > 0)
	    {
	      msg (SE, _("%s subcommand may not be used with %s."), "VARIABLES", "PAIRS");
	      goto parse_failed;
	    }

	  mode_count++;
	  tt.mode = MODE_PAIRED;
	  lex_match (lexer, T_EQUALS);

	  if (!parse_variables_const (lexer, dict,
				      &v1, &n_v1,
				      PV_NO_DUPLICATE | PV_NUMERIC))
	    goto parse_failed;

	  if ( lex_match (lexer, T_WITH))
	    {
	      with = true;
	      if (!parse_variables_const (lexer, dict,
					  &v2, &n_v2,
					  PV_NO_DUPLICATE | PV_NUMERIC))
		goto parse_failed;

	      if (lex_match (lexer, T_LPAREN)
		  && lex_match_id (lexer, "PAIRED")
		  && lex_match (lexer, T_RPAREN))
		{
		  paired = true;
		  if (n_v1 != n_v2)
		    {
		      msg (SE, _("PAIRED was specified but the number of variables "
				 "preceding WITH (%zu) did not match the number "
				 "following (%zu)."),
			   n_v1, n_v2);
		      goto parse_failed;
		    }
		}
	    }
	  {
	    int i;

	    if ( !with )
	      n_pairs = (n_v1 * (n_v1 - 1)) / 2.0;
	    else if ( paired )
	      n_pairs = n_v1;
	    else
	      n_pairs = n_v1 * n_v2;
	  
	    pairs = xcalloc (n_pairs, sizeof *pairs);

	    if ( with)
	      {
		int x = 0;
		if (paired)
		  {
		    for (i = 0 ; i < n_v1; ++i)
		      {
			vp *pair = &pairs[i];
			(*pair)[0] = v1[i];
			(*pair)[1] = v2[i];
		      }	
		  }
		else
		  {
		    for (i = 0 ; i < n_v1; ++i)
		      {
			int j;
			for (j = 0 ; j < n_v2; ++j)
			  {
			    vp *pair = &pairs[x++];
			    (*pair)[0] = v1[i];
			    (*pair)[1] = v2[j];
			  }
		      }
		  }
	      }
	    else
	      {
		int x = 0;
		for (i = 0 ; i < n_v1; ++i)
		  {
		    int j;

		    for (j = i + 1 ; j < n_v1; ++j)
		      {
			vp *pair = &pairs[x++];
			(*pair)[0] = v1[i];
			(*pair)[1] = v1[j];
		      }
		  }
	      }

	  }
	}
      else if (lex_match_id (lexer, "VARIABLES"))
	{
	  if ( tt.mode == MODE_PAIRED)
	    {
	      msg (SE, _("%s subcommand may not be used with %s."), "VARIABLES", "PAIRS");
	      goto parse_failed;
	    }

	  lex_match (lexer, T_EQUALS);

	  if (!parse_variables_const (lexer, dict,
				      &tt.vars,
				      &tt.n_vars,
				      PV_NO_DUPLICATE | PV_NUMERIC))
	    goto parse_failed;
	}
      else if ( lex_match_id (lexer, "MISSING"))
	{
          lex_match (lexer, T_EQUALS);
          while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
            {
	      if (lex_match_id (lexer, "INCLUDE"))
		{
		  tt.exclude = MV_SYSTEM;
		}
	      else if (lex_match_id (lexer, "EXCLUDE"))
		{
		  tt.exclude = MV_ANY;
		}
	      else if (lex_match_id (lexer, "LISTWISE"))
		{
		  tt.missing_type = MISS_LISTWISE;
		}
	      else if (lex_match_id (lexer, "ANALYSIS"))
		{
		  tt.missing_type = MISS_ANALYSIS;
		}
	      else
		{
                  lex_error (lexer, NULL);
		  goto parse_failed;
		}
	      lex_match (lexer, T_COMMA);
	    }
	}
      else if (lex_match_id (lexer, "CRITERIA"))
	{
          lex_match (lexer, T_EQUALS);
	  if ( lex_force_match_id (lexer, "CIN"))
	    if ( lex_force_match (lexer, T_LPAREN))
	      {
		lex_force_num (lexer);
		tt.confidence = lex_number (lexer);
		lex_get (lexer);
		lex_force_match (lexer, T_RPAREN);
	      }
	}
      else 
	{
	  lex_error (lexer, NULL);
	  goto parse_failed;
	}
    }

  if ( mode_count != 1)
    {
      msg (SE, _("Exactly one of TESTVAL, GROUPS and PAIRS subcommands "
		 "must be specified."));
      goto parse_failed;
    }

  if (tt.n_vars == 0 && tt.mode != MODE_PAIRED)
    {
      lex_sbc_missing ("VARIABLES");
      goto parse_failed;
    }



  /* Deal with splits etc */
  {
    struct casereader *group;
    struct casegrouper *grouper = casegrouper_create_splits (proc_open (ds), dict);

    while (casegrouper_get_next_group (grouper, &group))
      {
	if ( tt.mode == MODE_SINGLE)
	  {
	    if ( tt.missing_type == MISS_LISTWISE )
	      group  = casereader_create_filter_missing (group,
							 tt.vars, tt.n_vars,
							 tt.exclude,
							 NULL,  NULL);
	    one_sample_run (&tt, testval, group);
	  }
	else if ( tt.mode == MODE_PAIRED)
	  {
	    if ( tt.missing_type == MISS_LISTWISE )
	      {
		group  = casereader_create_filter_missing (group,
							   v1, n_v1,
							   tt.exclude,
							   NULL,  NULL);
		group  = casereader_create_filter_missing (group,
							   v2, n_v2,
							   tt.exclude,
							   NULL,  NULL);
	      }

	    paired_run (&tt, n_pairs, pairs, group);
	  }
	else /* tt.mode == MODE_INDEP */
	  {
	    if ( tt.missing_type == MISS_LISTWISE )
	      {
		group  = casereader_create_filter_missing (group,
							   tt.vars, tt.n_vars,
							   tt.exclude,
							   NULL,  NULL);

		group  = casereader_create_filter_missing (group,
							   &gvar, 1,
							   tt.exclude,
							   NULL,  NULL);

	      }

	    indep_run (&tt, gvar, cut, &gval0, &gval1, group);
	  }
      }

    ok = casegrouper_destroy (grouper);
    ok = proc_commit (ds) && ok;
  }

  free (pairs);
  free (v1);
  free (v2);

  free (tt.vars);

  return ok ? CMD_SUCCESS : CMD_FAILURE;

 parse_failed:
  return CMD_FAILURE;
}
Beispiel #12
0
/* Parse all the aggregate functions. */
static bool
parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
			   struct agr_proc *agr)
{
  struct agr_var *tail; /* Tail of linked list starting at agr->vars. */

  /* Parse everything. */
  tail = NULL;
  for (;;)
    {
      char **dest;
      char **dest_label;
      size_t n_dest;
      struct string function_name;

      enum mv_class exclude;
      const struct agr_func *function;
      int func_index;

      union agr_argument arg[2];

      const struct variable **src;
      size_t n_src;

      size_t i;

      dest = NULL;
      dest_label = NULL;
      n_dest = 0;
      src = NULL;
      function = NULL;
      n_src = 0;
      arg[0].c = NULL;
      arg[1].c = NULL;
      ds_init_empty (&function_name);

      /* Parse the list of target variables. */
      while (!lex_match (lexer, T_EQUALS))
	{
	  size_t n_dest_prev = n_dest;

	  if (!parse_DATA_LIST_vars (lexer, dict, &dest, &n_dest,
                                     (PV_APPEND | PV_SINGLE | PV_NO_SCRATCH
                                      | PV_NO_DUPLICATE)))
	    goto error;

	  /* Assign empty labels. */
	  {
	    int j;

	    dest_label = xnrealloc (dest_label, n_dest, sizeof *dest_label);
	    for (j = n_dest_prev; j < n_dest; j++)
	      dest_label[j] = NULL;
	  }



	  if (lex_is_string (lexer))
	    {
	      dest_label[n_dest - 1] = xstrdup (lex_tokcstr (lexer));
	      lex_get (lexer);
	    }
	}

      /* Get the name of the aggregation function. */
      if (lex_token (lexer) != T_ID)
	{
	  lex_error (lexer, _("expecting aggregation function"));
	  goto error;
	}

      ds_assign_substring (&function_name, lex_tokss (lexer));
      exclude = ds_chomp_byte (&function_name, '.') ? MV_SYSTEM : MV_ANY;

      for (function = agr_func_tab; function->name; function++)
	if (!c_strcasecmp (function->name, ds_cstr (&function_name)))
	  break;
      if (NULL == function->name)
	{
	  msg (SE, _("Unknown aggregation function %s."),
	       ds_cstr (&function_name));
	  goto error;
	}
      ds_destroy (&function_name);
      func_index = function - agr_func_tab;
      lex_get (lexer);

      /* Check for leading lparen. */
      if (!lex_match (lexer, T_LPAREN))
	{
	  if (function->src_vars == AGR_SV_YES)
	    {
              lex_force_match (lexer, T_LPAREN);
	      goto error;
	    }
	}
      else
        {
	  /* Parse list of source variables. */
	  {
	    int pv_opts = PV_NO_SCRATCH;

	    if (func_index == SUM || func_index == MEAN || func_index == SD)
	      pv_opts |= PV_NUMERIC;
	    else if (function->n_args)
	      pv_opts |= PV_SAME_TYPE;

	    if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
	      goto error;
	  }

	  /* Parse function arguments, for those functions that
	     require arguments. */
	  if (function->n_args != 0)
	    for (i = 0; i < function->n_args; i++)
	      {
		int type;

		lex_match (lexer, T_COMMA);
		if (lex_is_string (lexer))
		  {
		    arg[i].c = recode_string (dict_get_encoding (agr->dict),
                                              "UTF-8", lex_tokcstr (lexer),
                                              -1);
		    type = VAL_STRING;
		  }
		else if (lex_is_number (lexer))
		  {
		    arg[i].f = lex_tokval (lexer);
		    type = VAL_NUMERIC;
		  }
                else
                  {
		    msg (SE, _("Missing argument %zu to %s."),
                         i + 1, function->name);
		    goto error;
		  }

		lex_get (lexer);

		if (type != var_get_type (src[0]))
		  {
		    msg (SE, _("Arguments to %s must be of same type as "
			       "source variables."),
			 function->name);
		    goto error;
		  }
	      }

	  /* Trailing rparen. */
	  if (!lex_force_match (lexer, T_RPAREN))
            goto error;

	  /* Now check that the number of source variables match
	     the number of target variables.  If we check earlier
	     than this, the user can get very misleading error
	     message, i.e. `AGGREGATE x=SUM(y t).' will get this
	     error message when a proper message would be more
	     like `unknown variable t'. */
	  if (n_src != n_dest)
	    {
	      msg (SE, _("Number of source variables (%zu) does not match "
			 "number of target variables (%zu)."),
		    n_src, n_dest);
	      goto error;
	    }

          if ((func_index == PIN || func_index == POUT
              || func_index == FIN || func_index == FOUT)
              && (var_is_numeric (src[0])
                  ? arg[0].f > arg[1].f
                  : str_compare_rpad (arg[0].c, arg[1].c) > 0))
            {
              union agr_argument t = arg[0];
              arg[0] = arg[1];
              arg[1] = t;

              msg (SW, _("The value arguments passed to the %s function "
                         "are out-of-order.  They will be treated as if "
                         "they had been specified in the correct order."),
                   function->name);
            }
	}

      /* Finally add these to the linked list of aggregation
         variables. */
      for (i = 0; i < n_dest; i++)
	{
	  struct agr_var *v = xzalloc (sizeof *v);

	  /* Add variable to chain. */
	  if (agr->agr_vars != NULL)
	    tail->next = v;
	  else
	    agr->agr_vars = v;
          tail = v;
	  tail->next = NULL;
          v->moments = NULL;

	  /* Create the target variable in the aggregate
             dictionary. */
	  {
	    struct variable *destvar;

	    v->function = func_index;

	    if (src)
	      {
		v->src = src[i];

		if (var_is_alpha (src[i]))
		  {
		    v->function |= FSTRING;
		    v->string = xmalloc (var_get_width (src[i]));
		  }

		if (function->alpha_type == VAL_STRING)
		  destvar = dict_clone_var_as (agr->dict, v->src, dest[i]);
		else
                  {
                    assert (var_is_numeric (v->src)
                            || function->alpha_type == VAL_NUMERIC);
                    destvar = dict_create_var (agr->dict, dest[i], 0);
                    if (destvar != NULL)
                      {
                        struct fmt_spec f;
                        if ((func_index == N || func_index == NMISS)
                            && dict_get_weight (dict) != NULL)
                          f = fmt_for_output (FMT_F, 8, 2);
                        else
                          f = function->format;
                        var_set_both_formats (destvar, &f);
                      }
                  }
	      } else {
                struct fmt_spec f;
		v->src = NULL;
		destvar = dict_create_var (agr->dict, dest[i], 0);
		if (destvar != NULL)
		  {
		    if ((func_index == N || func_index == NMISS)
			&& dict_get_weight (dict) != NULL)
		      f = fmt_for_output (FMT_F, 8, 2);
		    else
		      f = function->format;
		    var_set_both_formats (destvar, &f);
		  }
	    }

	    if (!destvar)
	      {
		msg (SE, _("Variable name %s is not unique within the "
			   "aggregate file dictionary, which contains "
			   "the aggregate variables and the break "
			   "variables."),
		     dest[i]);
		goto error;
	      }

	    free (dest[i]);
	    if (dest_label[i])
              var_set_label (destvar, dest_label[i]);

	    v->dest = destvar;
	  }

	  v->exclude = exclude;

	  if (v->src != NULL)
	    {
	      int j;

	      if (var_is_numeric (v->src))
		for (j = 0; j < function->n_args; j++)
		  v->arg[j].f = arg[j].f;
	      else
		for (j = 0; j < function->n_args; j++)
		  v->arg[j].c = xstrdup (arg[j].c);
	    }
	}

      if (src != NULL && var_is_alpha (src[0]))
	for (i = 0; i < function->n_args; i++)
	  {
	    free (arg[i].c);
	    arg[i].c = NULL;
	  }

      free (src);
      free (dest);
      free (dest_label);

      if (!lex_match (lexer, T_SLASH))
	{
	  if (lex_token (lexer) == T_ENDCMD)
	    return true;

	  lex_error (lexer, "expecting end of command");
	  return false;
	}
      continue;

    error:
      ds_destroy (&function_name);
      for (i = 0; i < n_dest; i++)
	{
	  free (dest[i]);
	  free (dest_label[i]);
	}
      free (dest);
      free (dest_label);
      free (arg[0].c);
      free (arg[1].c);
      if (src && n_src && var_is_alpha (src[0]))
	for (i = 0; i < function->n_args; i++)
	  {
	    free (arg[i].c);
	    arg[i].c = NULL;
	  }
      free (src);

      return false;
    }
}
Beispiel #13
0
int
cmd_reliability (struct lexer *lexer, struct dataset *ds)
{
  const struct dictionary *dict = dataset_dict (ds);

  struct reliability reliability;
  reliability.n_variables = 0;
  reliability.variables = NULL;
  reliability.model = MODEL_ALPHA;
    reliability.exclude = MV_ANY;
  reliability.summary = 0;

  reliability.wv = dict_get_weight (dict);

  reliability.total_start = 0;

  lex_match (lexer, T_SLASH);

  if (!lex_force_match_id (lexer, "VARIABLES"))
    {
      goto error;
    }

  lex_match (lexer, T_EQUALS);

  if (!parse_variables_const (lexer, dict, &reliability.variables, &reliability.n_variables,
			      PV_NO_DUPLICATE | PV_NUMERIC))
    goto error;

  if (reliability.n_variables < 2)
    msg (MW, _("Reliability on a single variable is not useful."));


    {
      int i;
      struct cronbach *c;
      /* Create a default Scale */

      reliability.n_sc = 1;
      reliability.sc = xzalloc (sizeof (struct cronbach) * reliability.n_sc);

      ds_init_cstr (&reliability.scale_name, "ANY");

      c = &reliability.sc[0];
      c->n_items = reliability.n_variables;
      c->items = xzalloc (sizeof (struct variable*) * c->n_items);

      for (i = 0 ; i < c->n_items ; ++i)
	c->items[i] = reliability.variables[i];
    }



  while (lex_token (lexer) != T_ENDCMD)
    {
      lex_match (lexer, T_SLASH);

      if (lex_match_id (lexer, "SCALE"))
	{
	  struct const_var_set *vs;
	  if ( ! lex_force_match (lexer, T_LPAREN))
	    goto error;

	  if ( ! lex_force_string (lexer) ) 
	    goto error;

	  ds_init_substring (&reliability.scale_name, lex_tokss (lexer));

	  lex_get (lexer);

	  if ( ! lex_force_match (lexer, T_RPAREN))
	    goto error;

          lex_match (lexer, T_EQUALS);

	  vs = const_var_set_create_from_array (reliability.variables, reliability.n_variables);


	  if (!parse_const_var_set_vars (lexer, vs, &reliability.sc->items, &reliability.sc->n_items, 0))
	    {
	      const_var_set_destroy (vs);
	      goto error;
	    }

	  const_var_set_destroy (vs);
	}
      else if (lex_match_id (lexer, "MODEL"))
	{
          lex_match (lexer, T_EQUALS);
	  if (lex_match_id (lexer, "ALPHA"))
	    {
	      reliability.model = MODEL_ALPHA;
	    }
	  else if (lex_match_id (lexer, "SPLIT"))
	    {
	      reliability.model = MODEL_SPLIT;
	      reliability.split_point = -1;

	      if ( lex_match (lexer, T_LPAREN))
		{
		  lex_force_num (lexer);
		  reliability.split_point = lex_number (lexer);
		  lex_get (lexer);
		  lex_force_match (lexer, T_RPAREN);
		}
	    }
	  else
	    goto error;
	}
      else if (lex_match_id (lexer, "SUMMARY"))
        {
          lex_match (lexer, T_EQUALS);
	  if (lex_match_id (lexer, "TOTAL"))
	    {
	      reliability.summary |= SUMMARY_TOTAL;
	    }
	  else if (lex_match (lexer, T_ALL))
	    {
	      reliability.summary = 0xFFFF;
	    }
	  else
	    goto error;
	}
      else if (lex_match_id (lexer, "MISSING"))
        {
          lex_match (lexer, T_EQUALS);
          while (lex_token (lexer) != T_ENDCMD && lex_token (lexer) != T_SLASH)
            {
	      if (lex_match_id (lexer, "INCLUDE"))
		{
		  reliability.exclude = MV_SYSTEM;
		}
	      else if (lex_match_id (lexer, "EXCLUDE"))
		{
		  reliability.exclude = MV_ANY;
		}
	      else
		{
                  lex_error (lexer, NULL);
		  goto error;
		}
	    }
	}
      else
	{
	  lex_error (lexer, NULL);
	  goto error;
	}
    }

  if ( reliability.model == MODEL_SPLIT)
    {
      int i;
      const struct cronbach *s;

      if ( reliability.split_point >= reliability.n_variables)
        {
          msg (ME, _("The split point must be less than the number of variables"));
          goto error;
        }

      reliability.n_sc += 2 ;
      reliability.sc = xrealloc (reliability.sc, sizeof (struct cronbach) * reliability.n_sc);

      s = &reliability.sc[0];

      reliability.sc[1].n_items =
	(reliability.split_point == -1) ? s->n_items / 2 : reliability.split_point;

      reliability.sc[2].n_items = s->n_items - reliability.sc[1].n_items;
      reliability.sc[1].items = xzalloc (sizeof (struct variable *)
				 * reliability.sc[1].n_items);

      reliability.sc[2].items = xzalloc (sizeof (struct variable *) *
				 reliability.sc[2].n_items);

      for  (i = 0; i < reliability.sc[1].n_items ; ++i)
	reliability.sc[1].items[i] = s->items[i];

      while (i < s->n_items)
	{
	  reliability.sc[2].items[i - reliability.sc[1].n_items] = s->items[i];
	  i++;
	}
    }

  if ( reliability.summary & SUMMARY_TOTAL)
    {
      int i;
      const int base_sc = reliability.n_sc;

      reliability.total_start = base_sc;

      reliability.n_sc +=  reliability.sc[0].n_items ;
      reliability.sc = xrealloc (reliability.sc, sizeof (struct cronbach) * reliability.n_sc);


      for (i = 0 ; i < reliability.sc[0].n_items; ++i )
	{
	  int v_src;
	  int v_dest = 0;
	  struct cronbach *s = &reliability.sc[i + base_sc];

	  s->n_items = reliability.sc[0].n_items - 1;
	  s->items = xzalloc (sizeof (struct variable *) * s->n_items);
	  for (v_src = 0 ; v_src < reliability.sc[0].n_items ; ++v_src)
	    {
	      if ( v_src != i)
		s->items[v_dest++] = reliability.sc[0].items[v_src];
	    }
	}
    }


  if ( ! run_reliability (ds, &reliability)) 
    goto error;

  free (reliability.variables);
  return CMD_SUCCESS;

 error:
  free (reliability.variables);
  return CMD_FAILURE;
}
Beispiel #14
0
void do_picture(FILE *fp)
{
  flyback_flag = 0;
  int c;
  a_delete graphname;
  graphname = strsave("graph");		// default picture name in TeX mode
  while ((c = getc(fp)) == ' ')
    ;
  if (c == '<') {
    string filename;
    while ((c = getc(fp)) == ' ')
      ;
    while (c != EOF && c != ' ' && c != '\n') {
      filename += char(c);
      c = getc(fp);
    }
    if (c == ' ') {
      do {
	c = getc(fp);
      } while (c != EOF && c != '\n');
    }
    if (c == '\n') 
      current_lineno++;
    if (filename.length() == 0)
      error("missing filename after `<'");
    else {
      filename += '\0';
      const char *old_filename = current_filename;
      int old_lineno = current_lineno;
      // filenames must be permanent
      do_file(strsave(filename.contents()));
      current_filename = old_filename;
      current_lineno = old_lineno;
    }
    out->set_location(current_filename, current_lineno);
  }
  else {
    out->set_location(current_filename, current_lineno);
    string start_line;
    while (c != EOF) {
      if (c == '\n') {
	current_lineno++;
	break;
      }
      start_line += c;
      c = getc(fp);
    }
    if (c == EOF)
      return;
    start_line += '\0';
    double wid, ht;
    switch (sscanf(&start_line[0], "%lf %lf", &wid, &ht)) {
    case 1:
      ht = 0.0;
      break;
    case 2:
      break;
    default:
      ht = wid = 0.0;
      break;
    }
    out->set_desired_width_height(wid, ht);
    out->set_args(start_line.contents());
    lex_init(new top_input(fp));
    if (yyparse()) {
      had_parse_error = 1;
      lex_error("giving up on this picture");
    }
    parse_cleanup();
    lex_cleanup();

    // skip the rest of the .PF/.PE line
    while ((c = getc(fp)) != EOF && c != '\n')
      ;
    if (c == '\n')
      current_lineno++;
    out->set_location(current_filename, current_lineno);
  }
}
Beispiel #15
0
int get_delimited()
{
  token_buffer.clear();
  int c = input_stack::get_char();
  while (c == ' ' || c == '\t' || c == '\n')
    c = input_stack::get_char();
  if (c == EOF) {
    lex_error("missing delimiter");
    return 0;
  }
  context_buffer = char(c);
  int had_newline = 0;
  int start = c;
  int level = 0;
  enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL;
  for (;;) {
    c = input_stack::get_char();
    if (c == EOF) {
      lex_error("missing closing delimiter");
      return 0;
    }
    if (c == '\n')
      had_newline = 1;
    else if (!had_newline)
      context_buffer += char(c);
    switch (state) {
    case NORMAL:
      if (start == '{') {
	if (c == '{') {
	  level++;
	  break;
	}
	if (c == '}') {
	  if (--level < 0)
	    state = DELIM_END;
	  break;
	}
      }
      else {
	if (c == start) {
	  state = DELIM_END;
	  break;
	}
      }
      if (c == '"')
	state = IN_STRING;
      break;
    case IN_STRING_QUOTED:
      if (c == '\n')
	state = NORMAL;
      else
	state = IN_STRING;
      break;
    case IN_STRING:
      if (c == '"' || c == '\n')
	state = NORMAL;
      else if (c == '\\')
	state = IN_STRING_QUOTED;
      break;
    case DELIM_END:
      // This case it just to shut cfront 2.0 up.
    default:
      assert(0);
    }
    if (state == DELIM_END)
      break;
    token_buffer += c;
  }
  return 1;
}
Beispiel #16
0
static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **literal)
{
    LONGLONG d, hlp;
    int exp = 0;

    d = int_part;
    while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
        hlp = d*10 + *(ctx->ptr++) - '0';
        if(d>MAXLONGLONG/10 || hlp<0) {
            exp++;
            break;
        }
        else
            d = hlp;
    }
    while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
        exp++;
        ctx->ptr++;
    }

    if(*ctx->ptr == '.') {
        ctx->ptr++;

        while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
            hlp = d*10 + *(ctx->ptr++) - '0';
            if(d>MAXLONGLONG/10 || hlp<0)
                break;

            d = hlp;
            exp--;
        }
        while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
            ctx->ptr++;
    }

    if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' || *ctx->ptr == 'E')) {
        int sign = 1, e = 0;

        ctx->ptr++;
        if(ctx->ptr < ctx->end) {
            if(*ctx->ptr == '+') {
                ctx->ptr++;
            }else if(*ctx->ptr == '-') {
                sign = -1;
                ctx->ptr++;
            }else if(!isdigitW(*ctx->ptr)) {
                WARN("Expected exponent part\n");
                return lex_error(ctx, E_FAIL);
            }
        }

        if(ctx->ptr == ctx->end) {
            WARN("unexpected end of file\n");
            return lex_error(ctx, E_FAIL);
        }

        while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
            if(e > INT_MAX/10 || (e = e*10 + *ctx->ptr++ - '0')<0)
                e = INT_MAX;
        }
        e *= sign;

        if(exp<0 && e<0 && e+exp>0) exp = INT_MIN;
        else if(exp>0 && e>0 && e+exp<0) exp = INT_MAX;
        else exp += e;
    }

    if(is_identifier_char(*ctx->ptr)) {
        WARN("wrong char after zero\n");
        return lex_error(ctx, JS_E_MISSING_SEMICOLON);
    }

    *literal = new_double_literal(ctx, exp>=0 ? d*pow(10, exp) : d/pow(10, -exp));
    return tNumericLiteral;
}