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

Revision 191, 37.2 kB (checked in by bart, 3 years ago)

* Moved the FLOCK stuff to a place so it can be used by eLoader to
* Fixed quite some compile warnings on Win32
* Updated VC6 project files for Win32

(Note: I feel dirty now, I'm going to take a shower ;-) )

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