fixed bugs and added more features.

- fixed a bug in qse_sed_exec() to return success on flush() error
- added Sed::setError()
- completed a sample program sed03.cpp
This commit is contained in:
hyung-hwan 2009-05-30 00:21:41 +00:00
parent 0e679b0b7d
commit 7053747ab2
10 changed files with 171 additions and 57 deletions

View File

@ -38,14 +38,18 @@ public:
typedef qse_char_t char_t;
/** data type that can hold any character or an end-of-file value */
typedef qse_cint_t cint_t;
/** represents an unsigned integer number of the same size as void* */
/** redefines an unsigned integer number of the same size as void* */
typedef qse_size_t size_t;
/** signed version of size_t */
typedef qse_ssize_t ssize_t;
/** represents an integer */
/** redefines an integer */
typedef qse_long_t long_t;
/** represents a floating-point number */
/** redefines a floating-point number */
typedef qse_real_t real_t;
/** redefines a structure of a constant character pointer and length */
typedef qse_cstr_t cstr_t;
/** redefines a structure of a character pointer and length */
typedef qse_xstr_t xstr_t;
};
/////////////////////////////////

View File

@ -143,6 +143,15 @@ public:
*/
size_t getConsoleLine () throw ();
/**
* The setError() function sets information on an error occurred.
*/
void setError (
errnum_t err, ///< an error number
size_t lin = 0, ///< a line number
const cstr_t* args = QSE_NULL ///< strings for formatting an error message
);
/**
* The setConsoleLine() function changes the current line
* number from an input console.

View File

@ -21,13 +21,6 @@
#include <qse/sed/Sed.hpp>
/** @file
* A standard stream editor
*
* @example sed02.cpp
* The example shows a simple usage of the StdSed class.
*/
/////////////////////////////////
QSE_BEGIN_NAMESPACE(QSE)
/////////////////////////////////
@ -35,15 +28,13 @@ QSE_BEGIN_NAMESPACE(QSE)
/**
* The StdSed class inherits the Sed class and implements the standard
* IO handlers and memory manager for easier use.
*
*/
class StdSed: public Sed
{
protected:
/** allocate a memory chunk */
void* allocMem (qse_size_t n) throw ();
/** resize a memory chunk */
void* reallocMem (void* ptr, qse_size_t n) throw ();
/** free a memory chunk */
void freeMem (void* ptr) throw ();
int openConsole (Console& io);
@ -57,6 +48,16 @@ protected:
ssize_t writeFile (File& io, const char_t* data, size_t len);
};
/**
* @example sed02.cpp
* The example shows how to use the QSE::StdSed class to write a simple stream
* editor that reads from a standard input and writes to a standard output.
*
* @example sed03.cpp
* The example shows how to extend the QSE::StdSed class to read from and
* write to a string.
*/
/////////////////////////////////
QSE_END_NAMESPACE(QSE)
/////////////////////////////////

View File

@ -1,7 +1,19 @@
/*
* $Id: main.h 463 2008-12-09 06:52:03Z baconevi $
* $Id$
*
* {License}
Copyright 2006-2009 Chung, Hyung-Hwan.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _QSE_UTL_MAIN_H_
@ -10,6 +22,16 @@
#include <qse/types.h>
#include <qse/macros.h>
/** @file
* This file includes a macro and a function to help users to write a
* cross-platform main function.
*/
/**
* The #qse_main macro defines a main function wrapper for an underlying
* platform. Combined with the qse_runmain() function, it provides a consistant
* view to the main function.
*/
#if defined(_WIN32) && !defined(__MINGW32__)
# if defined(QSE_CHAR_IS_MCHAR)
# define qse_main main
@ -27,6 +49,10 @@
extern "C" {
#endif
/**
* The qse_runmain() function helps to invoke a main function independent of
* the character mode configured for the library.
*/
int qse_runmain (
int argc,
qse_achar_t* argv[],

View File

@ -89,6 +89,12 @@ Sed::errnum_t Sed::getErrorNumber () const throw ()
return (sed == QSE_NULL)? QSE_SED_ENOERR: qse_sed_geterrnum (sed);
}
void Sed::setError (errnum_t err, size_t lin, const cstr_t* args)
{
QSE_ASSERT (sed != QSE_NULL);
qse_sed_seterror (sed, err, lin, args);
}
Sed::size_t Sed::getConsoleLine () throw ()
{
QSE_ASSERT (sed != QSE_NULL);

View File

@ -1391,8 +1391,9 @@ static int read_file (
n = sed->e.in.fun (sed, QSE_SED_IO_OPEN, &arg);
if (n <= -1)
{
/*SETERR0 (sed, QSE_SED_EIOUSR, cmd->lnum);
return -1;*/
/*if (sed->errnum != QSE_SED_ENOERR)
* SETERR0 (sed, QSE_SED_EIOUSR, cmd->lnum);
*return -1;*/
/* it is ok if it is not able to open a file */
return 0;
}
@ -1521,7 +1522,10 @@ static int flush (qse_sed_t* sed)
if (n == 0)
{
/* reached the end of file - anything to do? */
/* reached the end of file - this is also an error */
if (sed->errnum == QSE_SED_ENOERR)
SETERR0 (sed, QSE_SED_EIOUSR, 0);
return -1;
}
pos += n;
@ -2629,7 +2633,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf)
/* flush the output stream in case it's not flushed
* in write functions */
n = flush (sed);
if (n <= -1) goto done;
if (n <= -1) { ret = -1; goto done; }
}
done:

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.10.1 from Makefile.am.
# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -33,7 +33,7 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = sed01$(EXEEXT) $(am__EXEEXT_1)
@ENABLE_CXX_TRUE@am__append_1 = sed02
@ENABLE_CXX_TRUE@am__append_1 = sed02 sed03
subdir = test/sed
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -43,7 +43,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/qse/config.h
CONFIG_CLEAN_FILES =
@ENABLE_CXX_TRUE@am__EXEEXT_1 = sed02$(EXEEXT)
@ENABLE_CXX_TRUE@am__EXEEXT_1 = sed02$(EXEEXT) sed03$(EXEEXT)
am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
@ -57,6 +57,10 @@ am__sed02_SOURCES_DIST = sed02.cpp
sed02_OBJECTS = $(am_sed02_OBJECTS)
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
@ENABLE_CXX_TRUE@sed02_DEPENDENCIES = $(am__DEPENDENCIES_2)
am__sed03_SOURCES_DIST = sed03.cpp
@ENABLE_CXX_TRUE@am_sed03_OBJECTS = sed03.$(OBJEXT)
sed03_OBJECTS = $(am_sed03_OBJECTS)
@ENABLE_CXX_TRUE@sed03_DEPENDENCIES = $(am__DEPENDENCIES_2)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/qse
depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp
am__depfiles_maybe = depfiles
@ -78,8 +82,9 @@ CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(sed01_SOURCES) $(sed02_SOURCES)
DIST_SOURCES = $(sed01_SOURCES) $(am__sed02_SOURCES_DIST)
SOURCES = $(sed01_SOURCES) $(sed02_SOURCES) $(sed03_SOURCES)
DIST_SOURCES = $(sed01_SOURCES) $(am__sed02_SOURCES_DIST) \
$(am__sed03_SOURCES_DIST)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -104,14 +109,13 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
ECHO = @ECHO@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
FGREP = @FGREP@
GREP = @GREP@
HAVE_CXX = @HAVE_CXX@
HAVE_OBJC = @HAVE_OBJC@
@ -127,6 +131,7 @@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
@ -138,6 +143,8 @@ OBJCDEPMODE = @OBJCDEPMODE@
OBJCFLAGS = @OBJCFLAGS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@ -158,7 +165,7 @@ abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_OBJC = @ac_ct_OBJC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
@ -190,6 +197,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@ -202,6 +210,7 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = -I$(top_srcdir)/include
@ -209,6 +218,8 @@ LDADD = -lqsesed -lqseutl -lqsecmn $(LIBM)
sed01_SOURCES = sed01.c
@ENABLE_CXX_TRUE@sed02_SOURCES = sed02.cpp
@ENABLE_CXX_TRUE@sed02_LDADD = -lqsesed++ $(LDADD)
@ENABLE_CXX_TRUE@sed03_SOURCES = sed03.cpp
@ENABLE_CXX_TRUE@sed03_LDADD = -lqsesed++ $(LDADD)
all: all-am
.SUFFIXES:
@ -217,8 +228,8 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@ -276,6 +287,9 @@ sed01$(EXEEXT): $(sed01_OBJECTS) $(sed01_DEPENDENCIES)
sed02$(EXEEXT): $(sed02_OBJECTS) $(sed02_DEPENDENCIES)
@rm -f sed02$(EXEEXT)
$(CXXLINK) $(sed02_OBJECTS) $(sed02_LDADD) $(LIBS)
sed03$(EXEEXT): $(sed03_OBJECTS) $(sed03_DEPENDENCIES)
@rm -f sed03$(EXEEXT)
$(CXXLINK) $(sed03_OBJECTS) $(sed03_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@ -285,6 +299,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sed01.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sed02.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sed03.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@ -339,7 +354,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS

View File

@ -1,4 +1,4 @@
/*
/**
* $Id$
*
Copyright 2006-2009 Chung, Hyung-Hwan.

View File

@ -1,4 +1,4 @@
/*
/**
* $Id$
*
Copyright 2006-2009 Chung, Hyung-Hwan.
@ -22,6 +22,13 @@
int sed_main (int argc, qse_char_t* argv[])
{
if (argc != 2)
{
qse_fprintf (QSE_STDERR,
QSE_T("usage: %s command-string\n"), argv[0]);
return -1;
}
QSE::StdSed sed;
if (sed.open () == -1)

View File

@ -1,4 +1,4 @@
/*
/**
* $Id$
*
Copyright 2006-2009 Chung, Hyung-Hwan.
@ -18,59 +18,101 @@
#include <qse/sed/StdSed.hpp>
#include <qse/utl/main.h>
#include <qse/utl/stdio.h>
#include <string>
#include <iostream>
typedef std::basic_string<QSE::StdSed::char_t> xstring;
typedef QSE::StdSed StdSed; // added for doxygen cross-reference
//
// The MySed class provides a handier interface to QSE::StdSed by
// reimplementing console I/O functions, combining compile() and execute(),
// and utilizing exception handling.
//
class MySed: protected QSE::StdSed
{
public:
MySed ()
{
if (open() == -1)
{
throw 1;
}
}
class Error
{
public:
Error (const char_t* msg) throw (): msg (msg) { }
const char_t* getMessage() const throw() { return msg; }
protected:
const char_t* msg;
};
~MySed ()
{
close ();
MySed ()
{
if (QSE::StdSed::open() == -1)
throw Error (QSE_T("cannot open"));
}
~MySed ()
{
QSE::StdSed::close ();
}
int exec (const char_t* cmds, const char_t* in, string& out)
void run (const char_t* cmds, const char_t* in, xstring& out)
{
if (compile (cmds) == -1) return -1;
if (execute () == -1) return -1;
return 0;
// remember an input string and an output string
this->in = in; this->out = &out;
// compile source commands and execute compiled commands.
if (QSE::StdSed::compile (cmds) <= -1 ||
QSE::StdSed::execute () <= -1)
{
throw Error (QSE::StdSed::getErrorMessage());
}
}
protected:
int openConsole (Console& io)
{
// override console I/O functions to perform I/O over strings.
int openConsole (Console& io)
{
if (io.getMode() == Console::WRITE) out->clear();
return 1;
}
int closeConsole (Console& io)
int closeConsole (Console& io)
{
return 0;
}
ssize_t readConsole (Console& io, char_t* buf, size_t len)
{
return 0;
ssize_t n = qse_strxcpy (buf, len, in);
in += n; return n;
}
ssize_t writeConsole (Console& io, const char_t* buf, size_t len)
{
return 0;
try { out->append (buf, len); return len; }
catch (...) { QSE::Sed::setError (QSE_SED_ENOMEM); throw; }
}
protected:
const char_t* in;
xstring* out;
};
int sed_main (int argc, qse_char_t* argv[])
{
MySed sed;
if (sed.exec (QSE_T("s/abc/XXXXXXXXXXX/g"), in, out) == 0)
try
{
MySed sed;
xstring out;
sed.run (
QSE_T("y/ABC/abc/;s/abc/def/g"),
QSE_T("ABCDEFabcdef"), out);
std::cout << QSE_T("OUTPUT: ") << out << std::endl;
}
catch (MySed::Error& err)
{
std::cout << QSE_T("ERROR: ") << err.getMessage() << std::endl;
return -1;
}