diff --git a/src/cpp.c b/src/cpp.c
index 01715a6d1001676c3e215c3a61cb4cd696c174bb..2dc2891a3bc2223abc0bf189bd7d108c4b618ce6 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -1314,13 +1314,6 @@ static ptrdiff_t find_end_of_char( struct cpp *this, const PCHARP data, ptrdiff_
       cpp_error(this,"End of file in character constant.");
       break;
     }
-
-    if(e++>32)
-    {
-      cpp_error(this,"Too long character constant.");
-      break;
-    }
-
     switch(INDEX_PCHARP(data,pos++))
     {
     case '\n':
diff --git a/src/lexer.h b/src/lexer.h
index 4a588369c13cdb48fbb841ea920a7841996cc2b0..57f1bf22d6fb987870cbe0087e19b3d2a08b88c9 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -842,8 +842,10 @@ unknown_directive:
 
     case '\'':
       {
-        int l = 0;
-        INT_TYPE res = 0;
+        unsigned int l = 0;
+        struct svalue res = svalue_int_zero;
+        MP_INT bigint;
+
         while(1)
         {
           INT32 tmp;
@@ -858,16 +860,24 @@ unknown_directive:
               tmp = char_const(lex);
               /* fallthrough. */
             default:
-              res <<= 8;
-              res |= tmp;
-              if( ++l > 4 )
+              l++;
+              if( l == sizeof(INT_TYPE)-1 )
+              {
+                /* overflow possible. Switch to bignums. */
+                mpz_init(&bigint);
+                mpz_set_ui(&bigint,res.u.integer);
+                TYPEOF(res) = PIKE_T_OBJECT;
+              }
+
+              if( l >= sizeof(INT_TYPE)-1 )
               {
-                yyerror("Too large character constant.");
-                /* skip the rest of the characters. */
-                do
-                  tmp = GETC();
-                while( tmp && (tmp != '\'') );
-                goto return_char;
+                mpz_mul_2exp(&bigint,&bigint,8);
+                mpz_add_ui(&bigint,&bigint,tmp);
+              }
+              else
+              {
+                res.u.integer <<= 8;
+                res.u.integer |= tmp;
               }
               break;
 
@@ -878,7 +888,15 @@ unknown_directive:
           }
         }
       return_char:
-        debug_malloc_pass( yylval->n=mkintnode(res) );
+        if( TYPEOF(res) == PIKE_T_OBJECT )
+        {
+          push_bignum( &bigint );
+          mpz_clear(&bigint);
+          reduce_stack_top_bignum();
+          res = *--Pike_sp;
+        }
+        debug_malloc_pass( yylval->n=mksvaluenode(&res) );
+        free_svalue( &res );
         return TOK_NUMBER;
       }
       /* notreached. */