void gram_error(char *s) { lex_error(0, s); }
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; }
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; }
/* 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; }
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; }
/* 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; }
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; }
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; }
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; } } } }
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(); } } }
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; }
/* 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; } }
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; }
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); } }
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; }
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; }