157705Sbostic /*- 257705Sbostic * Copyright (c) 1992 The Regents of the University of California. 357705Sbostic * All rights reserved. 457705Sbostic * 557705Sbostic * This code is derived from software contributed to Berkeley by 657705Sbostic * Rodney Ruddock of the University of Guelph. 757705Sbostic * 857705Sbostic * %sccs.include.redist.c% 957705Sbostic */ 1057705Sbostic 1157705Sbostic #ifndef lint 12*59475Sbostic static char sccsid[] = "@(#)sub.c 5.5 (Berkeley) 04/28/93"; 1357705Sbostic #endif /* not lint */ 1457705Sbostic 1557710Sbostic #include <sys/types.h> 1657710Sbostic 1757710Sbostic #include <regex.h> 1857710Sbostic #include <setjmp.h> 1957710Sbostic #include <stdio.h> 2057710Sbostic #include <stdlib.h> 2157710Sbostic #include <string.h> 2257710Sbostic 2358315Sbostic #ifdef DBI 2458315Sbostic #include <db.h> 2558315Sbostic #endif 2658315Sbostic 2757705Sbostic #include "ed.h" 2857710Sbostic #include "extern.h" 2957705Sbostic 3057705Sbostic /* 3157705Sbostic * The substitute command. It's big because of the backward compatability. 3257705Sbostic */ 3357705Sbostic void 3457705Sbostic s(inputt, errnum) 3557710Sbostic FILE *inputt; 3657710Sbostic int *errnum; 3757705Sbostic { 3857710Sbostic static int l_count2 = 1, l_global = 0, l_print = 0; 3957710Sbostic static int l_first_pass_flag = 0; 4057710Sbostic static char *l_match = NULL, *l_repl = NULL; 4157710Sbostic LINE *l_s_ret, *l_temp_line, *l_temp_line2, *l_kval, *l_last; 4257710Sbostic int l_s_flag, l_count, l_matched, l_nflag, l_cnt, yy, l_sr_flag = 0; 43*59475Sbostic int l_err, l_sl, l_rep_flag, l_u_reuse_flag=0; 4457710Sbostic char *l_match2 = NULL, *l_local = NULL, *l_local_temp = NULL; 4557705Sbostic #ifndef REG_STARTEND 4657710Sbostic size_t l_offset = 0; 4757705Sbostic #endif 4857705Sbostic 4958564Sralph if (Start_default && End_default) 5058564Sralph Start = End = current; 5157710Sbostic else 5258564Sralph if (Start_default) 5358564Sralph Start = End; 5458564Sralph if (Start == NULL) { 5557710Sbostic *errnum = -1; 5657710Sbostic return; 5757710Sbostic } 5858564Sralph Start_default = End_default = 0; 5957705Sbostic 6057710Sbostic l_sl = ss = getc(inputt); 6157710Sbostic if (l_first_pass_flag == 0) 6257710Sbostic l_match = l_repl = NULL; 6357710Sbostic l_match2 = get_pattern(l_sl, inputt, errnum, 0); 6458315Sbostic 6557710Sbostic if (*errnum < 0) { 6657710Sbostic if ((*errnum == -2) && (l_sl != '\n')) 6757710Sbostic return; 6857710Sbostic if ((l_match2 == NULL) || 6957710Sbostic (strlen(l_match2) > 4) || (l_first_pass_flag == 0)) 7057710Sbostic return; 7157710Sbostic *errnum = 0; 7257710Sbostic l_sr_flag = -1; 7357710Sbostic for (yy = 0; yy < (strlen(l_match2)); yy++) { 7457710Sbostic switch (l_match2[yy]) { 7557710Sbostic case '\n': 7657710Sbostic ss = getc(inputt); 7757710Sbostic goto bcg1; 7857710Sbostic break; 7957710Sbostic case 'r': 8057710Sbostic l_sr_flag = 1; 8157710Sbostic break; 8257710Sbostic case 'p': 8357710Sbostic l_print = (l_print) ? 0 : 1; 8457710Sbostic break; 8557710Sbostic case 'g': 8657710Sbostic l_global = (l_global) ? 0 : 1; 8757710Sbostic break; 8857710Sbostic case 'N': 8957710Sbostic l_count2 = 1; 9057710Sbostic break; 9157710Sbostic default: 9257710Sbostic *errnum = -1; 9357710Sbostic strcpy(help_msg, "illegal modifier to s"); 9457710Sbostic return; 9557710Sbostic } 9657710Sbostic } 9757710Sbostic ss = getc(inputt); 9857710Sbostic if (l_sr_flag == 1) 9957710Sbostic goto bcg2; 10057710Sbostic else 10157710Sbostic goto bcg1; 10257710Sbostic } 10357710Sbostic if (l_first_pass_flag) { 10457710Sbostic free(l_match); 10557710Sbostic free(l_repl); 10657710Sbostic } else 10757710Sbostic l_first_pass_flag = 1; 10857710Sbostic l_match = l_match2; 10957710Sbostic *errnum = 0; 11057710Sbostic l_repl = get_pattern(ss, inputt, errnum, 1); 11158315Sbostic if (sigint_flag && (!sigspecial)) 11257710Sbostic SIGINT_ACTION; 11357710Sbostic l_global = l_print = 0; 11457710Sbostic if (*errnum < 0) 11557710Sbostic if ((*errnum == -1) && (ss == '\n')) 11657710Sbostic /* Note, \n still in stream for next getc. */ 11757710Sbostic l_print = 1; 11857710Sbostic else 11957710Sbostic return; 12057710Sbostic *errnum = 0; 12157705Sbostic 12257710Sbostic l_count2 = 1; 12357705Sbostic 12457710Sbostic while (((ss = getc(inputt)) != '\n') && (ss != EOF)) 12557710Sbostic if (ss == 'g') 12657710Sbostic l_global = 1; 12757710Sbostic else 12857710Sbostic switch (ss) { 12957710Sbostic case 'p': 13057710Sbostic l_print = (l_print | (int) 1); 13157710Sbostic break; 13257710Sbostic case 'n': 13357710Sbostic l_print = (l_print | (int) 2); 13457710Sbostic break; 13557710Sbostic case 'l': 13657710Sbostic l_print = (l_print | (int) 4); 13757710Sbostic break; 13857710Sbostic default: 13957710Sbostic if ((ss > ('0' - 1)) && (ss < ('9' + 1))) 14057710Sbostic l_count2 = dig_num_conv(inputt, errnum); 14157710Sbostic else { 14257710Sbostic *errnum = -1; 14357710Sbostic strcpy(help_msg, 14457710Sbostic "illegal command option"); 14557710Sbostic return; 14657710Sbostic } 14757710Sbostic } 14857705Sbostic 14957705Sbostic bcg1: 15057710Sbostic if ((RE_flag == 0) && (l_match[1] == '\0')) { 15157710Sbostic *errnum = -1; 15257710Sbostic ungetc(ss, inputt); 15357710Sbostic return; 15457710Sbostic } else 15557710Sbostic if ((l_sr_flag == 0) && (l_match[1] || (RE_patt == NULL))) { 15658315Sbostic int l_m_len = 2 + strlen(l_match); 15758315Sbostic sigspecial++; 15857710Sbostic free(RE_patt); 15958315Sbostic RE_patt = malloc(sizeof(char) * (l_m_len)); 16058315Sbostic bcopy(l_match, RE_patt, l_m_len); 16158315Sbostic sigspecial--; 16258315Sbostic if (sigint_flag && (!sigspecial)) 16358315Sbostic SIGINT_ACTION; 16457710Sbostic } 16557710Sbostic RE_sol = (l_match[1] == '^') ? 1 : 0; 16657710Sbostic if ((l_match[1]) && 16757710Sbostic (regfree(&RE_comp), l_err = regcomp(&RE_comp, &l_match[1], 0))) { 16857710Sbostic regerror(l_err, &RE_comp, help_msg, 128); 16957710Sbostic *errnum = -1; 17057710Sbostic RE_flag = 0; 17157710Sbostic ungetc(ss, inputt); 17257710Sbostic return; 17357710Sbostic } 17457710Sbostic RE_flag = 1; 17558315Sbostic if (sigint_flag && (!sigspecial)) 17657710Sbostic SIGINT_ACTION; 17757705Sbostic bcg2: 17858564Sralph current = Start; 17957710Sbostic l_s_flag = 0; 18057710Sbostic do { 18157710Sbostic RE_match[0].rm_eo = 0; 18257710Sbostic get_line(current->handle, current->len); 18358315Sbostic if (sigint_flag && (!sigspecial)) 18458315Sbostic SIGINT_ACTION; 18557710Sbostic l_count = l_count2; 18657710Sbostic l_local = text; 187*59475Sbostic l_rep_flag = 1; 18857705Sbostic #ifndef REG_STARTEND 18957710Sbostic l_offset = 0; 19057705Sbostic #endif 19157710Sbostic do { 19257710Sbostic RE_match[0].rm_so = RE_match[0].rm_eo; 19357705Sbostic #ifdef REG_STARTEND 19457710Sbostic l_matched = regexec_n(&RE_comp, l_local, 19557710Sbostic (size_t)RE_SEC, RE_match, 0, l_count, 19657710Sbostic (size_t)current->len, 0); 19757705Sbostic #else 19857710Sbostic l_matched = regexec_n(&RE_comp, l_local, 19957710Sbostic (size_t)RE_SEC, RE_match, 0, l_count, 20057710Sbostic &l_offset, 0); 20157705Sbostic #endif 20257710Sbostic if (l_matched == 0) { 20357710Sbostic if ((l_s_flag == 0) && (g_flag == 0)) 20457710Sbostic u_clr_stk(); 20557710Sbostic l_count = l_s_flag = 1; 206*59475Sbostic l_rep_flag = 0; 20757710Sbostic /* 20857710Sbostic * The l_local passed into re_replace is not 20957710Sbostic * freed in re_replace because it is "text", 21057710Sbostic * the global line holder, for the first pass 21157710Sbostic * through this loop. The value returned by 21257710Sbostic * re_replace is a new string (with the first 21357710Sbostic * replacement in it). If the 'g' flag was 21457710Sbostic * set with substitute then this new string 21557710Sbostic * is passed in for the second pass and can 21657710Sbostic * be freed once re_replace is done with it. 21757710Sbostic * (...and so on for the rest of the 'g' 21857710Sbostic * passes. RE_match[0].rm_eo is changed in 21957710Sbostic * re_replace to be the new location of the 22057710Sbostic * next character immediately after the 22157710Sbostic * replacement since it is likely the 22257710Sbostic * position of that character has changed 22357710Sbostic * because of the replacement. 22457710Sbostic */ 22557705Sbostic #ifdef REG_STARTEND 22657710Sbostic l_local = re_replace(l_local, 22757710Sbostic (size_t)(RE_SEC - 1), RE_match, &l_repl[1]); 228*59475Sbostic (current->len) = strlen(l_local); 22957705Sbostic #else 23057710Sbostic l_local = re_replace(l_local, 23157710Sbostic (size_t)(RE_SEC - 1), RE_match, &l_repl[1], 23257710Sbostic l_offset); 23357705Sbostic #endif 23457710Sbostic } 23557710Sbostic if (l_global == 0) 23657710Sbostic break; 23757710Sbostic if (l_local[RE_match[0].rm_eo] == '\0') 23857710Sbostic break; 23957710Sbostic } while (!l_matched); 24057705Sbostic 241*59475Sbostic if (l_rep_flag) 242*59475Sbostic goto next; 24357710Sbostic l_cnt = l_nflag = 0; 24457710Sbostic l_kval = current; 24557710Sbostic l_temp_line = current->above; 24657710Sbostic l_temp_line2 = current->below; 24757710Sbostic l_local_temp = l_local; 24858315Sbostic sigspecial++; 24957710Sbostic for (;;) { 25057710Sbostic /* 25157710Sbostic * Make the new string the one for this line. Check if 25257710Sbostic * it needs to be split. 25357710Sbostic */ 25457710Sbostic if (l_local[l_cnt] == '\n' || l_local[l_cnt] == '\0') { 25557710Sbostic if (l_local[l_cnt] == '\0') 25657710Sbostic l_nflag = 1; 25757710Sbostic l_local[l_cnt] = '\0'; 25857710Sbostic l_s_ret = malloc(sizeof(LINE)); 25957710Sbostic if (l_s_ret == NULL) { 26057710Sbostic *errnum = -1; 26157710Sbostic strcpy(help_msg, "out of memory error"); 26257710Sbostic return; 26357710Sbostic } 26457710Sbostic (l_s_ret->len) = strlen(l_local); 26557710Sbostic (l_s_ret->handle) = add_line(l_local, l_s_ret->len); 26657710Sbostic (l_s_ret->above) = l_temp_line; 26757710Sbostic (l_s_ret->below) = NULL; 26857710Sbostic if (l_temp_line == NULL) 26957710Sbostic top = l_s_ret; 27057710Sbostic else { 271*59475Sbostic if ((current != Start) && 272*59475Sbostic ((&(current->above)) == u_stk->cell)) 273*59475Sbostic l_u_reuse_flag = 1; 274*59475Sbostic else { 275*59475Sbostic u_add_stk(&(l_temp_line->below)); 276*59475Sbostic l_u_reuse_flag = 0; 277*59475Sbostic } 27857710Sbostic (l_temp_line->below) = l_s_ret; 27957710Sbostic } 28057710Sbostic l_temp_line = l_s_ret; 28157710Sbostic if ((l_local[l_cnt] == '\0') && (l_nflag == 1)) 28257710Sbostic break; 28357710Sbostic else { 28457710Sbostic l_local = &(l_local[l_cnt + 1]); 28557710Sbostic l_cnt = 0; 28657710Sbostic } 28757710Sbostic } else 28857710Sbostic l_cnt++; 28957710Sbostic } 29057710Sbostic (l_s_ret->below) = l_temp_line2; 29157710Sbostic ku_chk(current, current, l_kval->below); 29257710Sbostic if (current == End) 29357710Sbostic End = l_s_ret; 29457710Sbostic current = l_s_ret; 29557710Sbostic l_last = current; 29657710Sbostic if (l_temp_line2 == NULL) 29757710Sbostic bottom = l_s_ret; 29857710Sbostic else { 299*59475Sbostic if (l_u_reuse_flag) 300*59475Sbostic u_pop_n_swap(&(l_temp_line2->above)); 301*59475Sbostic else 302*59475Sbostic u_add_stk(&(l_temp_line2->above)); 30357710Sbostic (l_temp_line2->above) = current; 30457710Sbostic } 30558315Sbostic sigspecial--; 30658315Sbostic if (sigint_flag && (!sigspecial)) 30758315Sbostic SIGINT_ACTION; 30857710Sbostic if (l_local_temp != text) 30957710Sbostic free(l_local_temp); 310*59475Sbostic next: 31157710Sbostic current = current->below; 31257710Sbostic } while (current != (End->below)); 31357705Sbostic 31457710Sbostic if (l_s_flag == 0) { 31558564Sralph current = Start; 31657710Sbostic strcpy(help_msg, "no matches found for substitution"); 31757710Sbostic *errnum = -1; 31857710Sbostic ungetc('\n', inputt); 31957710Sbostic return; 32057710Sbostic } 32157710Sbostic change_flag = 1; 32257710Sbostic current = l_last; 32357705Sbostic 32457710Sbostic if (l_print > 0) { 325*59475Sbostic Start = End = l_s_ret; /*current;*/ 32657710Sbostic ungetc(ss, inputt); 32757710Sbostic if (l_print == (l_print | (int) 1)) 32857710Sbostic p(inputt, errnum, 0); 32957710Sbostic if (l_print == (l_print | (int) 2)) 33057710Sbostic p(inputt, errnum, 1); 33157710Sbostic if (l_print == (l_print | (int) 4)) 33257710Sbostic l(inputt, errnum); 33357710Sbostic if (*errnum < 0) 33457710Sbostic return; 33557710Sbostic } 33657710Sbostic if (l_sr_flag == -1) { 33757710Sbostic regfree(&RE_comp); 33857710Sbostic regcomp(&RE_comp, &RE_patt[1], 0); 33957710Sbostic } 34057710Sbostic *errnum = 1; 34157710Sbostic } 342