/*
 * Copyright (C) 2006 Dan Carpenter.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
 *
 * Copyright 2019 Joyent, Inc.
 */

#ifndef   	SMATCH_H_
# define   	SMATCH_H_

#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <float.h>
#include <sys/time.h>
#include <sqlite3.h>
#include "lib.h"
#include "allocate.h"
#include "scope.h"
#include "parse.h"
#include "expression.h"
#include "avl.h"

typedef struct {
	struct symbol *type;
	union {
		long long value;
		unsigned long long uvalue;
		float fvalue;
		double dvalue;
		long double ldvalue;
	};
} sval_t;

typedef long long mtag_t;

struct smatch_state {
	const char *name;
	void *data;
};
#define STATE(_x) static struct smatch_state _x = { .name = #_x }
extern struct smatch_state undefined;
extern struct smatch_state ghost;
extern struct smatch_state merged;
extern struct smatch_state true_state;
extern struct smatch_state false_state;
DECLARE_ALLOCATOR(smatch_state);

static inline void *INT_PTR(int i)
{
	return (void *)(long)i;
}

static inline int PTR_INT(void *p)
{
	return (int)(long)p;
}

struct tracker {
	char *name;
	struct symbol *sym;
	unsigned short owner;
};
DECLARE_ALLOCATOR(tracker);
DECLARE_PTR_LIST(tracker_list, struct tracker);
DECLARE_PTR_LIST(stree_stack, struct stree);

/* The first 3 struct members must match struct tracker */
struct sm_state {
	const char *name;
	struct symbol *sym;
	unsigned short owner;
	unsigned short merged:1;
	unsigned int line;
  	struct smatch_state *state;
	struct stree *pool;
	struct sm_state *left;
	struct sm_state *right;
	struct state_list *possible;
};

struct var_sym {
	char *var;
	struct symbol *sym;
};
DECLARE_ALLOCATOR(var_sym);
DECLARE_PTR_LIST(var_sym_list, struct var_sym);

struct constraint {
	int op;
	int id;
};
DECLARE_PTR_LIST(constraint_list, struct constraint);

struct alloc_info {
	const char *fn;
	int size_param, nr;
};
extern struct alloc_info *alloc_funcs;

struct bit_info {
	unsigned long long set;
	unsigned long long possible;
};

enum hook_type {
	EXPR_HOOK,
	EXPR_HOOK_AFTER,
	STMT_HOOK,
	STMT_HOOK_AFTER,
	SYM_HOOK,
	STRING_HOOK,
	DECLARATION_HOOK,
	ASSIGNMENT_HOOK,
	ASSIGNMENT_HOOK_AFTER,
	RAW_ASSIGNMENT_HOOK,
	GLOBAL_ASSIGNMENT_HOOK,
	LOGIC_HOOK,
	CONDITION_HOOK,
	PRELOOP_HOOK,
	SELECT_HOOK,
	WHOLE_CONDITION_HOOK,
	FUNCTION_CALL_HOOK_BEFORE,
	FUNCTION_CALL_HOOK,
	CALL_HOOK_AFTER_INLINE,
	FUNCTION_CALL_HOOK_AFTER_DB,
	CALL_ASSIGNMENT_HOOK,
	MACRO_ASSIGNMENT_HOOK,
	BINOP_HOOK,
	OP_HOOK,
	DEREF_HOOK,
	CASE_HOOK,
	ASM_HOOK,
	CAST_HOOK,
	SIZEOF_HOOK,
	BASE_HOOK,
	FUNC_DEF_HOOK,
	AFTER_DEF_HOOK,
	END_FUNC_HOOK,
	AFTER_FUNC_HOOK,
	RETURN_HOOK,
	INLINE_FN_START,
	INLINE_FN_END,
	END_FILE_HOOK,
	NUM_HOOKS,
};

#define TRUE 1
#define FALSE 0

struct range_list;

void add_hook(void *func, enum hook_type type);
typedef struct smatch_state *(merge_func_t)(struct smatch_state *s1, struct smatch_state *s2);
typedef struct smatch_state *(unmatched_func_t)(struct sm_state *state);
void add_merge_hook(int client_id, merge_func_t *func);
void add_unmatched_state_hook(int client_id, unmatched_func_t *func);
void add_pre_merge_hook(int client_id, void (*hook)(struct sm_state *cur, struct sm_state *other));
typedef void (scope_hook)(void *data);
void add_scope_hook(scope_hook *hook, void *data);
typedef void (func_hook)(const char *fn, struct expression *expr, void *data);
typedef void (implication_hook)(const char *fn, struct expression *call_expr,
				struct expression *assign_expr, void *data);
typedef void (return_implies_hook)(struct expression *call_expr,
				   int param, char *key, char *value);
typedef int (implied_return_hook)(struct expression *call_expr, void *info, struct range_list **rl);
void add_function_hook(const char *look_for, func_hook *call_back, void *data);

void add_function_assign_hook(const char *look_for, func_hook *call_back,
			      void *info);
void add_implied_return_hook(const char *look_for,
			     implied_return_hook *call_back,
			     void *info);
void add_macro_assign_hook(const char *look_for, func_hook *call_back,
			      void *info);
void add_macro_assign_hook_extra(const char *look_for, func_hook *call_back,
			      void *info);
void return_implies_state(const char *look_for, long long start, long long end,
			 implication_hook *call_back, void *info);
void return_implies_state_sval(const char *look_for, sval_t start, sval_t end,
			 implication_hook *call_back, void *info);
void select_return_states_hook(int type, return_implies_hook *callback);
void select_return_states_before(void (*fn)(void));
void select_return_states_after(void (*fn)(void));
int get_implied_return(struct expression *expr, struct range_list **rl);
void allocate_hook_memory(void);
void allocate_tracker_array(int num_checks);

struct modification_data {
	struct smatch_state *prev;
	struct expression *cur;
};

typedef void (modification_hook)(struct sm_state *sm, struct expression *mod_expr);
void add_modification_hook(int owner, modification_hook *call_back);
void add_modification_hook_late(int owner, modification_hook *call_back);
struct smatch_state *get_modification_state(struct expression *expr);

int outside_of_function(void);
const char *get_filename(void);
const char *get_base_file(void);
char *get_function(void);
int get_lineno(void);
extern int final_pass;
extern struct symbol *cur_func_sym;
extern int option_debug;
extern int local_debug;
extern int debug_db;
bool debug_implied(void);
extern int option_info;
extern int option_spammy;
extern int option_timeout;
extern char *trace_variable;
extern struct stree *global_states;
int is_skipped_function(void);
int is_silenced_function(void);
extern bool implications_off;

/* smatch_impossible.c */
int is_impossible_path(void);
void set_path_impossible(void);

extern FILE *sm_outfd;
extern FILE *sql_outfd;
extern FILE *caller_info_fd;
extern int sm_nr_checks;
extern int sm_nr_errors;
extern const char *progname;

/*
 * How to use these routines:
 *
 * sm_fatal(): an internal error of some kind that should immediately exit
 * sm_ierror(): an internal error
 * sm_perror(): an internal error from parsing input source
 * sm_error(): an error from input source
 * sm_warning(): a warning from input source
 * sm_info(): info message (from option_info)
 * sm_debug(): debug message
 * sm_msg(): other message (please avoid using this)
 */

#define sm_printf(msg...) do {						\
	if (final_pass || option_debug || local_debug || debug_db)	\
		fprintf(sm_outfd, msg);					\
} while (0)

static inline void sm_prefix(void)
{
	sm_printf("%s: %s:%d %s() ", progname, get_filename(), get_lineno(), get_function());
}

static inline void print_implied_debug_msg();

extern bool __silence_warnings_for_stmt;

#define sm_print_msg(type, msg...) \
do {                                                           \
	print_implied_debug_msg();                             \
	if (!final_pass && !option_debug && !local_debug && !debug_db)	  \
		break;                                         \
	if (__silence_warnings_for_stmt && !option_debug && !local_debug) \
		break;					       \
	if (!option_info && is_silenced_function())	       \
		break;					       \
	sm_prefix();					       \
	if (type == 1) {				       \
		sm_printf("warn: ");			       \
		sm_nr_checks++;			    	       \
	} else if (type == 2) {				       \
		sm_printf("error: ");			       \
		sm_nr_checks++;				       \
	} else if (type == 3) {				       \
		sm_printf("parse error: ");		       \
		sm_nr_errors++;				       \
	}						       \
        sm_printf(msg);                                        \
        sm_printf("\n");                                       \
} while (0)

#define sm_msg(msg...) do { sm_print_msg(0, msg); } while (0)

extern char *implied_debug_msg;
static inline void print_implied_debug_msg(void)
{
	static struct symbol *last_printed = NULL;

	if (!implied_debug_msg)
		return;
	if (last_printed == cur_func_sym)
		return;
	last_printed = cur_func_sym;
	sm_msg("%s", implied_debug_msg);
}

#define sm_debug(msg...) do { if (option_debug) sm_printf(msg); } while (0)
#define db_debug(msg...) do { if (option_debug || debug_db) sm_printf(msg); } while (0)

#define sm_info(msg...) do {					\
	if (option_debug || (option_info && final_pass)) {	\
		sm_prefix();					\
		sm_printf("info: ");				\
		sm_printf(msg);					\
		sm_printf("\n");				\
	}							\
} while(0)

#define sm_warning(msg...) do { sm_print_msg(1, msg); } while (0)
#define sm_error(msg...) do { sm_print_msg(2, msg); } while (0)
#define sm_perror(msg...) do { sm_print_msg(3, msg); } while (0)

static inline void sm_fatal(const char *fmt, ...)
{
	va_list args;

	va_start(args, fmt);
	vfprintf(sm_outfd, fmt, args);
	va_end(args);

	fprintf(sm_outfd, "\n");

	exit(1);
}

static inline void sm_ierror(const char *fmt, ...)
{
	va_list args;

	sm_nr_errors++;

	fprintf(sm_outfd, "internal error: ");

	va_start(args, fmt);
	vfprintf(sm_outfd, fmt, args);
	va_end(args);

	fprintf(sm_outfd, "\n");
}
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))

struct smatch_state *__get_state(int owner, const char *name, struct symbol *sym);
struct smatch_state *get_state(int owner, const char *name, struct symbol *sym);
struct smatch_state *get_state_expr(int owner, struct expression *expr);
struct state_list *get_possible_states(int owner, const char *name,
				       struct symbol *sym);
struct state_list *get_possible_states_expr(int owner, struct expression *expr);
struct sm_state *set_state(int owner, const char *name, struct symbol *sym,
	       struct smatch_state *state);
struct sm_state *set_state_expr(int owner, struct expression *expr,
		struct smatch_state *state);
void delete_state(int owner, const char *name, struct symbol *sym);
void delete_state_expr(int owner, struct expression *expr);
void __delete_all_states_sym(struct symbol *sym);
void set_true_false_states(int owner, const char *name, struct symbol *sym,
			   struct smatch_state *true_state,
			   struct smatch_state *false_state);
void set_true_false_states_expr(int owner, struct expression *expr,
			   struct smatch_state *true_state,
			   struct smatch_state *false_state);

struct stree *get_all_states_from_stree(int owner, struct stree *source);
struct stree *get_all_states_stree(int id);
struct stree *__get_cur_stree(void);
int is_reachable(void);
void add_get_state_hook(void (*fn)(int owner, const char *name, struct symbol *sym));

/* smatch_helper.c */
DECLARE_PTR_LIST(int_stack, int);
char *alloc_string(const char *str);
char *alloc_string_newline(const char *str);
void free_string(char *str);
void append(char *dest, const char *data, int buff_len);
void remove_parens(char *str);
struct smatch_state *alloc_state_num(int num);
struct smatch_state *alloc_state_str(const char *name);
struct smatch_state *merge_str_state(struct smatch_state *s1, struct smatch_state *s2);
struct smatch_state *alloc_state_expr(struct expression *expr);
struct expression *get_argument_from_call_expr(struct expression_list *args,
					       int num);
struct expression *get_array_expr(struct expression *expr);

char *expr_to_var(struct expression *expr);
struct symbol *expr_to_sym(struct expression *expr);
char *expr_to_str(struct expression *expr);
char *expr_to_str_sym(struct expression *expr,
				     struct symbol **sym_ptr);
char *expr_to_var_sym(struct expression *expr,
			     struct symbol **sym_ptr);
char *expr_to_known_chunk_sym(struct expression *expr, struct symbol **sym);
char *expr_to_chunk_sym_vsl(struct expression *expr, struct symbol **sym, struct var_sym_list **vsl);
int get_complication_score(struct expression *expr);

int sym_name_is(const char *name, struct expression *expr);
int get_const_value(struct expression *expr, sval_t *sval);
int get_value(struct expression *expr, sval_t *val);
int get_implied_value(struct expression *expr, sval_t *val);
int get_implied_value_fast(struct expression *expr, sval_t *sval);
int get_implied_min(struct expression *expr, sval_t *sval);
int get_implied_max(struct expression *expr, sval_t *val);
int get_hard_max(struct expression *expr, sval_t *sval);
int get_fuzzy_min(struct expression *expr, sval_t *min);
int get_fuzzy_max(struct expression *expr, sval_t *max);
int get_absolute_min(struct expression *expr, sval_t *sval);
int get_absolute_max(struct expression *expr, sval_t *sval);
int parse_call_math(struct expression *expr, char *math, sval_t *val);
int parse_call_math_rl(struct expression *call, const char *math, struct range_list **rl);
const char *get_allocation_math(struct expression *expr);
char *get_value_in_terms_of_parameter_math(struct expression *expr);
char *get_value_in_terms_of_parameter_math_var_sym(const char *var, struct symbol *sym);
int expr_is_zero(struct expression *expr);
int known_condition_true(struct expression *expr);
int known_condition_false(struct expression *expr);
int implied_condition_true(struct expression *expr);
int implied_condition_false(struct expression *expr);
int can_integer_overflow(struct symbol *type, struct expression *expr);
void clear_math_cache(void);
void set_fast_math_only(void);
void clear_fast_math_only(void);

int is_array(struct expression *expr);
struct expression *get_array_base(struct expression *expr);
struct expression *get_array_offset(struct expression *expr);
const char *show_state(struct smatch_state *state);
struct statement *get_expression_statement(struct expression *expr);
struct expression *strip_parens(struct expression *expr);
struct expression *strip_expr(struct expression *expr);
struct expression *strip_expr_set_parent(struct expression *expr);
void scoped_state(int my_id, const char *name, struct symbol *sym);
int is_error_return(struct expression *expr);
int getting_address(struct expression *expr);
int get_struct_and_member(struct expression *expr, const char **type, const char **member);
char *get_member_name(struct expression *expr);
char *get_fnptr_name(struct expression *expr);
int cmp_pos(struct position pos1, struct position pos2);
int positions_eq(struct position pos1, struct position pos2);
struct statement *get_current_statement(void);
struct statement *get_prev_statement(void);
struct expression *get_last_expr_from_expression_stmt(struct expression *expr);

#define RETURN_VAR    -1
#define LOCAL_SCOPE   -2
#define FILE_SCOPE    -3
#define GLOBAL_SCOPE  -4
#define UNKNOWN_SCOPE -5
int get_param_num_from_sym(struct symbol *sym);
int get_param_num(struct expression *expr);
struct symbol *get_param_sym_from_num(int num);

int ms_since(struct timeval *start);
int parent_is_gone_var_sym(const char *name, struct symbol *sym);
int parent_is_gone(struct expression *expr);
int invert_op(int op);
int op_remove_assign(int op);
int expr_equiv(struct expression *one, struct expression *two);
void push_int(struct int_stack **stack, int num);
int pop_int(struct int_stack **stack);

/* smatch_type.c */
struct symbol *get_real_base_type(struct symbol *sym);
int type_bytes(struct symbol *type);
int array_bytes(struct symbol *type);
struct symbol *get_pointer_type(struct expression *expr);
struct symbol *get_type(struct expression *expr);
struct symbol *get_final_type(struct expression *expr);
struct symbol *get_promoted_type(struct symbol *left, struct symbol *right);
int type_signed(struct symbol *base_type);
int expr_unsigned(struct expression *expr);
int expr_signed(struct expression *expr);
int returns_unsigned(struct symbol *base_type);
int is_pointer(struct expression *expr);
int returns_pointer(struct symbol *base_type);
sval_t sval_type_max(struct symbol *base_type);
sval_t sval_type_min(struct symbol *base_type);
int nr_bits(struct expression *expr);
int is_void_pointer(struct expression *expr);
int is_char_pointer(struct expression *expr);
int is_string(struct expression *expr);
bool is_struct_ptr(struct symbol *type);
int is_static(struct expression *expr);
bool is_local_variable(struct expression *expr);
int types_equiv(struct symbol *one, struct symbol *two);
bool type_fits(struct symbol *type, struct symbol *test);
int fn_static(void);
const char *global_static();
struct symbol *cur_func_return_type(void);
struct symbol *get_arg_type(struct expression *fn, int arg);
struct symbol *get_member_type_from_key(struct expression *expr, const char *key);
struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key);
int is_struct(struct expression *expr);
char *type_to_str(struct symbol *type);

/* smatch_ignore.c */
void add_ignore(int owner, const char *name, struct symbol *sym);
int is_ignored(int owner, const char *name, struct symbol *sym);
void add_ignore_expr(int owner, struct expression *expr);
int is_ignored_expr(int owner, struct expression *expr);

/* smatch_var_sym */
struct var_sym *alloc_var_sym(const char *var, struct symbol *sym);
struct var_sym_list *expr_to_vsl(struct expression *expr);
void add_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym);
void add_var_sym_expr(struct var_sym_list **list, struct expression *expr);
void del_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym);
int in_var_sym_list(struct var_sym_list *list, const char *var, struct symbol *sym);
struct var_sym_list *clone_var_sym_list(struct var_sym_list *from_vsl);
void merge_var_sym_list(struct var_sym_list **dest, struct var_sym_list *src);
struct var_sym_list *combine_var_sym_lists(struct var_sym_list *one, struct var_sym_list *two);
int var_sym_lists_equiv(struct var_sym_list *one, struct var_sym_list *two);
void free_var_sym_list(struct var_sym_list **list);
void free_var_syms_and_list(struct var_sym_list **list);

/* smatch_tracker */
struct tracker *alloc_tracker(int owner, const char *name, struct symbol *sym);
void add_tracker(struct tracker_list **list, int owner, const char *name,
		struct symbol *sym);
void add_tracker_expr(struct tracker_list **list, int owner, struct expression *expr);
void del_tracker(struct tracker_list **list, int owner, const char *name,
		struct symbol *sym);
int in_tracker_list(struct tracker_list *list, int owner, const char *name,
		struct symbol *sym);
void free_tracker_list(struct tracker_list **list);
void free_trackers_and_list(struct tracker_list **list);

/* smatch_conditions */
int in_condition(void);

/* smatch_flow.c */

extern int __in_fake_assign;
extern int __in_fake_parameter_assign;
extern int __in_fake_struct_assign;
extern int in_fake_env;
void smatch (struct string_list *filelist);
int inside_loop(void);
int definitely_inside_loop(void);
struct expression *get_switch_expr(void);
int in_expression_statement(void);
void __process_post_op_stack(void);
void __split_expr(struct expression *expr);
void __split_label_stmt(struct statement *stmt);
void __split_stmt(struct statement *stmt);
extern int __in_function_def;
extern int __in_unmatched_hook;
extern int option_assume_loops;
extern int option_two_passes;
extern int option_no_db;
extern int option_file_output;
extern int option_time;
extern struct expression_list *big_expression_stack;
extern struct expression_list *big_condition_stack;
extern struct statement_list *big_statement_stack;
int is_assigned_call(struct expression *expr);
int inlinable(struct expression *expr);
extern int __inline_call;
extern struct expression *__inline_fn;
extern int __in_pre_condition;
extern int __bail_on_rest_of_function;
extern struct statement *__prev_stmt;
extern struct statement *__cur_stmt;
extern struct statement *__next_stmt;
void init_fake_env(void);
void end_fake_env(void);
int time_parsing_function(void);
bool taking_too_long(void);

/* smatch_struct_assignment.c */
struct expression *get_faked_expression(void);
void __fake_struct_member_assignments(struct expression *expr);

/* smatch_project.c */
int is_no_inline_function(const char *function);

/* smatch_conditions */
void __split_whole_condition(struct expression *expr);
void __handle_logic(struct expression *expr);
int is_condition(struct expression *expr);
int __handle_condition_assigns(struct expression *expr);
int __handle_select_assigns(struct expression *expr);
int __handle_expr_statement_assigns(struct expression *expr);

/* smatch_implied.c */
struct range_list_stack;
void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied);
struct stree *__implied_case_stree(struct expression *switch_expr,
				   struct range_list *case_rl,
				   struct range_list_stack **remaining_cases,
				   struct stree **raw_stree);
void overwrite_states_using_pool(struct sm_state *gate_sm, struct sm_state *pool_sm);
int assume(struct expression *expr);
void end_assume(void);
int impossible_assumption(struct expression *left, int op, sval_t sval);

/* smatch_slist.h */
bool has_dynamic_states(unsigned short owner);
void set_dynamic_states(unsigned short owner);

/* smatch_extras.c */
int in_warn_on_macro(void);
#define SMATCH_EXTRA 5 /* this is my_id from smatch extra set in smatch.c */
extern int RETURN_ID;

struct data_range {
	sval_t min;
	sval_t max;
};

#define MTAG_ALIAS_BIT (1ULL << 63)
#define MTAG_OFFSET_MASK 0xfffULL
#define MTAG_SEED 0xdead << 12

const extern unsigned long valid_ptr_min;
extern unsigned long valid_ptr_max;
extern const sval_t valid_ptr_min_sval;
extern sval_t valid_ptr_max_sval;
extern struct range_list *valid_ptr_rl;
void alloc_valid_ptr_rl(void);

static const sval_t array_min_sval = {
	.type = &ptr_ctype,
	{.value = 100000},
};
static const sval_t array_max_sval = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t text_seg_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t text_seg_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t data_seg_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t data_seg_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t bss_seg_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t bss_seg_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t stack_seg_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t stack_seg_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t kmalloc_seg_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t kmalloc_seg_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t vmalloc_seg_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t vmalloc_seg_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};
static const sval_t fn_ptr_min = {
	.type = &ptr_ctype,
	{.value = 4096},
};
static const sval_t fn_ptr_max = {
	.type = &ptr_ctype,
	{.value = ULONG_MAX - 4095},
};

char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym);
char *map_call_to_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym);
char *map_long_to_short_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack);

#define STRLEN_MAX_RET 1010101

/* smatch_absolute.c */
int get_absolute_min_helper(struct expression *expr, sval_t *sval);
int get_absolute_max_helper(struct expression *expr, sval_t *sval);

/* smatch_type_value.c */
int get_db_type_rl(struct expression *expr, struct range_list **rl);
/* smatch_data_val.c */
int get_mtag_rl(struct expression *expr, struct range_list **rl);
/* smatch_array_values.c */
int get_array_rl(struct expression *expr, struct range_list **rl);

/* smatch_states.c */
struct stree *__swap_cur_stree(struct stree *stree);
void __push_fake_cur_stree();
struct stree *__pop_fake_cur_stree();
void __free_fake_cur_stree();
void __set_fake_cur_stree_fast(struct stree *stree);
void __pop_fake_cur_stree_fast(void);
void __merge_stree_into_cur(struct stree *stree);

int unreachable(void);
void __set_cur_stree_readonly(void);
void __set_cur_stree_writable(void);
void __set_sm(struct sm_state *sm);
void __set_sm_cur_stree(struct sm_state *sm);
void __set_sm_fake_stree(struct sm_state *sm);
void __set_true_false_sm(struct sm_state *true_state,
			struct sm_state *false_state);
void nullify_path(void);
void __match_nullify_path_hook(const char *fn, struct expression *expr,
			       void *unused);
void __unnullify_path(void);
int __path_is_null(void);
void save_all_states(void);
void restore_all_states(void);
void free_goto_stack(void);
void clear_all_states(void);

struct sm_state *get_sm_state(int owner, const char *name,
				struct symbol *sym);
struct sm_state *get_sm_state_expr(int owner, struct expression *expr);
void __push_true_states(void);
void __use_false_states(void);
void __discard_false_states(void);
void __merge_false_states(void);
void __merge_true_states(void);

void __negate_cond_stacks(void);
void __use_pre_cond_states(void);
void __use_cond_true_states(void);
void __use_cond_false_states(void);
void __push_cond_stacks(void);
void __fold_in_set_states(void);
void __free_set_states(void);
struct stree *__copy_cond_true_states(void);
struct stree *__copy_cond_false_states(void);
struct stree *__pop_cond_true_stack(void);
struct stree *__pop_cond_false_stack(void);
void __and_cond_states(void);
void __or_cond_states(void);
void __save_pre_cond_states(void);
void __discard_pre_cond_states(void);
struct stree *__get_true_states(void);
struct stree *__get_false_states(void);
void __use_cond_states(void);
extern struct state_list *__last_base_slist;

void __push_continues(void);
void __discard_continues(void);
void __process_continues(void);
void __merge_continues(void);

void __push_breaks(void);
void __process_breaks(void);
int __has_breaks(void);
void __merge_breaks(void);
void __use_breaks(void);

void __save_switch_states(struct expression *switch_expr);
void __discard_switches(void);
int have_remaining_cases(void);
void __merge_switches(struct expression *switch_expr, struct range_list *case_rl);
void __push_default(void);
void __set_default(void);
int __pop_default(void);

void __push_conditions(void);
void __discard_conditions(void);

void __save_gotos(const char *name, struct symbol *sym);
void __merge_gotos(const char *name, struct symbol *sym);

void __print_cur_stree(void);
bool __print_states(const char *owner);
typedef void (check_tracker_hook)(int owner, const char *name, struct symbol *sym, struct smatch_state *state);
void add_check_tracker(const char *check_name, check_tracker_hook *fn);

/* smatch_hooks.c */
void __pass_to_client(void *data, enum hook_type type);
void __pass_case_to_client(struct expression *switch_expr,
			   struct range_list *rl);
int __has_merge_function(int client_id);
struct smatch_state *__client_merge_function(int owner,
					     struct smatch_state *s1,
					     struct smatch_state *s2);
struct smatch_state *__client_unmatched_state_function(struct sm_state *sm);
void call_pre_merge_hook(struct sm_state *cur, struct sm_state *other);
void __push_scope_hooks(void);
void __call_scope_hooks(void);

/* smatch_function_hooks.c */
void create_function_hook_hash(void);
void __match_initializer_call(struct symbol *sym);

/* smatch_db.c */
enum info_type {
	INTERNAL	= 0,
	/*
	 * Changing these numbers is a pain.  Don't do it.  If you ever use a
	 * number it can't be re-used right away so there may be gaps.
	 * We select these in order by type so if the order matters, then give
	 * it a number below 100-999,9000-9999 ranges. */

	PARAM_CLEARED	= 101,
	PARAM_LIMIT	= 103,
	PARAM_FILTER	= 104,

	PARAM_VALUE	= 1001,
	BUF_SIZE	= 1002,
	CAPPED_DATA	= 1004,
	RETURN_VALUE	= 1005,
	DEREFERENCE	= 1006,
	RANGE_CAP	= 1007,
	ABSOLUTE_LIMITS	= 1010,
	PARAM_ADD	= 1012,
	PARAM_FREED	= 1013,
	DATA_SOURCE	= 1014,
	FUZZY_MAX	= 1015,
	HARD_MAX	= 2015,
	STR_LEN		= 1016,
	ARRAY_LEN	= 1017,
	CAPABLE		= 1018,
	NS_CAPABLE	= 1019,
	CONTAINER	= 1020,
	CASTED_CALL	= 1021,
	TYPE_LINK	= 1022,
	UNTRACKED_PARAM = 1023,
	LOST_PARAM	= 2023,
	CULL_PATH	= 1024,
	PARAM_SET	= 1025,
	PARAM_USED	= 1026,
	BYTE_UNITS      = 1027,
	COMPARE_LIMIT	= 1028,
	PARAM_COMPARE	= 1029,
	CONSTRAINT	= 1031,
	PASSES_TYPE	= 1032,
	CONSTRAINT_REQUIRED = 1033,
	BIT_INFO	= 1034,
	NOSPEC		= 1035,
	NOSPEC_WB	= 1036,
	STMT_CNT	= 1037,
	TERMINATED	= 1038,
	FRESH_ALLOC	= 1044,
	ALLOCATOR	= 1045,

	/* put random temporary stuff in the 7000-7999 range for testing */
	USER_DATA	= 8017,
	USER_DATA_SET	= 9017,
	NO_OVERFLOW	= 8018,
	NO_OVERFLOW_SIMPLE = 8019,
	LOCKED		= 8020,
	UNLOCKED	= 8021,
	HALF_LOCKED	= 9022,
	LOCK_RESTORED	= 9023,
	KNOWN_LOCKED	= 9024,
	KNOWN_UNLOCKED 	= 9025,
	SET_FS		= 8022,
	ATOMIC_INC	= 8023,
	ATOMIC_DEC	= 8024,
	REFCOUNT	= 9025,
	NO_SIDE_EFFECT  = 8025,
	FN_ARG_LINK	= 8028,
	DATA_VALUE	= 8029,
	ARRAYSIZE_ARG	= 8033,
	SIZEOF_ARG	= 8034,
	MEMORY_TAG	= 8036,
	MTAG_ASSIGN	= 8035,
	STRING_VALUE	= 8041,

	BYTE_COUNT	= 8050,
	ELEM_COUNT	= 8051,
	ELEM_LAST	= 8052,
	USED_LAST	= 8053,
	USED_COUNT	= 8054,
};

extern struct sqlite3 *smatch_db;
extern struct sqlite3 *mem_db;
extern struct sqlite3 *cache_db;

void db_ignore_states(int id);
void select_caller_info_hook(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type);
void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm));
void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm));
void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr));
void add_returned_member_callback(int owner, void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state));
void select_call_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value));
void select_return_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value));
struct range_list *db_return_vals(struct expression *expr);
struct range_list *db_return_vals_from_str(const char *fn_name);
struct range_list *db_return_vals_no_args(struct expression *expr);
char *return_state_to_var_sym(struct expression *expr, int param, const char *key, struct symbol **sym);
char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl);
char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym);
const char *state_name_to_param_name(const char *state_name, const char *param_name);
const char *get_param_name_var_sym(const char *name, struct symbol *sym);
const char *get_param_name(struct sm_state *sm);
const char *get_mtag_name_var_sym(const char *state_name, struct symbol *sym);
const char *get_mtag_name_expr(struct expression *expr);
char *get_data_info_name(struct expression *expr);
char *sm_to_arg_name(struct expression *expr, struct sm_state *sm);
int is_recursive_member(const char *param_name);

char *escape_newlines(const char *str);
void sql_exec(struct sqlite3 *db, int (*callback)(void*, int, char**, char**), void *data, const char *sql);

#define sql_helper(db, call_back, data, sql...)					\
do {										\
	char sql_txt[1024];							\
										\
	sqlite3_snprintf(sizeof(sql_txt), sql_txt, sql);			\
	db_debug("debug: %s\n", sql_txt);					\
	sql_exec(db, call_back, data, sql_txt);					\
} while (0)

#define run_sql(call_back, data, sql...)					\
do {										\
	if (option_no_db)							\
		break;								\
	sql_helper(smatch_db, call_back, data, sql);				\
} while (0)

#define mem_sql(call_back, data, sql...)					\
	sql_helper(mem_db, call_back, data, sql)

#define cache_sql(call_back, data, sql...)					\
	sql_helper(cache_db, call_back, data, sql)

#define sql_insert_helper(table, db, ignore, late, values...)			\
do {										\
	struct sqlite3 *_db = db;						\
										\
	if (__inline_fn && !_db)						\
		_db = mem_db;							\
	if (_db) {								\
		char buf[1024];							\
		char *err, *p = buf;						\
		int rc;								\
										\
		p += snprintf(p, buf + sizeof(buf) - p,				\
			      "insert %sinto %s values (",			\
			      ignore ? "or ignore " : "", #table);		\
		p += snprintf(p, buf + sizeof(buf) - p, values);		\
		p += snprintf(p, buf + sizeof(buf) - p, ");");			\
		db_debug("mem-db: %s\n", buf);					\
		rc = sqlite3_exec(_db, buf, NULL, NULL, &err);			\
		if (rc != SQLITE_OK) {						\
			sm_ierror("SQL error #2: %s", err);			\
			sm_ierror("SQL: '%s'", buf);				\
			parse_error = 1;					\
		}								\
		break;								\
	}									\
	if (option_info) {							\
		FILE *tmp_fd = sm_outfd;					\
		sm_outfd = sql_outfd;						\
		sm_prefix();							\
	        sm_printf("SQL%s: insert %sinto " #table " values(",		\
			  late ? "_late" : "", ignore ? "or ignore " : "");	\
	        sm_printf(values);						\
	        sm_printf(");\n");						\
		sm_outfd = tmp_fd;						\
	}									\
} while (0)

#define sql_insert(table, values...) sql_insert_helper(table, 0, 0, 0, values);
#define sql_insert_or_ignore(table, values...) sql_insert_helper(table, 0, 1, 0, values);
#define sql_insert_late(table, values...) sql_insert_helper(table, 0, 0, 1, values);
#define sql_insert_cache(table, values...) sql_insert_helper(table, cache_db, 1, 0, values);

char *get_static_filter(struct symbol *sym);

void sql_insert_return_states(int return_id, const char *return_ranges,
		int type, int param, const char *key, const char *value);
void sql_insert_caller_info(struct expression *call, int type, int param,
		const char *key, const char *value);
void sql_insert_function_ptr(const char *fn, const char *struct_name);
void sql_insert_return_values(const char *return_values);
void sql_insert_return_implies(int type, int param, const char *key, const char *value);
void sql_insert_function_type_size(const char *member, const char *ranges);
void sql_insert_function_type_info(int type, const char *struct_type, const char *member, const char *value);
void sql_insert_type_info(int type, const char *member, const char *value);
void sql_insert_local_values(const char *name, const char *value);
void sql_insert_function_type_value(const char *type, const char *value);
void sql_insert_function_type(int param, const char *value);
void sql_insert_parameter_name(int param, const char *value);
void sql_insert_data_info(struct expression *data, int type, const char *value);
void sql_insert_data_info_var_sym(const char *var, struct symbol *sym, int type, const char *value);
void sql_save_constraint(const char *con);
void sql_save_constraint_required(const char *data, int op, const char *limit);
void sql_copy_constraint_required(const char *new_limit, const char *old_limit);
void sql_insert_fn_ptr_data_link(const char *ptr, const char *data);
void sql_insert_fn_data_link(struct expression *fn, int type, int param, const char *key, const char *value);
void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name);
void sql_insert_mtag_info(mtag_t tag, int type, const char *value);
void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset);
void sql_insert_mtag_alias(mtag_t orig, mtag_t alias);
int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container);
int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag);
struct smatch_state *get_mtag_return(struct expression *expr, struct smatch_state *state);
struct range_list *swap_mtag_seed(struct expression *expr, struct range_list *rl);

void sql_select_return_states(const char *cols, struct expression *call,
	int (*callback)(void*, int, char**, char**), void *info);
void sql_select_call_implies(const char *cols, struct expression *call,
	int (*callback)(void*, int, char**, char**));

void open_smatch_db(char *db_file);

/* smatch_files.c */
int open_data_file(const char *filename);
int open_schema_file(const char *schema);
struct token *get_tokens_file(const char *filename);

/* smatch.c */
extern char *option_debug_check;
extern char *option_project_str;
extern char *bin_dir;
extern char *data_dir;
extern int option_no_data;
extern int option_full_path;
extern int option_call_tree;
extern int num_checks;

enum project_type {
	PROJ_NONE,
	PROJ_KERNEL,
	PROJ_WINE,
	PROJ_ILLUMOS_KERNEL,
	PROJ_ILLUMOS_USER,
	PROJ_UNKNOWN,
};
extern enum project_type option_project;
const char *check_name(unsigned short id);
int id_from_name(const char *name);

/* smatch_buf_size.c */
int get_array_size(struct expression *expr);
int get_array_size_bytes(struct expression *expr);
int get_array_size_bytes_min(struct expression *expr);
int get_array_size_bytes_max(struct expression *expr);
struct range_list *get_array_size_bytes_rl(struct expression *expr);
int get_real_array_size(struct expression *expr);
int last_member_is_resizable(struct symbol *type);
/* smatch_strlen.c */
int get_implied_strlen(struct expression *expr, struct range_list **rl);
int get_size_from_strlen(struct expression *expr);

/* smatch_capped.c */
int is_capped(struct expression *expr);
int is_capped_var_sym(const char *name, struct symbol *sym);

/* check_user_data.c */
int is_user_macro(struct expression *expr);
int is_capped_user_data(struct expression *expr);
int implied_user_data(struct expression *expr, struct range_list **rl);
struct stree *get_user_stree(void);
int get_user_rl(struct expression *expr, struct range_list **rl);
int is_user_rl(struct expression *expr);
int get_user_rl_var_sym(const char *name, struct symbol *sym, struct range_list **rl);
bool user_rl_capped(struct expression *expr);
struct range_list *var_user_rl(struct expression *expr);

/* check_locking.c */
void print_held_locks();

/* check_assigned_expr.c */
extern int check_assigned_expr_id;
struct expression *get_assigned_expr(struct expression *expr);
struct expression *get_assigned_expr_name_sym(const char *name, struct symbol *sym);
/* smatch_return_to_param.c */
void __add_return_to_param_mapping(struct expression *assign, const char *return_string);
char *map_call_to_param_name_sym(struct expression *expr, struct symbol **sym);

/* smatch_comparison.c */
extern int comparison_id;
#define UNKNOWN_COMPARISON 0
#define IMPOSSIBLE_COMPARISON -1
struct compare_data {
	/* The ->left and ->right expression pointers might be NULL (I'm lazy) */
	struct expression *left;
	const char *left_var;
	struct var_sym_list *left_vsl;
	int comparison;
	struct expression *right;
	const char *right_var;
	struct var_sym_list *right_vsl;
};
DECLARE_ALLOCATOR(compare_data);
struct smatch_state *alloc_compare_state(
		struct expression *left,
		const char *left_var, struct var_sym_list *left_vsl,
		int comparison,
		struct expression *right,
		const char *right_var, struct var_sym_list *right_vsl);
int comparison_intersection(int orig, int op);
int merge_comparisons(int one, int two);
int combine_comparisons(int left_compare, int right_compare);
int state_to_comparison(struct smatch_state *state);
struct smatch_state *merge_compare_states(struct smatch_state *s1, struct smatch_state *s2);
int get_comparison(struct expression *left, struct expression *right);
int get_comparison_no_extra(struct expression *a, struct expression *b);
int get_comparison_strings(const char *one, const char *two);
int possible_comparison(struct expression *a, int comparison, struct expression *b);
struct state_list *get_all_comparisons(struct expression *expr);
struct state_list *get_all_possible_equal_comparisons(struct expression *expr);
void __add_return_comparison(struct expression *call, const char *range);
void __add_comparison_info(struct expression *expr, struct expression *call, const char *range);
char *get_printed_param_name(struct expression *call, const char *param_name, struct symbol *param_sym);
char *name_sym_to_param_comparison(const char *name, struct symbol *sym);
char *expr_equal_to_param(struct expression *expr, int ignore);
char *expr_lte_to_param(struct expression *expr, int ignore);
char *expr_param_comparison(struct expression *expr, int ignore);
int flip_comparison(int op);
int negate_comparison(int op);
int remove_unsigned_from_comparison(int op);
int param_compare_limit_is_impossible(struct expression *expr, int left_param, char *left_key, char *value);
void filter_by_comparison(struct range_list **rl, int comparison, struct range_list *right);
void __compare_param_limit_hook(struct expression *left_expr, struct expression *right_expr,
				const char *state_name,
				struct smatch_state *true_state, struct smatch_state *false_state);
int impossibly_high_comparison(struct expression *expr);

/* smatch_sval.c */
sval_t *sval_alloc(sval_t sval);
sval_t *sval_alloc_permanent(sval_t sval);
sval_t sval_blank(struct expression *expr);
sval_t sval_type_val(struct symbol *type, long long val);
sval_t sval_type_fval(struct symbol *type, long double fval);
sval_t sval_from_val(struct expression *expr, long long val);
sval_t sval_from_fval(struct expression *expr, long double fval);
int sval_is_ptr(sval_t sval);
bool sval_is_fp(sval_t sval);
int sval_unsigned(sval_t sval);
int sval_signed(sval_t sval);
int sval_bits(sval_t sval);
int sval_bits_used(sval_t sval);
int sval_is_negative(sval_t sval);
int sval_is_positive(sval_t sval);
int sval_is_min(sval_t sval);
int sval_is_max(sval_t sval);
int sval_is_a_min(sval_t sval);
int sval_is_a_max(sval_t sval);
int sval_is_negative_min(sval_t sval);
int sval_cmp_t(struct symbol *type, sval_t one, sval_t two);
int sval_cmp_val(sval_t one, long long val);
sval_t sval_min(sval_t one, sval_t two);
sval_t sval_max(sval_t one, sval_t two);
int sval_too_low(struct symbol *type, sval_t sval);
int sval_too_high(struct symbol *type, sval_t sval);
int sval_fits(struct symbol *type, sval_t sval);
sval_t sval_cast(struct symbol *type, sval_t sval);
sval_t sval_preop(sval_t sval, int op);
sval_t sval_binop(sval_t left, int op, sval_t right);
int sval_binop_overflows(sval_t left, int op, sval_t right);
int sval_binop_overflows_no_sign(sval_t left, int op, sval_t right);
int find_first_zero_bit(unsigned long long uvalue);
int sm_fls64(unsigned long long uvalue);
unsigned long long fls_mask(unsigned long long uvalue);
unsigned long long sval_fls_mask(sval_t sval);
const char *sval_to_str(sval_t sval);
const char *sval_to_str_or_err_ptr(sval_t sval);
const char *sval_to_numstr(sval_t sval);
sval_t ll_to_sval(long long val);

/* smatch_string_list.c */
int list_has_string(struct string_list *str_list, const char *str);
int insert_string(struct string_list **str_list, const char *str);
struct string_list *clone_str_list(struct string_list *orig);
struct string_list *combine_string_lists(struct string_list *one, struct string_list *two);

/* smatch_start_states.c */
struct stree *get_start_states(void);

/* smatch_recurse.c */
int has_symbol(struct expression *expr, struct symbol *sym);
int has_variable(struct expression *expr, struct expression *var);
int has_inc_dec(struct expression *expr);

/* smatch_stored_conditions.c */
struct smatch_state *get_stored_condition(struct expression *expr);
struct expression_list *get_conditions(struct expression *expr);
struct sm_state *stored_condition_implication_hook(struct expression *expr,
			struct state_list **true_stack,
			struct state_list **false_stack);
/* smatch_parsed_conditions.c */
struct sm_state *parsed_condition_implication_hook(struct expression *expr,
			struct state_list **true_stack,
			struct state_list **false_stack);
/* smatch_comparison.c */
struct sm_state *comparison_implication_hook(struct expression *expr,
					     struct state_list **true_stack,
					     struct state_list **false_stack);

/* check_string_len.c */
int get_formatted_string_size(struct expression *call, int arg);
int get_formatted_string_min_size(struct expression *call, int arg);

/* smatch_param_set.c */
int param_was_set(struct expression *expr);
int param_was_set_var_sym(const char *name, struct symbol *sym);
void print_limited_param_set(int return_id, char *return_ranges, struct expression *expr);
/* smatch_param_filter.c */
int param_has_filter_data(struct sm_state *sm);

/* smatch_links.c */
void set_up_link_functions(int id, int linkid);
struct smatch_state *merge_link_states(struct smatch_state *s1, struct smatch_state *s2);
void store_link(int link_id, const char *name, struct symbol *sym, const char *link_name, struct symbol *link_sym);

/* check_buf_comparison */
const char *limit_type_str(unsigned int limit_type);
struct expression *get_size_variable(struct expression *buf, int *limit_type);
struct expression *get_array_variable(struct expression *size);
int buf_comparison_index_ok(struct expression *expr);

/* smatch_untracked_param.c */
void mark_untracked(struct expression *expr, int param, const char *key, const char *value);
void add_untracked_param_hook(void (func)(struct expression *call, int param));
void add_lost_param_hook(void (func)(struct expression *call, int param));
void mark_all_params_untracked(int return_id, char *return_ranges, struct expression *expr);

/* smatch_strings.c */
struct state_list *get_strings(struct expression *expr);
struct expression *fake_string_from_mtag(mtag_t tag);

/* smatch_estate.c */
int estate_get_single_value(struct smatch_state *state, sval_t *sval);

/* smatch_address.c */
int get_address_rl(struct expression *expr, struct range_list **rl);
int get_member_offset(struct symbol *type, const char *member_name);
int get_member_offset_from_deref(struct expression *expr);

/* for now this is in smatch_used_parameter.c */
void __get_state_hook(int owner, const char *name, struct symbol *sym);

/* smatch_buf_comparison.c */
int db_var_is_array_limit(struct expression *array, const char *name, struct var_sym_list *vsl);

struct range_list *get_fs(void);

struct stree *get_all_return_states(void);
struct stree_stack *get_all_return_strees(void);
int on_atomic_dec_path(void);
int was_inced(const char *name, struct symbol *sym);
void set_refcount_inc(char *name, struct symbol *sym);
void set_refcount_dec(char *name, struct symbol *sym);

/* smatch_constraints.c */
char *get_constraint_str(struct expression *expr);
struct constraint_list *get_constraints(struct expression *expr);
char *unmet_constraint(struct expression *data, struct expression *offset);
char *get_required_constraint(const char *data_str);

/* smatch_container_of.c */
int get_param_from_container_of(struct expression *expr);
int get_offset_from_container_of(struct expression *expr);
char *get_container_name(struct expression *container, struct expression *expr);

/* smatch_mtag.c */
mtag_t str_to_mtag(const char *str);
int get_string_mtag(struct expression *expr, mtag_t *tag);
int get_toplevel_mtag(struct symbol *sym, mtag_t *tag);
int create_mtag_alias(mtag_t tag, struct expression *expr, mtag_t *new);
int expr_to_mtag_offset(struct expression *expr, mtag_t *tag, int *offset);
void update_mtag_data(struct expression *expr, struct smatch_state *state);
int get_mtag_sval(struct expression *expr, sval_t *sval);

/* Trinity fuzzer stuff */
const char *get_syscall_arg_type(struct symbol *sym);

/* smatch_bit_info.c */
struct bit_info *rl_to_binfo(struct range_list *rl);
struct bit_info *get_bit_info(struct expression *expr);
struct bit_info *get_bit_info_var_sym(const char *name, struct symbol *sym);
/* smatch_mem_tracker.c */
extern int option_mem;
unsigned long get_mem_kb(void);
unsigned long get_max_memory(void);

/* check_is_nospec.c */
bool is_nospec(struct expression *expr);
long get_stmt_cnt(void);

/* smatch_nul_terminator.c */
bool is_nul_terminated_var_sym(const char *name, struct symbol *sym);
bool is_nul_terminated(struct expression *expr);
/* check_kernel.c  */
bool is_ignored_kernel_data(const char *name);

bool is_fresh_alloc_var_sym(const char *var, struct symbol *sym);
bool is_fresh_alloc(struct expression *expr);
static inline bool type_is_ptr(struct symbol *type)
{
	return type &&
	       (type->type == SYM_PTR ||
		type->type == SYM_ARRAY ||
		type->type == SYM_FN);
}

static inline bool type_is_fp(struct symbol *type)
{
	return type &&
	       (type == &float_ctype ||
		type == &double_ctype ||
		type == &ldouble_ctype);
}

static inline int type_bits(struct symbol *type)
{
	if (!type)
		return 0;
	if (type_is_ptr(type))
		return bits_in_pointer;
	if (!type->examined)
		examine_symbol_type(type);
	return type->bit_size;
}

static inline int type_unsigned(struct symbol *base_type)
{
	if (!base_type)
		return 0;
	if (is_ptr_type(base_type))
		return 1;
	if (base_type->ctype.modifiers & MOD_UNSIGNED)
		return 1;
	return 0;
}

static inline int type_positive_bits(struct symbol *type)
{
	if (!type)
		return 0;
	if (is_ptr_type(type))
		return bits_in_pointer;
	if (type_unsigned(type))
		return type_bits(type);
	return type_bits(type) - 1;
}

static inline int sval_positive_bits(sval_t sval)
{
	return type_positive_bits(sval.type);
}

/*
 * Returns -1 if one is smaller, 0 if they are the same and 1 if two is larger.
 */

static inline int fp_cmp(sval_t one, sval_t two)
{
	struct symbol *type;

	if (sval_is_fp(one) && sval_is_fp(two))
		type = type_bits(one.type) > type_bits(two.type) ? one.type : two.type;
	else if (sval_is_fp(one))
		type = one.type;
	else
		type = two.type;

	one = sval_cast(type, one);
	two = sval_cast(type, two);

	if (one.type == &float_ctype) {
		if (one.fvalue < two.fvalue)
			return -1;
		if (one.fvalue == two.fvalue)
			return 0;
		return 1;
	}
	if (one.type == &double_ctype) {
		if (one.dvalue < two.dvalue)
			return -1;
		if (one.dvalue == two.dvalue)
			return 0;
		return 1;
	}
	if (one.type == &ldouble_ctype) {
		if (one.ldvalue < two.ldvalue)
			return -1;
		if (one.ldvalue == two.ldvalue)
			return 0;
		return 1;
	}
	sm_perror("bad type in fp_cmp(): %s", type_to_str(type));
	return 1;
}

static inline int sval_cmp(sval_t one, sval_t two)
{
	struct symbol *type;

	if (sval_is_fp(one) || sval_is_fp(two))
		return fp_cmp(one, two);

	type = one.type;
	if (sval_positive_bits(two) > sval_positive_bits(one))
		type = two.type;
	if (type_bits(type) < 31)
		type = &int_ctype;

	one = sval_cast(type, one);
	two = sval_cast(type, two);

	if (type_unsigned(type)) {
		if (one.uvalue < two.uvalue)
			return -1;
		if (one.uvalue == two.uvalue)
			return 0;
		return 1;
	}
	/* fix me handle type promotion and unsigned values */
	if (one.value < two.value)
		return -1;
	if (one.value == two.value)
		return 0;
	return 1;
}

#endif 	    /* !SMATCH_H_ */


Pedestrian 0.00 1 -2.1090423623707633 739.53 173.78 750.19 212.04 1.7514116609845114 0.6551889040780139 0.8671696191439533 5.95 1.79 33.35 -1.9324891806287723 0.89591587
Car 0.47 3 1.9792803088810782 0.00 189.30 113.74 266.56 1.4412401024071884 1.6723911625058794 4.101918282114067 -13.92 2.02 16.98 1.2925894446851043 0.9947417
Car 0.00 0 1.8675513128426413 316.83 181.03 378.52 211.91 1.5364463258354377 1.686655259943142 3.9644804095254327 -14.25 2.04 39.33 1.5199444530867394 0.9999999
DontCare -1 -1 1.4559970731523375 1066.50 230.99 1153.47 252.63 1.5488149527280044 1.7518429153324508 4.866465585433044 -1000 -1000 -1000 2.241395236549786 0.96418566
DontCare -1 -1 0.7175384322789053 833.65 192.18 1048.71 235.81 1.3322106752364349 1.6158497196347856 4.110586123667755 -1000 -1000 -1000 1.5029365956763536 0.9256009
DontCare -1 -1 0.585618213811193 758.61 175.36 899.92 191.18 1.3961049023835372 1.7042739161015892 4.077412562571563 -1000 -1000 -1000 1.3710163772086412 0.93508697
DontCare -1 -1 1.2530028680947165 671.93 172.77 713.62 200.23 1.483567528781147 1.6568816576810026 4.109776036940612 -1000 -1000 -1000 2.038401031492165 0.9959584
DontCare -1 -1 2.236477688946996 544.49 174.06 619.17 185.35 1.4519826549856376 1.6512268076376462 3.854066065173694 -1000 -1000 -1000 3.0218758523444444 0.9524154
DontCare -1 -1 0.9622848788884024 645.40 174.71 661.87 184.06 1.5139108317723882 1.644468931966036 3.74452602317194 -1000 -1000 -1000 1.7476830422858507 0.9114326


import styled from 'styled-components'

// import { cs } from '@/utils'
import { WrapperBase, ScrollWrapperBase, ShadowBarBase } from './index'
import { getShadowBackground, getShadowSize, getScrollbarThin } from './metrics'

export const Wrapper = styled(WrapperBase)`
  position: relative;

  .os-host:not(:hover) {
    visibility: ${({ showOnHover }) => (showOnHover ? 'hidden' : 'inherit')};
  }

  .os-theme-dark > .os-scrollbar-vertical,
  .os-theme-light > .os-scrollbar-vertical {
    width: ${({ barSize }) =>
      `${getScrollbarThin(barSize, 'vertical')} !important`};
  }
`
export const ScrollWrapper = styled(ScrollWrapperBase)``
const ShadowBar = styled(ShadowBarBase)`
  left: 0px;
  height: ${({ shadowSize }) => getShadowSize(shadowSize)};
  width: 100%;
  background: ${({ shadowSize }) =>
    getShadowBackground(shadowSize, 'vertical')};
  border-top: ${({ withBorder }) => (withBorder ? '1px solid' : 'none')};
  border-color: ${({ withBorder }) => (withBorder ? '#084255' : 'none')};
`
export const TopShadowBar = styled(ShadowBar)`
  top: 0;
  z-index: 2;
`
export const BottomShadowBar = styled(ShadowBar)`
  bottom: 0;
  transform: rotate(180deg);
`


<template>

      <el-row :gutter="20">
        <el-col :span="6">
          <el-input v-model="listQuery.name" size="mini" placeholder="请输入角色名称"></el-input>
        </el-col>
        <el-col :span="6">
          <el-button type="success" size="mini" icon="el-icon-search" @click.native="search">{{ $t('button.search') }}</el-button>
          <el-button type="primary" size="mini" icon="el-icon-refresh" @click.native="reset">{{ $t('button.reset') }}</el-button>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="24">
          <el-button type="success" size="mini" icon="el-icon-plus" @click.native="add">{{ $t('button.add') }}</el-button>
          <el-button type="primary" size="mini" icon="el-icon-edit" @click.native="edit">{{ $t('button.edit') }}</el-button>
          <el-button type="danger" size="mini" icon="el-icon-delete" @click.native="remove">{{ $t('button.delete') }}</el-button>
          <el-button type="primary" size="mini" icon="el-icon-setting" @click.native="openPermissions">权限配置</el-button>
        </el-col>
      </el-row>

    <el-table :data="list" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row
              @current-change="handleCurrentChange">

      <el-table-column label="名称">
        <template slot-scope="scope">
          {{scope.row.name}}
        </template>
      </el-table-column>
      <el-table-column label="编码">
        <template slot-scope="scope">
          {{scope.row.tips}}
        </template>
      </el-table-column>
      <el-table-column label="所在部门">
        <template slot-scope="scope">
          {{scope.row.deptName}}
        </template>
      </el-table-column>
      <el-table-column label="上级角色">
        <template slot-scope="scope">
          {{scope.row.pName}}
        </template>
      </el-table-column>

    </el-table>

    <el-pagination
      background
      layout="total, sizes, prev, pager, next, jumper"
      :page-sizes="[10, 20, 50, 100,500]"
      :page-size="listQuery.limit"
      :total="total"
      :current-page.sync="listQuery.page"
      @size-change="changeSize"
      @current-change="fetchPage"
      @prev-click="fetchPrev"
      @next-click="fetchNext">
    </el-pagination>

    <el-dialog
      :title="formTitle"
      :visible.sync="formVisible"
      width="70%">
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="编码" prop="tips">
              <el-input v-model="form.tips" minlength=1></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="名称" prop="name">
              <el-input v-model="form.name" minlength=1></el-input>
            </el-form-item>
          </el-col>

          <el-col :span="12">
            <el-form-item label="上级角色">
              <el-input
                placeholder="请选择上级角色"
                v-model="form.pName"
                readonly="readonly"
                @click.native="roleTree.show = !roleTree.show">
              </el-input>
              <el-tree v-if="roleTree.show"
                       empty-text="暂无数据"
                       :expand-on-click-node="false"
                       :data="list"
                       :props="roleTree.defaultProps"
                       @node-click="handleRoleNodeClick"
                       class="input-tree">
              </el-tree>

            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="排序">
              <el-input v-model="form.num" type="number"></el-input>
            </el-form-item>
          </el-col>

          <el-col :span="12">
            <el-form-item label="所在部门">
              <el-input
                placeholder="请选择所在部门"
                v-model="form.deptName"
                readonly="readonly"
                @click.native="deptTree.show = !deptTree.show">
              </el-input>
              <el-tree v-if="deptTree.show"
                       empty-text="暂无数据"
                       :expand-on-click-node="false"
                       :data="deptList"
                       :props="deptTree.defaultProps"
                       @node-click="handleDeptNodeClick"
                       class="input-tree">
              </el-tree>

            </el-form-item>
          </el-col>

        </el-row>
        <el-form-item>
          <el-button type="primary" @click="save">{{ $t('button.submit') }}</el-button>
          <el-button @click.native="formVisible = false">{{ $t('button.cancel') }}</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <el-dialog
      title="权限配置"
      :visible.sync="permissonVisible"
      width="25%">
      <el-form>
        <el-row>
          <el-col :span="12">
            <el-tree
              :data="permissons"
              ref="permissonTree"
              show-checkbox
              node-key="id"
              :default-checked-keys="checkedPermissionKeys"
              :props="defaultProps">
            </el-tree>

          </el-col>
        </el-row>
        <el-form-item>
          <el-button type="primary" @click="savePermissions">{{ $t('button.submit') }}</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

</template>


sp_before_semi = ignore


<?php

namespace OCDI;

class DownloaderTest extends \WP_UnitTestCase {
	/**
	 * Class setup.
	 */
	function setUp() {
		parent::setUp();

		// Downloader with the default WP uploads directory.
		$this->downloader = new Downloader();

		// Default download path.
		$upload_dir         = wp_upload_dir();
		$this->default_path = trailingslashit( $upload_dir['path'] );
	}

	/**
	 * Testing the get_download_directory_path method.
	 */
	function test_get_download_directory_path() {
		// Test default path (no argument when initializing Downloader class).
		$this->assertEquals( $this->default_path, $this->downloader->get_download_directory_path() );

		// Test invalid path.
		$downloader2 = new Downloader( 'test' );
		$this->assertEquals( $this->default_path, $downloader2->get_download_directory_path() );

		// Test a valid path.
		$path = plugin_dir_path( __FILE__ );
		$downloader3 = new Downloader( $path );
		$this->assertEquals( $path, $downloader3->get_download_directory_path() );
	}

	/**
	 * Testing the set_download_directory_path method.
	 */
	function test_set_download_directory_path() {
		// Test empty path.
		$downloader1 = new Downloader( '' );
		$downloader1->set_download_directory_path( '' );
		$this->assertEquals( $this->default_path, $downloader1->get_download_directory_path() );

		// Test invalid path.
		$downloader1->set_download_directory_path( 'test' );
		$this->assertEquals( $this->default_path, $downloader1->get_download_directory_path() );

		// Test a valid path.
		$path = plugin_dir_path( __FILE__ );
		$downloader1->set_download_directory_path( $path );
		$this->assertEquals( $path, $downloader1->get_download_directory_path() );
	}

	/**
	 * Testing the get_error_from_response method.
	 * Private function.
	 */
	function test_get_error_from_response() {
		$expected = array(
			'error_code'    => 'test_error',
			'error_message' => 'Error test',
		);

		// Test response with array.
		$method_response = \TestHelpers::invoke_method(
			$this->downloader,
			'get_error_from_response',
			array(
				array(
					'response' => array(
						'code'    => 'test_error',
						'message' => 'Error test',
					),
				),
			)
		);
		$this->assertEquals( $expected, $method_response );

		// Test response with WP_error object.
		$method_response = \TestHelpers::invoke_method(
			$this->downloader,
			'get_error_from_response',
			array(
				new \WP_Error(
					'test_error',
					'Error test'
				)
			)
		);
		$this->assertEquals( $expected, $method_response );
	}

	/**
	 * Testing the get_content_from_url method.
	 * Private function.
	 */
	function test_get_content_from_url() {
		// Empty URL parameter.
		$expected_code   = 'missing_url';
		$method_response = \TestHelpers::invoke_method(
			$this->downloader,
			'get_content_from_url',
			array(
				''
			)
		);

		$this->assertTrue( is_wp_error( $method_response ) );
		$this->assertEquals( $expected_code, $method_response->get_error_code() );

		// Invalid URL parameter.
		$expected_code   = 'download_error';
		$method_response = \TestHelpers::invoke_method(
			$this->downloader,
			'get_content_from_url',
			array(
				'http://invalid-url.com'
			)
		);

		$this->assertTrue( is_wp_error( $method_response ) );
		$this->assertEquals( $expected_code, $method_response->get_error_code() );

		// Valid URL parameter - a test file with the content of "test".
		$expected = 'test';
		$method_response = \TestHelpers::invoke_method(
			$this->downloader,
			'get_content_from_url',
			array(
				'https://raw.githubusercontent.com/proteusthemes/one-click-demo-import/aa2fbfccbc3331ac46e64ebba33c4cf58b1c39a8/tests/data/test-files/test.txt'
			)
		);

		$this->assertEquals( $expected, $method_response );
	}

	/**
	 * Testing the download_file method.
	 */
	function test_download_file() {
		$expected = $this->default_path . 'test.txt';
		$file     = $this->downloader->download_file( 'https://raw.githubusercontent.com/proteusthemes/one-click-demo-import/aa2fbfccbc3331ac46e64ebba33c4cf58b1c39a8/tests/data/test-files/test.txt', 'test.txt' );

		$this->assertEquals( $expected, $file );
		$this->assertTrue( file_exists( $file ) );

		// Delete the downloaded file.
		unlink( $file );
	}
}


## Test extract operation.
# XFAIL: system-darwin

RUN: rm -rf %t && mkdir -p %t/extracted/

# Extracting from an empty archive should not warn or error:
RUN: llvm-ar cr %t/empty.a
RUN: llvm-ar x %t/empty.a 2>&1 | count 0

RUN: echo filea > %t/a.txt
RUN: echo fileb > %t/b.txt
RUN: llvm-ar rc %t/archive.a %t/a.txt %t/b.txt

# Single member:
RUN: cd %t/extracted && llvm-ar x %t/archive.a a.txt
RUN: diff %t/a.txt %t/extracted/a.txt

# All members:
RUN: rm %t/extracted/a.txt
RUN: cd %t/extracted && llvm-ar x %t/archive.a
RUN: diff %t/a.txt %t/extracted/a.txt
RUN: diff %t/b.txt %t/extracted/b.txt


                        <?= $label ?>

                            <?=Num::format($total, 0)?>

                        <? if (Num::percent_change($total, $total_past) < 0) : ?>

                                <svg class="self-center flex-shrink-0 h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20">
                                    <path fill-rule="evenodd" d="M14.707 10.293a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L9 12.586V5a1 1 0 012 0v7.586l2.293-2.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
                                </svg>

                                    <?= __('Decreased by') ?>

                                <?=Num::percent_change($total, $total_past)?>

                        <? else : ?>

                                <svg class="self-center flex-shrink-0 h-5 w-5 text-green-500" fill="currentColor" viewBox="0 0 20 20">
                                    <path fill-rule="evenodd" d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
                                </svg>

                                    <?= __('Increased by') ?>

                                <?=Num::percent_change($total, $total_past)?>

                        <? endif ?>

                            <?=sprintf(__('%s days ago'), $days_ago)?>

            <?=Chart::line($chart, $chart_config, $chart_colors)?>

            <a href="<?=Route::url('oc-panel', ['controller' => 'stats', 'action'=> $detail_action])?>?<?=http_build_query(['rel' => ''] + Request::current()->query())?>" class="font-medium text-blue-600 hover:text-blue-500 transition ease-in-out duration-150">
                View all


// This source file is part of the Swift.org open source project
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

// RUN: not %target-swift-frontend %s -typecheck
{}
{
({class j}}}if{{class
case,


<Workspace Version="0.7.5.3566" X="30" Y="377.07867494824" zoom="1.32712215320911" Description="Checks whether a given view is a rendering." Category="Clockwork.Revit.Views.View.Query" Name="View.TypeIsRendering" ID="b0447f47-0d5d-4013-923c-7f14abbd2118">
  <Elements>
    <Dynamo.Nodes.Function type="Dynamo.Nodes.Function" guid="e8f2edca-cf74-4cf1-aa9c-4058f9fd139e" nickname="Turn Into List" x="179" y="26" isVisible="true" isUpstreamVisible="true" lacing="Disabled">
      <ID value="cd09ad33-8c34-4850-ac26-24448d92c38f" />
      <Name value="Turn Into List" />
      <Description value="Turns an element (or a nested list) into a flat list" />
      <Inputs>
        <Input value="item" />
      </Inputs>
      <Outputs>
        <Output value="" />
      </Outputs>
    </Dynamo.Nodes.Function>
    <Dynamo.Nodes.Symbol type="Dynamo.Nodes.Symbol" guid="4d7090a5-55aa-4d07-aa91-3d027092bbd0" nickname="Input" x="6.02808112324493" y="-38.9921996879875" isVisible="true" isUpstreamVisible="true" lacing="Disabled">
      <Symbol value="View(s)" />
    </Dynamo.Nodes.Symbol>
    <Dynamo.Nodes.Output type="Dynamo.Nodes.Output" guid="3dd0e04f-7e66-43d9-ab0b-1f3af78e3288" nickname="Output" x="896.232449297972" y="-37.6755070202808" isVisible="true" isUpstreamVisible="true" lacing="Disabled">
      <Symbol value="bool" />
    </Dynamo.Nodes.Output>
    <DSIronPythonNode.PythonNode type="DSIronPythonNode.PythonNode" guid="e530854e-1aeb-4010-90be-00759562b87d" nickname="Python Script" x="384" y="26" isVisible="true" isUpstreamVisible="true" lacing="Disabled" inputcount="1">
      <Script>import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

views = UnwrapElement(IN[0])
booleans = list()

for view in views:
	if str(view.ViewType) == 'Rendering':
		booleans.append(True)
	else:
		booleans.append(False)
OUT = booleans		</Script>
    </DSIronPythonNode.PythonNode>
    <Dynamo.Nodes.Function type="Dynamo.Nodes.Function" guid="8e4972d3-a5dd-4923-a5e5-e4b2d044e04b" nickname="ReturnListOrSingleValue" x="604.232449297972" y="-37.6755070202808" isVisible="true" isUpstreamVisible="true" lacing="Disabled">
      <ID value="44ac4888-4aa4-49a9-9344-23b729c11df9" />
      <Name value="ReturnListOrSingleValue" />
      <Description value="If the item in input #1 is not a list, only the first item of the list in input #2 will be returned." />
      <Inputs>
        <Input value="item #1 (unknown)" />
        <Input value="item #2 (list)" />
      </Inputs>
      <Outputs>
        <Output value="" />
      </Outputs>
    </Dynamo.Nodes.Function>
  </Elements>
  <Connectors>
    <Dynamo.Models.ConnectorModel start="e8f2edca-cf74-4cf1-aa9c-4058f9fd139e" start_index="0" end="e530854e-1aeb-4010-90be-00759562b87d" end_index="0" portType="0" />
    <Dynamo.Models.ConnectorModel start="4d7090a5-55aa-4d07-aa91-3d027092bbd0" start_index="0" end="e8f2edca-cf74-4cf1-aa9c-4058f9fd139e" end_index="0" portType="0" />
    <Dynamo.Models.ConnectorModel start="4d7090a5-55aa-4d07-aa91-3d027092bbd0" start_index="0" end="8e4972d3-a5dd-4923-a5e5-e4b2d044e04b" end_index="0" portType="0" />
    <Dynamo.Models.ConnectorModel start="e530854e-1aeb-4010-90be-00759562b87d" start_index="0" end="8e4972d3-a5dd-4923-a5e5-e4b2d044e04b" end_index="1" portType="0" />
    <Dynamo.Models.ConnectorModel start="8e4972d3-a5dd-4923-a5e5-e4b2d044e04b" start_index="0" end="3dd0e04f-7e66-43d9-ab0b-1f3af78e3288" end_index="0" portType="0" />
  </Connectors>
  <Notes />
</Workspace>


#!/bin/bash -e
#
# Compile and check with clang.
#
# Copyright (c) 2016 Red Hat Inc.
#
# Authors:
#  Fam Zheng <famz@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2
# or (at your option) any later version. See the COPYING file in
# the top-level directory.

. common.rc

requires clang

cd "$BUILD_DIR"

OPTS="--cxx=clang++ --cc=clang --host-cc=clang"
# -fsanitize=undefined is broken on Fedora 23, skip it for now
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834
#OPTS="$OPTS --extra-cflags=-fsanitize=undefined \
    #--extra-cflags=-fno-sanitize=float-divide-by-zero"
build_qemu $OPTS
check_qemu
install_qemu


<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RunConfigurationProducerService">
    <option name="ignoredProducers">
      <set>
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
      </set>
    </option>
  </component>
</project>


<?php

namespace Illuminate\Bus;

use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
use Illuminate\Contracts\Queue\Factory as QueueFactoryContract;
use Illuminate\Contracts\Bus\QueueingDispatcher as QueueingDispatcherContract;

class BusServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Dispatcher::class, function ($app) {
            return new Dispatcher($app, function ($connection = null) use ($app) {
                return $app[QueueFactoryContract::class]->connection($connection);
            });
        });

        $this->app->alias(
            Dispatcher::class, DispatcherContract::class
        );

        $this->app->alias(
            Dispatcher::class, QueueingDispatcherContract::class
        );
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [
            Dispatcher::class,
            DispatcherContract::class,
            QueueingDispatcherContract::class,
        ];
    }
}


netcdf tst_group_data {
dimensions:
	dim = 4 ;
variables:
	float var(dim) ;
		var:units = "m/s" ;

// global attributes:
		:title = "for testing groups" ;
data:

 var = 1, 2, 3, 4 ;

group: g1 {
  dimensions:
  	dim = 1 ;
  variables:
  	float var(dim) ;
  		var:units = "km/hour" ;

  // group attributes:
  		:title = "in first group" ;
  data:

   var = 1 ;
  } // group g1

group: g2 {
  dimensions:
  	dim = 2 ;
  variables:
  	float var(dim) ;
  		var:units = "cm/sec" ;

  // group attributes:
  		:title = "in second group" ;
  data:

   var = 1, 2 ;

  group: g3 {
    dimensions:
    	dim = 3 ;
    variables:
    	float var(dim) ;
    		var:units = "mm/msec" ;
    	float var2(/dim, /g2/dim, dim) ;

    // group attributes:
    		:title = "in third group" ;
    data:

     var = 1, 2, 3 ;

     var2 =
  1, 2, 3,
  4, 5, 6,
  7, 8, 9,
  10, 11, 12,
  13, 14, 15,
  16, 17, 18,
  19, 20, 21,
  22, 23, 24 ;
    } // group g3
  } // group g2
}


/*
Copyright (c) 2018-2020 Uber Technologies, Inc.

This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
*/
// @flow
// BASEUI-GENERATED-FLAG-COMPONENT
// DO NOT EDIT THIS FILE DIRECTLY

import * as React from 'react';

export default function FlagEE(props: mixed) {
  return (
    <img
      src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD8AAAAtBAMAAADrb658AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAeUExURfz8/PT09BEREVKd5Vmk7RkZGUuV3iAgICQkJCYmJq3rrjoAAAEVSURBVDjL1YyxasQwDIblN7DfoASyHyR4Pmgf4DCYrIWA51tCbuzWZOuYvG1/yfElBxdfh6OlH7b0S/olestzpL83HKjKc6S6rqvXeo/q4YUfGGyeA7VtCMGGNlgrKtbWLt13khJdrpIJU15AaMWQ4xmGeZoGMI7jNM/DhIQ/Sxd5+qIhzwf1ec7UXy7959rYVqxh6Jvd9YYvdFsa4CUK6JzJ+8YnRHVrDU7k79E9MmwvOIal27KMnTtRWRZ4gEXhOJSxIc0XQpChE5FSuVCwIcszDP8CreTR+hE0iSaFSmmtAEf+BolLZGUMaWxIpbUx6BnkqHRUMBiZs9Q8jheuLgNDhA9KTjXvcEqGW9RV7RjMrxq+AYEyNRq9P9ddAAAAAElFTkSuQmCC"
      alt="EE"
      {...props}
    />
  );
}


	  Wearable Sensing EEGLAB Extension 1.09
	  --------------------------------------

The purpose of this plug-in is to allow EEGLAB to read the
.CSV files produced by Wearable Sensing's DSI-Streamer software.
This will allow you to take advantage of EEGLAB's data processing
features to analyze the data you collect with Wearable Sensing's
dry electrode systems.

This plugin works best with DSI-Streamer versions 0.6.x and forward.
We recommend you use the most recent version, which can be accessed
from the Wearable Sensing website.

	For more information on DSI-Streamer and other Wearable Sensing
	products, please visit our website:

	http://www.wearablesensing.com/support.php

	For more information on EEGLAB, please visit SCCN's website:

	http://sccn.ucsd.edu/eeglab/

Version notes
-------------

1.00: Initial release

1.01:
	Bugfix: Sampling rate error
	 -Sampling rate was not registering properly.  Now, the files loaded
	  into EEGLAB should have correct sampling rate and load EEG data correctly.

1.02:

	New Feature: Backwards compatibility
	 -Previously, the plugin only worked with files generated by 0.7.x.
	  Now, it works with 0.6.x

1.03:
	Bugfix: Corrected DSI-7 Loading
	 -Occasionally, DSI-7 would not load into EEGLAB.
	  This has been resolved.

1.04:
	Bugfix: Reference Channel now properly loads.
	 -Previous versions of this extension did not actually
	  include the reference channel.  It should correctly load now.

1.05:
	Revisions: Clarified Filter type (FIR), changed default value
	 -Previous versions did not specify what type of filter was applied
	  to the data when it is initially loaded, and had a value of 100 as
	  default.  After testing, we believe a default of 70 is better.

	Bugfix: Lowpass Filter now works properly
	 -Previously, the initial FIR filter was not actually being applied
	  to the data.  This has been corrected.

1.06:
	Revision: Event names are now "1","2", etc. instead of "trigger 1", "trigger 2"
	 -This is preferred for ERPLAB integration.

	Revision: Minor documentation corrections
	 -The help file now correctly indicates [70] as the recommended default lowpass.

1.07:
	Revision: DSI-Streamer 0.7.31 has a function for including custom events..
	 -As of this version of the DSI-Streamer plugin, the comments are not registered
          into EEGLAB, but at least this version no longer crashes.  1.08 should register them.
	Bugfix: if Trigger is at a non-zero value in the first time index, Plugin should no longer crash.

1.08:
	Revision: DSI-Streamer 0.7.34 should be able to load this version
	New Feature: Tidied up code should make loading larger datafiles faster.

1.09:
	Improved backwards compatability.
		-Functions in previous version could only be used in 2013 forward.  This is no longer true.

Requirements
------------

MATLAB, version 2008 or more recent

MATLAB Signal processing toolbox

EEGLAB version 12 or more recent
(obtainable from the EEGLAB website)

Installation
------------

  1. In the EEG folders, find the following directory: /eeglab(VERSION)/plugins/
	-(VERSION) above will be the EEGLAB version, such as 13_3_3

  2. Extract the Wearable Sensing folder from the .zip file
     into that directory.

  3. Run EEGLAB through MATLAB.

If done correctly, the "From WearableSensing .CSVs" option
should be visible in EEGLAB's File menu in the
"Import Data" > "Using EEGLAB functions and plugins" subdirectories.

Features
--------

-Imports Event Triggers from the CSV files
-Specify channels, time ranges to import
-Lowpass filter on import (recommended at 100 Hz, or lower)

Problems? Requests?
-------------------

If you encounter any bugs or would like to request any features,
please contact:

steven@wearablesensing.com


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IBClasses</key>
	<array>
		<dict>
			<key>ACTIONS</key>
			<dict>
				<key>changePlaybackLocation</key>
				<string>id</string>
				<key>changePlaybackVolume</key>
				<string>id</string>
				<key>fastForward</key>
				<string>id</string>
				<key>insert</key>
				<string>id</string>
				<key>recordPause</key>
				<string>id</string>
				<key>rewind</key>
				<string>id</string>
				<key>setAudioFileFormat</key>
				<string>id</string>
				<key>setChannelGain</key>
				<string>id</string>
				<key>startRecording</key>
				<string>id</string>
				<key>togglePlaythru</key>
				<string>id</string>
			</dict>
			<key>CLASS</key>
			<string>SproutedAudioRecorder</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>OUTLETS</key>
			<dict>
				<key>fastforward</key>
				<string>NSButton</string>
				<key>insertButton</key>
				<string>NSButton</string>
				<key>mMeteringView</key>
				<string>PDMeteringView</string>
				<key>playbackLocSlider</key>
				<string>PDMovieSlider</string>
				<key>playbackLockHolder</key>
				<string>NSView</string>
				<key>player</key>
				<string>QTMovieView</string>
				<key>recAlbumField</key>
				<string>NSTextField</string>
				<key>recArtistField</key>
				<string>NSTextField</string>
				<key>recProgress</key>
				<string>NSProgressIndicator</string>
				<key>recProgressText</key>
				<string>NSTextField</string>
				<key>recProgressWin</key>
				<string>NSWindow</string>
				<key>recTitleField</key>
				<string>NSTextField</string>
				<key>recordButton</key>
				<string>NSButton</string>
				<key>recordFormat</key>
				<string>NSPopUpButton</string>
				<key>recorderController</key>
				<string>NSObjectController</string>
				<key>rewind</key>
				<string>NSButton</string>
				<key>timeField</key>
				<string>NSTextField</string>
				<key>view</key>
				<string>NSView</string>
				<key>volumeImage</key>
				<string>NSImageView</string>
				<key>volumeSlider</key>
				<string>NSSlider</string>
			</dict>
			<key>SUPERCLASS</key>
			<string>SproutedRecorder</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>PDMeteringView</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>MeteringView</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>NSView</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>NSResponder</string>
		</dict>
		<dict>
			<key>ACTIONS</key>
			<dict>
				<key>relaunch</key>
				<string>id</string>
			</dict>
			<key>CLASS</key>
			<string>NSApplication</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>NSResponder</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>FirstResponder</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>NSObject</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>NSObject</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>PDMovieSlider</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>NSSlider</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>NSCell</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>NSObject</string>
		</dict>
		<dict>
			<key>CLASS</key>
			<string>MeteringView</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>SUPERCLASS</key>
			<string>NSView</string>
		</dict>
		<dict>
			<key>ACTIONS</key>
			<dict>
				<key>saveRecording</key>
				<string>id</string>
				<key>stopRecording</key>
				<string>id</string>
			</dict>
			<key>CLASS</key>
			<string>SproutedRecorder</string>
			<key>LANGUAGE</key>
			<string>ObjC</string>
			<key>OUTLETS</key>
			<dict>
				<key>view</key>
				<string>NSView</string>
			</dict>
			<key>SUPERCLASS</key>
			<string>NSObject</string>
		</dict>
	</array>
	<key>IBVersion</key>
	<string>1</string>
</dict>
</plist>


@staticPath: "../../";
// Z-indexes
@zindex-context   : 10;
@zindex-content   : @zindex-context+100;
@zindex-tooltips  : @zindex-content+100;
@zindex-loading   : @zindex-tooltips+100;
@zindex-breadcrumb: @zindex-loading+100;
@zindex-header    : @zindex-breadcrumb+100;
// Icons font
@import '//netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css';
// Bootstrap dependancies
@import 'components/bootstrap/loader.less';
@import 'components/bootstrap/alert.less';
@import 'components/bootstrap/fonts.less';
@import 'components/bootstrap/dropdown-menu.less';
@import 'components/bootstrap/form.less';
@import 'components/bootstrap/icon.less';
@import 'components/bootstrap/menu.less';
@import 'components/bootstrap/navs.less';
@import 'components/bootstrap/modals.less';
@import 'components/bootstrap/pagination.less';
@import 'components/bootstrap/panel.less';
// Custom mixin and helper classes
@import 'components/tools/tools.less';
@import 'components/animations/animations.less';
// Core
@import 'components/graphviz/graphviz.less';

@embed-heading-height: 30px;

.embed {

	position:fixed;
	top:0;
	bottom:0;
	right:0;
	left:0;

	&--loading:before {
		content:"";
		position:absolute;
		top:0;
		bottom:0;
		right:0;
		left:0;
		background:@brand-secondary;
		z-index:30;
	}

	&--loading:after {
		z-index:40;
		color:white;
		content:"Loading...";
		position:absolute;
		top:50%;
		left:50%;
		.translate(-50%, -50%);
	}

	&__heading {
		z-index: 20;
		background: @brand-secondary;
		position:fixed;
		top:0;
		right:0;
		left:0;
		padding:0 10px;
		height: @embed-heading-height;
		line-height: @embed-heading-height;
		white-space: nowrap;
		color: contrast(@brand-secondary);
		overflow: hidden;
		.box-shadow(0 0 10px black);

		&__name {
			display: inline-block;
			font-size: inherit;
			margin:0;
			font-weight: bold;
			a, a:hover, a:active {
				color:white;
			}
		}

		&__brand {
			position: absolute;
			right:0px;
			top:0;
			padding:inherit;
			font-size:0.8em;
			background: @brand-secondary;
			.box-shadow(0 0 20px 10px @brand-secondary);
		}
	}

	&__graphviz {
		z-index: 10;
		position:absolute;
		top:@embed-heading-height;
		bottom:0;
		left:0;
		right:0;
	}
}


<!doctype html>

		<meta charset="utf-8">

		<title>reveal.js - Tests</title>

		<link rel="stylesheet" href="../css/reveal.css">
		<link rel="stylesheet" href="qunit-1.12.0.css">

1

					<video data-src="fake-url.mp4"></video>
					<audio data-src="fake-url.mp3"></audio>

2.1

2.2

2.3

3.1

4.1

4.2

4.3

3.2

4.1

4.2

3.3

3.3.1

3.3.2

3.3.3

4


// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: jdtang@google.com (Jonathan Tang)

#include "util.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#include <stdio.h>

#include "gumbo.h"
#include "parser.h"

// TODO(jdtang): This should be elsewhere, but there's no .c file for
// SourcePositions and yet the constant needs some linkage, so this is as good
// as any.
const GumboSourcePosition kGumboEmptySourcePosition = { 0, 0, 0 };

/*
 * Default memory management helpers;
 * set to system's realloc and free by default
 */
void *(* gumbo_user_allocator)(void *, size_t) = realloc;
void (* gumbo_user_free)(void *) = free;

void gumbo_memory_set_allocator(void *(*allocator_p)(void *, size_t))
{
  gumbo_user_allocator = allocator_p ? allocator_p : realloc;
}

void gumbo_memory_set_free(void (*free_p)(void *))
{
  gumbo_user_free = free_p ? free_p : free;
}

bool gumbo_isspace(unsigned char ch)
{
  switch(ch) {
    case ' ':
    case '\f':
    case '\r':
    case '\n':
    case '\t':
      return true;
    default:
      return false;
  }
}

bool gumbo_isalnum(unsigned char ch)
{
  if ('a' <= ch && ch <= 'z') return true;
  if ('A' <= ch && ch <= 'Z') return true;
  if ('0' <= ch && ch <= '9') return true;
  return false;
}

// Debug function to trace operation of the parser.  Pass --copts=-DGUMBO_DEBUG
// to use.
void gumbo_debug(const char* format, ...) {
#ifdef GUMBO_DEBUG
  va_list args;
  va_start(args, format);
  vprintf(format, args);
  va_end(args);
  fflush(stdout);
#endif
}


.TH ola_uni_merge 1 "June 2015"
.SH NAME
ola_uni_merge \- Set the merge mode for a universe in olad.
.SH SYNOPSIS
.B ola_uni_merge
--universe <uni> [--ltp]
.SH DESCRIPTION
.B ola_uni_merge
is used to set the merge mode for a universe. Without --ltp it will revert to
HTP mode.
.SH OPTIONS
.IP "-l, --ltp"
Change to LTP mode.
.IP "-u, --universe <universe>"
Id of the universe to name.
.IP "-h, --help"
Display the help message
.SH SEE ALSO
.BR olad(1) ,
.


# 7.3 review exercises

# Display whether the length of user input is <, > or = 5 characters
my_input = input("Type something: ")

if len(my_input) < 5:
    print("Your input is less than 5 characters long.")
elif len(my_input) > 5:
    print("Your input is greater than 5 characters long.")
else:
    print("Your input is 5 characters long.")


/**
 * created by jiang, 16/2/24
 * Copyright (c) 2016, jyuesong@gmail.com All Rights Reserved.
 * *                #                                                   #
 * #                       _oo0oo_                     #
 * #                      o8888888o                    #
 * #                      88" . "88                    #
 * #                      (| -_- |)                    #
 * #                      0\  =  /0                    #
 * #                    ___/`---'\___                  #
 * #                  .' \\|     |# '.                 #
 * #                 / \\|||  :  |||# \                #
 * #                / _||||| -:- |||||- \              #
 * #               |   | \\\  -  #/ |   |              #
 * #               | \_|  ''\---/''  |_/ |             #
 * #               \  .-\__  '-'  ___/-. /             #
 * #             ___'. .'  /--.--\  `. .'___           #
 * #          ."" '<  `.___\_<|>_/___.' >' "".         #
 * #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       #
 * #         \  \ `_.   \_ __\ /__ _/   .-` /  /       #
 * #     =====`-.____`.___ \_____/___.-`___.-'=====    #
 * #                       `=---='                     #
 * #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   #
 * #                                                   #
 * #               佛祖保佑         永无BUG              #
 * #                                                   #
 */

package android.jiang.com.progressview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by jiang on 16/2/24.
 */
public class ProgressView extends View {

    /**
     * 绘制的笔
     */
    private Paint mPaint;

    /**
     * 控件的宽高
     */
    private int mWidth;
    private int mHeight;

    /**
     * 圆的半径
     */
    private int circleRadius;
    /**
     * 圆弧的半径
     */
    private int stokenRadius;

    /**
     * 圆弧的宽度
     */
    private int stokenWidth;
    /**
     * 线与圆弧之间的距离
     */
    private int linePadding;

    /**
     * 选中和没选中的颜色
     */
    private int checkedColor = Color.WHITE;
    private int uncheckedColor = Color.parseColor("#ECA6AD");

    /**
     * 文字的大小
     */
    private int normaltextSize;

    /**
     * 文字距离顶部的距离
     */
    private int textPaddingTop;

    /**
     * 个数
     */
    private int circleCount = 0;

    /**
     * 文本的信息
     */
    private Paint.FontMetricsInt fontMetricsInt;

    /**
     * 圆的y轴
     */
    private int circlePointY;

    /**
     * 根据宽度算出平均分得的宽度
     */
    private int everyWidth;

    /**
     * 数据
     */
    private List<Model> mModels = new ArrayList<>();

    /**
     * 常量
     *
     * @param context
     */
    public static final int CIRCLE_RADIUS = 4;
    public static final int STOKEN_RADIUS = 9;
    public static final int STOKEN_WIDTH = 2;
    public static final int LINE_PADDING = 6;
    public static final int TEXTPADDINGTOP = 10;
    public static final int NORMALTEXTSIZE = 14;
    public static final int AFTER = 144;
    public static final int STARTING = 143;
    public static final int BEFORE = 142;

    public ProgressView(Context context) {
        this(context, null);
    }

    public ProgressView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initValues();
        initpaint();
    }

    /**
     * 配置一些初始值
     */
    private void initValues() {
        circleRadius = Utils.dip2px(getContext(), CIRCLE_RADIUS);
        stokenRadius = Utils.dip2px(getContext(), STOKEN_RADIUS);
        stokenWidth = Utils.dip2px(getContext(), STOKEN_WIDTH);
        linePadding = Utils.dip2px(getContext(), LINE_PADDING);
        textPaddingTop = Utils.dip2px(getContext(), TEXTPADDINGTOP);
        normaltextSize = Utils.sp2px(getContext(), NORMALTEXTSIZE);
    }

    /**
     * 配置画笔
     */
    private void initpaint() {
        mPaint = new Paint();
        mPaint.setStrokeWidth(stokenWidth);
        mPaint.setTextSize(normaltextSize);
        fontMetricsInt = mPaint.getFontMetricsInt();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        configValues();

    }

    /**
     * 配置需要用到的数据
     */
    private void configValues() {
        mWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
        mHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();

        circlePointY = mHeight / 2;
        everyWidth = mWidth / (circleCount + 1);
    }

    public void setData(List<Model> models) {
        mModels = models;
        fillInfo();
        invalidate();

    }

    private void fillInfo() {
        circleCount = mModels.size();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (circleCount == 0)
            return;
        for (int i = 0; i < circleCount; i++) {
            int color = getColor(i);
            boolean needStoken = needStoken(i);
            drawCircleWithParam(canvas, everyWidth * (i + 1), circlePointY, needStoken, color, mModels.get(i).name);
            if (i == circleCount - 1)
                return;
            drawLine(canvas, everyWidth * (i + 1), everyWidth * (i + 2), getColor(i + 1));

        }
    }

    private int getColor(int i) {
        int color;
        Model model = mModels.get(i);
        if (model.state == BEFORE) {
            color = checkedColor;
        } else if (model.state == STARTING) {
            color = checkedColor;
        } else {
            color = uncheckedColor;
        }
        return color;
    }

    private boolean needStoken(int i) {
        boolean needStoken = false;
        Model model = mModels.get(i);
        if (model.state == ProgressView.STARTING) {
            needStoken = true;
        }

        return needStoken;
    }

    /**
     * 画线
     *
     * @param canvas
     * @param circleStartX
     * @param mayEndX
     * @param color
     */
    private void drawLine(Canvas canvas, int circleStartX, int mayEndX, int color) {

        int startX = circleStartX + stokenRadius + stokenWidth + linePadding;
        int endX = mayEndX - stokenWidth - stokenRadius - linePadding;
        int startY = mHeight / 2;

        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(color);
        canvas.drawLine(startX, startY, endX, startY, mPaint);
    }

    /**
     * 画圆
     *
     * @param canvas
     * @param circleX
     * @param circleY
     * @param needStoken
     * @param color
     * @param value
     */
    private void drawCircleWithParam(Canvas canvas, int circleX, int circleY, boolean needStoken, int color, String value) {

        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(color);
        canvas.drawCircle(circleX, circleY, circleRadius, mPaint);
        int textWidth = (int) mPaint.measureText(value, 0, value.length());
        int textStartX = circleX - textWidth / 2;
        int textStartY = Math.abs(Math.abs(fontMetricsInt.bottom) + Math.abs(fontMetricsInt.top)) / 2 + circleY + textPaddingTop;
        textStartY += stokenRadius + stokenWidth;

        canvas.drawText(value, textStartX, textStartY, mPaint);
        if (needStoken) {
            mPaint.setStyle(Paint.Style.STROKE);
            canvas.drawCircle(circleX, circleY, stokenRadius, mPaint);
        }
    }

    static class Model {
        String name;

        public Model(String name, int state) {
            this.name = name;
            this.state = state;
        }

        int state;  // BEFORE STARTING AFTER
    }
}