aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/sciteco.7.template2
-rw-r--r--src/parser.cpp2
-rw-r--r--src/qregisters.cpp122
-rw-r--r--src/qregisters.h16
4 files changed, 116 insertions, 26 deletions
diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template
index 7a2e924..ef994e8 100644
--- a/doc/sciteco.7.template
+++ b/doc/sciteco.7.template
@@ -456,7 +456,7 @@ Another construct that may be used as an argument barrier to explicitly
separate arguments is the comma (\(lq,\(rq).
It is obligatory when trying to push a sequence of number constants
like in \(lq1,2\(rq but is optional in many contexts where it is
-mandatory in classic TECO, like in \(lqQaQbD\(rq.
+mandatory in classic TECO, like in \(lq.ZD\(rq.
I recommend to use it as much as possible in code where clarity
matters.
.LP
diff --git a/src/parser.cpp b/src/parser.cpp
index 8c9e209..0e10347 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -517,7 +517,7 @@ StateStart::StateStart() : State()
transitions['['] = &States::pushqreg;
transitions[']'] = &States::popqreg;
transitions['G'] = &States::getqregstring;
- transitions['Q'] = &States::getqreginteger;
+ transitions['Q'] = &States::queryqreg;
transitions['U'] = &States::setqreginteger;
transitions['%'] = &States::increaseqreg;
transitions['M'] = &States::macro;
diff --git a/src/qregisters.cpp b/src/qregisters.cpp
index 940ce23..e16224f 100644
--- a/src/qregisters.cpp
+++ b/src/qregisters.cpp
@@ -47,12 +47,12 @@ namespace States {
StateLoadQReg loadqreg;
StateEPctCommand epctcommand;
StateSaveQReg saveqreg;
+ StateQueryQReg queryqreg;
StateCtlUCommand ctlucommand;
StateEUCommand eucommand;
StateSetQRegString setqregstring_nobuilding(false);
StateSetQRegString setqregstring_building(true);
StateGetQRegString getqregstring;
- StateGetQRegInteger getqreginteger;
StateSetQRegInteger setqreginteger;
StateIncreaseQReg increaseqreg;
StateMacro macro;
@@ -158,6 +158,49 @@ QRegisterData::get_string(void)
return str;
}
+gsize
+QRegisterData::get_string_size(void)
+{
+ gsize size;
+
+ if (!string.is_initialized())
+ return 0;
+
+ if (QRegisters::current)
+ QRegisters::current->string.update(QRegisters::view);
+
+ string.edit(QRegisters::view);
+
+ size = QRegisters::view.ssm(SCI_GETLENGTH);
+
+ if (QRegisters::current)
+ QRegisters::current->string.edit(QRegisters::view);
+
+ return size;
+}
+
+gint
+QRegisterData::get_character(gint position)
+{
+ gint ret = -1;
+
+ if (position < 0)
+ return -1;
+
+ if (QRegisters::current)
+ QRegisters::current->string.update(QRegisters::view);
+
+ string.edit(QRegisters::view);
+
+ if (position < QRegisters::view.ssm(SCI_GETLENGTH))
+ ret = QRegisters::view.ssm(SCI_GETCHARAT, position);
+
+ if (QRegisters::current)
+ QRegisters::current->string.edit(QRegisters::view);
+
+ return ret;
+}
+
void
QRegister::edit(void)
{
@@ -276,6 +319,21 @@ QRegisterBufferInfo::get_string(void)
return g_strdup(ring.current->filename ? : "");
}
+gsize
+QRegisterBufferInfo::get_string_size(void)
+{
+ return ring.current->filename ? strlen(ring.current->filename) : 0;
+}
+
+gint
+QRegisterBufferInfo::get_character(gint position)
+{
+ if (position < 0 || position >= (gint)get_string_size())
+ return -1;
+
+ return ring.current->filename[position];
+}
+
void
QRegisterBufferInfo::edit(void)
{
@@ -661,6 +719,51 @@ StateSaveQReg::done(const gchar *str)
}
/*$
+ * Qq -> n -- Query Q-Register integer or string
+ * <position>Qq -> character
+ * :Qq -> size
+ *
+ * Without any arguments, get and return the integer-part of
+ * Q-Register <q>.
+ *
+ * With one argument, return the <character> code at <position>
+ * from the string-part of Q-Register <q>.
+ * Positions are handled like buffer positions \(em they
+ * begin at 0 up to the length of the string minus 1.
+ * An error is thrown for invalid positions.
+ *
+ * When colon-modified, Q does not pop any arguments from
+ * the expression stack and returns the <size> of the string
+ * in Q-Register <q>.
+ * Naturally, for empty strings, 0 is returned.
+ *
+ * The command fails for undefined registers.
+ */
+State *
+StateQueryQReg::got_register(QRegister &reg)
+{
+ BEGIN_EXEC(&States::start);
+
+ expressions.eval();
+
+ if (eval_colon()) {
+ /* Query Q-Register string size */
+ expressions.push(reg.get_string_size());
+ } else if (expressions.args() > 0) {
+ /* Query character from Q-Register string */
+ gint c = reg.get_character(expressions.pop_num_calc());
+ if (c < 0)
+ throw RangeError('Q');
+ expressions.push(c);
+ } else {
+ /* Query integer */
+ expressions.push(reg.get_integer());
+ }
+
+ return &States::start;
+}
+
+/*$
* [c1,c2,...]^Uq[string]$ -- Set or append to Q-Register string without string building
* [c1,c2,...]:^Uq[string]$
*
@@ -794,23 +897,6 @@ StateGetQRegString::got_register(QRegister &reg)
}
/*$
- * Qq -> n -- Query Q-Register integer
- *
- * Gets and returns the integer-part of Q-Register <q>.
- * The command fails for undefined registers.
- */
-State *
-StateGetQRegInteger::got_register(QRegister &reg)
-{
- BEGIN_EXEC(&States::start);
-
- expressions.eval();
- expressions.push(reg.get_integer());
-
- return &States::start;
-}
-
-/*$
* nUq -- Set Q-Register integer
* -Uq
* [n]:Uq -> Success|Failure
diff --git a/src/qregisters.h b/src/qregisters.h
index 9dd3989..60b6f48 100644
--- a/src/qregisters.h
+++ b/src/qregisters.h
@@ -103,6 +103,8 @@ public:
undo_set_string();
}
virtual gchar *get_string(void);
+ virtual gsize get_string_size(void);
+ virtual gint get_character(gint position);
/*
* The QRegisterStack must currently access the
@@ -159,6 +161,8 @@ public:
void undo_append_string(void) {}
gchar *get_string(void);
+ gsize get_string_size(void);
+ gint get_character(gint pos);
void edit(void);
};
@@ -367,6 +371,11 @@ private:
State *done(const gchar *str);
};
+class StateQueryQReg : public StateExpectQReg {
+private:
+ State *got_register(QRegister &reg);
+};
+
class StateCtlUCommand : public StateExpectQReg {
public:
StateCtlUCommand() : StateExpectQReg(true) {}
@@ -400,11 +409,6 @@ private:
State *got_register(QRegister &reg);
};
-class StateGetQRegInteger : public StateExpectQReg {
-private:
- State *got_register(QRegister &reg);
-};
-
class StateSetQRegInteger : public StateExpectQReg {
public:
StateSetQRegInteger() : StateExpectQReg(true) {}
@@ -446,12 +450,12 @@ namespace States {
extern StateLoadQReg loadqreg;
extern StateEPctCommand epctcommand;
extern StateSaveQReg saveqreg;
+ extern StateQueryQReg queryqreg;
extern StateCtlUCommand ctlucommand;
extern StateEUCommand eucommand;
extern StateSetQRegString setqregstring_nobuilding;
extern StateSetQRegString setqregstring_building;
extern StateGetQRegString getqregstring;
- extern StateGetQRegInteger getqreginteger;
extern StateSetQRegInteger setqreginteger;
extern StateIncreaseQReg increaseqreg;
extern StateMacro macro;