+static void FuncConcat (void)
+/* Handle the .CONCAT function */
+{
+ char Buf[MAX_STR_LEN+1];
+ char* B;
+ unsigned Length;
+ unsigned L;
+
+ /* Skip it */
+ NextTok ();
+
+ /* Left paren expected */
+ ConsumeLParen ();
+
+ /* Concatenate any number of strings */
+ B = Buf;
+ B[0] = '\0';
+ Length = 0;
+ while (1) {
+
+ /* Next token must be a string */
+ if (Tok != TOK_STRCON) {
+ Error (ERR_STRCON_EXPECTED);
+ SkipUntilSep ();
+ return;
+ }
+
+ /* Get the length of the string const and check total length */
+ L = strlen (SVal);
+ if (Length + L > MAX_STR_LEN) {
+ Error (ERR_STRING_TOO_LONG);
+ /* Try to recover */
+ SkipUntilSep ();
+ return;
+ }
+
+ /* Add the new string */
+ memcpy (B, SVal, L);
+ Length += L;
+ B += L;
+
+ /* Skip the string token */
+ NextTok ();
+
+ /* Comma means another argument */
+ if (Tok == TOK_COMMA) {
+ NextTok ();
+ } else {
+ /* Done */
+ break;
+ }
+ }
+
+ /* Terminate the string */
+ *B = '\0';
+
+ /* We expect a closing parenthesis, but will not skip it but replace it
+ * by the string token just created.
+ */
+ if (Tok != TOK_RPAREN) {
+ Error (ERR_RPAREN_EXPECTED);
+ } else {
+ Tok = TOK_STRCON;
+ strcpy (SVal, Buf);
+ }
+}
+
+
+
+static void FuncLeft (void)
+/* Handle the .LEFT function */
+{
+ long Count;
+ TokList* List;
+
+ /* Skip it */
+ NextTok ();
+
+ /* Left paren expected */
+ ConsumeLParen ();
+
+ /* Count argument */
+ Count = ConstExpression ();
+ if (Count < 0 || Count > 100) {
+ Error (ERR_RANGE);
+ Count = 1;
+ }
+ ConsumeComma ();
+
+ /* Read the token list */
+ List = CollectTokens (0, (unsigned) Count);
+
+ /* Since we want to insert the list before the now current token, we have
+ * to save the current token in some way and then skip it. To do this, we
+ * will add the current token at the end of the token list (so the list
+ * will never be empty), push the token list, and then skip the current
+ * token. This will replace the current token by the first token from the
+ * list (which will be the old current token in case the list was empty).
+ */
+ AddCurTok (List);
+
+ /* Insert it into the scanner feed */
+ PushTokList (List, ".LEFT");
+
+ /* Skip the current token */
+ NextTok ();
+}
+
+
+