comparison toys/pending/sed.c @ 1545:b6ff5dc17763 draft

Implement a few sed commands. Not done, and not tested yet.
author Rob Landley <rob@landley.net>
date Sat, 08 Nov 2014 01:51:59 -0600
parents ad6b2f0e566b
children 2997847aa299
comparison
equal deleted inserted replaced
1544:e3aeb7435efe 1545:b6ff5dc17763
178 struct arg_list *e; 178 struct arg_list *e;
179 179
180 // processed pattern list 180 // processed pattern list
181 struct double_list *pattern; 181 struct double_list *pattern;
182 182
183 char *nextline; 183 char *nextline, *remember;
184 long nextlen, count; 184 void *restart;
185 long nextlen, rememberlen, count;
185 int fdout, noeol; 186 int fdout, noeol;
186 ) 187 )
187 188
188 struct step { 189 struct step {
189 struct step *next, *prev; 190 struct step *next, *prev;
234 */ 235 */
235 return regexec(preg, string, nmatch, pmatch, eflags); 236 return regexec(preg, string, nmatch, pmatch, eflags);
236 237
237 } 238 }
238 239
240 // Extend allocation to include new string.
241
242 static char *extend_string(char **old, char *new, int oldlen, int newlen)
243 {
244 int newline = newlen < 0;
245 char *s;
246
247 if (newline) newlen = -newlen;
248 s = *old = xrealloc(*old, oldlen+newlen+newline+1);
249 if (newline) s[oldlen++] = '\n';
250 memcpy(s+oldlen, new, newlen);
251 s[oldlen+newlen] = 0;
252
253 return s+oldlen+newlen;
254 }
255
239 // Apply pattern to line from input file 256 // Apply pattern to line from input file
240 static void walk_pattern(char **pline, long plen) 257 static void walk_pattern(char **pline, long plen)
241 { 258 {
242 char *line = TT.nextline; 259 char *line = TT.nextline, *append = 0;
243 long len = TT.nextlen; 260 long len = TT.nextlen;
244 struct step *logrus; 261 struct step *logrus;
245 int eol = 0; 262 int eol = 0, tea = 0;
246 263
247 // Grab next line for deferred processing (EOF detection, we get a NULL 264 // Grab next line for deferred processing (EOF detection: we get a NULL
248 // pline at EOF to flush last line). Note that only end of _last_ input 265 // pline at EOF to flush last line). Note that only end of _last_ input
249 // file matches $ (unless we're doing -i). 266 // file matches $ (unless we're doing -i).
250 if (pline) { 267 if (pline) {
251 TT.nextline = *pline; 268 TT.nextline = *pline;
252 TT.nextlen = plen; 269 TT.nextlen = plen;
255 272
256 if (!line || !len) return; 273 if (!line || !len) return;
257 if (line[len-1] == '\n') line[--len] = eol++; 274 if (line[len-1] == '\n') line[--len] = eol++;
258 TT.count++; 275 TT.count++;
259 276
260 for (logrus = (void *)TT.pattern; logrus; logrus = logrus->next) { 277 logrus = TT.restart ? TT.restart : (void *)TT.pattern;
261 char c = logrus->c; 278 TT.restart = 0;
279 while (logrus) {
280 char *str, c = logrus->c;
262 281
263 // Have we got a matching range for this rule? 282 // Have we got a matching range for this rule?
264 if (*logrus->lmatch || *logrus->rmatch) { 283 if (*logrus->lmatch || *logrus->rmatch) {
265 int miss = 0; 284 int miss = 0;
266 long lm; 285 long lm;
303 } 322 }
304 // Deferred disable from regex end match 323 // Deferred disable from regex end match
305 if (miss) logrus->hit = 0; 324 if (miss) logrus->hit = 0;
306 } 325 }
307 326
308 // Process like the wind, bullseye! 327 // Process command
309 328
310 // if (strchr("dDgGhHlnNpPqx=", c)) { 329 if (c == 'a') {
311 330 long alen = append ? strlen(append) : 0;
312 331
313 // if (strchr("abcirstTwy:", c) 332 str = logrus->arg1+(char *)logrus;
314 if (c == 'p') { 333 extend_string(&append, str, alen, -strlen(str));
334 } else if (c == 'b') {
335 str = logrus->arg1+(char *)logrus;
336
337 if (!*str) break;
338 for (logrus = (void *)TT.pattern; logrus; logrus = logrus->next)
339 if (logrus->c == ':' && !strcmp(logrus->arg1+(char *)logrus, str))
340 break;
341 if (!logrus) error_exit("no :%s", str);
342 } else if (c == 'd') goto done;
343 else if (c == 'D') {
344 // Delete up to \n or end of buffer
345 for (str = line; !*str || *str == '\n'; str++);
346 len -= str - line;
347 memmove(line, str, len);
348 line[len] = 0;
349
350 // restart script
351 logrus = (void *)TT.pattern;
352 continue;
353 } else if (c == 'g') {
354 free(line);
355 line = xstrdup(TT.remember);
356 len = TT.rememberlen;
357 } else if (c == 'G') {
358 line = xrealloc(line, len+TT.rememberlen+2);
359 line[len++] = '\n';
360 memcpy(line+len, TT.remember, TT.rememberlen);
361 line[len += TT.rememberlen] = 0;
362 } else if (c == 'h') {
363 free(TT.remember);
364 TT.remember = xstrdup(line);
365 TT.rememberlen = len;
366 } else if (c == 'H') {
367 TT.remember = xrealloc(TT.remember, TT.rememberlen+len+2);
368 TT.remember[TT.rememberlen++] = '\n';
369 memcpy(TT.remember+TT.rememberlen, line, len);
370 TT.remember[TT.rememberlen += len] = 0;
371 } else if (c == 'l') {
372 error_exit("todo: l");
373 } else if (c == 'n') {
374 TT.restart = logrus->next;
375
376 break;
377 } else if (c == 'N') {
378 if (pline) {
379 TT.restart = logrus->next;
380 extend_string(&line, TT.nextline, plen, -TT.nextlen);
381 free(TT.nextline);
382 TT.nextline = line;
383 }
384
385 goto append;
386 } else if (c == 'p') {
315 if (emit(line, len, eol)) break; 387 if (emit(line, len, eol)) break;
316 } else error_exit("what?"); 388 } else if (c == 'q') break;
389 else if (c == 'x') {
390 long swap = TT.rememberlen;
391
392 str = TT.remember;
393 TT.remember = line;
394 line = str;
395 TT.rememberlen = len;
396 len = swap;
397 } else if (c == '=') xprintf("%ld\n", TT.count);
398 // labcirstTwy
399 else if (c != ':') error_exit("todo: %c", c);
400
401 logrus = logrus->next;
317 } 402 }
318 403
319 if (!(toys.optflags & FLAG_n)) emit(line, len, eol); 404 if (!(toys.optflags & FLAG_n)) emit(line, len, eol);
320 405
406 done:
321 free(line); 407 free(line);
408
409 append:
410 if (append) {
411 emit(append, strlen(append), 1);
412 free(append);
413 }
322 } 414 }
323 415
324 // Genericish function, can probably get moved to lib.c 416 // Genericish function, can probably get moved to lib.c
325 417
326 // Iterate over lines in file, calling function. Function can write NULL to 418 // Iterate over lines in file, calling function. Function can write NULL to
420 *to = delim; 512 *to = delim;
421 } 513 }
422 *pstr = from + rc; 514 *pstr = from + rc;
423 515
424 return rc; 516 return rc;
425 }
426
427 // Extend allocation to include new string. We use offsets instead of
428 // pointers so realloc() moving stuff doesn't break things. Do it
429 // here instead of toybuf so there's no maximum size.
430
431 static char *extend_string(char **old, char *new, int oldlen, int newlen)
432 {
433 *old = xrealloc(*old, oldlen+newlen+1);
434 memcpy(*old+oldlen, new, newlen);
435 (*old)[oldlen+newlen] = 0;
436
437 return (*old)+oldlen+newlen;
438 } 517 }
439 518
440 // Translate primal pattern into walkable form. 519 // Translate primal pattern into walkable form.
441 static void jewel_of_judgement(char **pline, long len) 520 static void jewel_of_judgement(char **pline, long len)
442 { 521 {
634 do_lines(xopen(dworkin->arg, O_RDONLY), dworkin->arg, jewel_of_judgement); 713 do_lines(xopen(dworkin->arg, O_RDONLY), dworkin->arg, jewel_of_judgement);
635 dlist_terminate(TT.pattern); 714 dlist_terminate(TT.pattern);
636 if (TT.nextlen) error_exit("no }"); 715 if (TT.nextlen) error_exit("no }");
637 716
638 TT.fdout = 1; 717 TT.fdout = 1;
718 TT.remember = xstrdup("");
639 719
640 // Inflict pattern upon input files 720 // Inflict pattern upon input files
641 loopfiles_rw(args, O_RDONLY, 0, 0, do_sed); 721 loopfiles_rw(args, O_RDONLY, 0, 0, do_sed);
642 722
643 if (!(toys.optflags & FLAG_i)) walk_pattern(0, 0); 723 if (!(toys.optflags & FLAG_i)) walk_pattern(0, 0);