static array<tree> upgrade_brackets (array<tree> a, int level) { array<int> tp= symbol_types (a); //cout << "Upgrade " << a << ", " << tp << "\n"; if (admits_brackets (tp)) { //cout << " Downgrade dubious\n"; array<tree> r= simplify_matching (a, downgrade_dubious (tp), level); if (r != a) return upgrade_brackets (r, level); //cout << " Detect french\n"; r= simplify_matching (a, detect_french_interval (a, tp), level); if (r != a) return upgrade_brackets (r, level); //cout << " Detect absolute 1\n"; r= simplify_matching (a, detect_absolute (a, tp, false), level); if (r != a) return upgrade_brackets (r, level); //cout << " Detect absolute 2\n"; r= simplify_matching (a, detect_absolute (a, tp, true), level); if (r != a) return upgrade_brackets (r, level); //cout << " Detect probable\n"; r= simplify_matching (a, detect_probable (a, tp), level); if (r != a) return upgrade_brackets (r, level); //cout << " Detect dummy substitution\n"; if (replace_dummies (a) != a) { array<tree> a2= replace_dummies (a); array<int> tp2= symbol_types (a2); r= simplify_matching (a2, detect_probable (a2, tp2), level); if (r != a2) return upgrade_brackets (r, level); } //cout << " Confirm all\n"; r= simplify_matching (a, confirm_all (tp), level); if (r != a) return upgrade_brackets (r, level); //cout << " Missing left\n"; if (get_preference ("automatic brackets") != "off") r= add_missing_left (a, tp); if (r != a) return upgrade_brackets (r, level); //cout << " Missing right\n"; if (get_preference ("automatic brackets") != "off") r= add_missing_right (a, tp); if (r != a) return upgrade_brackets (r, level); } if (admits_bigops (tp)) { array<tree> r= prefix_split (a, tp, level); if (r != a) return upgrade_brackets (r, level); r= infix_split (a, tp, symbol_priorities (a), level); if (r != a) return upgrade_brackets (r, level); r= postfix_split (a, tp, level); if (r != a) return upgrade_brackets (r, level); ASSERT (tp[0] == SYMBOL_OPEN_BIG, "invalid situation"); r= upgrade_brackets (range (a, 1, N(a)), level + 1); tree body= concat_recompose (r); r= array<tree> (); r << make_around (a[0], body); return r; } return a; }
int rx_mode(message pkt, int b) { // MODE <nick> ({\+|-}{i|w|o|O|r}*)* // or MODE <channel> {[\+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>] [<ban mask>] int fd=bufs[b].handle; // If appropriate, trigger auto-join servlist *serv=bufs[b].autoent; if(autojoin && serv && serv->chans && !serv->join) { chanlist *curr=serv->chans; while(curr) { char joinmsg[8+strlen(curr->name)]; sprintf(joinmsg, "JOIN %s %s", curr->name, curr->key?curr->key:""); irc_tx(fd, joinmsg); char jmsg[16+strlen(curr->name)]; sprintf(jmsg, "auto: Joining %s", curr->name); add_to_buffer(b, JOIN, QUIET, 0, true, jmsg, ""); curr=curr->next; } serv->join=true; } if(pkt.nargs<2) { e_buf_print(b, ERR, pkt, "Not enough arguments: "); return(0); } char *from, *user, *host; prefix_split(pkt.prefix, &from, &user, &host); for(int b2=0;b2<nbufs;b2++) { if((bufs[b2].type==CHANNEL)&&(bufs[b2].server==b)&&(irc_strcasecmp(pkt.args[0], bufs[b2].bname, bufs[b].casemapping)==0)) { bool plus=false; switch(*pkt.args[1]) { case '+': plus=true; case '-':; /* fallthrough */ unsigned int i; for(i=0;i<bufs[b].npfx;i++) { if(bufs[b].prefixes[i].letter==pkt.args[1][1]) { // user expected if(pkt.nargs<3) { e_buf_print(b, ERR, pkt, "Not enough arguments: "); return(0); } name *curr=bufs[b2].nlist; while(curr) { if(irc_strcasecmp(curr->data, pkt.args[2], bufs[b].casemapping)==0) { bool found=false; for(unsigned int j=0;j<curr->npfx;j++) { if(curr->prefixes[j].letter==pkt.args[1][1]) { if(plus) found=true; else { curr->npfx--; for(unsigned int k=j;k<curr->npfx;k++) curr->prefixes[k]=curr->prefixes[k+1]; if(curr==bufs[b2].us) { char ms[curr->npfx?curr->npfx+1:2]; if(curr->npfx) { for(unsigned int i=0;i<curr->npfx;i++) ms[i]=curr->prefixes[i].letter; ms[curr->npfx]=0; } else { ms[0]='-'; ms[1]=0; } char mm[24+strlen(curr->data)+strlen(ms)+strlen(from)]; sprintf(mm, "You (%s) are now mode %s (%s)", curr->data, ms, from); add_to_buffer(b2, MODE, NORMAL, 0, false, mm, ""); } else { char ms[curr->npfx?curr->npfx+1:2]; if(curr->npfx) { for(unsigned int i=0;i<curr->npfx;i++) ms[i]=curr->prefixes[i].letter; ms[curr->npfx]=0; } else { ms[0]='-'; ms[1]=0; } char mm[16+strlen(ms)+strlen(from)]; sprintf(mm, " is now mode %s (%s)", ms, from); add_to_buffer(b2, MODE, NORMAL, 0, false, mm, curr->data); } } } } if(plus&&!found) { unsigned int n=curr->npfx++; prefix *pfx=realloc(curr->prefixes, curr->npfx*sizeof(prefix)); if(pfx) (curr->prefixes=pfx)[n]=bufs[b].prefixes[i]; else curr->npfx=n; // XXX silent fail if(curr==bufs[b2].us) { char ms[curr->npfx?curr->npfx+1:2]; if(curr->npfx) { for(unsigned int i=0;i<curr->npfx;i++) ms[i]=curr->prefixes[i].letter; ms[curr->npfx]=0; } else { ms[0]='-'; ms[1]=0; } char mm[24+strlen(curr->data)+strlen(ms)+strlen(from)]; sprintf(mm, "You (%s) are now mode %s (%s)", curr->data, ms, from); add_to_buffer(b2, MODE, NORMAL, 0, false, mm, ""); } else { char ms[curr->npfx?curr->npfx+1:2]; if(curr->npfx) { for(unsigned int i=0;i<curr->npfx;i++) ms[i]=curr->prefixes[i].letter; ms[curr->npfx]=0; } else { ms[0]='-'; ms[1]=0; } char mm[16+strlen(ms)+strlen(from)]; sprintf(mm, " is now mode %s (%s)", ms, from); add_to_buffer(b2, MODE, NORMAL, 0, false, mm, curr->data); } } break; } curr=curr->next; } if(!curr) e_buf_print(b, ERR, pkt, "No such nick: "); break; } } if(i==bufs[b].npfx) { // it's a channel mode bool found=false; for(i=0;i<bufs[b2].npfx;i++) { if(bufs[b2].prefixes[i].letter==pkt.args[1][1]) { if(plus) found=true; else { bufs[b2].npfx--; for(unsigned int j=i;j<bufs[b2].npfx;j++) bufs[b2].prefixes[j]=bufs[b2].prefixes[j+1]; char ms[bufs[b2].npfx?bufs[b2].npfx+1:2]; if(bufs[b2].npfx) { for(unsigned int i=0;i<bufs[b2].npfx;i++) ms[i]=bufs[b2].prefixes[i].letter; ms[bufs[b2].npfx]=0; } else { ms[0]='-'; ms[1]=0; } char mm[16+strlen(ms)+strlen(from)]; sprintf(mm, " is now mode %s (%s)", ms, from); add_to_buffer(b2, MODE, QUIET, 0, false, mm, bufs[b2].bname); } } } if(plus&&!found) { unsigned int n=bufs[b2].npfx++; prefix *pfx=realloc(bufs[b2].prefixes, bufs[b2].npfx*sizeof(prefix)); if(pfx) (bufs[b2].prefixes=pfx)[n]=(prefix){.letter=pkt.args[1][1], .pfx=0}; // channel modes don't have associated prefixes else bufs[b2].npfx=n; // XXX silent fail char ms[bufs[b2].npfx?bufs[b2].npfx+1:2]; if(bufs[b2].npfx) { for(unsigned int i=0;i<bufs[b2].npfx;i++) ms[i]=bufs[b2].prefixes[i].letter; ms[bufs[b2].npfx]=0; } else { ms[0]='-'; ms[1]=0; } char mm[16+strlen(ms)+strlen(from)]; sprintf(mm, " is now mode %s (%s)", ms, from); add_to_buffer(b2, MODE, QUIET, 0, false, mm, bufs[b2].bname); } } break; default: e_buf_print(b, ERR, pkt, "Malformed modespec - missing +/-: "); break; }