changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: acme: Apply each -/+ only once (#156)

changeset 7482: d6de6e9ab3d1
parent 7481: 94daa09298cb
child 7485: 50813cd186d3
author: Ori Bernstein <>
date: Wed, 04 Dec 2019 12:55:03 -0800
files: sys/src/cmd/acme/addr.c
description: acme: Apply each -/+ only once (#156)

When plumbing an address like `3-`, Acme selects line 1,
and similarly `3+` selects line 5.
The same problem can be observed for character addresses (`#123+`)
but _not_ for ones like `+`, `.+` or `/foo/+`:
The problem only occurs when a number is followed by a direction (`-`/`+`).

Following along with the example `3-` through `address` (in addr.c):
We read `3` into `c` and match the `case` on line 239.
The `while` loop on line 242ff reads additional digits into `c`
and puts the first non-digit back by decrementing the index `q`.
Then we find the range for line 3 on line 251 and continue.

On the next iteration, we set `prevc` to the last `c`,
but since that part read ahead _into `c`_,
`c` is currently the _next_ character we will read, `-`,
and now `prevc` is too.

Then in the case block (line 210) the condition on line 211 holds
and Acme believes that it has read two `-` in sequence
and modifies the range to account for the “first” `-`.
The “second” `-` gets applied after the loop is done, on line 292.

So the general problem is:
While reading numbers, Acme reads the next character after the number into `c`.
It decrements the counter to ensure it will read it again on the next iteration,
but it still uses it to update `prevc`.

This change solves the problem by reading digits into `nc` instead.
This variable is used to similar effect in the block for directions (line 212)
and fills the role of “local `c` that we can safely use to read ahead” nicely.

(imported from plan9front a82a8b6368274d77d42f526e379b74e79c137e26)
     1.1--- a/sys/src/cmd/acme/addr.c
     1.2+++ b/sys/src/cmd/acme/addr.c
     1.3@@ -215,12 +215,12 @@ address(Mntdir *md, Text *t, Range lim, 
     1.4 		case '5': case '6': case '7': case '8': case '9':
     1.5 			n = c -'0';
     1.6 			while(q<q1){
     1.7-				c = (*getc)(a, q++);
     1.8-				if(c<'0' || '9'<c){
     1.9+				nc = (*getc)(a, q++);
    1.10+				if(nc<'0' || '9'<nc){
    1.11 					q--;
    1.12 					break;
    1.13 				}
    1.14-				n = n*10+(c-'0');
    1.15+				n = n*10+(nc-'0');
    1.16 			}
    1.17 			if(*evalp)
    1.18 				r = number(md, t, r, n, dir, size, evalp);