3 # this is a line editor using only /bin/sh, /bin/dd and /bin/rm
5 # /bin/rm is not really required, but it is nice to clean up temporary files
11 # temporary files we might need
14 trap "$rm -f $tmp $tmp.1 $tmp.2 $tmp.3 $tmp.4 $tmp.5 $tmp.6 $ed.a $ed.b $ed.c; exit" 0 1 2 3
16 # from now on, no more rm - the above trap is enough
19 # we do interesting things with IFS, but better save it...
22 # in case "echo" is not a shell builtin...
27 $dd of=$tmp 2>/dev/null <<EOF
31 set `$dd if=$tmp bs=1 of=/dev/null skip=1 2>&1`
33 $dd if=$tmp bs=1 count=$1 2>/dev/null
35 *) $dd 2>/dev/null <<EOF
42 # this is used to generate garbage files
66 # arithmetic using dd!
68 # add variable n1 n2 n3...
69 # assigns n1+n2+n3+... to variable
74 $dd if=/dev/null of=$tmp bs=1 2>/dev/null
79 *) zero | $dd of=$tmp.1 bs=1 "count=$n" 2>/dev/null
80 ( $dd if=$tmp; $dd if=$tmp.1 ) 2>/dev/null | $dd of=$tmp.2 2>/dev/null
81 $dd if=$tmp.2 of=$tmp 2>/dev/null
86 set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
91 # subtract variable n1 n2
92 # subtracts n2 from n1, assigns result to variable
96 zero | $dd of=$tmp bs=1 "count=$2" 2>/dev/null
98 set `$dd if=$tmp bs=1 of=/dev/null "skip=$3" 2>&1`
106 # multiply variable n1 n2
111 zero | $dd "bs=$2" of=$tmp "count=$3" 2>/dev/null
113 set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
118 # divide variable n1 n2
119 # variable = int( n1 / n2 )
123 zero | $dd bs=1 of=$tmp "count=$2" 2>/dev/null
125 set `$dd if=$tmp "bs=$3" of=/dev/null 2>&1`
130 # compare variable n1 n2 sets variable to lt if n1<n2, gt if n1>n2, eq if n1==n2
136 subtract somename "$n1" "$n2"
139 *) eval $res=gt; return;
141 subtract somename "$n2" "$n1"
144 *) eval $res=lt; return;
149 # lt n1 n2 returns true if n1 < n2
154 subtract somename "$n2" "$n1"
161 # le n1 n2 returns true if n1 <= n2
166 subtract somename "$n1" "$n2"
173 # gt n1 n2 returns true if n1 > n2
178 subtract somename "$n1" "$n2"
185 # ge n1 n2 returns true if n1 >= n2
190 subtract somename "$n2" "$n1"
197 # useful functions for the line editor
199 # open a file - copy it to the buffers
203 set `$dd "if=$file" of=/dev/null 2>&1`
207 # copy the first line to $ed.c
212 case "`$dd "if=$file" bs=1 skip=$len count=1 2>/dev/null`" in
218 # now $len is the length of the first line (including newline)
219 $dd "if=$file" bs=1 count=$len of=$ed.c 2>/dev/null
220 $dd "if=$file" bs=1 skip=$len of=$ed.b 2>/dev/null
221 $dd if=/dev/null of=$ed.a 2>/dev/null
225 # save a file - copy the buffers to the file
228 # make a backup copy of the original
229 $dd "if=$1" "of=$1.bak" 2>/dev/null
231 ( $dd if=$ed.a; $dd if=$ed.c; $dd if=$ed.b ) > "$1" 2>/dev/null
234 # replace n1 n2 bla replaces n2 chars of current line, starting n1-th
237 $dd if=$ed.c of=$tmp.1 bs=1 "count=$1" 2>/dev/null
238 ( $dd if=$ed.c "skip=$1" bs=1 | $dd of=$tmp.2 bs=1 "skip=$2" ) 2>/dev/null
241 ( $dd if=$tmp.1; Echo -n "$@"; $dd if=$tmp.2 ) > $tmp.3 2>/dev/null
242 $dd if=$tmp.3 of=$ed.c 2>/dev/null
246 # replace the n-th occurence of s with bla
251 # first we have to find it - this is fun!
252 # we have $tmp.4 => text before string, $tmp.5 => text after
253 $dd if=/dev/null of=$tmp.4 2>/dev/null
254 $dd if=$ed.c of=$tmp.5 2>/dev/null
257 $dd of=$tmp.6 2>/dev/null <<EOF
262 case "`$dd if=$tmp.5 2>/dev/null`" in
266 # now we want to replace the string
267 Echo -n "$@" > $tmp.2
268 Echo -n "$string" > $tmp.1
270 set `$dd bs=1 if=$tmp.1 of=/dev/null 2>&1`
274 ( $dd if=$tmp.4; $dd if=$tmp.2; $dd if=$tmp.5 bs=1 skip=$slen ) \
276 $dd if=$tmp of=$ed.c 2>/dev/null
280 ( $dd if=$tmp.4; $dd if=$tmp.5 bs=1 count=1 ) > $tmp 2>/dev/null
281 $dd if=$tmp of=$tmp.4 2>/dev/null
282 # and remove it from $tmp.5
283 $dd if=$tmp.5 of=$tmp bs=1 skip=1 2>/dev/null
284 $dd if=$tmp of=$tmp.5 2>/dev/null
287 ?*) # add one more byte...
288 ( $dd if=$tmp.4; $dd if=$tmp.5 bs=1 count=1 ) > $tmp 2>/dev/null
289 $dd if=$tmp of=$tmp.4 2>/dev/null
290 # and remove it from $tmp.5
291 $dd if=$tmp.5 of=$tmp bs=1 skip=1 2>/dev/null
292 $dd if=$tmp of=$tmp.5 2>/dev/null
304 ( $dd if=$ed.a; $dd if=$ed.c ) 2>/dev/null > $tmp.3
305 $dd if=$ed.b of=$tmp.4 2>/dev/null
307 $dd if=$tmp.3 of=$ed.a 2>/dev/null
311 # delete current line
314 $dd if=$ed.a 2>/dev/null > $tmp.1
315 $dd if=$ed.b of=$tmp.2 2>/dev/null
317 $dd if=$tmp.1 of=$ed.a 2>/dev/null
321 # insert before current line (without changing current)
323 ( $dd if=$ed.a; Echo "$@" ) 2>/dev/null > $tmp.1
324 $dd if=$tmp.1 of=$ed.a 2>/dev/null
332 *) subtract lineno $lineno 1
333 # read last line of $ed.a
335 set `$dd if=$ed.a of=/dev/null bs=1 2>&1`
342 subtract size $size 1
346 *) subtract size1 $size 1
347 case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
358 *) case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
359 ?*) go=true; subtract size $size 1 ;;
360 *) go=false; add size $size 1 ;;
365 # now $size is the size of the first n-1 lines
367 ( $dd if=$ed.c; $dd if=$ed.b ) 2>/dev/null > $tmp.5
368 $dd if=$tmp.5 of=$ed.b 2>/dev/null
371 0) $dd if=$ed.a of=$ed.c 2>/dev/null
372 $dd if=/dev/null of=$tmp.5 2>/dev/null
374 *) $dd if=$ed.a of=$ed.c bs=1 skip=$size 2>/dev/null
375 $dd if=$ed.a of=$tmp.5 bs=1 count=$size 2>/dev/null
379 $dd if=$tmp.5 of=$ed.a 2>/dev/null
384 # goes to a given line
387 compare bla "$rl" $lineno
391 gt) while gt "$rl" $lineno
396 lt) while lt "$rl" $lineno
406 $dd if=$ed.c 2>/dev/null
417 case "$cmd:$state" in
418 open:open) Echo "There is a file open already" ;;
419 open:*) if open "$arg"
420 then state=open; name="$arg"; $autoprint
421 else Echo "Cannot open $arg"
424 new:open) Echo "There is a file open already" ;;
430 close:changed) Echo "Use 'discard' or 'save'" ;;
431 close:closed) Echo "Closed already" ;;
432 close:*) state=closed ;;
433 save:closed) Echo "There isn't a file to save" ;;
434 save:*) case "$arg" in
440 discard:changed) Echo "Your problem!"; state=closed ;;
441 discard:*) state=closed ;;
442 print:closed) Echo "No current file" ;;
444 goto:closed) Echo "No current file" ;;
445 goto:*) goto "$arg"; $autoprint ;;
446 next:closed) Echo "No current file" ;;
447 next:*) next; $autoprint ;;
448 prev:closed) Echo "No current file" ;;
449 prev:*) prev; $autoprint ;;
450 name:closed) Echo "No current file" ;;
451 name:*) name="$arg" ;;
452 replace:closed) Echo "No current file" ;;
453 replace:*) if rstring 1 $arg
454 then state=changed; $autoprint
455 else Echo "Not found"
458 nreplace:closed) Echo "No current file" ;;
459 nreplace:*) if rstring $arg
460 then state=changed; $autoprint
461 else Echo "Not found"
464 delete:closed) Echo "No current file" ;;
465 delete:*) delete; state=changed; $autoprint ;;
466 insert:closed) Echo "No current file" ;;
467 insert:*) insert "$arg"; prev; state=changed; $autoprint ;;
468 quit:changed) Echo "Use 'save' or 'discard'" ;;
469 quit:*) Echo "bye"; exit;;
470 autoprint:*) autoprint="lineout" ;;
471 noprint:*) autoprint="" ;;
473 *) Echo "Command not understood" ;;