root/eaccelerator/tags/0.9.3/encoder.c

Revision 57, 37.5 kB (checked in by segv74, 4 years ago)

bug fix for 1091815 ( Encoded files and php4.3.10 )
- not much tested yet.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2    +----------------------------------------------------------------------+
3    | eAccelerator project                                                 |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 2004 eAccelerator                                      |
6    | http://eaccelerator.sourceforge.net                                  |
7    +----------------------------------------------------------------------+
8    | This program is free software; you can redistribute it and/or        |
9    | modify it under the terms of the GNU General Public License          |
10    | as published by the Free Software Foundation; either version 2       |
11    | of the License, or (at your option) any later version.               |
12    |                                                                      |
13    | This program is distributed in the hope that it will be useful,      |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16    | GNU General Public License for more details.                         |
17    |                                                                      |
18    | You should have received a copy of the GNU General Public License    |
19    | along with this program; if not, write to the Free Software          |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21    | MA  02111-1307, USA.                                                 |
22    |                                                                      |
23    | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24    +----------------------------------------------------------------------+
25    | Author(s): Dmitry Stogov <dstogov@users.sourceforge.net>             |
26    +----------------------------------------------------------------------+
27    $Id$
28 */
29
30 #include "eaccelerator.h"
31 #include "eaccelerator_version.h"
32
33 #ifdef HAVE_EACCELERATOR
34 #ifdef WITH_EACCELERATOR_ENCODER
35
36 #include "opcodes.h"
37 #include "zend.h"
38 #include "zend_API.h"
39 #include "php.h"
40 #include <math.h>
41
42 #ifndef WITHOUT_FILE_FILTER
43 #define IEQ(need)  (ch == (need) || \
44                     ((need) >= 'a' && (need) <= 'z' && ch == ((need)-'a'+'A')))
45
46 #define SKIP_WHITESPACES() do {\
47                              ch = fgetc(yyin);\
48                              while (ch == ' ' || ch == '\t' ||\
49                                     ch == '\r' || ch == '\n') {\
50                                fputc(ch,yyout);\
51                                ch = fgetc(yyin);\
52                              }\
53                            } while(0)
54
55 static void filter_script(FILE *yyin, FILE *yyout TSRMLS_DC) {
56   register int ch = EOF;
57   int repeat = 0;
58   int allow = 1;
59
60   int label_len, pos;
61   char label[256];
62
63   while (1) {
64     if (!repeat) {
65       ch = fgetc(yyin);
66     } else {
67       repeat = 0;
68     }
69     if (ch == EOF) break;
70     fputc(ch,yyout);
71     if (ch == '\'' || ch == '"' || ch == '`') {
72       /* skip strings */
73       register int start = ch;
74       do {
75         ch = fgetc(yyin);
76         if (ch == EOF) break;
77         fputc(ch,yyout);
78         if (ch == '\\') {
79           ch = fgetc(yyin);
80           if (ch == EOF) break;
81           fputc(ch,yyout);
82           ch = fgetc(yyin);
83           if (ch == EOF) break;
84           fputc(ch,yyout);
85         }
86       } while (ch != start);
87       allow = 1;
88     } else if (ch == '#') {
89       /* skip one line comments */
90 one_line_comment:
91       do {
92         ch = fgetc(yyin);
93         if (ch == EOF) break;
94         fputc(ch,yyout);
95       } while (ch != '\r' && ch != '\n');
96       allow = 1;
97     } else if (ch == '/') {
98       ch = fgetc(yyin);
99       if (ch == EOF) break;
100       if (ch == '/') {
101         fputc(ch,yyout);
102         /* skip one line comments */
103         goto one_line_comment;
104       } else if (ch == '*') {
105         fputc(ch,yyout);
106         /* skip multiline comments */
107         while (1) {
108           do {
109             ch = fgetc(yyin);
110             if (ch == EOF) break;
111             fputc(ch,yyout);
112           } while (ch != '*');
113           if (ch == EOF) break;
114           while (ch == '*') {
115             ch = fgetc(yyin);
116             if (ch == EOF) break;
117             fputc(ch,yyout);
118           }
119           if (ch == EOF || ch == '/') break;
120         }
121       } else {
122         repeat = 1;
123       }
124       allow = 1;
125     } else if (ch == '?' || (ch == '%' && CG(asp_tags))) {
126       /* end of script */
127       ch = fgetc(yyin);
128       if (ch == EOF) break;
129       if (ch == '>') {
130         fputc(ch,yyout);
131         return;
132       } else {
133         repeat = 1;
134       }
135       allow = 1;
136     } else if (ch == '<') {
137       repeat = 1;
138       /* </script> */
139       ch = fgetc(yyin);
140       if (ch == EOF) break;
141       if (ch == '/') {
142         fputc(ch,yyout);
143         ch = fgetc(yyin);
144         if (ch == EOF) break;
145         if (IEQ('s')) {
146           fputc(ch,yyout);
147           ch = fgetc(yyin);
148           if (ch == EOF) break;
149           if (IEQ('c')) {
150             fputc(ch,yyout);
151             ch = fgetc(yyin);
152             if (ch == EOF) break;
153             if (IEQ('r')) {
154               fputc(ch,yyout);
155               ch = fgetc(yyin);
156               if (ch == EOF) break;
157               if (IEQ('i')) {
158                 fputc(ch,yyout);
159                 ch = fgetc(yyin);
160                 if (ch == EOF) break;
161                 if (IEQ('p')) {
162                   fputc(ch,yyout);
163                   ch = fgetc(yyin);
164                   if (ch == EOF) break;
165                   if (IEQ('t')) {
166                     fputc(ch,yyout);
167                     SKIP_WHITESPACES();
168                     if (ch == '>') {
169                       fputc(ch,yyout);
170                       return;
171                     }
172                   }
173                 }
174               }
175             }
176           }
177         }
178       } else if (ch == '<') {
179         repeat = 1;
180         fputc(ch,yyout);
181         ch = fgetc(yyin);
182         if (ch == EOF) break;
183         if (ch == '<') {
184           /* heredoc */
185           fputc(ch,yyout);
186           do {
187             ch = fgetc(yyin);
188             if (ch == EOF) break;
189             fputc(ch,yyout);
190           } while (ch == '\t' || ch == ' ');
191           if ((ch >= 'a' && ch <= 'z') ||
192               (ch >= 'A' && ch <= 'Z') ||
193               ch == '_' ||
194               (ch >= '\x7f' && ch <= '\xff')) {
195             label[0] = ch;
196             label_len = 1;
197             while(1) {
198               ch = fgetc(yyin);
199               if (ch == EOF) break;
200               fputc(ch,yyout);
201               if ((ch >= 'a' && ch <= 'z') ||
202                   (ch >= 'A' && ch <= 'Z') ||
203                   (ch >= '0' && ch <= '9') ||
204                   ch == '_' ||
205                   (ch >= '\x7f' && ch <= '\xff')) {
206                 label[label_len] = ch;
207                 label_len++;
208                 if (label_len >= sizeof(label)-1) break;
209               } else {
210                 break;
211               }
212             }
213             if (ch == '\r' || ch =='\n') {
214               label[label_len] = '\000';
215               while (1) {
216                 if (ch == '\r' || ch == '\n') {
217                   ch = fgetc(yyin);
218                   if (ch == EOF) break;
219                   fputc(ch,yyout);
220                   pos = 0;
221                   while (1) {
222                     if (pos == label_len && ch == ';') {
223                       ch = fgetc(yyin);
224                       if (ch == EOF) break;
225                       fputc(ch,yyout);
226                     }
227                     if (pos == label_len && (ch == '\r' || ch == '\n')) {
228                       break;
229                     }
230                     if (pos > label_len || label[pos] != ch) {
231                       break;
232                     }
233                     pos++;
234                     ch = fgetc(yyin);
235                     if (ch == EOF) break;
236                     fputc(ch,yyout);
237                   }
238                   if (pos == label_len && (ch == '\r' || ch == '\n')) {
239                     break;
240                   }
241                 } else {
242                   ch = fgetc(yyin);
243                   if (ch == EOF) break;
244                   fputc(ch,yyout);
245                 }
246               }
247             }
248           }
249           repeat = 0;
250         }
251       }
252       allow = 1;
253     } else if (allow && ch == '_') {
254       label[0] = ch = fgetc(yyin);
255       if (ch == EOF) {break;}
256       if (ch == '_') {
257         label[1] = ch = fgetc(yyin);
258         if (ch == EOF) {fwrite(label,1,1,yyout); break;}
259         if (IEQ('f')) {
260           label[2] = ch = fgetc(yyin);
261           if (ch == EOF) {fwrite(label,2,1,yyout); break;}
262           if (IEQ('i')) {
263             label[3] = ch = fgetc(yyin);
264             if (ch == EOF) {fwrite(label,3,1,yyout); break;}
265             if (IEQ('l')) {
266               label[4] = ch = fgetc(yyin);
267               if (ch == EOF) {fwrite(label,4,1,yyout); break;}
268               if (IEQ('e')) {
269                 label[5] = ch = fgetc(yyin);
270                 if (ch == EOF) {fwrite(label,5,1,yyout); break;}
271                 if (ch == '_') {
272                   label[6] = ch = fgetc(yyin);
273                   if (ch == EOF) {fwrite(label,6,1,yyout); break;}
274                   if (ch == '_') {
275                     ch = fgetc(yyin);
276                     repeat = 1;
277                     if ((ch >= 'a' && ch <= 'z') ||
278                         (ch >= 'A' && ch <= 'Z') ||
279                         (ch >= '0' && ch <= '9') ||
280                         (ch >= '\x7f' && ch <= '\xff') ||
281                         ch == '_') {
282                       fwrite(label,7,1,yyout);
283                     } else {
284                       fputs("eaccelerator_loader_file()",yyout);
285                     }
286                   } else {
287                     fwrite(label,7,1,yyout);
288                   }
289                 } else {
290                   fwrite(label,6,1,yyout);
291                 }
292               } else {
293                 fwrite(label,5,1,yyout);
294               }
295             } else {
296               fwrite(label,4,1,yyout);
297             }
298           } else {
299             fwrite(label,3,1,yyout);
300           }
301         } else if (IEQ('l')) {
302           label[2] = ch = fgetc(yyin);
303           if (ch == EOF) {fwrite(label,2,1,yyout); break;}
304           if (IEQ('i')) {
305             label[3] = ch = fgetc(yyin);
306             if (ch == EOF) {fwrite(label,3,1,yyout); break;}
307             if (IEQ('n')) {
308               label[4] = ch = fgetc(yyin);
309               if (ch == EOF) {fwrite(label,4,1,yyout); break;}
310               if (IEQ('e')) {
311                 label[5] = ch = fgetc(yyin);
312                 if (ch == EOF) {fwrite(label,5,1,yyout); break;}
313                 if (ch == '_') {
314                   label[6] = ch = fgetc(yyin);
315                   if (ch == EOF) {fwrite(label,6,1,yyout); break;}
316                   if (ch == '_') {
317                     ch = fgetc(yyin);
318                     repeat = 1;
319                     if ((ch >= 'a' && ch <= 'z') ||
320                         (ch >= 'A' && ch <= 'Z') ||
321                         (ch >= '0' && ch <= '9') ||
322                         (ch >= '\x7f' && ch <= '\xff') ||
323                         ch == '_') {
324                       fwrite(label,7,1,yyout);
325                     } else {
326                       fputs("eaccelerator_loader_line()",yyout);
327                     }
328                   } else {
329                     fwrite(label,7,1,yyout);
330                   }
331                 } else {
332                   fwrite(label,6,1,yyout);
333                 }
334               } else {
335                 fwrite(label,5,1,yyout);
336               }
337             } else {
338               fwrite(label,4,1,yyout);
339             }
340           } else {
341             fwrite(label,3,1,yyout);
342           }
343         } else {
344           fwrite(label,2,1,yyout);
345         }
346       } else {
347         fwrite(label,1,1,yyout);
348       }
349       allow = 0;
350     } else if ((ch >= 'a' && ch <= 'z') ||
351                (ch >= 'A' && ch <= 'Z') ||
352                (ch >= '\x7f' && ch <= '\xff') ||
353                ch == '_' || ch == '$') {
354       allow = 0;
355     } else if (ch == '-') {
356       ch = fgetc(yyin);
357       if (ch == EOF) break;
358       if (ch == '>') {
359         fputc(ch,yyout);
360         allow = 0;
361       } else {
362         repeat = 1;
363         allow = 1;
364       }
365     } else {
366       allow = 1;
367     }
368   }
369 }
370
371 static void filter_file(FILE *yyin, FILE *yyout TSRMLS_DC) {
372   register int ch = EOF;
373   int repeat = 0;
374
375   while (1) {
376     if (!repeat) {
377       ch = fgetc(yyin);
378     } else {
379       repeat = 0;
380     }
381     if (ch == EOF) break;
382     fputc(ch,yyout);
383     if (ch == '<') {
384       ch = fgetc(yyin);
385       if (ch == EOF) break;
386       if (ch == '?') {
387         fputc(ch,yyout);
388         if (CG(short_tags)) {
389           filter_script(yyin, yyout TSRMLS_CC);
390         } else {
391           repeat = 1;
392           ch = fgetc(yyin);
393           if (ch == EOF) break;
394           if (IEQ('p')) {
395             fputc(ch,yyout);
396             ch = fgetc(yyin);
397             if (ch == EOF) break;
398             if (IEQ('h')) {
399               fputc(ch,yyout);
400               ch = fgetc(yyin);
401               if (ch == EOF) break;
402               if (IEQ('p')) {
403                 fputc(ch,yyout);
404                 ch = fgetc(yyin);
405                 if (ch == EOF) break;
406                 if (ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t') {
407                   fputc(ch,yyout);
408                   filter_script(yyin, yyout TSRMLS_CC);
409                   repeat = 0;
410                 }
411               }
412             }
413           }
414         }
415       } else if (ch == '%' && CG(asp_tags)) {
416         fputc(ch,yyout);
417         filter_script(yyin, yyout TSRMLS_CC);
418       } else if (IEQ('s')) {
419         repeat = 1;
420         fputc(ch,yyout);
421         ch = fgetc(yyin);
422         if (ch == EOF) break;
423         if (IEQ('c')) {
424           fputc(ch,yyout);
425           ch = fgetc(yyin);
426           if (ch == EOF) break;
427           if (IEQ('r')) {
428             fputc(ch,yyout);
429             ch = fgetc(yyin);
430             if (ch == EOF) break;
431             if (IEQ('i')) {
432               fputc(ch,yyout);
433               ch = fgetc(yyin);
434               if (ch == EOF) break;
435               if (IEQ('p')) {
436                 fputc(ch,yyout);
437                 ch = fgetc(yyin);
438                 if (ch == EOF) break;
439                 if (IEQ('t')) {
440                   fputc(ch,yyout);
441                   SKIP_WHITESPACES();
442                   if (ch == EOF) break;
443                   if (IEQ('l')) {
444                     fputc(ch,yyout);
445                     ch = fgetc(yyin);
446                     if (ch == EOF) break;
447                     if (IEQ('a')) {
448                       fputc(ch,yyout);
449                       ch = fgetc(yyin);
450                       if (ch == EOF) break;
451                       if (IEQ('n')) {
452                         fputc(ch,yyout);
453                         ch = fgetc(yyin);
454                         if (ch == EOF) break;
455                         if (IEQ('g')) {
456                           fputc(ch,yyout);
457                           ch = fgetc(yyin);
458                           if (ch == EOF) break;
459                           if (IEQ('u')) {
460                             fputc(ch,yyout);
461                             ch = fgetc(yyin);
462                             if (ch == EOF) break;
463                             if (IEQ('a')) {
464                               fputc(ch,yyout);
465                               ch = fgetc(yyin);
466                               if (ch == EOF) break;
467                               if (IEQ('g')) {
468                                 fputc(ch,yyout);
469                                 ch = fgetc(yyin);
470                                 if (ch == EOF) break;
471                                 if (IEQ('e')) {
472                                   register int start = '\000';
473                                   fputc(ch,yyout);
474                                   SKIP_WHITESPACES();
475                                   if (ch == EOF) break;
476                                   if (ch == '=') {
477                                     fputc(ch,yyout);
478                                     SKIP_WHITESPACES();
479                                     if (ch == EOF) break;
480                                     if (ch == '\'' || ch == '"') {
481                                       fputc(ch,yyout);
482                                       start = ch;
483                                       ch = fgetc(yyin);
484                                       if (ch == EOF) break;
485                                     }
486                                     if (IEQ('p')) {
487                                       fputc(ch,yyout);
488                                       ch = fgetc(yyin);
489                                       if (ch == EOF) break;
490                                       if (IEQ('h')) {
491                                         fputc(ch,yyout);
492                                         ch = fgetc(yyin);
493                                         if (ch == EOF) break;
494                                         if (IEQ('p')) {
495                                           fputc(ch,yyout);
496                                           if (start != '\000') {
497                                             ch = fgetc(yyin);
498                                             if (ch == EOF) break;
499                                             if (ch == start) {
500                                               fputc(ch,yyout);
501                                               start = '\000';
502                                             }
503                                           }
504                                           if (start == '\000') {
505                                             SKIP_WHITESPACES();
506                                             if (ch == '>') {
507                                               fputc(ch,yyout);
508                                               filter_script(yyin, yyout TSRMLS_CC);
509                                               repeat = 0;
510                                             }
511                                           }
512                                         }
513                                       }
514                                     }
515                                   }
516                                 }
517                               }
518                             }
519                           }
520                         }
521                       }
522                     }
523                   }
524                 }
525               }
526             }
527           }
528         }
529       } else {
530         repeat = 1;
531       }
532     }
533   }
534 }
535 #endif
536
537 static inline void encode(unsigned char c) {
538   zend_write((char*)&c, 1);
539 }
540
541 static inline void encode32(unsigned int i) {
542   encode((unsigned char)(i & 0xff));
543   encode((unsigned char)((i >> 8) & 0xff));
544   encode((unsigned char)((i >> 16) & 0xff));
545   encode((unsigned char)((i >> 24) & 0xff));
546 }
547
548 static inline void encode16(unsigned short i) {
549   encode((unsigned char)(i & 0xff));
550   encode((unsigned char)((i >> 8) & 0xff));
551 }
552
553 static void encode_var(unsigned int var, unsigned int count) {
554   unsigned int v = VAR_NUM(var);
555   if (v >= count) {
556     zend_bailout();
557   }
558   if (count < 0xff) {
559     encode((unsigned char)v);
560   } else if (count < 0xffff) {
561     encode16((unsigned short)v);
562   } else {
563     encode32(v);
564   }
565 }
566
567 static void encode_opline(unsigned int opline, unsigned int last) {
568   if (opline >= last && opline != (unsigned int)-1) {
569     zend_bailout();
570   }
571   if (last < 0xff-1) {
572     encode((unsigned char)opline);
573   } else if (last < 0xffff-1) {
574     encode16((unsigned short)opline);
575   } else {
576     encode32(opline);
577   }
578 }
579
580 static void encode_zstr(const char* str) {
581   if (str != NULL) {
582     int len = strlen(str);
583     ZEND_WRITE(str,len+1);
584   } else {
585     encode(0);
586   }
587 }
588
589 static void encode_lstr(const char* str, unsigned int len) {
590   if (str != NULL && len > 0) {
591     encode32(len);
592     ZEND_WRITE(str,len);
593   } else {
594     encode32(0);
595   }
596 }
597
598 static inline void encode_pstr(const unsigned char* str) {
599   if (str != NULL) {
600     unsigned int len = str[0];
601     ZEND_WRITE((const char*)str,len+1);
602   } else {
603     encode(0);
604   }
605 }
606
607 static void encode_double(double d) {
608   char sign = 0;
609   int  exp;
610   unsigned long i1, i2;
611
612   if (d < 0.0) {
613     sign = 1;
614     d = -d;
615   }
616   d = frexp(d, &exp);
617   d = d * 4294967296.0;
618   i1 = (unsigned long)floor(d);
619   d = (d - i1) * 4294967296.0;
620   i2 = (unsigned long)floor(d);
621
622   encode(sign);
623   encode32(exp);
624   encode32(i1);
625   encode32(i2);
626 }
627
628 typedef void (*encode_bucket_t)(void*);
629
630 #define encode_zval_hash(from) encode_hash(from, (encode_bucket_t)encode_zval_ptr)
631
632 static void encode_zval_ptr(zval** from);
633 static void encode_hash(HashTable* from, encode_bucket_t encode_bucket);
634
635 static void encode_zval(zval* from, int refs) {
636   encode(from->type);
637   if (refs) {
638     encode(from->is_ref);
639     encode32(from->refcount);
640   } else if (!from->is_ref || from->refcount != 2) {
641     zend_bailout();
642   }
643
644   switch (from->type & ~IS_CONSTANT_INDEX) {
645     case IS_NULL:
646       break;
647     case IS_BOOL:
648       encode((unsigned char)from->value.lval);
649       break;
650     case IS_LONG:
651       encode32(from->value.lval);
652       break;
653     case IS_DOUBLE:
654       encode_double(from->value.dval);
655       break;
656     case IS_CONSTANT:
657     case IS_STRING:
658 /*???    case FLAG_IS_BC:*/
659       encode_lstr(from->value.str.val, from->value.str.len);
660       break;
661     case IS_ARRAY:
662     case IS_CONSTANT_ARRAY:
663       encode_zval_hash(from->value.ht);
664       break;
665     case IS_OBJECT:
666     case IS_RESOURCE:
667       /*???*/
668     default:
669       zend_bailout();
670       break;
671   }
672 }
673
674 static void encode_znode(znode* from, unsigned int vars_count) {
675   encode((unsigned char)from->op_type);
676   if (from->op_type == IS_CONST) {
677     encode_zval(&from->u.constant, 0);
678   } else if (from->op_type == IS_VAR ||
679              from->op_type == IS_TMP_VAR) {
680     encode_var(from->u.var, vars_count);
681   } else if (from->op_type != IS_UNUSED) {
682     zend_bailout();
683   }
684 }
685
686
687 static void encode_zval_ptr(zval** from) {
688   encode_zval(*from, 1);
689 }
690
691 #ifdef ZEND_ENGINE_2
692 static void encode_property_info(zend_property_info* from) {
693   encode32(from->flags);
694   encode_lstr(from->name, from->name_length);
695 }
696
697 static void encode_class_entry(zend_class_entry* from);
698
699 static void encode_class_entry_ptr(zend_class_entry** from) {
700   encode_class_entry(*from);
701 }
702 #endif
703
704 static void encode_hash(HashTable* from, encode_bucket_t encode_bucket) {
705   if (from != NULL &&
706       from->nNumOfElements > 0) {
707     Bucket* p;
708     encode32(from->nNumOfElements);
709     p = from->pListHead;
710     while (p != NULL) {
711       encode_lstr(p->arKey, p->nKeyLength);
712       if (p->nKeyLength == 0) {
713         encode32(p->h);
714       }
715       encode_bucket(p->pData);
716       p = p->pListNext;
717     }
718   } else {
719     encode32(0);
720   }
721 }
722
723 #ifdef ZEND_ENGINE_2
724 #define encode_zval_hash_ex(from,p) encode_hash_ex(from, p, (encode_bucket_t)encode_zval_ptr)
725
726 static void encode_hash_ex(HashTable* from, Bucket* p, encode_bucket_t encode_bucket) {
727   if (from != NULL &&
728       from->nNumOfElements > 0) {
729     unsigned int n = 0;
730     Bucket* q = p;
731     while (q != NULL) {
732       ++n;
733       q = q->pListNext;
734     }
735     encode32(n);
736     while (p != NULL) {
737       encode_lstr(p->arKey, p->nKeyLength);
738       if (p->nKeyLength == 0) {
739         encode32(p->h);
740       }
741       encode_bucket(p->pData);
742       p = p->pListNext;
743     }
744   } else {
745     encode32(0);
746   }
747 }
748 #endif
749
750 static void encode_op_array(zend_op_array* from) {
751   zend_op *opline;
752   zend_op *end;
753
754   if (from->type == ZEND_INTERNAL_FUNCTION) {
755   } else if (from->type == ZEND_USER_FUNCTION) {
756   } else {
757     zend_bailout();
758   }
759   encode(from->type);
760 #ifdef ZEND_ENGINE_2
761   encode32(from->num_args);
762   if (from->num_args > 0) {
763     zend_uint i;
764     for (i = 0; i < from->num_args; i++) {
765       encode_lstr(from->arg_info[i].name,from->arg_info[i].name_len);
766       encode_lstr(from->arg_info[i].class_name,from->arg_info[i].class_name_len);
767       encode(from->arg_info[i].allow_null);
768       encode(from->arg_info[i].pass_by_reference);
769     }
770   }
771   encode(from->pass_rest_by_reference);
772 #else
773   encode_pstr(from->arg_types);
774 #endif
775   encode_zstr(from->function_name);
776 #ifdef ZEND_ENGINE_2
777   encode32(from->fn_flags);
778   if (from->scope != NULL) {
779     TSRMLS_FETCH();
780     {
781       Bucket* q = CG(class_table)->pListHead;
782       while (q != NULL) {
783         if (*(zend_class_entry**)q->pData == from->scope) {
784           encode_lstr(q->arKey, q->nKeyLength);
785           goto scope_stored;
786         }
787         q = q->pListNext;
788       }
789     }
790   }
791   encode32(0);
792 scope_stored:
793 #endif
794   if (from->type == ZEND_INTERNAL_FUNCTION) {
795     return;
796   }
797   encode32(from->T);
798 #ifdef ZEND_ENGINE_2
799   encode(from->uses_this);
800 #else
801   encode(from->uses_globals);
802 #endif
803   encode(from->return_reference);
804
805   if (from->opcodes != NULL && from->last > 0) {
806     encode32(from->last);
807     if (from->brk_cont_array != NULL && from->last_brk_cont > 0) {
808       zend_uint i;
809       encode32(from->last_brk_cont);
810       for (i = 0; i < from->last_brk_cont; i++) {
811         encode_opline(from->brk_cont_array[i].brk, from->last);
812         encode_opline(from->brk_cont_array[i].cont, from->last);
813         encode_opline(from->brk_cont_array[i].parent, from->last_brk_cont);
814       }
815     } else {
816       encode32(0);
817     }
818 #ifdef ZEND_ENGINE_2
819         if (from->try_catch_array != NULL && from->last_try_catch > 0)
820         {
821                 zend_uint i;
822                 encode32(from->last_try_catch);
823                 for (i = 0; i < from->last_try_catch; i++)
824                 {
825                         encode_opline(from->try_catch_array[i].try_op, from->last);
826                         encode_opline(from->try_catch_array[i].catch_op, from->last);
827 //                      encode_opline(from->try_catch_array[i].parent, from->last_try_catch);
828                 }
829         }
830         else
831         {
832                 encode32(0);
833         }
834 #endif
835         opline = from->opcodes;
836     end = opline + from->last;
837     for (;opline < end; opline++) {
838       const opcode_dsc* op_dsc = get_opcode_dsc(opline->opcode);
839       if (op_dsc == NULL) {
840         zend_bailout();
841       } else {
842         unsigned int ops = op_dsc->ops;
843         encode(opline->opcode);
844 #if MMC_ENCODER_VERSION < 2
845         encode32(opline->lineno);
846 #endif
847         switch (ops & EXT_MASK) {
848           case EXT_UNUSED:
849              break;
850           case EXT_STD:
851           case EXT_FCALL:
852           case EXT_ARG:
853           case EXT_IFACE:
854             encode32(opline->extended_value);
855             break;
856           case EXT_SEND:
857           case EXT_SEND_NOREF:
858           case EXT_INIT_FCALL:
859           case EXT_FETCH:
860           case EXT_CAST:
861           case EXT_DECLARE:
862           case EXT_FCLASS:
863           case EXT_BIT:
864           case EXT_ISSET:
865           case EXT_ASSIGN:
866             encode((unsigned char)opline->extended_value);
867             break;
868           case EXT_FE:
869 #if MMC_ENCODER_VERSION >= 3
870             encode((unsigned char)opline->extended_value);
871 #endif
872             break;
873           case EXT_OPLINE:
874             encode_opline(opline->extended_value, from->last);
875             break;
876           case EXT_CLASS:
877             encode_var(opline->extended_value, from->T);
878             break;
879           default:
880             zend_bailout();
881             break;
882         }
883         switch (ops & RES_MASK) {
884           case RES_UNUSED:
885             break;
886           case RES_TMP:
887           case RES_CLASS:
888             encode_var(opline->result.u.var, from->T);
889             break;
890           case RES_VAR:
891             encode_var(opline->result.u.var, from->T);
892             if ((opline->result.u.EA.type & EXT_TYPE_UNUSED) != 0) {
893               encode(1);
894             } else {
895               encode(0);
896             }
897             break;
898           case RES_STD:
899             encode_znode(&opline->result, from->T);
900             if (opline->result.op_type == IS_VAR) {
901               if ((opline->result.u.EA.type & EXT_TYPE_UNUSED) != 0) {
902                 encode(1);
903               } else {
904                 encode(0);
905               }
906             }
907             break;
908           default:
909             zend_bailout();
910             break;
911         }
912         switch (ops & OP1_MASK) {
913           case OP1_UNUSED:
914             break;
915           case OP1_OPLINE:
916             encode_opline(opline->op1.u.opline_num,from->last);
917             break;
918           case OP1_BRK:
919           case OP1_CONT:
920             encode_opline(opline->op1.u.opline_num, from->last_brk_cont);
921             break;
922           case OP1_CLASS:
923           case OP1_TMP:
924           case OP1_VAR:
925             encode_var(opline->op1.u.var, from->T);
926             break;
927           case OP1_UCLASS:
928             encode((unsigned char)opline->op1.op_type);
929             if (opline->op1.op_type != IS_UNUSED) {
930               encode_var(opline->op1.u.var, from->T);
931             }
932             break;
933           case OP1_ARG:
934             encode32(opline->op1.u.constant.value.lval);
935             break;
936 #ifdef ZEND_ENGINE_2
937           case OP1_JMPADDR:
938             encode_opline(opline->op1.u.jmp_addr - from->opcodes, from->last);
939             break;
940 #endif
941           case OP1_STD:
942             encode_znode(&opline->op1, from->T);
943             break;
944           default:
945             zend_bailout();
946             break;
947         }
948         switch (ops & OP2_MASK) {
949           case OP2_UNUSED:
950             break;
951           case OP2_OPLINE:
952             encode_opline(opline->op2.u.opline_num, from->last);
953             break;
954           case OP2_ARG:
955             encode32(opline->op2.u.opline_num);
956             break;
957           case OP2_ISSET:
958           case OP2_INCLUDE:
959             encode((unsigned char)opline->op2.u.constant.value.lval);
960             break;
961           case OP2_FETCH:
962 #ifdef ZEND_ENGINE_2
963             encode((unsigned char)opline->op2.u.EA.type);
964             if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) {
965               encode_var(opline->op2.u.var, from->T);
966             }
967 #else
968             encode((unsigned char)opline->op2.u.fetch_type);
969 #endif
970             break;
971           case OP2_CLASS:
972           case OP2_TMP:
973           case OP2_VAR:
974             encode_var(opline->op2.u.var, from->T);
975             break;
976 #ifdef ZEND_ENGINE_2
977           case OP2_JMPADDR:
978             encode_opline(opline->op2.u.jmp_addr - from->opcodes, from->last);
979             break;
980 #endif
981           case OP2_STD:
982             encode_znode(&opline->op2, from->T);
983             break;
984           default:
985             zend_bailout();
986             break;
987         }
988       }
989     }
990   } else {
991     encode32(0);
992   }
993   encode_zval_hash(from->static_variables);
994 #if MMC_ENCODER_VERSION < 2
995   encode_zstr(from->filename);
996 #endif
997 #ifdef ZEND_ENGINE_2
998   encode32(from->line_start);
999   encode32(from->line_end);
1000   encode_lstr(from->doc_comment, from->doc_comment_len);
1001 #endif
1002 }
1003
1004 static void encode_class_entry(zend_class_entry* from) {
1005   encode(from->type);
1006   encode_lstr(from->name,from->name_length);
1007 #ifdef ZEND_ENGINE_2
1008   encode32(from->ce_flags);
1009   encode32(from->num_interfaces);
1010 #endif
1011
1012   if (from->parent != NULL && from->parent->name) {
1013     encode_lstr(from->parent->name, from->parent->name_length);
1014   } else {
1015     encode32(0);
1016   }
1017
1018 #ifdef ZEND_ENGINE_2
1019 #if MMC_ENCODER_VERSION < 2
1020   encode32(from->line_start);
1021   encode32(from->line_end);
1022   encode_zstr(from->filename);
1023 #endif
1024   encode_lstr(from->doc_comment, from->doc_comment_len);
1025
1026   encode_zval_hash(&from->constants_table);
1027   encode_zval_hash(&from->default_properties);
1028   encode_hash(&from->properties_info, (encode_bucket_t)encode_property_info);
1029   encode_zval_hash(from->static_members);
1030 #else
1031   encode_zval_hash(&from->default_properties);
1032 #endif
1033   encode_hash(&from->function_table, (encode_bucket_t)encode_op_array);
1034 }
1035
1036 static int eaccelerator_encode(char* key, zend_op_array* op_array,
1037                           Bucket* f, Bucket *c) {
1038   encode_zstr("EACCELERATOR");
1039   encode32(MMC_ENCODER_VERSION);
1040 #ifdef ZEND_ENGINE_2
1041   encode(2);
1042 #else
1043   encode(1);
1044 #endif
1045   while (c != NULL) {
1046     zend_class_entry *ce;
1047 #ifdef ZEND_ENGINE_2
1048     ce = *(zend_class_entry**)c->pData;
1049     encode(MMC_ENCODER_CLASS);
1050     encode_lstr(c->arKey, c->nKeyLength);
1051     encode_class_entry(ce);
1052 #else
1053     encode(MMC_ENCODER_CLASS);
1054     encode_lstr(c->arKey, c->nKeyLength);
1055     ce = (zend_class_entry*)c->pData;
1056     encode_class_entry(ce);
1057 #endif
1058     c = c->pListNext;
1059   }
1060   encode(MMC_ENCODER_END);
1061
1062   while (f != NULL) {
1063     encode(MMC_ENCODER_FUNCTION);
1064     encode_lstr(f->arKey, f->nKeyLength);
1065     encode_op_array((zend_op_array*)f->pData);
1066     f = f->pListNext;
1067   }
1068   encode(MMC_ENCODER_END);
1069   encode_op_array(op_array);
1070   return 1;
1071 }
1072
1073 #ifdef ZEND_ENGINE_2
1074
1075 ZEND_DLIMPORT int is