-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathm_exec_opcode.c
More file actions
132 lines (125 loc) · 2.93 KB
/
Copy pathm_exec_opcode.c
File metadata and controls
132 lines (125 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "monty.h"
/**
* check_opcode - checks if opcode takes argument or not or if
* it even exists.
* @opcode: the opcode to check.
*
* Return: 1 (opcode takes argument), 0 (opcode doesn't take arguments),
* -1 (opcode doesn't exist), 2 for comment.
*/
int check_opcode(char *opcode)
{
int i;
char *arg_opcodes[] = {
"push", NULL
};
char *nonarg_opcodes[] = {
"pall", "pint", "pop", "swap",
"add", "nop", "sub", "div",
"mul", "mod", "pchar", "pstr",
"rotl", "rotr", "stack", "queue",
NULL
};
if (opcode == NULL)
return (0);
if (is_comment(opcode))
return (2);
for (i = 0; arg_opcodes[i] != NULL; i++)
if (exact_match(opcode, arg_opcodes[i]))
return (1);
for (i = 0; nonarg_opcodes[i] != NULL; i++)
if (exact_match(opcode, nonarg_opcodes[i]))
return (0);
return (-1);
}
/**
* execute_opcode - executes an opcode.
* @stack: the for the opcode to operate on.
* @opcode: the opcode to executed.
* @line_number: the number of the line the opcode was found on.
*
* Return: if it returns to the caller (successful), else
* it will exit print an error message.
*/
void execute_opcode(stack_t **stack, char *opcode, unsigned int line_number)
{
instruction_t instructions[] = {
{"push", &op_push}, {"pall", &op_pall}, {"pint", &op_pint},
{"pop", &op_pop}, {"swap", &op_swap}, {"add", &op_add},
{"nop", &op_nop}, {"sub", &op_sub}, {"div", &op_div},
{"mul", &op_mul}, {"mod", &op_mod}, {"pchar", &op_pchar},
{"pstr", &op_pstr}, {"rotl", &op_rotl}, {"rotr", &op_rotr},
{"stack", &op_stack}, {"queue", &op_queue}
};
int i;
for (i = 0; i < OPCODES_N; i++)
{
if (exact_match(opcode, (instructions[i]).opcode))
{
free(opcode);
opcode_info.opcode = NULL;
(instructions[i]).f(stack, line_number);
break;
}
}
}
/**
* handle_opcode_line - extracts the neccessary information from a line of
* montybyte code.
* @line: the line to analayz.
*
* Return: opcode if the line contains a valid opcode.
* else if blank line NULL.
* else prints the right error message and exit.
*/
char *handle_opcode_line(char *line)
{
char *token = NULL, *opcode = NULL, *tmp = NULL;
char *delimeters = " \t\n";
int ret;
if (line == NULL)
return (NULL);
token = strtok(line, delimeters);
if (token == NULL)
{
free(line);
return (NULL);
}
ret = check_opcode(token);
if (ret == -1)
{
opcode_info.opcode = _strdup(token);
free(line); /* needs fixing */
exit_error_msg(_MONTY_UNKNOWN_INSTRUCTION, opcode_info.opcode);
}
if (ret == 1)
{
tmp = strtok(NULL, delimeters);
if (tmp != NULL)
opcode_info.arg = _strdup(tmp);
else
opcode_info.arg = NULL;
}
if (ret == 2)
{
free(line);
return (NULL);
}
opcode = _strdup(token);
free(line);
return (opcode);
}
/**
* is_comment - checks if a given line is a comment or not.
* @line: The line to check.
*
* Return: 1 (comment), 0 (not).
*/
int is_comment(char *line)
{
if (line == NULL)
return (0);
if (*line == '#')
return (1);
return (0);
}