mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
303 lines
12 KiB
Plaintext
303 lines
12 KiB
Plaintext
NAME
|
|
protect - read or adjust protect status for a variable or named block
|
|
|
|
SYNOPSIS
|
|
protect(var [, N [, depth])
|
|
protect(nblk [, N [, depth]])
|
|
|
|
TYPES
|
|
var lvalue
|
|
nblk named block
|
|
N integer, abs(N) < 65536
|
|
depth nonnegative integer
|
|
|
|
return null value
|
|
|
|
DESCRIPTION
|
|
The protection status of the association of an lvalue A with
|
|
its value is represented by a nonnegative integer less than 2^16.
|
|
The current value sts of this status is returned by protect(A).
|
|
Each nonzero bit of the low eight bits of sts corresponds to a
|
|
builtin kind of protection as follows:
|
|
|
|
bit value protection
|
|
|
|
1 no assign to A
|
|
2 no change of A by assignment
|
|
4 no change of type value of A
|
|
8 no error value for A
|
|
16 no copy to A
|
|
32 no relocation for A or its elements
|
|
64 no assign from A
|
|
128 no copy from A
|
|
|
|
For example, A having protection status 65 = 1 + 64 prevents
|
|
execution of assignments of the forms A = expression and V = A
|
|
where V is an lvalue. Attempting either of these assignments
|
|
will return an error value and leave the value of A or V unchanged.
|
|
|
|
Initially, when created, any lvalue A has zero status corresponding
|
|
to "no protection". This may be restored at any time by protect(A, 0).
|
|
|
|
If N is positive and A does not already have the protection
|
|
corresponding to a nonzero bit of N, protect(A, N) adds that
|
|
protection to the status of A. For example, if protect(A) is 65,
|
|
protect(A, 17) will add the no-copy-to protection so that the
|
|
new protection status of A will be 81 = 1 + 16 + 64.
|
|
|
|
Similarly, if N is negative and A has the protection corresponding
|
|
to a nonzero bit of abs(N), protect(A,N) will remove that kind of
|
|
protection. For example if protect(A) = 65, then protect(A, -17)
|
|
will remove the no-assign-to protection and the new value of
|
|
protect(A) will be 64. Note that protect(A, -65535) has the same
|
|
effect as protect(A, 0).
|
|
|
|
For the purposes of this function, the depth of a global or local
|
|
variable is zero; if A has depth d and the value of A is a list,
|
|
matrix, object or association, its elements have depth d + 1.
|
|
For example, after:
|
|
|
|
; obj point {x,y}
|
|
; X = mat[3] = {1, list(2,3), mat[2] = {obj point, obj point} }
|
|
|
|
X has depth 0; X[0], X[1] and X[2] have depth 1; X[1][0], X[1][1],
|
|
X[2][0] and X[2][1] have depth 2; X[2][0].x, X[2][0].y, X[2][1].x
|
|
and X[2][1].y have depth 3. For any lvalue A, protect(A, N, depth)
|
|
applies protect(A, N) to A and to all elements, elements of
|
|
elements, etc., up to the stated depth. In the above example,
|
|
protect(X, 20, 2) gives no-type-change and no-copy-to protection
|
|
to 8 of the listed lvalues, but not to the components of the
|
|
objects X[2][0] and X[2][1]; With any d >= 3, protect(X, 20, d)
|
|
would give that protection the 12 listed lvalues.
|
|
|
|
If B is a variable with positive status and assignment of B to A is
|
|
permitted, execution of the assignment A = B adds to the protections
|
|
of A all protections of B that A does not already have. Except when
|
|
the value returned is the result of the evaluation of an lvalue with
|
|
positive status, calc's builtin operators and functions return values
|
|
with zero protection status. For example, whatever the protection
|
|
statuses of X and Y, X + sqrt(Y) will have zero status, but
|
|
t ? X : Y may have nonzero status. The list, matrix, object or
|
|
association returned by the use of list, mat, obj or assoc will have
|
|
zero status, but any element specified by an lvalue will receive
|
|
its status; e.g. after L = list(X, X^2) , protect(L[0]) equals
|
|
protect(X) and both protect(L) and protect(L[1]) are zero.
|
|
|
|
Users may define functions that return values with positive status, e.g.
|
|
|
|
; define noassigntovalue(x) {protect(x,1); return x};
|
|
; S = noassigntovalue(42);
|
|
|
|
will result in S having the value 42 and no-assign-to protection.
|
|
By using a backquote with a variable as argument, an even simpler
|
|
function:
|
|
|
|
; define noassignto(x) = protect(x, 1);
|
|
|
|
gives no-assign-to protection to the variable; i.e. noassignto(`A)
|
|
achieves the same as protect(A,1).
|
|
|
|
In the brief descriptions above of builtin kinds of protection,
|
|
"assign" refers to use of '=' as in A = expr to assign the value
|
|
of expr to A, and in A = {..., expr, ...} to assign the value of expr
|
|
to some component of A, and to the assignments implicit in
|
|
quomod(x, y, A, B), and pre or post ++ or --. Swapping of lvalues is
|
|
prevented if either value has no-assign-to or no-assign-from
|
|
protection. (Swapping of octets is prevented if at least one of
|
|
them is in a string or block with no-copy-to or no-copy-from
|
|
protection.)
|
|
|
|
"Copying" refers to initialization using {...} and to the operations
|
|
copy and blkcpy as applied to strings, blocks, lists and matrices.
|
|
Although A = {..., expr, ...) assigns the value of expr to an
|
|
element of A, it is also regarded as copying to A. Thus, initialization
|
|
of A may be prevented either by giving no-copy-to protection to A or
|
|
no-assignment=to protection to the elements of A. Assignments to and
|
|
from characters or octets in strings or blocks are also regarded as
|
|
copying to or from the string or block. For example, after
|
|
A = "abc", protect(A,16) would prevent the assignment A[0] = 'x'.
|
|
(Note that in this example, A[0] is not an lvalue in the sense
|
|
normally understood - the only values it can have are nonnegative
|
|
integers less than 256. The only kinds of protection relevant to an
|
|
octet are the no-copy-to, no-copy-from and no-change protections of
|
|
the string or block in which the octet resides.)
|
|
|
|
The no-relocate protection applies to lists and blocks. For lists,
|
|
it refers to the operations push, pop, append, remove, insert and
|
|
delete. For example, if A = list(2,3,5,7), protect(A, 32) will
|
|
prevent any change in the content or size of the list.
|
|
No-relocation protection of a block prevents reallocation of the
|
|
memory used by a block and the freeing of a named block, For example,
|
|
if a block B has maxsize 256, then after:
|
|
|
|
; protect(B, 32);
|
|
|
|
copy(A, B) will fail if the copying would cause size(B) to equal or
|
|
exceed 256; if B is a named block, blkfree(B) will not be permitted.
|
|
|
|
The elements of the list returned by list(...) will initially have zero
|
|
protection status except when an argument is an lvalue with positive
|
|
status, in which case the corresponding element will receive that
|
|
status. E.g., L = list(A,B) will result in L[0] having status
|
|
protect(A) and L[1] having status protect(B). L itself will have
|
|
the status L had before the assignment. There is a similar copying
|
|
of protection status when "= { ... }" initialization is used for
|
|
matrices, lists or objects. For example, except when A or B has
|
|
no-assign-from protection, M = mat [2] = {A,B} or mat M[2] = {A,B}
|
|
will result in M[0] and M[1] having statuses protect(A) and
|
|
protect(B) respectively. (If A or B has no-assign-from protection,
|
|
mat[2] = {A,B} returns an error value.)
|
|
|
|
Although M = mat[2] = {...} and mat M[2] = {...} do the same thing,
|
|
these are different from (M = mat[2]) = {...} and (mat M[3]) = {...}.
|
|
In the former pair of statements, the result of mat[2] = {...} is being
|
|
assigned to M. In the latter statements, a matrix with zero elements is
|
|
being assigned to M and then that matrix is being "reinitialized". Both
|
|
will fail if M has no-assign-to protection, but only the latter
|
|
would be prevented by M having no-copy-to protection.
|
|
|
|
When the functions which can move elements like of sort, reverse,
|
|
swap, insert, pop, remove, push and append. are evaluated, the
|
|
protection statuses move with the values, e.g. if among the values
|
|
and elements involved, there is just one with value 42, then the
|
|
lvalue to which the value 42 is moved will get the status the lvalue
|
|
with value 42 had before the evaluation of the function. This is
|
|
relevant to evaluation of expressions like A = sort(A),
|
|
append(A, pop(A)), insert(A,2,B,C). Note that when pop(A) is first
|
|
evaluated it is located on the stack calc uses for calculating
|
|
expressions rather than being the value of an lvalue. With an
|
|
explicit assignment like X = pop(A) or the implied assignment in
|
|
append(A, pop(A)), it becomes the value of an lvalue.
|
|
|
|
Users may use higher bits values for other kinds of protection or
|
|
simply to store information about an lvalue and its current value.
|
|
For example 1024 might be used to indicate that the lvalue is always
|
|
to have positive value. Then code for evaluating a function might
|
|
include lines like
|
|
|
|
; if (protect(A) & 1024 && B <= 0) {
|
|
;; return newerror("Prohibited assignment");
|
|
;; }
|
|
; A = B;
|
|
|
|
When an operation forbidden by a particular bit in the protection
|
|
status of A is attempted, an error value is created but unless this
|
|
causes errcount to exceed errmax, the only immediate evidence
|
|
for the error might be the incrementing of errcount. Sometimes the
|
|
failure causes the return of the error value; e.g. swap(A,B) if
|
|
not permitted returns an appropriate error value rather than the
|
|
null value. If the value of A is a number and A has no-type-change
|
|
protection, A = "abc" returns an error value. The error-number of
|
|
the most recent error value is returned by errno(), a string
|
|
describing it by strerror().
|
|
|
|
A named block may be referred to by using the blocks() or blk()
|
|
functions, or by assigning it to a variable A and then using either
|
|
A or *A. In the latter cases, protect(A, sts) sets the status for
|
|
the variable A; protect(*A, sts) assigns the status for the named
|
|
block. For example, protect(*A,16) will prevent any copying to the
|
|
named block; protect(A,16) will prevent any copying to the named block
|
|
only when it is referred to by A.
|
|
|
|
EXAMPLE
|
|
; A = 27
|
|
; protect(A,1)
|
|
; A = 45
|
|
; A
|
|
27
|
|
; strerror()
|
|
"No-assign-to destination for assign"
|
|
; protect(A,64)
|
|
; protect(A)
|
|
65
|
|
; X = A
|
|
; X
|
|
0
|
|
; strerror()
|
|
"No-assign-from source for assign"
|
|
; protect(A,-1)
|
|
; protect(A)
|
|
64
|
|
; protect(A,4)
|
|
; protect(A)
|
|
68
|
|
; A = "abc"
|
|
; A
|
|
27
|
|
; strerror()
|
|
"No-type-change destination for assign"
|
|
; B = 45
|
|
; swap(A,B)
|
|
Error 10372
|
|
; strerror()
|
|
"No-assign-to-or-from argument for swap"
|
|
; protect(A,-64)
|
|
; protect(A)
|
|
4
|
|
; swap(A,B)
|
|
; A
|
|
45
|
|
; B
|
|
27
|
|
|
|
; A = mat[4] = {1,2,3,4}
|
|
; B = list(5,6,7,8)
|
|
; protect(A,16)
|
|
; copy(B,A)
|
|
Error 10226
|
|
; strerror()
|
|
"No-copy-to destination variable"
|
|
|
|
; A = list(1,2,3)
|
|
; protect(A,32)
|
|
; append(A,4)
|
|
Error 10402
|
|
; strerror()
|
|
"No-relocate for list append"
|
|
|
|
; A = blk(0,5)
|
|
; copy("abc", A)
|
|
; copy("de",A)
|
|
Error 10229
|
|
; strerror()
|
|
"No-relocate destination variable"
|
|
|
|
; A = blk("alpha") = {1,2,3,4,5}
|
|
; protect(A,0)
|
|
; protect(*A, 16)
|
|
; copy("abc", A)
|
|
Error 10228
|
|
; strerror()
|
|
"No-copy-to destination named block"
|
|
|
|
LIMITS
|
|
none
|
|
|
|
LINK LIBRARY
|
|
none
|
|
|
|
SEE ALSO
|
|
assign, copy, blk, error, errno, strerror
|
|
|
|
## Copyright (C) 1999-2006,2021 Landon Curt Noll
|
|
##
|
|
## Calc is open software; you can redistribute it and/or modify it under
|
|
## the terms of the version 2.1 of the GNU Lesser General Public License
|
|
## as published by the Free Software Foundation.
|
|
##
|
|
## Calc is distributed in the hope that it will be useful, but WITHOUT
|
|
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
## Public License for more details.
|
|
##
|
|
## A copy of version 2.1 of the GNU Lesser General Public License is
|
|
## distributed with calc under the filename COPYING-LGPL. You should have
|
|
## received a copy with calc; if not, write to Free Software Foundation, Inc.
|
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
##
|
|
## Under source code control: 1997/07/10 22:38:44
|
|
## File existed as early as: 1997
|
|
##
|
|
## chongo <was here> /\oo/\ http://www.isthe.com/chongo/
|
|
## Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|