OSSP CVS Repository

ossp - Check-in [1288]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 1288
Date: 2001-Nov-09 18:01:37 (local)
2001-Nov-09 17:01:37 (UTC)
User:rse
Branch:
Comment: import first cut of OSSP var
Tickets:
Inspections:
Files:
ossp-pkg/var/Makefile      added-> 1.1.1.1
ossp-pkg/var/Odinfile      1.1 -> 1.1.1.1    
ossp-pkg/var/Odinfile      added-> 1.1
ossp-pkg/var/TODO      added-> 1.1.1.1
ossp-pkg/var/command.c      1.1 -> 1.1.1.1    
ossp-pkg/var/command.c      added-> 1.1
ossp-pkg/var/cut-out-offset.c      1.1 -> 1.1.1.1    
ossp-pkg/var/cut-out-offset.c      added-> 1.1
ossp-pkg/var/expand-character-class.c      1.1 -> 1.1.1.1    
ossp-pkg/var/expand-character-class.c      added-> 1.1
ossp-pkg/var/expand-named-characters.c      1.1 -> 1.1.1.1    
ossp-pkg/var/expand-named-characters.c      added-> 1.1
ossp-pkg/var/expand.c      1.1 -> 1.1.1.1    
ossp-pkg/var/expand.c      added-> 1.1
ossp-pkg/var/expression.c      1.1 -> 1.1.1.1    
ossp-pkg/var/expression.c      added-> 1.1
ossp-pkg/var/input.c      1.1 -> 1.1.1.1    
ossp-pkg/var/input.c      added-> 1.1
ossp-pkg/var/internal.h      1.1 -> 1.1.1.1    
ossp-pkg/var/internal.h      added-> 1.1
ossp-pkg/var/padding.c      1.1 -> 1.1.1.1    
ossp-pkg/var/padding.c      added-> 1.1
ossp-pkg/var/regression-tests/.run-tests      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/.run-tests      added-> 1.1
ossp-pkg/var/regression-tests/Makefile      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/Makefile      added-> 1.1
ossp-pkg/var/regression-tests/Odinfile      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/Odinfile      added-> 1.1
ossp-pkg/var/regression-tests/empty-search-pattern.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/empty-search-pattern.c      added-> 1.1
ossp-pkg/var/regression-tests/expand-character-class.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand-character-class.c      added-> 1.1
ossp-pkg/var/regression-tests/expand-named-characters.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand-named-characters.c      added-> 1.1
ossp-pkg/var/regression-tests/expand1.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand1.c      added-> 1.1
ossp-pkg/var/regression-tests/expand2.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand2.c      added-> 1.1
ossp-pkg/var/regression-tests/expand3.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand3.c      added-> 1.1
ossp-pkg/var/regression-tests/expand4.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand4.c      added-> 1.1
ossp-pkg/var/regression-tests/expand5.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand5.c      added-> 1.1
ossp-pkg/var/regression-tests/expand6.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/expand6.c      added-> 1.1
ossp-pkg/var/regression-tests/force-expand.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/force-expand.c      added-> 1.1
ossp-pkg/var/regression-tests/offset-failure.c      1.1 -> 1.1.1.1    
ossp-pkg/var/regression-tests/offset-failure.c      added-> 1.1
ossp-pkg/var/search-and-replace.c      1.1 -> 1.1.1.1    
ossp-pkg/var/search-and-replace.c      added-> 1.1
ossp-pkg/var/text.c      1.1 -> 1.1.1.1    
ossp-pkg/var/text.c      added-> 1.1
ossp-pkg/var/tokenbuf.c      1.1 -> 1.1.1.1    
ossp-pkg/var/tokenbuf.c      added-> 1.1
ossp-pkg/var/transpose.c      1.1 -> 1.1.1.1    
ossp-pkg/var/transpose.c      added-> 1.1
ossp-pkg/var/varexp.h      1.1 -> 1.1.1.1    
ossp-pkg/var/varexp.h      added-> 1.1
ossp-pkg/var/variable.c      1.1 -> 1.1.1.1    
ossp-pkg/var/variable.c      added-> 1.1

ossp-pkg/var/Makefile -> 1.1.1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,50 ----
+ # Build libvarexp.
+ 
+ CC             = gcc
+ AR             = ar
+ RANLIB                 = ranlib
+ 
+ WARNFLAGS      = -Wall -pedantic
+ OPTFLAGS       = -O3 -pipe
+ 
+ CPPFLAGS       =
+ CFLAGS         =
+ LDFLAGS                =
+ 
+ OBJS           = expand-named-characters.o expand-character-class.o command.o \
+                  expression.o variable.o text.o expand.o input.o tokenbuf.o   \
+                  search-and-replace.o cut-out-offset.o transpose.o padding.o
+ 
+ .c.o:
+        $(CC) $(CPPFLAGS) $(WARNFLAGS) $(OPTFLAGS) $(CFLAGS) -c $<
+ 
+ all:   libvarexp.a
+ 
+ libvarexp.a:   $(OBJS)
+        @rm -f $@
+        $(AR) cr $@ $(OBJS)
+        $(RANLIB) $@
+ 
+ clean::
+        @(cd regression-tests && $(MAKE) clean)
+        rm -f $(OBJS)
+        rm -f libvarexp.a
+ 
+ check::
+        (cd regression-tests && $(MAKE) check)
+ 
+ # Dependencies
+ 
+ command.o: internal.h varexp.h
+ cut-out-offset.o: internal.h varexp.h
+ expand-character-class.o: internal.h varexp.h
+ expand-named-characters.o: internal.h varexp.h
+ expand.o: internal.h varexp.h
+ expression.o: internal.h varexp.h
+ input.o: internal.h varexp.h
+ padding.o: internal.h varexp.h
+ search-and-replace.o: internal.h varexp.h
+ text.o: internal.h varexp.h
+ tokenbuf.o: internal.h varexp.h
+ transpose.o: internal.h varexp.h
+ variable.o: internal.h varexp.h


ossp-pkg/var/Odinfile -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,23 ----
+ # Build variable-expression library.
+ 
+ libvarexp.a == %libvarexp.a.sm +cc='gcc -Wall -pedantic' \
+                                +debug \
+                                :a
+ 
+ %libvarexp.a.sm == <<
+     expand-named-characters.c
+     expand-character-class.c
+     command.c
+     expression.c
+     variable.c
+     text.c
+     expand.c
+     input.c
+     tokenbuf.c
+     search-and-replace.c
+     cut-out-offset.c
+     transpose.c
+     padding.c
+ 
+ %clean ! == !<<
+     rm -f libvarexp.a


ossp-pkg/var/Odinfile 1.1 -> 1.1.1.1



ossp-pkg/var/TODO -> 1.1.1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,175 ----
+                               libvar.a
+ 
+  - 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<start>-}, ${parameter:o<start>-<end>}
+ 
+  - ${parameter:o<start>,}, ${parameter:o<start>,<length>}
+ 
+  - ${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/<width>/<string>/<align>} expandiert
+    "parameter" in einen String der Mindestbreite <width>, wobei abhaengig
+    von <align> ("r" = right, "l" = left, "c" = center) noch fehlende
+    Zeichen mit <string> 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-=-=-=-="
+ 
+  - 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
+ 
+  - 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            : '[^$]+'
+ 
+  - Doku sollte ein Beispiel für Quoting von Shell- und
+    Regexp-Ausdrücken enthalten.
+ 
+  - 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.


ossp-pkg/var/command.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,385 ----
+ #include "internal.h"
+ 
+ int command(const char* begin, const char* end, const var_config_t* config,
+             const char nameclass[256], var_cb_t lookup, void* lookup_context,
+             int force_expand, tokenbuf* data)
+     {
+     const char* p = begin;
+     tokenbuf tmptokbuf;
+     tokenbuf search, replace, flags;
+     tokenbuf number1, number2;
+     int isrange;
+     int rc;
+ 
+     init_tokenbuf(&tmptokbuf);
+     init_tokenbuf(&search);
+     init_tokenbuf(&replace);
+     init_tokenbuf(&flags);
+     init_tokenbuf(&number1);
+     init_tokenbuf(&number2);
+ 
+     if (begin == end)
+         return 0;
+ 
+     switch (tolower(*p))
+         {
+         case 'l':               /* Turn data to lowercase. */
+             if (data->begin)
+                 {
+                 char* ptr;
+                 /* If the buffer does not life in an allocated buffer,
+                    we have to copy it before modifying the contents. */
+ 
+                 if (data->buffer_size == 0)
+                     {
+                     if (!assign_to_tokenbuf(data, data->begin, data->end - data->begin))
+                         {
+                         rc = VAR_OUT_OF_MEMORY;
+                         goto error_return;
+                         }
+                     }
+                 for (ptr = (char*)data->begin; ptr != data->end; ++ptr)
+                     *ptr = tolower(*ptr);
+                 }
+             ++p;
+             break;
+ 
+         case 'u':               /* Turn data to uppercase. */
+             if (data->begin)
+                 {
+                 char* ptr;
+                 if (data->buffer_size == 0)
+                     {
+                     if (!assign_to_tokenbuf(data, data->begin, data->end - data->begin))
+                         {
+                         rc = VAR_OUT_OF_MEMORY;
+                         goto error_return;
+                         }
+                     }
+                 for (ptr = (char*)data->begin; ptr != data->end; ++ptr)
+                     *ptr = toupper(*ptr);
+                 }
+             ++p;
+             break;
+ 
+         case 'o':               /* Cut out substrings. */
+             ++p;
+             rc = number(p, end);
+             if (rc == 0)
+                 {
+                 rc = VAR_MISSING_START_OFFSET;
+                 goto error_return;
+                 }
+             else
+                 {
+                 number1.begin = p;
+                 number1.end   = p + rc;
+                 number1.buffer_size = 0;
+                 p += rc;
+                 }
+ 
+             if (*p == ',')
+                 {
+                 isrange = 0;
+                 ++p;
+                 }
+             else if (*p == '-')
+                 {
+                 isrange = 1;
+                 ++p;
+                 }
+             else
+                 {
+                 rc = VAR_INVALID_OFFSET_DELIMITER;
+                 goto error_return;
+                 }
+ 
+             rc = number(p, end);
+             number2.begin = p;
+             number2.end   = p + rc;
+             number2.buffer_size = 0;
+             p += rc;
+             if (data->begin)
+                 {
+                 rc = cut_out_offset(data, &number1, &number2, isrange);
+                 if (rc < 0)
+                     goto error_return;
+                 }
+             break;
+ 
+         case '#':               /* Substitute length of the string. */
+             if (data->begin)
+                 {
+                 char buf[1024];
+                 sprintf(buf, "%d", data->end - data->begin);
+                 free_tokenbuf(data);
+                 if (!assign_to_tokenbuf(data, buf, strlen(buf)))
+                     {
+                     rc = VAR_OUT_OF_MEMORY;
+                     goto error_return;
+                     }
+                 }
+             ++p;
+             break;
+ 
+         case '-':               /* Substitute parameter if data is empty. */
+             ++p;
+             rc = exptext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                      force_expand, &tmptokbuf);
+             if (rc < 0)
+                 goto error_return;
+             else if (rc == 0)
+                 {
+                 rc = VAR_MISSING_PARAMETER_IN_COMMAND;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             if (data->begin != NULL && data->begin == data->end)
+                 {
+                 free_tokenbuf(data);
+                 move_tokenbuf(&tmptokbuf, data);
+                 }
+             break;
+ 
+         case '*':               /* Return "" if data is not empty, parameter otherwise. */
+             ++p;
+             rc = exptext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                      force_expand, &tmptokbuf);
+             if (rc < 0)
+                 goto error_return;
+             else if (rc == 0)
+                 {
+                 rc = VAR_MISSING_PARAMETER_IN_COMMAND;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             if (data->begin != NULL)
+                 {
+                 if (data->begin == data->end)
+                     {
+                     free_tokenbuf(data);
+                     move_tokenbuf(&tmptokbuf, data);
+                     }
+                 else
+                     {
+                     free_tokenbuf(data);
+                     data->begin = data->end = "";
+                     data->buffer_size = 0;
+                     }
+                 }
+             break;
+ 
+         case '+':               /* Substitute parameter if data is not empty. */
+             ++p;
+             rc = exptext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                      force_expand, &tmptokbuf);
+             if (rc < 0)
+                 goto error_return;
+             else if (rc == 0)
+                 {
+                 rc = VAR_MISSING_PARAMETER_IN_COMMAND;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             if (data->begin != NULL)
+                 {
+                 if (data->begin != data->end)
+                     {
+                     free_tokenbuf(data);
+                     move_tokenbuf(&tmptokbuf, data);
+                     }
+                 }
+             break;
+ 
+         case 's':               /* Search and replace. */
+             ++p;
+ 
+             if (*p != '/')
+                 return VAR_MALFORMATTED_REPLACE;
+             else
+                 ++p;
+ 
+             rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                       force_expand, &search);
+             if (rc < 0)
+                 goto error_return;
+             else
+                 p += rc;
+ 
+             if (*p != '/')
+                 {
+                 rc = VAR_MALFORMATTED_REPLACE;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                       force_expand, &replace);
+             if (rc < 0)
+                 goto error_return;
+             else
+                 p += rc;
+ 
+             if (*p != '/')
+                 {
+                 rc = VAR_MALFORMATTED_REPLACE;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             rc = exptext(p, end, config);
+             if (rc < 0)
+                 goto error_return;
+             else
+                 {
+                 flags.begin = p;
+                 flags.end = p + rc;
+                 flags.buffer_size = 0;
+                 p += rc;
+                 }
+ 
+             if (data->begin)
+                 {
+                 rc = search_and_replace(data, &search, &replace, &flags);
+                 if (rc < 0)
+                     goto error_return;
+                 }
+             break;
+ 
+         case 'y':               /* Transpose characters from class A to class B. */
+             ++p;
+ 
+             if (*p != '/')
+                 return VAR_MALFORMATTED_TRANSPOSE;
+             else
+                 ++p;
+ 
+             rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                       force_expand, &search);
+             if (rc < 0)
+                 goto error_return;
+             else
+                 p += rc;
+ 
+             if (*p != '/')
+                 {
+                 rc = VAR_MALFORMATTED_TRANSPOSE;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                       force_expand, &replace);
+             if (rc < 0)
+                 goto error_return;
+             else
+                 p += rc;
+ 
+             if (*p != '/')
+                 {
+                 rc = VAR_MALFORMATTED_TRANSPOSE;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             if (data->begin)
+                 {
+                 rc = transpose(data, &search, &replace);
+                 if (rc < 0)
+                     goto error_return;
+                 }
+             break;
+ 
+ 
+         case 'p':               /* Padding. */
+             ++p;
+ 
+             if (*p != '/')
+                 return VAR_MALFORMATTED_PADDING;
+             else
+                 ++p;
+ 
+             rc = number(p, end);
+             if (rc == 0)
+                 {
+                 rc = VAR_MISSING_PADDING_WIDTH;
+                 goto error_return;
+                 }
+             else
+                 {
+                 number1.begin = p;
+                 number1.end   = p + rc;
+                 number1.buffer_size = 0;
+                 p += rc;
+                 }
+ 
+             if (*p != '/')
+                 {
+                 rc = VAR_MALFORMATTED_PADDING;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             rc = substext_or_variable(p, end, config, nameclass, lookup, lookup_context,
+                                       force_expand, &replace);
+             if (rc < 0)
+                 goto error_return;
+             else
+                 p += rc;
+ 
+             if (*p != '/')
+                 {
+                 rc = VAR_MALFORMATTED_PADDING;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             if (*p != 'l' && *p != 'c' && *p != 'r')
+                 {
+                 rc = VAR_MALFORMATTED_PADDING;
+                 goto error_return;
+                 }
+             else
+                 ++p;
+ 
+             if (data->begin)
+                 {
+                 rc = padding(data, &number1, &replace, p[-1]);
+                 if (rc < 0)
+                     goto error_return;
+                 }
+             break;
+ 
+         default:
+             return VAR_UNKNOWN_COMMAND_CHAR;
+         }
+ 
+     /* Exit gracefully. */
+ 
+     free_tokenbuf(&tmptokbuf);
+     free_tokenbuf(&search);
+     free_tokenbuf(&replace);
+     free_tokenbuf(&flags);
+     free_tokenbuf(&number1);
+     free_tokenbuf(&number2);
+     return p - begin;
+ 
+   error_return:
+     free_tokenbuf(data);
+     free_tokenbuf(&tmptokbuf);
+     free_tokenbuf(&search);
+     free_tokenbuf(&replace);
+     free_tokenbuf(&flags);
+     free_tokenbuf(&number1);
+     free_tokenbuf(&number2);
+     return rc;
+     }


ossp-pkg/var/command.c 1.1 -> 1.1.1.1



ossp-pkg/var/cut-out-offset.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,58 ----
+ #include "internal.h"
+ 
+ size_t tokenbuf2int(tokenbuf* number)
+     {
+     const char* p;
+     size_t num = 0;
+     for (p = number->begin; p != number->end; ++p)
+         {
+         num *= 10;
+         num += *p - '0';
+         }
+     return num;
+     }
+ 
+ int cut_out_offset(tokenbuf* data, tokenbuf* number1, tokenbuf* number2, int isrange)
+     {
+     tokenbuf res;
+     const char* p;
+     size_t num1 = tokenbuf2int(number1);
+     size_t num2 = tokenbuf2int(number2);
+ 
+     /* Determine begin of result string. */
+ 
+     if ((data->end - data->begin) < num1)
+         return VAR_OFFSET_OUT_OF_BOUNDS;
+     else
+         p = data->begin + num1;
+ 
+     /* If num2 is zero, we copy the rest from there. */
+ 
+     if (num2 == 0)
+         {
+         if (!assign_to_tokenbuf(&res, p, data->end - p))
+             return VAR_OUT_OF_MEMORY;
+         }
+     else                        /* OK, then use num2. */
+         {
+         if (isrange)
+             {
+             if ((p + num2) > data->end)
+                 return VAR_RANGE_OUT_OF_BOUNDS;
+             if (!assign_to_tokenbuf(&res, p, num2))
+                 return VAR_OUT_OF_MEMORY;
+             }
+         else
+             {
+             if (num2 < num1)
+                 return VAR_OFFSET_LOGIC_ERROR;
+             if ((data->begin + num2) > data->end)
+                 return VAR_RANGE_OUT_OF_BOUNDS;
+             if (!assign_to_tokenbuf(&res, p, (data->begin + num2) - p))
+                 return VAR_OUT_OF_MEMORY;
+             }
+         }
+     free_tokenbuf(data);
+     move_tokenbuf(&res, data);
+     return VAR_OK;
+     }


ossp-pkg/var/cut-out-offset.c 1.1 -> 1.1.1.1



ossp-pkg/var/expand-character-class.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,48 ----
+ #include "internal.h"
+ 
+ static void expand_range(char a, char b, char class[256])
+     {
+     assert(a <= b);
+     assert(class != NULL);
+ 
+     do
+         {
+         class[(int)a] = 1;
+         }
+     while (++a <= b);
+     }
+ 
+ 
+ var_rc_t expand_character_class(const char* desc, char class[256])
+     {
+     size_t i;
+ 
+     assert(desc != NULL);
+     assert(class != NULL);
+ 
+     /* Clear the class array. */
+ 
+     for (i = 0; i < 256; ++i)
+         class[i] = 0;
+ 
+     /* Walk through the class description and set the appropriate
+        entries in the array. */
+ 
+     while(*desc != '\0')
+         {
+         if (desc[1] == '-' && desc[2] != '\0')
+             {
+             if (desc[0] > desc[2])
+                 return VAR_INCORRECT_CLASS_SPEC;
+             expand_range(desc[0], desc[2], class);
+             desc += 3;
+             }
+         else
+             {
+             class[(int)*desc] = 1;
+             ++desc;
+             }
+         }
+ 
+     return VAR_OK;
+     }


ossp-pkg/var/expand-character-class.c 1.1 -> 1.1.1.1



ossp-pkg/var/expand-named-characters.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,177 ----
+ #include "internal.h"
+ 
+ /* Internal parsing code for octal. */
+ 
+ static int isoct(char c)
+     {
+     if (c >= '0' && c <= '7')
+         return 1;
+     else
+         return 0;
+     }
+ 
+ static var_rc_t expand_octal(const char** src, char** dst, const char* end)
+     {
+     unsigned char c;
+ 
+     if (end - *src < 3)
+         return VAR_INCOMPLETE_OCTAL;
+     if (!isoct(**src) || !isoct((*src)[1]) || !isoct((*src)[2]))
+         return VAR_INVALID_OCTAL;
+ 
+     c = **src - '0';
+     if (c > 3)
+         return VAR_OCTAL_TOO_LARGE;
+     c *= 8;
+     ++(*src);
+ 
+     c += **src - '0';
+     c *= 8;
+     ++(*src);
+ 
+     c += **src - '0';
+ 
+     **dst = (char)c;
+     ++(*dst);
+     return VAR_OK;
+     }
+ 
+ static int ishex(char c)
+     {
+     if ((c >= '0' && c <= '9') ||
+         (c >= 'a' && c <= 'f') ||
+         (c >= 'A' && c <= 'F'))
+         return 1;
+     else
+         return 0;
+     }
+ 
+ /* Internal parsing code for hex. */
+ 
+ static var_rc_t expand_simple_hex(const char** src, char** dst, const char* end)
+     {
+     unsigned char c = 0;
+ 
+     if (end - *src < 2)
+         return VAR_INCOMPLETE_HEX;
+     if (!ishex(**src) || !ishex((*src)[1]))
+         return VAR_INVALID_HEX;
+ 
+     if (**src >= '0' && **src <= '9')
+         c = **src - '0';
+     else if (c >= 'a' && c <= 'f')
+         c = **src - 'a' + 10;
+     else if (c >= 'A' && c <= 'F')
+         c = **src - 'A' + 10;
+ 
+     c = c << 4;
+     ++(*src);
+ 
+     if (**src >= '0' && **src <= '9')
+         c += **src - '0';
+     else if (**src >= 'a' && **src <= 'f')
+         c += **src - 'a' + 10;
+     else if (**src >= 'A' && **src <= 'F')
+         c += **src - 'A' + 10;
+ 
+     **dst = (char)c;
+     ++(*dst);
+     return VAR_OK;
+     }
+ 
+ static var_rc_t expand_grouped_hex(const char** src, char** dst, const char* end)
+     {
+     var_rc_t rc;
+ 
+     while (*src < end && **src != '}')
+         {
+         if ((rc = expand_simple_hex(src, dst, end)) != 0)
+             return rc;
+         ++(*src);
+         }
+     if (*src == end)
+         return VAR_INCOMPLETE_GROUPED_HEX;
+ 
+     return VAR_OK;
+     }
+ 
+ static var_rc_t expand_hex(const char** src, char** dst, const char* end)
+     {
+     if (*src == end)
+         return VAR_INCOMPLETE_HEX;
+     if (**src == '{')
+         {
+         ++(*src);
+         return expand_grouped_hex(src, dst, end);
+         }
+     else
+         return expand_simple_hex(src, dst, end);
+     }
+ 
+ /*
+   Expand the following named characters in the buffer:
+ 
+        \t          tab
+        \n          newline
+        \r          return
+        \033        octal char
+        \x1B        hex char
+        \x{263a}    wide hex char
+ 
+   Any other character quoted by a backslash is copied verbatim.
+ */
+ 
+ var_rc_t expand_named_characters(const char* src, size_t len, char* dst)
+     {
+     const char* end = src + len;
+     var_rc_t rc;
+ 
+     assert(src != NULL);
+     assert(dst != NULL);
+ 
+     while (src < end)
+         {
+         if (*src == '\\')
+             {
+             if (++src == end)
+                 return VAR_INCOMPLETE_NAMED_CHARACTER;
+             switch (*src)
+                 {
+                 case 'n':
+                     *dst++ = '\n';
+                     break;
+                 case 't':
+                     *dst++ = '\t';
+                     break;
+                 case 'r':
+                     *dst++ = '\r';
+                     break;
+                 case 'x':
+                     ++src;
+                     if ((rc = expand_hex(&src, &dst, end)) != 0)
+                         return rc;
+                     break;
+                 case '0':
+                 case '1':
+                 case '2':
+                 case '3':
+                 case '4':
+                 case '5':
+                 case '6':
+                 case '7':
+                 case '8':
+                 case '9':
+                     if ((rc = expand_octal(&src, &dst, end)) != 0)
+                         return rc;
+                     break;
+                 default:
+                     *dst++ = *src;
+                 }
+             ++src;
+             }
+         else
+             *dst++ = *src++;
+         }
+     *dst = '\0';
+     return VAR_OK;
+     }


ossp-pkg/var/expand-named-characters.c 1.1 -> 1.1.1.1



ossp-pkg/var/expand.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,60 ----
+ #include "internal.h"
+ 
+ const var_config_t var_config_default =
+     {
+     '$',                        /* varinit */
+     '{',                        /* startdelim */
+     '}',                        /* enddelim */
+     '\\',                       /* escape */
+     "a-zA-Z0-9_"                /* namechars */
+     };
+ 
+ var_rc_t var_expand(const char* input_buf, size_t input_len,
+                     char** result, size_t* result_len,
+                     var_cb_t lookup, void* lookup_context,
+                     const var_config_t* config, int force_expand)
+     {
+     char nameclass[256];
+     var_rc_t rc;
+     tokenbuf output;
+ 
+     /* Assert everything is as we expect it. */
+ 
+     assert(input != NULL);
+     assert(result != NULL);
+     assert(result_len != NULL);
+     assert(lookup != NULL);
+ 
+     /* Expand the class description for valid variable names. */
+ 
+     if (config == NULL)
+         config = &var_config_default;
+     rc = expand_character_class(config->namechars, nameclass);
+     if (rc != VAR_OK)
+         return rc;
+ 
+     /* Make sure that the specials defined in the configuration do not
+        appear in the character name class. */
+ 
+     if (nameclass[(int)config->varinit] ||
+         nameclass[(int)config->startdelim] ||
+         nameclass[(int)config->enddelim] ||
+         nameclass[(int)config->escape])
+         return VAR_INVALID_CONFIGURATION;
+ 
+     /* Call the parser. */
+ 
+     output.begin = output.end = NULL;
+     output.buffer_size = 0;
+     rc = input(input_buf, input_buf + input_len, config, nameclass,
+                lookup, lookup_context, force_expand, &output);
+     if (rc != VAR_OK)
+         {
+         free_tokenbuf(&output);
+         return rc;
+         }
+     *result     = (char*)output.begin;
+     *result_len = output.end - output.begin;
+ 
+     return VAR_OK;
+     }


ossp-pkg/var/expand.c 1.1 -> 1.1.1.1



ossp-pkg/var/expression.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,163 ----
+ #include "internal.h"
+ 
+ int expression(const char* begin, const char* end, const var_config_t* config,
+                const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                int force_expand, tokenbuf* result)
+     {
+     const char* p = begin;
+     const char* data;
+     size_t len, buffer_size;
+     int failed = 0;
+     int rc;
+     tokenbuf name;
+     tokenbuf tmp;
+ 
+     /* Clear the tokenbufs to make sure we have a defined state. */
+ 
+     init_tokenbuf(&name);
+     init_tokenbuf(&tmp);
+     init_tokenbuf(result);
+ 
+     /* Expect STARTDELIM. */
+ 
+     if (p == end || *p != config->startdelim)
+         return 0;
+ 
+     if (++p == end)
+         return VAR_INCOMPLETE_VARIABLE_SPEC;
+ 
+     /* Get the name of the variable to expand. The name may consist of
+        an arbitrary number of VARNAMEs and VARIABLEs. */
+ 
+     do
+         {
+         rc = varname(p, end, nameclass);
+         if (rc < 0)
+             goto error_return;
+         else if (rc > 0)
+             {
+             if (!append_to_tokenbuf(&name, p, rc))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             }
+ 
+         rc = variable(p, end, config, nameclass, lookup, lookup_context, force_expand, &tmp);
+         if (rc < 0)
+             goto error_return;
+         else if (rc > 0)
+             {
+             if (!append_to_tokenbuf(&name, tmp.begin, tmp.end - tmp.begin))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             }
+         }
+     while (rc > 0);
+ 
+     /* We must have the complete variable name now, so make sure we
+        do. */
+ 
+     if (name.begin == name.end)
+         {
+         rc = VAR_INCOMPLETE_VARIABLE_SPEC;
+         goto error_return;
+         }
+ 
+     /* Now we have the name of the variable stored in "name". We
+        expect an ENDDELIM here. */
+ 
+     if (p == end || (*p != config->enddelim && *p != ':'))
+         {
+         rc = VAR_INCOMPLETE_VARIABLE_SPEC;
+         goto error_return;
+         }
+     else
+         ++p;
+ 
+     /* Use the lookup callback to get the variable's contents. */
+ 
+     rc = (*lookup)(lookup_context, name.begin, name.end - name.begin, &data, &len, &buffer_size);
+     if (rc < 0)
+         goto error_return;
+     else if (rc == 0)
+         {
+         /* The variable is undefined. What we'll do now depends on the
+            force_expand flag. */
+ 
+         if (force_expand)
+             {
+             rc = VAR_UNDEFINED_VARIABLE;
+             goto error_return;
+             }
+         else
+             {
+             /* Initialize result to point back to the original text in
+                the buffer. */
+ 
+             result->begin       = begin-1;
+             result->end         = p;
+             result->buffer_size = 0;
+             failed              = 1;
+             }
+         }
+     else
+         {
+         /* The preliminary result is the contents of the variable.
+            This may be modified by the commands that may follow. */
+ 
+         result->begin       = data;
+         result->end         = data + len;
+         result->buffer_size = buffer_size;
+         }
+ 
+     if (p[-1] == ':')
+         {
+         /* Parse and execute commands. */
+ 
+         free_tokenbuf(&tmp);
+         --p;
+         while (p != end && *p == ':')
+             {
+             ++p;
+             if (!failed)
+                 rc = command(p, end, config, nameclass, lookup, lookup_context, force_expand, result);
+             else
+                 rc = command(p, end, config, nameclass, lookup, lookup_context, force_expand, &tmp);
+             if (rc < 0)
+                 goto error_return;
+             p += rc;
+             if (failed)
+                 result->end += rc;
+             }
+ 
+         if (p == end || *p != config->enddelim)
+             {
+             rc = VAR_INCOMPLETE_VARIABLE_SPEC;
+             goto error_return;
+             }
+         ++p;
+         if (failed)
+             ++result->end;
+         }
+ 
+     /* Exit gracefully. */
+ 
+     free_tokenbuf(&name);
+     free_tokenbuf(&tmp);
+     return p - begin;
+ 
+     /* Exit in case of an error. */
+ 
+   error_return:
+     free_tokenbuf(&name);
+     free_tokenbuf(&tmp);
+     free_tokenbuf(result);
+     return rc;
+     }


ossp-pkg/var/expression.c 1.1 -> 1.1.1.1



ossp-pkg/var/input.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,54 ----
+ #include "internal.h"
+ 
+ var_rc_t input(const char* begin, const char* end, const var_config_t* config,
+                const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                int force_expand, tokenbuf* output)
+     {
+     int rc;
+     tokenbuf result;
+ 
+     init_tokenbuf(&result);
+ 
+     do
+         {
+         rc = text(begin, end, config->varinit, config->escape);
+         if (rc > 0)
+             {
+             if (!append_to_tokenbuf(output, begin, rc))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             begin += rc;
+             }
+         else if (rc < 0)
+             goto error_return;
+ 
+         rc = variable(begin, end, config, nameclass, lookup, lookup_context, force_expand, &result);
+         if (rc > 0)
+             {
+             if (!append_to_tokenbuf(output, result.begin, result.end - result.begin))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             else
+                 begin += rc;
+             }
+         else if (rc < 0)
+             goto error_return;
+         }
+     while (rc > 0);
+ 
+     if (begin != end)
+         {
+         rc = VAR_INPUT_ISNT_TEXT_NOR_VARIABLE;
+         goto error_return;
+         }
+ 
+     return VAR_OK;
+ 
+   error_return:
+     free_tokenbuf(&result);
+     return rc;
+     }


ossp-pkg/var/input.c 1.1 -> 1.1.1.1



ossp-pkg/var/internal.h -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,86 ----
+ #ifndef INTERNAL_H
+ #define INTERNAL_H
+ 
+ #include <assert.h>
+ #include <ctype.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <errno.h>
+ #include "varexp.h"
+ 
+ #ifdef DMALLOC
+ #    define DMALLOC_FUNC_CHECK
+ #    include <dmalloc.h>
+ #endif
+ 
+ /* Turn character class descriptions into a lookup-array. */
+ 
+ var_rc_t expand_character_class(const char* desc, char class[256]);
+ 
+ /*
+    The tokenbuf structure is used by the parser routines. If
+    buffer_size is >0, it means that the buffer has been allocated by
+    malloc(3) and must be free(3)ed when not used anymore.
+ */
+ 
+ typedef struct
+     {
+     const char*  begin;
+     const char*  end;
+     size_t buffer_size;
+     }
+ tokenbuf;
+ 
+ int append_to_tokenbuf(tokenbuf* output, const char* begin, size_t rc);
+ void free_tokenbuf(tokenbuf* buf);
+ void init_tokenbuf(tokenbuf* buf);
+ int assign_to_tokenbuf(tokenbuf* buf, const char* data, size_t len);
+ void move_tokenbuf(tokenbuf* src, tokenbuf* dst);
+ 
+ var_rc_t input(const char* begin, const char* end, const var_config_t* config,
+                const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                int force_expand, tokenbuf* output);
+ 
+ int variable(const char* begin, const char* end, const var_config_t* config,
+              const char nameclass[256], var_cb_t lookup, void* lookup_context,
+              int force_expand, tokenbuf* result);
+ 
+ 
+ int command(const char* begin, const char* end, const var_config_t* config,
+             const char nameclass[256], var_cb_t lookup, void* lookup_context,
+             int force_expand, tokenbuf* result);
+ 
+ int exptext(const char* begin, const char* end, const var_config_t* config);
+ 
+ int exptext_or_variable(const char* begin, const char* end, const var_config_t* config,
+                         const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                         int force_expand, tokenbuf* result);
+ 
+ 
+ int substext_or_variable(const char* begin, const char* end, const var_config_t* config,
+                          const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                          int force_expand, tokenbuf* result);
+ 
+ int substext(const char* begin, const char* end, const var_config_t* config);
+ 
+ int search_and_replace(tokenbuf* data, tokenbuf* search, tokenbuf* replace, tokenbuf* flags);
+ 
+ int varname(const char* begin, const char* end, const char nameclass[256]);
+ 
+ int expression(const char* begin, const char* end, const var_config_t* config,
+                const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                int force_expand, tokenbuf* result);
+ 
+ int text(const char* begin, const char* end, char varinit, char escape);
+ 
+ int number(const char* begin, const char* end);
+ 
+ int cut_out_offset(tokenbuf* data, tokenbuf* number1, tokenbuf* number2, int isrange);
+ 
+ int transpose(tokenbuf* data, tokenbuf* search, tokenbuf* replace);
+ 
+ int padding(tokenbuf* data, tokenbuf* width, tokenbuf* fill, char position);
+ 
+ size_t tokenbuf2int(tokenbuf* number);
+ 
+ #endif /* !defined(INTERNAL_H) */


ossp-pkg/var/internal.h 1.1 -> 1.1.1.1



ossp-pkg/var/padding.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,139 ----
+ #include <sys/types.h>
+ #include <regex.h>
+ #include "internal.h"
+ 
+ int padding(tokenbuf* data, tokenbuf* widthstr, tokenbuf* fill, char position)
+     {
+     tokenbuf result;
+     size_t width = tokenbuf2int(widthstr);
+     int i;
+ 
+     printf("Padding data '%s' to width '%d' by filling in '%s' to position '%c'.\n",
+            data->begin, width, fill->begin, position);
+ 
+     if (fill->begin == fill->end)
+         return VAR_EMPTY_PADDING_FILL_STRING;
+ 
+     init_tokenbuf(&result);
+ 
+     if (position == 'l')
+         {
+         i = width - (data->end - data->begin);
+         if (i > 0)
+             {
+             printf("Missing %d characters at the end of the data string.\n", i);
+             i = i / (fill->end - fill->begin);
+             printf("That's %d times the padding string.\n", i);
+             while(i > 0)
+                 {
+                 if (!append_to_tokenbuf(data, fill->begin, fill->end - fill->begin))
+                     return VAR_OUT_OF_MEMORY;
+                 --i;
+                 }
+             i = (width - (data->end - data->begin)) % (fill->end - fill->begin);
+             printf("Plus a remainder of %d characters.\n", i);
+             if (!append_to_tokenbuf(data, fill->begin, i))
+                 return VAR_OUT_OF_MEMORY;
+             }
+         }
+     else if (position == 'r')
+         {
+         i = width - (data->end - data->begin);
+         if (i > 0)
+             {
+             printf("Missing %d characters at the beginning of the data string.\n", i);
+             i = i / (fill->end - fill->begin);
+             printf("That's %d times the padding string.\n", i);
+             while(i > 0)
+                 {
+                 if (!append_to_tokenbuf(&result, fill->begin, fill->end - fill->begin))
+                     {
+                     free_tokenbuf(&result);
+                     return VAR_OUT_OF_MEMORY;
+                     }
+                 --i;
+                 }
+             i = (width - (data->end - data->begin)) % (fill->end - fill->begin);
+             printf("Plus a remainder of %d characters.\n", i);
+             if (!append_to_tokenbuf(&result, fill->begin, i))
+                 {
+                 free_tokenbuf(&result);
+                 return VAR_OUT_OF_MEMORY;
+                 }
+             if (!append_to_tokenbuf(&result, data->begin, data->end - data->begin))
+                 {
+                 free_tokenbuf(&result);
+                 return VAR_OUT_OF_MEMORY;
+                 }
+ 
+             free_tokenbuf(data);
+             move_tokenbuf(&result, data);
+             }
+         }
+      else if (position == 'c')
+         {
+         i = (width - (data->end - data->begin)) / 2;
+         if (i > 0)
+             {
+             /* Create the prefix. */
+ 
+             printf("Missing %d characters at the beginning of the data string.\n", i);
+             i = i / (fill->end - fill->begin);
+             printf("That's %d times the padding string.\n", i);
+             while(i > 0)
+                 {
+                 if (!append_to_tokenbuf(&result, fill->begin, fill->end - fill->begin))
+                     {
+                     free_tokenbuf(&result);
+                     return VAR_OUT_OF_MEMORY;
+                     }
+                 --i;
+                 }
+             i = ((width - (data->end - data->begin)) / 2) % (fill->end - fill->begin);
+             printf("Plus a remainder of %d characters.\n", i);
+             if (!append_to_tokenbuf(&result, fill->begin, i))
+                 {
+                 free_tokenbuf(&result);
+                 return VAR_OUT_OF_MEMORY;
+                 }
+ 
+             /* Append the actual data string. */
+ 
+             if (!append_to_tokenbuf(&result, data->begin, data->end - data->begin))
+                 {
+                 free_tokenbuf(&result);
+                 return VAR_OUT_OF_MEMORY;
+                 }
+ 
+             /* Append the suffix. */
+ 
+             i = width - (result.end - result.begin);
+             printf("Missing %d characters at the end of the data string.\n", i);
+             i = i / (fill->end - fill->begin);
+             printf("That's %d times the padding string.\n", i);
+             while(i > 0)
+                 {
+                 if (!append_to_tokenbuf(&result, fill->begin, fill->end - fill->begin))
+                     {
+                     free_tokenbuf(&result);
+                     return VAR_OUT_OF_MEMORY;
+                     }
+                 --i;
+                 }
+             i = width - (result.end - result.begin);
+             printf("Plus a remainder of %d characters.\n", i);
+             if (!append_to_tokenbuf(&result, fill->begin, i))
+                 {
+                 free_tokenbuf(&result);
+                 return VAR_OUT_OF_MEMORY;
+                 }
+ 
+             /* Move string from temporary buffer to data buffer. */
+ 
+             free_tokenbuf(data);
+             move_tokenbuf(&result, data);
+             }
+         }
+ 
+     return VAR_OK;
+     }


ossp-pkg/var/padding.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/.run-tests -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,44 ----
+ #! /bin/sh
+ 
+ if [ $# -lt 1 ]; then
+     echo "Usage: $0 test1.exe [...]"
+     exit 1
+ fi
+ 
+ RESCOLUMN=50
+ numTests=0
+ numFails=0
+ 
+ echo "Running test suite:"
+ 
+ pad=''
+ n=$RESCOLUMN
+ while [ $n -gt 0 ]; do
+     pad="$pad."
+     n=`expr $n - 1`
+ done
+ for suite in "$@"; do
+     name=`basename "${suite}"`
+     name=`expr "${name}" : '\(.*\)\.exe$'`
+     echo "$name$pad" | awk '{ printf("%s ", substr($0, 0, n)); }' n=$RESCOLUMN
+     export DMALLOC_OPTIONS=debug=0x4f47d03,inter=1,log=/tmp/$name.dmalloc
+     numTests=`expr $numTests + 1`
+     eval ./$suite >/dev/null 2>&1
+     if [ $? -eq 0 ]; then
+         echo "OK"
+     else
+         numFails=`expr $numFails + 1`
+         echo "FAILED"
+     fi
+ done
+ 
+ echo
+ if [ $numFails -eq 0 ]; then
+     echo "Summary: All tests succeeded."
+     exit 0
+ else
+     percent=`expr $numFails \* 100`
+     percent=`expr $percent / $numTests`
+     echo "Summary: $numFails of $numTests tests failed ($percent%)."
+     exit 1
+ fi


ossp-pkg/var/regression-tests/.run-tests 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/Makefile -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,44 ----
+ # Regression tests for libvarexp.
+ 
+ CC             = gcc
+ AR             = ar
+ RANLIB                 = ranlib
+ 
+ WARNFLAGS      = -Wall -pedantic
+ OPTFLAGS       = -O3 -pipe
+ 
+ CPPFLAGS       =
+ CFLAGS         =
+ LDFLAGS                =
+ 
+ .SUFFIXES:     .exe
+ 
+ TESTS          =  expand-named-characters.exe expand-character-class.exe \
+                   expand1.exe expand2.exe force-expand.exe expand3.exe \
+                   expand4.exe expand5.exe expand6.exe empty-search-pattern.exe \
+                   offset-failure.exe
+ 
+ .c.exe:
+        $(CC) $(CPPFLAGS) $(WARNFLAGS) $(OPTFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< -L.. -lvarexp
+ 
+ check:
+        @(cd .. && $(MAKE) libvarexp.a)
+        @$(MAKE) $(TESTS)
+        @./.run-tests $(TESTS)
+ 
+ clean::
+        rm -f $(TESTS)
+ 
+ # Dependencies
+ 
+ empty-search-pattern.exe: ../internal.h ../varexp.h
+ expand-character-class.exe: ../internal.h ../varexp.h
+ expand-named-characters.exe: ../internal.h ../varexp.h
+ expand1.exe: ../internal.h ../varexp.h
+ expand2.exe: ../internal.h ../varexp.h
+ expand3.exe: ../internal.h ../varexp.h
+ expand4.exe: ../internal.h ../varexp.h
+ expand5.exe: ../internal.h ../varexp.h
+ expand6.exe: ../internal.h ../varexp.h
+ force-expand.exe: ../internal.h ../varexp.h
+ offset-failure.exe: ../internal.h ../varexp.h


ossp-pkg/var/regression-tests/Makefile 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/Odinfile -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,81 ----
+ # Regression tests for libvarexp.
+ 
+ %test == () +cmd='sh' (%run-tests) \
+                       (expand-named-characters.exe) \
+                       (expand-character-class.exe) \
+                       (expand1.exe) \
+                       (expand2.exe) \
+                       (force-expand.exe) \
+                       (expand3.exe) \
+                       (expand4.exe) \
+                       (expand5.exe) \
+                       (expand6.exe) \
+                       (empty-search-pattern.exe) \
+                       (offset-failure.exe) \
+                       +output_show \
+                       :stdout
+ 
+ expand-named-characters.exe == expand-named-characters.c +(%test.flags) :exe
+ expand-character-class.exe == expand-character-class.c +(%test.flags) :exe
+ expand1.exe == expand1.c +(%test.flags) :exe
+ expand2.exe == expand2.c +(%test.flags) :exe
+ force-expand.exe == force-expand.c +(%test.flags) :exe
+ expand3.exe == expand3.c +(%test.flags) :exe
+ expand4.exe == expand4.c +(%test.flags) :exe
+ expand5.exe == expand5.c +(%test.flags) :exe
+ expand6.exe == expand6.c +(%test.flags) :exe
+ empty-search-pattern.exe == empty-search-pattern.c +(%test.flags) :exe
+ offset-failure.exe == offset-failure.c +(%test.flags) :exe
+ 
+ %test.flags == <<
+     +lib=(../libvarexp.a)
+     +cc='gcc -Wall -pedantic'
+     +debug
+ 
+ %run-tests == <<[eof]
+     if [ $# -lt 1 ]; then
+         echo "Usage: $0 test1.exe [...]"
+         exit 1
+     fi
+ 
+     RESCOLUMN=50
+     numTests=0
+     numFails=0
+ 
+     echo "Running test suite:"
+ 
+     pad=''
+     n=$RESCOLUMN
+     while [ $n -gt 0 ]; do
+         pad="$pad."
+         n=`expr $n - 1`
+     done
+     for suite in "$@"; do
+         name=`basename "${suite}"`
+         name=`expr "${name}" : '\(.*\)\.exe$'`
+         echo "$name$pad" | awk '{ printf("%s ", substr($0, 0, n)); }' n=$RESCOLUMN
+         export DMALLOC_OPTIONS=debug=0x4f47d03,inter=1,log=/tmp/$name.dmalloc
+         numTests=`expr $numTests + 1`
+         eval $suite >/dev/null 2>&1
+         if [ $? -eq 0 ]; then
+             echo "OK"
+         else
+             numFails=`expr $numFails + 1`
+             echo "FAILED"
+         fi
+     done
+ 
+     echo
+     if [ $numFails -eq 0 ]; then
+         echo "Summary: All tests succeeded."
+         exit 0
+     else
+         percent=`expr $numFails \* 100`
+         percent=`expr $percent / $numTests`
+         echo "Summary: $numFails of $numTests tests failed ($percent%)."
+         exit 1
+     fi
+ [eof]
+ 
+ %clean ! == !<<
+     rm -f *.exe


ossp-pkg/var/regression-tests/Odinfile 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/empty-search-pattern.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,48 ----
+ #include "../internal.h"
+ 
+ int env_lookup(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     char tmp[256];
+ 
+     if (name_len > sizeof(tmp)-1)
+         {
+         printf("Callback can't expand variable names longer than %d characters.\n", sizeof(tmp-1));
+         exit(1);
+         }
+     memcpy(tmp, varname, name_len);
+     tmp[name_len] = '\0';
+     *data = getenv(tmp);
+     if (*data == NULL)
+         return 0;
+     *data_len = strlen(*data);
+     *buffer_size = 0;
+     return 1;
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input = "${HOME:s/$EMPTY/test/}";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     if (setenv("HOME", "/home/regression-tests", 1) != 0 ||
+         setenv("EMPTY", "", 1) != 0)
+         {
+         printf("Failed to set the environment: %s.\n", strerror(errno));
+         return 1;
+         }
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &env_lookup, NULL,
+                     NULL, 0);
+     if (rc != VAR_EMPTY_SEARCH_STRING)
+         {
+         printf("var_expand() should have failed with VAR_EMPTY_SEARCH_STRING but returned %d.\n", rc);
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/empty-search-pattern.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand-character-class.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,56 ----
+ #include "../internal.h"
+ 
+ static void class2string(char class[256], char* buf)
+     {
+     size_t i;
+     for (i = 0; i < 256; ++i)
+         {
+         if (class[i])
+             *buf++ = (char)i;
+         }
+     *buf = '\0';
+     }
+ 
+ struct test_case
+     {
+     const char* input;
+     const char* expected;
+     var_rc_t    rc;
+     };
+ 
+ int main(int argc, char** argv)
+     {
+     struct test_case tests[] =
+         {
+         { "",               "",                             VAR_OK                   },
+         { "abcabc",         "abc",                          VAR_OK                   },
+         { "a-z",            "abcdefghijklmnopqrstuvwxyz",   VAR_OK                   },
+         { "a-eA-Eabcdef-",  "-ABCDEabcdef",                 VAR_OK                   },
+         { "-a-eA-Eabcdef-", "-ABCDEabcdef",                 VAR_OK                   },
+         { "0-9-",           "-0123456789",                  VAR_OK                   },
+         { "g-a",            NULL,                           VAR_INCORRECT_CLASS_SPEC }
+         };
+     size_t i;
+     char class[256];
+     char tmp[1024];
+ 
+     for (i = 0; i < sizeof(tests) / sizeof(struct test_case); ++i)
+         {
+         if (expand_character_class(tests[i].input, class) != tests[i].rc)
+             {
+             printf("expand_character_class() failed test case %d.\n", i);
+             return 1;
+             }
+         if (tests[i].expected != NULL)
+             {
+             class2string(class, tmp);
+             if (strcmp(tmp, tests[i].expected) != 0)
+                 {
+                 printf("expand_character_class() failed test case %d.\n", i);
+                 return 1;
+                 }
+             }
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand-character-class.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand-named-characters.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,49 ----
+ #include "../internal.h"
+ 
+ struct test_case
+     {
+     const char* input;
+     const char* expected;
+     var_rc_t    rc;
+     };
+ 
+ int main(int argc, char** argv)
+     {
+     struct test_case tests[] =
+         {
+         { "",                     "",                 VAR_OK                         },
+         { "\\",                   NULL,               VAR_INCOMPLETE_NAMED_CHARACTER },
+         { "hello world",          "hello world",      VAR_OK                         },
+         { "\\n",                  "\n",               VAR_OK                         },
+         {"\\t",                   "\t",               VAR_OK                         },
+         { "\\rhello\\tworld\\n",  "\rhello\tworld\n", VAR_OK                         },
+         { "\\x5a\\x5A",           "ZZ",               VAR_OK                         },
+         { "\\x5g\\x5A",           NULL,               VAR_INVALID_HEX                },
+         { "\\x5",                 NULL,               VAR_INCOMPLETE_HEX             },
+         { "\\033",                "\033",             VAR_OK                         },
+         { "\\03",                 NULL,               VAR_INCOMPLETE_OCTAL           },
+         { "\\038",                NULL,               VAR_INVALID_OCTAL              },
+         { "\\400",                NULL,               VAR_OCTAL_TOO_LARGE            },
+         { "\\x{4243}",            "BC",               VAR_OK                         },
+         { "\\x{}",                "",                 VAR_OK                         },
+         { "\\x{5a5A5a5A}",        "ZZZZ",             VAR_OK                         },
+         { "\\x{",                 NULL,               VAR_INCOMPLETE_GROUPED_HEX     },
+         { "x\\x{5a5A5a5A}a",      "xZZZZa",           VAR_OK                         },
+         { "x\\x{5a5A5a\\0015A}a", NULL,               VAR_INVALID_HEX                },
+         { "x\\x{5a\\x{5a}5A}a",   NULL,               VAR_INVALID_HEX                }
+         };
+     size_t i;
+     char tmp[1024];
+ 
+     for (i = 0; i < sizeof(tests) / sizeof(struct test_case); ++i)
+         {
+         if (expand_named_characters(tests[i].input, strlen(tests[i].input), tmp) != tests[i].rc ||
+             (tests[i].expected != NULL && strcmp(tmp, tests[i].expected) != 0))
+             {
+             printf("expand_named_characters() failed test case %d.\n", i);
+             return 1;
+             }
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand-named-characters.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand1.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,45 ----
+ #include "../internal.h"
+ 
+ int dummy(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     printf("The dummy callback should not have been called!\n");
+     exit(1);
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input  = "This is a \\$test!";
+     const char* output = "This is a \\$test!";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &dummy, NULL,
+                     NULL, 0);
+     if (rc != VAR_OK)
+         {
+         printf("var_expand() failed with error %d.\n", rc);
+         return 1;
+         }
+ 
+     if (tmp_len != strlen(output))
+         {
+         printf("The length of the output string is not what we expected: %d != %d.\n",
+                tmp_len, strlen(output));
+         return 1;
+         }
+ 
+     if (memcmp(tmp, output, tmp_len) != 0)
+         {
+         printf("The buffer returned by var_expand() is not what we expected.\n");
+         return 1;
+         }
+ 
+     free(tmp);
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand1.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand2.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,56 ----
+ #include "../internal.h"
+ 
+ int dummy(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     if (name_len != sizeof("test")-1)
+         {
+         printf("The the length of the variable name (%d) doesn't fit.\n", name_len);
+         exit(1);
+         }
+     if (memcmp(varname, "test", sizeof("test")-1) != 0)
+         {
+         printf("Callback called for unknown variable.\n");
+         exit(1);
+         }
+     *data        = "foobar";
+     *data_len    = sizeof("foobar")-1;
+     *buffer_size = 0;
+ 
+     return 1;
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input  = "This is a $test!";
+     const char* output = "This is a foobar!";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &dummy, NULL,
+                     NULL, 0);
+     if (rc != VAR_OK)
+         {
+         printf("var_expand() failed with error %d.\n", rc);
+         return 1;
+         }
+ 
+     if (tmp_len != strlen(output))
+         {
+         printf("The length of the output string is not what we expected: %d != %d.\n",
+                tmp_len, strlen(output));
+         return 1;
+         }
+ 
+     if (memcmp(tmp, output, tmp_len) != 0)
+         {
+         printf("The buffer returned by var_expand() is not what we expected.\n");
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand2.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand3.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,81 ----
+ #include "../internal.h"
+ 
+ int env_lookup(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     char tmp[256];
+ 
+     if (name_len > sizeof(tmp)-1)
+         {
+         printf("Callback can't expand variable names longer than %d characters.\n", sizeof(tmp-1));
+         exit(1);
+         }
+     memcpy(tmp, varname, name_len);
+     tmp[name_len] = '\0';
+     *data = getenv(tmp);
+     if (*data == NULL)
+         return 0;
+     *data_len = strlen(*data);
+     *buffer_size = 0;
+     return 1;
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input =                            \
+         "\\$HOME      = '$HOME'\\n"                \
+         "\\$OSTYPE    = '$OSTYPE'\\n"              \
+         "\\$UNDEFINED = '$UNDEFINED'\\n"           \
+         "\\$TERM      = '$TERM'\\n";
+     const char* output =                           \
+         "$HOME      = '/home/regression-tests'\n"  \
+         "$OSTYPE    = 'regression-os'\n"           \
+         "$UNDEFINED = '$UNDEFINED'\n"              \
+         "$TERM      = 'regression-term'\n";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     if (setenv("HOME", "/home/regression-tests", 1) != 0 ||
+         setenv("OSTYPE", "regression-os", 1) != 0 ||
+         setenv("TERM", "regression-term", 1) != 0)
+         {
+         printf("Failed to set the environment: %s.\n", strerror(errno));
+         return 1;
+         }
+     unsetenv("UNDEFINED");
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &env_lookup, NULL,
+                     NULL, 0);
+     if (rc != VAR_OK)
+         {
+         printf("var_expand() failed with error %d.\n", rc);
+         return 1;
+         }
+ 
+     rc = expand_named_characters(tmp, tmp_len, tmp);
+     if (rc != VAR_OK)
+         {
+         printf("expand_named_characters() failed with error %d.\n", rc);
+         return 1;
+         }
+     else
+         tmp_len = strlen(tmp);
+ 
+     if (tmp_len != strlen(output))
+         {
+         printf("The length of the output string is not what we expected: %d != %d.\n",
+                tmp_len, strlen(output));
+         return 1;
+         }
+ 
+     if (memcmp(tmp, output, tmp_len) != 0)
+         {
+         printf("The buffer returned by var_expand() is not what we expected.\n");
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand3.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand4.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,81 ----
+ #include "../internal.h"
+ 
+ int env_lookup(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     char tmp[256];
+ 
+     if (name_len > sizeof(tmp)-1)
+         {
+         printf("Callback can't expand variable names longer than %d characters.\n", sizeof(tmp-1));
+         exit(1);
+         }
+     memcpy(tmp, varname, name_len);
+     tmp[name_len] = '\0';
+     *data = getenv(tmp);
+     if (*data == NULL)
+         return 0;
+     *data_len = strlen(*data);
+     *buffer_size = 0;
+     return 1;
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input =                            \
+         "\\$HOME      = '${HOME}'\\n"              \
+         "\\$OSTYPE    = '${OSTYPE}'\\n"            \
+         "\\$UNDEFINED = '${UNDEFINED}'\\n"         \
+         "\\$TERM      = '${TERM}'\\n";
+     const char* output =                           \
+         "$HOME      = '/home/regression-tests'\n"  \
+         "$OSTYPE    = 'regression-os'\n"           \
+         "$UNDEFINED = '${UNDEFINED}'\n"            \
+         "$TERM      = 'regression-term'\n";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     if (setenv("HOME", "/home/regression-tests", 1) != 0 ||
+         setenv("OSTYPE", "regression-os", 1) != 0 ||
+         setenv("TERM", "regression-term", 1) != 0)
+         {
+         printf("Failed to set the environment: %s.\n", strerror(errno));
+         return 1;
+         }
+     unsetenv("UNDEFINED");
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &env_lookup, NULL,
+                     NULL, 0);
+     if (rc != VAR_OK)
+         {
+         printf("var_expand() failed with error %d.\n", rc);
+         return 1;
+         }
+ 
+     rc = expand_named_characters(tmp, tmp_len, tmp);
+     if (rc != VAR_OK)
+         {
+         printf("expand_named_characters() failed with error %d.\n", rc);
+         return 1;
+         }
+     else
+         tmp_len = strlen(tmp);
+ 
+     if (tmp_len != strlen(output))
+         {
+         printf("The length of the output string is not what we expected: %d != %d.\n",
+                tmp_len, strlen(output));
+         return 1;
+         }
+ 
+     if (memcmp(tmp, output, tmp_len) != 0)
+         {
+         printf("The buffer returned by var_expand() is not what we expected.\n");
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand4.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand5.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,85 ----
+ #include "../internal.h"
+ 
+ int env_lookup(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     char tmp[256];
+ 
+     if (name_len > sizeof(tmp)-1)
+         {
+         printf("Callback can't expand variable names longer than %d characters.\n", sizeof(tmp-1));
+         exit(1);
+         }
+     memcpy(tmp, varname, name_len);
+     tmp[name_len] = '\0';
+     *data = getenv(tmp);
+     if (*data == NULL)
+         return 0;
+     *data_len = strlen(*data);
+     *buffer_size = 0;
+     return 1;
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input =                            \
+         "\\$HOME      = '${HOME}'\\n"              \
+         "\\$OSTYPE    = '${$FOO${BAR}}'\\n"        \
+         "\\$UNDEFINED = '${UNDEFINED}'\\n"         \
+         "\\$TERM      = '${TERM}'\\n";
+     const char* output =                           \
+         "$HOME      = '/home/regression-tests'\n"  \
+         "$OSTYPE    = 'regression-os'\n"           \
+         "$UNDEFINED = '${UNDEFINED}'\n"            \
+         "$TERM      = 'regression-term'\n";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     if (setenv("HOME", "/home/regression-tests", 1) != 0 ||
+         setenv("OSTYPE", "regression-os", 1) != 0 ||
+         setenv("TERM", "regression-term", 1) != 0 ||
+         setenv("FOO", "OS", 1) != 0 ||
+         setenv("BAR", "TYPE", 1) != 0)
+         {
+         printf("Failed to set the environment: %s.\n", strerror(errno));
+         return 1;
+         }
+     unsetenv("UNDEFINED");
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &env_lookup, NULL,
+                     NULL, 0);
+     if (rc != VAR_OK)
+         {
+         printf("var_expand() failed with error %d.\n", rc);
+         return 1;
+         }
+ 
+     rc = expand_named_characters(tmp, tmp_len, tmp);
+     if (rc != VAR_OK)
+         {
+         printf("expand_named_characters() failed with error %d.\n", rc);
+         return 1;
+         }
+     else
+         tmp_len = strlen(tmp);
+ 
+     printf("==================================================\n%s==================================================\n", tmp);
+ 
+     if (tmp_len != strlen(output))
+         {
+         printf("The length of the output string is not what we expected: %d != %d.\n",
+                tmp_len, strlen(output));
+         return 1;
+         }
+ 
+     if (memcmp(tmp, output, tmp_len) != 0)
+         {
+         printf("The buffer returned by var_expand() is not what we expected.\n");
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand5.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/expand6.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,121 ----
+ #include "../internal.h"
+ 
+ int env_lookup(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     char tmp[256];
+ 
+     if (name_len > sizeof(tmp)-1)
+         {
+         printf("Callback can't expand variable names longer than %d characters.\n", sizeof(tmp-1));
+         exit(1);
+         }
+     memcpy(tmp, varname, name_len);
+     tmp[name_len] = '\0';
+     *data = getenv(tmp);
+     if (*data == NULL)
+         return 0;
+     *data_len = strlen(*data);
+     *buffer_size = 0;
+     return 1;
+     }
+ 
+ struct test_case
+     {
+     const char* input;
+     const char* expected;
+     };
+ 
+ int main(int argc, char** argv)
+     {
+     const struct test_case tests[] =
+         {
+         { "$HOME",                      "/home/regression-tests"          },
+         { "${FOO}",                     "os"                              },
+         { "${BAR}",                     "type"                            },
+         { "${${FOO:u}${BAR:u}:l:u}",    "REGRESSION-OS"                   },
+         { "${UNDEFINED}",               "${UNDEFINED}"                    },
+         { "${OSTYPE:#}",                "13"                              },
+         { "${EMPTY:-test${FOO}test}",   "testostest"                      },
+         { "${EMPTY:-test${FOO:u}test}", "testOStest"                      },
+         { "${TERM:-test${FOO}test}",    "regression-term"                 },
+         { "${EMPTY:+FOO}",              ""                                },
+         { "${HOME:+test${FOO}test}",    "testostest"                      },
+         { "${HOME:+${OS${BAR:u}}}",     "regression-os"                   },
+         { "${HOME:+OS${UNDEFINED:u}}",  "OS${UNDEFINED:u}"                },
+         { "${UNDEFINED:+OS${BAR:u}}",   "${UNDEFINED:+OS${BAR:u}}"        },
+         { "${HOME:*heinz}",             ""                                },
+         { "${EMPTY:*claus}",            "claus"                           },
+         { "${TERM}",                    "regression-term"                 },
+         { "${HOME:s/reg/bla/}",         "/home/blaression-tests"          },
+         { "${HOME:s/e/bla/}",           "/hombla/regression-tests"        },
+         { "${HOME:s/e/bla/g}",          "/hombla/rblagrblassion-tblasts"  },
+         { "${HOME:s/\\//_/g}",          "_home_regression-tests"          },
+         { "${HOME:s/[eso]/_/g}",        "/h_m_/r_gr___i_n-t__t_"          },
+         { "${HOME:s/[esO]/_/g}",        "/hom_/r_gr___ion-t__t_"          },
+         { "${HOME:s/[esO]/_/gi}",       "/h_m_/r_gr___i_n-t__t_"          },
+         { "${OSTYPE:s/^[re]/_/g}",      "_egression-os"                   },
+         { "${EMPTY:s/^[re]/_/g}",       ""                                },
+         { "${HOME:s/.*/heinz/}",        "heinz"                           },
+         { "${HOME:s/e/bla/t}",          "/hombla/regression-tests"        },
+         { "${HOME:s/E/bla/t}",          "/home/regression-tests"          },
+         { "${HOME:s/E/bla/ti}",         "/hombla/regression-tests"        },
+         { "${HOME:s/E/bla/tig}",        "/hombla/rblagrblassion-tblasts"  },
+         { "${HOME:o1-5}",               "home/"                           },
+         { "${HOME:o1,5}",               "home"                            },
+         { "${HOME:o5,}",                "/regression-tests"               },
+         { "${HOME:o5-}",                "/regression-tests"               },
+         { "${HOME:o7,13}",              "egress"                          },
+         { "${HOME:y/a-z/A-YZ/}",        "/HOME/REGRESSION-TESTS"          },
+         { "${HOME:y/e-g/a-c/}",         "/homa/racrassion-tasts"          },
+         { "${FOO:p/15/../l}",           "os............."                 },
+         { "${FOO:p/15/12345/l}",        "os1234512345123"                 },
+         { "${FOO:p/15/../r}",           ".............os"                 },
+         { "${FOO:p/15/12345/r}",        "1234512345123os"                 },
+         { "${FOO:p/15/../c}",           "......os......."                 },
+         { "${FOO:p/15/12345/c}",        "123451os1234512"                 }
+         };
+     /*
+         { "${HOME:s/g(res)s/x\\\\1x/g}","/homE/rEgrEssion-tEsts"          }
+         { "${HOME:s/\\x65/\\x45/g}",    "/home/regression-tests"          }
+     */
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+     size_t   i;
+ 
+     if (setenv("HOME", "/home/regression-tests", 1) != 0 ||
+         setenv("OSTYPE", "regression-os", 1) != 0 ||
+         setenv("TERM", "regression-term", 1) != 0 ||
+         setenv("FOO", "os", 1) != 0 ||
+         setenv("BAR", "type", 1) != 0 ||
+         setenv("EMPTY", "", 1) != 0)
+         {
+         printf("Failed to set the environment: %s.\n", strerror(errno));
+         return 1;
+         }
+     unsetenv("UNDEFINED");
+ 
+     for (i = 0; i < sizeof(tests) / sizeof(struct test_case); ++i)
+         {
+         rc = var_expand(tests[i].input, strlen(tests[i].input),
+                         &tmp, &tmp_len,
+                         &env_lookup, NULL,
+                         NULL, 0);
+         if (rc != VAR_OK)
+             {
+             printf("Test case #%d: var_expand() failed with return code %d.\n", i, rc);
+             return 1;
+             }
+         if (tmp_len != strlen(tests[i].expected) || tmp == NULL || memcmp(tests[i].expected, tmp, tmp_len) != 0)
+             {
+             printf("Test case #%d: Expected result '%s' but got '%s'.\n", i, tests[i].expected, tmp);
+             return 1;
+             }
+         printf("Test case #%02d: '%s' --> '%s'.\n", i, tests[i].input, tmp);
+         free(tmp);
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/expand6.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/force-expand.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,65 ----
+ #include "../internal.h"
+ 
+ int dummy(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     if (name_len != sizeof("heinz_ist_doof")-1)
+         {
+         printf("The the length of the variable name (%d) doesn't fit.\n", name_len);
+         exit(1);
+         }
+     if (memcmp(varname, "heinz_ist_doof", sizeof("heinz_ist_doof")-1) != 0)
+         {
+         printf("Callback called for unknown variable.\n");
+         exit(1);
+         }
+     return 0;                   /* say it's undefined */
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input  = "This is a $heinz_ist_doof!";
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     /* Run var_expand() with force_expand and expect failure. */
+ 
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &dummy, NULL,
+                     NULL, 1);
+     if (rc != VAR_UNDEFINED_VARIABLE)
+         {
+         printf("var_expand() should have failed with error UNDEFINED_VARIABLE, but returned %d.\n", rc);
+         return 1;
+         }
+ 
+     /* Run var_expand() without force_expand and expect input == output. */
+ 
+     rc = var_expand(input, strlen(input),
+                     &tmp, &tmp_len,
+                     &dummy, NULL,
+                     NULL, 0);
+     if (rc != VAR_OK)
+         {
+         printf("var_expand() failed with error %d.\n", rc);
+         return 1;
+         }
+ 
+     if (tmp_len != strlen(input))
+         {
+         printf("The length of the input string is not what we expected: %d != %d.\n",
+                tmp_len, strlen(input));
+         return 1;
+         }
+ 
+     if (memcmp(tmp, input, tmp_len) != 0)
+         {
+         printf("The buffer returned by var_expand() is not what we expected.\n");
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/force-expand.c 1.1 -> 1.1.1.1



ossp-pkg/var/regression-tests/offset-failure.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,68 ----
+ #include "../internal.h"
+ 
+ int env_lookup(void* context,
+           const char* varname, size_t name_len,
+           const char** data, size_t* data_len, size_t* buffer_size)
+     {
+     char tmp[256];
+ 
+     if (name_len > sizeof(tmp)-1)
+         {
+         printf("Callback can't expand variable names longer than %d characters.\n", sizeof(tmp-1));
+         exit(1);
+         }
+     memcpy(tmp, varname, name_len);
+     tmp[name_len] = '\0';
+     *data = getenv(tmp);
+     if (*data == NULL)
+         return 0;
+     *data_len = strlen(*data);
+     *buffer_size = 0;
+     return 1;
+     }
+ 
+ int main(int argc, char** argv)
+     {
+     const char* input1 = "${HOME:o88,}";
+     const char* input2 = "${HOME:o88-90}";
+     const char* input3 = "${HOME:o8-90}";
+     const char* input4 = "${HOME:o8,90}";
+     const char* input5 = "${HOME:o8,4}";
+ 
+     char*    tmp;
+     size_t   tmp_len;
+     var_rc_t rc;
+ 
+     if (setenv("HOME", "/home/regression-tests", 1) !=0)
+         {
+         printf("Failed to set the environment: %s.\n", strerror(errno));
+         return 1;
+         }
+     if ((rc = var_expand(input1, strlen(input1), &tmp, &tmp_len, &env_lookup, NULL, NULL, 0)) != VAR_OFFSET_OUT_OF_BOUNDS)
+         {
+         printf("var_expand() should have failed with VAR_OFFSET_OUT_OF_BOUNDS but returned %d.\n", rc);
+         return 1;
+         }
+     if ((rc = var_expand(input2, strlen(input2), &tmp, &tmp_len, &env_lookup, NULL, NULL, 0)) != VAR_OFFSET_OUT_OF_BOUNDS)
+         {
+         printf("var_expand() should have failed with VAR_OFFSET_OUT_OF_BOUNDS but returned %d.\n", rc);
+         return 1;
+         }
+     if ((rc = var_expand(input3, strlen(input3), &tmp, &tmp_len, &env_lookup, NULL, NULL, 0)) != VAR_RANGE_OUT_OF_BOUNDS)
+         {
+         printf("var_expand() should have failed with VAR_RANGE_OUT_OF_BOUNDS but returned %d.\n", rc);
+         return 1;
+         }
+     if ((rc = var_expand(input4, strlen(input4), &tmp, &tmp_len, &env_lookup, NULL, NULL, 0)) != VAR_RANGE_OUT_OF_BOUNDS)
+         {
+         printf("var_expand() should have failed with VAR_RANGE_OUT_OF_BOUNDS but returned %d.\n", rc);
+         return 1;
+         }
+     if ((rc = var_expand(input5, strlen(input5), &tmp, &tmp_len, &env_lookup, NULL, NULL, 0)) != VAR_OFFSET_LOGIC_ERROR)
+         {
+         printf("var_expand() should have failed with VAR_OFFSET_LOGIC_ERROR but returned %d.\n", rc);
+         return 1;
+         }
+ 
+     return 0;
+     }


ossp-pkg/var/regression-tests/offset-failure.c 1.1 -> 1.1.1.1



ossp-pkg/var/search-and-replace.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,158 ----
+ #include <sys/types.h>
+ #include <regex.h>
+ #include "internal.h"
+ 
+ int search_and_replace(tokenbuf* data, tokenbuf* search, tokenbuf* replace, tokenbuf* flags)
+     {
+     const char* p;
+     int case_insensitive = 0;
+     int global = 0;
+     int no_regex = 0;
+     int rc;
+ 
+     if (search->begin == search->end)
+         return VAR_EMPTY_SEARCH_STRING;
+ 
+     printf("Search '%s' in '%s' and replace it with '%s'.\n",
+            search->begin, data->begin, replace->begin);
+ 
+     for (p = flags->begin; p != flags->end; ++p)
+         {
+         switch (tolower(*p))
+             {
+             case 'i':
+                 case_insensitive = 1;
+                 printf("case_insensitive = 1;\n");
+                 break;
+             case 'g':
+                 global = 1;
+                 printf("global = 1;\n");
+                 break;
+             case 't':
+                 no_regex = 1;
+                 printf("no_regex = 1;\n");
+                 break;
+             default:
+                 return VAR_UNKNOWN_REPLACE_FLAG;
+             }
+         }
+ 
+     if (no_regex)
+         {
+         tokenbuf tmp;
+         init_tokenbuf(&tmp);
+ 
+         for (p = data->begin; p != data->end; )
+             {
+             if (case_insensitive)
+                 rc = strncasecmp(p, search->begin, search->end - search->begin);
+             else
+                 rc = strncmp(p, search->begin, search->end - search->begin);
+             if (rc != 0)
+                 {               /* no match, copy character */
+                 if (!append_to_tokenbuf(&tmp, p, 1))
+                     {
+                     free_tokenbuf(&tmp);
+                     return VAR_OUT_OF_MEMORY;
+                     }
+                 ++p;
+                 }
+             else
+                 {
+                 append_to_tokenbuf(&tmp, replace->begin, replace->end - replace->begin);
+                 p += search->end - search->begin;
+                 if (!global)
+                     {
+                     if (!append_to_tokenbuf(&tmp, p, data->end - p))
+                         {
+                         free_tokenbuf(&tmp);
+                         return VAR_OUT_OF_MEMORY;
+                         }
+                     break;
+                     }
+                 }
+             }
+ 
+         free_tokenbuf(data);
+         move_tokenbuf(&tmp, data);
+         }
+     else
+         {
+         tokenbuf tmp;
+         tokenbuf mydata;
+         regex_t preg;
+         regmatch_t pmatch[33];
+         int regexec_flag;
+ 
+         /* Copy the pattern and the data to our own buffer to make
+            sure they're terminated with a null byte. */
+ 
+         if (!assign_to_tokenbuf(&tmp, search->begin, search->end - search->begin))
+             return VAR_OUT_OF_MEMORY;
+         if (!assign_to_tokenbuf(&mydata, data->begin, data->end - data->begin))
+             {
+             free_tokenbuf(&tmp);
+             return VAR_OUT_OF_MEMORY;
+             }
+ 
+         /* Compile the pattern. */
+ 
+         printf("data is.................: '%s'\n", mydata.begin);
+         printf("regex search pattern is.: '%s'\n", tmp.begin);
+         printf("regex replace pattern is: '%s'\n", replace->begin);
+         rc = regcomp(&preg, tmp.begin, REG_EXTENDED | ((case_insensitive) ? REG_ICASE : 0));
+         free_tokenbuf(&tmp);
+         if (rc != 0)
+             {
+             free_tokenbuf(&mydata);
+             return VAR_INVALID_REGEX_IN_REPLACE;
+             }
+         printf("Subexpression in pattern: '%d'\n", preg.re_nsub);
+ 
+         /* Match the pattern and create the result string in the tmp
+            buffer. */
+ 
+         for (p = mydata.begin; p != mydata.end; )
+             {
+             if (p == mydata.begin || p[-1] == '\n')
+                 regexec_flag = 0;
+             else
+                 regexec_flag = REG_NOTBOL;
+             if (regexec(&preg, p, sizeof(pmatch) / sizeof(regmatch_t), pmatch, regexec_flag) == REG_NOMATCH)
+                 {
+                 printf("No match; appending remainder ('%s') to output string.\n", p);
+                 append_to_tokenbuf(&tmp, p, mydata.end - p);
+                 break;
+                 }
+             else
+                 {
+ #if 0
+                 printf("Match from offset %ld to %ld in string '%s'.\n",
+                        pmatch[0].rm_so, pmatch[0].rm_eo, p);
+ #endif
+                 if (!append_to_tokenbuf(&tmp, p, pmatch[0].rm_so) ||
+                     !append_to_tokenbuf(&tmp, replace->begin, replace->end - replace->begin))
+                     {
+                     regfree(&preg);
+                     free_tokenbuf(&tmp);
+                     free_tokenbuf(&mydata);
+                     return VAR_OUT_OF_MEMORY;
+                     }
+                 else
+                     p += pmatch[0].rm_eo;
+                 if (!global)
+                     {
+                     append_to_tokenbuf(&tmp, p, mydata.end - p);
+                     break;
+                     }
+                 }
+             }
+ 
+         regfree(&preg);
+         free_tokenbuf(data);
+         move_tokenbuf(&tmp, data);
+         free_tokenbuf(&mydata);
+         }
+ 
+     return VAR_OK;
+     }


ossp-pkg/var/search-and-replace.c 1.1 -> 1.1.1.1



ossp-pkg/var/text.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,173 ----
+ #include "internal.h"
+ 
+ int text(const char* begin, const char* end, char varinit, char escape)
+     {
+     const char* p;
+     for (p = begin; p != end && *p != varinit; ++p)
+         {
+         if (*p == escape)
+             {
+             if (p+1 == end)
+                 return VAR_INCOMPLETE_QUOTED_PAIR;
+             else
+                 ++p;
+             }
+         }
+     return p - begin;
+     }
+ 
+ int varname(const char* begin, const char* end, const char nameclass[256])
+     {
+     const char* p;
+     for (p = begin; p != end && nameclass[(int)*p]; ++p)
+         ;
+     return p - begin;
+     }
+ 
+ int number(const char* begin, const char* end)
+     {
+     const char* p;
+     for (p = begin; p != end && isdigit(*p); ++p)
+         ;
+     return p - begin;
+     }
+ 
+ int substext(const char* begin, const char* end, const var_config_t* config)
+     {
+     const char* p;
+     for (p = begin; p != end && *p != config->varinit && *p != '/'; ++p)
+         {
+         if (*p == config->escape)
+             {
+             if (p+1 == end)
+                 return VAR_INCOMPLETE_QUOTED_PAIR;
+             else
+                 ++p;
+             }
+         }
+     return p - begin;
+     }
+ 
+ int exptext(const char* begin, const char* end, const var_config_t* config)
+     {
+     const char* p;
+     for (p = begin; p != end && *p != config->varinit && *p != config->enddelim && *p != ':'; ++p)
+         {
+         if (*p == config->escape)
+             {
+             if (p+1 == end)
+                 return VAR_INCOMPLETE_QUOTED_PAIR;
+             else
+                 ++p;
+             }
+         }
+     return p - begin;
+     }
+ 
+ int exptext_or_variable(const char* begin, const char* end, const var_config_t* config,
+                         const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                         int force_expand, tokenbuf* result)
+     {
+     const char* p = begin;
+     tokenbuf tmp;
+     int rc;
+ 
+     init_tokenbuf(result);
+     init_tokenbuf(&tmp);
+ 
+     if (begin == end)
+         return 0;
+ 
+     do
+         {
+         rc = exptext(p, end, config);
+         if (rc < 0)
+             goto error_return;
+         else if (rc > 0)
+             {
+             if (!append_to_tokenbuf(result, p, rc))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             }
+ 
+         rc = variable(p, end, config, nameclass, lookup, lookup_context, force_expand, &tmp);
+         if (rc < 0)
+             goto error_return;
+         else if (rc > 0)
+             {
+             p += rc;
+             if (!append_to_tokenbuf(result, tmp.begin, tmp.end - tmp.begin))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             }
+         }
+     while (rc > 0);
+ 
+     free_tokenbuf(&tmp);
+     return p - begin;
+ 
+   error_return:
+     free_tokenbuf(&tmp);
+     free_tokenbuf(result);
+     return rc;
+     }
+ 
+ int substext_or_variable(const char* begin, const char* end, const var_config_t* config,
+                          const char nameclass[256], var_cb_t lookup, void* lookup_context,
+                          int force_expand, tokenbuf* result)
+     {
+     const char* p = begin;
+     tokenbuf tmp;
+     int rc;
+ 
+     init_tokenbuf(result);
+     init_tokenbuf(&tmp);
+ 
+     if (begin == end)
+         return 0;
+ 
+     do
+         {
+         rc = substext(p, end, config);
+         if (rc < 0)
+             goto error_return;
+         else if (rc > 0)
+             {
+             if (!append_to_tokenbuf(result, p, rc))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             else
+                 p += rc;
+             }
+ 
+         rc = variable(p, end, config, nameclass, lookup, lookup_context, force_expand, &tmp);
+         if (rc < 0)
+             goto error_return;
+         else if (rc > 0)
+             {
+             p += rc;
+             if (!append_to_tokenbuf(result, tmp.begin, tmp.end - tmp.begin))
+                 {
+                 rc = VAR_OUT_OF_MEMORY;
+                 goto error_return;
+                 }
+             }
+         }
+     while (rc > 0);
+ 
+     free_tokenbuf(&tmp);
+     return p - begin;
+ 
+   error_return:
+     free_tokenbuf(&tmp);
+     free_tokenbuf(result);
+     return rc;
+     }


ossp-pkg/var/text.c 1.1 -> 1.1.1.1



ossp-pkg/var/tokenbuf.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,115 ----
+ #include "internal.h"
+ 
+ #define VAR_INITIAL_BUFFER_SIZE 1
+ 
+ void init_tokenbuf(tokenbuf* buf)
+     {
+     buf->begin = buf->end = NULL;
+     buf->buffer_size = 0;
+     }
+ 
+ void move_tokenbuf(tokenbuf* src, tokenbuf* dst)
+     {
+     dst->begin = src->begin;
+     dst->end = src->end;
+     dst->buffer_size = src->buffer_size;
+     init_tokenbuf(src);
+     }
+ 
+ int assign_to_tokenbuf(tokenbuf* buf, const char* data, size_t len)
+     {
+     char* p = malloc(len+1);
+     if (p)
+         {
+         memcpy(p, data, len);
+         buf->begin       = p;
+         buf->end         = p + len;
+         buf->buffer_size = len + 1;
+         *((char*)(buf->end)) = '\0';
+         return 1;
+         }
+     else
+         return 0;
+     }
+ 
+ int append_to_tokenbuf(tokenbuf* output, const char* data, size_t len)
+     {
+     char*  new_buffer;
+     size_t new_size;
+ 
+     /* Is the tokenbuffer initialized at all? If not, allocate a
+        standard-sized buffer to begin with. */
+ 
+     if (output->begin == NULL)
+         {
+         if ((output->begin = output->end = malloc(VAR_INITIAL_BUFFER_SIZE)) == NULL)
+             return 0;
+         else
+             output->buffer_size = VAR_INITIAL_BUFFER_SIZE;
+         }
+ 
+     /* Does the token contain text, but no buffer has been allocated
+        yet? */
+ 
+     if (output->buffer_size == 0)
+         {
+         /* Check whether data borders to output. If, we can append
+            simly by increasing the end pointer. */
+ 
+         if (output->end == data)
+             {
+             output->end += len;
+             return 1;
+             }
+ 
+         /* OK, so copy the contents of output into an allocated buffer
+            so that we can append that way. */
+ 
+         else
+             {
+             char* tmp = malloc(output->end - output->begin + len + 1);
+             if (!tmp)
+                 return 0;
+             memcpy(tmp, output->begin, output->end - output->begin);
+             output->buffer_size = output->end - output->begin;
+             output->begin = tmp;
+             output->end   = tmp + output->buffer_size;
+             output->buffer_size += len + 1;
+             }
+         }
+ 
+     /* Does the token fit into the current buffer? If not, realloc a
+        larger buffer that fits. */
+ 
+     if ((output->buffer_size - (output->end - output->begin)) <= len)
+         {
+         new_size = output->buffer_size;
+         do
+             {
+             new_size *= 2;
+             }
+         while ((new_size - (output->end - output->begin)) <= len);
+         new_buffer = realloc((char*)output->begin, new_size);
+         if (new_buffer == NULL)
+             return 0;
+         output->end = new_buffer + (output->end - output->begin);
+         output->begin = new_buffer;
+         output->buffer_size = new_size;
+         }
+ 
+     /* Append the data at the end of the current buffer. */
+ 
+     memcpy((char*)output->end, data, len);
+     output->end += len;
+     *((char*)output->end) = '\0';
+     return 1;
+     }
+ 
+ 
+ void free_tokenbuf(tokenbuf* buf)
+     {
+     if (buf->begin != NULL && buf->buffer_size > 0)
+         free((char*)buf->begin);
+     buf->begin = buf->end = NULL;
+     buf->buffer_size = 0;
+     }


ossp-pkg/var/tokenbuf.c 1.1 -> 1.1.1.1



ossp-pkg/var/transpose.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,97 ----
+ #include <sys/types.h>
+ #include <regex.h>
+ #include "internal.h"
+ 
+ static int expand_class_description(tokenbuf* src, tokenbuf* dst)
+     {
+     unsigned char c, d;
+     const char* p = src->begin;
+     while(p != src->end)
+         {
+         if ((src->end - p) >= 3 && p[1] == '-')
+             {
+             printf("Expand class.\n");
+             if (*p > p[2])
+                 return VAR_INCORRECT_TRANSPOSE_CLASS_SPEC;
+             for (c = *p, d = p[2]; c <= d; ++c)
+                 {
+                 if (!append_to_tokenbuf(dst, (char*)&c, 1))
+                     return VAR_OUT_OF_MEMORY;
+                 }
+             p += 3;
+             }
+         else
+             {
+             printf("Copy verbatim.\n");
+             if (!append_to_tokenbuf(dst, p, 1))
+                 return VAR_OUT_OF_MEMORY;
+             else
+                 ++p;
+             }
+         }
+     return VAR_OK;
+     }
+ 
+ int transpose(tokenbuf* data, tokenbuf* search, tokenbuf* replace)
+     {
+     tokenbuf srcclass, dstclass;
+     const char* p;
+     int rc;
+     size_t i;
+ 
+     init_tokenbuf(&srcclass);
+     init_tokenbuf(&dstclass);
+ 
+     if ((rc = expand_class_description(search, &srcclass)) != VAR_OK)
+         goto error_return;
+     if ((rc = expand_class_description(replace, &dstclass)) != VAR_OK)
+         goto error_return;
+ 
+     printf("Transpose from '%s' to '%s'.\n",
+            srcclass.begin, dstclass.begin);
+ 
+     if (srcclass.begin == srcclass.end)
+         {
+         rc = VAR_EMPTY_TRANSPOSE_CLASS;
+         goto error_return;
+         }
+     if ((srcclass.end - srcclass.begin) != (dstclass.end - dstclass.begin))
+         {
+         rc = VAR_TRANSPOSE_CLASSES_MISMATCH;
+         goto error_return;
+         }
+ 
+     if (data->buffer_size == 0)
+         {
+         tokenbuf tmp;
+         if (!assign_to_tokenbuf(&tmp, data->begin, data->end - data->begin))
+             {
+             rc = VAR_OUT_OF_MEMORY;
+             goto error_return;
+             }
+         move_tokenbuf(&tmp, data);
+         }
+ 
+     for (p = data->begin; p != data->end; ++p)
+         {
+         for (i = 0; i <= (srcclass.end - srcclass.begin); ++i)
+             {
+             if (*p == srcclass.begin[i])
+                 {
+                 *((char*)p) = dstclass.begin[i];
+                 break;
+                 }
+             }
+         }
+ 
+     free_tokenbuf(&srcclass);
+     free_tokenbuf(&dstclass);
+     return VAR_OK;
+ 
+   error_return:
+     free_tokenbuf(search);
+     free_tokenbuf(replace);
+     free_tokenbuf(&srcclass);
+     free_tokenbuf(&dstclass);
+     return rc;
+     }


ossp-pkg/var/transpose.c 1.1 -> 1.1.1.1



ossp-pkg/var/varexp.h -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,127 ----
+ #ifndef LIB_VARIABLE_EXPAND_H
+ #define LIB_VARIABLE_EXPAND_H
+ 
+ #include <stdlib.h>
+ 
+ /* Error codes returned by the varexp library. */
+ 
+ typedef enum
+     {
+     VAR_EMPTY_PADDING_FILL_STRING      = -32,
+     VAR_MISSING_PADDING_WIDTH          = -31,
+     VAR_MALFORMATTED_PADDING           = -30,
+     VAR_INCORRECT_TRANSPOSE_CLASS_SPEC = -29,
+     VAR_EMPTY_TRANSPOSE_CLASS          = -28,
+     VAR_TRANSPOSE_CLASSES_MISMATCH     = -27,
+     VAR_MALFORMATTED_TRANSPOSE         = -26,
+     VAR_OFFSET_LOGIC_ERROR             = -25,
+     VAR_OFFSET_OUT_OF_BOUNDS           = -24,
+     VAR_RANGE_OUT_OF_BOUNDS            = -23,
+     VAR_INVALID_OFFSET_DELIMITER       = -22,
+     VAR_MISSING_START_OFFSET           = -21,
+     VAR_EMPTY_SEARCH_STRING            = -20,
+     VAR_MISSING_PARAMETER_IN_COMMAND   = -19,
+     VAR_INVALID_REGEX_IN_REPLACE       = -18,
+     VAR_UNKNOWN_REPLACE_FLAG           = -17,
+     VAR_MALFORMATTED_REPLACE           = -16,
+     VAR_UNKNOWN_COMMAND_CHAR           = -14,
+     VAR_INPUT_ISNT_TEXT_NOR_VARIABLE   = -13,
+     VAR_UNDEFINED_VARIABLE             = -12,
+     VAR_INCOMPLETE_VARIABLE_SPEC       = -11,
+     VAR_OUT_OF_MEMORY                  = -10,
+     VAR_INVALID_CONFIGURATION          = -9,
+     VAR_INCORRECT_CLASS_SPEC           = -8,
+     VAR_INCOMPLETE_GROUPED_HEX         = -7,
+     VAR_INCOMPLETE_OCTAL               = -6,
+     VAR_INVALID_OCTAL                  = -5,
+     VAR_OCTAL_TOO_LARGE                = -4,
+     VAR_INVALID_HEX                    = -3,
+     VAR_INCOMPLETE_HEX                 = -2,
+     VAR_INCOMPLETE_NAMED_CHARACTER     = -1,
+     VAR_INCOMPLETE_QUOTED_PAIR         = -1,
+     VAR_OK                             = 0
+     }
+ var_rc_t;
+ 
+ /*
+    Expand the following named characters to their binary
+    representation:
+ 
+        \t          tab
+        \n          newline
+        \r          return
+        \033        octal char
+        \x1B        hex char
+        \x{263a}    wide hex char
+ 
+   Any other character quoted by a backslash is copied verbatim.
+ */
+ 
+ var_rc_t expand_named_characters(const char* src, size_t len, char* dst);
+ 
+ /*
+    The callback will be called by variable_expand(), providing the
+    following parameterns:
+ 
+         context         - passed through from variable_expand()'s
+                           parameters
+         varname         - pointer to the name of the variable to
+                           expand
+         name_len        - length of the string starting at varname
+         data            - location, where the callback should store
+                           the pointer to the contents of the looked-up
+                           variable
+         data_len        - location, where the callback should store
+                           the length of the data
+         malloced_buffer - location, where the callback should store
+                           either TRUE or FALSE, telling the framework
+                           whether the buffer must be free(3)ed.
+ 
+    The return code is interpreted as follows:
+        >0               - OK
+         0               - undefined variable
+        <0 - error
+ */
+ 
+ typedef int (*var_cb_t)(void* context,
+                         const char* varname, size_t name_len,
+                         const char** data, size_t* data_len, size_t* buffer_size);
+ 
+ /*
+    This structure configures the parser's specials. I think, the fields
+    are pretty self-explanatory. The only one worth mentioning is
+    force_expand, which is a boolean. If set to TRUE, variable_expand()
+    will fail with an error if the lookup callback returns "undefined
+    variable". If set to FALSE, variable_expand() will copy the
+    expression that failed verbatimly to the output so that another pass
+    may expand it.
+ 
+    The comments after each field show the default configuration.
+ */
+ 
+ typedef struct
+     {
+     char  varinit;               /* '$' */
+     char  startdelim;            /* '{' */
+     char  enddelim;              /* '}' */
+     char  escape;                /* '\' */
+     char* namechars;             /* 'a-zA-Z0-9_' */
+     }
+ var_config_t;
+ extern const var_config_t var_config_default;
+ 
+ /*
+    variable_expand() will parse the contents of input for variable
+    expressions and expand them using the provided lookup callback. The
+    pointer to the resulting buffer is stored in result, its length in
+    result_len. The buffer is always terminated by a '\0' byte, which is
+    not included in the result_len count. The buffer must be free(3)ed
+    by the caller.
+ */
+ 
+ var_rc_t var_expand(const char* input, size_t input_len,
+                     char** result, size_t* result_len,
+                     var_cb_t lookup, void* lookup_context,
+                     const var_config_t* config, int force_expand);
+ 
+ #endif /* !defined(LIB_VARIABLE_EXPAND_H) */


ossp-pkg/var/varexp.h 1.1 -> 1.1.1.1



ossp-pkg/var/variable.c -> 1.1

*** /dev/null    Fri Apr 19 06:37:11 2024
--- -    Fri Apr 19 06:39:52 2024
***************
*** 0 ****
--- 1,63 ----
+ #include "internal.h"
+ 
+ int variable(const char* begin, const char* end, const var_config_t* config,
+              const char nameclass[256], var_cb_t lookup, void* lookup_context,
+              int force_expand, tokenbuf* result)
+     {
+     const char* p = begin;
+     const char* data;
+     size_t len, buffer_size;
+     int rc, rc2;
+ 
+     /* Clear the result tokenbuf to make sure we're in a defined
+        state. */
+ 
+     init_tokenbuf(result);
+ 
+     /* Expect VARINIT. */
+ 
+     if (p == end || *p != config->varinit)
+         return 0;
+ 
+     if (++p == end)
+         return VAR_INCOMPLETE_VARIABLE_SPEC;
+ 
+     /* Try to read the variable name. If that fails, we're parsing a
+        complex expression. */
+ 
+     rc = varname(p, end, nameclass);
+     if (rc < 0)
+         return rc;
+     else if (rc > 0)
+         {
+         rc2 = (*lookup)(lookup_context, p, rc, &data, &len, &buffer_size);
+         if (rc2 < 0)
+             return rc2;
+         else if (rc2 == 0)
+             {
+             if (force_expand)
+                 return VAR_UNDEFINED_VARIABLE;
+             else
+                 {
+                 result->begin       = begin;
+                 result->end         = begin + 1 + rc;
+                 result->buffer_size = 0;
+                 return 1 + rc;
+                 }
+             }
+         else
+             {
+             result->begin       = data;
+             result->end         = data + len;
+             result->buffer_size = buffer_size;
+             return 1 + rc;
+             }
+         }
+ 
+     /* OK, we're dealing with a complex expression here. */
+ 
+     rc = expression(p, end, config, nameclass, lookup, lookup_context, force_expand, result);
+     if (rc > 0)
+         ++rc;
+     return rc;
+     }


ossp-pkg/var/variable.c 1.1 -> 1.1.1.1


CVSTrac 2.0.1