#include "utils/json.h"
 #include "utils/typcache.h"
 
-typedef enum
+typedef enum                   /* types of JSON values */
 {
-   JSON_VALUE_INVALID,
+   JSON_VALUE_INVALID,         /* non-value tokens are reported as this */
    JSON_VALUE_STRING,
    JSON_VALUE_NUMBER,
    JSON_VALUE_OBJECT,
    JSON_VALUE_NULL
 } JsonValueType;
 
-typedef struct
+typedef struct                 /* state of JSON lexer */
 {
-   char       *input;
-   char       *token_start;
-   char       *token_terminator;
-   JsonValueType token_type;
-   int         line_number;
-   char       *line_start;
+   char       *input;          /* whole string being parsed */
+   char       *token_start;    /* start of current token within input */
+   char       *token_terminator; /* end of previous or current token */
+   JsonValueType token_type;   /* type of current token, once it's known */
+   int         line_number;    /* current line number (counting from 1) */
+   char       *line_start;     /* start of current line within input (BROKEN!!) */
 } JsonLexContext;
 
-typedef enum
+typedef enum                   /* states of JSON parser */
 {
    JSON_PARSE_VALUE,           /* expecting a value */
    JSON_PARSE_ARRAY_START,     /* saw '[', expecting value or ']' */
    JSON_PARSE_OBJECT_COMMA     /* saw object ',', expecting next label */
 } JsonParseState;
 
-typedef struct JsonParseStack
+typedef struct JsonParseStack  /* the parser state has to be stackable */
 {
    JsonParseState state;
+   /* currently only need the state enum, but maybe someday more stuff */
 } JsonParseStack;
 
-typedef enum
+typedef enum                   /* required operations on state stack */
 {
-   JSON_STACKOP_NONE,
-   JSON_STACKOP_PUSH,
-   JSON_STACKOP_PUSH_WITH_PUSHBACK,
-   JSON_STACKOP_POP
+   JSON_STACKOP_NONE,          /* no-op */
+   JSON_STACKOP_PUSH,          /* push new JSON_PARSE_VALUE stack item */
+   JSON_STACKOP_PUSH_WITH_PUSHBACK, /* push, then rescan current token */
+   JSON_STACKOP_POP            /* pop, or expect end of input if no stack */
 } JsonStackOp;
 
 static void json_validate_cstring(char *input);
 static void report_parse_error(JsonParseStack *stack, JsonLexContext *lex);
 static void report_invalid_token(JsonLexContext *lex);
 static char *extract_mb_char(char *s);
-static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds);
+static void composite_to_json(Datum composite, StringInfo result,
+                             bool use_line_feeds);
 static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
                  Datum *vals, bool *nulls, int *valcount,
                  TYPCATEGORY tcategory, Oid typoutputfunc,
                  bool use_line_feeds);
-static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds);
+static void array_to_json_internal(Datum array, StringInfo result,
+                                  bool use_line_feeds);
 
 /* fake type category for JSON so we can distinguish it in datum_to_json */
 #define TYPCATEGORY_JSON 'j'
 /* letters appearing in numeric output that aren't valid in a JSON number */
 #define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
+/* chars to consider as part of an alphanumeric token */
+#define JSON_ALPHANUMERIC_CHAR(c)  \
+   (((c) >= 'a' && (c) <= 'z') || \
+    ((c) >= 'A' && (c) <= 'Z') || \
+    ((c) >= '0' && (c) <= '9') || \
+    (c) == '_' || \
+    IS_HIGHBIT_SET(c))
+
+
 /*
  * Input.
  */
 
    json_validate_cstring(text);
 
+   /* Internal representation is the same as text, for now */
    PG_RETURN_TEXT_P(cstring_to_text(text));
 }
 
 Datum
 json_out(PG_FUNCTION_ARGS)
 {
+   /* we needn't detoast because text_to_cstring will handle that */
    Datum       txt = PG_GETARG_DATUM(0);
 
    PG_RETURN_CSTRING(TextDatumGetCString(txt));
 Datum
 json_send(PG_FUNCTION_ARGS)
 {
-   StringInfoData buf;
    text       *t = PG_GETARG_TEXT_PP(0);
+   StringInfoData buf;
 
    pq_begintypsend(&buf);
    pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
 
    /* Set up parse stack. */
    stacksize = 32;
-   stacktop = palloc(sizeof(JsonParseStack) * stacksize);
+   stacktop = (JsonParseStack *) palloc(sizeof(JsonParseStack) * stacksize);
    stack = stacktop;
    stack->state = JSON_PARSE_VALUE;
 
                    stack->state = JSON_PARSE_ARRAY_NEXT;
                else if (lex.token_start[0] == ']')
                    op = JSON_STACKOP_POP;
-               else if (lex.token_start[0] == '['
-                        || lex.token_start[0] == '{')
+               else if (lex.token_start[0] == '[' ||
+                        lex.token_start[0] == '{')
                {
                    stack->state = JSON_PARSE_ARRAY_NEXT;
                    op = JSON_STACKOP_PUSH_WITH_PUSHBACK;
            case JSON_PARSE_OBJECT_START:
                if (lex.token_type == JSON_VALUE_STRING)
                    stack->state = JSON_PARSE_OBJECT_LABEL;
-               else if (lex.token_type == JSON_VALUE_INVALID
-                        && lex.token_start[0] == '}')
+               else if (lex.token_type == JSON_VALUE_INVALID &&
+                        lex.token_start[0] == '}')
                    op = JSON_STACKOP_POP;
                else
                    report_parse_error(stack, &lex);
                break;
            case JSON_PARSE_OBJECT_LABEL:
-               if (lex.token_type == JSON_VALUE_INVALID
-                   && lex.token_start[0] == ':')
+               if (lex.token_type == JSON_VALUE_INVALID &&
+                   lex.token_start[0] == ':')
                {
                    stack->state = JSON_PARSE_OBJECT_NEXT;
                    op = JSON_STACKOP_PUSH;
                     (int) stack->state);
        }
 
-       /* Push or pop the stack, if needed. */
+       /* Push or pop the state stack, if needed. */
        switch (op)
        {
            case JSON_STACKOP_PUSH:
            case JSON_STACKOP_PUSH_WITH_PUSHBACK:
-               ++stack;
+               stack++;
                if (stack >= &stacktop[stacksize])
                {
+                   /* Need to enlarge the stack. */
                    int         stackoffset = stack - stacktop;
 
-                   stacksize = stacksize + 32;
-                   stacktop = repalloc(stacktop,
-                                       sizeof(JsonParseStack) * stacksize);
+                   stacksize += 32;
+                   stacktop = (JsonParseStack *)
+                       repalloc(stacktop,
+                                sizeof(JsonParseStack) * stacksize);
                    stack = stacktop + stackoffset;
                }
                stack->state = JSON_PARSE_VALUE;
                        report_parse_error(NULL, &lex);
                    return;
                }
-               --stack;
+               stack--;
                break;
            case JSON_STACKOP_NONE:
                /* nothing to do */
    while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
    {
        if (*s == '\n')
-           ++lex->line_number;
-       ++s;
+           lex->line_number++;
+       s++;
    }
    lex->token_start = s;
 
    /* Determine token type. */
-   if (strchr("{}[],:", s[0]))
+   if (strchr("{}[],:", s[0]) != NULL)
    {
-       /* strchr() doesn't return false on a NUL input. */
+       /* strchr() is willing to match a zero byte, so test for that. */
        if (s[0] == '\0')
        {
            /* End of string. */
         * whole word as an unexpected token, rather than just some
         * unintuitive prefix thereof.
         */
-       for (p = s; (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')
-            || (*p >= '0' && *p <= '9') || *p == '_' || IS_HIGHBIT_SET(*p);
-            ++p)
-           ;
+       for (p = s; JSON_ALPHANUMERIC_CHAR(*p); p++)
+           /* skip */ ;
 
-       /*
-        * We got some sort of unexpected punctuation or an otherwise
-        * unexpected character, so just complain about that one character.
-        */
        if (p == s)
        {
+           /*
+            * We got some sort of unexpected punctuation or an otherwise
+            * unexpected character, so just complain about that one
+            * character.
+            */
            lex->token_terminator = s + 1;
            report_invalid_token(lex);
        }
 static void
 json_lex_string(JsonLexContext *lex)
 {
-   char       *s = lex->token_start + 1;
+   char       *s;
 
-   for (s = lex->token_start + 1; *s != '"'; ++s)
+   for (s = lex->token_start + 1; *s != '"'; s++)
    {
        /* Per RFC4627, these characters MUST be escaped. */
        if ((unsigned char) *s < 32)
        else if (*s == '\\')
        {
            /* OK, we have an escape character. */
-           ++s;
+           s++;
            if (*s == '\0')
            {
                lex->token_terminator = s;
                int         i;
                int         ch = 0;
 
-               for (i = 1; i <= 4; ++i)
+               for (i = 1; i <= 4; i++)
                {
                    if (s[i] == '\0')
                    {
                /* Account for the four additional bytes we just parsed. */
                s += 4;
            }
-           else if (!strchr("\"\\/bfnrt", *s))
+           else if (strchr("\"\\/bfnrt", *s) == NULL)
            {
-               /* Error out. */
+               /* Not a valid string escape, so error out. */
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                         errmsg("invalid input syntax for type json"),
 
    /* Part (2): parse main digit string. */
    if (*s == '0')
-       ++s;
+       s++;
    else if (*s >= '1' && *s <= '9')
    {
        do
        {
-           ++s;
+           s++;
        } while (*s >= '0' && *s <= '9');
    }
    else
    /* Part (3): parse optional decimal portion. */
    if (*s == '.')
    {
-       ++s;
+       s++;
        if (*s < '0' || *s > '9')
            error = true;
        else
        {
            do
            {
-               ++s;
+               s++;
            } while (*s >= '0' && *s <= '9');
        }
    }
    /* Part (4): parse optional exponent. */
    if (*s == 'e' || *s == 'E')
    {
-       ++s;
+       s++;
        if (*s == '+' || *s == '-')
-           ++s;
+           s++;
        if (*s < '0' || *s > '9')
            error = true;
        else
        {
            do
            {
-               ++s;
+               s++;
            } while (*s >= '0' && *s <= '9');
        }
    }
 
-   /* Check for trailing garbage. */
-   for (p = s; (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')
-        || (*p >= '0' && *p <= '9') || *p == '_' || IS_HIGHBIT_SET(*p); ++p)
-       ;
+   /*
+    * Check for trailing garbage.  As in json_lex(), any alphanumeric stuff
+    * here should be considered part of the token for error-reporting
+    * purposes.
+    */
+   for (p = s; JSON_ALPHANUMERIC_CHAR(*p); p++)
+       error = true;
    lex->token_terminator = p;
-   if (p > s || error)
+   if (error)
        report_invalid_token(lex);
 }
 
                        lex->input),
                 errdetail("The input string ended unexpectedly.")));
 
-   /* Work out the offending token. */
+   /* Separate out the offending token. */
    toklen = lex->token_terminator - lex->token_start;
    token = palloc(toklen + 1);
    memcpy(token, lex->token_start, toklen);
 }
 
 /*
- * Turn a scalar Datum into JSON. Hand off a non-scalar datum to
- * composite_to_json or array_to_json_internal as appropriate.
+ * Turn a scalar Datum into JSON, appending the string to "result".
+ *
+ * Hand off a non-scalar datum to composite_to_json or array_to_json_internal
+ * as appropriate.
  */
-static inline void
-datum_to_json(Datum val, bool is_null, StringInfo result, TYPCATEGORY tcategory,
-             Oid typoutputfunc)
+static void
+datum_to_json(Datum val, bool is_null, StringInfo result,
+             TYPCATEGORY tcategory, Oid typoutputfunc)
 {
-
    char       *outputstr;
 
    if (is_null)
            outputstr = OidOutputFunctionCall(typoutputfunc, val);
            escape_json(result, outputstr);
            pfree(outputstr);
+           break;
    }
 }
 
                  bool *nulls, int *valcount, TYPCATEGORY tcategory,
                  Oid typoutputfunc, bool use_line_feeds)
 {
-
    int         i;
-   char       *sep;
+   const char *sep;
 
    Assert(dim < ndims);
 
    int         count = 0;
    Datum      *elements;
    bool       *nulls;
-
    int16       typlen;
    bool        typbyval;
    char        typalign,
               *tuple;
    int         i;
    bool        needsep = false;
-   char       *sep;
+   const char *sep;
 
    sep = use_line_feeds ? ",\n " : ",";