[C++] Implement all other text functions
diff --git a/func.cc b/func.cc
index cd96411..b9faa8a 100644
--- a/func.cc
+++ b/func.cc
@@ -1,8 +1,11 @@
 #include "func.h"
 
+#include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <algorithm>
+#include <iterator>
 #include <unordered_map>
 
 #include "eval.h"
@@ -103,24 +106,97 @@
   }
 }
 
-void WordFunc(const vector<Value*>&, Evaluator*, string*) {
-  printf("TODO(word)");
+static int GetNumericValueForFunc(const string& buf) {
+  StringPiece s = TrimLeftSpace(buf);
+  char* end;
+  long n = strtol(s.data(), &end, 10);
+  if (n < 0 || n == LONG_MAX || s.data() + s.size() != end) {
+    return -1;
+  }
+  return n;
 }
 
-void WordlistFunc(const vector<Value*>&, Evaluator*, string*) {
-  printf("TODO(wordlist)");
+void WordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
+  shared_ptr<string> n_str = args[0]->Eval(ev);
+  int n = GetNumericValueForFunc(*n_str);
+  if (n < 0) {
+    ev->Error(StringPrintf(
+        "*** non-numeric first argument to `word' function: '%s'.",
+        n_str->c_str()));
+  }
+  if (n == 0) {
+    ev->Error("*** first argument to `word' function must be greater than 0.");
+  }
+
+  shared_ptr<string> text = args[1]->Eval(ev);
+  for (StringPiece tok : WordScanner(*text)) {
+    n--;
+    if (n == 0) {
+      AppendString(tok, s);
+      break;
+    }
+  }
 }
 
-void WordsFunc(const vector<Value*>&, Evaluator*, string*) {
-  printf("TODO(words)");
+void WordlistFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
+  shared_ptr<string> s_str = args[0]->Eval(ev);
+  int si = GetNumericValueForFunc(*s_str);
+  if (si < 0) {
+    ev->Error(StringPrintf(
+        "*** non-numeric first argument to `wordlist' function: '%s'.",
+        s_str->c_str()));
+  }
+  if (si == 0) {
+    ev->Error(StringPrintf(
+        "*** invalid first argument to `wordlist' function: %s`",
+        s_str->c_str()));
+  }
+
+  shared_ptr<string> e_str = args[1]->Eval(ev);
+  int ei = GetNumericValueForFunc(*e_str);
+  if (ei < 0) {
+    ev->Error(StringPrintf(
+        "*** non-numeric second argument to `wordlist' function: '%s'.",
+        e_str->c_str()));
+  }
+
+  shared_ptr<string> text = args[2]->Eval(ev);
+  int i = 0;
+  WordWriter ww(s);
+  for (StringPiece tok : WordScanner(*text)) {
+    i++;
+    if (si <= i && i <= ei) {
+      ww.Write(tok);
+    }
+  }
 }
 
-void FirstwordFunc(const vector<Value*>&, Evaluator*, string*) {
-  printf("TODO(firstword)");
+void WordsFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
+  shared_ptr<string> text = args[0]->Eval(ev);
+  WordScanner ws(*text);
+  int n = 0;
+  for (auto iter = ws.begin(); iter != ws.end(); ++iter)
+    n++;
+  char buf[32];
+  sprintf(buf, "%d", n);
+  *s += buf;
 }
 
-void LastwordFunc(const vector<Value*>&, Evaluator*, string*) {
-  printf("TODO(lastword)");
+void FirstwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
+  shared_ptr<string> text = args[0]->Eval(ev);
+  for (StringPiece tok : WordScanner(*text)) {
+    AppendString(tok, s);
+    return;
+  }
+}
+
+void LastwordFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
+  shared_ptr<string> text = args[0]->Eval(ev);
+  StringPiece last;
+  for (StringPiece tok : WordScanner(*text)) {
+    last = tok;
+  }
+  AppendString(last, s);
 }
 
 void JoinFunc(const vector<Value*>&, Evaluator*, string*) {