コード例 #1
0
ファイル: cstr.c プロジェクト: joncampbell123/doslib
int set_cstr(char **str,const char *src) {
    free_cstr(str);

    if (src != NULL)
        *str = strdup(src);

    return (*str != NULL);
}
コード例 #2
0
ファイル: shdropls.c プロジェクト: joncampbell123/doslib
void shell_droplist_entry_free(struct shell_droplist_t *ent) {
    free_cstr(&ent->file);
    ent->next = NULL;
}
コード例 #3
0
ファイル: preprocessor.c プロジェクト: rswinkle/C_Interpreter
void handle_macro(preprocessor_state* preproc, int macro)
{
	FILE* input = preproc->input;
	FILE* output = preproc->output;
	lexer_state* lexer = &preproc->lexer;

	rsw_cstr expansion;
	init_cstr_str(&expansion, preproc->values.a[macro], strlen(preproc->values.a[macro]));

	macro_params* p = GET_PARAM(&preproc->params, macro);
	
	//do initial argument expansion
	if (p->num_params >= 0)
		parse_params(preproc, macro, &expansion);

	cvector_i valid_macros;
	cvec_i(&valid_macros, preproc->macros.size, preproc->macros.size);
	for (int i=0; i < preproc->macros.size; ++i) {
		valid_macros.a[i] = i;
	}

	rescan_expansion(preproc, &expansion, &valid_macros, macro);

	lexer_state save_lex;
	long fpos;
	token_lex t;

	save_lex = *lexer;
	if ((fpos = ftell(input)) == -1) {
		perror("ftell error in handle_macro");
		exit(0);
	}
	t = read_token(input, lexer, NULL);
	*lexer = save_lex;
	if (fseek(input, fpos, SEEK_SET)) {
		perror("fseek failure in handle_macro");
		exit(0);
	}
	
	if (t.tok.type == LPAREN) { 
		char* search, *found;
		search = expansion.a;

		int len;
		for (int i=0; i < preproc->macros.size; ++i) {
			if (i == macro)
				continue;

			len = strlen(preproc->macros.a[i]);
			search = expansion.a;
			while (1) {
				found = strstr(search, preproc->macros.a[i]);
				if (!found)
					break;
				if (found[len]) {
					search = found + len;
					continue;
				}

				if (found != expansion.a) {
					if (isalpha(found[-1]) || found[-1] == '_') {
						search = found + len;
						continue;
					}
				}
				//don't need to check the end because we already did
				
				p = GET_PARAM(&preproc->params, i);
				if (p->num_params != -1) {
					*found = 0; //cut off matched macro
					fprintf(output, "%s", expansion.a);
					handle_macro(preproc, i);

					goto exit;
				}

				search = found + len;
			}
		}
	} else if (t.tok.type == ID || t.tok.type == STR_LITERAL) {
		free(t.tok.v.id);
	}

	fprintf(output, "%s", expansion.a);

exit:

	free_cstr(&expansion);
	cvec_free_i(&valid_macros);
}
コード例 #4
0
ファイル: preprocessor.c プロジェクト: rswinkle/C_Interpreter
unsigned int macro_expansion(preprocessor_state* preproc, rsw_cstr* expansion, unsigned long beginning, cvector_i* valid_macros, int macro_index)
{
	//vaild_macros should never be NULL unless I uncomment that alternative method in prescan_argument
	//int macro = (valid_macros) ? valid_macros->a[macro_index] : macro_index;
	int macro = valid_macros->a[macro_index];

	rsw_cstr local_expansion, scratch;
	init_cstr_str(&local_expansion, preproc->values.a[macro], strlen(preproc->values.a[macro]));
	init_cstr_str(&scratch, local_expansion.a, local_expansion.size);

	rsw_cstr arg_expansion;
	init_cstr_cap(&arg_expansion, 50);

	macro_params* p = GET_PARAM(&preproc->params, macro);
	int param_len, val_len, parens, loc;

	char* search, *found, *c;

	//beginning is start of macro name so jump forward len (the first c++ will jump over '(' )
	c = &expansion->a[beginning + strlen(preproc->macros.a[macro])];
	if (p->num_params != -1)
		while (isspace(*c)) ++c;

	parens = 0;
	for (int i=0; i < p->num_params; ++i) {
		val_len = 0;

		c++;
		while (isspace(*c)) ++c; //ignore spaces on edges ie after ( and ,

		if (*c == '(')
			parens++;
		do {
			val_len += snprintf(macro_buf+val_len, MAX_MACRO_LEN-val_len, "%c", *c);

			c++;
			if (*c == '(') {
				parens++;
			} else if (*c == ')') {
				parens--;
				if (parens == -1) {
					if (i != p->num_params-1)
						preprocessor_error(NULL, &preproc->lexer, "more arguments expected for macro\n");
					break;
				}
			}
		} while (*c != ',' || parens > 0);

		cstr_insert_str(&arg_expansion, 0, macro_buf, val_len);
		prescan_argument(preproc, &arg_expansion);

		param_len = strlen(p->names[i]);
		
		loc = cstr_find_str(&scratch, p->names[i]);
		while (loc != (size_t)-1) {
			cstr_replace_substr(&local_expansion, loc, param_len, arg_expansion.a, arg_expansion.size); //assuming size doesn't include \0
			cstr_replace_substr(&scratch, loc, param_len, arg_expansion.a, arg_expansion.size); //assuming size doesn't include \0

			for (int j=loc; j < loc+arg_expansion.size; ++j)
				scratch.a[j] = '*';

			loc = cstr_find_str_start_at(&scratch, p->names[i], loc+arg_expansion.size); //-1 here?
		}

		arg_expansion.size = 0;
	}
	
	if (!p->num_params) // increment for ) because it didn't get it in loop
		++c;

	//TODO test without this
	if (p->num_params == -1)
		--c;

	rescan_expansion(preproc, &local_expansion, valid_macros, macro_index);

	cstr_replace_substr(expansion, beginning, (c - expansion->a) - beginning + 1, local_expansion.a, local_expansion.size);

	unsigned int local_size = local_expansion.size;

	free_cstr(&local_expansion);
	free_cstr(&scratch);
	free_cstr(&arg_expansion);

	return beginning + local_size;
}
コード例 #5
0
ファイル: preprocessor.c プロジェクト: rswinkle/C_Interpreter
void parse_params(preprocessor_state* preproc, int macro, rsw_cstr* expansion)
{
	macro_params* p = GET_PARAM(&preproc->params, macro);
	token_lex t;

	rsw_cstr scratch;
	init_cstr_str(&scratch, expansion->a, expansion->size);

	//read (
	read_token(preproc->input, &preproc->lexer, NULL);

	int param_len, val_len, parens, loc;
	char* search, *found;

	rsw_cstr arg_expansion;
	init_cstr_cap(&arg_expansion, 50);

	parens = 0;
	for (int i=0; i < p->num_params; ++i) {
		val_len = 0;

		t = read_token(preproc->input, &preproc->lexer, NULL);
		if (t.tok.type == LPAREN)
			parens++;
		do {
			val_len += print_token_to_str(&t.tok, macro_buf+val_len, MAX_MACRO_LEN-val_len);

			if (t.tok.type == ID || t.tok.type == STR_LITERAL)
				free(t.tok.v.id);

			t = read_token(preproc->input, &preproc->lexer, NULL);
			if (t.tok.type == LPAREN) {
				parens++;
			} else if (t.tok.type == RPAREN) {
				parens--;
				if (parens == -1) {
					if (i != p->num_params-1)
						preprocessor_error(&t, &preproc->lexer, "more arguments expected for macro,");
					break;
				}
			}
		} while (t.tok.type != COMMA || parens > 0); //could put && parens != -1 and change above

		//perform prescan to handle nested calls
		//This contradicts C : A Reference Manual pg 50 but it's the only/easiest
		//way to get correct behavior (ie preventing infinite recursion but allowing nested calls to the same macro)
		//I know gcc does this (http://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_3.html#SEC32)
		cstr_insert_str(&arg_expansion, 0, macro_buf, val_len);
		prescan_argument(preproc, &arg_expansion);

		param_len = strlen(p->names[i]);
	//	val_len = strlen(macro_buf);

		loc = cstr_find_str(&scratch, p->names[i]);
		while (loc != (size_t)-1) {
			cstr_replace_substr(expansion, loc, param_len, arg_expansion.a, arg_expansion.size); //assuming size doesn't include \0
			cstr_replace_substr(&scratch, loc, param_len, arg_expansion.a, arg_expansion.size); //assuming size doesn't include \0

			//overwrite replacement in scratch with a character not allowed in identifiers
			//so that replacement of a subsequent parameter won't replace within an expansion
			//ie #define MYMACRO(a, b) a + b;
			//called as MYMACRO(b, a) would wrongly go to b + b -> a + a instead of b + a
			for (int j=loc; j < loc+arg_expansion.size; ++j)
				scratch.a[j] = '*';

			loc = cstr_find_str_start_at(&scratch, p->names[i], loc+arg_expansion.size); //-1 here
		}

		//reset for next argument
		arg_expansion.size = 0;
	}

	//read ) for 0 params, others get read in loop
	if (!p->num_params) {
		token_lex t = read_token(preproc->input, &preproc->lexer, NULL);
		if (t.tok.type != RPAREN)
			preprocessor_error(&t, &preproc->lexer, "expected ) in function style macro with 0 arguments,");
	}

	free_cstr(&arg_expansion);
	free_cstr(&scratch);
}