diff --git a/src/toolsrc/codegen.c b/src/toolsrc/codegen.c
index a6bb4d4..9177565 100755
--- a/src/toolsrc/codegen.c
+++ b/src/toolsrc/codegen.c
@@ -473,7 +473,7 @@ void emit_idconst(char *name, int value)
 int emit_data(int vartype, int consttype, long constval, int constsize)
 {
     int datasize, i;
-    char *str;
+    unsigned char *str;
     if (consttype == 0)
     {
         datasize = constsize;
@@ -481,9 +481,10 @@ int emit_data(int vartype, int consttype, long constval, int constsize)
     }
     else if (consttype & STRING_TYPE)
     {
-        datasize = constsize;
-        str = (char *)constval;
-        printf("\t%s\t$%02X\n", DB, --constsize);
+        str = (unsigned char *)constval;
+        constsize = *str++;
+        datasize = constsize + 1;
+        printf("\t%s\t$%02X\n", DB, constsize);
         while (constsize-- > 0)
         {
             printf("\t%s\t$%02X", DB, *str++);
@@ -546,10 +547,10 @@ void emit_const(int cval)
     else
         printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval);
 }
-void emit_conststr(long conststr, int strsize)
+void emit_conststr(long conststr)
 {
     printf("\t%s\t$2E\t\t\t; CS\n", DB);
-    emit_data(0, STRING_TYPE, conststr, strsize);
+    emit_data(0, STRING_TYPE, conststr, 0);
 }
 void emit_lb(void)
 {
@@ -908,14 +909,14 @@ void release_seq(t_opseq *seq)
 /*
  * Crunch sequence (peephole optimize)
  */
-int crunch_seq(t_opseq *seq)
+int crunch_seq(t_opseq **seq)
 {
     t_opseq *opnext, *opnextnext;
-    t_opseq *op = seq;
+    t_opseq *op = *seq;
     int crunched = 0;
     int freeops  = 0;
     int shiftcnt;
-    
+
     while (op && (opnext = op->nextop))
     {
         switch (op->code)
@@ -972,26 +973,40 @@ int crunch_seq(t_opseq *seq)
                         op->code  = SAW_CODE;
                         freeops   = 1;
                         break;
-                    case BINARY_CODE(MUL_TOKEN):
-                        for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
+                    case BRFALSE_CODE:
+                        if (op->val)
                         {
-                            if (op->val == (1 << shiftcnt))
-                            {
-                                op->val = shiftcnt;
-                                opnext->code = BINARY_CODE(SHL_TOKEN);
-                                break;
-                            }
+                            opnextnext = opnext->nextop; // Remove never taken branch
+                            if (op == *seq)
+                                *seq = opnextnext;
+                            opnext->nextop = NULL;
+                            release_seq(op);
+                            opnext = opnextnext;
+                            crunched = 1;
+                        }
+                        else
+                        {
+                            op->code = BRNCH_CODE; // Always taken branch
+                            op->tag  = opnext->tag;
+                            freeops  = 1;
                         }
                         break;
-                    case BINARY_CODE(DIV_TOKEN):
-                       for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
+                    case BRTRUE_CODE:
+                        if (!op->val)
                         {
-                            if (op->val == (1 << shiftcnt))
-                            {
-                                op->val = shiftcnt;
-                                opnext->code = BINARY_CODE(SHR_TOKEN);
-                                break;
-                            }
+                            opnextnext = opnext->nextop; // Remove never taken branch
+                            if (op == *seq)
+                                *seq = opnextnext;
+                            opnext->nextop = NULL;
+                            release_seq(op);
+                            opnext = opnextnext;
+                            crunched = 1;
+                        }
+                        else
+                        {
+                            op->code = BRNCH_CODE; // Always taken branch
+                            op->tag  = opnext->tag;
+                            freeops  = 1;
                         }
                         break;
                     case CONST_CODE: // Collapse constant operation
@@ -1072,6 +1087,28 @@ int crunch_seq(t_opseq *seq)
                                     break;
                             }
                         break; // CONST_CODE
+                    case BINARY_CODE(MUL_TOKEN):
+                        for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
+                        {
+                            if (op->val == (1 << shiftcnt))
+                            {
+                                op->val = shiftcnt;
+                                opnext->code = BINARY_CODE(SHL_TOKEN);
+                                break;
+                            }
+                        }
+                        break;
+                    case BINARY_CODE(DIV_TOKEN):
+                       for (shiftcnt = 0; shiftcnt < 16; shiftcnt++)
+                        {
+                            if (op->val == (1 << shiftcnt))
+                            {
+                                op->val = shiftcnt;
+                                opnext->code = BINARY_CODE(SHR_TOKEN);
+                                break;
+                            }
+                        }
+                        break;
                 }
                 break; // CONST_CODE
             case LADDR_CODE:
@@ -1212,11 +1249,10 @@ t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2)
 int emit_seq(t_opseq *seq)
 {
     t_opseq *op;
+    int emitted = 0;
 
-    if (!seq)
-        return (0);
     if (outflags & OPTIMIZE)
-        while (crunch_seq(seq));
+        while (crunch_seq(&seq));
     while (seq)
     {
         op = seq;
@@ -1255,7 +1291,7 @@ int emit_seq(t_opseq *seq)
                 emit_const(op->val);
                 break;
             case STR_CODE:
-                emit_conststr(op->val, op->offsz);
+                emit_conststr(op->val);
                 break;
             case LB_CODE:
                 emit_lb();
@@ -1329,15 +1365,26 @@ int emit_seq(t_opseq *seq)
             case DUP_CODE:
                 emit_dup();
                 break;
+                break;
             case PUSH_EXP_CODE:
                 emit_push_exp();
                 break;
             case PULL_EXP_CODE:
                 emit_pull_exp();
                 break;
+            case BRNCH_CODE:
+                emit_brnch(op->tag);
+                break;
+            case BRFALSE_CODE:
+                emit_brfls(op->tag);
+                break;
+            case BRTRUE_CODE:
+                emit_brtru(op->tag);
+                break;
             default:
                 return (0);
         }
+        emitted++;
         seq = seq->nextop;
         /*
          * Free this op
@@ -1345,5 +1392,5 @@ int emit_seq(t_opseq *seq)
         op->nextop = freeop_lst;
         freeop_lst = op;
     }
-    return (1);
+    return (emitted);
 }
diff --git a/src/toolsrc/codegen.h b/src/toolsrc/codegen.h
index f69c96b..b25f0b4 100755
--- a/src/toolsrc/codegen.h
+++ b/src/toolsrc/codegen.h
@@ -61,11 +61,14 @@ typedef struct _opseq {
 #define DUP_CODE    0x0319
 #define PUSH_EXP_CODE 0x031A
 #define PULL_EXP_CODE 0x031B
+#define BRNCH_CODE  0x031C
+#define BRFALSE_CODE 0x031D
+#define BRTRUE_CODE 0x031E
 
 #define gen_uop(seq,op)     gen_seq(seq,UNARY_CODE(op),0,0,0,0)
 #define gen_op(seq,op)      gen_seq(seq,BINARY_CODE(op),0,0,0,0)
 #define gen_const(seq,val)  gen_seq(seq,CONST_CODE,val,0,0,0)
-#define gen_str(seq,str,len) gen_seq(seq,STR_CODE,str,0,len,0)
+#define gen_str(seq,str)    gen_seq(seq,STR_CODE,str,0,0,0)
 #define gen_lcladr(seq,idx) gen_seq(seq,LADDR_CODE,0,0,idx,0)
 #define gen_gbladr(seq,tag,typ) gen_seq(seq,GADDR_CODE,0,tag,0,typ)
 #define gen_idxb(seq)       gen_seq(seq,ADD_CODE,0,0,0,0)
@@ -78,6 +81,8 @@ typedef struct _opseq {
 #define gen_pushexp(seq)    gen_seq(seq,PUSH_EXP_CODE,0,0,0,0)
 #define gen_pullexp(seq)    gen_seq(seq,PULL_EXP_CODE,0,0,0,0)
 #define gen_drop(seq)       gen_seq(seq,DROP_CODE,0,0,0,0)
+#define gen_brfls(seq,tag)  gen_seq(seq,BRFALSE_CODE,0,tag,0,0)
+#define gen_brtru(seq,tag)  gen_seq(seq,BRTRUE_CODE,0,tag,0,0)
 
 void emit_flags(int flags);
 void emit_header(void);
@@ -94,7 +99,7 @@ void emit_idconst(char *name, int value);
 int emit_data(int vartype, int consttype, long constval, int constsize);
 void emit_codetag(int tag);
 void emit_const(int cval);
-void emit_conststr(long conststr, int strsize);
+void emit_conststr(long conststr);
 void emit_lb(void);
 void emit_lw(void);
 void emit_llb(int index);
@@ -137,7 +142,7 @@ void emit_start(void);
 void emit_rld(void);
 void emit_esd(void);
 void release_seq(t_opseq *seq);
-int crunch_seq(t_opseq *seq);
+int crunch_seq(t_opseq **seq);
 t_opseq *gen_seq(t_opseq *seq, int opcode, long cval, int tag, int offsz, int type);
 t_opseq *cat_seq(t_opseq *seq1, t_opseq *seq2);
 int emit_seq(t_opseq *seq);
diff --git a/src/toolsrc/lex.c b/src/toolsrc/lex.c
index 7319f68..06d87e4 100755
--- a/src/toolsrc/lex.c
+++ b/src/toolsrc/lex.c
@@ -5,7 +5,7 @@
 #include <ctype.h>
 #include "plasm.h"
 
-char *statement, *tokenstr, *scanpos = (char*) "";
+char *statement, *tokenstr, *scanpos = "", *strpos = "";
 t_token scantoken, prevtoken;
 int tokenlen;
 long constval;
@@ -224,68 +224,68 @@ t_token scan(void)
             scanpos += 4;
         }
     }
-    else if ((scanpos[0] & 0x7F) == '\"') // Hack for string quote char in case we have to rewind later
+    else if (scanpos[0] == '\"') // Hack for string quote char in case we have to rewind later
     {
-        char *scanshift, quotechar;
         int scanoffset;
         /*
          * String constant.
          */
-        quotechar = scanpos[0];
-        *scanpos |= 0x80; // Set high bit in case of rewind
-        scantoken = STRING_TOKEN;
-        constval = (long)++scanpos;
-        while (*scanpos &&  *scanpos != quotechar)
+        scantoken   = STRING_TOKEN;
+        constval    = (long)strpos++;
+        scanpos++;
+        while (*scanpos &&  *scanpos != '\"')
         {
             if (*scanpos == '\\')
             {
-                scanoffset = 1;
+                scanoffset = 2;
                 switch (scanpos[1])
                 {
                     case 'n':
-                        *scanpos = 0x0D;
+                        *strpos++ = 0x0D;
                         break;
                     case 'r':
-                        *scanpos = 0x0A;
+                        *strpos++ = 0x0A;
                         break;
                     case 't':
-                        *scanpos = '\t';
+                        *strpos++ = '\t';
                         break;
                     case '\'':
-                        *scanpos = '\'';
+                        *strpos++ = '\'';
                         break;
                     case '\"':
-                        *scanpos = '\"';
+                        *strpos++ = '\"';
                         break;
                     case '\\':
-                        *scanpos = '\\';
+                        *strpos++ = '\\';
                         break;
                     case '0':
-                        *scanpos = '\0';
+                        *strpos++ = '\0';
                         break;
                     case '$':
                         if (hexdigit(scanpos[2]) < 0 || hexdigit(scanpos[3]) < 0) {
                             parse_error("Bad string constant");
                             return (-1);
                         }
-                        *scanpos = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]);
-                        scanoffset = 3;
+                        *strpos++ = hexdigit(scanpos[2]) * 16 + hexdigit(scanpos[3]);
+                        scanoffset = 4;
                         break;
                     default:
                         parse_error("Bad string constant");
                         return (-1);
                 }
-                for (scanshift = scanpos + 1; *scanshift; scanshift++)
-                    scanshift[0] = scanshift[scanoffset];
+                scanpos += scanoffset;
             }
-            scanpos++;
+            else
+                *strpos++ = *scanpos++;
         }
         if (!*scanpos)
         {
             parse_error("Unterminated string");
             return (-1);
         }
-        *scanpos++ |= 0x80; // Set high bit in case of rewind
+        *((unsigned char *)constval) = (long)strpos - constval - 1;
+        *strpos++ = '\0';
+        scanpos++;
     }
     else
     {
@@ -404,30 +404,34 @@ void scan_rewind(char *backptr)
 }
 int scan_lookahead(void)
 {
-    char *backpos  = scanpos;
-    char *backstr  = tokenstr;
+    char *backscan = scanpos;
+    char *backtkn  = tokenstr;
+    char *backstr  = strpos;
     int prevtoken  = scantoken;
-    int prevlen       = tokenlen;
+    int prevlen    = tokenlen;
     int look       = scan();
-    scanpos        = backpos;
-    tokenstr       = backstr;
+    scanpos        = backscan;
+    tokenstr       = backtkn;
+    strpos         = backstr;
     scantoken      = prevtoken;
     tokenlen       = prevlen;
     return (look);
 }
 char inputline[512];
+char conststr[1024];
 int next_line(void)
 {
     int len;
     t_token token;
     char* new_filename;
+    strpos = conststr;
     if (inputfile == NULL)
     {
         /*
          * First-time init
          */
         inputfile = stdin;
-        filename = (char*) "<stdin>";
+        filename = "<stdin>";
     }
     if (*scanpos == ';')
     {
@@ -491,9 +495,8 @@ int next_line(void)
         outer_inputfile = inputfile;
         outer_filename = filename;
         outer_lineno = lineno;
-        new_filename = (char*) malloc(tokenlen-1);
-        strncpy(new_filename, (char*)constval, tokenlen-2);
-        new_filename[tokenlen-2] = 0;
+        new_filename = (char *) malloc(*((unsigned char *)constval) + 1);
+        strncpy(new_filename, (char *)(constval + 1), *((unsigned char *)constval) + 1);
         inputfile = fopen(new_filename, "r");
         if (inputfile == NULL)
         {
diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c
index d3191cd..943de13 100755
--- a/src/toolsrc/parse.c
+++ b/src/toolsrc/parse.c
@@ -220,7 +220,7 @@ int parse_constval(void)
         case CLOSE_PAREN_TOKEN:
             break;
         case STRING_TOKEN:
-            size  = tokenlen - 1;
+            size  = 1;
             value = constval;
             type  = STRING_TYPE;
             if (mod)
@@ -412,7 +412,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth)
         /*
          * This is a special case. Just emit the string and return
          */
-        codeseq = gen_str(codeseq, constval, tokenlen - 1);
+        codeseq = gen_str(codeseq, constval);
         scan();
         return (codeseq);
     }
@@ -487,7 +487,7 @@ t_opseq *parse_value(t_opseq *codeseq, int rvalue, int *stackdepth)
             }
             else
                 scan_rewind(tokenstr);
-            if (cfnparms && (cfnparms != value))
+            if ((type & FUNC_TYPE) && (cfnparms != value))
                 parse_warn("Parameter count mismatch");
             if (stackdepth)
                 *stackdepth = cfnvals + cfnparms - value;
@@ -766,6 +766,7 @@ int parse_stmnt(void)
     int tag_prevbrk, tag_prevcnt, tag_else, tag_endif, tag_while, tag_wend, tag_repeat, tag_for, tag_choice, tag_of;
     int type, addr, step, cfnvals;
     char *idptr;
+    t_opseq *seq;
 
     /*
      * Optimization for last function LEAVE and OF clause.
@@ -775,14 +776,15 @@ int parse_stmnt(void)
     switch (scantoken)
     {
         case IF_TOKEN:
-            if (!emit_seq(parse_expr(NULL, NULL)))
+            if (!(seq = parse_expr(NULL, NULL)))
             {
                 parse_error("Bad expression");
                 return (0);
             }
             tag_else  = tag_new(BRANCH_TYPE);
             tag_endif = tag_new(BRANCH_TYPE);
-            emit_brfls(tag_else);
+            seq = gen_brfls(seq, tag_else);
+            emit_seq(seq);
             scan();
             do
             {
@@ -791,13 +793,14 @@ int parse_stmnt(void)
                     break;
                 emit_brnch(tag_endif);
                 emit_codetag(tag_else);
-                if (!emit_seq(parse_expr(NULL, NULL)))
+                if (!(seq = parse_expr(NULL, NULL)))
                 {
                     parse_error("Bad expression");
                     return (0);
                 }
                 tag_else = tag_new(BRANCH_TYPE);
-                emit_brfls(tag_else);
+                seq = gen_brfls(seq, tag_else);
+                emit_seq(seq);
             } while (1);
             if (scantoken == ELSE_TOKEN)
             {
@@ -826,13 +829,14 @@ int parse_stmnt(void)
             tag_prevbrk = break_tag;
             break_tag   = tag_wend;
             emit_codetag(tag_while);
-            if (!emit_seq(parse_expr(NULL, NULL)))
+            if (!(seq = parse_expr(NULL, NULL)))
             {
                 parse_error("Bad expression");
                 return (0);
             }
-            emit_brfls(tag_wend);
-            while (parse_stmnt()) next_line();
+            seq = gen_brfls(seq, tag_wend);
+            emit_seq(seq);
+                while (parse_stmnt()) next_line();
             if (scantoken != LOOP_TOKEN)
             {
                 parse_error("Missing WHILE/END");
@@ -859,12 +863,13 @@ int parse_stmnt(void)
             }
             emit_codetag(cont_tag);
             cont_tag = tag_prevcnt;
-            if (!emit_seq(parse_expr(NULL, NULL)))
+            if (!(seq = parse_expr(NULL, NULL)))
             {
                 parse_error("Bad expression");
                 return (0);
             }
-            emit_brfls(tag_repeat);
+            seq = gen_brfls(seq, tag_repeat);
+            emit_seq(seq);
             emit_codetag(break_tag);
             break_tag = tag_prevbrk;
             break;