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 \emph default
) )
\series default \series default
returns the value of the cell at position returns the value of the cell at the specified location.
\emph on In the first form, if any of
x
\emph default
,
\emph on
y
\emph default
,
\emph on
z
\emph default
.
If any of
\emph on \emph on
x x
\emph default \emph default
@ -5466,8 +5454,29 @@ y
z z
\emph default \emph default
]]]) ]]])
\begin_inset space ~
\end_inset
|
\begin_inset space ~
\end_inset
\series default \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 \emph on
x x
\emph default \emph default
@ -5475,30 +5484,65 @@ x
\emph on \emph on
y y
\emph default \emph default
, or
\emph on \emph on
z z
\emph default \emph default
. is omitted, the coordinate of the cell is used.
If The second form is in fact a no-op, but it is allowed for convenience
\emph on \end_layout
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.
\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 \end_layout
\begin_layout Description \begin_layout Description

View File

@ -305,68 +305,15 @@ static double deg2rad(double x)
#define INTPATIBLE(t) (t.type == INT || t.type == EMPTY) #define INTPATIBLE(t) (t.type == INT || t.type == EMPTY)
/* @ */ /*{{{*/ typedef enum {ABSOLUTE, RELATIVE} LocConvention;
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;
}
/*}}}*/
}
/*}}}*/
/* & */ /*{{{*/ /* & */ /*{{{*/
static Token adr_func(int argc, const Token argv[]) static Token adr_func(int argc, const Token argv[], LocConvention lcon)
{ {
/* variables */ /*{{{*/ /* variables */ /*{{{*/
Token result; Token result;
Dimensions dim; Dimensions dim;
size_t i;
/*}}}*/ /*}}}*/
/* asserts */ /*{{{*/ /* asserts */ /*{{{*/
@ -374,47 +321,64 @@ static Token adr_func(int argc, const Token argv[])
/*}}}*/ /*}}}*/
LOCATION_GETS(result.u.location, upd_l); LOCATION_GETS(result.u.location, upd_l);
if (argc==3 && INTPATIBLE(argv[0]) && INTPATIBLE(argv[1]) && if (argc == 1 && argv[0].type == LOCATION) return argv[0];
INTPATIBLE(argv[2])) for (i = 0; i < argc && i < HYPER; ++i)
/* result is location of the given position */ /*{{{*/
{ {
result.type=LOCATION; if (!INTPATIBLE(argv[i])) break;
for (dim = X; dim < HYPER; ++dim) if (lcon == ABSOLUTE) result.u.location[i] = argv[i].u.integer;
if (argv[dim].type == INT) result.u.location[dim] = argv[dim].u.integer; else result.u.location[i] += argv[i].u.integer;
} }
/*}}}*/ if (i < argc)
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 */ /*{{{*/
{ {
result.type=EEK; result.type=EEK;
result.u.err=strcpy(malloc(strlen(_("Usage: &([integer x][,[integer y][,[integer z]]])"))+1),_("Usage: &([integer x][,[integer y][,[integer z]]])")); 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; 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 */ /*{{{*/ /* x */ /*{{{*/
static Token x_func(int argc, const Token argv[]) 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. */ compatible, new entries should be appended. */
Tfunc tfunc[]= Tfunc tfunc[]=
{ {
{ "@", at_func }, { "@", abs_at_func },
{ "&", adr_func }, { "&", abs_adr_func },
{ "x", x_func }, { "x", x_func },
{ "y", y_func }, { "y", y_func },
{ "z", z_func }, { "z", z_func },
@ -1489,6 +1453,8 @@ Tfunc tfunc[]=
{ "time", time_func }, { "time", time_func },
{ "bitand", bitand_func }, { "bitand", bitand_func },
{ "bitor", bitor_func }, { "bitor", bitor_func },
{ "D", rel_adr_func },
{ "R", rel_at_func },
{ "", (Token (*)(int, const Token[]))0 } { "", (Token (*)(int, const Token[]))0 }
}; };
/*}}}*/ /*}}}*/