예제 #1
0
char *escape_string(const char *input)
{
	expand_buf_t *escape_string = eb_init(strlen(input) + strlen(input) / 2);

	eb_append(escape_string, "\"", 1);

	unsigned int i;
	for (i = 0; i < strlen(input); i++)
	{
		switch (input[i])
		{
		case '"':
			{
				eb_append(escape_string, "\\\"", -1);
				break;
			}
		case '\\': 
			{
				eb_append(escape_string, "\\\\", -1);
				break;
			}
		default:
			{
				eb_append(escape_string, &input[i], 1);
				break;
			}
		}
	}

	eb_append(escape_string, "\"", 1);
	char *result = eb_extract(escape_string);
	eb_free(escape_string);
	return result;
}
예제 #2
0
char *parse_emit_string (const char *ptr, ES_TYPE type, void *echo_target) {
	static int level = 0;
	char *word = NULL;
	int session;
	bool fWasParsed;
	char *name_end;

	level++;

	arg_context_t context = ARG_CONTEXT_INITIALIZER;
	while ((word = extract_arg_string(&ptr, &context)) != NULL)
	{
		// handle strings
		if (word[0] == '"')
		{
			char *next = next_expr (word, EXPR_DELIMS);
			if (*next != '\0') 
				goto echo_error;
			
			reduce_string (word);
			if (type == ES_ECHO)
			{
				if (echo_target != NULL)
				{
					fprintf ((FILE *) echo_target, "%s", word);
				}
			}
			else if (type == ES_FCREATE) {
				eb_append((expand_buf_t *) echo_target, word, strlen(word));
			} else {
				int i;
				for (i = 0; word[i]; i++) {
					if ((mode & MODE_NORMAL) || (mode & MODE_LIST))
						write_out (word[i]);
	                stats_datasize++;
	                program_counter++;
				}
			}

		} else {
			int value;

			session = StartSPASMErrorSession();
			fWasParsed = parse_num(word, &value);
			if (fWasParsed == true)
			{
				switch (type) 
				{
					case ES_ECHO: 
					{
						if (echo_target != NULL)
						{
							fprintf ((FILE *) echo_target, "%d", value);
						}
						break;
					}
#ifdef USE_BUILTIN_FCREATE
					case ES_FCREATE:
					{
						char buffer[256];
						sprintf_s(buffer, "%d", value);
						eb_append((expand_buf_t *) echo_target, buffer, -1);
						break;
					}
#endif
					case ES_BYTE: 
					{
						write_arg(value, ARG_NUM_8, 0, 0);
		                stats_datasize++;
		                program_counter++;
		                break;
					}
					case ES_WORD:
					{
		                write_arg(value, ARG_NUM_16, 0, 0);
		                stats_datasize+=2;
		                program_counter+=2;
		                break;
					}
					case ES_LONG:
					{
						write_arg(value, ARG_NUM_24, 0, 0);
						stats_datasize+=3;
						program_counter+=3;
						break;
					}
				}

				ReplaySPASMErrorSession(session);
			}
			else if (IsSPASMErrorSessionFatal(session) == false && type != ES_FCREATE)
			{
				switch (type) 
				{
				case ES_ECHO:
					break;
				case ES_BYTE: 
					{
						add_pass_two_expr(word, ARG_NUM_8, 0, 0);
		                stats_datasize++;
		                program_counter++;
		                break;
					}
				case ES_WORD:
					{
		                add_pass_two_expr(word, ARG_NUM_16, 0, 0);
		                stats_datasize+=2;
		                program_counter+=2;
		                break;
					}
				case ES_LONG:
					{
						add_pass_two_expr(word, ARG_NUM_24, 0, 0);
						stats_datasize += 3;
						program_counter += 3;
						break;
					}
				}

				ReplayFatalSPASMErrorSession(session);
			}
			else
			{
				char name[256];
				char *next;
				define_t *define;

				name_end = word;
				//printf("error occured: %d, forward: %d, value: %d\n", error_occurred, parser_forward_ref_err, value);
				read_expr (&name_end, name, "(");
				//printf("Looking up %s\n", name);
				next = name_end;
				read_expr (&next, NULL, ")");
				
				if (*next != '\0')
					goto echo_error;

				if ((define = search_defines (name))) {
					char *expr;
					list_t *args = NULL;
	
					//handle defines
					if (define->contents == NULL)
					{
						SetLastSPASMError(SPASM_ERR_ARG_USED_WITHOUT_VALUE, name);
					}
					
					if (*(name_end - 1) == '(') name_end--;
					name_end = parse_args (name_end, define, &args);
					if (!name_end)
						return (char *) ptr;
					
					expr = parse_define (define);
					if (expr != NULL)
					{
						arg_context_t nested_context = ARG_CONTEXT_INITIALIZER;

						// Is it some kind of argument list?
						const char *nested_expr = expr;
						extract_arg_string(&nested_expr, &nested_context);

						if (extract_arg_string(&nested_expr, &nested_context) != NULL)
						{
							// if it is, plug it in to the emit string
							parse_emit_string(expr, type, echo_target);
						}
						else
						{
							if (IsErrorInSPASMErrorSession(session, SPASM_ERR_EXCEEDED_RECURSION_LIMIT) == false)
							{
								
								int inner_session = StartSPASMErrorSession();
								parse_emit_string(expr, type, echo_target);
								if (IsSPASMErrorSessionFatal(inner_session))
								{
									EndSPASMErrorSession(inner_session);
									AddSPASMErrorSessionAnnotation(session, _T("Error during evaluation of macro '%s'"), define->name);

									ReplaySPASMErrorSession(session);
								}
								else
								{
									EndSPASMErrorSession(inner_session);
								}
								//ReplaySPASMErrorSession(session);
							}
							else
							{
								ReplaySPASMErrorSession(session);
							}
						}
						free (expr);
					}
					remove_arg_set (args);
				}
				else
				{
echo_error:
					
					switch (type)
					{
					case ES_ECHO:
						{
							if (echo_target != NULL)
							{
								fprintf((FILE *) echo_target, "(error)");
							}
							break;
						}
					case ES_FCREATE:
						{
							SetLastSPASMError(SPASM_ERR_LABEL_NOT_FOUND, word);
							eb_append((expand_buf_t *) echo_target, "(error)", -1);
							break;
						}
					}

					ReplaySPASMErrorSession(session);
				}
			}
			EndSPASMErrorSession(session);
		}
	}

	if (type == ES_ECHO && level == 1) {
		if (echo_target == stdout) putchar ('\n');
		else {
			if (echo_target != NULL)
			{
				fclose ((FILE *) echo_target);
			}
		}
	}
	
	level--;
	return (char *) ptr;
}
예제 #3
0
static void expand_expr_full (const char *expr, expand_buf *new_expr, int depth, bool search_local) {
	const char *block_start;
	char *name;
	static char separators[] = "=+-*<>|&/%^()\\, \t\r";
	define_t *define;
	label_t *label;
	int name_len;

	if (depth > RECURSION_LIMIT) {
		SetLastSPASMError (SPASM_ERR_RECURSION_DEPTH, RECURSION_LIMIT);
		return;
	}

	while (*expr) {
		//handle strings
		if (*expr == '\"') {
			block_start = expr++;
			while (*expr && *expr != '\"') {
				if (!(*expr == '\\' && *(++expr) == '\0'))
					expr++;
			}
			if (*expr)
				expr++;

			eb_append (new_expr, block_start, expr - block_start);
		}

		//get the next name and look it up
		name = skip_to_name_end (expr);
		name_len = name - expr;
		//skip if there's no name, or if it's a macro with arguments
		if (name_len > 0) {
			name = strndup (expr, name_len);
			
			//if it's a define, recursively expand its contents
			if ((define = search_defines (name, search_local)) && define->contents != NULL) {
				list_t *args = NULL;

				if (define->num_args > 0) {
					expr = parse_args (expr + name_len, define, &args);
					if (!expr) {
						free (name);
						return;
					}
				} else {
					expr += name_len;
				}
				expand_expr_full (define->contents, new_expr, depth + 1, search_local);
				remove_arg_set (args);
				if (error_occurred) return;
			//if it's a label, write its value
			} else if ((label = search_labels (name))) {
				char buf[10];
				snprintf (buf, sizeof(buf), "%d", label->value);
				eb_append (new_expr, buf, -1);
				expr += name_len;
			//otherwise, it might be a forward ref, so just write the name
			} else {
				eb_append (new_expr, name, name_len);
				expr += name_len;
			}
			
			free (name);
		} else if (*expr) {
			//if it can't be a name, just write the next char and move on
			eb_append (new_expr, expr, 1);
			expr++;
		}

		//skip past separators
		block_start = expr;
		while (*expr && strchr (separators, *expr))
			expr++;

		//write those
		eb_append (new_expr, block_start, expr - block_start);
	}
}