pike.git / lib / modules / Tools.pmod / sed.pmod

version» Context lines:

pike.git/lib/modules/Tools.pmod/sed.pmod:1: + // edit commands supported: + // <firstline>,<lastline><edit command> + // ^^ numeral (17) ^^ + // or relative (+17, -17) + // or a search regexp (/regexp/) + // or multiple (17/regexp//regexp/+2) + // + // D - delete first line in space + // G - insert hold space + // H - append current space to hold space + // P - print current data + // a<string> - insert + // c<string> - change current space + // d - delete current space + // h - copy current space to hold space + // i<string> - print string + // l - print current space + // p - print first line in data + // q - quit evaluating + // s/regexp/with/x - replace + // y/chars/chars/ - replace chars + // + // where line is numeral, first 'line'==0    -  + static array sedreplace(string s,object re,string with, +  array whatin,int first,int lastmod, +  multiset flags) + { +  array a; +  string w=0; +  array pr=({}); +  +  if (!(a=re->split(s))) +  return 0; +  +  if (first) +  { +  array wa; +  wa=sedreplace(a[0],re,with,whatin,first,lastmod,flags); +  if (wa) +  if (!flags["g"]) +  return ({wa[0],wa[1]+s[strlen(a[0])..]}); +  else +  pr=wa[0],w=wa[1]; +  else +  w=a[0]; +  } +  +  string t= +  replace(with,whatin[..sizeof(a)-first+lastmod-1], +  a[first..sizeof(a)+lastmod-1]); +  +  if (flags["p"]) pr+=({t}); +  +  s=(w||"")+t; +  if (flags["g"]) +  { +  if (lastmod) +  { +  array wa; +  wa=sedreplace(a[-1],re,with,whatin,first,lastmod,flags); +  if (wa) +  { +  pr+=wa[0]; +  s+=wa[1]; +  } +  else +  s+=a[-1]; +  } +  } +  else +  s+=a[-1]; +  +  return ({pr,s}); + }; +  + static array scan_for_linenumber(string cmd, +  array(string) in, +  int n) + { +  int x; +  string what; +  object re; +  +  while (cmd!="" && ((cmd[0]>='0' && cmd[0]<='9') +  || cmd[0]=='/' || cmd[0]=='+' || cmd[0]=='-')) +  { +  if (cmd[0]>='0' && cmd[0]<='9') +  { +  sscanf(cmd,"%d%s",n,cmd); +  // n--; if first line==1 +  } +  else if (cmd[0]=='+') +  { +  sscanf(cmd,"+%d%s",x,cmd); +  n+=x; +  } +  else if (cmd[0]=='-') +  { +  sscanf(cmd,"-%d%s",x,cmd); +  n-=x; +  } +  else if (sscanf(cmd,"/%s/%s",what,cmd)==2) +  { +  re=Regexp(what); +  while (n<sizeof(in)) +  { +  if (re->match(in[n])) break; +  n++; +  } +  } +  else break; +  } +  if (n<0) n=0; else if (n>=sizeof(in)) n=sizeof(in)-1; +  return ({n,cmd}); + } +  + string|array `()(string|array(string) commands, +  string|array(string) data, +  void|int suppress) + { +  int start,stop; +  string div,what,with,inflags; +  multiset flags; +  array whatin=({"\\1","\\2","\\3","\\4","\\5","\\6","\\7","\\8","\\9"}); +  array print=({}); +  array hold=({}); +  object re; +  array a1,a2; +  array in,e; +  +  if (arrayp(data)) in=copy_value(data); +  else in=data/"\n"; +  +  if (arrayp(commands)) e=commands; +  else e=commands/"\n"; +  +  start=0; +  stop=sizeof(in)-1; +  +  foreach (e, string cmd) +  { +  if (cmd!="" && ((cmd[0]>='0' && cmd[0]<='9') +  || cmd[0]=='/' || cmd[0]=='+' || cmd[0]=='-')) +  { +  a1=scan_for_linenumber(cmd,in,start); +  stop=start=a1[0]; +  cmd=a1[1]; +  } +  +  if (cmd[0..1]==",$") { cmd=cmd[2..]; stop=sizeof(in)-1; } +  else if (sscanf(cmd,",%s",cmd)) +  { +  a1=scan_for_linenumber(cmd,in,start); +  stop=a1[0]; +  cmd=a1[1]; +  } +  +  if (stop>sizeof(in)-1) stop=sizeof(in)-1; +  if (start<0) start=0; +  +  if (cmd=="") continue; +  switch (cmd[0]) +  { +  case 's': +  div=cmd[1..1]; +  if (div=="%") div="%%"; +  inflags=""; +  if (sscanf(cmd,"%*c"+div+"%s"+div+"%s"+div+"%s", +  what,with,inflags)<3) continue; +  flags=aggregate_multiset(@(inflags/"")); +  +  int first=0,lastmod=0; +  if (what!="") // fix the regexp for working split +  { +  if (what[0]!='^') what="^(.*)"+what,first=1; +  if (what[-1]!='$') what=what+"(.*)$",lastmod=-1; +  } +  re=Regexp(what); +  +  while (start<=stop) +  { +  array sa=sedreplace(in[start],re,with,whatin, +  first,lastmod,flags); +  +  if (sa) +  { +  in[start]=sa[1]; +  print+=sa[0]; +  if (!flags["g"]) break; +  } +  start++; +  } +  +  break; +  +  case 'y': +  div=cmd[1..1]; +  if (div=="%") div="%%"; +  inflags=""; +  if (sscanf(cmd,"%*c"+div+"%s"+div+"%s"+div+"%s", +  what,with,inflags)<3) continue; +  if (strlen(what)!=strlen(with)) +  { +  what=what[0..strlen(with)-1]; +  with=with[0..strlen(what)-1]; +  } +  +  a1=what/"",a2=with/""; +  +  while (start<=stop) +  { +  in[start]=replace(in[start],a1,a2); +  start++; +  } +  break; +  +  case 'G': // insert hold space +  in=in[..start-1]+hold+in[start..]; +  if (stop>=start) stop+=sizeof(hold); +  break; +  +  case 'a': // insert line +  in=in[..start-1]+({cmd[1..]})+in[start..]; +  if (stop>=start) stop++; +  break; +  +  case 'c': // change +  in=in[..start-1]+({cmd[1..]})+in[stop+1..]; +  stop=start; +  break; +  +  case 'd': // delete +  in=in[..start-1]+in[stop+1..]; +  stop=start; +  break; +  +  case 'D': // delete first line +  in=in[..start-1]+in[start+1..]; +  stop=start; +  break; +  +  case 'h': // copy +  hold=in[start..stop]; +  break; +  +  case 'H': // appending copy +  hold+=in[start..stop]; +  break; +  +  case 'i': // print text +  print+=({cmd[1..]}); +  break; +  +  case 'l': // print space +  print+=in[start..stop]; +  break; +  +  case 'P': // print all +  print+=in; +  break; +  +  case 'p': // print first +  print+=in[..0]; +  break; +  +  case 'q': // quit +  if (!suppress) +  return (arrayp(data)?(print+in):((print+in)*"\n")); +  return (arrayp(data)?(print):(print*"\n")); +  +  default: +  // error? just ignore for now +  } +  } +  if (!suppress) +  return (arrayp(data)?(print+in):(print+in)*"\n"); +  return (arrayp(data)?(print):(print*"\n")); + } +  +  +    Newline at end of file added.