⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_compile.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:

static int slang_struct_equal (const slang_struct *x, const slang_struct *y)
{
	unsigned int i;
	if (x->fields->num_variables != y->fields->num_variables)
		return 0;
	for (i = 0; i < x->fields->num_variables; i++)
	{
		slang_variable *varx = x->fields->variables + i;
		slang_variable *vary = y->fields->variables + i;
		if (slang_string_compare (varx->name, vary->name) != 0)
			return 0;
		if (!slang_type_specifier_equal (&varx->type.specifier, &vary->type.specifier))
			return 0;
		if (varx->type.specifier.type == slang_spec_array)
		{
			/* TODO compare array sizes */
		}
	}
	return 1;
}

/* slang_function */
/* XXX mem! */
static void slang_function_construct (slang_function *func)
{
	func->kind = slang_func_ordinary;
	slang_variable_construct (&func->header);
	func->parameters = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope));
	slang_variable_scope_construct (func->parameters);
	func->body = NULL;
	func->address = ~0;
}

static void slang_function_destruct (slang_function *func)
{
	slang_variable_destruct (&func->header);
	slang_variable_scope_destruct (func->parameters);
	slang_alloc_free (func->parameters);
	if (func->body != NULL)
	{
		slang_operation_destruct (func->body);
		slang_alloc_free (func->body);
	}
}

/* slang_function_scope */

static void slang_function_scope_construct (slang_function_scope *scope)
{
	scope->functions = NULL;
	scope->num_functions = 0;
	scope->outer_scope = NULL;
}

static void slang_function_scope_destruct (slang_function_scope *scope)
{
	unsigned int i;
	for (i = 0; i < scope->num_functions; i++)
		slang_function_destruct (scope->functions + i);
	slang_alloc_free (scope->functions);
}

static int slang_function_scope_find_by_name (slang_function_scope *funcs, const char *name,
	int all_scopes)
{
	unsigned int i;
	for (i = 0; i < funcs->num_functions; i++)
		if (slang_string_compare (name, funcs->functions[i].header.name) == 0)
			return 1;
	if (all_scopes && funcs->outer_scope != NULL)
		return slang_function_scope_find_by_name (funcs->outer_scope, name, 1);
	return 0;
}

static slang_function *slang_function_scope_find (slang_function_scope *funcs, slang_function *fun,
	int all_scopes)
{
	unsigned int i;
	for (i = 0; i < funcs->num_functions; i++)
	{
		slang_function *f = funcs->functions + i;
		unsigned int j;
		if (slang_string_compare (fun->header.name, f->header.name) != 0)
			continue;
		if (fun->param_count != f->param_count)
			continue;
		for (j = 0; j < fun->param_count; j++)
		{
			if (!slang_type_specifier_equal (&fun->parameters->variables[j].type.specifier,
				&f->parameters->variables[j].type.specifier))
			{
				break;
			}
		}
		if (j == fun->param_count)
			return f;
	}
	if (all_scopes && funcs->outer_scope != NULL)
		return slang_function_scope_find (funcs->outer_scope, fun, 1);
	return NULL;
}

/* slang_translation_unit */

void slang_translation_unit_construct (slang_translation_unit *unit)
{
	slang_variable_scope_construct (&unit->globals);
	slang_function_scope_construct (&unit->functions);
	slang_struct_scope_construct (&unit->structs);
}

void slang_translation_unit_destruct (slang_translation_unit *unit)
{
	slang_variable_scope_destruct (&unit->globals);
	slang_function_scope_destruct (&unit->functions);
	slang_struct_scope_destruct (&unit->structs);
}

/* slang_info_log */

static char *out_of_memory = "error: out of memory\n";

void slang_info_log_construct (slang_info_log *log)
{
	log->text = NULL;
	log->dont_free_text = 0;
}

void slang_info_log_destruct (slang_info_log *log)
{
	if (!log->dont_free_text)
		slang_alloc_free (log->text);
}

static int slang_info_log_message (slang_info_log *log, const char *prefix, const char *msg)
{
	unsigned int new_size;
	if (log->dont_free_text)
		return 0;
	new_size = slang_string_length (prefix) + 3 + slang_string_length (msg);
	if (log->text != NULL)
	{
		log->text = (char *) slang_alloc_realloc (log->text, slang_string_length (log->text) + 1,
			new_size + slang_string_length (log->text) + 1);
	}
	else
	{
		log->text = (char *) slang_alloc_malloc (new_size + 1);
		if (log->text != NULL)
			*log->text = '\0';
	}
	if (log->text == NULL)
		return 0;
	slang_string_concat (log->text, prefix);
	slang_string_concat (log->text, ": ");
	slang_string_concat (log->text, msg);
	slang_string_concat (log->text, "\n");
	return 1;
}

int slang_info_log_error (slang_info_log *log, const char *msg, ...)
{
	va_list va;
	char buf[1024];

	va_start (va, msg);
	vsprintf (buf, msg, va);
	if (slang_info_log_message (log, "error", buf))
		return 1;
	slang_info_log_memory (log);
	va_end (va);
	return 0;
}

int slang_info_log_warning (slang_info_log *log, const char *msg, ...)
{
	va_list va;
	char buf[1024];

	va_start (va, msg);
	vsprintf (buf, msg, va);
	if (slang_info_log_message (log, "warning", buf))
		return 1;
	slang_info_log_memory (log);
	va_end (va);
	return 0;
}

void slang_info_log_memory (slang_info_log *log)
{
	if (!slang_info_log_message (log, "error", "out of memory"))
	{
		log->dont_free_text = 1;
		log->text = out_of_memory;
	}
}

/* slang_parse_ctx */

typedef struct slang_parse_ctx_
{
	const byte *I;
	slang_info_log *L;
	int parsing_builtin;
} slang_parse_ctx;

/* _slang_compile() */

static int parse_identifier (slang_parse_ctx *C, char **id)
{
	*id = slang_string_duplicate ((const char *) C->I);
	if (*id == NULL)
	{
		slang_info_log_memory (C->L);
		return 0;
	}
	C->I += strlen ((const char *) C->I) + 1;
	return 1;
}

static int parse_number (slang_parse_ctx *C, int *number)
{
	const int radix = (int) (*C->I++);
	*number = 0;
	while (*C->I != '\0')
	{
		int digit;
		if (*C->I >= '0' && *C->I <= '9')
			digit = (int) (*C->I - '0');
		else if (*C->I >= 'A' && *C->I <= 'Z')
			digit = (int) (*C->I - 'A') + 10;
		else
			digit = (int) (*C->I - 'a') + 10;
		*number = *number * radix + digit;
		C->I++;
	}
	C->I++;
	if (*number > 65535)
		slang_info_log_warning (C->L, "%d: literal integer overflow", *number);
	return 1;
}

static int parse_float (slang_parse_ctx *C, float *number)
{
	char *integral = NULL;
	char *fractional = NULL;
	char *exponent = NULL;
	char *whole = NULL;

	if (!parse_identifier (C, &integral))
		return 0;

	if (!parse_identifier (C, &fractional))
	{
		slang_alloc_free (integral);
		return 0;
	}

	if (!parse_identifier (C, &exponent))
	{
		slang_alloc_free (fractional);
		slang_alloc_free (integral);
		return 0;
	}

	whole = (char *) (slang_alloc_malloc ((strlen (integral) + strlen (fractional) + strlen (
		exponent) + 3) * sizeof (char)));
	if (whole == NULL)
	{
		slang_alloc_free (exponent);
		slang_alloc_free (fractional);
		slang_alloc_free (integral);
		slang_info_log_memory (C->L);
		return 0;
	}

	slang_string_copy (whole, integral);
	slang_string_concat (whole, ".");
	slang_string_concat (whole, fractional);
	slang_string_concat (whole, "E");
	slang_string_concat (whole, exponent);

	*number = (float) (atof (whole));

	slang_alloc_free (whole);
	slang_alloc_free (exponent);
	slang_alloc_free (fractional);
	slang_alloc_free (integral);
	return 1;
}

/* revision number - increment after each change affecting emitted output */
#define REVISION 2

static int check_revision (slang_parse_ctx *C)
{
	if (*C->I != REVISION)
	{
		slang_info_log_error (C->L, "internal compiler error");
		return 0;
	}
	C->I++;
	return 1;
}

static int parse_statement (slang_parse_ctx *, slang_operation *, slang_variable_scope *,
	slang_struct_scope *, slang_function_scope *);
static int parse_expression (slang_parse_ctx *, slang_operation *, slang_variable_scope *,
	slang_struct_scope *, slang_function_scope *);

/* type qualifier */
#define TYPE_QUALIFIER_NONE 0
#define TYPE_QUALIFIER_CONST 1
#define TYPE_QUALIFIER_ATTRIBUTE 2
#define TYPE_QUALIFIER_VARYING 3
#define TYPE_QUALIFIER_UNIFORM 4
#define TYPE_QUALIFIER_FIXEDOUTPUT 5
#define TYPE_QUALIFIER_FIXEDINPUT 6

static int parse_type_qualifier (slang_parse_ctx *C, slang_type_qualifier *qual)
{
	switch (*C->I++)
	{
	case TYPE_QUALIFIER_NONE:
		*qual = slang_qual_none;
		break;
	case TYPE_QUALIFIER_CONST:
		*qual = slang_qual_const;
		break;
	case TYPE_QUALIFIER_ATTRIBUTE:
		*qual = slang_qual_attribute;
		break;
	case TYPE_QUALIFIER_VARYING:
		*qual = slang_qual_varying;
		break;
	case TYPE_QUALIFIER_UNIFORM:
		*qual = slang_qual_uniform;
		break;
	case TYPE_QUALIFIER_FIXEDOUTPUT:
		*qual = slang_qual_fixedoutput;
		break;
	case TYPE_QUALIFIER_FIXEDINPUT:
		*qual = slang_qual_fixedinput;
		break;
	default:
		return 0;
	}
	return 1;
}

/* type specifier */
#define TYPE_SPECIFIER_VOID 0
#define TYPE_SPECIFIER_BOOL 1
#define TYPE_SPECIFIER_BVEC2 2
#define TYPE_SPECIFIER_BVEC3 3
#define TYPE_SPECIFIER_BVEC4 4
#define TYPE_SPECIFIER_INT 5
#define TYPE_SPECIFIER_IVEC2 6
#define TYPE_SPECIFIER_IVEC3 7
#define TYPE_SPECIFIER_IVEC4 8
#define TYPE_SPECIFIER_FLOAT 9
#define TYPE_SPECIFIER_VEC2 10
#define TYPE_SPECIFIER_VEC3 11
#define TYPE_SPECIFIER_VEC4 12
#define TYPE_SPECIFIER_MAT2 13
#define TYPE_SPECIFIER_MAT3 14
#define TYPE_SPECIFIER_MAT4 15
#define TYPE_SPECIFIER_SAMPLER1D 16
#define TYPE_SPECIFIER_SAMPLER2D 17
#define TYPE_SPECIFIER_SAMPLER3D 18
#define TYPE_SPECIFIER_SAMPLERCUBE 19
#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
#define TYPE_SPECIFIER_STRUCT 22
#define TYPE_SPECIFIER_TYPENAME 23

/* structure field */
#define FIELD_NONE 0
#define FIELD_NEXT 1
#define FIELD_ARRAY 2

static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec,
	slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs)
{
	switch (*C->I++)
	{
	case TYPE_SPECIFIER_VOID:
		spec->type = slang_spec_void;
		break;
	case TYPE_SPECIFIER_BOOL:
		spec->type = slang_spec_bool;
		break;
	case TYPE_SPECIFIER_BVEC2:
		spec->type = slang_spec_bvec2;
		break;
	case TYPE_SPECIFIER_BVEC3:
		spec->type = slang_spec_bvec3;
		break;
	case TYPE_SPECIFIER_BVEC4:
		spec->type = slang_spec_bvec4;
		break;
	case TYPE_SPECIFIER_INT:
		spec->type = slang_spec_int;
		break;
	case TYPE_SPECIFIER_IVEC2:
		spec->type = slang_spec_ivec2;
		break;
	case TYPE_SPECIFIER_IVEC3:
		spec->type = slang_spec_ivec3;
		break;
	case TYPE_SPECIFIER_IVEC4:
		spec->type = slang_spec_ivec4;
		break;
	case TYPE_SPECIFIER_FLOAT:
		spec->type = slang_spec_float;
		break;
	case TYPE_SPECIFIER_VEC2:
		spec->type = slang_spec_vec2;
		break;
	case TYPE_SPECIFIER_VEC3:
		spec->type = slang_spec_vec3;
		break;
	case TYPE_SPECIFIER_VEC4:
		spec->type = slang_spec_vec4;
		break;
	case TYPE_SPECIFIER_MAT2:
		spec->type = slang_spec_mat2;
		break;
	case TYPE_SPECIFIER_MAT3:
		spec->type = slang_spec_mat3;
		break;
	case TYPE_SPECIFIER_MAT4:
		spec->type = slang_spec_mat4;
		break;
	case TYPE_SPECIFIER_SAMPLER1D:
		spec->type = slang_spec_sampler1D;
		break;
	case TYPE_SPECIFIER_SAMPLER2D:
		spec->type = slang_spec_sampler2D;
		break;
	case TYPE_SPECIFIER_SAMPLER3D:
		spec->type = slang_spec_sampler3D;
		break;
	case TYPE_SPECIFIER_SAMPLERCUBE:
		spec->type = slang_spec_samplerCube;
		break;
	case TYPE_SPECIFIER_SAMPLER1DSHADOW:
		spec->type = slang_spec_sampler1DShadow;
		break;
	case TYPE_SPECIFIER_SAMPLER2DSHADOW:
		spec->type = slang_spec_sampler2DShadow;
		break;
	case TYPE_SPECIFIER_STRUCT:
		spec->type = slang_spec_struct;
		{
			char *name;
			if (!parse_identifier (C, &name))
				return 0;
			if (*name != '\0' && slang_struct_scope_find (structs, name, 0) != NULL)
			{
				slang_info_log_error (C->L, "%s: duplicate type name", name);
				slang_alloc_free (name);
				return 0;
			}
			spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
			if (spec->_struct == NULL)
			{
				slang_alloc_free (name);
				slang_info_log_memory (C->L);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -