Пример #1
0
void startmacro(const char * line_)
{
	thisone=NULL;
	if (!confirmqpar(line_)) error<errblock>(0, "Broken macro declaration");
	string line=line_;
	clean(line);
	char * startpar=strqchr(line.str, '(');
	if (!startpar) error<errblock>(0, "Broken macro declaration");
	*startpar=0;
	startpar++;
	if (!confirmname(line)) error<errblock>(0, "Bad macro name");
	thisname=line;
	char * endpar=strqrchr(startpar, ')');
	//confirmqpar requires that all parentheses are matched, and a starting one exists, therefore it is harmless to not check for nulls
	if (endpar[1]) error<errblock>(0, "Broken macro declaration");
	*endpar=0;
	for (int i=0;startpar[i];i++)
	{
		char c=startpar[i];
		if (!isalnum(c) && c!='_' && c!=',') error<errline>(0, "Broken macro declaration");
		if (c==',' && isdigit(startpar[i+1])) error<errline>(0, "Broken macro declaration");
	}
	if (*startpar==',' || isdigit(*startpar) || strstr(startpar, ",,") || endpar[-1]==',') error<errline>(0, "Broken macro declaration");
	macrodata * ignored;
	if (macros.find(thisname, ignored)) error<errblock>(0, "Duplicate macro");
	thisone=(macrodata*)malloc(sizeof(macrodata));
	new(thisone) macrodata;
	if (*startpar)
	{
		thisone->arguments=(const char**)qpsplit(strdup(startpar), ",", &thisone->numargs);
	}
	else
	{
		const char ** noargs=(const char**)malloc(sizeof(const char**));
		*noargs=NULL;
		thisone->arguments=noargs;
		thisone->numargs=0;
	}
	for (int i=0;thisone->arguments[i];i++)
	{
		if (!confirmname(thisone->arguments[i])) error<errblock>(0, "Bad macro argument name");
		for (int j=i+1;thisone->arguments[j];j++)
		{
			if (!strcmp(thisone->arguments[i], thisone->arguments[j])) error<errblock>(0, S"Duplicate macro argument '"+thisone->arguments[i]+"'");
		}
	}
	thisone->fname=strdup(thisfilename);
	thisone->startline=thisline;
	numlines=0;
}
Пример #2
0
void expand_alias_parameters(args_t **args, args_t *alias_args)
{
	int i;
	args_t *new_args;
	args_t *redir_args = 0;
	args_t *deleted;

/*	if(alias_args->argc == 0)
		return;*/

	rearrange_args(*args, ";");

	/* do not include redirections in %-parameters */
	i = rearrange_redirections(alias_args);
	if(i != -1) {
		redir_args = args_create();
		args_add_args2(redir_args, alias_args, i);
		args_del(alias_args, i, alias_args->argc - i);
	}

	deleted = args_create();
	args_add_args(deleted, alias_args);

	new_args = args_create();
	args_add_args(new_args, *args);

	for(i=0; i<new_args->argc; i++)
	{
		char *e;

		/* %* can not be used embedded in an argument */
		if(strcmp(new_args->argv[i], "%*") == 0) {
			args_del(new_args, i, 1);
			args_insert_args(new_args, i, deleted, 0, deleted->argc);
			args_clear(alias_args);
			continue;
		}

		e = strqchr(new_args->argv[i], '%');
		if(e) {
			char *ep;
			char *ins;
			char *tmp;
			int n;

			*e = 0;
			n = strtoul(++e, &ep, 0) - 1;

			if(ep != e && n < alias_args->argc && n >= 0) {
				ins = deleted->argv[n];
				free(alias_args->argv[n]);
				alias_args->argv[n] = 0;
			} else
				ins = 0;

			/* insert the parameter in this argument */
			asprintf(&tmp, "%s%s%s", new_args->argv[i], ins ? ins : "", ep);
			free(new_args->argv[i]);
			new_args->argv[i] = tmp;
		}

	}

	args_destroy(deleted);
	args_remove_empty(alias_args);
	args_add_args(new_args, alias_args);

	if(redir_args) {
		args_add_args(new_args, redir_args);
		args_destroy(redir_args);
	}

	args_remove_empty(new_args);

	args_destroy(*args);
	*args = new_args;
}
Пример #3
0
void callmacro(const char * data)
{
	int numcm=reallycalledmacros++;
	macrodata * thisone;
	if (!confirmqpar(data)) merror("Broken macro usage");
	string line=data;
	clean(line);
	char * startpar=strqchr(line.str, '(');
	if (!startpar) merror("Broken macro usage");
	*startpar=0;
	startpar++;
	if (!confirmname(line)) merror("Bad macro name");
	if (!macros.find(line, thisone)) merror("Unknown macro");
	char * endpar=strqrchr(startpar, ')');
	if (endpar[1]) merror("Broken macro usage");
	*endpar=0;
	autoptr<const char **> args;
	int numargs=0;
	char *tmp_asd=strdup(startpar);
	if (*startpar) args=(const char**)qpsplit(tmp_asd, ",", &numargs);
	//free(tmp_asd);
	if (numargs!=thisone->numargs) merror("Wrong number of arguments to macro");
	macrorecursion++;
	int startif=numif;
	for (int i=0;i<thisone->numlines;i++)
	{
		try
		{
			thisfilename=thisone->fname;
			thisline=thisone->startline+i+1;
			thisblock=NULL;
			string out;
			string intmp=thisone->lines[i];
			for (char * in=intmp.str;*in;)
			{
				if (*in=='<' && in[1]=='<')
				{
					out+="<<";
					in+=2;
				}
				else if (*in=='<' && isalnum(in[1]))
				{
					char * end=in+1;
					while (*end && *end!='<' && *end!='>') end++;
					if (*end!='>')
					{
						out+=*(in++);
						continue;
					}
					*end=0;
					in++;
					if (!confirmname(in)) error<errline>(0, "Broken macro contents");
					bool found=false;
					for (int i=0;thisone->arguments[i];i++)
					{
						if (!strcmp(in, thisone->arguments[i]))
						{
							found=true;
							if (args[i][0]=='"')
							{
								string s=args[i];
								out+=dequote(s.str);
							}
							else out+=args[i];
							break;
						}
					}
					if (!found) error<errline>(0, "Unknown macro argument");
					in=end+1;
				}
				else out+=*(in++);
			}
			calledmacros=numcm;
			assembleline(thisone->fname, thisone->startline+i, out);
		}
		catch(errline&){}
	}
	macrorecursion--;
	if (repeatnext!=1)
	{
		thisblock=NULL;
		repeatnext=1;
		merror("rep or if at the end of a macro");
	}
	if (numif!=startif)
	{
		thisblock=NULL;
		numif=startif;
		numtrue=startif;
		merror("Unclosed if statement");
	}
}