/* * if.c: handles the IF command for IRCII * * Written By Michael Sandrof * * Copyright (c) 1990 Michael Sandrof. * Copyright (c) 1991, 1992 Troy Rollo. * Copyright (c) 1992-2003 Matthew R. Green. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: if.c,v 1.8 2003/01/08 20:00:54 f Exp $ */ #include "irc.h" #include "alias.h" #include "ircaux.h" #include "window.h" #include "vars.h" #include "output.h" #include "if.h" static int charcount _((char *, int)); /* * next_expr finds the next expression delimited by brackets. The type * of bracket expected is passed as a parameter. Returns NULL on error. */ char * next_expr(args, itype) char **args; int itype; { char *ptr, *ptr2, *ptr3; char type = (char)itype; if (!*args) return NULL; ptr2 = *args; if (!*ptr2) return 0; if (*ptr2 != type) { say("Expression syntax"); return 0; } /* { */ ptr = MatchingBracket(ptr2 + 1, type, (type == '(') ? ')' : '}'); if (!ptr) { say("Unmatched '%c'", type); return 0; } *ptr = '\0'; do { ptr2++; } while (isspace(*ptr2)); ptr3 = ptr+1; while (isspace(*ptr3)) ptr3++; *args = ptr3; if (*ptr2) { ptr--; while (isspace(*ptr)) *ptr-- = '\0'; } return ptr2; } /*ARGSUSED*/ void ifcmd(command, args, subargs) char *command, *args; char *subargs; { char *exp; char *sub; int flag = 0; int result; if (!(exp = next_expr(&args, '('))) { yell("Missing CONDITION in IF"); return; } sub = parse_inline(exp, subargs?subargs:empty_string, &flag); if (get_int_var(DEBUG_VAR) & DEBUG_EXPANSIONS) yell("If expression expands to: (%s)", sub); if (!*sub || *sub == '0') result = 0; else result = 1; new_free(&sub); if (!(exp = next_expr(&args, '{'))) { yell("Missing THEN portion in IF"); return; } if (!result && !(exp = next_expr(&args, '{'))) return; parse_line((char *) 0, exp, subargs ? subargs : empty_string, 0, 0, 0); return; } /*ARGSUSED*/ void whilecmd(command, args, subargs) char *command, *args; char *subargs; { char *exp = (char *) 0, *ptr, *body = (char *) 0, *newexp = (char *) 0; int args_used; /* this isn't used here, but is passed * to expand_alias() */ if ((ptr = next_expr(&args, '(')) == (char *) 0) { yell("WHILE: missing boolean expression"); return; } malloc_strcpy(&exp, ptr); if ((ptr = next_expr(&args, '{')) == (char *) 0) { say("WHILE: missing expression"); new_free(&exp); return; } malloc_strcpy(&body, ptr); while (1) { malloc_strcpy(&newexp, exp); ptr = parse_inline(newexp, subargs ? subargs : empty_string, &args_used); if (*ptr && *ptr !='0') { new_free(&ptr); parse_line((char *) 0, body, subargs ? subargs : empty_string, 0, 0, 0); } else break; } new_free(&newexp); new_free(&ptr); new_free(&exp); new_free(&body); } static int charcount(string, what) char *string; int what; { int x = 0; char *place = string - 1; while ((place = index(place + 1, what))) x++; return x; } /* * How it works -- if There are no parenthesis, it must be a * foreach array command. If there are parenthesis, and there are * exactly two commas, it must be a C-like for command, else it must * must be an foreach word command */ void foreach_handler(command,args,subargs) char *command, *args, *subargs; { char *temp = (char *) 0; char *placeholder; char *temp2 = (char *) 0; malloc_strcpy(&temp, args); placeholder = temp; if (*temp == '(') { if ((temp2 = next_expr(&temp,'(')) == (char *) 0) { new_free(&placeholder); return; } if (charcount(temp2, ',') == 2) forcmd(command,args,subargs); else fe(command,args,subargs); } else foreach(command,args,subargs); new_free(&placeholder); } /*ARGSUSED*/ void foreach(command, args, subargs) char *command, *args; char *subargs; { char *struc = (char *) 0, *ptr, *body = (char *) 0, *var = (char *) 0; char **sublist; int total; int i; int slen; int old_display; if ((ptr = new_next_arg(args, &args)) == (char *) 0) { yell("FOREACH: missing structure expression"); return; } malloc_strcpy(&struc, ptr); malloc_strcat(&struc, "."); upper(struc); if ((var = next_arg(args, &args)) == (char *) 0) { new_free(&struc); yell("FOREACH: missing variable"); return; } while (isspace(*args)) args++; if ((body = next_expr(&args, '{')) == (char *) 0) /* } */ { new_free(&struc); yell("FOREACH: missing statement"); return; } sublist = match_alias(struc, &total, VAR_ALIAS); slen = strlen(struc); old_display = window_display; for (i = 0; i < total; i++) { window_display = 0; add_alias(VAR_ALIAS, var, sublist[i]+slen); window_display = old_display; parse_line((char *) 0, body, subargs ? subargs : empty_string, 0, 0, 0); new_free(&sublist[i]); } new_free(&sublist); new_free(&struc); } /* * FE: Written by Jeremy Nelson (jnelson@iastate.edu) * * FE: replaces recursion * * The thing about it is that you can nest variables, as this command calls * expand_alias until the list doesnt change. So you can nest lists in * lists, and hopefully that will work. However, it also makes it * impossible to have $s anywhere in the list. Maybe ill change that * some day. */ void fe(command, args, subargs) char *command, *args, *subargs; { char *list = (char *) 0, *templist = (char *) 0, *placeholder, *oldlist = (char *) 0, *sa, *vars, *var[255], *word = (char *) 0, *todo = (char *) 0; int ind, x, y, blah, args_flag; int old_display; for (x = 0; x < 254; var[x++] = (char *) 0) ; list = next_expr(&args, '('); /* ) */ if (!list) { yell ("FE: Missing List for /FE"); return; } sa = subargs ? subargs : " "; malloc_strcpy(&templist, list); do { malloc_strcpy(&oldlist, templist); new_free(&templist); templist = expand_alias((char *) 0,oldlist,sa,&args_flag, (char **) 0); } while (strcmp(templist, oldlist)); new_free(&oldlist); if (*templist == '\0') { new_free(&templist); return; } vars = args; if (!(args = index(args, '{'))) /* } */ { yell ("FE: Missing commands"); new_free(&templist); return; } *(args-1) = '\0'; ind = 0; while ((var[ind++] = next_arg(vars, &vars))) { if (ind == 255) { yell ("FE: Too many variables"); new_free(&templist); return; } } ind = ind ? ind - 1: 0; if (!(todo = next_expr(&args, '{'))) /* } { */ { yell ("FE: Missing }"); new_free(&templist); return; } blah = word_count(templist); old_display = window_display; placeholder = templist; for ( x = 0 ; x < blah ; ) { window_display = 0; for ( y = 0 ; y < ind ; y++ ) { word = ((x+y)