| Home > Technical articles | e-mail: laurie@tratt.net github: ltratt twitter: @laurencetratt |
|
October 3 2005
printf and common sense. Frankly I have never found debuggers of any practical use (apart from when using those languages so crude that one needs a debugger to view a stack trace).
There is however one other technique in my debugging armoury, and it involves the humble grep -iRl Func | xargs neditThis does a case insensitive ( -i), recursive (-R) search and then prints out just the filename of matching files (-l). Cunning uses of grep's regular expressions can result in a very powerful debugging aid which unfortunately seems to be severely underutilized by most people.
Despite my fondness for Recently I have had much cause to make use of my simple utility on an evolving code base. Continually backing up data, and refining a regular expression until it matches only its intended target is highly repetitive and tedious, and in my experience anything that is repetitive and tedious leads, sooner or later, to boredom induced errors. So I sat down and quickly cooked up a new variant of my utility which I have flippantly named
srep on a code base of C files. The following command executes srep on all .c and .h files in the current directory, and outputs a unified diff (-u) into the changes file.
find . | grep "\\.[ch]$" | xargs srep -u Con_Func_Obj \ Con_Func_Seg > changesA fragment of the changes file is as follows (the full unified diff can be found here)
--- ./VM.c Sun Oct 2 14:31:38 2005
+++ ./VM.c Sun Oct 2 14:31:38 2005
@@ -183,12 +183,12 @@
Con_Obj * Con_VM_apply(Con_EC_Obj *ec, Con_Obj *func)
{
jmp_buf env;
- Con_Func_Obj *func_seg;
+ Con_Func_Seg *func_seg;
Con_Obj *return_obj;
if ((func->seg_c_class != ec->vm->builtins[CON_BUILTIN_FUNC_CLASS]))
return NULL;
- func_seg = (Con_Func_Obj *) func;
+ func_seg = (Con_Func_Seg *) func;
if (func_seg->pc_type == PC_TYPE_C_FUNCTION) {
if (sigsetjmp(env, 0) == 0) {
Once I have verified that the changes that will be made are what I expect, I can then apply this diff in the normal fashion:
patch -p0 < changes srep has a useful variant on this, which is to output files in a unified diff but with the additional output from Tim Peter's ndiff utility. The -n flag tells srep to produce a hybrid unified / ndiff patch such as the following fragment (the full hybrid diff can be found here):
--- ./VM.c Sun Oct 2 14:31:38 2005
+++ ./VM.c Sun Oct 2 14:31:38 2005
@@ -154,12 +154,12 @@
Con_Obj * Con_VM_apply(Con_EC_Obj *ec, Con_Obj *func)
{
jmp_buf env;
- Con_Func_Obj *func_seg;
? ^^^
+ Con_Func_Seg *func_seg;
? ^^^
Con_Obj *return_obj;
if ((func->seg_c_class != ec->vm->builtins[CON_BUILTIN_FUNC_CLASS])
return NULL;
- func_seg = (Con_Func_Obj *) func;
? ^^^
+ func_seg = (Con_Func_Seg *) func;
? ^^^
if (func_seg->pc_type == PC_TYPE_C_FUNCTION) {
if (sigsetjmp(env, 0) == 0) {
What srep takes from ndiff is the lines beginning with ? which show you which characters within a line are affected by the diff. This can be very useful when you are trying to visually track which intra-line changes will be made by applying a diff. Unfortunately the patch utility complains about such lines, so one can not directly feed such a diff into patch. One can however use srep to automatically modify the changes diff into valid patch input by removing all lines starting with ?:
srep "^\\?.*?\n" "" changesAs this example suggests, if srep is run without either the unified (-u) or ndiff (-n) output options, it modifies files in situ.
Updated (October 7 2005): Attributed the paraphrased "common-sense" quote to Kernighan. |
| Home > Technical Articles | e-mail: laurie@tratt.net github: ltratt twitter: @laurencetratt |
| Copyright © 1995-2012 Laurence Tratt | |