diff --git a/src/lexer.h b/src/lexer.h
index 9540487e7c623c2d871f09d062044e9d2b87eee6..18edf75bd8fb4ec911c43953852ffc2b3c644e6a 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -815,30 +815,17 @@ static int low_yylex(struct lex *lex, YYSTYPE *yylval)
 
       default:
 unknown_directive:
-	/* FIXME: This doesn't look all that safe...
-	 * buf isn't NUL-terminated, and it won't work on wide strings.
-	 * /grubba 1999-02-20
-	 * It also modified a shared string... ie. this code was not
-	 * good at all. Fixed.
-	 * /grubba 2000-11-19 (in Versailles)
-	 */
 	if (len < 256) {
 #if (SHIFT == 0)
 	  struct pike_string *dir =
 	    make_shared_binary_string(buf, len);
-#else /* SHIFT != 0 */
-#if (SHIFT == 1)
+#elif (SHIFT == 1)
 	  struct pike_string *dir =
 	    make_shared_binary_string1((p_wchar1 *)buf, len);
-#else /* SHIFT != 1 */
-#if (SHIFT == 2)
+#elif (SHIFT == 2)
 	  struct pike_string *dir =
 	    make_shared_binary_string2((p_wchar2 *)buf, len);
-#else /* SHIFT != 2 */
-#error Unsupported SHIFT.
-#endif /* SHIFT == 2 */
-#endif /* SHIFT == 1 */
-#endif /* SHIFT == 0 */
+#endif
 	  my_yyerror("Unknown preprocessor directive %S.", dir);
 	  free_string(dir);
 	} else {
@@ -854,27 +841,47 @@ unknown_directive:
       continue;
 
     case '\'':
-      switch(c=GETC())
       {
-      case 0:
-	lex->pos -= (1<<SHIFT);
-	yyerror("Unexpected end of file\n");
-	break;
-
-      case '\\':
-	c = char_const(lex);
-	break;
+        int l = 0;
+        INT_TYPE res = 0;
+        while(1)
+        {
+          INT32 tmp;
+          switch( (tmp=GETC()) )
+          {
+            case 0:
+              lex->pos -= (1<<SHIFT);
+              yyerror("Unexpected end of file\n");
+              goto return_char;
+
+            case '\\':
+              tmp = char_const(lex);
+              /* fallthrough. */
+            default:
+              res <<= 8;
+              res |= tmp;
+              if( ++l > 8 )
+              {
+                yyerror("Too large character constant.");
+                /* skip the rest of the characters. */
+                do
+                  tmp = GETC();
+                while( tmp && (tmp != '\'') );
+                goto return_char;
+              }
+              break;
 
-      case '\'':
-	yyerror("Zero-length character constant.");
-	debug_malloc_pass( yylval->n=mkintnode(0) );
-	return TOK_NUMBER;
+            case '\'':
+              if( l == 0 )
+                yyerror("Zero-length character constant.");
+              goto return_char;
+          }
+        }
+      return_char:
+        debug_malloc_pass( yylval->n=mkintnode(res) );
+        return TOK_NUMBER;
       }
-      if(!GOBBLE('\''))
-	yyerror("Unterminated character constant.");
-      debug_malloc_pass( yylval->n=mkintnode(c) );
-      return TOK_NUMBER;
-	
+      /* notreached. */
     case '"':
     {
       struct pike_string *s=readstring(lex);
@@ -882,7 +889,7 @@ unknown_directive:
       free_string(s);
       return TOK_STRING;
     }
-  
+
     case ':':
       if(GOBBLE(':')) return TOK_COLON_COLON;
       return c;