www.pudn.com > ASM86_64.rar > parse.c


#include "i_attribute.h"
#include "a64-2.h"
#include "parse.h"
#include "error.h"
#include "opcode.h"
#include "iob.h"
#include "label.h"

#include 


static char err_msg[80];
static kw_id_t keyword_id = 0;

void print_ekey();


static errno_t parse_keyword(char *s);
static errno_t parse_label(char *s);
static struct return_struct do_parse_transfer(char *s, i_key_t *i_key);


errno_t analyse_line(line_info_t *line_info, e_key_t *e_key, char *s) 
{
	errno_t errno = 0;
	char str[80];

	int i = 0;
	unsigned char c = 0;
	
	if (!s || !s[0]) return ERR_LINE;

	char *p = s;

	/* i_key link */
	i_key_t *i_key = 0;
	ops_attr_t ops_attr = { 0, 0, 0 };


	while (*p && ((*p == ' ') || (*p == KEY_TAB))) 
			p++;		/* skip space or TAB */

	while (*p && ((*p != ' ') && (*p != KEY_TAB))) 
		str[i++] = *p++;
		
	str[i] = 0;
	if (c = get_prefixid(str)) {
		/* this is a instruction prefix */	
		e_key->i_prefix = (prefix_t*)a64_malloc(sizeof(prefix_t));
		e_key->i_prefix->lock = c == 0xf0 ? c : 0;
		e_key->i_prefix->rep = c != 0xf0 ? c : 0;

		i = 0;
		while (*p && ((*p == ' ') || (*p == KEY_TAB))) 
			p++;	/* skip ' ' */

		/* get next instruction string */
		while (*p && ((*p != ' ') && (*p != KEY_TAB)))
			str[i++] = *p++;
		str[i] = 0;

	}

	/* found instruction set */
	if (!(i_key = (i_key_t *)get_ins(str))) {
		mount_err_link(ERR_INS, line_errmsg, 0);

		return ERR_INS; 
	}

	if (c) {
		if (c == 0xf0) {	/* it's lock prefix */
			/* do nothing */	
		} else if (!is_string_ins(i_key)) {	/* it's rep prefix */
			/* example: rep movsb */
			sprintf(err_msg, "at %d: invalid instruction \n", line);
			mount_err_link(0, 0, err_msg);
			return ERR_INS;
		}
	}


next:
	

	/* found instruction */	
	e_key->ops_key = (ops_key_t *)a64_malloc(sizeof(ops_key_t));

	errno |= get_ops_key(e_key->ops_key, p);

	/* check operands valid ??? */
	if (!check_ops_key(e_key->ops_key)) {
		sprintf(err_msg, "at %d: %s\n", line,
			"check operands error, it's invalid operands");

		mount_err_link(0, 0, err_msg);

		return ERR_OPERAND;
	}

	get_ops_attr(&ops_attr,	e_key->ops_key);


	o_key_t *so_key = e_key->ops_key->so_key;
	o_key_t *do_key = e_key->ops_key->do_key;
	mem_t *mem = so_key && so_key->mem ? so_key->mem :
		do_key && do_key->mem ? do_key->mem : 0;
	
	if (mem) {
		if (mem->transfer_cast) {
			if (((i_key == CALL) || (i_key == JMP)) && so_key->mem)
				ops_attr.so_attr |= FAR_POINTER;
			else {
				sprintf(err_msg, 
					"error at %d: error cast\n", line);
				mount_err_link(0, 0, err_msg);

				return ERR_ERROR;
			}
		}	
	}

	
	if (!(e_key->i_key = get_i_key(i_key, &ops_attr))) {
		sprintf(err_msg, "at %d: %s\n", line,
			"invalid instruction or operands");

		mount_err_link(0, 0, err_msg);
			
		return ERR_INS;
	}

	/* check the instruct in current bits is valid ??? */
	if (is_ONLY_IN_BITS(e_key->i_key->i_attr)) {
		if (get_ONLY_BITS(e_key->i_key->i_attr) != current_bits) {
			sprintf(err_msg, "error at %d: %s\n", line,
				"instruct in current bits invalid");

			mount_err_link(0, 0, err_msg);

			return ERR_INS;
		}
	}
	
	
	e_key->bits = current_bits;

	return errno;
}


/********************************************************/
static struct return_struct pre_analyse_line(char *s)
{
	struct return_struct ret = { E_OK, s };
	
	if (!s)
		return ret;

	char *p = s;

	int i = 0;
	char str[80];
	
	errno_t errno = 0;


	for ( ; ; p++) {

		if (is_c(*p) || is_n(*p) || *p == '_') {
			str[i++] = *p;	
		} else switch (*p) {
		case 0 :
			str[i] = 0;
			if (ret.code == E_LABEL && i == 0) {
				sprintf(err_msg, "error at %d: %s\n",
					line, "label string error");
				mount_err_link(0, 0, err_msg);
				ret.code == E_ERROR;
				return ret;
			} else if (ret.code == E_KEYWORD && (i == 0)) {
				ret.code = E_ERROR;
			} else if (ret.code == E_NEED_CONON ||
					((ret.code == E_LABEL) && i))
			{
				sprintf(err_msg, "error at %d: %s\n",
					line, "label loss ':'");

				mount_err_link(0, 0, err_msg);
				ret.code = E_ERROR;
				return ret;

			} else if (ret.code == E_OK && i) {
				/* keep E_OK for next step */
				if (keyword_id = get_keyword(str)) {
					ret.code = E_KEYWORD;
					ret.ptr += i;
				}
			} else if (((ret.code == E_BLANK) || 
					(ret.code == E_TAB)) && i) {
				/** reserved for E_KEYWORD */
				if (keyword_id = get_keyword(str)) {	
					ret.code = E_KEYWORD;
					ret.ptr += i;
				} else {
					ret.code = E_OK;
					ret.ptr = s;
				}
			} else 
				ret.code = E_NEW_LINE;

			goto do_parse_error;
		case ' ':
		case KEY_TAB:
			if (i) {
				str[i] = 0;
				if (ret.code == E_KEYWORD) {
					if (keyword_id = get_keyword(str)) {
						ret.code = E_KEYWORD;
						ret.ptr += i;
					} else
						ret.code = E_ERROR;

					goto do_parse_error;

				} else if ((ret.code == E_TAB) ||
						(ret.code == E_BLANK)) {
					i_key_t *i_key;
					/* it's keyword ??? */
					if (keyword_id = get_keyword(str)) {
						ret.code = E_KEYWORD;
						/* skip keyword string */
						ret.ptr += i;
					} 
					else if (i_key=get_transfer_ins(str)) {
						ret.ptr = p + 1;

						ret = do_parse_transfer(
								ret.ptr,i_key);
						
						if (ret.code == E_OK)
							ret.ptr = s;
					
					} else
						ret.code = E_OK;

					goto do_parse_error;

				} else if (ret.code == E_LABEL) {
					/* it's label string */
					/* next step do by E_CONON */

					ret.code = E_NEED_CONON;
					i = 0;

				} else if (ret.code == E_NEED_CONON) {
					sprintf(err_msg, "error at %d: %s \n",
						line, "label loss ':'");
					mount_err_link(0, 0, err_msg);

					ret.code = E_ERROR;
					return ret;

				} else if (ret.code == E_CONON) {
					/* parse label... 
					   next step to do parse line....
					*/
					i_key_t *i_key = 0;
					if (i_key = get_transfer_ins(str)) {
						ret.ptr = p + 1;
						ret = do_parse_transfer(
							ret.ptr, i_key);
						if (ret.code == E_OK)
							ret.ptr = s;
					} else {
						ret.code = E_OK; 
					}

					goto do_parse_error;
				} else if (ret.code == E_BLANK) {
					if (keyword_id = get_keyword(str)) {
						ret.code = E_KEYWORD;
						ret.ptr += i;
					} else
						ret.code = E_OK;

					goto do_parse_error;

				} else if (ret.code == E_OK) {
					i_key_t *i_key = 0;
					if (keyword_id = get_keyword(str)) {
						ret.code = E_KEYWORD;
						ret.ptr += i;
					} 
					else if (i_key=get_transfer_ins(str))
					{
						ret.ptr = p + 1;
						ret = do_parse_transfer(
							ret.ptr, i_key);

						if (ret.code == E_OK)
							ret.ptr = s;	
					}
					/* next step to do parse line... */
					goto do_parse_error;
				}


			/* it's blank string...... */
			} else {
				if (ret.code == E_KEYWORD) {
					/* it's keyword */
					/* it's allow ". xxxx" */
	
					break;
				} else if (ret.code == E_LABEL) {
					/* it's error */
					sprintf(err_msg, "error at %d: %s\n",
						line, "the label is error");
					mount_err_link(0, 0, err_msg);
					ret.code = E_ERROR;
					goto do_parse_error;

				} else if (ret.code == E_CONON) {
					if (*p == ' ')
						ret.code = E_BLANK;
					else	
						ret.code = E_TAB;
					ret.ptr = p + 1;
				} else if (ret.code == E_NEED_CONON) {
					/* keep the flag for label */
				} else {
					if (*p == ' ')
						ret.code = E_BLANK;
					else if (*p == KEY_TAB) 
						ret.code = E_TAB;
				}
			}
			ret.ptr = p + 1;
			break;
		case '.': 			/* it's a keyword */
			if (i || ret.code == E_KEYWORD || ret.code == E_LABEL
				|| ret.code == E_CONON)  {
				ret.code = E_ERROR;
				goto do_parse_error;
			}
			ret.code = E_KEYWORD;
			ret.ptr = p + 1;

			i = 0; break;
		case '@':			/* it's a label */
			if(i || ret.code == E_KEYWORD || ret.code == E_LABEL
				|| ret.code == E_CONON) { 
				ret.code = E_ERROR;
				goto do_parse_error;
			}
			ret.code = E_LABEL;
			ret.ptr = p + 1;
			i = 0; break;
		case ':':
			if ((ret.code != E_LABEL) && (ret.code != E_NEED_CONON)) 
			{
				ret.code = E_ERROR;
				goto do_parse_error;
			}
		
			if (ret.code != E_NEED_CONON)
				str[i] = 0;

			if (errno = parse_label(str)) {
				mount_err_link(E_LABEL, line_errmsg, 0);
				ret.code = E_ERROR;
				return ret;
			}
			ret.code = E_CONON;
			ret.ptr = p + 1;
			i = 0; break;
		case '!':			/* it's a comment */
			ret.code = E_COMMENT;
			return ret;
		case '\n':			/* new line */
			ret.code = E_NEW_LINE;
			goto do_parse_error;
		default: 
			ret.code = E_ERROR;
			goto do_parse_error;
		}

	}

do_parse_error:
	if (ret.code == E_ERROR) {
		sprintf(err_msg, "error at line %d: %s '%c'\n",
			line, "parse error at ", *p);

		mount_err_link(0, 0, err_msg);
	}

	return ret;
}


/*************************************************************/
static errno_t parse_label(char *s)
{
	errno_t errno = 0;
	
	if (!is_label(s))
		mount_label_table(s);
	else
		errno = E_LABEL;

	return errno;
}


static struct return_struct do_parse_transfer(char *p, i_key_t *i_key)
{
	struct return_struct ret = { 0, p };


	int i = 0;
	char str[80];

	while (*p && (*p == ' ' || *p == KEY_TAB))
		p++;	

	if (*p == '@') {
		p++;

		while (*p && *p != ' ' && *p != KEY_TAB)
			str[i++] = *p++;
		str[i] = 0;

		mount_hole_link(str, i_key);

		ret.code = E_NEW_LINE;

	} else {
		/* this is a memory operand 
		   example: jmp [ecx] */

		ret.code = E_OK;
	}

	return ret;
}


/*************************************************************/
static errno_t parse_keyword(char *s)
{
	errno_t errno = 0;

	char *p = s;

	int i = 0;
	char str[80];

	while (*p && (*p == ' '|| *p == KEY_TAB))  
			p++;

	while (*p && *p != ' ' && *p != KEY_TAB)
			str[i++] = *p++;
	str[i] = 0;

	while (*p && (*p == ' ' || *p == KEY_TAB)) p++;

	switch (keyword_id) {
	case KW_MODE:
		current_mode = get_modeid(str);
		if (!current_mode || *p) {
			sprintf(err_msg, "error at %d: mode value error\n", 
					line);
			mount_err_link(0, 0, err_msg);
			return ERR_ERROR;
		}
		
		break;
	case KW_BITS:
		current_bits = get_bitsid(str);
		if (!current_bits || *p) {
			sprintf(err_msg, "error at %d: bits value error\n",
				line);
			mount_err_link(0, 0, err_msg);
			return ERR_ERROR;
		}

		break;

	case KW_FUNCTION: 	/* it's function */
		break;
	case KW_VAR:
		break;
	case KW_CONST:
		break;
	case KW_CODE:
		break;
	case KW_TEXT:
		break;
	case KW_BYTE:
		break;
	case KW_WORD:
		break;
	case KW_DWORD:
		break;
	case KW_QWORD:
		break;
	case KW_MACRO:
		break;
	case KW_PTR:
		break;
	}

	return errno;
}

/*********************************************************************/
/*
static proceed_parse_keyword(char *s)
{
}
*/

/************************************************************************
 function: analyse_file()
 paramter: void:
 return value: errno if error
	
************************************************************************/

errno_t analyse_file(struct iob *iob)
{
	errno_t errno = 0;
	struct return_struct ret = { E_OK, 0 };

	char linebuf[LINE_SIZE];
	char err_msg[80];

	e_key_t *head_e_key = e_key_link;

	line_info_t line_info = { 0, 0 };
		
	/* parse file */
	while (read_into_iob(iob, sizeof(iob->buf))) {
		/* parse line */
		while (readln_from_iob(iob, linebuf)) {
			line++; 
			
			ret = pre_analyse_line(linebuf);

			if (ret.code == E_ERROR) {
				return ERR_OPERAND;
			} else if (ret.code == E_KEYWORD) {
				errno = parse_keyword(ret.ptr);
				if (errno)	
					return ERR_OPERAND;
					// goto do_analyse_file_error;
				continue;
			} else if (ret.code == E_BLANK) {
			} else if (ret.code == E_NEW_LINE) {
			} else if (ret.code == E_COMMENT) {
			} else if (ret.code == E_OK) {

				e_key_t *p = 
					(e_key_t *)a64_malloc(sizeof(e_key_t));
				p->line = line;

				errno = analyse_line(&line_info, p, ret.ptr);
				if (errno)
					return errno;

				if (!head_e_key) {	
					head_e_key = p;
					e_key_link = p;	/* global e_key link */
				} else {
					while (head_e_key->next)
						head_e_key = head_e_key->next;
					head_e_key->next = p;
				}

				
			}


			/* next line .... */
		}
	}

do_analyse_file_error:

	return errno;
}

/************************************************************************/

void print_ekey()
{
	e_key_t *e_key = e_key_link;

	while (e_key) {
	
#if 0
		puts("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
		if (e_key->ops_key)
			print_ops(e_key->ops_key);
		if (e_key->i_key) {
			printf("---i_attr: %x\n", e_key->i_key->i_attr);
			printf("---opcode:%x\n", e_key->i_key->opcode);
		}
		if (e_key->i_prefix) {
			printf("---lock: %x\n" ,e_key->i_prefix->lock);
			printf("---rep: %x\n", e_key->i_prefix->rep);
		}

		puts("#############################");
#endif

		printf("e_key line is %d\n", e_key->line);
		e_key = e_key->next;
	}
}


/*

char *testfile = "test.s";
#include 

int main()
{
	struct iob riob, wiob;
	int fd = open(testfile, O_RDONLY);
	int fdw = open("kkk", O_CREAT);
	init_iob(fd, &riob);
	init_iob(fdw, &wiob);

	char *e_buf = (char *)malloc(512);
	errno_t errno = 0;
	int i = 0;


	errno = analyse_file(&riob);
	if (errno) {
		printf("%d\n",current_mode);
		print_err();
		exit(1);
	}

	if (errno = generate(&wiob)) {
		print_err();
		release_resource();
		exit(1);
	}	

	flush_all_iob(&wiob);



#ifdef DEBUG_PRINT_CODE
	while(i