]> code.delx.au - gnu-emacs/blob - test/manual/etags/php-src/lce_functions.php
Merge from origin/emacs-25
[gnu-emacs] / test / manual / etags / php-src / lce_functions.php
1 <?php
2 if(!defined("LCE_FUNCTIONS"))
3 {
4 define("LCE_FUNCTIONS", 1);
5 include("base.php");
6 include("lce_config.php");
7
8 // Unknown line class
9 define("LCE_UNKNOWN", 0);
10 // pure whitespace
11 define("LCE_WS", 1);
12 // a unqualified comment
13 define("LCE_COMMENT", 2);
14 // a user/translator comment
15 define("LCE_COMMENT_USER", 3);
16 // a tool-generated comment
17 define("LCE_COMMENT_TOOL", 4);
18 // A line containing a MSGID
19 define("LCE_MSGID", 5);
20 // A line containing a MSGSTR
21 define("LCE_MSGSTR", 6);
22 // A quoted text string
23 define("LCE_TEXT", 7);
24
25 define("STATE_ABORT", 0);
26 define("STATE_OK", 1);
27 define("STATE_LOOP", 2);
28
29 class POEntryAD extends AD
30 {
31 function validate($value)
32 {
33 // print '"<pre>' . $value . '"<br></pre>';
34 $result = AD::validate(trim($value));
35 //return $result;
36 if($result[0])
37 {
38 $lines = explode("\n", ereg_replace("\r", "", $result[1]));
39 //$lines = explode("\n", $result[1]);
40 /* print "<pre>";
41 print_r($lines);
42 print "</pre>";*/
43 $res = array();
44 for($i = 0; $i < count($lines); $i++)
45 {
46 if(trim($lines[$i]) != "")
47 $res[] = $lines[$i];
48 }
49 $result[1] = join("\n", $res);
50 /* print "<pre>";
51 print_r($result[1]);
52 print "</pre>";*/
53
54 $result[0] = $this->checkQuotation($result[1]);
55 }
56 return $result;
57 }
58
59 function checkQuotation($str)
60 {
61 $rex = "\\\\n|\\\\t|\\\\r|\\\\\"";
62 $str = ereg_replace($rex, "", $str);
63 $str = ereg_replace("\\\\\\\\", "", $str);
64 return !(strstr($str, "\"")
65 || strstr($str, "\\"));
66 }
67 }
68
69
70 class CommentAD extends AD
71 {
72 var $prefix;
73 function CommentAD(
74 $name, // the name of the variable
75 $not_null = 0,
76 $type = "", // as returned by gettype
77 $prefix = "# ")
78 {
79 $this->prefix = $prefix;
80 AD::AD($name, $not_null, $type);
81 }
82
83 function validate($value)
84 {
85 $res = AD::validate($value);
86 return $res;
87 if($res[0] && $res[1] != "")
88 {
89 $mod_lines = array();
90 $lines = explode("\n", $res[1]);
91
92 for($i = 0; $i < count($lines); $i++)
93 {
94 $line = $lines[$i];
95 if(substr($line, 0, 1) != "#")
96 $line = $this->prefix . $line;
97 $mod_lines[] = $line;
98 }
99 $res[1] = join("\n", $mod_lines);
100 }
101 return $res;
102 }
103 }
104
105 class POEntry extends HtmlValidator
106 {
107 var $msgid;
108 var $msgstr;
109 var $user_comment;
110 var $sys_comment;
111 var $unk_comment;
112
113 var $msgid_lc = 0;
114 var $msgstr_lc = 0;
115 var $user_comment_lc = 0;
116 var $sys_comment_lc = 0;
117 var $unk_comment_lc = 0;
118
119 function POEntry()
120 {
121 $this->atts = array(
122 new AD("msgid"),
123 new POEntryAD("msgstr", REQUIRED_ATTRIBUTE),
124 new CommentAD("user_comment"),
125 new POEntryAD("sys_comment"),
126 new POEntryAD("unk_comment"),
127 new AD("msgid_lc", NOT_REQUIRED_ATTRIBUTE, 0),
128 new AD("msgstr_lc", NOT_REQUIRED_ATTRIBUTE, 0),
129 new AD("user_comment_lc", NOT_REQUIRED_ATTRIBUTE, 0),
130 new AD("sys_comment_lc", NOT_REQUIRED_ATTRIBUTE, 0),
131 new AD("unk_comment_lc", NOT_REQUIRED_ATTRIBUTE, 0)
132 );
133 }
134
135 function lineCount($entry)
136 {
137 $lc = count(explode("\n", $entry));
138 return $lc;
139 }
140
141 function serializeToVars($prefix)
142 {
143 $this->user_comment_lc = $this->lineCount($this->user_comment);
144 $this->unk_comment_lc = $this->lineCount($this->sys_comment);
145 $this->sys_comment_lc = $this->lineCount($this->unk_comment);
146 $this->msgid_lc = $this->lineCount($this->msgid);
147 $this->msgstr_lc = $this->lineCount($this->msgstr);
148 return HtmlValidator::serializeToVars($prefix);
149 }
150
151 function write()
152 {
153 $content = "";
154 $content .= $this->user_comment . "\n";
155 $content .= $this->unk_comment . "\n";
156 $content .= $this->sys_comment . "\n";
157 $content .= "msgid \"" . $this->msgid . "\"\n";
158 $content .= 'msgstr "' . join("\"\n\"", explode("\n", $this->msgstr)) . "\"" . "\n\n";
159 return $content;
160 }
161 }
162
163 class POReader extends HTMLValidator
164 {
165 var $msgid;
166 var $msgstr;
167 var $user_comment;
168 var $sys_comment;
169 var $unk_comment;
170 var $state;
171 var $ignore_ws;
172 var $po_entries;
173 var $poe_num;
174 var $filename;
175 var $domain;
176
177 function gettext($msgid)
178 {
179 if(isset($this->po_entries[$msgid]))
180 {
181 $po = $this->po_entries[$msgid];
182 return StripCSlashes(join("", explode("\n", $po->msgstr)));
183 //return $po->msgstr;
184 }
185 return $msgid;
186 }
187
188
189 function parseFromVars($prefix)
190 {
191 $res = HtmlValidator::parseFromVars($prefix);
192 if($res[0])
193 {
194 $poe_res = true;
195 $this->po_entries = array();
196 for($i = 0; $i < $this->poe_num; $i++)
197 {
198 $poe = new POEntry;
199 $res = $poe->parseFromVars($prefix . "_POE$i");
200 if($res[0])
201 {
202 $msgid = $prefix . "_POE" . $i . "_MSGID";
203 $msgid = $$msgid;
204 $this->po_entries[$prefix . "_POE" . $i . "_MSGID"] = $res[1];
205 }
206 else
207 $poe_res = false;
208 }
209 }
210 if(!$poe_res)
211 $GLOBALS[$prefix . "_ERR"] = 1;
212 return array($poe_res, $this);
213 }
214
215 function serializeToVars($prefix)
216 {
217 HtmlValidator::serializeToVars($prefix);
218 reset($this->po_entries);
219 $i = 0;
220 while($poe = each($this->po_entries))
221 {
222 $poe = $poe[1];
223 $poe->serializeToVars($prefix . "_POE$i");
224 $i++;
225 }
226 }
227
228
229 function POReader($domain, $filename)
230 {
231 $this->domain = $domain;
232 $this->filename = $filename;
233 $this->ignore_ws = true;
234 $this->po_entries = array();
235 $this->atts = array(
236 new AD("domain", REQUIRED_ATTRIBUTE),
237 new AD("filename", REQUIRED_ATTRIBUTE),
238 new AD("poe_num", REQUIRED_ATTRIBUTE, 0)
239 );
240 }
241
242
243 function read()
244 {
245 if($fh = fopen($this->filename, "r"))
246 {
247 $this->lines = array();
248 while (!feof ($fh))
249 {
250 $line = fgets($fh, 4096);
251 $this->lines[] = $line;
252 }
253 fclose($fh);
254 }
255 $this->createPOEntries();
256 $this->poe_num = count($this->po_entries);
257 }
258
259 function write($save="yes")
260 {
261 reset($this->po_entries);
262 $content = "";
263 while($poe = each($this->po_entries))
264 {
265 $poe = $poe[1];
266 $content .= $poe->write();
267 }
268
269 if(($fh = fopen($this->filename, "w"))
270 && $save == "yes")
271 {
272 fwrite($fh, $content);
273 }
274 return $content;
275 }
276
277 function isComment($class)
278 {
279 if($class == LCE_COMMENT || $class == LCE_COMMENT_USER || $class == LCE_COMMENT_TOOL)
280 return true;
281 return false;
282 }
283
284 function comment($line, $class)
285 {
286 if($this->isComment($class))
287 {
288 if($class == LCE_COMMENT_USER)
289 $this->user_comment .= $line;
290 else if($class == LCE_COMMENT_TOOL)
291 $this->sys_comment .= $line;
292 else
293 $this->unk_comment .= $line;
294 return STATE_OK;
295 }
296 if($class == LCE_MSGID)
297 {
298 $this->state = "msgid";
299 return STATE_LOOP;
300 }
301 return STATE_ABORT;
302 }
303
304 function msgid($line, $class)
305 {
306 if($class == LCE_MSGID || $class == LCE_TEXT)
307 {
308 $line = $this->stripLine($line, LCE_MSGID);
309 $this->msgid .= $line;
310 return STATE_OK;
311 }
312 if($class == LCE_MSGSTR)
313 {
314 $this->state = "msgstr";
315 return STATE_LOOP;
316 }
317 return STATE_ABORT;
318 }
319
320 function msgstr($line, $class)
321 {
322 if($class == LCE_MSGSTR || $class == LCE_TEXT)
323 {
324 $line = $this->stripLine($line, $class);
325 $this->msgstr .= $line;
326 return STATE_OK;
327 }
328 // We have a different state, so we have to create a POEntry
329 $poe = new POEntry;
330 $poe->user_comment = trim($this->user_comment);
331 $poe->sys_comment = trim($this->sys_comment);
332 $poe->unk_comment = trim($this->unk_comment);
333 $poe->msgid = trim($this->msgid);
334 $poe->msgstr = trim($this->msgstr);
335 $this->po_entries[trim($this->msgid)] = $poe;
336 $this->state = "start";
337 return STATE_LOOP;
338 }
339
340 function start($line, $class)
341 {
342 $this->user_comment = "";
343 $this->sys_comment = "";
344 $this->unk_comment = "";
345 $this->msgid = "";
346 $this->msgstr = "";
347 if($this->isComment($class))
348 {
349 $this->state = "comment";
350 return STATE_LOOP;
351 }
352 if($class == LCE_MSGID)
353 {
354 $this->state = "msgid";
355 return STATE_LOOP;
356 }
357 return STATE_OK;
358 }
359
360 function createPOEntries()
361 {
362 $this->msgid = "";
363 $this->msgstr = "";
364 $this->user_comment = "";
365 $this->sys_comment = "";
366 $this->state = "start";
367
368 reset($this->lines);
369 for($i = 0; $i < count($this->lines); $i++)
370 {
371 $line = $this->lines[$i];
372 $class = $this->classifyLine($line);
373 if($class != LCE_WS || !$this->ignore_ws)
374 {
375 $state_ret = STATE_LOOP;
376 while($state_ret == STATE_LOOP)
377 {
378 $state = $this->state;
379 //print "$this->state $class:$line <br>";
380 $state_ret = $this->$state($line, $class);
381 }
382 //print "state_ret = $state_ret <br>";
383 }
384 if($state_ret == STATE_ABORT)
385 break;
386 }
387 // Get the last entry
388 if($state_ret != STATE_ABORT)
389 {
390 $this->msgstr("", LCE_UNKNOWN);
391 }
392 }
393
394 function stripLine($line, $class)
395 {
396 switch($class)
397 {
398 case LCE_TEXT:
399 ereg('^"(.*)"', $line, $regs);
400 $line = $regs[1] . "\n";
401 break;
402 case LCE_MSGID:
403 if(substr($line, strlen("msgid")) == "msgid")
404 {
405 $line = substr($line, strlen("msgid") + 1);
406 }
407 ereg('"(.*)"', $line, $regs);
408 $line = $regs[1];
409 break;
410 case LCE_MSGSTR:
411 // TODO: Check if ^ can be removed
412 $line = substr($line, strlen("msgstr") + 1);
413 ereg('^"(.*)"', $line, $regs);
414 $line = $regs[1] . "\n";
415 break;
416
417 }
418 return $line;
419 }
420
421 function printClassification()
422 {
423 reset($this->lines);
424 for($i = 0; $i < count($this->lines); $i++)
425 {
426 $line = $this->lines[$i];
427 $class = $this->classifyLine($line);
428 print "#$i: $class $line<br>";
429 }
430 }
431
432 function classifyLine($line)
433 {
434 if(ereg("^[ \n\r\t]*$", $line))
435 return LCE_WS;
436 if(ereg("^#.*\$", $line))
437 {
438 if(ereg("^[,:-~].*", substr($line, 1)))
439 {
440 return LCE_COMMENT_TOOL;
441 }
442 if(ereg("^[ \n\r\t].*", substr($line, 1)))
443 {
444 return LCE_COMMENT_USER;
445 }
446 return LCE_COMMENT;
447 }
448 if(ereg("^msgid (.*)\$", $line, $regs))
449 {
450 $line = $regs[1];
451 if($this->classifyLine($line) == LCE_TEXT)
452 return LCE_MSGID;
453 }
454 if(ereg("^msgstr (.*)\$", $line, $regs))
455 {
456 $line = $regs[1];
457 if($this->classifyLine($line) == LCE_TEXT)
458 return LCE_MSGSTR;
459 }
460 if(ereg('^".*"', $line))
461 {
462 // TODO: Check correct escapes
463 return LCE_TEXT;
464 }
465
466 return LCE_UNKNOWN;
467 }
468 }
469
470
471 function getTextDomains($lines)
472 {
473 $default_domain = "";
474 $domains = array();
475 while($gl = each($GLOBALS))
476 {
477 $gname = $gl[0];
478 global $$gname;
479 }
480 for($i = 0; $i < count($lines); $i++)
481 {
482 if(ereg("bindtextdomain\(([^,]+),([^\)]+)\)", $lines[$i], $regs))
483 {
484 //print "Line:" . $lines[$i] . " <br>";
485 $name = $regs[1];
486 $ev = "\$directory = ". $regs[2] . ";";
487 print $ev;
488 eval($ev);
489 $domains[] = array($name, $directory);
490 }
491 if(ereg("textdomain\(([^\)]+)\)", $lines[$i], $regs))
492 $default_domain = $regs[1];
493 }
494 return array($default_domain, $domains);
495 }
496
497
498 class PORManager extends HtmlValidator
499 {
500 var $por_a;
501
502 function PORManager()
503 {
504 $this->por_a = array();
505 }
506
507 function addPOReader($d_name, &$por)
508 {
509 $this->por_a[$d_name] = &$por;
510 }
511
512 function &getPOReader($domain)
513 {
514 return $this->por_a[$domain];
515 }
516
517 function getDomainNames()
518 {
519 return array_keys($this->por_a);
520 }
521 }
522
523 function &loadPORManager()
524 {
525 global $LCE_PORMAN;
526 if(!isset($LCE_PORMAN))
527 {
528 $LCE_PORMAN = new PORManager();
529 }
530 return $LCE_PORMAN;
531 }
532
533
534 // More or less intelligent filename joining
535 // As available in PYTHONs os.path
536 function fileJoin()
537 {
538 $numargs = func_num_args();
539 $args = func_get_args();
540 for($i = 0; $i < $numargs - 1; $i++)
541 {
542 if(substr($args[$i], -1) != "/")
543 $args[$i] = $args[$i] . "/";
544 if($i > 0)
545 {
546 if(substr($args[$i],0 , 1) == "/")
547 $args[$i] = substr($args[$i], 1);
548 }
549
550 }
551 return join("", $args);
552 }
553
554 if(defined("LCE_TESTSERVER"))
555 {
556
557 function lce_bindtextdomain($d_name, $d_path)
558 {
559 global $LANG, $LC_MESSAGES, $LC_ALL, $LCE_LANG;
560 global $LCE_ERR;
561 global $LCE_PO_SUFFIX;
562 global $LCE_MANAGER;
563
564 $path_orig = $d_path;
565 // This is not complete and reflects
566 // my not very far going understanding of the
567 // different $LC_x thingies.
568 if(isset($LC_MESSAGES))
569 {
570 //print "LC_MESSAGES<br>";
571 $lang_suffix = $LC_MESSAGES;
572 }
573 else if(isset($LC_ALL))
574 {
575 //print "LC_ALL<br>";
576 $lang_suffix = $LC_ALL;
577 }
578 else if(isset($LANG))
579 {
580 //print "LANG<br>";
581 $lang_suffix = $LANG;
582 }
583 else
584 {
585 //print "LCE_LANG<br>";
586 $lang_suffix = $LCE_LANG;
587 }
588
589 //print "LangSuffix: $lang_suffix \n";
590 //print "D_Path: " . fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX) . "<br>";
591 // First try: the whole lang_suffix
592
593 if(file_exists(fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX)))
594 $d_path = fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX);
595 else
596 {
597 $lang_suffix = substr($lang_suffix, 0, 2);
598 if(file_exists(fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name. $LCE_PO_SUFFIX)))
599 $d_path = fileJoin(fileJoin($d_path, $lang_suffix, "LC_MESSAGES", $d_name . $LCE_PO_SUFFIX));
600 else
601 {
602 $LCE_ERR = "No PO-file found";
603 return false;
604 }
605 }
606 //print "D_Path: $d_path \n";
607 $por = new POReader($d_name, $d_path, $path_orig);
608 $por->read();
609 $porman =& loadPORManager();
610 $porman->addPOReader($d_name, $por);
611 return true;
612 }
613
614 function lce_textdomain($domain)
615 {
616 global $LCE_DOMAIN;
617 $LCE_DOMAIN = $domain;
618 }
619
620 function lce_gettext($msgid)
621 {
622 global $LCE_DOMAIN;
623 return lce_dgettext($LCE_DOMAIN, $msgid);
624 }
625
626 function lce_dgettext($domain, $msgid)
627 {
628 $porman =& loadPORManager();
629 if($por = &$porman->getPOReader($domain))
630 return $por->gettext($msgid);
631 return $msgid;
632 }
633
634 function lce()
635 {
636 global $LCE_LCEDITLOC;
637 $porman =& loadPORManager();
638 $domains = $porman->getDomainNames();
639 for($i = 0; $i < count($domains); $i++)
640 {
641 $por =& $porman->getPOReader($domains[$i]);
642 $domain = "domain=" . urlencode($por->domain);
643 $filename = "filename=" . urlencode($por->filename);
644 $url = $LCE_LCEDITLOC . "?" . $domain . "&" . $filename;
645 print "<a target=\"_blank\" href=\"" . $url . "\">Domain: $por->domain</a><br>";
646 }
647 }
648 }
649 else
650 {
651 function lce_bindtextdomain($domain, $path)
652 {
653 bindtextdomain($domain, $path);
654 }
655
656 function lce_textdomain($domain)
657 {
658 textdomain($domain);
659 }
660
661 function lce_gettext($msgid)
662 {
663 return gettext($msgid);
664 }
665
666 function lce_dgettext($domain, $msgid)
667 {
668 return dgettext($domain, $msgid);
669 }
670 function lce()
671 {
672 }
673 }
674
675
676 function lce_geteditcode($type, $name, $text, $rows=2)
677 {
678 global $LCE_EDIT_LEVEL;
679 $level_map = array("msgid" => 4,
680 "sys_comment" => 3,
681 "user_comment" => 2,
682 "msgstr" => 1
683 );
684 if($level_map[$type] > $LCE_EDIT_LEVEL)
685 {
686 return "<input type=\"hidden\" name=\"" . $name . "\" value=\"" . $text . "\"><pre>\n" . $text . "\n</pre>";
687 }
688 else
689 {
690 return "<textarea name=\"" . $name . "\" rows=\"" . $rows . "\" cols=\"60\">" . $text . "</textarea>";
691 }
692 }
693 }
694 /*
695 ;;; Local Variables: ***
696 ;;; mode:C ***
697 ;;; End: ***
698 */
699 ?>