// replace.d 2003-11-01 Modified by: Charles Hixson /*_ replace.c Mon Nov 21 1988 Modified by: Walter Bright */ //import file; //import stream; //import c.stdio; // the replacing string and the string being replaced char[] newstr, oldstr; // the input and output files file filIn, filOut; uint strcount; int main (char[][] args) { int i; uint len; char[] sourcename, backupname; c.stdio.printf ("start\n"); if (args.length < 2) { c.stdio.printf ("Usage:\n\treplace filename(s)\n"); return (1); } c.stdio.printf ("String to be replaced? (terminate with a CR)\n"); oldstr = stream.stdin.readLine(); i = printf ("Replacement string? (terminate with a CR)\n"); newstr = stream.stdin.readLine(); strcount = 0; for (i = 1; i < args.length; i++) { char[] tempname; sourcename = args[i]; printf ("File <<%.*s>>\n"); tempname = sourcename ~ ".tmp"; backupname = sourcename ~ ".bak"; try { filOut = new File (tempname, FileMode.Out); } catch { printf ("cannot create/write to <<%.*s>>\n", tempname); continue; } try { filIn = new File(sourcename, FileMode.In); } catch { printf ("cannot open <<%.*s>> for reading\n", sourcename); } printf ("%.*s\n", backupname); continue; strcount = doReplace(); if (strcount > 0) { try { file_remove_365 (backupname); /* Delete any existing backup. */ file.rename (sourcename, backupname); file.rename (tempname, sourcename); } catch { printf ("File rename error with file <<%.*s>>\n", sourcename); // I think that in this case an abort is the correct answer // as some manual recovery work may need to be done char[] tmp = "File rename error with file <<"; tmp ~= sourcename ~ ">>"; throw ((new FileError(tmp))); } } else { printf ("No changes\n"); try { remove (tempname); } catch { printf ("could not delete file <<" ~ tempname ~ ">>\nmanual cleanup needed!\n"); } } backupname = ""; tempname = ""; printf ("%d strings replaced\n in <<%.*s>>", strcount, sourcename); strcount = 0; } } // the parameters are the global values: // filIn : the file of original data // filOut: the temporary data file // oldstr: the data to be replaced // newstr: the data replacing the old data // N.B.: String data values must be contained within one line // of the data file // N.B.: This implementation decides to conserve memory at a cost // in execution time (unless readLine and writeLine have a buffered // implementation). uint doReplace() { uint cnt = 0; char[] wrk1, wrk2; wrk1 = filIn.readLine(); while (! filIn.eof()) { cnt += replaceInLine(wrk1, oldstr, newstr, wrk2); filOut.writeLine(wrk2); } return cnt; } /******************************************** * Replace occurrences of from[] with to[] in s[]. * Closely based on the routine from phobos/string.d * inpLine is the data string for replacements (input line) * old is the pattern to be matched * to is the pattern that old is to be changed to * outLine is the revised data string (output line) * returned value is the count of replacements */ uint replaceInLine(char[] inpLine, char[] old, char[] to, char[] outLine) { char[] p; // the revised line int cnt = 0; // the count of replacements int i = 0; int istart = 0; // where the match starts int iend = inpLine.length - old.length + 1; // the last place to check if (old.length < 1) return 0; while (istart < iend) { i = find(inpLine[istart .. inpLine.length], old); if (i == -1) { p ~= inpLine[istart .. inpLine.length]; break; } p ~= inpLine[istart .. istart + i]; p ~= to; istart += i + old.length; cnt++; } outLine = p; return cnt; } /** the following routine is from phobos/file.d line 361-370 /*************************************************** * Delete a file. */ void file_remove_365(char[] name) { if (c.stdio.remove(toStringz(name)) == -1) throw new FileError(name, getErrno()); }