Kategorien
Allgemein

Hohe Hürden für wahre Helden

Ich kann die armen PHP Programmierer nur bedauern. Das schreiben von einfachen Anwendungen mit PHP soll ja recht einfach sein, aber wehe es gibt einen Fehler. Das Debuggen von PHP Programmen ist nicht einfach.

Aus dem Grunde werden wohl die meisten PHP Anwender das Debuggen per echo oder var_dump anwenden. Wenn das aber nicht mehr ausreicht, so muss doch ein echter Debugger her. Da gibt es mehrere in der OpenSource Welt.

Ausprobiert habe ich XDebug und DBG.

DBG war als erstes an der Reihe. Nachdem ich das Modul nach Anleitung kompiliert und installiert hatte, dauerte es auch nur noch einen halben Tag, bis ich mich mit PHPEclipse mit dem Debugging anfangen konnte. DBG kann sich pro Anfrage per Parameter auf einen anderen entfernten Debugger einlassen. Was von Vorteil ist, wenn mehrere Entwickler mit einem Webserver arbeiten. Leider habe ich es nicht hinbekommen, dass auch jede Anfrage an den Debugger weitergeleitet wurde. Alles in allem, keine schöne Erfahrung.

Danach habe ich noch XDebug ausprobiert, da es von der pdt Erweiterung des Eclipse-Projektes genutzt werden kann. Mit der von DBG gewonnenen Erfahrung bin ich schon viel schneller zum Debuggen gekommen. Aber anscheinend geht XDebug davon aus, das immer nur ein Entwickler debuggen will. Denn das PHP Modul verbindet sich immer mit einem bei Apache Start voreingestellten Host und Port. Dafür zeigte sich der Debugger etwas stabiler als DBG. Als nettes Beiwerk verändert XDebug die Ausgabe von var_dump und den Fehlermeldungen von PHP. Auch ist ein einfacher Profiler einschaltbar, dessen Ergebnisse mit kcachegrind auswertbar sind. (DBG soll auch einen Profiler enthalten, aber die Doku ist quasi nicht vorhanden.)

Alles in allem: Arme PHP Entwickler.

Kategorien
Allgemein

XML-RPC und Zope mit Ümläüten

In Vorbereitung auf den WS-Vortrag von Jörg, wollte ich eine einfache Zope Methode per XML-RPC nutzen. Und wieder einmal kam mir das Character-encoding dazwischen.

Das Problem bei dem XML-RPC Aufruf war die fehlende Kodierungsangabe in der XML Deklaration den Zope für die Antwort automatisch generiert. Fehlt aber keine Kodierung wird bei XML Dokumenten von UTF-8 ausgegangen. Wie ich bei den JSP Seiten schon erwähnt hatte.

Da Zope aber anscheinend gar nicht wusste, dass meine String-Antworten Umlaute enthielten und sie auch nicht als Unicode-Strings vorlagen, hat es sie auch nicht als UTF-8 kodierte Strings in die XML-RPC Antwort eingebettet. Glücklicherweise wusste ich sowohl die Kodierung der Strings in meiner Methode und auch, wie ich sie in Unicode-Strings umwandele:

unicode_string = unicode(alter_string, 'iso-8859-1')

Kaum war diese Umwandelung aktiv, funktionierte die Anfrage auch von meinem XML-RPC Client heraus.

Nun kann Jörg also loslegen.

Kategorien
Allgemein

Einfacher Interpreter einer einfachen Sprache

Nachdem Jörg mir ein paar Perl-Bücher geliehen hatte und schon seit längerer Zeit das „Hello World!“ Plakat auf unserem stillen Örtchen hängt, musste ich mich einfach an einen Brainfuck Interpreter versuchen.

Und hier ist das Ergebnis:

#!/usr/bin/perl
{
  package BF;
  use strict;
  use warnings;

  my @REGISTERS=('PP', 'MP', 'LOOP');
  my %OPERATORS=(
      '+' => sub {
          my ($self) = @_;
          return if $self->{_registers}{'LOOP'} < 0;
          $self->{_memory}[$self->{_registers}{'MP'}]++;
          $self->{_registers}{'PP'}++;
      },
      '-' => sub {
          my ($self) = @_;
          return if $self->{_registers}{'LOOP'} < 0;
          $self->{_memory}[$self->{_registers}{'MP'}]--;
          $self->{_registers}{'PP'}++;
      },
      '.' => sub {
          my ($self) = @_;
          return if $self->{_registers}{'LOOP'} < 0;
          push @{ $self->{_output} }, $self->{_memory}[$self->{_registers}{'MP'}];
          $self->{_registers}{'PP'}++;
      },
      '>' => sub {
          my ($self) = @_;
          return if $self->{_registers}{'LOOP'} < 0;
          $self->{_registers}{'MP'}++;
          $self->{_registers}{'PP'}++;
      },
      '<' => sub {
          my ($self) = @_;
          return if $self->{_registers}{'LOOP'} < 0;
          $self->{_registers}{'MP'}--;
          $self->{_registers}{'PP'}++;
      },
      '[' => sub {
          my ($self) = @_;
          if ($self->{_memory}[$self->{_registers}{'MP'}] > 0) {
              push @{ $self->{_stack} }, $self->{_registers}{'PP'};
          } else {
              $self->{_registers}{'LOOP'}--;
          }
          $self->{_registers}{'PP'}++;
          return;
      },
      ']' => sub {
          my ($self) = @_;
          my $loop_stacktart = pop @{ $self->{_stack} };
          if ($self->{_memory}[$self->{_registers}{'MP'}]) {
              $self->{_registers}{'PP'} = $loop_stacktart;
          } else {
              $self->{_registers}{'PP'}++;
          }
          $self->{_registers}{'LOOP'}++;
      },
  );

  sub new {
      my $class = shift;
      my $data = {
          _registers => { map { $_ => 0 } @REGISTERS },
          _memory => [],
          _stack => [],
          _output => [],
      };
      bless $data, $class;
  };

  sub run {
      my $self = shift;
      while ($self->{_registers}{PP} < $self->{_max_program_size}) {
          my $op_char = $self->{_program}[$self->{_registers}{PP}];
          my $op = $OPERATORS{$op_char};
          $op->($self);
      }
  }

  sub set_memory {
      my ($self, $memory) = @_;
      $self->{_program} = [ split //, $memory ];
      $self->{_max_program_size} = @{ $self->{_program} };
  }

  sub output {
      my $self = shift;
      return join ',', @{ $self->{_output} };
  }

  sub char_output {
      my $self = shift;
      return join '', map { chr($_) } @{ $self->{_output} };
  }
}

package main;
use strict;
use warnings;

use Test::More qw(no_plan);

my %test_data = (
    '++.' => '2',
    '++-.' => '1',
    '++.>+.<+.' => '2,1,3',
    '+++.[-.].' => '3,2,1,0,0',
    '++.[->++[.-]<]' => '2,2,1,2,1',
    '++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.' => '72,101,108,108,111,32,87,111,114,108,100,33,10',
);
while (my ($prog, $exptected_output) = each %test_data) {
    my $bf = BF->new();
    $bf->set_memory($prog);
    $bf->run();
    is($bf->output(), $exptected_output, $prog);
}

my $bf = BF->new();
$bf->set_memory('++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.');
$bf->run();
is("Hello World!n", $bf->char_output(), "Hello World!");

Eine tolle sinnlose Beschäftigung.

Und wen es interessiert: Das Plakat zum Programm.

Kategorien
Allgemein

Standardkodierung von JSP Seiten

Wird eine JSP Seite in ein Servlet übersetzt und dann auch noch von einem Browser aus aufgerufen, so sind etwa vier Kodierungen durchlaufen.

Zuerst wird aus einer JSP Seite eine Java Klasse erzeugt. Hierfür findet eine Konvertierung von ISO-8859-1 nach UTF-8 statt. Will man eine andere Kodierung in der JSP Seite pflegen, so muss das mit einer pageEncoding Anweisung angegeben werden.

Dann wird aus der Java Klasse der JavaVM Bytecode erzeugt. Hier findet – so die Java Klasse in UTF-8 kodiert ist – keine konvertierung statt. In der JavaVM ist dann alles in Unicode.

Nun kommt der spannende Augenblick und ein Browser greift auf das übersetzt JSP-Servlet zu. Die Kodierung der HTTP-Anfrage des Browsers wird genutzt um die Daten der Anfrage vom Servlet-Container in Unicode zu wandeln.

Für die Reise zurück wandelt eine JSP Seite dann den Datenstrom – so nichts anderes vorgegeben – wieder in ISO-8859-1 um.

Um das ganze noch ein wenig spannender zu gestalten, ist die Standard-Kodierung von JSP Dokumenten – also XML-basierte JSP’s – natürlich UTF-8.

Seltsam also, das normalerweise so wenig Kodierungs-Probleme auftreten.