@@ -1263,6 +1263,7 @@ static bool ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end,
12631263 assert (a != NULL );
12641264 assert (pp != NULL );
12651265 assert (edcontext != NULL );
1266+ bool allow_non_convergent = PromiseGetConstraintAsBoolean (ctx , "allow_non_convergent" , pp );
12661267
12671268 char line_buff [CF_EXPANDSIZE ];
12681269 char after [CF_BUFSIZE ];
@@ -1330,17 +1331,25 @@ static bool ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end,
13301331 break ;
13311332 }
13321333 }
1333-
1334+ char line_buff_cp [ CF_EXPANDSIZE ];
13341335 if (NotAnchored (pp -> promiser ) && BlockTextMatch (ctx , pp -> promiser , line_buff , & start_off , & end_off ))
13351336 {
1336- RecordInterruption (ctx , pp , a ,
1337- "Promised replacement '%s' on line '%s' for pattern '%s'"
1338- " is not convergent while editing '%s'"
1339- " (regular expression matches the replacement string)" ,
1340- line_buff , ip -> name , pp -> promiser , edcontext -> filename );
1341- * result = PromiseResultUpdate (* result , PROMISE_RESULT_INTERRUPTED );
1342- PromiseRef (LOG_LEVEL_ERR , pp );
1343- break ;
1337+ strlcpy (line_buff_cp , line_buff , sizeof (line_buff_cp ));
1338+ strlcpy (after , line_buff_cp + end_off , sizeof (after ));
1339+ snprintf (line_buff_cp + start_off , sizeof (line_buff_cp ) - start_off ,
1340+ "%s%s" , BufferData (replace ), after );
1341+
1342+ if (!allow_non_convergent || (strlen (line_buff ) != strlen (line_buff_cp )))
1343+ {
1344+ RecordInterruption (ctx , pp , a ,
1345+ "Promised replacement '%s' on line '%s' for pattern '%s'"
1346+ " is not convergent while editing '%s'"
1347+ " (regular expression matches the replacement string)" ,
1348+ line_buff , ip -> name , pp -> promiser , edcontext -> filename );
1349+ * result = PromiseResultUpdate (* result , PROMISE_RESULT_INTERRUPTED );
1350+ PromiseRef (LOG_LEVEL_ERR , pp );
1351+ break ;
1352+ }
13441353 }
13451354
13461355 if (!MakingChanges (ctx , pp , a , result , "replace pattern '%s' in '%s'" , pp -> promiser ,
@@ -1366,8 +1375,14 @@ static bool ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end,
13661375 break ;
13671376 }
13681377
1369- if (BlockTextMatch (ctx , pp -> promiser , ip -> name , & start_off , & end_off ))
1378+ if (BlockTextMatch (ctx , pp -> promiser , ip -> name , & start_off , & end_off ) && (!allow_non_convergent
1379+ || (strlen (line_buff ) != strlen (line_buff_cp ))))
13701380 {
1381+ strlcpy (line_buff_cp , line_buff , sizeof (line_buff_cp ));
1382+ strlcpy (after , line_buff_cp + end_off , sizeof (after ));
1383+ snprintf (line_buff_cp + start_off , sizeof (line_buff_cp ) - start_off ,
1384+ "%s%s" , BufferData (replace ), after );
1385+
13711386 RecordInterruption (ctx , pp , a ,
13721387 "Promised replacement '%s' for pattern '%s' is not properly convergent while editing '%s'"
13731388 " (pattern still matches the end-state replacement string '%s', consider use"
0 commit comments