# Error-Handling für CLISP
# Bruno Haible 9.12.1994
# Marcus Daniels 8.4.1994

#include "lispbibl.c"


# SYS::*RECURSIVE-ERROR-COUNT* = Rekursionstiefe der Ausgabe von Errormeldungen

# UP: Beginnt die Ausgabe einer Errormeldung.
# begin_error()
# < STACK_0: Stream (i.a. *ERROR-OUTPUT*)
# < STACK_1: Wert von *error-handler*
# < STACK_2: Argumentliste für *error-handler*
# < STACK_3: Condition-Typ (i.a. SIMPLE-ERROR) oder NIL
# erniedrigt STACK um 7
  local void begin_error (void);
  local void begin_error()
    { end_system_call(); # keine Betriebssystem-Operation läuft mehr
      #ifdef PENDING_INTERRUPTS
      interrupt_pending = FALSE; # Ctrl-C-Wartezeit ist gleich beendet
      begin_system_call();
      #ifdef HAVE_UALARM
      ualarm(0,0); # SIGALRM-Timer abbrechen
      #else
      #ifdef EMUNIX_OLD_8h # EMX-Bug umgehen
      alarm(1000);
      #endif
      alarm(0); # SIGALRM-Timer abbrechen
      #endif
      end_system_call();
      #endif
      # Error-Count erhöhen, bei >3 Ausgabe-Abbruch:
      dynamic_bind(S(recursive_error_count),fixnum_inc(Symbol_value(S(recursive_error_count)),1));
      if (!mposfixnump(Symbol_value(S(recursive_error_count)))) # sollte ein Fixnum >=0 sein
        { Symbol_value(S(recursive_error_count)) = Fixnum_0; } # sonst Notkorrektur
      if (posfixnum_to_L(Symbol_value(S(recursive_error_count))) > 3)
        { # Mehrfach verschachtelte Fehlermeldung.
          Symbol_value(S(recursive_error_count)) = Fixnum_0; # Error-Count löschen
          # *PRINT-PRETTY* an NIL binden (um Speicher zu sparen):
          dynamic_bind(S(print_pretty),NIL);
          fehler(serious_condition,
                 DEUTSCH ? "Unausgebbare Fehlermeldung" :
                 ENGLISH ? "Unprintable error message" :
                 FRANCAIS ? "Message inimprimable" :
                 ""
                );
        }
     {var reg1 object error_handler = Symbol_value(S(error_handler)); # *ERROR-HANDLER*
      if (!nullp(error_handler))
        # *ERROR-HANDER* /= NIL
        { pushSTACK(NIL); pushSTACK(NIL); pushSTACK(error_handler);
          pushSTACK(make_string_output_stream()); # String-Output-Stream
        }
        else
        if (nullp(Symbol_value(S(use_clcs)))) # SYS::*USE-CLCS*
          # *ERROR-HANDER* = NIL, SYS::*USE-CLCS* = NIL
          { pushSTACK(NIL); pushSTACK(NIL); pushSTACK(NIL);
            pushSTACK(var_stream(S(error_output))); # Stream *ERROR-OUTPUT*
            terpri(&STACK_0); # neue Zeile
            write_sstring(&STACK_0,O(error_string1)); # "*** - " ausgeben
          }
          else
          # *ERROR-HANDER* = NIL, SYS::*USE-CLCS* /= NIL
          { pushSTACK(S(simple_error)); pushSTACK(NIL); pushSTACK(unbound);
            pushSTACK(make_string_output_stream()); # String-Output-Stream
          }
    }}

# UP: Gibt ein Error-Objekt aus.
  local void write_errorobject (object obj);
  local void write_errorobject(obj)
    var reg1 object obj;
    { if (nullp(STACK_1))
        { dynamic_bind(S(prin_stream),unbound); # SYS::*PRIN-STREAM* an #<UNBOUND> binden
          dynamic_bind(S(print_escape),T); # *PRINT-ESCAPE* an T binden
          prin1(&STACK_(0+3+3),obj); # direkt ausgeben
          dynamic_unbind();
          dynamic_unbind();
        }
        else
        { # obj auf die Argumentliste schieben:
          pushSTACK(obj);
          obj = allocate_cons();
          Car(obj) = popSTACK();
          Cdr(obj) = STACK_2; STACK_2 = obj;
          # und "~S" in den Format-String schreiben:
          write_schar(&STACK_0,'~'); write_schar(&STACK_0,'S');
    }   }

# UP: Gibt ein Error-Character aus.
  local void write_errorchar (object obj);
  local void write_errorchar(obj)
    var reg1 object obj;
    { if (nullp(STACK_1))
        { write_char(&STACK_0,obj); } # direkt ausgeben
        else
        { # obj auf die Argumentliste schieben:
          pushSTACK(obj);
          obj = allocate_cons();
          Car(obj) = popSTACK();
          Cdr(obj) = STACK_2; STACK_2 = obj;
          # und "~A" in den Format-String schreiben:
          write_schar(&STACK_0,'~'); write_schar(&STACK_0,'A');
    }   }

# UP: Gibt einen Errorstring aus. Bei jeder Tilde '~' wird ein Objekt aus dem
# Stack ausgegeben, bei jedem '$' wird ein Character aus dem Stack ausgegeben.
# write_errorstring(errorstring)
# > STACK_0: Stream usw.
# > errorstring: Errorstring (ein unverschieblicher ASCIZ-String)
# > STACK_7, STACK_8, ...: Argumente (für jedes '~' bzw. '$' eines),
#   in umgekehrter Reihenfolge wie bei FUNCALL !
# < ergebnis: STACK-Wert oberhalb des Stream und der Argumente
  local object* write_errorstring (const char* errorstring);
  local object* write_errorstring(errorstring)
    var reg1 const char* errorstring;
    { var reg2 object* argptr = args_end_pointer STACKop 7; # Pointer übern Stream und Frame
      loop
        { var reg3 uintB ch = *errorstring++; # nächstes Zeichen
          if (ch==0) break; # String zu Ende?
          if (ch=='~') # Tilde?
            # ja -> ein Objekt vom Stack ausgeben:
            { write_errorobject(BEFORE(argptr)); }
          elif (ch=='$') # '$' ?
            # ja -> ein Character vom Stack ausgeben:
            { write_errorchar(BEFORE(argptr)); }
          else
            # nein -> Zeichen normal ausgeben:
            { write_char(&STACK_0,code_char(ch)); }
        }
      return argptr;
    }

# Beendet die Ausgabe einer Fehlermeldung und startet neuen Driver.
# end_error();
  nonreturning_function(local, end_error, (object* stackptr));
  local void end_error(stackptr)
    var reg2 object* stackptr;
    { if (nullp(STACK_1))
        # *ERROR-HANDER* = NIL, SYS::*USE-CLCS* = NIL
        { skipSTACK(4); # Fehlermeldung wurde schon ausgegeben
          dynamic_unbind(); # Bindungsframe für sys::*recursive-error-count* auflösen,
                            # da keine Fehlermeldungs-Ausgabe mehr aktiv
          set_args_end_pointer(stackptr);
          break_driver(NIL); # Break-Driver aufrufen (kehrt nicht zurück)
        }
        else
        { STACK_0 = get_output_stream_string(&STACK_0);
         {var reg4 object arguments = nreverse(STACK_2);
          # Stackaufbau: type, args, handler, errorstring.
          if (!eq(STACK_1,unbound))
            # *ERROR-HANDER* /= NIL
            { # Stackaufbau: nil, args, handler, errorstring.
              # (apply *error-handler* nil errorstring args) ausführen:
              check_SP(); check_STACK();
              {var reg1 object error_handler = STACK_1; STACK_1 = NIL;
               apply(error_handler,2,arguments);
               skipSTACK(2);
              }
              dynamic_unbind(); # Bindungsframe für sys::*recursive-error-count* auflösen,
                                # da keine Fehlermeldungs-Ausgabe mehr aktiv
              set_args_end_pointer(stackptr);
              break_driver(NIL); # Break-Driver aufrufen (kehrt nicht zurück)
            }
            else
            # *ERROR-HANDER* = NIL, SYS::*USE-CLCS* /= NIL
            { # Stackaufbau: type, args, --, errorstring.
              var reg1 object type = STACK_3;
              var reg5 object errorstring = STACK_0;
              skipSTACK(4);
              dynamic_unbind(); # Bindungsframe für sys::*recursive-error-count* auflösen
              # (APPLY #'coerce-to-condition errorstring args 'error type keyword-arguments)
              # ausführen:
              pushSTACK(errorstring); pushSTACK(arguments); pushSTACK(S(error)); pushSTACK(type);
             {var reg3 uintC argcount = 4;
              # arithmetic-error, division-by-zero, floating-point-overflow, floating-point-underflow
              #   --> ergänze :operation :operands ??
              # cell-error, uncound-variable, undefined-function
              #   --> ergänze :name
              if (eq(type,S(simple_cell_error))
                  || eq(type,S(simple_unbound_variable))
                  || eq(type,S(simple_undefined_function))
                 )
                { pushSTACK(S(Kname)); pushSTACK(BEFORE(stackptr)); # :name ...
                  argcount += 2;
                }
              # type-error --> ergänze :datum, :expected-type
              if (eq(type,S(simple_type_error)))
                { pushSTACK(S(Kexpected_type)); pushSTACK(BEFORE(stackptr)); # :expected-type ...
                  pushSTACK(S(Kdatum)); pushSTACK(BEFORE(stackptr)); # :datum ...
                  argcount += 4;
                }
              # package-error --> ergänze :package
              if (eq(type,S(simple_package_error)))
                { pushSTACK(S(Kpackage)); pushSTACK(BEFORE(stackptr)); # :package ...
                  argcount += 2;
                }
              # stream-error, end-of-file --> ergänze :stream
              if (eq(type,S(simple_stream_error))
                  || eq(type,S(simple_end_of_file))
                 )
                { pushSTACK(S(Kstream)); pushSTACK(BEFORE(stackptr)); # :stream ...
                  argcount += 2;
                }
              # file-error --> ergänze :pathname
              if (eq(type,S(simple_file_error)))
                { pushSTACK(S(Kpathname)); pushSTACK(BEFORE(stackptr)); # :pathname ...
                  argcount += 2;
                }
              funcall(S(coerce_to_condition),argcount); # (SYS::COERCE-TO-CONDITION ...)
              # set_args_end_pointer(stackptr); # wozu? macht das Debuggen nur schwieriger!
              pushSTACK(value1); # condition retten
              pushSTACK(value1); funcall(L(clcs_signal),1); # (SIGNAL condition)
              dynamic_bind(S(prin_stream),unbound); # SYS::*PRIN-STREAM* an #<UNBOUND> binden
              pushSTACK(STACK_(0+3)); # condition
              funcall(L(invoke_debugger),1); # (INVOKE-DEBUGGER condition)
            }}
        }}
      NOTREACHED
    }

# Fehlermeldung mit Errorstring. Kehrt nicht zurück.
# fehler(errortype,errorstring);
# > errortype: Condition-Typ
# > errorstring: Konstanter ASCIZ-String.
#   Bei jeder Tilde wird ein LISP-Objekt vom STACK genommen und statt der
#   Tilde ausgegeben.
# > auf dem STACK: Initialisierungswerte für die Condition, je nach errortype
  nonreturning_function(global, fehler, (conditiontype errortype, const char * errorstring));
  global void fehler(errortype,errorstring)
    var reg2 conditiontype errortype;
    var reg1 const char * errorstring;
    { begin_error(); # Fehlermeldung anfangen
      if (!nullp(STACK_3)) # *ERROR-HANDLER* = NIL, SYS::*USE-CLCS* /= NIL ?
        { # Error-Typ-Symbol zu errortype auswählen:
          var reg3 object sym = S(simple_condition); # erster Error-Typ
          sym = objectplus(sym,
                           (soint)(sizeof(*TheSymbol(sym))<<(oint_addr_shift-addr_shift))
                           * (uintL)errortype
                          );
          STACK_3 = sym;
        }
      end_error(write_errorstring(errorstring)); # Fehlermeldung ausgeben, beenden
    }

#ifdef ATARI
  # Behandlung von BIOS- und GEMDOS-Fehlern
  # OS_error(errorcode);
  # > sintW errorcode: negativer Fehlercode
    nonreturning_function(global, OS_error, (sintW errorcode));
    global void OS_error(errorcode)
      var reg2 sintW errorcode;
      { clr_break_sem_4(); # keine GEMDOS-Operation mehr aktiv
        begin_error(); # Fehlermeldung anfangen
       {var reg1 uintW errcode = -errorcode; # positive Fehlernummer
        # Meldungbeginn ausgeben:
        write_errorstring(errcode < 32
                           ? # Fehlernummern <32 kommen vom BIOS
                             (DEUTSCH ? "BIOS-Fehler " :
                              ENGLISH ? "BIOS error " :
                              FRANCAIS ? "Erreur BIOS " :
                              ""
                             )
                           : # Fehlernummern >=32 kommen vom GEMDOS
                             (DEUTSCH ? "GEMDOS-Fehler " :
                              ENGLISH ? "GEMDOS error " :
                              FRANCAIS ? "Erreur GEMDOS " :
                              ""
                             )
                         );
        # Fehlernummer ausgeben:
        write_errorobject(fixnum(errcode));
        # nach Möglichkeit noch ausführlicher:
        if (errcode < 68)
          {# Zu Fehlernummern <68 ist ein Text da.
           #ifdef LANGUAGE_STATIC
             #define lang3(deutsch,english,francais)  DEUTSCH ? deutsch : ENGLISH ? english : FRANCAIS ? francais : ""
             #define lang1(string)  string
             #define langcount  1
             #define language  0
           #else
             #define lang3(deutsch,english,francais)  english, deutsch, francais
             #define lang1(string)  string, string, string
             #define langcount  3
           #endif
           local const char* errormsg_table[68*langcount] = {
             /*  0 */ lang3( /* DEUTSCH */ "OK, kein Fehler" ,
                             /* ENGLISH */ "Ok, No error" ,
                             /* FRANCAIS */ "Ok, pas d'erreur"),
             /*  1 */ lang3( /* DEUTSCH */ "Allgemeiner Fehler" ,
                             /* ENGLISH */ "General error" ,
                             /* FRANCAIS */ "Erreur générale"),
             /*  2 */ lang3( /* DEUTSCH */ "Laufwerk nicht da oder nicht bereit" ,
                             /* ENGLISH */ "Drive not ready" ,
                             /* FRANCAIS */ "Unité de disque ne répond pas"),
             /*  3 */ lang3( /* DEUTSCH */ "Unbekannter Befehl" ,
                             /* ENGLISH */ "Unknown command" ,
                             /* FRANCAIS */ "Commande inconnue"),
             /*  4 */ lang3( /* DEUTSCH */ "Prüfsumme stimmt nicht" ,
                             /* ENGLISH */ "CRC error" ,
                             /* FRANCAIS */ "Mauvais CRC"),
             /*  5 */ lang3( /* DEUTSCH */ "Illegale Anforderung, ungültiger Befehl" ,
                             /* ENGLISH */ "Bad request (invalid command)" ,
                             /* FRANCAIS */ "Requête illégale (commande invalide)"),
             /*  6 */ lang3( /* DEUTSCH */ "Track nicht gefunden" ,
                             /* ENGLISH */ "Seek error (track not found)" ,
                             /* FRANCAIS */ "Piste non trouvée"),
             /*  7 */ lang3( /* DEUTSCH */ "Unknown media (ungültiger Bootsektor)" ,
                             /* ENGLISH */ "Unknown media" ,
                             /* FRANCAIS */ "Médium inconnu (secteur de boot invalide)"),
             /*  8 */ lang3( /* DEUTSCH */ "Sektor nicht gefunden" ,
                             /* ENGLISH */ "Sector not found" ,
                             /* FRANCAIS */ "Secteur non trouvé"),
             /*  9 */ lang3( /* DEUTSCH */ "Kein Papier" ,
                             /* ENGLISH */ "Printer error (no paper?)" ,
                             /* FRANCAIS */ "Plus de papier"),
             /* 10 */ lang3( /* DEUTSCH */ "Fehler beim Schreibzugriff" ,
                             /* ENGLISH */ "Write fault" ,
                             /* FRANCAIS */ "Erreur en écriture"),
             /* 11 */ lang3( /* DEUTSCH */ "Fehler beim Lesezugriff" ,
                             /* ENGLISH */ "Read fault" ,
                             /* FRANCAIS */ "Erreur en lecture"),
             /* 12 */ lang3( /* DEUTSCH */ "Allgemeiner Fehler" ,
                             /* ENGLISH */ "General error" ,
                             /* FRANCAIS */ "Erreur générale"),
             /* 13 */ lang3( /* DEUTSCH */ "Diskette schreibgeschützt" ,
                             /* ENGLISH */ "Disk write-protected" ,
                             /* FRANCAIS */ "Disquette protégée contre l'écriture"),
             /* 14 */ lang3( /* DEUTSCH */ "Diskette wurde gewechselt" ,
                             /* ENGLISH */ "Disk was changed" ,
                             /* FRANCAIS */ "La disquette fut changée"),
             /* 15 */ lang3( /* DEUTSCH */ "Unbekanntes Gerät" ,
                             /* ENGLISH */ "Unknown device" ,
                             /* FRANCAIS */ "Device inconnu"),
             /* 16 */ lang3( /* DEUTSCH */ "Fehlerhafter Sektor, nicht verifizierbar" ,
                             /* ENGLISH */ "Bad sector encountered during verify" ,
                             /* FRANCAIS */ "Trouvé mauvais secteur pendant validation"),
             /* 17 */ lang3( /* DEUTSCH */ "Diskette einlegen" ,
                             /* ENGLISH */ "No disk in drive" ,
                             /* FRANCAIS */ "Pas de disquette dans le lecteur"),
             /* 18 ... 31 */ lang1(""), lang1(""), lang1(""), lang1(""), lang1(""),
                             lang1(""), lang1(""), lang1(""), lang1(""), lang1(""),
                             lang1(""), lang1(""), lang1(""), lang1(""),
             /* 32 */ lang3( /* DEUTSCH */ "Ungültige Funktionsnummer" ,
                             /* ENGLISH */ "Invalid function number" ,
                             /* FRANCAIS */ "Numéro de fonction incorrect"),
             /* 33 */ lang3( /* DEUTSCH */ "Datei nicht gefunden" ,
                             /* ENGLISH */ "File not found" ,
                             /* FRANCAIS */ "Fichier non trouvé"),
             /* 34 */ lang3( /* DEUTSCH */ "Pfadname nicht gefunden" ,
                             /* ENGLISH */ "Path not found" ,
                             /* FRANCAIS */ "Chemin non trouvé"),
             /* 35 */ lang3( /* DEUTSCH */ "Zuviele offene Dateien" ,
                             /* ENGLISH */ "Too many files open" ,
                             /* FRANCAIS */ "Trop de fichiers ouverts"),
             /* 36 */ lang3( /* DEUTSCH */ "Zugriff verweigert" ,
                             /* ENGLISH */ "Access not possible" ,
                             /* FRANCAIS */ "Accès non possible"),
             /* 37 */ lang3( /* DEUTSCH */ "Ungültige Handle-Nummer" ,
                             /* ENGLISH */ "Invalid handle number" ,
                             /* FRANCAIS */ "numéro de descripteur de fichier invalide"),
             /* 38 */ lang1(""),
             /* 39 */ lang3( /* DEUTSCH */ "Nicht genügend Speicher" ,
                             /* ENGLISH */ "Not enough memory" ,
                             /* FRANCAIS */ "Pas assez de mémoire"),
             /* 40 */ lang3( /* DEUTSCH */ "Ungültige Speicherblockadresse" ,
                             /* ENGLISH */ "Invalid memory block address" ,
                             /* FRANCAIS */ "Adresse de bloc mémoire invalide"),
             /* 41 ... 45 */ lang1(""), lang1(""), lang1(""), lang1(""), lang1(""),
             /* 46 */ lang3( /* DEUTSCH */ "Ungültige Laufwerksbezeichnung" ,
                             /* ENGLISH */ "Invalid drive spec" ,
                             /* FRANCAIS */ "Mauvais descripteur de lecteur"),
             /* 47 */ lang1(""),
             /* 48 */ lang3( /* DEUTSCH */ "Datei müßte kopiert werden" ,
                             /* ENGLISH */ "Rename across disks impossible" ,
                             /* FRANCAIS */ "Le fichier devrait être copié"),
             /* 49 */ lang3( /* DEUTSCH */ "Keine weiteren Dateien" ,
                             /* ENGLISH */ "No more files" ,
                             /* FRANCAIS */ "Pas plus de fichiers"),
             /* 50 ... 63 */ lang1(""), lang1(""), lang1(""), lang1(""), lang1(""),
                             lang1(""), lang1(""), lang1(""), lang1(""), lang1(""),
                             lang1(""), lang1(""), lang1(""), lang1(""),
             /* 64 */ lang3( /* DEUTSCH */ "Bereichsüberschreitung" ,
                             /* ENGLISH */ "Range error, context unknown" ,
                             /* FRANCAIS */ "Valeur hors d'intervalle de validité"),
             /* 65 */ lang3( /* DEUTSCH */ "Interner Fehler (Diskettenwechsel?)" ,
                             /* ENGLISH */ "Internal error" ,
                             /* FRANCAIS */ "Erreur interne (changement de disquette?)"),
             /* 66 */ lang3( /* DEUTSCH */ "Kein ladbares Programm" ,
                             /* ENGLISH */ "Invalid program load format" ,
                             /* FRANCAIS */ "Fichier non exécutable"),
             /* 67 */ lang3( /* DEUTSCH */ "SETBLOCK darf nicht mehr Speicher belegen" ,
                             /* ENGLISH */ "SETBLOCK failed, growth restraints" ,
                             /* FRANCAIS */ "SETBLOCK ne peut pas occuper plus de mémoire"),
             };
           var reg2 const char* errormsg = errormsg_table[errcode*langcount+language];
           if (!(errormsg[0] == 0)) # nichtleere Meldung?
             { write_errorstring(": ");
               write_errorstring(errormsg);
             }
          }
        end_error(args_end_pointer STACKop 7); # Fehlermeldung beenden
      }}
#endif # ATARI

#ifdef AMIGAOS
  # Behandlung von AMIGAOS-Fehlern
  # OS_error();
  # > IoErr(): Fehlercode
    nonreturning_function(global, OS_error, (void));
    global void OS_error ()
      { var reg1 uintC errcode = IoErr(); # Fehlernummer
        end_system_call();
        clr_break_sem_4(); # keine AMIGAOS-Operation mehr aktiv
        begin_error(); # Fehlermeldung anfangen
        # Meldungbeginn ausgeben:
        write_errorstring(DEUTSCH ? "AmigaOS-Fehler " :
                          ENGLISH ? "Amiga OS error " :
                          FRANCAIS ? "Erreur S.E. Amiga " :
                          ""
                         );
        # Fehlernummer ausgeben:
        write_errorobject(fixnum(errcode));
        {
          #ifdef LANGUAGE_STATIC
            #define lang3(english,deutsch,francais)  ENGLISH ? english : DEUTSCH ? deutsch : FRANCAIS ? francais : ""
            #define lang1(string)  string
            #define langcount  1
            #define language  0
          #else
            #define lang3(english,deutsch,francais)  english, deutsch, francais
            #define lang1(string)  string, string, string
            #define langcount  3
          #endif
          local const char* error100_msg_table[23*(1+langcount)] = {
            /* 100 */ "", lang1(""),
            /* 101 */ "", lang1(""),
            /* 102 */ "", lang1(""),
            /* 103 */ "ERROR_NO_FREE_STORE",
                      lang3( /* ENGLISH */ "not enough memory available" ,
                             /* DEUTSCH */ "nicht genügend Speicher vorhanden" ,
                             /* FRANCAIS */ "Pas assez de mémoire"),
            /* 104 */ "", lang1(""),
            /* 105 */ "ERROR_TASK_TABLE_FULL",
                      lang3( /* ENGLISH */ "process table full" ,
                             /* DEUTSCH */ "keine weiteren CLI Prozesse mehr" ,
                             /* FRANCAIS */ "La table des processus est pleine"),
            /* 106 */ "", lang1(""),
            /* 107 */ "", lang1(""),
            /* 108 */ "", lang1(""),
            /* 109 */ "", lang1(""),
            /* 110 */ "", lang1(""),
            /* 111 */ "", lang1(""),
            /* 112 */ "", lang1(""),
            /* 113 */ "", lang1(""),
            /* 114 */ "ERROR_BAD_TEMPLATE",
                      lang3( /* ENGLISH */ "bad template" ,
                             /* DEUTSCH */ "ungültiges Muster" ,
                             /* FRANCAIS */ "mauvais schéma"),
            /* 115 */ "ERROR_BAD_NUMBER",
                      lang3( /* ENGLISH */ "bad number" ,
                             /* DEUTSCH */ "ungültige Zahl" ,
                             /* FRANCAIS */ "mauvais nombre"),
            /* 116 */ "ERROR_REQUIRED_ARG_MISSING",
                      lang3( /* ENGLISH */ "required argument missing" ,
                             /* DEUTSCH */ "benötigtes Schlüsselwort nicht vorhanden" ,
                             /* FRANCAIS */ "mot clé manque"),
            /* 117 */ "ERROR_KEY_NEEDS_ARG",
                      lang3( /* ENGLISH */ "value after keyword missing" ,
                             /* DEUTSCH */ "kein Wert nach Schlüsselwort vorhanden" ,
                             /* FRANCAIS */ "mot clé sans valeur"),
            /* 118 */ "ERROR_TOO_MANY_ARGS",
                      lang3( /* ENGLISH */ "wrong number of arguments" ,
                             /* DEUTSCH */ "falsche Anzahl Argumente" ,
                             /* FRANCAIS */ "mauvais nombre d'arguments"),
            /* 119 */ "ERROR_UNMATCHED_QUOTES",
                      lang3( /* ENGLISH */ "unmatched quotes" ,
                             /* DEUTSCH */ "ausstehende Anführungszeichen" ,
                             /* FRANCAIS */ "guillemets non terminés"),
            /* 120 */ "ERROR_LINE_TOO_LONG",
                      lang3( /* ENGLISH */ "argument line invalid or too long" ,
                             /* DEUTSCH */ "ungültige Zeile oder Zeile zu lang" ,
                             /* FRANCAIS */ "ligne est mauvaise ou trop longue"),
            /* 121 */ "ERROR_FILE_NOT_OBJECT",
                      lang3( /* ENGLISH */ "file is not executable" ,
                             /* DEUTSCH */ "Datei ist nicht ausführbar" ,
                             /* FRANCAIS */ "fichier non exécutable"),
            /* 122 */ "ERROR_INVALID_RESIDENT_LIBRARY",
                      lang3( /* ENGLISH */ "invalid resident library" ,
                             /* DEUTSCH */ "ungültige residente Library" ,
                             /* FRANCAIS */ "Librarie résidente non valide"),
            };
          local const char* error200_msg_table[44*(1+langcount)] = {
            /* 200 */ "", lang1(""),
            /* 201 */ "ERROR_NO_DEFAULT_DIR",
                      lang3( /* ENGLISH */ "" ,
                             /* DEUTSCH */ "" ,
                             /* FRANCAIS */ ""),
            /* 202 */ "ERROR_OBJECT_IN_USE",
                      lang3( /* ENGLISH */ "object is in use" ,
                             /* DEUTSCH */ "Objekt wird schon benutzt" ,
                             /* FRANCAIS */ "l'objet est utilisé"),
            /* 203 */ "ERROR_OBJECT_EXISTS",
                      lang3( /* ENGLISH */ "object already exists" ,
                             /* DEUTSCH */ "Objekt existiert bereits" ,
                             /* FRANCAIS */ "l'objet existe déjà"),
            /* 204 */ "ERROR_DIR_NOT_FOUND",
                      lang3( /* ENGLISH */ "directory not found" ,
                             /* DEUTSCH */ "Verzeichnis nicht gefunden" ,
                             /* FRANCAIS */ "répertoire non trouvé"),
            /* 205 */ "ERROR_OBJECT_NOT_FOUND",
                      lang3( /* ENGLISH */ "object not found" ,
                             /* DEUTSCH */ "Objekt nicht gefunden" ,
                             /* FRANCAIS */ "objet non trouvé"),
            /* 206 */ "ERROR_BAD_STREAM_NAME",
                      lang3( /* ENGLISH */ "invalid window description" ,
                             /* DEUTSCH */ "ungültige Fensterbeschreibung" ,
                             /* FRANCAIS */ "mauvais descripteur de fenêtre"),
            /* 207 */ "ERROR_OBJECT_TOO_LARGE",
                      lang3( /* ENGLISH */ "object too large" ,
                             /* DEUTSCH */ "Objekt zu groß" ,
                             /* FRANCAIS */ "objet trop grand"),
            /* 208 */ "", lang1(""),
            /* 209 */ "ERROR_ACTION_NOT_KNOWN",
                      lang3( /* ENGLISH */ "packet request type unknown" ,
                             /* DEUTSCH */ "unbekannter Pakettyp" , # ??
                             /* FRANCAIS */ "Type de paquet inconnu"),
            /* 210 */ "ERROR_INVALID_COMPONENT_NAME",
                      lang3( /* ENGLISH */ "object name invalid" ,
                             /* DEUTSCH */ "ungültiger Objektname" ,
                             /* FRANCAIS */ "nom d'objet incorrect"),
            /* 211 */ "ERROR_INVALID_LOCK",
                      lang3( /* ENGLISH */ "invalid object lock" ,
                             /* DEUTSCH */ "ungültiger Objektlock" ,
                             /* FRANCAIS */ "«lock» invalide d'un objet"),
            /* 212 */ "ERROR_OBJECT_WRONG_TYPE",
                      lang3( /* ENGLISH */ "object is not of required type" ,
                             /* DEUTSCH */ "Objekt ist nicht von benötigten Typ" ,
                             /* FRANCAIS */ "objet de mauvais type"),
            /* 213 */ "ERROR_DISK_NOT_VALIDATED",
                      lang3( /* ENGLISH */ "disk not validated" ,
                             /* DEUTSCH */ "Datenträger ist nicht validiert" ,
                             /* FRANCAIS */ "volume non validé"),
            /* 214 */ "ERROR_DISK_WRITE_PROTECTED",
                      lang3( /* ENGLISH */ "disk is write-protected" ,
                             /* DEUTSCH */ "Datenträger ist schreibgeschützt" ,
                             /* FRANCAIS */ "disquette protégée contre l'écriture"),
            /* 215 */ "ERROR_RENAME_ACROSS_DEVICES",
                      lang3( /* ENGLISH */ "rename across devices attempted" ,
                             /* DEUTSCH */ "rename über Laufwerke versucht" ,
                             /* FRANCAIS */ "«rename» à travers des unités distinctes"),
            /* 216 */ "ERROR_DIRECTORY_NOT_EMPTY",
                      lang3( /* ENGLISH */ "directory not empty" ,
                             /* DEUTSCH */ "Verzeichnis ist nicht leer" ,
                             /* FRANCAIS */ "répertoire non vide"),
            /* 217 */ "ERROR_TOO_MANY_LEVELS",
                      lang3( /* ENGLISH */ "too many levels" ,
                             /* DEUTSCH */ "zu viele Verweise" ,
                             /* FRANCAIS */ "trop de niveaux"),
            /* 218 */ "ERROR_DEVICE_NOT_MOUNTED",
                      lang3( /* ENGLISH */ "device (or volume) is not mounted" ,
                             /* DEUTSCH */ "Datenträger ist in keinem Laufwerk" ,
                             /* FRANCAIS */ "l'unité n'est dans aucun lecteur"),
            /* 219 */ "ERROR_SEEK_ERROR",
                      lang3( /* ENGLISH */ "seek failure" ,
                             /* DEUTSCH */ "seek schlug fehl" ,
                             /* FRANCAIS */ "erreur pendant un déplacement (seek)"),
            /* 220 */ "ERROR_COMMENT_TOO_BIG",
                      lang3( /* ENGLISH */ "comment is too long" ,
                             /* DEUTSCH */ "Kommentar ist zu lang" ,
                             /* FRANCAIS */ "Commentaire trop long"),
            /* 221 */ "ERROR_DISK_FULL",
                      lang3( /* ENGLISH */ "disk is full" ,
                             /* DEUTSCH */ "Datenträger ist voll" ,
                             /* FRANCAIS */ "support plein"),
            /* 222 */ "ERROR_DELETE_PROTECTED",
                      lang3( /* ENGLISH */ "object is protected from deletion" ,
                             /* DEUTSCH */ "Datei ist gegen Löschen geschützt" ,
                             /* FRANCAIS */ "objet est protégé contre l'effacement"),
            /* 223 */ "ERROR_WRITE_PROTECTED",
                      lang3( /* ENGLISH */ "file is write protected" ,
                             /* DEUTSCH */ "Datei ist schreibgeschützt" ,
                             /* FRANCAIS */ "fichier protégé contre l'écriture"),
            /* 224 */ "ERROR_READ_PROTECTED",
                      lang3( /* ENGLISH */ "file is read protected" ,
                             /* DEUTSCH */ "Datei ist lesegeschützt" ,
                             /* FRANCAIS */ "fichier protégé contre la lecture"),
            /* 225 */ "ERROR_NOT_A_DOS_DISK",
                      lang3( /* ENGLISH */ "not a valid DOS disk" ,
                             /* DEUTSCH */ "kein gültiger DOS-Datenträger" ,
                             /* FRANCAIS */ "disque non DOS"),
            /* 226 */ "ERROR_NO_DISK",
                      lang3( /* ENGLISH */ "no disk in drive" ,
                             /* DEUTSCH */ "kein Datenträger im Laufwerk" ,
                             /* FRANCAIS */ "pas de disquette dans le lecteur"),
            /* 227 */ "", lang1(""),
            /* 228 */ "", lang1(""),
            /* 229 */ "", lang1(""),
            /* 230 */ "", lang1(""),
            /* 231 */ "", lang1(""),
            /* 232 */ "ERROR_NO_MORE_ENTRIES",
                      lang3( /* ENGLISH */ "no more entries in directory" ,
                             /* DEUTSCH */ "keine weiteren Verzeichniseinträge mehr" ,
                             /* FRANCAIS */ "pas plus d'entrées dans le répertoire"),
            /* 233 */ "ERROR_IS_SOFT_LINK",
                      lang3( /* ENGLISH */ "object is soft link" ,
                             /* DEUTSCH */ "Objekt ist ein Softlink" ,
                             /* FRANCAIS */ "l'objet est un «soft link»"),
            /* 234 */ "ERROR_OBJECT_LINKED",
                      lang3( /* ENGLISH */ "object is linked" ,
                             /* DEUTSCH */ "Objekt ist gelinkt" ,
                             /* FRANCAIS */ "l'objet est lié"),
            /* 235 */ "ERROR_BAD_HUNK",
                      lang3( /* ENGLISH */ "bad loadfile hunk" ,
                             /* DEUTSCH */ "Datei teilweise nicht ladbar" ,
                             /* FRANCAIS */ "fichier pas entièrement chargeable"),
            /* 236 */ "ERROR_NOT_IMPLEMENTED",
                      lang3( /* ENGLISH */ "function not implemented" ,
                             /* DEUTSCH */ "unimplementierte Funktion" ,
                             /* FRANCAIS */ "fonction non implémentée"),
            /* 237 */ "", lang1(""),
            /* 238 */ "", lang1(""),
            /* 239 */ "", lang1(""),
            /* 240 */ "ERROR_RECORD_NOT_LOCKED",
                      lang3( /* ENGLISH */ "record not locked" ,
                             /* DEUTSCH */ "" ,
                             /* FRANCAIS */ ""),
            /* 241 */ "ERROR_LOCK_COLLISION",
                      lang3( /* ENGLISH */ "record lock collision" ,
                             /* DEUTSCH */ "" ,
                             /* FRANCAIS */ ""),
            /* 242 */ "ERROR_LOCK_TIMEOUT",
                      lang3( /* ENGLISH */ "record lock timeout" ,
                             /* DEUTSCH */ "" ,
                             /* FRANCAIS */ ""),
            /* 243 */ "ERROR_UNLOCK_ERROR",
                      lang3( /* ENGLISH */ "record unlock error" ,
                             /* DEUTSCH */ "" ,
                             /* FRANCAIS */ ""),
            };
          local const char* error300_msg_table[6*(1+langcount)] = {
            /* 300 */ "", lang1(""),
            /* 301 */ "", lang1(""),
            /* 302 */ "", lang1(""),
            /* 303 */ "ERROR_BUFFER_OVERFLOW",
                      lang3( /* ENGLISH */ "buffer overflow" ,
                             /* DEUTSCH */ "Puffer-Überlauf" ,
                             /* FRANCAIS */ "débordement de tampon"),
            /* 304 */ "ERROR_BREAK",
                      lang3( /* ENGLISH */ "break" ,
                             /* DEUTSCH */ "Unterbrechung" ,
                             /* FRANCAIS */ "interruption"),
            /* 305 */ "ERROR_NOT_EXECUTABLE",
                      lang3( /* ENGLISH */ "file not executable" ,
                             /* DEUTSCH */ "Datei ist nicht ausführbar" ,
                             /* FRANCAIS */ "fichier non exécutable"),
            };
          var reg3 const char* errorname = "";
          var reg3 const char* errormsg = "";
          var reg2 uintC index;
          if (errcode == 0)
            { errorname = "";
              errormsg =
                /*  0 */ DEUTSCH ? "OK, kein Fehler" :
                         ENGLISH ? "Ok, No error" :
                         FRANCAIS ? "Ok, pas d'erreur" :
                         "";
            }
          elif ((index = errcode-100) < 23)
            { errorname = error100_msg_table[index*(1+langcount)];
              errormsg = error100_msg_table[index*(1+langcount)+1+language];
            }
          elif ((index = errcode-200) < 44)
            { errorname = error200_msg_table[index*(1+langcount)];
              errormsg = error200_msg_table[index*(1+langcount)+1+language];
            }
          elif ((index = errcode-300) < 6)
            { errorname = error300_msg_table[index*(1+langcount)];
              errormsg = error300_msg_table[index*(1+langcount)+1+language];
            }
          if (!(errorname[0] == 0)) # bekannter Name?
            { write_errorstring(" (");
              write_errorstring(errorname);
              write_errorstring(")");
            }
          if (!(errormsg[0] == 0)) # nichtleere Meldung?
            { write_errorstring(": ");
              write_errorstring(errormsg);
            }
        }
        # Fehlercode löschen (fürs nächste Mal):
        ((struct Process *)FindTask(NULL))->pr_Result2 = 0L;
        end_error(args_end_pointer STACKop 7); # Fehlermeldung beenden
      }
#endif

#ifdef DJUNIX
  # Behandlung von DJUNIX-(DOS-)Fehlern
  # OS_error();
  # > int errno: Fehlercode
    nonreturning_function(global, OS_error, (void));
    global void OS_error ()
      { var reg1 uintC errcode = errno; # positive Fehlernummer
        end_system_call();
        clr_break_sem_4(); # keine DOS-Operation mehr aktiv
        begin_error(); # Fehlermeldung anfangen
        # Meldungbeginn ausgeben:
        write_errorstring(DEUTSCH ? "DJDOS-Fehler " :
                          ENGLISH ? "DJDOS error " :
                          FRANCAIS ? "Erreur DJDOS " :
                          ""
                         );
        # Fehlernummer ausgeben:
        write_errorobject(fixnum(errcode));
        # nach Möglichkeit noch ausführlicher:
        if (errcode < 36)
          {# Zu Fehlernummern <36 ist ein Text da.
           #ifdef LANGUAGE_STATIC
             #define lang3(english,deutsch,francais)  ENGLISH ? english : DEUTSCH ? deutsch : FRANCAIS ? francais : ""
             #define lang1(string)  string
             #define langcount  1
             #define language  0
           #else
             #define lang3(english,deutsch,francais)  english, deutsch, francais
             #define lang1(string)  string, string, string
             #define langcount  3
           #endif
           local const char* errormsg_table[36*(1+langcount)] = {
             /*  0 */ "", lang1(""),
             /*  1 */ "ENOSYS",
                      lang3( /* ENGLISH */ "Function not implemented" ,
                             /* DEUTSCH */ "Funktion ist nicht implementiert" ,
                             /* FRANCAIS */ "fonction non implémentée"),
             /*  2 */ "ENOENT",
                      lang3( /* ENGLISH */ "No such file or directory" ,
                             /* DEUTSCH */ "File oder Directory existiert nicht" ,
                             /* FRANCAIS */ "fichier ou répertoire non existant"),
             /*  3 */ "ENOTDIR",
                      lang3( /* ENGLISH */ "Not a directory" ,
                             /* DEUTSCH */ "Das ist kein Directory" ,
                             /* FRANCAIS */ "n'est pas un répertoire"),
             /*  4 */ "EMFILE",
                      lang3( /* ENGLISH */ "Too many open files" ,
                             /* DEUTSCH */ "Zu viele offene Files" ,
                             /* FRANCAIS */ "Trop de fichiers ouverts"),
             /*  5 */ "EACCES",
                      lang3( /* ENGLISH */ "Permission denied" ,
                             /* DEUTSCH */ "Keine Berechtigung" ,
                             /* FRANCAIS */ "Accès dénié"),
             /*  6 */ "EBADF",
                      lang3( /* ENGLISH */ "Bad file number" ,
                             /* DEUTSCH */ "File-Descriptor wurde nicht für diese Operation geöffnet" ,
                             /* FRANCAIS */ "descripteur de fichier non alloué"),
             /*  7 */ "EARENA",
                      lang3( /* ENGLISH */ "Memory control blocks destroyed" ,
                             /* DEUTSCH */ "Speicherverwaltung ist durcheinander" ,
                             /* FRANCAIS */ "gestionnaire de mémoire perdu"),
             /*  8 */ "ENOMEM",
                      lang3( /* ENGLISH */ "Not enough memory" ,
                             /* DEUTSCH */ "Hauptspeicher oder Swapspace reicht nicht" ,
                             /* FRANCAIS */ "Pas assez de mémoire"),
             /*  9 */ "ESEGV",
                      lang3( /* ENGLISH */ "Invalid memory address" ,
                             /* DEUTSCH */ "Ungültige Speicher-Adresse" ,
                             /* FRANCAIS */ "adresse mémoire illicite"),
             /* 10 */ "EBADENV",
                      lang3( /* ENGLISH */ "Invalid environment" ,
                             /* DEUTSCH */ "Ungültiges Environment" ,
                             /* FRANCAIS */ "environnement incorrect"),
             /* 11 */ "", lang1(""),
             /* 12 */ "EACCODE",
                      lang3( /* ENGLISH */ "Invalid access code" ,
                             /* DEUTSCH */ "Ungültiger Zugriffsmodus" ,
                             /* FRANCAIS */ "mode d'accès illégal"),
             /* 13...14 */ "", lang1(""), "", lang1(""),
             /* 15 */ "ENODEV",
                      lang3( /* ENGLISH */ "No such device" ,
                             /* DEUTSCH */ "Gerät nicht da oder unpassend" ,
                             /* FRANCAIS */ "il n'y a pas de telle unité"),
             /* 16 */ "ECURDIR",
                      lang3( /* ENGLISH */ "Attempt to remove the current directory" ,
                             /* DEUTSCH */ "Das aktuelle Verzeichnis kann nicht entfernt werden" ,
                             /* FRANCAIS */ "Le répertoire courant ne peut pas être effacé"),
             /* 17 */ "ENOTSAME",
                      lang3( /* ENGLISH */ "Can't move to other than the same device" ,
                             /* DEUTSCH */ "Verschieben geht nicht über Laufwerksgrenzen hinweg" ,
                             /* FRANCAIS */ "ne peux pas déplacer au-delà de l'unité"),
             /* 18 */ "ENOMORE",
                      lang3( /* ENGLISH */ "No more files" ,
                             /* DEUTSCH */ "Keine weiteren Dateien" ,
                             /* FRANCAIS */ "pas plus de fichier"),
             /* 19 */ "EINVAL",
                      lang3( /* ENGLISH */ "Invalid argument" ,
                             /* DEUTSCH */ "Ungültiger Parameter" ,
                             /* FRANCAIS */ "Paramètre illicite"),
             /* 20 */ "E2BIG",
                      lang3( /* ENGLISH */ "Arg list too long" ,
                             /* DEUTSCH */ "Zu lange Argumentliste" ,
                             /* FRANCAIS */ "liste d'arguments trop longue"),
             /* 21 */ "ENOEXEC",
                      lang3( /* ENGLISH */ "Exec format error" ,
                             /* DEUTSCH */ "Kein ausführbares Programm" ,
                             /* FRANCAIS */ "Programme non exécutable"),
             /* 22 */ "EXDEV",
                      lang3( /* ENGLISH */ "Cross-device link" ,
                             /* DEUTSCH */ "Links können nur aufs selbe Gerät gehen" ,
                             /* FRANCAIS */ "liens uniquement sur la même unité"),
             /* 23...27 */ "", lang1(""), "", lang1(""), "", lang1(""), "", lang1(""), "", lang1(""),
             /* 28...32 */ "", lang1(""), "", lang1(""), "", lang1(""), "", lang1(""), "", lang1(""),
             /* 33 */ "EDOM",
                      lang3( /* ENGLISH */ "Argument out of domain" ,
                             /* DEUTSCH */ "Argument zu mathematischer Funktion außerhalb des Definitionsbereichs" ,
                             /* FRANCAIS */ "argument hors du domaine de définition d'une fonction mathématique"),
             /* 34 */ "ERANGE",
                      lang3( /* ENGLISH */ "Result too large" ,
                             /* DEUTSCH */ "Ergebnis mathematischer Funktion zu groß" ,
                             /* FRANCAIS */ "débordement de valeur"),
             /* 35 */ "EEXIST",
                      lang3( /* ENGLISH */ "File exists" ,
                             /* DEUTSCH */ "File existiert schon" ,
                             /* FRANCAIS */ "Le fichier existe déjà"),
             };
           var reg2 const char* errorname = errormsg_table[errcode*(1+langcount)];
           var reg2 const char* errormsg = errormsg_table[errcode*(1+langcount)+1+language];
           if (!(errorname[0] == 0)) # bekannter Name?
             { write_errorstring(" (");
               write_errorstring(errorname);
               write_errorstring(")");
             }
           if (!(errormsg[0] == 0)) # nichtleere Meldung?
             { write_errorstring(": ");
               write_errorstring(errormsg);
             }
          }
        end_error(args_end_pointer STACKop 7); # Fehlermeldung beenden
      }
  # Ausgabe eines Fehlers, direkt übers Betriebssystem
  # errno_out(errorcode);
  # > int errorcode: Fehlercode
    global void errno_out (int errorcode);
    global void errno_out(errorcode)
      var reg1 int errorcode;
      { asciz_out(" errno = "); dez_out(errorcode); asciz_out("." CRLFstring); }
#endif

#if defined(UNIX) || defined(EMUNIX) || defined(WATCOM) || defined(RISCOS)

  # Behandlung von UNIX-Fehlern
  # OS_error();
  # > int errno: Fehlercode
    nonreturning_function(global, OS_error, (void));

  # Problem: viele verschiedene UNIX-Versionen, jede wieder mit anderen
  # Fehlermeldungen.
  # Abhilfe: Die Fehlernamen sind einigermaßen portabel. Die englische
  # Fehlermeldung übernehmen wir, die Übersetzungen machen wir selbst.
  # Französische Fehlermeldungen von Tristan <marc@david.saclay.cea.fr>.

  #if !(defined(UNIX) || defined(EMUNIX) || defined(WATCOM)) # Konflikt mit unix.d bzw. msdos.d bzw. <stdlib.h> vermeiden
    extern int sys_nerr; # Anzahl der Betriebssystem-Fehlermeldungen
    extern char* sys_errlist[]; # Betriebssystem-Fehlermeldungen
  #endif

  # Tabelle der Fehlermeldungen und ihrer Namen:
    typedef struct { const char* name; const char* msg; } os_error;
    local os_error* errormsg_table;

  # Initialisierung der Tabelle:
    global int init_errormsg_table (void);
    global int init_errormsg_table()
      { var reg1 uintC i;
        begin_system_call();
        errormsg_table = (os_error*) malloc(sys_nerr * sizeof(os_error));
        end_system_call();
        if (errormsg_table == NULL) # Speicher reicht nicht?
          { return -1; }
        # Tabelle vor-initialisieren:
        for (i=0; i<sys_nerr; i++)
          { errormsg_table[i].name = "";
            errormsg_table[i].msg = sys_errlist[i];
          }
        # Tabelle initialisieren:
        /* allgemein verbreitete UNIX-Errors: */
        #ifdef EPERM
        errormsg_table[EPERM].name = "EPERM";
        errormsg_table[EPERM].msg =
          #if !defined(UNIX_LINUX)
          ENGLISH ? "Not owner" :
          #else
          ENGLISH ? "Operation not permitted" :
          #endif
          DEUTSCH ? "Keine Berechtigung dazu" :
          FRANCAIS ? "Opération non autorisée" :
          "";
        #endif
        #ifdef ENOENT
        errormsg_table[ENOENT].name = "ENOENT";
        errormsg_table[ENOENT].msg =
          ENGLISH ? "No such file or directory" :
          DEUTSCH ? "File oder Directory existiert nicht" :
          FRANCAIS ? "Fichier ou répertoire inéxistant" :
          "";
        #endif
        #ifdef ESRCH
        errormsg_table[ESRCH].name = "ESRCH";
        errormsg_table[ESRCH].msg =
          ENGLISH ? "No such process" :
          DEUTSCH ? "Dieser Prozeß existiert nicht (mehr)" :
          FRANCAIS ? "Processus inexistant" :
          "";
        #endif
        #ifdef EINTR
        errormsg_table[EINTR].name = "EINTR";
        errormsg_table[EINTR].msg =
          ENGLISH ? "Interrupted system call" :
          DEUTSCH ? "Unterbrechung während Betriebssystem-Aufruf" :
          FRANCAIS ? "Appel système interrompu" :
          "";
        #endif
        #ifdef EIO
        errormsg_table[EIO].name = "EIO";
        errormsg_table[EIO].msg =
          ENGLISH ? "I/O error" :
          DEUTSCH ? "Fehler bei Schreib-/Lesezugriff" :
          FRANCAIS ? "Erreur E/S" :
          "";
        #endif
        #ifdef ENXIO
        errormsg_table[ENXIO].name = "ENXIO";
        errormsg_table[ENXIO].msg =
          ENGLISH ? "No such device or address" :
          DEUTSCH ? "Gerät existiert nicht oder Laufwerk leer" :
          FRANCAIS ? "Périphérique ou adresse inexistant" :
          "";
        #endif
        #ifdef E2BIG
        errormsg_table[E2BIG].name = "E2BIG";
        errormsg_table[E2BIG].msg =
          ENGLISH ? "Arg list too long" :
          DEUTSCH ? "Zu lange Argumentliste" :
          FRANCAIS ? "Liste d'arguments trop longue" :
          "";
        #endif
        #ifdef ENOEXEC
        errormsg_table[ENOEXEC].name = "ENOEXEC";
        errormsg_table[ENOEXEC].msg =
          ENGLISH ? "Exec format error" :
          DEUTSCH ? "Kein ausführbares Programm" :
          FRANCAIS ? "Erreur sur le format exécutable" :
          "";
        #endif
        #ifdef EBADF
        errormsg_table[EBADF].name = "EBADF";
        errormsg_table[EBADF].msg =
          ENGLISH ? "Bad file number" :
          DEUTSCH ? "File-Descriptor wurde nicht für diese Operation geöffnet" :
          FRANCAIS ? "Mauvais numéro de fichier" :
          "";
        #endif
        #ifdef ECHILD
        errormsg_table[ECHILD].name = "ECHILD";
        errormsg_table[ECHILD].msg =
          ENGLISH ? "No child processes" :
          DEUTSCH ? "Worauf warten?" :
          FRANCAIS ? "Pas de processus fils" :
          "";
        #endif
        #ifdef EAGAIN
        errormsg_table[EAGAIN].name = "EAGAIN";
        errormsg_table[EAGAIN].msg =
          ENGLISH ? "No more processes" :
          DEUTSCH ? "Kann keinen weiteren Prozeß erzeugen" :
          FRANCAIS ? "Essayez encore" :
          "";
        #endif
        #ifdef ENOMEM
        errormsg_table[ENOMEM].name = "ENOMEM";
        errormsg_table[ENOMEM].msg =
          ENGLISH ? "Not enough memory" :
          #if !defined(UNIX_SUNOS4)
          DEUTSCH ? "Hauptspeicher oder Swapspace reicht nicht" :
          #else
          DEUTSCH ? "Speicher-Adreßbereich oder Swapspace reicht nicht" :
          #endif
          FRANCAIS ? "Plus de mémoire" :
          "";
        #endif
        #ifdef EACCES
        errormsg_table[EACCES].name = "EACCES";
        errormsg_table[EACCES].msg =
          ENGLISH ? "Permission denied" :
          DEUTSCH ? "Keine Berechtigung" :
          FRANCAIS ? "Permission refusée" :
          "";
        #endif
        #ifdef EFAULT
        errormsg_table[EFAULT].name = "EFAULT";
        errormsg_table[EFAULT].msg =
          ENGLISH ? "Bad address" :
          DEUTSCH ? "Ungültige Adresse" :
          FRANCAIS ? "Mauvaise adresse" :
          "";
        #endif
        #ifdef ENOTBLK
        errormsg_table[ENOTBLK].name = "ENOTBLK";
        errormsg_table[ENOTBLK].msg =
          ENGLISH ? "Block device required" :
          DEUTSCH ? "Nur block-strukturierte Geräte erlaubt" :
          FRANCAIS ? "Périphérique bloc requis" :
          "";
        #endif
        #ifdef EBUSY
        errormsg_table[EBUSY].name = "EBUSY";
        errormsg_table[EBUSY].msg =
          #if !defined(UNIX_SUNOS4)
          ENGLISH ? "Mount device busy" :
          DEUTSCH ? "Gerät enthält Einheit und darf sie nicht auswerfen" :
          #else
          ENGLISH ? "Device busy" :
          DEUTSCH ? "Filesystem darf nicht gekappt werden" :
          #endif
          FRANCAIS ? "Périphérique occupé" :
          "";
        #endif
        #ifdef EEXIST
        errormsg_table[EEXIST].name = "EEXIST";
        errormsg_table[EEXIST].msg =
          ENGLISH ? "File exists" :
          DEUTSCH ? "File existiert schon" :
          FRANCAIS ? "Le fichier existe" :
          "";
        #endif
        #ifdef EXDEV
        errormsg_table[EXDEV].name = "EXDEV";
        errormsg_table[EXDEV].msg =
          ENGLISH ? "Cross-device link" :
          DEUTSCH ? "Links können nur aufs selbe Gerät gehen" :
          FRANCAIS ? "Lien entre périphériques différents" :
          "";
        #endif
        #ifdef ENODEV
        errormsg_table[ENODEV].name = "ENODEV";
        errormsg_table[ENODEV].msg =
          ENGLISH ? "No such device" :
          DEUTSCH ? "Gerät nicht da oder unpassend" :
          FRANCAIS ? "Périphérique inexistant" :
          "";
        #endif
        #ifdef ENOTDIR
        errormsg_table[ENOTDIR].name = "ENOTDIR";
        errormsg_table[ENOTDIR].msg =
          ENGLISH ? "Not a directory" :
          DEUTSCH ? "Das ist kein Directory" :
          FRANCAIS ? "N'est pas un répertoire" :
          "";
        #endif
        #ifdef EISDIR
        errormsg_table[EISDIR].name = "EISDIR";
        errormsg_table[EISDIR].msg =
          ENGLISH ? "Is a directory" :
          DEUTSCH ? "Das ist ein Directory" :
          FRANCAIS ? "Est un répertoire" :
          "";
        #endif
        #ifdef EINVAL
        errormsg_table[EINVAL].name = "EINVAL";
        errormsg_table[EINVAL].msg =
          ENGLISH ? "Invalid argument" :
          DEUTSCH ? "Ungültiger Parameter" :
          FRANCAIS ? "Argument invalide" :
          "";
        #endif
        #ifdef ENFILE
        errormsg_table[ENFILE].name = "ENFILE";
        errormsg_table[ENFILE].msg =
          ENGLISH ? "File table overflow" :
          DEUTSCH ? "Tabelle der offenen Files ist voll" :
          FRANCAIS ? "Dépassement de la table des fichiers" :
          "";
        #endif
        #ifdef EMFILE
        errormsg_table[EMFILE].name = "EMFILE";
        errormsg_table[EMFILE].msg =
          ENGLISH ? "Too many open files" :
          DEUTSCH ? "Zu viele offene Files" :
          FRANCAIS ? "Trop de fichiers ouverts" :
          "";
        #endif
        #ifdef ENOTTY
        errormsg_table[ENOTTY].name = "ENOTTY";
        errormsg_table[ENOTTY].msg =
          ENGLISH ? "Inappropriate ioctl for device" :
          DEUTSCH ? "Falscher Gerätetyp" :
          FRANCAIS ? "Périphérique ne comprend pas ce ioctl" :
          "";
        #endif
        #ifdef ETXTBSY
        errormsg_table[ETXTBSY].name = "ETXTBSY";
        errormsg_table[ETXTBSY].msg =
          ENGLISH ? "Text file busy" :
          DEUTSCH ? "Programm wird gerade geändert oder ausgeführt" :
          FRANCAIS ? "Fichier code occupé" :
          "";
        #endif
        #ifdef EFBIG
        errormsg_table[EFBIG].name = "EFBIG";
        errormsg_table[EFBIG].msg =
          ENGLISH ? "File too large" :
          DEUTSCH ? "Zu großes File" :
          FRANCAIS ? "Fichier trop grand" :
          "";
        #endif
        #ifdef ENOSPC
        errormsg_table[ENOSPC].name = "ENOSPC";
        errormsg_table[ENOSPC].msg =
          ENGLISH ? "No space left on device" :
          DEUTSCH ? "Platte oder Diskette voll" :
          FRANCAIS ? "Plus d'espace libre sur le périphérique" :
          "";
        #endif
        #ifdef ESPIPE
        errormsg_table[ESPIPE].name = "ESPIPE";
        errormsg_table[ESPIPE].msg =
          ENGLISH ? "Illegal seek" :
          DEUTSCH ? "Nicht positionierbares File" :
          FRANCAIS ? "seek illégal" :
          "";
        #endif
        #ifdef EROFS
        errormsg_table[EROFS].name = "EROFS";
        errormsg_table[EROFS].msg =
          ENGLISH ? "Read-only file system" :
          DEUTSCH ? "Dieses Filesystem erlaubt keinen Schreibzugriff" :
          FRANCAIS ? "Système de fichiers en lecture seulement" :
          "";
        #endif
        #ifdef EMLINK
        errormsg_table[EMLINK].name = "EMLINK";
        errormsg_table[EMLINK].msg =
          ENGLISH ? "Too many links" :
          DEUTSCH ? "Zu viele Links auf ein File" :
          FRANCAIS ? "Trop de liens" :
          "";
        #endif
        #ifdef EPIPE
        errormsg_table[EPIPE].name = "EPIPE";
        errormsg_table[EPIPE].msg =
          ENGLISH ? "Broken pipe" :
          DEUTSCH ? "Output versackt" :
          FRANCAIS ? "Rupture du tuyau" :
          "";
        #endif
        /* Errors bei mathematischen Funktionen: */
        #ifdef EDOM
        errormsg_table[EDOM].name = "EDOM";
        errormsg_table[EDOM].msg =
          ENGLISH ? "Argument out of domain" :
          DEUTSCH ? "Argument zu mathematischer Funktion außerhalb des Definitionsbereichs" :
          FRANCAIS ? "Argument mathématique en dehors du domaine de définition de la fonction" :
          "";
        #endif
        #ifdef ERANGE
        errormsg_table[ERANGE].name = "ERANGE";
        errormsg_table[ERANGE].msg =
          ENGLISH ? "Result too large" :
          DEUTSCH ? "Ergebnis mathematischer Funktion zu groß" :
          FRANCAIS ? "Résultat mathématique non représentable" :
          "";
        #endif
        /* Errors bei Non-Blocking I/O und Interrupt I/O: */
        #ifdef EWOULDBLOCK
        errormsg_table[EWOULDBLOCK].name = "EWOULDBLOCK";
        errormsg_table[EWOULDBLOCK].msg =
          ENGLISH ? "Operation would block" :
          DEUTSCH ? "Darauf müßte gewartet werden" :
          FRANCAIS ? "L'opération devrait bloquer" :
          "";
        #endif
        #ifdef EINPROGRESS
        errormsg_table[EINPROGRESS].name = "EINPROGRESS";
        errormsg_table[EINPROGRESS].msg =
          ENGLISH ? "Operation now in progress" :
          DEUTSCH ? "Das kann lange dauern" :
          FRANCAIS ? "Operation maintenant en cours" :
          "";
        #endif
        #ifdef EALREADY
        errormsg_table[EALREADY].name = "EALREADY";
        errormsg_table[EALREADY].msg =
          ENGLISH ? "Operation already in progress" :
          DEUTSCH ? "Es läuft schon eine Operation" :
          FRANCAIS ? "Operation déjà en cours" :
          "";
        #endif
        /* weitere allgemein übliche Errors: */
        #ifdef ELOOP
        errormsg_table[ELOOP].name = "ELOOP";
        errormsg_table[ELOOP].msg =
          ENGLISH ? "Too many levels of symbolic links" :
          DEUTSCH ? "Zu viele symbolische Links in einem Pathname" :
          FRANCAIS ? "Trop de liens symboliques rencontrés" :
          "";
        #endif
        #ifdef ENAMETOOLONG
        errormsg_table[ENAMETOOLONG].name = "ENAMETOOLONG";
        errormsg_table[ENAMETOOLONG].msg =
          ENGLISH ? "File name too long" :
          DEUTSCH ? "Zu langer Filename" :
          FRANCAIS ? "Nom du fichier trop long" :
          "";
        #endif
        #ifdef ENOTEMPTY
        errormsg_table[ENOTEMPTY].name = "ENOTEMPTY";
        errormsg_table[ENOTEMPTY].msg =
          ENGLISH ? "Directory not empty" :
          DEUTSCH ? "Directory ist nicht leer" :
          FRANCAIS ? "Répertoire non vide" :
          "";
        #endif
        /* Errors im Zusammenhang mit Network File System (NFS): */
        #ifdef ESTALE
        errormsg_table[ESTALE].name = "ESTALE";
        errormsg_table[ESTALE].msg =
          ENGLISH ? "Stale NFS file handle" :
          DEUTSCH ? "Offenes File auf entferntem Filesystem wurde gelöscht" :
          FRANCAIS ? "Fichier NFS perdu" :
          "";
        #endif
        #ifdef EREMOTE
        errormsg_table[EREMOTE].name = "EREMOTE";
        errormsg_table[EREMOTE].msg =
          ENGLISH ? "Too many levels of remote in path" :
          DEUTSCH ? "Mount läuft nicht auf entfernten Filesystemen" :
          FRANCAIS ? "Mount éloigné ne marche pas" :
          "";
        #endif
        /* Errors im Zusammenhang mit Sockets, IPC und Netzwerk: */
        #ifdef ENOTSOCK
        errormsg_table[ENOTSOCK].name = "ENOTSOCK";
        errormsg_table[ENOTSOCK].msg =
          ENGLISH ? "Socket operation on non-socket" :
          DEUTSCH ? "Socket-Operation und kein Socket" :
          FRANCAIS ? "Opération de type socket sur un fichier non-socket" :
          "";
        #endif
        #ifdef EDESTADDRREQ
        errormsg_table[EDESTADDRREQ].name = "EDESTADDRREQ";
        errormsg_table[EDESTADDRREQ].msg =
          ENGLISH ? "Destination address required" :
          DEUTSCH ? "Operation braucht Zieladresse" :
          FRANCAIS ? "Adresse de destination obligatoire" :
          "";
        #endif
        #ifdef EMSGSIZE
        errormsg_table[EMSGSIZE].name = "EMSGSIZE";
        errormsg_table[EMSGSIZE].msg =
          ENGLISH ? "Message too long" :
          DEUTSCH ? "Zu lange Nachricht" :
          FRANCAIS ? "Message trop long" :
          "";
        #endif
        #ifdef EPROTOTYPE
        errormsg_table[EPROTOTYPE].name = "EPROTOTYPE";
        errormsg_table[EPROTOTYPE].msg =
          ENGLISH ? "Protocol wrong type for socket" :
          DEUTSCH ? "Dieses Protokoll paßt nicht zu diesem Socket" :
          FRANCAIS ? "Mauvais type de protocole pour un socket" :
          "";
        #endif
        #ifdef ENOPROTOOPT
        errormsg_table[ENOPROTOOPT].name = "ENOPROTOOPT";
        errormsg_table[ENOPROTOOPT].msg =
          #if defined(UNIX_SUNOS4)
          ENGLISH ? "Option not supported by protocol" :
          #else
          #if defined(UNIX_BSD)
          ENGLISH ? "Bad protocol option" :
          #else /* UNIX_HPUX, UNIX_LINUX */
          ENGLISH ? "Protocol not available" :
          #endif
          #endif
          DEUTSCH ? "Fehlerhafte Option zu Protokoll auf Socket" :
          FRANCAIS ? "Protocole non disponible" :
          "";
        #endif
        #ifdef EPROTONOSUPPORT
        errormsg_table[EPROTONOSUPPORT].name = "EPROTONOSUPPORT";
        errormsg_table[EPROTONOSUPPORT].msg =
          ENGLISH ? "Protocol not supported" :
          DEUTSCH ? "Protokoll nicht implementiert" :
          FRANCAIS ? "Protocole non supporté" :
          "";
        #endif
        #ifdef ESOCKTNOSUPPORT
        errormsg_table[ESOCKTNOSUPPORT].name = "ESOCKTNOSUPPORT";
        errormsg_table[ESOCKTNOSUPPORT].msg =
          ENGLISH ? "Socket type not supported" :
          DEUTSCH ? "Socket-Typ nicht implementiert" :
          FRANCAIS ? "Type de socket non supporté" :
          "";
        #endif
        #ifdef EOPNOTSUPP
        errormsg_table[EOPNOTSUPP].name = "EOPNOTSUPP";
        errormsg_table[EOPNOTSUPP].msg =
          ENGLISH ? "Operation not supported on socket" :
          DEUTSCH ? "Operation auf diesem Socket nicht implementiert" :
          FRANCAIS ? "Opération non supportée sur socket" :
          "";
        #endif
        #ifdef EPFNOSUPPORT
        errormsg_table[EPFNOSUPPORT].name = "EPFNOSUPPORT";
        errormsg_table[EPFNOSUPPORT].msg =
          ENGLISH ? "Protocol family not supported" :
          DEUTSCH ? "Protokoll-Familie nicht implementiert" :
          FRANCAIS ? "Famille de protocoles non supportée" :
          "";
        #endif
        #ifdef EAFNOSUPPORT
        errormsg_table[EAFNOSUPPORT].name = "EAFNOSUPPORT";
        errormsg_table[EAFNOSUPPORT].msg =
          ENGLISH ? "Address family not supported by protocol family" :
          DEUTSCH ? "Adressen-Familie paßt nicht zu diesem Protokoll" :
          FRANCAIS ? "Famille d'adresses non supportée par le protocole" :
          "";
        #endif
        #ifdef EADDRINUSE
        errormsg_table[EADDRINUSE].name = "EADDRINUSE";
        errormsg_table[EADDRINUSE].msg =
          ENGLISH ? "Address already in use" :
          DEUTSCH ? "Adresse schon belegt" :
          FRANCAIS ? "Adresse déjà utilisée" :
          "";
        #endif
        #ifdef EADDRNOTAVAIL
        errormsg_table[EADDRNOTAVAIL].name = "EADDRNOTAVAIL";
        errormsg_table[EADDRNOTAVAIL].msg =
          ENGLISH ? "Can't assign requested address" :
          DEUTSCH ? "Adresse nicht (auf diesem Rechner) verfügbar" :
          FRANCAIS ? "Ne peut pas assigner l'adresse demandée" :
          "";
        #endif
        #ifdef ENETDOWN
        errormsg_table[ENETDOWN].name = "ENETDOWN";
        errormsg_table[ENETDOWN].msg =
          ENGLISH ? "Network is down" :
          DEUTSCH ? "Netz streikt" :
          FRANCAIS ? "Le réseau est éteint" :
          "";
        #endif
        #ifdef ENETUNREACH
        errormsg_table[ENETUNREACH].name = "ENETUNREACH";
        errormsg_table[ENETUNREACH].msg =
          ENGLISH ? "Network is unreachable" :
          DEUTSCH ? "Netz unbekannt und außer Sichtweite" :
          FRANCAIS ? "Le réseau ne peut être atteint" :
          "";
        #endif
        #ifdef ENETRESET
        errormsg_table[ENETRESET].name = "ENETRESET";
        errormsg_table[ENETRESET].msg =
          ENGLISH ? "Network dropped connection on reset" :
          DEUTSCH ? "Rechner bootete, Verbindung gekappt" :
          FRANCAIS ? "Le réseau a rompu la connection à cause d'une remise à zéro" :
          "";
        #endif
        #ifdef ECONNABORTED
        errormsg_table[ECONNABORTED].name = "ECONNABORTED";
        errormsg_table[ECONNABORTED].msg =
          ENGLISH ? "Software caused connection abort" :
          DEUTSCH ? "Mußte diese Verbindung kappen" :
          FRANCAIS ? "Echec de connection à cause du logiciel" :
          "";
        #endif
        #ifdef ECONNRESET
        errormsg_table[ECONNRESET].name = "ECONNRESET";
        errormsg_table[ECONNRESET].msg =
          ENGLISH ? "Connection reset by peer" :
          DEUTSCH ? "Gegenseite kappte die Verbindung" :
          FRANCAIS ? "Connection remise à zéro par le correspondant" :
          "";
        #endif
        #ifdef ENOBUFS
        errormsg_table[ENOBUFS].name = "ENOBUFS";
        errormsg_table[ENOBUFS].msg =
          ENGLISH ? "No buffer space available" :
          DEUTSCH ? "Nicht genügend Platz für einen Buffer" :
          FRANCAIS ? "Pas d'espace disponible pour un buffer" :
          "";
        #endif
        #ifdef EISCONN
        errormsg_table[EISCONN].name = "EISCONN";
        errormsg_table[EISCONN].msg =
          ENGLISH ? "Socket is already connected" :
          DEUTSCH ? "Socket ist bereits verbunden" :
          FRANCAIS ? "Le socket est déjà connecté" :
          "";
        #endif
        #ifdef ENOTCONN
        errormsg_table[ENOTCONN].name = "ENOTCONN";
        errormsg_table[ENOTCONN].msg =
          ENGLISH ? "Socket is not connected" :
          DEUTSCH ? "Socket hat keine Verbindung" :
          FRANCAIS ? "Le socket n'est pas connecté" :
          "";
        #endif
        #ifdef ESHUTDOWN
        errormsg_table[ESHUTDOWN].name = "ESHUTDOWN";
        errormsg_table[ESHUTDOWN].msg =
          ENGLISH ? "Can't send after socket shutdown" :
          DEUTSCH ? "Shutdown hat den Socket schon deaktiviert" :
          FRANCAIS ? "Impossibilité d'envoyer après un arrêt de socket" :
          "";
        #endif
        #ifdef ETOOMANYREFS
        errormsg_table[ETOOMANYREFS].name = "ETOOMANYREFS";
        errormsg_table[ETOOMANYREFS].msg =
          ENGLISH ? "Too many references: can't splice" :
          "";
        #endif
        #ifdef ETIMEDOUT
        errormsg_table[ETIMEDOUT].name = "ETIMEDOUT";
        errormsg_table[ETIMEDOUT].msg =
          ENGLISH ? "Connection timed out" :
          DEUTSCH ? "Verbindung nach Timeout gekappt" :
          FRANCAIS ? "Durée écoulée pour la connection" :
          "";
        #endif
        #ifdef ECONNREFUSED
        errormsg_table[ECONNREFUSED].name = "ECONNREFUSED";
        errormsg_table[ECONNREFUSED].msg =
          ENGLISH ? "Connection refused" :
          DEUTSCH ? "Gegenseite verweigert die Verbindung" :
          FRANCAIS ? "Connection refusée" :
          "";
        #endif
        #if 0
        errormsg_table[].name = "";
        errormsg_table[].msg =
          ENGLISH ? "Remote peer released connection" :
          "";
        #endif
        #ifdef EHOSTDOWN
        errormsg_table[EHOSTDOWN].name = "EHOSTDOWN";
        errormsg_table[EHOSTDOWN].msg =
          ENGLISH ? "Host is down" :
          DEUTSCH ? "Gegenseite ist wohl abgeschaltet" :
          FRANCAIS ? "L'hôte est éteint" :
          "";
        #endif
        #ifdef EHOSTUNREACH
        errormsg_table[EHOSTUNREACH].name = "EHOSTUNREACH";
        errormsg_table[EHOSTUNREACH].msg =
          ENGLISH ? "Host is unreachable" :
          DEUTSCH ? "Gegenseite nicht in Sichtweite, nicht erreichbar" :
          FRANCAIS ? "Aucune route pour cet hôte" :
          "";
        #endif
        #if 0
        errormsg_table[].name = "";
        errormsg_table[].msg =
          ENGLISH ? "Networking error" :
          "";
        #endif
        /* Quotas: */
        #ifdef EPROCLIM
        errormsg_table[EPROCLIM].name = "EPROCLIM";
        errormsg_table[EPROCLIM].msg =
          ENGLISH ? "Too many processes" :
          DEUTSCH ? "Zu viele Prozesse am Laufen" :
          FRANCAIS ? "Trop de processus" :
          "";
        #endif
        #ifdef EUSERS
        errormsg_table[EUSERS].name = "EUSERS";
        errormsg_table[EUSERS].msg =
          ENGLISH ? "Too many users" :
          DEUTSCH ? "Zu viele Benutzer aktiv" :
          FRANCAIS ? "Trop d'utilisateurs" :
          "";
        #endif
        #ifdef EDQUOT
        errormsg_table[EDQUOT].name = "EDQUOT";
        errormsg_table[EDQUOT].msg =
          ENGLISH ? "Disk quota exceeded" :
          DEUTSCH ? "Plattenplatz rationiert, Ihr Anteil ist erschöpft" :
          FRANCAIS ? "Ration d'espace est épuisée" :
          "";
        #endif
        /* Errors im Zusammenhang mit STREAMS: */
        #ifdef ENOSTR
        errormsg_table[ENOSTR].name = "ENOSTR";
        errormsg_table[ENOSTR].msg =
          ENGLISH ? "Not a stream device" :
          DEUTSCH ? "Das ist kein STREAM" :
          "";
        #endif
        #ifdef ETIME
        errormsg_table[ETIME].name = "ETIME";
        errormsg_table[ETIME].msg =
          ENGLISH ? "Timer expired" :
          DEUTSCH ? "STREAM braucht länger als erwartet" :
          "";
        #endif
        #ifdef ENOSR
        errormsg_table[ENOSR].name = "ENOSR";
        errormsg_table[ENOSR].msg =
          ENGLISH ? "Out of stream resources" :
          DEUTSCH ? "Kein Platz für weiteren STREAM" :
          "";
        #endif
        #ifdef ENOMSG
        errormsg_table[ENOMSG].name = "ENOMSG";
        errormsg_table[ENOMSG].msg =
          ENGLISH ? "No message of desired type" :
          DEUTSCH ? "Nachrichten dieses Typs gibt es hier nicht" :
          "";
        #endif
        #ifdef EBADMSG
        errormsg_table[EBADMSG].name = "EBADMSG";
        errormsg_table[EBADMSG].msg =
          ENGLISH ? "Not a data message" :
          DEUTSCH ? "Nachricht von unbekanntem Typ angekommen" :
          "";
        #endif
        /* Errors bei SystemV IPC: */
        #ifdef EIDRM
        errormsg_table[EIDRM].name = "EIDRM";
        errormsg_table[EIDRM].msg =
          ENGLISH ? "Identifier removed" :
          DEUTSCH ? "Name (einer Semaphore) wurde gelöscht" :
          FRANCAIS ? "Identificateur supprimé" :
          "";
        #endif
        /* Errors bei SystemV Record-Locking: */
        #ifdef EDEADLK
        errormsg_table[EDEADLK].name = "EDEADLK";
        errormsg_table[EDEADLK].msg =
          ENGLISH ? "Resource deadlock would occur" :
          DEUTSCH ? "Das würde zu einem Deadlock führen" :
          FRANCAIS ? "Blocage mutuel de la ressource " :
          "";
        #endif
        #ifdef ENOLCK
        errormsg_table[ENOLCK].name = "ENOLCK";
        errormsg_table[ENOLCK].msg =
          ENGLISH ? "No record locks available" :
          DEUTSCH ? "Zu viele Zugriffsvorbehalte auf einmal" :
          FRANCAIS ? "Pas de verrou disponible" :
          "";
        #endif
        /* Errors bei Remote File System (RFS): */
        #ifdef ENONET
        errormsg_table[ENONET].name = "ENONET";
        errormsg_table[ENONET].msg =
          ENGLISH ? "Machine is not on the network" :
          DEUTSCH ? "Rechner nicht übers Netz erreichbar" :
          FRANCAIS ? "La machine n'est pas sur le réseau" :
          "";
        #endif
        #ifdef EREMOTE
        errormsg_table[EREMOTE].name = "EREMOTE";
        errormsg_table[EREMOTE].msg =
          ENGLISH ? "Object is remote" :
          DEUTSCH ? "Das kann nur der dortige Rechner" :
          FRANCAIS ? "Objet à distance" :
          "";
        #endif
        #ifdef ERREMOTE
        errormsg_table[ERREMOTE].name = "ERREMOTE";
        errormsg_table[ERREMOTE].msg =
          ENGLISH ? "Object is remote" :
          DEUTSCH ? "Das kann nur der dortige Rechner" :
          FRANCAIS ? "Objet à distance" :
          "";
        #endif
        #ifdef ENOLINK
        errormsg_table[ENOLINK].name = "ENOLINK";
        errormsg_table[ENOLINK].msg =
          ENGLISH ? "Link has been severed" :
          DEUTSCH ? "Verbindung ist zusammengebrochen" :
          FRANCAIS ? "Le lien a été coupé" :
          "";
        #endif
        #ifdef EADV
        errormsg_table[EADV].name = "EADV";
        errormsg_table[EADV].msg =
          ENGLISH ? "Advertise error" :
          DEUTSCH ? "Andere Rechner benutzen noch unsere Ressourcen" :
          FRANCAIS ? "Erreur d'annonce" :
          "";
        #endif
        #ifdef ESRMNT
        errormsg_table[ESRMNT].name = "ESRMNT";
        errormsg_table[ESRMNT].msg =
          ENGLISH ? "Srmount error" :
          DEUTSCH ? "Andere Rechner benutzen noch unsere Ressourcen" :
          FRANCAIS ? "Erreur srmount" :
          "";
        #endif
        #ifdef ECOMM
        errormsg_table[ECOMM].name = "ECOMM";
        errormsg_table[ECOMM].msg =
          ENGLISH ? "Communication error on send" :
          DEUTSCH ? "Beim Senden: Rechner nicht erreichbar" :
          FRANCAIS ? "Erreur de communication lors d'un envoi" :
          "";
        #endif
        #ifdef EPROTO
        errormsg_table[EPROTO].name = "EPROTO";
        errormsg_table[EPROTO].msg =
          ENGLISH ? "Protocol error" :
          DEUTSCH ? "Protokoll klappt nicht" :
          FRANCAIS ? "Erreur de protocole" :
          "";
        #endif
        #ifdef EMULTIHOP
        errormsg_table[EMULTIHOP].name = "EMULTIHOP";
        errormsg_table[EMULTIHOP].msg =
          ENGLISH ? "Multihop attempted" :
          DEUTSCH ? "Ressourcen nicht direkt erreichbar" :
          FRANCAIS ? "Tentative de sauts multiples" :
          "";
        #endif
        #ifdef EDOTDOT
        errormsg_table[EDOTDOT].name = "EDOTDOT";
        errormsg_table[EDOTDOT].msg =
          "";
        #endif
        #ifdef EREMCHG
        errormsg_table[EREMCHG].name = "EREMCHG";
        errormsg_table[EREMCHG].msg =
          ENGLISH ? "Remote address changed" :
          DEUTSCH ? "Rechner hat jetzt eine andere Adresse" :
          FRANCAIS ? "Adresse à distance changée" :
          "";
        #endif
        /* Errors von POSIX: */
        #ifdef ENOSYS
        errormsg_table[ENOSYS].name = "ENOSYS";
        errormsg_table[ENOSYS].msg =
          ENGLISH ? "Function not implemented" :
          DEUTSCH ? "POSIX-Funktion hier nicht implementiert" :
          FRANCAIS ? "Fonction non implémenté" :
          "";
        #endif
        /* Sonstige: */
        #ifdef EMSDOS /* emx 0.8e - 0.8h */
        errormsg_table[EMSDOS].name = "EMSDOS";
        errormsg_table[EMSDOS].msg =
          ENGLISH ? "Not supported under MS-DOS" :
          DEUTSCH ? "Das geht unter MS-DOS nicht" :
          FRANCAIS ? "Pas supporté sous MS-DOS" :
          "";
        #endif
        return 0;
      }

    global void OS_error ()
      { var reg1 uintC errcode = errno; # positive Fehlernummer
        end_system_call();
        clr_break_sem_4(); # keine UNIX-Operation mehr aktiv
        begin_error(); # Fehlermeldung anfangen
       {# Meldungbeginn ausgeben:
        #ifdef UNIX
        write_errorstring(DEUTSCH ? "UNIX-Fehler " :
                          ENGLISH ? "UNIX error " :
                          FRANCAIS ? "Erreur UNIX " :
                          ""
                         );
        #else
        write_errorstring(DEUTSCH ? "UNIX-Bibliotheks-Fehler " :
                          ENGLISH ? "UNIX library error " :
                          FRANCAIS ? "Erreur dans la librairie UNIX " :
                          ""
                         );
        #endif
        # Fehlernummer ausgeben:
        write_errorobject(fixnum(errcode));
        #if 0
        { # Fehlermeldung des Betriebssystems ausgeben:
          if (errcode < sys_nerr)
            { var reg2 const char* errormsg = sys_errlist[errcode];
              write_errorstring(": ");
              write_errorstring(errormsg);
        }   }
        #else # nach Möglichkeit noch ausführlicher:
        { # eigene Fehlermeldung ausgeben:
          if (errcode < sys_nerr)
            # Zu dieser Fehlernummer ist ein Text da.
            { var reg2 const char* errorname = errormsg_table[errcode].name;
              var reg2 const char* errormsg = errormsg_table[errcode].msg;
              if (!(errorname[0] == 0)) # bekannter Name?
                { write_errorstring(" (");
                  write_errorstring(errorname);
                  write_errorstring(")");
                }
              if (!(errormsg[0] == 0)) # nichtleere Meldung?
                { write_errorstring(": ");
                  write_errorstring(errormsg);
                }
        }   }
        #endif
       }
        errno = 0; # Fehlercode löschen (fürs nächste Mal)
        end_error(args_end_pointer STACKop 7); # Fehlermeldung beenden
      }

  # Ausgabe eines Fehlers, direkt übers Betriebssystem
  # errno_out(errorcode);
  # > int errorcode: Fehlercode
    global void errno_out (int errorcode);
    global void errno_out(errorcode)
      var reg1 int errorcode;
      { asciz_out(" errno = ");
        if ((uintL)errorcode < sys_nerr)
          { var reg2 const char* errorname = errormsg_table[errorcode].name;
            var reg2 const char* errormsg = errormsg_table[errorcode].msg;
            if (!(errorname[0] == 0)) # bekannter Name?
              { asciz_out(errorname); }
              else
              { dez_out(errorcode); }
            if (!(errormsg[0] == 0)) # nichtleere Meldung?
              { asciz_out(": "); asciz_out(errormsg); }
          }
          else
          { dez_out(errorcode); }
        asciz_out("." CRLFstring);
      }

#endif # UNIX || EMUNIX || WATCOM || RISCOS

LISPFUN(error,1,0,rest,nokey,0,NIL)
# (ERROR errorstring {expr})
# Kehrt nicht zurück.
# (defun error (errorstring &rest args)
#   (if (or *error-handler* (not *use-clcs*))
#     (progn
#       (if *error-handler*
#         (apply *error-handler* nil errorstring args)
#         (progn
#           (terpri *error-output*)
#           (write-string "*** - " *error-output*)
#           (apply #'format *error-output* errorstring args)
#       ) )
#       (funcall *break-driver* nil)
#     )
#     (let ((condition (coerce-to-condition errorstring args 'error 'simple-error)))
#       (signal condition)
#       (invoke-debugger condition)
#     )
# ) )
  { if (!nullp(Symbol_value(S(error_handler))) || nullp(Symbol_value(S(use_clcs))))
      { begin_error(); # Fehlermeldung anfangen
        rest_args_pointer skipSTACKop 1; # Pointer über die Argumente
        {var reg5 object fun;
         var reg4 object arg1;
         if (nullp(STACK_1))
           { fun = S(format); arg1 = STACK_0; } # (FORMAT *error-output* ...)
           else
           { fun = STACK_1; arg1 = NIL; } # (FUNCALL *error-handler* NIL ...)
         skipSTACK(3);
         # Errormeldung ausgeben:
         #   (FORMAT *ERROR-OUTPUT* errorstring {expr})
         # bzw. ({handler} nil errorstring {expr})
         pushSTACK(arg1);
         { var reg1 object* ptr = rest_args_pointer;
           var reg3 uintC count;
           dotimespC(count,1+argcount, { pushSTACK(NEXT(ptr)); } );
         }
         funcall(fun,2+argcount); # fun (= FORMAT bzw. handler) aufrufen
        }
        # Fehlermeldung beenden, vgl. end_error():
        dynamic_unbind(); # Keine Fehlermeldungs-Ausgabe mehr aktiv
        set_args_end_pointer(rest_args_pointer); # STACK aufräumen
        break_driver(NIL); # Break-Driver aufrufen (kehrt nicht zurück)
      }
      else
      { {var reg1 object arguments = listof(argcount); pushSTACK(arguments); }
        pushSTACK(S(error));
        pushSTACK(S(simple_error));
        funcall(S(coerce_to_condition),4); # (SYS::COERCE-TO-CONDITION ...)
        pushSTACK(value1); # condition retten
        pushSTACK(value1); funcall(L(clcs_signal),1); # (SIGNAL condition)
        dynamic_bind(S(prin_stream),unbound); # SYS::*PRIN-STREAM* an #<UNBOUND> binden
        pushSTACK(STACK_(0+3)); # condition
        funcall(L(invoke_debugger),1); # (INVOKE-DEBUGGER condition)
      }
    NOTREACHED
  }

LISPFUNN(defclcs,1)
# (SYSTEM::%DEFCLCS error-types)
# setzt die für ERROR-OF-TYPE benötigten Daten.
  { O(error_types) = popSTACK();
    value1 = NIL; mv_count=0;
  }

# Konvertiert einen Condition-Typ zur entsprechenden Simple-Condition.
# convert_simple_condition(type)
  local object convert_simple_condition (object type);
  local object convert_simple_condition(type)
    var reg2 object type;
    { # Vektor O(error_types) wie eine Aliste durchlaufen:
      var reg4 object v = O(error_types);
      var reg1 object* ptr = &TheSvector(v)->data[0];
      var reg3 uintL count;
      dotimesL(count,TheSvector(v)->length,
               { if (eq(type,Car(*ptr))) { return Cdr(*ptr); }
                 ptr++;
               });
      return type; # nicht gefunden -> Typ unverändert lassen
    }

LISPFUN(error_of_type,2,0,rest,nokey,0,NIL)
# (SYSTEM::ERROR-OF-TYPE type {keyword value}* errorstring {expr}*)
# Kehrt nicht zurück.
# (defun error-of-type (type &rest arguments)
#   ; Keyword-Argumente von den anderen Argumenten abspalten:
#   (let ((keyword-arguments '()))
#     (loop
#       (unless (and (consp arguments) (keywordp (car arguments))) (return))
#       (push (pop arguments) keyword-arguments)
#       (push (pop arguments) keyword-arguments)
#     )
#     (setq keyword-arguments (nreverse keyword-arguments))
#     (let ((errorstring (first arguments))
#           (args (rest arguments)))
#       ; Los geht's!
#       (if (or *error-handler* (not *use-clcs*))
#         (progn
#           (if *error-handler*
#             (apply *error-handler* nil errorstring args)
#             (progn
#               (terpri *error-output*)
#               (write-string "*** - " *error-output*)
#               (apply #'format *error-output* errorstring args)
#           ) )
#           (funcall *break-driver* nil)
#         )
#         (let ((condition
#                 (apply #'coerce-to-condition errorstring args
#                        'error (convert-simple-condition type) keyword-arguments
#              )) )
#           (signal condition)
#           (invoke-debugger condition)
#         )
# ) ) ) )
  { var reg6 uintC keyword_argcount = 0;
    rest_args_pointer skipSTACKop 1; # Pointer über die Argumente hinter type
    while (argcount>=2)
      { var reg3 object next_arg = Next(rest_args_pointer); # nächstes Argument
        if (!(symbolp(next_arg) && keywordp(next_arg))) break; # Keyword?
        rest_args_pointer skipSTACKop -2; argcount -= 2; keyword_argcount += 2;
      }
    # Nächstes Argument hoffentlich ein String.
    if (!nullp(Symbol_value(S(error_handler))) || nullp(Symbol_value(S(use_clcs))))
      { # Der Typ und die Keyword-Argumente werden ignoriert.
        begin_error(); # Fehlermeldung anfangen
        {var reg5 object fun;
         var reg4 object arg1;
         if (nullp(STACK_1))
           { fun = S(format); arg1 = STACK_0; } # (FORMAT *error-output* ...)
           else
           { fun = STACK_1; arg1 = NIL; } # (FUNCALL *error-handler* NIL ...)
         skipSTACK(3);
         # Errormeldung ausgeben:
         #   (FORMAT *ERROR-OUTPUT* errorstring {expr})
         # bzw. ({handler} nil errorstring {expr})
         pushSTACK(arg1);
         { var reg1 object* ptr = rest_args_pointer;
           var reg3 uintC count;
           dotimespC(count,1+argcount, { pushSTACK(NEXT(ptr)); } );
         }
         funcall(fun,2+argcount); # fun (= FORMAT bzw. handler) aufrufen
        }
        # Fehlermeldung beenden, vgl. end_error():
        dynamic_unbind(); # Keine Fehlermeldungs-Ausgabe mehr aktiv
        set_args_end_pointer(rest_args_pointer); # STACK aufräumen
        break_driver(NIL); # Break-Driver aufrufen (kehrt nicht zurück)
      }
      else
      { var reg5 object arguments = listof(argcount);
        # Stackaufbau: type, {keyword, value}*, errorstring.
        # Ein wenig im Stack umordnen:
        var reg4 object errorstring = STACK_0;
        pushSTACK(NIL); pushSTACK(NIL);
        { var reg1 object* ptr2 = args_end_pointer;
          var reg2 object* ptr1 = ptr2 STACKop 3;
          var reg3 uintC count;
          dotimesC(count,keyword_argcount, { BEFORE(ptr2) = BEFORE(ptr1); } );
          BEFORE(ptr2) = convert_simple_condition(BEFORE(ptr1));
          BEFORE(ptr2) = S(error);
          BEFORE(ptr2) = arguments;
          BEFORE(ptr2) = errorstring;
        }
        # Stackaufbau: errorstring, args, ERROR, type, {keyword, value}*.
        funcall(S(coerce_to_condition),4+keyword_argcount); # (SYS::COERCE-TO-CONDITION ...)
        pushSTACK(value1); # condition retten
        pushSTACK(value1); funcall(L(clcs_signal),1); # (SIGNAL condition)
        dynamic_bind(S(prin_stream),unbound); # SYS::*PRIN-STREAM* an #<UNBOUND> binden
        pushSTACK(STACK_(0+3)); # condition
        funcall(L(invoke_debugger),1); # (INVOKE-DEBUGGER condition)
      }
    NOTREACHED
  }

LISPFUNN(invoke_debugger,1)
# (INVOKE-DEBUGGER condition), CLtL2 S. 915
# Kehrt nicht zurück.
# (defun invoke-debugger (condition)
#   (when *debugger-hook*
#     (let ((debugger-hook *debugger-hook*)
#           (*debugger-hook* nil))
#       (funcall debugger-hook condition debugger-hook)
#   ) )
#   (funcall *break-driver* nil condition t)
# )
  { var reg1 object hook = Symbol_value(S(debugger_hook));
    if (!nullp(hook))
      { var reg2 object condition = STACK_0;
        dynamic_bind(S(debugger_hook),NIL); # *DEBUGGER-HOOK* an NIL binden
        pushSTACK(condition); pushSTACK(hook); funcall(hook,2); # Debugger-Hook aufrufen
        dynamic_unbind();
      }
    # *BREAK-DRIVER* kann hier als /= NIL angenommen werden.
    pushSTACK(NIL); pushSTACK(STACK_(0+1)); pushSTACK(T);
    funcall(Symbol_value(S(break_driver)),3); # Break-Driver aufrufen
    reset(); # kehrt wider Erwarten zurück -> zur nächsten Schleife zurück
    NOTREACHED
  }

# UP: Führt eine Break-Schleife wegen Tastaturunterbrechung aus.
# > STACK_0 : aufrufende Funktion
# verändert STACK, kann GC auslösen
  global void tast_break (void);
  global void tast_break()
    {
      #ifdef PENDING_INTERRUPTS
      interrupt_pending = FALSE; # Ctrl-C-Wartezeit ist gleich beendet
      begin_system_call();
      #ifdef HAVE_UALARM
      ualarm(0,0); # SIGALRM-Timer abbrechen
      #else
      #ifdef EMUNIX_OLD_8h # EMX-Bug umgehen
      alarm(1000);
      #endif
      alarm(0); # SIGALRM-Timer abbrechen
      #endif
      end_system_call();
      #endif
      # Simuliere begin_error(), 7 Elemente auf den STACK:
      pushSTACK(NIL); pushSTACK(NIL); pushSTACK(NIL);
      pushSTACK(NIL); pushSTACK(NIL); pushSTACK(NIL);
      pushSTACK(var_stream(S(debug_io))); # Stream *DEBUG-IO*
      terpri(&STACK_0); # neue Zeile
      write_sstring(&STACK_0,O(error_string1)); # "*** - " ausgeben
      # String ausgeben, Aufrufernamen verbrauchen, STACK aufräumen:
      set_args_end_pointer(
        write_errorstring(DEUTSCH ? "~: Tastatur-Interrupt" :
                          ENGLISH ? "~: User break" :
                          FRANCAIS ? "~ : Interruption clavier" :
                          "~"
                         ));
      break_driver(T); # Break-Driver aufrufen
    }

LISPFUN(clcs_signal,1,0,rest,nokey,0,NIL)
# (SIGNAL datum {arg}*), CLtL2 S. 888
# (defun signal (datum &rest arguments)
#   (let ((condition
#           (coerce-to-condition datum arguments 'signal
#                                'simple-condition ; CLtL2 p. 918 specifies this
#        )) )
#     (when (typep condition *break-on-signals*)
#       ; Enter the debugger prior to signalling the condition
#       (restart-case (invoke-debugger condition)
#         (continue ())
#     ) )
#     (invoke-handlers condition)
#     nil
# ) )
  { {var reg1 object arguments = listof(argcount); pushSTACK(arguments); }
    pushSTACK(S(clcs_signal));
    pushSTACK(S(simple_condition));
    funcall(S(coerce_to_condition),4); # (SYS::COERCE-TO-CONDITION ...)
    pushSTACK(value1); # condition retten
    pushSTACK(value1); pushSTACK(Symbol_value(S(break_on_signals)));
    funcall(S(safe_typep),2); # (SYS::SAFE-TYPEP condition *BREAK-ON-SIGNALS*)
    if (!nullp(value1))
      # Break-Driver aufrufen: (funcall *break-driver* t condition t)
      { # *BREAK-DRIVER* kann hier als /= NIL angenommen werden.
        pushSTACK(T); pushSTACK(STACK_(0+1)); pushSTACK(T);
        funcall(Symbol_value(S(break_driver)),3);
      }
   {var reg1 object condition = popSTACK(); # condition zurück
    invoke_handlers(condition); # Handler aufrufen
    value1 = NIL; mv_count=1; # Wert NIL
  }}

# Fehlermeldung, wenn ein Objekt keine Liste ist.
# fehler_list(obj);
# > arg: Nicht-Liste
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_list, (object obj));
  global void fehler_list(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(list)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine Liste." :
             ENGLISH ? "~: ~ is not a list" :
             FRANCAIS ? "~ : ~ n'est pas une liste." :
             ""
            );
    }

# Fehlermeldung, wenn ein Objekt kein Symbol ist.
# fehler_kein_symbol(caller,obj);
# > caller: Aufrufer (ein Symbol)
# > obj: Nicht-Symbol
  nonreturning_function(global, fehler_kein_symbol, (object caller, object obj));
  global void fehler_kein_symbol(caller,obj)
    var reg2 object caller;
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(symbol)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj);
      pushSTACK(caller);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist kein Symbol." :
             ENGLISH ? "~: ~ is not a symbol" :
             FRANCAIS ? "~ : ~ n'est pas un symbole." :
             ""
            );
    }

# Fehlermeldung, wenn ein Objekt kein Symbol ist.
# fehler_symbol(obj);
# > subr_self: Aufrufer (ein SUBR oder FSUBR)
# > obj: Nicht-Symbol
  nonreturning_function(global, fehler_symbol, (object obj));
  global void fehler_symbol(obj)
    var reg2 object obj;
    { var reg1 object aufrufer = subr_self;
      aufrufer = (subrp(aufrufer) ? TheSubr(aufrufer)->name : TheFsubr(aufrufer)->name);
      fehler_kein_symbol(aufrufer,obj);
    }

# Fehlermeldung, wenn ein Objekt kein Simple-Vector ist.
# fehler_kein_svector(caller,obj);
# > caller: Aufrufer (ein Symbol)
# > obj: Nicht-Svector
  nonreturning_function(global, fehler_kein_svector, (object caller, object obj));
  global void fehler_kein_svector(caller,obj)
    var reg2 object caller;
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(simple_vector)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj);
      pushSTACK(caller);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist kein Simple-Vector." :
             ENGLISH ? "~: ~ is not a simple-vector" :
             FRANCAIS ? "~: ~ n'est pas de type SIMPLE-VECTOR." :
             ""
            );
    }

# Fehlermeldung, wenn ein Objekt kein Vektor ist.
# fehler_vector(obj);
# > subr_self: Aufrufer (ein SUBR)
# > obj: Nicht-Vektor
  nonreturning_function(global, fehler_vector, (object obj));
  global void fehler_vector(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(vector)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist kein Vektor." :
             ENGLISH ? "~: ~ is not a vector" :
             FRANCAIS ? "~: ~ n'est pas un vecteur." :
             ""
            );
    }

# Fehlermeldung, falls ein Argument kein Character ist:
# fehler_char(obj);
# > obj: Das fehlerhafte Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_char, (object obj));
  global void fehler_char(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(character)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: Argument ~ ist kein Character." :
             ENGLISH ? "~: argument ~ is not a character" :
             FRANCAIS ? "~: L'argument ~ n'est pas un caractère." :
             ""
            );
    }

# Fehler, wenn Argument kein String-Char ist.
# fehler_string_char(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_string_char, (object obj));
  global void fehler_string_char(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(string_char)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist kein String-Char." :
             ENGLISH ? "~: ~ is not a string-char" :
             FRANCAIS ? "~ : ~ n'est pas de type STRING-CHAR." :
             ""
            );
    }

# Fehlermeldung, falls ein Argument kein String ist:
# > obj: Das fehlerhafte Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_string, (object obj));
  global void fehler_string(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(string)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: Argument ~ ist kein String." :
             ENGLISH ? "~: argument ~ is not a string" :
             FRANCAIS ? "~: L'argument ~ n'est pas une chaîne." :
             ""
            );
    }

# Fehlermeldung, falls ein Argument kein Simple-String ist:
# > obj: Das fehlerhafte Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_sstring, (object obj));
  global void fehler_sstring(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(simple_string)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: Argument ~ ist kein Simple-String." :
             ENGLISH ? "~: argument ~ is not a simple string" :
             FRANCAIS ? "~: L'argument ~ n'est pas de type SIMPLE-STRING." :
             ""
            );
    }

# Fehlermeldung, wenn ein Argument kein Stream ist:
# fehler_stream(obj);
# > obj: Das fehlerhafte Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_stream, (object obj));
  global void fehler_stream(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(stream)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: Argument muß ein Stream sein, nicht ~" :
             ENGLISH ? "~: argument ~ should be a stream" :
             FRANCAIS ? "~ : L'argument doit être de type STREAM et non pas ~." :
             ""
            );
    }

#ifdef HAVE_FFI

# Fehler, wenn Argument kein Integer vom Typ `uint8' ist.
# fehler_uint8(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_uint8, (object obj));
  global void fehler_uint8(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_uint8)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 8-bit-Zahl." :
             ENGLISH ? "~: ~ is not an 8-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 8 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `sint8' ist.
# fehler_sint8(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_sint8, (object obj));
  global void fehler_sint8(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_sint8)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 8-bit-Zahl." :
             ENGLISH ? "~: ~ is not an 8-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 8 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `uint16' ist.
# fehler_uint16(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_uint16, (object obj));
  global void fehler_uint16(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_uint16)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 16-bit-Zahl." :
             ENGLISH ? "~: ~ is not a 16-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 16 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `sint16' ist.
# fehler_sint16(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_sint16, (object obj));
  global void fehler_sint16(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_sint16)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 16-bit-Zahl." :
             ENGLISH ? "~: ~ is not a 16-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 16 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `uint32' ist.
# fehler_uint32(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_uint32, (object obj));
  global void fehler_uint32(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_uint32)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 32-bit-Zahl." :
             ENGLISH ? "~: ~ is not an 32-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 32 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `sint32' ist.
# fehler_sint32(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_sint32, (object obj));
  global void fehler_sint32(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_sint32)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 32-bit-Zahl." :
             ENGLISH ? "~: ~ is not an 32-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 32 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `uint64' ist.
# fehler_uint64(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_uint64, (object obj));
  global void fehler_uint64(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_uint64)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 64-bit-Zahl." :
             ENGLISH ? "~: ~ is not an 64-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 64 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `sint64' ist.
# fehler_sint64(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_sint64, (object obj));
  global void fehler_sint64(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(O(type_sint64)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine 64-bit-Zahl." :
             ENGLISH ? "~: ~ is not an 64-bit number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre à 64 bits." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `uint' ist.
# fehler_uint(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_uint, (object obj));
  global void fehler_uint(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      #if (int_bitsize==16)
      pushSTACK(O(type_uint16)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #else # (int_bitsize==32)
      pushSTACK(O(type_uint32)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #endif
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine `unsigned int'-Zahl." :
             ENGLISH ? "~: ~ is not an `unsigned int' number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre «unsigned int»." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `sint' ist.
# fehler_sint(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_sint, (object obj));
  global void fehler_sint(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      #if (int_bitsize==16)
      pushSTACK(O(type_sint16)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #else # (int_bitsize==32)
      pushSTACK(O(type_sint32)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #endif
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine `int'-Zahl." :
             ENGLISH ? "~: ~ is not an `int' number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre «int»." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `ulong' ist.
# fehler_ulong(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_ulong, (object obj));
  global void fehler_ulong(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      #if (long_bitsize==32)
      pushSTACK(O(type_uint32)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #else # (long_bitsize==64)
      pushSTACK(O(type_uint64)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #endif
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine `unsigned long'-Zahl." :
             ENGLISH ? "~: ~ is not a `unsigned long' number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre «unsigned long»." :
             ""
            );
    }

# Fehler, wenn Argument kein Integer vom Typ `slong' ist.
# fehler_slong(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_slong, (object obj));
  global void fehler_slong(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      #if (long_bitsize==32)
      pushSTACK(O(type_sint32)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #else # (long_bitsize==64)
      pushSTACK(O(type_sint64)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      #endif
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist keine `long'-Zahl." :
             ENGLISH ? "~: ~ is not a `long' number" :
             FRANCAIS ? "~ : ~ n'est pas un nombre «long»." :
             ""
            );
    }

# Fehler, wenn Argument kein Single-Float ist.
# fehler_ffloat(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_ffloat, (object obj));
  global void fehler_ffloat(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(single_float)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist kein Single-Float." :
             ENGLISH ? "~: ~ is not a single-float" :
             FRANCAIS ? "~ : ~ n'est pas de type SINGLE-FLOAT." :
             ""
            );
    }

# Fehler, wenn Argument kein Double-Float ist.
# fehler_dfloat(obj);
# > obj: fehlerhaftes Argument
# > subr_self: Aufrufer (ein SUBR)
  nonreturning_function(global, fehler_dfloat, (object obj));
  global void fehler_dfloat(obj)
    var reg1 object obj;
    { pushSTACK(obj); # Wert für Slot DATUM von TYPE-ERROR
      pushSTACK(S(double_float)); # Wert für Slot EXPECTED-TYPE von TYPE-ERROR
      pushSTACK(obj); pushSTACK(TheSubr(subr_self)->name);
      fehler(type_error,
             DEUTSCH ? "~: ~ ist kein Double-Float." :
             ENGLISH ? "~: ~ is not a double-float" :
             FRANCAIS ? "~ : ~ n'est pas de type DOUBLE-FLOAT." :
             ""
            );
    }

#endif

