root/eaccelerator/tags/0.9.5-rc1/encoder.c

Revision 201, 37.6 kB (checked in by bart, 3 years ago)

A lot of fixes to silence the compile warnings generated when compiling with the default Fedora compiler options

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