head 1.31; access; symbols LMTP2NNTP_1_2_0:1.30 LMTP2NNTP_1_2b4:1.30 LMTP2NNTP_1_2b3:1.30 LMTP2NNTP_1_2b2:1.30 LMTP2NNTP_1_2b1:1.30 LMTP2NNTP_1_2a8:1.30 LMTP2NNTP_1_2a7:1.30 LMTP2NNTP_1_2a6:1.30 LMTP2NNTP_1_2a5:1.30 LMTP2NNTP_1_2a4:1.30 VAR_0_9_0:1.30 LMTP2NNTP_1_2a3:1.22 OSSP_RC_SPEC:1.9 last-version-before-change-to-ossp-style:1.1.1.1 VAR_0_0_0:1.1.1.1 VENDOR:1.1.1; locks; strict; comment @# @; 1.31 date 2003.02.14.21.17.07; author rse; state dead; branches; next 1.30; 1.30 date 2002.03.07.14.59.14; author rse; state Exp; branches; next 1.29; 1.29 date 2002.03.07.12.19.46; author rse; state Exp; branches; next 1.28; 1.28 date 2002.03.07.12.11.09; author rse; state Exp; branches; next 1.27; 1.27 date 2002.03.07.09.42.43; author rse; state Exp; branches; next 1.26; 1.26 date 2002.03.07.09.14.05; author rse; state Exp; branches; next 1.25; 1.25 date 2002.03.06.15.30.35; author rse; state Exp; branches; next 1.24; 1.24 date 2002.03.06.10.25.32; author rse; state Exp; branches; next 1.23; 1.23 date 2002.03.06.10.19.06; author rse; state Exp; branches; next 1.22; 1.22 date 2002.03.04.12.01.53; author rse; state Exp; branches; next 1.21; 1.21 date 2002.03.04.11.54.05; author rse; state Exp; branches; next 1.20; 1.20 date 2002.03.04.11.53.27; author rse; state Exp; branches; next 1.19; 1.19 date 2002.02.28.12.10.33; author rse; state Exp; branches; next 1.18; 1.18 date 2002.02.28.11.54.25; author rse; state Exp; branches; next 1.17; 1.17 date 2002.02.28.11.40.46; author rse; state Exp; branches; next 1.16; 1.16 date 2002.02.28.11.15.38; author rse; state Exp; branches; next 1.15; 1.15 date 2002.02.28.11.08.27; author rse; state Exp; branches; next 1.14; 1.14 date 2002.02.28.08.48.44; author rse; state Exp; branches; next 1.13; 1.13 date 2002.02.28.08.08.16; author rse; state Exp; branches; next 1.12; 1.12 date 2002.02.27.11.56.01; author rse; state Exp; branches; next 1.11; 1.11 date 2002.02.27.11.55.26; author rse; state Exp; branches; next 1.10; 1.10 date 2002.02.27.11.36.53; author rse; state Exp; branches; next 1.9; 1.9 date 2002.01.04.22.31.43; author rse; state Exp; branches; next 1.8; 1.8 date 2001.12.16.18.13.22; author rse; state Exp; branches; next 1.7; 1.7 date 2001.12.13.09.20.37; author thl; state Exp; branches; next 1.6; 1.6 date 2001.11.20.15.33.07; author simons; state Exp; branches; next 1.5; 1.5 date 2001.11.14.12.59.24; author rse; state Exp; branches; next 1.4; 1.4 date 2001.11.13.14.43.43; author simons; state Exp; branches; next 1.3; 1.3 date 2001.11.13.12.49.29; author simons; state Exp; branches; next 1.2; 1.2 date 2001.11.13.12.18.51; author simons; state Exp; branches; next 1.1; 1.1 date 2001.11.09.17.01.37; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.11.09.17.01.37; author rse; state Exp; branches; next ; desc @@ 1.31 log @final polishing for release 1.0.0 @ text @ OSSP var ======== - there are memory leaks according to Dmalloc! @ 1.30 log @remember issue @ text @@ 1.29 log @Yeah, reduce the TODO list to zero items\! @ text @d5 2 @ 1.28 log @New API functions var_format and var_formatv which provide a convinience interface to printf-style expansion and variable expansion. var_format is like a combination of snprintf(3) and var_expand(). Example: Assume the variable value context gives "bar" for ${ARRAY[7]}, then the call.. var_format(var, &tmp, 1, "foo${ARRAY[%d]}quux", 7);o ..results in tmp containing the malloc(3)'ed string "foobarquux". Thanks to Thomas L. for providing the hint to this functionality. @ text @a0 1 OSSP var d2 2 a3 1 o document exception handling @ 1.27 log @problems seems to be beeing solved implicitly by recent fixes ;) @ text @a2 7 o New feature: allow var_expand (or with a new function based on var_expand like var_printf) to first substitute printf-style %x constructs and then the OSSP var constructs. This allow more flexibility in expanding templates, because one can expand indices and other dynamic stuff into the template inside variable constructs. Think about var_printf("${array[%d]}", i); @ 1.26 log @Major bugfixing and enhancing of search & replace operation: - finally fix ${name:s/$/foo/} type substitutions (zero-length matching!) - add s/.../.../mg matching support (Perl-style multiline) - make non-multiline matching the default @ text @a9 3 o with PCRE active, ./var_play '${HOME:s/x$/foo/}' fails horribly with an impossible error invalid character class! @ 1.25 log @remember great idea @ text @a9 4 o ./var_play '${HOME:s/$/foo/}' does nothing because it seems that internally a zero-size pattern match does is not handled correctly. @ 1.24 log @Welcome to the wonderful world of TODO lists: One point solved, two new discovered... shit! :-( @ text @d3 7 @ 1.23 log @now solved, too. @ text @d3 7 @ 1.22 log @Fix regex problem by no longer allowing variables in the pattern part of s/pattern/subst/. Because it is far more common that one needs '$' there instead of a variable. @ text @a2 7 o "problem"!?: ${unknown:-foo} fails on force_expand and results in no expansion (kept as is) if not forced_expand. It only does the expected if the callback returns empty strings for undefined variables. This is certainly intended this way, but has to be documented better? @ 1.21 log @already done @ text @a2 8 o problem: ${foo:s/^(.+)$/<\1>/} -> fails with malformatted search & replace error because it tries to parse the $ as a variable. ${foo:s/^(.+)\$/<\1>/} -> does not substitute because it leaves the \$ in the regex and this no longer matches the end (instead it matches a dollar) @ 1.20 log @Add new important feature: user-supplied post-operation functions. This allows one to configure a var_cb_operation_t callback in the var_t context and allow it to implement functions triggered by ${name:%func[(arg)]}. This is especially intended for application-specific encoding and post-adjustment functions. @ text @a17 2 o use internal context to carry information @ 1.19 log @merge old internal_expand() into new var_expand() @ text @a21 5 o additional feature: functions via callback. ${foo:F:F} calls callback for bar with result of foo expansion and then callback for quux with the result returned from bar. @ 1.18 log @Start internal code and logic cleanups: - move the name class table generation from var_expand() to var_config() by moving the table into var_t. - move inital parts of internal_expand to var_expand(). @ text @a21 3 o add internal library context and move initialization and configuration into this context. @ 1.17 log @more docs, less TODO @ text @a17 2 o generate internals into context @ 1.16 log @one more @ text @d19 1 d21 1 a22 115 o document arithmetic expressions --------------------------------------------------------------------- - Man braucht ein Schleifenkonstrukt, das über Arrays iteriert: [${foo}${bar}] Dies wird so interpretiert, daß der Parser an den Variablennamen den jeweiligen Index anhängt, und die ganze Zeile expandiert, solange, bis _alle_ in dem Konstrukt verwandten Variablen für den derzeitigen Index undefiniert sind -- sind nur einzelne Variablen undefiniert, werden sie durch den Leerstring "" ersetzt. Text innerhalb des Konstrukten wird "verbatim" in jeder Zeile erhalten, beispielsweise: [${foo}: ${bar}\n] Hierzu muß var_expand() wissen, wie sie einen indizierten Variablenzugriff erzeugen kann. Hierzu wird var_config_t um "char startindex" und "char endindex" erweitert. Weiterhin wird in var_config_t "char current_index" ein Zeichen konfiguriert, unter dem der aktuelle Index der Schleife zu bekommen ist. Defaults werden sein: "[", "]" und "#" respektive. Wenn Variablen innerhalb des Konstruktes bereits einen Index haben, wird dieser (unter Beachtung eventuell notwendiger Arithmetik) berechnet und "fest" verwendet, zum Beispiel: [${foo[1]}] oder [${foo[(#+1)/2]}] Dementsprechend sind die folgenden Ausdrück equivalent: [${foo[#]}] == [${foo}] Wir unterstützen die vier Grundrechenarten, Modulo und Klammerung für arithmetische Operationen. Weiterhin wird der Callback um einen Parameter "int index" erweitert, welchen im Falle eines "normalen Variablenzugriffs" auf Null gesetzt wird. Zugriffe auf Indices, die nicht existieren, müssen vom Callback mit "UNDEFINED" quittiert werden. Ein Zugriff auf einen negativen Index liefert die Anzahl der Elemente in dem Array als String zurück. Ebenso liefert das Konstrukt ${foo:#} die Anzahl der Elemente zurück, wenn $foo ein Array ist. [...]-Konstrukte können beliebig tief geschachtelt werden. Innerhalb von Indixangaben dürfen erneut Variablen verwendet werden. Arrays werden nur in "expressions" erkannt, und im Konstrukt werden auch nur "expressions" gesondert behandelt; normale Variablen werden in jedem Pass normal expandiert. Sind "stardindex", "endindex" oder "current_index" leer (gleich '\0'), wird dieses Konstrukt vom Parser nicht erkannt und als Text interpretiert -- abgesehen von den Variablen, natürlich, welche aber nicht in einer Schleife expandiert werden, noch werden beim Callback Array-Elemente abgefragt. **** CLARIFICATION **** < [ $HOME ${ARRAY} ] is same as > [ $HOME ${ARRAY[0]} ] must use > [ $HOME ${ARRAY[#]} ] Correction to termination condition: we loop unless all ARRAYs containing '#' somewhere in the index expression return undefined. Any array using an constant index and scalar variables are ignored when evaluating the termination condition. Additionally we need support for explicit indexing, ranges and stepping using the following "regex-style" quantifiers: [ ... body ... ]{begin,step,end} [ ... body ... ]{begin,end} begin, step and end can be digits or arithmetic expressions using variables (exactly like the index expressions) or empty string with default for the empty string - begin = 0 - step = 1 - end = maximum of all $#{anyvar} where ${anyvar[...#...]} occurs in body. {,,} is same as {0,end} and can be omitted. < ${ARRAY:s/foo/bar:#} is same as > ${ARRAY[0]:s/foo/bar/:#} This means that operation has nothing to do with arrays but works on scalars. Correction to index variable from var_cb_t: this is a signed integer and allows negative, zero and positive indexes. It's up to the lookup callback to decide what is undefined. Some callbacks may support negative indices to support indexing from the end backwards through the array. This means negative numbers can not be used as the magic identifier for "gimme the number of elements for this variable". The callback needs another input, enum { VAR_LOOKUP_VALUE, VAR_LOOKUP_ELEMENTS, ... } var_lookup_t which tells the callback what to look up. Initially, only these modes are supported but we have room for future expansion here. The syntax change to adopt these changes is: $#{foo} returns the number of elements in foo while ${foo:#} returns the number of characters in the expanded value of foo. This keeps :# an command and makes ${foo} executing callback with VAR_LOOKUP_VALUE and $#{foo} executing callback with VAR_LOOKUP_ELEMENTS. Additionally it adopts Perl syntax. Extreme case: $#{foo:#} tells you how many digits the number of elements of foo has. Examples now working correctly: - Creation of a Newsgroups: header from To: headers w/o the last comma Newsgroup: [${To[#]}${To[#+1]:+${Separator} }] Newsgroup: [${To[#-1]:+${Separator} }${To[#]}] - Assume index zero is a header and the last element is a footer. Print a table with header, ruler, body, ruler and footer. ${foo[0]} ${empty:p/-/${foo[0]:#}/} [$foo{#}\n]{1,$#{foo}-1} ${empty:p/-/${foo[$#{foo}]:#}/} ${foo[$#{foo}]} --------------------------------------------------------------------- a25 15 o bugfix?: (thl) habe einen Bug in lib_var gefunden, scheint konzeptioneller Art zu sein. Ich benoetige zwei Passes fuer eine Anwendung, da es zwei verschiedene Arten von Variablen gibt. Eine hat nur Zahlen als gueltigen Namen, die andere Zahlen, Buchstaben, Punkt und Strich. Und die Ergebnisse des ersten Passes koennen die Namen des zweiten beeinflussen, daher muessen es zwei Passes sein. Sollte eigentlich funktionieren, dafuer gibt es die namechars im var_config_t und das force_expand feature. Ich setze also zuerst die namechars auf "0-9" und force_expand auf FALSE, anschliessend die namechars auf "0-9a-zA-Z.-" und force_expand auf TRUE. Aber bei einem Input von "${0}${abc}" bricht der Parser den ersten Pass bei "abc" mit "failed: incomplete variable" ab! Workaround: gleiche Namespaces, d.h. namechar's, verwenden - aber das ist nicht wirklich die ultimative Loesung. @ 1.15 log @another bug @ text @d11 7 @ 1.14 log @URL fixing and additional documents @ text @d3 8 a14 1 o document loop construct @ 1.13 log @HEADS UPS: Mega-commit, revamping the whole library! - completely new API - completely new manual page @ text @a2 1 o add README @ 1.12 log @remember an issue @ text @d3 5 d124 1 a124 3 o manual page style cleanup and perhaps merge with var_qref.pod? o add library context and move initialization and configuration @ 1.11 log @fix offset documentation @ text @d119 1 a119 1 o manual page style cleanup @ 1.10 log @update TODO @ text @a120 2 o docs of o1,2 und o1-2 seem to be still incorrect @ 1.9 log @remember @ text @d3 3 a6 1 a7 1 a14 1 a15 1 a21 1 a24 1 a25 1 a26 1 a27 1 a28 1 a29 1 a31 1 a38 1 a39 1 a41 1 a44 1 a50 2 - Abgabe: 6.12.2001 zum Nikolaustag im CVS. d117 3 d121 1 d123 2 a124 1 --- d126 19 a144 2 o manual page style cleanup o docs of o1,2 und o1-2 seem to be still incorrect @ 1.8 log @test commit for new repository @ text @d134 5 @ 1.7 log @clarifications @ text @d133 1 @ 1.6 log @Neues, fettes, geplantes Feature. @ text @d65 68 @ 1.5 log @remember my stuff here (added strerror issue, too) @ text @d3 1 a3 2 - Doku sollte ein Beispiel für Quoting von Shell- und Regexp-Ausdrücken enthalten. d5 1 a5 1 - Unterstützung von PCRE. d7 7 d15 1 a15 1 ---- RSE: -------------------------------------------------------------------- d17 6 a22 91 - HAS TO BE: adding a var_error() function which translates var_rc_t into a text version ala strerror(3). - HAS TO BE: still missing PCRE support plus corresponding Autoconf stuff - CAN BE: as in L2, reduce the large 1024 auto-variable with a a lot smaller (on 32-bit boxes just 21 bytes) but still fully sufficiently-sized variable: Index: var.c =================================================================== RCS file: /u/rse/arc/cvs/ossp/ossp-pkg/var/var.c,v retrieving revision 1.14 diff -u -d -u -d -r1.14 var.c --- var.c 2001/11/14 11:11:01 1.14 +++ var.c 2001/11/14 11:37:54 @@@@ -1261,8 +1261,8 @@@@ case '#': /* Substitute length of the string. */ if (data->begin) { - char buf[1024]; - sprintf(buf, "%d", data->end - data->begin); + char buf[((sizeof(int)*8)/3)+10]; /* sufficient size: <#bits> x log_10(2) + safety */ + sprintf(buf, "%d", (int)(data->end - data->begin)); tokenbuf_free(data); if (!tokenbuf_assign(data, buf, strlen(buf))) { rc = VAR_ERR_OUT_OF_MEMORY; - SHOULD BE: the "magic" number 256 in name class definitions would be nice if replaced by a symbolic name - SHOULD BE: the expand_octal() function checks that in the octal number NNN (representing a character) the first number is not larger than 3 because the 0xff is (octal) 377. Unfortunately this still allows things like 399 which is illegal because larger than 0xff (the maximum fitting into an 8-bit character). My suggestions: Index: var.c =================================================================== RCS file: /u/rse/arc/cvs/ossp/ossp-pkg/var/var.c,v retrieving revision 1.15 diff -u -d -u -d -r1.15 var.c --- var.c 2001/11/14 12:02:40 1.15 +++ var.c 2001/11/14 12:14:49 @@@@ -209,7 +209,7 @@@@ static var_rc_t expand_octal(const char **src, char **dst, const char *end) { - unsigned char c; + unsigned int c; if (end - *src < 3) return VAR_ERR_INCOMPLETE_OCTAL; @@@@ -217,8 +217,6 @@@@ return VAR_ERR_INVALID_OCTAL; c = **src - '0'; - if (c > 3) - return VAR_ERR_OCTAL_TOO_LARGE; c *= 8; ++(*src); @@@@ -227,6 +225,9 @@@@ ++(*src); c += **src - '0'; + + if (c > 0xff) + return VAR_ERR_OCTAL_TOO_LARGE; **dst = (char) c; ++(*dst); - SHOULD BE: the tokenbuf functions like tokenbuf_append() return 1 or 0 and the other routines convert this into var_rc_t values. I recommend to change the tokenbuf functions to already return var_rc_t values and pass this value through in other functions. This way the different errors in tokenbuf_append() are visible, too. - CAN BE: I IMHO would reduce the code size of the recursive descent parser by 1. making the prototype and corresponding parameter names of all functions identical (see for example text() for a current exclusion) and then use a macro to replace the long prototype description on every function. - SHOULD BE: the return code semantics are still not clear to me (perhaps it is solved by documentation). Especially it confuses me a lot that internally it uses "int" instead of "var_rc_t" and does arithmetics like "1 + rc" before finanlly it is casted to an var_rc_t. So how should anyone can do anything reasonable with return codes > 0. He does not know what they mean, doesn't he? d24 3 a26 1 ------------------------------------------------------------------------ d28 37 @ 1.4 log @Unescaping and submatching are implemented and hence removed from the TODO file. @ text @d7 98 @ 1.3 log @Moved the grammar from this file to the man page. @ text @a2 13 - Beim Suchen/Ersetzen mit Regular-Expression-Unterstützung fehlt noch die Erkennung von \1, \2 etc. - Jedes Vorkommen eines der folgenden Konstrukte im Text wird durch das zugehörige Sonderzeichen ersetzt. \t tab \n newline \r return \033 octal char \x1B hex char \x{263a} wide hex char @ 1.2 log @Removed the items that are fully implemented from the TODO file. @ text @a15 39 - Syntax: input : ( TEXT | variable )* variable : '$' ( name | expression ) expression : START-DELIM ( name | variable )+ ( ':' command )* END-DELIM name : ( VARNAME | SPECIAL1 | SPECIAL2 )+ command : '-' ( EXPTEXT | variable )+ | '+' ( EXPTEXT | variable )+ | 'o' ( NUMBER ('-' | ',') ( NUMBER )? ) | '#' | '*' ( EXPTEXT | variable )+ | 's' '/' ( variable | SUBSTTEXT )+ '/' ( variable | SUBSTTEXT )* '/' ( 'g' | 'i' | 't' )* | 'y' '/' ( variable | SUBSTTEXT )+ '/' ( variable | SUBSTTEXT )* '/' | 'p' '/' NUMBER '/' ( variable | SUBSTTEXT )* '/' ( 'r' | 'l' | 'c' ) | 'l' | 'u' START-DELIM : '{' END-DELIM : '}' VARNAME : '[a-zA-Z0-9_]+' SPECIAL1 : '[' SPECIAL2 : ']' NUMBER : '[0-9]+' SUBSTTEXT : '[^$/]' EXPTEXT : '[^$}:]+' TEXT : '[^$]+' @ 1.1 log @Initial revision @ text @d1 1 a1 1 libvar.a d3 2 a4 66 - Prefix ist "var_", beziehungsweise "VAR_". - Eine Variable kann im Text in der Form $name oder ${name} angegeben werden, wobei die Wahl der Klammern '{' '}' und des '$' parametriesiert werden können. - Gültige Zeichen für einen Variablennamen sind konfigurierbar. Garbage in -- garbage out. - Ein echtes '$'-Zeichen im Text kann durch Voranstellung eines wählbaren Escapezeichen dargestellt werden. Default ist der Backslash ('\'). - Der Aufrufer der Funktion soll steuern können, wie sich die Library verhält, wenn eine Variable nicht existiert. Denkbar sind: - Abbruch mit Fehler, - die Variable wird zu "", oder - der Ausdruck wird unverändert in den Ausgabetext übernommen, sodaß eventuell ein zweiter Pass gemacht werden kann. - ${parameter:-word} wird normal expandiert. Wenn "parameter" leer ist, wird stattdessen "word" eingesetzt. - ${parameter:+word} substituiert "word" wenn "parameter" nicht leer ist, sonst wird "" substituiert. - ${parameter:o-}, ${parameter:o-} - ${parameter:o,}, ${parameter:o,} - ${parameter:#} expandiert zur Länge des Inhaltes von "parameter". - ${parameter:s/pattern/string/[gti]} expandiert "parameter" und führt dann eine Ersetzung mittels des regulären Ausdrucks "pattern" durch. Wird das 'g'-Flag angegeben, wird nicht nur eine Instanz von "pattern" durch "string" ersetzt, sondern alle. Das 't'-Flag signalisiert, daß eine reine Text-Ersetzung ohne Unterstützung von regulären Ausdrücken gewünscht ist. Das 'i'-Flag besagt, daß die Suche nach "pattern" case-insensitiv durchgeführt wird. - ${parameter:y/ochars/nchars/} expandiert den Inhalt von "parameter" und transformiert dabei nach dem Prinzip von tr(1) die "ochars" im Text zu "nchars". - ${parameter:l} wandelt den Inhalt von "parameter" in Kleinbuchstaben, bevor es die Variable expandiert. Dies geschieht über toupper(3). - ${parameter:u} wandelt den Inhalt von "parameter" in Großbuchstaben, bevor es die Variable expandiert. Dies geschieht über tolower(3). - ${parameter:*word} expandiert zum leeren Wort, wenn "parameter" nicht leer ist, sonst zu "word". - Padding: ${parameter:p///} expandiert "parameter" in einen String der Mindestbreite , wobei abhaengig von ("r" = right, "l" = left, "c" = center) noch fehlende Zeichen mit aufgefuellt werden. Diest ist gedacht, um in Templates saubere Tabellen erzeugen zu koennen. Beispiele (foo="bar"): "${foo:p/6/./r}" -> "bar..." "${foo:p/6/./l}" -> "...bar" "${foo:p/6/./c}" -> ".bar.." (oder "..bar.", egal) "${foo:p/20/-=/c}" -> "-=-=-=-=-bar-=-=-=-=" d58 1 a58 54 - Wir unterstützen PCRE-, POSIX-Regex- oder keine regulären Ausdrücke. Dies kann über autoconf zur Compilezeit angegeben werden. - Das Escaping-Problem: Unsere Library macht zwei Dinge: (1) Sie expandiert Variablen-Ausdrücke mit Unterstützung von Operationen wie Suchen/Ersetzen, und (2) sie expandiert sogenannte "quoted pairs", wie zum Beispiel \n. Das Problem ist nun, daß sie dies in zwei Pässen tun will -- und muß. Die Frage ist jedoch, in welcher Reihenfolge tut sie es und welche Ergebnisse werden in den Ausgabetext ausgegeben? Betrachtet man folgendes Beispiel, wird das Problem klarer: Variablen: TEST = foo Eingabe..: Der Betrag auf Konto $TEST ist \$50. Soll die korrekte Ausgabe an dieser Stelle nun Der Betrag auf Konto foo ist \$50. oder Der Betrag auf Konto foo ist $50. sein? Die erste Form ist die, die man intuitiv erwartet, die zweite Form ist jedoch die, die man braucht, wenn man den Text durch mehrere Pässe jagen will -- was wir ausdrücklich vorgesehen haben. Schlimmer noch: Wie soll die Library die Eingabe Der Betrag auf Konto ${TEST:s/(.*)/\1bar/} ist \$50. interpretieren? Würde unser Parser das Token "\1" interpretieren, würde nur eine "1" zurückbleiben, der Benutzer müßte also "\\1" schreiben, um das Ergebnis zu erhalten, was er erwartet. Interpretierte unser Parser die "quoted pairs" nicht, könnte man den Ausdruck ${TEST:s/\n/ /g} nicht verwenden, weil die Regular-Expression-Funktionen ein '\n' nicht kennen. Nehmen wir also an, wir interpretieren "quoted pairs" und leben damit, daß der Benutzer dann doppelt escapen muß ... Wie verhält sich das dann mit mehreren Pässen? Läuft die Library zweimal über die Eingabe, bräuchte man bereits Der Betrag auf Konto ${TEST:s/(.*)/\\1bar/} ist \$50. @ 1.1.1.1 log @import first cut of OSSP var @ text @@