* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)v_increment.c 9.2 (Berkeley) 11/20/94";
static char * const fmt
[] = {
static void inc_err
__P((SCR
*, enum nresult
));
* v_increment -- [count]#[#+-]
* Increment/decrement a keyword number.
size_t beg
, blen
, end
, len
, nlen
, wlen
;
char *bp
, *ntype
, *p
, *t
, nbuf
[100];
/* Validate the operator. */
if (vp
->character
!= '+' && vp
->character
!= '-') {
msgq(sp
, M_ERR
, "177|Usage: %s", vp
->kp
->usage
);
/* If new value set, save it off, but it has to fit in a long. */
if (F_ISSET(vp
, VC_C1SET
)) {
if (vp
->count
> LONG_MAX
) {
if ((p
= file_gline(sp
, vp
->m_start
.lno
, &len
)) == NULL
) {
if (file_lline(sp
, &lno
))
GETLINE_ERR(sp
, vp
->m_start
.lno
);
* Skip any leading space before the number. Getting a cursor word
* implies moving the cursor to its beginning, if we moved, refresh
for (moved
= 0, beg
= vp
->m_start
.cno
;
beg
< len
&& isspace(p
[beg
]); moved
= 1, ++beg
);
#define ishex(c) (isdigit(c) || strchr("abcdefABCDEF", c))
#define isoctal(c) (isdigit(c) && (c) != '8' && (c) != '9')
* Look for 0[Xx], or leading + or - signs, guess at the base.
* The character after that must be a number.
p
[beg
] == '0' && (p
[beg
+ 1] == 'X' || p
[beg
+ 1] == 'x')) {
ntype
= p
[beg
+ 1] == 'X' ? fmt
[HEXC
] : fmt
[HEXL
];
} else if (len
> 1 && p
[beg
] == '0') {
} else if (len
>= 1 && (p
[beg
] == '+' || p
[beg
] == '-')) {
nonum
: msgq(sp
, M_ERR
, "213|Cursor not in a number");
/* Find the end of the word, possibly correcting the base. */
if (p
[end
] == '8' || p
[end
] == '9') {
* If the line was at the end of the buffer, we have to copy it
* so we can guarantee that it's NULL-terminated. We make the
* buffer big enough to fit the line changes as well, and only
GET_SPACE_RET(sp
, bp
, blen
, len
+ 50);
memmove(bp
, &p
[beg
], wlen
);
* Octal or hex deal in unsigned longs, everything else is done
if ((nret
= nget_slong(sp
, &lval
, t
, NULL
, 10)) != NUM_OK
)
ltmp
= vp
->character
== '-' ? -change
: change
;
if (lval
> 0 && ltmp
> 0 && !NPFITS(LONG_MAX
, lval
, ltmp
)) {
if (lval
< 0 && ltmp
< 0 && !NNFITS(LONG_MIN
, lval
, ltmp
)) {
nlen
= snprintf(nbuf
, sizeof(nbuf
), ntype
, lval
);
if ((nret
= nget_uslong(sp
, &ulval
, t
, NULL
, base
)) != NUM_OK
)
if (vp
->character
== '+') {
if (!NPFITS(ULONG_MAX
, ulval
, change
)) {
nlen
= snprintf(nbuf
, sizeof(nbuf
), ntype
, wlen
, ulval
);
* UNIX sprintf(3) functions lose the leading 0[Xx] if
* the number is a 0. Not cool.
if (base
== 16 && ulval
== 0) {
nbuf
[1] = ntype
== fmt
[HEXC
] ? 'X' : 'x';
/* Build the new line. */
memmove(bp
+ beg
, nbuf
, nlen
);
memmove(bp
+ beg
+ nlen
, p
+ end
, len
- beg
- (end
- beg
));
len
= beg
+ nlen
+ (len
- beg
- (end
- beg
));
rval
= file_sline(sp
, vp
->m_start
.lno
, bp
, len
);
FREE_SPACE(sp
, bp
, blen
);
msgq(sp
, M_ERR
, "178|Resulting number too large");
msgq(sp
, M_ERR
, "179|Resulting number too small");