aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorØyvind Harboe <oyvind.harboe@zylin.com>2010-02-21 21:27:23 +0100
committerØyvind Harboe <oyvind.harboe@zylin.com>2010-02-21 21:27:23 +0100
commit4aa0c56d48fe3e4f04ed33d1b5786398db56d43d (patch)
tree3b4f6b557bb133bae08ba72c4099b1916477b091
parentd93957f71062edb53b34e3033b512e942de458c4 (diff)
downloadjimtcl-4aa0c56d48fe3e4f04ed33d1b5786398db56d43d.zip
jimtcl-4aa0c56d48fe3e4f04ed33d1b5786398db56d43d.tar.gz
jimtcl-4aa0c56d48fe3e4f04ed33d1b5786398db56d43d.tar.bz2
dos2unix: convert to unix line endings
To ease rebasing Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
-rw-r--r--jim-array-1.0.tcl208
-rw-r--r--jim-glob-1.0.tcl266
-rw-r--r--jim-readdir.c240
-rw-r--r--jim-regexp.c964
4 files changed, 839 insertions, 839 deletions
diff --git a/jim-array-1.0.tcl b/jim-array-1.0.tcl
index 38cda0f..2c25b23 100644
--- a/jim-array-1.0.tcl
+++ b/jim-array-1.0.tcl
@@ -1,104 +1,104 @@
-# (c) 2008 Steve Bennett <steveb@workware.net.au>
-#
-# Implements a Tcl-compatible array command based on dict
-#
-# The FreeBSD license
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials
-# provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation
-# are those of the authors and should not be interpreted as representing
-# official policies, either expressed or implied, of the Jim Tcl Project.
-
-package provide array 1.0
-
-proc array {subcmd arrayname args} {
- # $name is the name of the array in the caller's context
- upvar $arrayname name
-
- if {$subcmd eq "exists"} {
- return [info exists name]
- }
-
- if {![info exists name]} {
- set name [dict create]
- }
-
- switch $subcmd {
- set {
- # The argument should be a list, but we also
- # support name value pairs
- if {[llength $args] == 1} {
- set args [lindex $args 0]
- }
- foreach {key value} $args {
- dict set name $key $value
- }
- return $name
- }
- size {
- return [/ [llength $name] 2]
- }
- }
-
- # The remaining options take a pattern
- if {[llength $args] > 0} {
- set pattern [lindex $args 0]
- } else {
- set pattern *
- }
-
- switch $subcmd {
- names {
- set keys {}
- foreach {key value} $name {
- if {[string match $pattern $key]} {
- lappend keys $key
- }
- }
- return $keys
- }
- get {
- set list {}
- foreach {key value} $name {
- if {[string match $pattern $key]} {
- lappend list $key $value
- }
- }
- return $list
- }
- unset {
- foreach {key value} $name {
- if {[string match $pattern $key]} {
- dict unset name $key
- }
- }
- return
- }
- }
-
- # Tcl-compatible error message
- error "bad option \"$subcmd\": must be exists, get, names, set, size, or unset"
-}
+# (c) 2008 Steve Bennett <steveb@workware.net.au>
+#
+# Implements a Tcl-compatible array command based on dict
+#
+# The FreeBSD license
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and documentation
+# are those of the authors and should not be interpreted as representing
+# official policies, either expressed or implied, of the Jim Tcl Project.
+
+package provide array 1.0
+
+proc array {subcmd arrayname args} {
+ # $name is the name of the array in the caller's context
+ upvar $arrayname name
+
+ if {$subcmd eq "exists"} {
+ return [info exists name]
+ }
+
+ if {![info exists name]} {
+ set name [dict create]
+ }
+
+ switch $subcmd {
+ set {
+ # The argument should be a list, but we also
+ # support name value pairs
+ if {[llength $args] == 1} {
+ set args [lindex $args 0]
+ }
+ foreach {key value} $args {
+ dict set name $key $value
+ }
+ return $name
+ }
+ size {
+ return [/ [llength $name] 2]
+ }
+ }
+
+ # The remaining options take a pattern
+ if {[llength $args] > 0} {
+ set pattern [lindex $args 0]
+ } else {
+ set pattern *
+ }
+
+ switch $subcmd {
+ names {
+ set keys {}
+ foreach {key value} $name {
+ if {[string match $pattern $key]} {
+ lappend keys $key
+ }
+ }
+ return $keys
+ }
+ get {
+ set list {}
+ foreach {key value} $name {
+ if {[string match $pattern $key]} {
+ lappend list $key $value
+ }
+ }
+ return $list
+ }
+ unset {
+ foreach {key value} $name {
+ if {[string match $pattern $key]} {
+ dict unset name $key
+ }
+ }
+ return
+ }
+ }
+
+ # Tcl-compatible error message
+ error "bad option \"$subcmd\": must be exists, get, names, set, size, or unset"
+}
diff --git a/jim-glob-1.0.tcl b/jim-glob-1.0.tcl
index 9529df0..853c464 100644
--- a/jim-glob-1.0.tcl
+++ b/jim-glob-1.0.tcl
@@ -1,133 +1,133 @@
-# (c) 2008 Steve Bennett <steveb@workware.net.au>
-#
-# Implements a Tcl-compatible glob command based on readdir
-#
-# The FreeBSD license
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following
-# disclaimer in the documentation and/or other materials
-# provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation
-# are those of the authors and should not be interpreted as representing
-# official policies, either expressed or implied, of the Jim Tcl Project.
-
-package provide glob 1.0
-package require readdir 1.0
-
-# If $dir is a directory, return a list of all entries
-# it contains which match $pattern
-#
-proc _glob_readdir_pattern {dir pattern} {
- set result {}
-
- # readdir doesn't return . or .., so simulate it here
- if {$pattern eq "." || $pattern eq ".."} {
- return $pattern
- }
- # Use -nocomplain here to return nothing if $dir is not a directory
- foreach name [readdir -nocomplain $dir] {
- if {[string match $pattern $name]} {
- lappend result $name
- }
- }
-
- return $result
-}
-
-# glob entries in directory $dir and pattern $rem
-#
-proc _glob_do {dir rem} {
- # Take one level from rem
- # Avoid regexp here
- set i [string first / $rem]
- if {$i < 0} {
- set pattern $rem
- set rempattern ""
- } else {
- set j $i
- incr j
- incr i -1
- set pattern [string range $rem 0 $i]
- set rempattern [string range $rem $j end]
- }
-
- # Determine the appropriate separator and globbing dir
- set sep /
- set globdir $dir
- if {[string match "*/" $dir]} {
- set sep ""
- } elseif {$dir eq ""} {
- set globdir .
- set sep ""
- }
-
- set result {}
-
- # Use readdir and select all files which match the pattern
- foreach f [_glob_readdir_pattern $globdir $pattern] {
- if {$rempattern eq ""} {
- # This is a terminal entry, so add it
- lappend result $dir$sep$f
- } else {
- # Expany any entries at this level and add them
- lappend result {expand}[_glob_do $dir$sep$f $rempattern]
- }
- }
- return $result
-}
-
-# Implements the Tcl glob command
-#
-# Usage: glob ?-nocomplain? pattern ...
-#
-# Patterns use string match pattern matching for each
-# directory level.
-#
-# e.g. glob te[a-e]*/*.tcl
-#
-proc glob {args} {
- set nocomplain 0
-
- if {[lindex $args 0] eq "-nocomplain"} {
- set nocomplain 1
- set args [lrange $args 1 end]
- }
-
- set result {}
- foreach pattern $args {
- if {$pattern eq "/"} {
- lappend result /
- } elseif {[string match "/*" $pattern]} {
- lappend result {expand}[_glob_do / [string range $pattern 1 end]]
- } else {
- lappend result {expand}[_glob_do "" $pattern]
- }
- }
-
- if {$nocomplain == 0 && [llength $result] == 0} {
- error "no files matched glob patterns"
- }
-
- return $result
-}
+# (c) 2008 Steve Bennett <steveb@workware.net.au>
+#
+# Implements a Tcl-compatible glob command based on readdir
+#
+# The FreeBSD license
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and documentation
+# are those of the authors and should not be interpreted as representing
+# official policies, either expressed or implied, of the Jim Tcl Project.
+
+package provide glob 1.0
+package require readdir 1.0
+
+# If $dir is a directory, return a list of all entries
+# it contains which match $pattern
+#
+proc _glob_readdir_pattern {dir pattern} {
+ set result {}
+
+ # readdir doesn't return . or .., so simulate it here
+ if {$pattern eq "." || $pattern eq ".."} {
+ return $pattern
+ }
+ # Use -nocomplain here to return nothing if $dir is not a directory
+ foreach name [readdir -nocomplain $dir] {
+ if {[string match $pattern $name]} {
+ lappend result $name
+ }
+ }
+
+ return $result
+}
+
+# glob entries in directory $dir and pattern $rem
+#
+proc _glob_do {dir rem} {
+ # Take one level from rem
+ # Avoid regexp here
+ set i [string first / $rem]
+ if {$i < 0} {
+ set pattern $rem
+ set rempattern ""
+ } else {
+ set j $i
+ incr j
+ incr i -1
+ set pattern [string range $rem 0 $i]
+ set rempattern [string range $rem $j end]
+ }
+
+ # Determine the appropriate separator and globbing dir
+ set sep /
+ set globdir $dir
+ if {[string match "*/" $dir]} {
+ set sep ""
+ } elseif {$dir eq ""} {
+ set globdir .
+ set sep ""
+ }
+
+ set result {}
+
+ # Use readdir and select all files which match the pattern
+ foreach f [_glob_readdir_pattern $globdir $pattern] {
+ if {$rempattern eq ""} {
+ # This is a terminal entry, so add it
+ lappend result $dir$sep$f
+ } else {
+ # Expany any entries at this level and add them
+ lappend result {expand}[_glob_do $dir$sep$f $rempattern]
+ }
+ }
+ return $result
+}
+
+# Implements the Tcl glob command
+#
+# Usage: glob ?-nocomplain? pattern ...
+#
+# Patterns use string match pattern matching for each
+# directory level.
+#
+# e.g. glob te[a-e]*/*.tcl
+#
+proc glob {args} {
+ set nocomplain 0
+
+ if {[lindex $args 0] eq "-nocomplain"} {
+ set nocomplain 1
+ set args [lrange $args 1 end]
+ }
+
+ set result {}
+ foreach pattern $args {
+ if {$pattern eq "/"} {
+ lappend result /
+ } elseif {[string match "/*" $pattern]} {
+ lappend result {expand}[_glob_do / [string range $pattern 1 end]]
+ } else {
+ lappend result {expand}[_glob_do "" $pattern]
+ }
+ }
+
+ if {$nocomplain == 0 && [llength $result] == 0} {
+ error "no files matched glob patterns"
+ }
+
+ return $result
+}
diff --git a/jim-readdir.c b/jim-readdir.c
index 9942167..8b4d3ba 100644
--- a/jim-readdir.c
+++ b/jim-readdir.c
@@ -1,120 +1,120 @@
-/*
- * Copyright (c) 2008 Steve Bennett <steveb@worware.net.au>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on original work by:
- *-----------------------------------------------------------------------------
- * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies. Karl Lehenbauer and
- * Mark Diekhans make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *-----------------------------------------------------------------------------
- *
- * Tcl readdir command.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <dirent.h>
-
-#define JIM_EXTENSION
-#include "jim.h"
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Jim_ReaddirCmd --
- * Implements the rename TCL command:
- * readdir ?-nocomplain? dirPath
- *
- * Results:
- * Standard TCL result.
- *-----------------------------------------------------------------------------
- */
-int
-Jim_ReaddirCmd (Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- const char *dirPath;
- DIR *dirPtr;
- struct dirent *entryPtr;
- int nocomplain = 0;
-
- if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) {
- nocomplain = 1;
- }
- if (argc != 2 && !nocomplain) {
- Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath");
- return JIM_ERR;
- }
-
- dirPath = Jim_GetString(argv[1 + nocomplain], NULL);
-
- dirPtr = opendir (dirPath);
- if (dirPtr == NULL) {
- if (nocomplain) {
- return JIM_OK;
- }
- Jim_SetResultString(interp, strerror(errno), -1);
- return JIM_ERR;
- }
- Jim_SetResultString(interp, strerror(errno), -1);
-
- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
-
- while ((entryPtr = readdir (dirPtr)) != NULL) {
- if (entryPtr->d_name [0] == '.') {
- if (entryPtr->d_name [1] == '\0') {
- continue;
- }
- if ((entryPtr->d_name [1] == '.') &&
- (entryPtr->d_name [2] == '\0'))
- continue;
- }
- Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, entryPtr->d_name, -1));
- }
- closedir (dirPtr);
-
- return JIM_OK;
-}
-
-int Jim_OnLoad(Jim_Interp *interp)
-{
- Jim_InitExtension(interp);
- if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG) != JIM_OK) {
- return JIM_ERR;
- }
- Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
- return JIM_OK;
-}
+/*
+ * Copyright (c) 2008 Steve Bennett <steveb@worware.net.au>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
+ *
+ * Based on original work by:
+ *-----------------------------------------------------------------------------
+ * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies. Karl Lehenbauer and
+ * Mark Diekhans make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *-----------------------------------------------------------------------------
+ *
+ * Tcl readdir command.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
+#define JIM_EXTENSION
+#include "jim.h"
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Jim_ReaddirCmd --
+ * Implements the rename TCL command:
+ * readdir ?-nocomplain? dirPath
+ *
+ * Results:
+ * Standard TCL result.
+ *-----------------------------------------------------------------------------
+ */
+int
+Jim_ReaddirCmd (Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ const char *dirPath;
+ DIR *dirPtr;
+ struct dirent *entryPtr;
+ int nocomplain = 0;
+
+ if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) {
+ nocomplain = 1;
+ }
+ if (argc != 2 && !nocomplain) {
+ Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath");
+ return JIM_ERR;
+ }
+
+ dirPath = Jim_GetString(argv[1 + nocomplain], NULL);
+
+ dirPtr = opendir (dirPath);
+ if (dirPtr == NULL) {
+ if (nocomplain) {
+ return JIM_OK;
+ }
+ Jim_SetResultString(interp, strerror(errno), -1);
+ return JIM_ERR;
+ }
+ Jim_SetResultString(interp, strerror(errno), -1);
+
+ Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+
+ while ((entryPtr = readdir (dirPtr)) != NULL) {
+ if (entryPtr->d_name [0] == '.') {
+ if (entryPtr->d_name [1] == '\0') {
+ continue;
+ }
+ if ((entryPtr->d_name [1] == '.') &&
+ (entryPtr->d_name [2] == '\0'))
+ continue;
+ }
+ Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, entryPtr->d_name, -1));
+ }
+ closedir (dirPtr);
+
+ return JIM_OK;
+}
+
+int Jim_OnLoad(Jim_Interp *interp)
+{
+ Jim_InitExtension(interp);
+ if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+ Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
+ return JIM_OK;
+}
diff --git a/jim-regexp.c b/jim-regexp.c
index de2cbb8..68e9988 100644
--- a/jim-regexp.c
+++ b/jim-regexp.c
@@ -1,482 +1,482 @@
-/*
- * Copyright (c) 2008 Steve Bennett <steveb@workware.net.au>
- *
- * Implements the regexp and regsub commands for Jim
- *
- * Uses C library regcomp()/regexec() for the matching.
- *
- * The FreeBSD license
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies, either expressed or implied, of the Jim Tcl Project.
- *
- * Based on code originally from Tcl 6.7:
- *
- * Copyright 1987-1991 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
-#include <regex.h>
-#include <string.h>
-
-#define JIM_EXTENSION
-#include "jim.h"
-
-/* REVISIT: Would be useful in jim.h */
-static void Jim_SetIntResult(Jim_Interp *interp, jim_wide wide)
-{
- Jim_SetResult(interp, Jim_NewIntObj(interp, wide));
-}
-
-/**
- * REVISIT: Should cache a number of compiled regexps for performance reasons.
- */
-static regex_t *
-compile_regexp(Jim_Interp *interp, const char *pattern, int flags)
-{
- int ret;
-
- regex_t *result = (regex_t *)Jim_Alloc(sizeof(*result));
-
- if ((ret = regcomp(result, pattern, REG_EXTENDED | flags)) != 0) {
- char buf[100];
- regerror(ret, result, buf, sizeof(buf));
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "couldn't compile regular expression pattern: ", buf, NULL);
- Jim_Free(result);
- return NULL;
- }
- return result;
-}
-
-int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- int opt_indices = 0;
- int opt_all = 0;
- int opt_inline = 0;
- regex_t *regex;
- int match, i, j;
- long offset = 0;
- regmatch_t *pmatch = NULL;
- int source_len;
- int result = JIM_OK;
- const char *pattern;
- const char *source_str;
- int num_matches = 0;
- int num_vars;
- Jim_Obj *resultListObj = NULL;
- int regcomp_flags = 0;
-
- if (argc < 3) {
- wrongNumArgs:
- Jim_WrongNumArgs(interp, 1, argv, "?-nocase? ?-line? ?-indices? ?-start offset? ?-all? ?-inline? exp string ?matchVar? ?subMatchVar ...?");
- return JIM_ERR;
- }
-
- for (i = 1; i < argc; i++) {
- if (Jim_CompareStringImmediate(interp, argv[i], "-indices")) {
- opt_indices = 1;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-nocase")) {
- regcomp_flags |= REG_ICASE;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-line")) {
- regcomp_flags |= REG_NEWLINE;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-all")) {
- opt_all = 1;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-inline")) {
- opt_inline = 1;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-start")) {
- if (++i == argc) {
- goto wrongNumArgs;
- }
- if (Jim_GetLong(interp, argv[i], &offset) != JIM_OK) {
- return JIM_ERR;
- }
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "--")) {
- i++;
- break;
- }
- else {
- const char *opt = Jim_GetString(argv[i], NULL);
- if (*opt == '-') {
- /* Bad option */
- goto wrongNumArgs;
- }
- break;
- }
- }
- if (argc - i < 2) {
- goto wrongNumArgs;
- }
-
- pattern = Jim_GetString(argv[i], NULL);
- regex = compile_regexp(interp, pattern, regcomp_flags);
- if (regex == NULL) {
- return JIM_ERR;
- }
-
- source_str = Jim_GetString(argv[i + 1], &source_len);
-
- num_vars = argc - i - 2;
-
- if (opt_inline) {
- if (num_vars) {
- Jim_SetResultString(interp, "regexp match variables not allowed when using -inline", -1);
- result = JIM_ERR;
- goto done;
- }
- /* REVISIT: Ugly! */
- num_vars = 100;
- }
-
- pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch));
-
- /* If an offset has been specified, adjust for that now.
- * If it points past the end of the string, point to the terminating null
- */
- if (offset) {
- if (offset > source_len) {
- source_str += source_len;
- } else if (offset > 0) {
- source_str += offset;
- }
- }
-
- if (opt_inline) {
- resultListObj = Jim_NewListObj(interp, NULL, 0);
- }
-
- next_match:
- match = regexec(regex, source_str, num_vars + 1, pmatch, 0);
- if (match >= REG_BADPAT) {
- char buf[100];
- regerror(match, regex, buf, sizeof(buf));
- Jim_SetResultString(interp, "", 0);
- Jim_AppendStrings(interp, Jim_GetResult(interp), "error while matching pattern: ", buf, NULL);
- result = JIM_ERR;
- goto done;
- }
-
- if (match == REG_NOMATCH) {
- goto done;
- }
-
- num_matches++;
-
- if (opt_all && !opt_inline) {
- /* Just count the number of matches, so skip the substitution h*/
- goto try_next_match;
- }
-
- /*
- * If additional variable names have been specified, return
- * index information in those variables.
- */
-
- //fprintf(stderr, "source_str=%s, [0].rm_eo=%d\n", source_str, pmatch[0].rm_eo);
-
- j = 0;
- for (i += 2; opt_inline ? pmatch[j].rm_so != -1 : i < argc; i++, j++) {
- Jim_Obj *resultObj;
-
- if (opt_indices) {
- resultObj = Jim_NewListObj(interp, NULL, 0);
- }
- else {
- resultObj = Jim_NewStringObj(interp, "", 0);
- }
-
- if (pmatch[j].rm_so == -1) {
- if (opt_indices) {
- Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
- Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
- }
- } else {
- int len = pmatch[j].rm_eo - pmatch[j].rm_so;
- if (opt_indices) {
- Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + pmatch[j].rm_so));
- Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + pmatch[j].rm_so + len - 1));
- } else {
- Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len);
- }
- }
-
- if (opt_inline) {
- Jim_ListAppendElement(interp, resultListObj, resultObj);
- }
- else {
- /* And now set the result variable */
- result = Jim_SetVariable(interp, argv[i], resultObj);
-
- if (result != JIM_OK) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "couldn't set variable \"", Jim_GetString(argv[i], NULL), "\"", NULL);
- Jim_FreeObj(interp, resultObj);
- break;
- }
- }
- }
-
- try_next_match:
- if (opt_all && pattern[0] != '^' && *source_str) {
- if (pmatch[0].rm_eo) {
- source_str += pmatch[0].rm_eo;
- }
- else {
- source_str++;
- }
- if (*source_str) {
- goto next_match;
- }
- }
-
- done:
- if (result == JIM_OK) {
- if (opt_inline) {
- Jim_SetResult(interp, resultListObj);
- }
- else {
- Jim_SetIntResult(interp, num_matches);
- }
- }
-
- Jim_Free(pmatch);
- regfree(regex);
- Jim_Free(regex);
- return result;
-}
-
-#define MAX_SUB_MATCHES 10
-
-int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- int regcomp_flags = 0;
- int opt_all = 0;
- long offset = 0;
- regex_t *regex;
- const char *p;
- int result = JIM_ERR;
- regmatch_t pmatch[MAX_SUB_MATCHES + 1];
- int num_matches = 0;
-
- int i;
- Jim_Obj *varname;
- Jim_Obj *resultObj;
- const char *source_str;
- int source_len;
- const char *replace_str;
- const char *pattern;
-
- if (argc < 5) {
- wrongNumArgs:
- Jim_WrongNumArgs(interp, 1, argv, "?-nocase? ?-all? exp string subSpec varName");
- return JIM_ERR;
- }
-
- for (i = 1; i < argc; i++) {
- if (Jim_CompareStringImmediate(interp, argv[i], "-nocase")) {
- regcomp_flags |= REG_ICASE;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-line")) {
- regcomp_flags |= REG_NEWLINE;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-all")) {
- opt_all = 1;
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "-start")) {
- if (++i == argc) {
- goto wrongNumArgs;
- }
- if (Jim_GetLong(interp, argv[i], &offset) != JIM_OK) {
- return JIM_ERR;
- }
- }
- else if (Jim_CompareStringImmediate(interp, argv[i], "--")) {
- i++;
- break;
- }
- else {
- const char *opt = Jim_GetString(argv[i], NULL);
- if (*opt == '-') {
- /* Bad option */
- goto wrongNumArgs;
- }
- break;
- }
- }
- if (argc - i != 4) {
- goto wrongNumArgs;
- }
-
- pattern = Jim_GetString(argv[i], NULL);
- regex = compile_regexp(interp, pattern, regcomp_flags);
- if (regex == NULL) {
- return JIM_ERR;
- }
-
- source_str = Jim_GetString(argv[i + 1], &source_len);
- replace_str = Jim_GetString(argv[i + 2], NULL);
- varname = argv[i + 3];
-
- /* Create the result string */
- resultObj = Jim_NewStringObj(interp, "", 0);
-
- /* If an offset has been specified, adjust for that now.
- * If it points past the end of the string, point to the terminating null
- */
- if (offset) {
- if (offset > source_len) {
- offset = source_len;
- } else if (offset < 0) {
- offset = 0;
- }
- }
-
- /* Copy the part before -start */
- Jim_AppendString(interp, resultObj, source_str, offset);
-
- /*
- * The following loop is to handle multiple matches within the
- * same source string; each iteration handles one match and its
- * corresponding substitution. If "-all" hasn't been specified
- * then the loop body only gets executed once.
- */
-
- for (p = source_str + offset; *p != 0; ) {
- const char *src;
- int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, 0);
- if (match >= REG_BADPAT) {
- char buf[100];
- regerror(match, regex, buf, sizeof(buf));
- Jim_SetResultString(interp, "", 0);
- Jim_AppendStrings(interp, Jim_GetResult(interp), "error while matching pattern: ", buf, NULL);
- goto done;
- }
- if (match == REG_NOMATCH) {
- break;
- }
-
- num_matches++;
-
- /*
- * Copy the portion of the source string before the match to the
- * result variable.
- */
- Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so);
-
- /*
- * Append the subSpec (replace_str) argument to the variable, making appropriate
- * substitutions. This code is a bit hairy because of the backslash
- * conventions and because the code saves up ranges of characters in
- * subSpec to reduce the number of calls to Jim_SetVar.
- */
-
- for (src = replace_str; *src; src++) {
- int index;
- int c = *src;
-
- if (c == '&') {
- index = 0;
- }
- else if (c == '\\') {
- c = *++src;
- if ((c >= '0') && (c <= '9')) {
- index = c - '0';
- }
- else if ((c == '\\') || (c == '&')) {
- Jim_AppendString(interp, resultObj, src, 1);
- continue;
- }
- else {
- Jim_AppendString(interp, resultObj, src - 1, 2);
- continue;
- }
- }
- else {
- Jim_AppendString(interp, resultObj, src, 1);
- continue;
- }
- if ((index < MAX_SUB_MATCHES) && pmatch[index].rm_so != -1 && pmatch[index].rm_eo != -1) {
- Jim_AppendString(interp, resultObj, p + pmatch[index].rm_so, pmatch[index].rm_eo - pmatch[index].rm_so);
- }
- }
-
- p += pmatch[0].rm_eo;
-
- if (!opt_all || pmatch[0].rm_eo == 0 || pattern[0] == '^') {
- /* If we are doing a single match, or we haven't moved with this match
- * or this is an anchored match, we stop */
- break;
- }
- }
-
- /*
- * Copy the portion of the string after the last match to the
- * result variable.
- */
- Jim_AppendString(interp, resultObj, p, -1);
-
- /* And now set the result variable */
- result = Jim_SetVariable(interp, varname, resultObj);
-
- if (result == JIM_OK) {
- Jim_SetIntResult(interp, num_matches);
- }
- else {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp), "couldn't set variable \"", Jim_GetString(varname, NULL), "\"", NULL);
- Jim_FreeObj(interp, resultObj);
- }
-
- done:
- regfree(regex);
- Jim_Free(regex);
- return result;
-}
-
-int Jim_OnLoad(Jim_Interp *interp)
-{
- Jim_InitExtension(interp);
- if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG) != JIM_OK) {
- return JIM_ERR;
- }
- Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL);
- Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL);
- return JIM_OK;
-}
+/*
+ * Copyright (c) 2008 Steve Bennett <steveb@workware.net.au>
+ *
+ * Implements the regexp and regsub commands for Jim
+ *
+ * Uses C library regcomp()/regexec() for the matching.
+ *
+ * The FreeBSD license
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the Jim Tcl Project.
+ *
+ * Based on code originally from Tcl 6.7:
+ *
+ * Copyright 1987-1991 Regents of the University of California
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <regex.h>
+#include <string.h>
+
+#define JIM_EXTENSION
+#include "jim.h"
+
+/* REVISIT: Would be useful in jim.h */
+static void Jim_SetIntResult(Jim_Interp *interp, jim_wide wide)
+{
+ Jim_SetResult(interp, Jim_NewIntObj(interp, wide));
+}
+
+/**
+ * REVISIT: Should cache a number of compiled regexps for performance reasons.
+ */
+static regex_t *
+compile_regexp(Jim_Interp *interp, const char *pattern, int flags)
+{
+ int ret;
+
+ regex_t *result = (regex_t *)Jim_Alloc(sizeof(*result));
+
+ if ((ret = regcomp(result, pattern, REG_EXTENDED | flags)) != 0) {
+ char buf[100];
+ regerror(ret, result, buf, sizeof(buf));
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "couldn't compile regular expression pattern: ", buf, NULL);
+ Jim_Free(result);
+ return NULL;
+ }
+ return result;
+}
+
+int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ int opt_indices = 0;
+ int opt_all = 0;
+ int opt_inline = 0;
+ regex_t *regex;
+ int match, i, j;
+ long offset = 0;
+ regmatch_t *pmatch = NULL;
+ int source_len;
+ int result = JIM_OK;
+ const char *pattern;
+ const char *source_str;
+ int num_matches = 0;
+ int num_vars;
+ Jim_Obj *resultListObj = NULL;
+ int regcomp_flags = 0;
+
+ if (argc < 3) {
+ wrongNumArgs:
+ Jim_WrongNumArgs(interp, 1, argv, "?-nocase? ?-line? ?-indices? ?-start offset? ?-all? ?-inline? exp string ?matchVar? ?subMatchVar ...?");
+ return JIM_ERR;
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (Jim_CompareStringImmediate(interp, argv[i], "-indices")) {
+ opt_indices = 1;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-nocase")) {
+ regcomp_flags |= REG_ICASE;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-line")) {
+ regcomp_flags |= REG_NEWLINE;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-all")) {
+ opt_all = 1;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-inline")) {
+ opt_inline = 1;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-start")) {
+ if (++i == argc) {
+ goto wrongNumArgs;
+ }
+ if (Jim_GetLong(interp, argv[i], &offset) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "--")) {
+ i++;
+ break;
+ }
+ else {
+ const char *opt = Jim_GetString(argv[i], NULL);
+ if (*opt == '-') {
+ /* Bad option */
+ goto wrongNumArgs;
+ }
+ break;
+ }
+ }
+ if (argc - i < 2) {
+ goto wrongNumArgs;
+ }
+
+ pattern = Jim_GetString(argv[i], NULL);
+ regex = compile_regexp(interp, pattern, regcomp_flags);
+ if (regex == NULL) {
+ return JIM_ERR;
+ }
+
+ source_str = Jim_GetString(argv[i + 1], &source_len);
+
+ num_vars = argc - i - 2;
+
+ if (opt_inline) {
+ if (num_vars) {
+ Jim_SetResultString(interp, "regexp match variables not allowed when using -inline", -1);
+ result = JIM_ERR;
+ goto done;
+ }
+ /* REVISIT: Ugly! */
+ num_vars = 100;
+ }
+
+ pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch));
+
+ /* If an offset has been specified, adjust for that now.
+ * If it points past the end of the string, point to the terminating null
+ */
+ if (offset) {
+ if (offset > source_len) {
+ source_str += source_len;
+ } else if (offset > 0) {
+ source_str += offset;
+ }
+ }
+
+ if (opt_inline) {
+ resultListObj = Jim_NewListObj(interp, NULL, 0);
+ }
+
+ next_match:
+ match = regexec(regex, source_str, num_vars + 1, pmatch, 0);
+ if (match >= REG_BADPAT) {
+ char buf[100];
+ regerror(match, regex, buf, sizeof(buf));
+ Jim_SetResultString(interp, "", 0);
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "error while matching pattern: ", buf, NULL);
+ result = JIM_ERR;
+ goto done;
+ }
+
+ if (match == REG_NOMATCH) {
+ goto done;
+ }
+
+ num_matches++;
+
+ if (opt_all && !opt_inline) {
+ /* Just count the number of matches, so skip the substitution h*/
+ goto try_next_match;
+ }
+
+ /*
+ * If additional variable names have been specified, return
+ * index information in those variables.
+ */
+
+ //fprintf(stderr, "source_str=%s, [0].rm_eo=%d\n", source_str, pmatch[0].rm_eo);
+
+ j = 0;
+ for (i += 2; opt_inline ? pmatch[j].rm_so != -1 : i < argc; i++, j++) {
+ Jim_Obj *resultObj;
+
+ if (opt_indices) {
+ resultObj = Jim_NewListObj(interp, NULL, 0);
+ }
+ else {
+ resultObj = Jim_NewStringObj(interp, "", 0);
+ }
+
+ if (pmatch[j].rm_so == -1) {
+ if (opt_indices) {
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1));
+ }
+ } else {
+ int len = pmatch[j].rm_eo - pmatch[j].rm_so;
+ if (opt_indices) {
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + pmatch[j].rm_so));
+ Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, offset + pmatch[j].rm_so + len - 1));
+ } else {
+ Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len);
+ }
+ }
+
+ if (opt_inline) {
+ Jim_ListAppendElement(interp, resultListObj, resultObj);
+ }
+ else {
+ /* And now set the result variable */
+ result = Jim_SetVariable(interp, argv[i], resultObj);
+
+ if (result != JIM_OK) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "couldn't set variable \"", Jim_GetString(argv[i], NULL), "\"", NULL);
+ Jim_FreeObj(interp, resultObj);
+ break;
+ }
+ }
+ }
+
+ try_next_match:
+ if (opt_all && pattern[0] != '^' && *source_str) {
+ if (pmatch[0].rm_eo) {
+ source_str += pmatch[0].rm_eo;
+ }
+ else {
+ source_str++;
+ }
+ if (*source_str) {
+ goto next_match;
+ }
+ }
+
+ done:
+ if (result == JIM_OK) {
+ if (opt_inline) {
+ Jim_SetResult(interp, resultListObj);
+ }
+ else {
+ Jim_SetIntResult(interp, num_matches);
+ }
+ }
+
+ Jim_Free(pmatch);
+ regfree(regex);
+ Jim_Free(regex);
+ return result;
+}
+
+#define MAX_SUB_MATCHES 10
+
+int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ int regcomp_flags = 0;
+ int opt_all = 0;
+ long offset = 0;
+ regex_t *regex;
+ const char *p;
+ int result = JIM_ERR;
+ regmatch_t pmatch[MAX_SUB_MATCHES + 1];
+ int num_matches = 0;
+
+ int i;
+ Jim_Obj *varname;
+ Jim_Obj *resultObj;
+ const char *source_str;
+ int source_len;
+ const char *replace_str;
+ const char *pattern;
+
+ if (argc < 5) {
+ wrongNumArgs:
+ Jim_WrongNumArgs(interp, 1, argv, "?-nocase? ?-all? exp string subSpec varName");
+ return JIM_ERR;
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (Jim_CompareStringImmediate(interp, argv[i], "-nocase")) {
+ regcomp_flags |= REG_ICASE;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-line")) {
+ regcomp_flags |= REG_NEWLINE;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-all")) {
+ opt_all = 1;
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "-start")) {
+ if (++i == argc) {
+ goto wrongNumArgs;
+ }
+ if (Jim_GetLong(interp, argv[i], &offset) != JIM_OK) {
+ return JIM_ERR;
+ }
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[i], "--")) {
+ i++;
+ break;
+ }
+ else {
+ const char *opt = Jim_GetString(argv[i], NULL);
+ if (*opt == '-') {
+ /* Bad option */
+ goto wrongNumArgs;
+ }
+ break;
+ }
+ }
+ if (argc - i != 4) {
+ goto wrongNumArgs;
+ }
+
+ pattern = Jim_GetString(argv[i], NULL);
+ regex = compile_regexp(interp, pattern, regcomp_flags);
+ if (regex == NULL) {
+ return JIM_ERR;
+ }
+
+ source_str = Jim_GetString(argv[i + 1], &source_len);
+ replace_str = Jim_GetString(argv[i + 2], NULL);
+ varname = argv[i + 3];
+
+ /* Create the result string */
+ resultObj = Jim_NewStringObj(interp, "", 0);
+
+ /* If an offset has been specified, adjust for that now.
+ * If it points past the end of the string, point to the terminating null
+ */
+ if (offset) {
+ if (offset > source_len) {
+ offset = source_len;
+ } else if (offset < 0) {
+ offset = 0;
+ }
+ }
+
+ /* Copy the part before -start */
+ Jim_AppendString(interp, resultObj, source_str, offset);
+
+ /*
+ * The following loop is to handle multiple matches within the
+ * same source string; each iteration handles one match and its
+ * corresponding substitution. If "-all" hasn't been specified
+ * then the loop body only gets executed once.
+ */
+
+ for (p = source_str + offset; *p != 0; ) {
+ const char *src;
+ int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, 0);
+ if (match >= REG_BADPAT) {
+ char buf[100];
+ regerror(match, regex, buf, sizeof(buf));
+ Jim_SetResultString(interp, "", 0);
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "error while matching pattern: ", buf, NULL);
+ goto done;
+ }
+ if (match == REG_NOMATCH) {
+ break;
+ }
+
+ num_matches++;
+
+ /*
+ * Copy the portion of the source string before the match to the
+ * result variable.
+ */
+ Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so);
+
+ /*
+ * Append the subSpec (replace_str) argument to the variable, making appropriate
+ * substitutions. This code is a bit hairy because of the backslash
+ * conventions and because the code saves up ranges of characters in
+ * subSpec to reduce the number of calls to Jim_SetVar.
+ */
+
+ for (src = replace_str; *src; src++) {
+ int index;
+ int c = *src;
+
+ if (c == '&') {
+ index = 0;
+ }
+ else if (c == '\\') {
+ c = *++src;
+ if ((c >= '0') && (c <= '9')) {
+ index = c - '0';
+ }
+ else if ((c == '\\') || (c == '&')) {
+ Jim_AppendString(interp, resultObj, src, 1);
+ continue;
+ }
+ else {
+ Jim_AppendString(interp, resultObj, src - 1, 2);
+ continue;
+ }
+ }
+ else {
+ Jim_AppendString(interp, resultObj, src, 1);
+ continue;
+ }
+ if ((index < MAX_SUB_MATCHES) && pmatch[index].rm_so != -1 && pmatch[index].rm_eo != -1) {
+ Jim_AppendString(interp, resultObj, p + pmatch[index].rm_so, pmatch[index].rm_eo - pmatch[index].rm_so);
+ }
+ }
+
+ p += pmatch[0].rm_eo;
+
+ if (!opt_all || pmatch[0].rm_eo == 0 || pattern[0] == '^') {
+ /* If we are doing a single match, or we haven't moved with this match
+ * or this is an anchored match, we stop */
+ break;
+ }
+ }
+
+ /*
+ * Copy the portion of the string after the last match to the
+ * result variable.
+ */
+ Jim_AppendString(interp, resultObj, p, -1);
+
+ /* And now set the result variable */
+ result = Jim_SetVariable(interp, varname, resultObj);
+
+ if (result == JIM_OK) {
+ Jim_SetIntResult(interp, num_matches);
+ }
+ else {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "couldn't set variable \"", Jim_GetString(varname, NULL), "\"", NULL);
+ Jim_FreeObj(interp, resultObj);
+ }
+
+ done:
+ regfree(regex);
+ Jim_Free(regex);
+ return result;
+}
+
+int Jim_OnLoad(Jim_Interp *interp)
+{
+ Jim_InitExtension(interp);
+ if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+ Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL);
+ Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL);
+ return JIM_OK;
+}