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; }
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; }
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"); } }