override public Token token()
        {
            for (;;)
            {
                /* Deal with lexed tokens first. */

                if (arg != null)
                {
                    if (arg.hasNext())
                    {
                        Token tok2 = arg.next();
                        /* XXX PASTE -> INVALID. */
                        Debug.Assert(tok2.getType() != Token.M_PASTE,
                                     "Unexpected paste token");
                        return(tok2);
                    }
                    arg = null;
                }

                if (!tokens.hasNext())
                {
                    return(new Token(Token.EOF, -1, -1, ""));                   /* End of macro. */
                }
                Token tok = tokens.next();
                int   idx;
                switch (tok.getType())
                {
                case Token.M_STRING:
                    /* Use the nonexpanded arg. */
                    idx = (int)tok.getValue();
                    return(stringify(tok, args.get(idx)));

                case Token.M_ARG:
                    /* Expand the arg. */
                    idx = (int)tok.getValue();
                    // System.out.println("Pushing arg " + args.get(idx));
                    arg = args.get(idx).expansion();
                    break;

                case Token.M_PASTE:
                    paste(tok);
                    break;

                default:
                    return(tok);
                }
            }     /* for */
        }
        /* At this point, we have consumed the first M_PASTE.
         * @see Macro#addPaste(Token) */
        private void paste(Token ptok)
        {
            StringBuilder buf = new StringBuilder();
            Token         err = null;

            /* We know here that arg is null or expired,
             * since we cannot paste an expanded arg. */

            int count = 2;

            for (int i = 0; i < count; i++)
            {
                if (!tokens.hasNext())
                {
                    /* XXX This one really should throw. */
                    error(ptok.getLine(), ptok.getColumn(),
                          "Paste at end of expansion");
                    buf.append(' ').append(ptok.getText());
                    break;
                }
                Token tok = tokens.next();
                // System.out.println("Paste " + tok);
                switch (tok.getType())
                {
                case Token.M_PASTE:
                    /* One extra to paste, plus one because the
                     * paste token didn't count. */
                    count += 2;
                    ptok   = tok;
                    break;

                case Token.M_ARG:
                    int idx = (int)tok.getValue();
                    concat(buf, args.get(idx));
                    break;

                /* XXX Test this. */
                case Token.CCOMMENT:
                case Token.CPPCOMMENT:
                    break;

                default:
                    buf.append(tok.getText());
                    break;
                }
            }

            /* Push and re-lex. */

            /*
             * StringBuilder		src = new StringBuilder();
             * escape(src, buf);
             * StringLexerSource	sl = new StringLexerSource(src.toString());
             */
            StringLexerSource sl = new StringLexerSource(buf.toString());

            /* XXX Check that concatenation produces a valid token. */

            arg = new SourceIterator(sl);
        }