Add relative address and at functions

This commit is contained in:
Glen Whitney 2019-07-29 14:14:36 -04:00
parent a5bf64b061
commit b3ea9f7ad9
2 changed files with 136 additions and 126 deletions

View File

@ -5393,20 +5393,8 @@ l
\emph default
)
\series default
returns the value of the cell at position
\emph on
x
\emph default
,
\emph on
y
\emph default
,
\emph on
z
\emph default
.
If any of
returns the value of the cell at the specified location.
In the first form, if any of
\emph on
x
\emph default
@ -5465,9 +5453,30 @@ y
z
\emph default
]]])
]]])
\begin_inset space ~
\end_inset
|
\begin_inset space ~
\end_inset
\series default
returns a pointer to the cell at location
&
\series medium
(location
\emph on
\begin_inset space ~
\end_inset
l
\emph default
)
\series default
returns the specified location.
In the first form, if any of
\emph on
x
\emph default
@ -5475,30 +5484,65 @@ x
\emph on
y
\emph default
,
or
\emph on
z
\emph default
.
If
\emph on
z
\emph default
is omitted, the
\emph on
z
\emph default
position of the current cell is used.
If
\emph on
y
\emph default
is missing as well, the
\emph on
y
\emph default
position (row) of the cell is used.
is omitted, the coordinate of the cell is used.
The second form is in fact a no-op, but it is allowed for convenience
\end_layout
\begin_layout Description
R() Exactly the same as
\series bold
@
\series default
, except the coordinates of the argument are interpreted as an offset to
the current location (rather than as absolute coordinates in the sheet);
think
\begin_inset Quotes eld
\end_inset
R
\begin_inset Quotes erd
\end_inset
for
\begin_inset Quotes eld
\end_inset
relative.
\begin_inset Quotes erd
\end_inset
Thus R(-1) returns the value of the cell immediately to the left of this
one.
\end_layout
\begin_layout Description
D() Exactly the same as
\series bold
&
\series default
, except the coordinates of the argument are added to the current location.
Think
\begin_inset Quotes eld
\end_inset
D
\begin_inset Quotes erd
\end_inset
for
\begin_inset Quotes eld
\end_inset
displaced (by).
\begin_inset Quotes erd
\end_inset
Thus, D(-1) returns the location of the cell immediately to the left of
this one.
\end_layout
\begin_layout Description

View File

@ -305,68 +305,15 @@ static double deg2rad(double x)
#define INTPATIBLE(t) (t.type == INT || t.type == EMPTY)
/* @ */ /*{{{*/
static Token at_func(int argc, const Token argv[])
{
/* variables */ /*{{{*/
Token result;
Location tmp;
Dimensions dim;
/*}}}*/
/* asserts */ /*{{{*/
assert(argv!=(Token*)0);
/*}}}*/
if (argc==0)
/* return value at current location */ /*{{{*/
return (getvalue(upd_sheet, upd_l));
/*}}}*/
if (argc==1 && argv[0].type==LOCATION)
/* return value at location pointed to by argument */ /*{{{*/
return (getvalue(upd_sheet, argv[0].u.location));
/*}}}*/
LOCATION_GETS(tmp, upd_l);
if (argc==1 && (argv[0].type==INT || argv[0].type==EMPTY))
/* return value at x on current y,z */ /*{{{*/
{
if (argv[0].type == INT) tmp[X] = argv[0].u.integer;
return getvalue(upd_sheet, tmp);
}
/*}}}*/
if (argc==2 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]))
/* return value at x,y on current z */ /*{{{*/
{
if (argv[0].type == INT) tmp[X] = argv[0].u.integer;
if (argv[1].type == INT) tmp[Y] = argv[1].u.integer;
return getvalue(upd_sheet, tmp);
}
/*}}}*/
if (argc==3 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]) &&
INTPATIBLE(argv[2]))
/* return value at x,y,z */ /*{{{*/
{
for (dim = X; dim < HYPER; ++dim)
if (argv[dim].type == INT) tmp[dim] = argv[dim].u.integer;
return getvalue(upd_sheet, tmp);
}
/*}}}*/
else
/* return error */ /*{{{*/
{
result.type=EEK;
result.u.err=strcpy(malloc(strlen(_("Usage: @([integer x][,[integer y][,[integer z]]]) or @(location)"))+1),_("Usage: @([integer x][,[integer y][,[integer z]]]) or @(location)"));
return result;
}
/*}}}*/
}
/*}}}*/
typedef enum {ABSOLUTE, RELATIVE} LocConvention;
/* & */ /*{{{*/
static Token adr_func(int argc, const Token argv[])
static Token adr_func(int argc, const Token argv[], LocConvention lcon)
{
/* variables */ /*{{{*/
Token result;
Dimensions dim;
size_t i;
/*}}}*/
/* asserts */ /*{{{*/
@ -374,47 +321,64 @@ static Token adr_func(int argc, const Token argv[])
/*}}}*/
LOCATION_GETS(result.u.location, upd_l);
if (argc==3 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]) &&
INTPATIBLE(argv[2]))
/* result is location of the given position */ /*{{{*/
if (argc == 1 && argv[0].type == LOCATION) return argv[0];
for (i = 0; i < argc && i < HYPER; ++i)
{
result.type=LOCATION;
for (dim = X; dim < HYPER; ++dim)
if (argv[dim].type == INT) result.u.location[dim] = argv[dim].u.integer;
if (!INTPATIBLE(argv[i])) break;
if (lcon == ABSOLUTE) result.u.location[i] = argv[i].u.integer;
else result.u.location[i] += argv[i].u.integer;
}
/*}}}*/
else if (argc==2 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]))
/* result is location of the given position in the current z layer */ /*{{{*/
{
result.type=LOCATION;
for (dim = X; dim <= Y; ++dim)
if (argv[dim].type == INT) result.u.location[dim] = argv[dim].u.integer;
}
/*}}}*/
else if (argc==1 && INTPATIBLE(argv[0]))
/* result is location of the given position in the current y,z layer */ /*{{{*/
{
result.type=LOCATION;
if (argv[0].type == INT) result.u.location[X] = argv[0].u.integer;
}
/*}}}*/
else if (argc==0)
/* result is location of the current position */ /*{{{*/
{
result.type=LOCATION;
}
/*}}}*/
else
/* result is type error */ /*{{{*/
if (i < argc)
{
result.type=EEK;
result.u.err=strcpy(malloc(strlen(_("Usage: &([integer x][,[integer y][,[integer z]]])"))+1),_("Usage: &([integer x][,[integer y][,[integer z]]])"));
}
/*}}}*/
else
result.type = LOCATION;
return result;
}
/*}}}*/
/* @ */ /*{{{*/
static Token at_func(int argc, const Token argv[], LocConvention lcon)
{
Token location;
location = adr_func(argc, argv, lcon);
if (location.type == EEK)
{
Token result;
result.type = EEK;
char *pref = _("Inside @: ");
result.u.err = malloc(strlen(location.u.err) + strlen(pref) + 1);
strcpy(result.u.err, pref);
strcat(result.u.err, location.u.err);
tfree(&location);
return result;
}
return getvalue(upd_sheet, location.u.location);
}
static Token abs_adr_func(int argc, const Token argv[])
{
return adr_func(argc, argv, ABSOLUTE);
}
static Token abs_at_func(int argc, const Token argv[])
{
return at_func(argc, argv, ABSOLUTE);
}
static Token rel_adr_func(int argc, const Token argv[])
{
return adr_func(argc, argv, RELATIVE);
}
static Token rel_at_func(int argc, const Token argv[])
{
return at_func(argc, argv, RELATIVE);
}
/* x */ /*{{{*/
static Token x_func(int argc, const Token argv[])
{
@ -1446,8 +1410,8 @@ static Token time_func(int argc, const Token argv[])
compatible, new entries should be appended. */
Tfunc tfunc[]=
{
{ "@", at_func },
{ "&", adr_func },
{ "@", abs_at_func },
{ "&", abs_adr_func },
{ "x", x_func },
{ "y", y_func },
{ "z", z_func },
@ -1489,6 +1453,8 @@ Tfunc tfunc[]=
{ "time", time_func },
{ "bitand", bitand_func },
{ "bitor", bitor_func },
{ "D", rel_adr_func },
{ "R", rel_at_func },
{ "", (Token (*)(int, const Token[]))0 }
};
/*}}}*/