summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pygments/cmdline.py21
-rw-r--r--pygments/filter.py9
-rw-r--r--pygments/filters/__init__.py14
-rw-r--r--pygments/formatters/__init__.py5
-rw-r--r--pygments/formatters/latex.py2
-rw-r--r--pygments/lexer.py12
-rw-r--r--tests/examplefiles/ceval.c1745
-rw-r--r--tests/examplefiles/example.c5334
-rw-r--r--tests/examplefiles/example.cpp3881
-rw-r--r--tests/examplefiles/example.rb5704
-rw-r--r--tests/examplefiles/ltmain.sh4122
-rw-r--r--tests/examplefiles/perlfunc.14503
-rw-r--r--tests/examplefiles/pleac.in.rb1736
-rw-r--r--tests/examplefiles/test.html1668
-rw-r--r--tests/test_examplefiles.py2
-rw-r--r--tests/test_latex_formatter.py50
16 files changed, 86 insertions, 28722 deletions
diff --git a/pygments/cmdline.py b/pygments/cmdline.py
index 53f47206..3e98af39 100644
--- a/pygments/cmdline.py
+++ b/pygments/cmdline.py
@@ -17,7 +17,8 @@ from pygments.util import ClassNotFound, OptionError, docstring_headline
from pygments.lexers import get_all_lexers, get_lexer_by_name, get_lexer_for_filename, \
find_lexer_class
from pygments.formatters import get_all_formatters, get_formatter_by_name, \
- get_formatter_for_filename, TerminalFormatter, find_formatter_class
+ get_formatter_for_filename, find_formatter_class, \
+ TerminalFormatter # pylint:disable-msg=E0611
from pygments.filters import get_all_filters, find_filter_class
from pygments.styles import get_all_styles, get_style_by_name
@@ -102,22 +103,22 @@ def _parse_filters(f_strs):
return filters
-def _print_help(type, name):
+def _print_help(what, name):
try:
- if type == 'lexer':
+ if what == 'lexer':
cls = find_lexer_class(name)
print "Help on the %s lexer:" % cls.name
print dedent(cls.__doc__)
- elif type == 'formatter':
+ elif what == 'formatter':
cls = find_formatter_class(name)
print "Help on the %s formatter:" % cls.name
print dedent(cls.__doc__)
- elif type == 'filter':
+ elif what == 'filter':
cls = find_filter_class(name)
print "Help on the %s filter:" % name
print dedent(cls.__doc__)
except ClassNotFound:
- print >>sys.stderr, "%s not found!" % type
+ print >>sys.stderr, "%s not found!" % what
def _print_list(what):
@@ -175,6 +176,8 @@ def main(args):
"""
Main command line entry point.
"""
+ # pylint: disable-msg=R0911,R0912,R0915
+
usage = USAGE % ((args[0],) * 5)
try:
@@ -226,12 +229,12 @@ def main(args):
print >>sys.stderr, usage
return 2
- type, name = args
- if type not in ('lexer', 'formatter', 'filter'):
+ what, name = args
+ if what not in ('lexer', 'formatter', 'filter'):
print >>sys.stderr, usage
return 2
- _print_help(type, name)
+ _print_help(what, name)
return 0
# parse -O options
diff --git a/pygments/filter.py b/pygments/filter.py
index f304953c..2da319d1 100644
--- a/pygments/filter.py
+++ b/pygments/filter.py
@@ -16,11 +16,11 @@ def apply_filters(stream, filters, lexer=None):
a stream. If lexer is given it's forwarded to the
filter, otherwise the filter receives `None`.
"""
- def _apply(filter, stream):
- for token in filter.filter(lexer, stream):
+ def _apply(filter_, stream):
+ for token in filter_.filter(lexer, stream):
yield token
- for filter in filters:
- stream = _apply(filter, stream)
+ for filter_ in filters:
+ stream = _apply(filter_, stream)
return stream
@@ -69,5 +69,6 @@ class FunctionFilter(Filter):
Filter.__init__(self, **options)
def filter(self, lexer, stream):
+ # pylint: disable-msg=E1102
for ttype, value in self.function(lexer, stream, self.options):
yield ttype, value
diff --git a/pygments/filters/__init__.py b/pygments/filters/__init__.py
index 524e3bbb..ccb78652 100644
--- a/pygments/filters/__init__.py
+++ b/pygments/filters/__init__.py
@@ -21,28 +21,28 @@ from pygments.util import get_list_opt, ClassNotFound
from pygments.plugin import find_plugin_filters
-def find_filter_class(filter):
+def find_filter_class(filtername):
"""
Lookup a filter by name. Return None if not found.
"""
- if filter in FILTERS:
- return FILTERS[filter]
+ if filtername in FILTERS:
+ return FILTERS[filtername]
for name, cls in find_plugin_filters():
- if name == filter:
+ if name == filtername:
return cls
return None
-def get_filter_by_name(filter, **options):
+def get_filter_by_name(filtername, **options):
"""
Return an instantiated filter. Options are passed to the filter
initializer if wanted. Raise a ClassNotFound if not found.
"""
- cls = find_filter_class(filter)
+ cls = find_filter_class(filtername)
if cls:
return cls(**options)
else:
- raise ClassNotFound('filter %r not found' % filter)
+ raise ClassNotFound('filter %r not found' % filtername)
def get_all_filters():
diff --git a/pygments/formatters/__init__.py b/pygments/formatters/__init__.py
index 397f5027..8d0feaaa 100644
--- a/pygments/formatters/__init__.py
+++ b/pygments/formatters/__init__.py
@@ -16,8 +16,9 @@ from pygments.plugin import find_plugin_formatters
from pygments.util import docstring_headline, ClassNotFound
ns = globals()
-for cls in FORMATTERS:
- ns[cls.__name__] = cls
+for fcls in FORMATTERS:
+ ns[fcls.__name__] = fcls
+del fcls
__all__ = ['get_formatter_by_name', 'get_formatter_for_filename',
'get_all_formatters'] + [cls.__name__ for cls in FORMATTERS]
diff --git a/pygments/formatters/latex.py b/pygments/formatters/latex.py
index a1e35c75..bc40cf1b 100644
--- a/pygments/formatters/latex.py
+++ b/pygments/formatters/latex.py
@@ -216,6 +216,6 @@ class LatexFormatter(Formatter):
dict(docclass = self.docclass,
preamble = self.preamble,
title = self.title,
- encoding = self.encoding,
+ encoding = self.encoding or 'latin1',
styledefs = self.get_style_defs(),
code = outfile.getvalue()))
diff --git a/pygments/lexer.py b/pygments/lexer.py
index 6cec28f8..25d36e08 100644
--- a/pygments/lexer.py
+++ b/pygments/lexer.py
@@ -86,8 +86,8 @@ class Lexer(object):
self.encoding = options.get('encoding', 'latin1')
# self.encoding = options.get('inencoding', None) or self.encoding
self.filters = []
- for filter in get_list_opt(options, 'filters', ()):
- self.add_filter(filter)
+ for filter_ in get_list_opt(options, 'filters', ()):
+ self.add_filter(filter_)
def __repr__(self):
if self.options:
@@ -96,13 +96,13 @@ class Lexer(object):
else:
return '<pygments.lexers.%s>' % self.__class__.__name__
- def add_filter(self, filter, **options):
+ def add_filter(self, filter_, **options):
"""
Add a new stream filter to this lexer.
"""
- if not isinstance(filter, Filter):
- filter = get_filter_by_name(filter, **options)
- self.filters.append(filter)
+ if not isinstance(filter_, Filter):
+ filter = get_filter_by_name(filter_, **options)
+ self.filters.append(filter_)
def analyse_text(text):
"""
diff --git a/tests/examplefiles/ceval.c b/tests/examplefiles/ceval.c
index 99e87e81..c6739630 100644
--- a/tests/examplefiles/ceval.c
+++ b/tests/examplefiles/ceval.c
@@ -2602,1748 +2602,3 @@ fast_yield:
return retval;
}
-/* This is gonna seem *real weird*, but if you put some other code between
- PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
- the test in the if statements in Misc/gdbinit (pystack and pystackv). */
-
-PyObject *
-PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
- PyObject **args, int argcount, PyObject **kws, int kwcount,
- PyObject **defs, int defcount, PyObject *closure)
-{
- register PyFrameObject *f;
- register PyObject *retval = NULL;
- register PyObject **fastlocals, **freevars;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *x, *u;
-
- if (globals == NULL) {
- PyErr_SetString(PyExc_SystemError,
- "PyEval_EvalCodeEx: NULL globals");
- return NULL;
- }
-
- assert(tstate != NULL);
- assert(globals != NULL);
- f = PyFrame_New(tstate, co, globals, locals);
- if (f == NULL)
- return NULL;
-
- fastlocals = f->f_localsplus;
- freevars = f->f_localsplus + co->co_nlocals;
-
- if (co->co_argcount > 0 ||
- co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
- int i;
- int n = argcount;
- PyObject *kwdict = NULL;
- if (co->co_flags & CO_VARKEYWORDS) {
- kwdict = PyDict_New();
- if (kwdict == NULL)
- goto fail;
- i = co->co_argcount;
- if (co->co_flags & CO_VARARGS)
- i++;
- SETLOCAL(i, kwdict);
- }
- if (argcount > co->co_argcount) {
- if (!(co->co_flags & CO_VARARGS)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes %s %d "
- "%sargument%s (%d given)",
- PyString_AsString(co->co_name),
- defcount ? "at most" : "exactly",
- co->co_argcount,
- kwcount ? "non-keyword " : "",
- co->co_argcount == 1 ? "" : "s",
- argcount);
- goto fail;
- }
- n = co->co_argcount;
- }
- for (i = 0; i < n; i++) {
- x = args[i];
- Py_INCREF(x);
- SETLOCAL(i, x);
- }
- if (co->co_flags & CO_VARARGS) {
- u = PyTuple_New(argcount - n);
- if (u == NULL)
- goto fail;
- SETLOCAL(co->co_argcount, u);
- for (i = n; i < argcount; i++) {
- x = args[i];
- Py_INCREF(x);
- PyTuple_SET_ITEM(u, i-n, x);
- }
- }
- for (i = 0; i < kwcount; i++) {
- PyObject *keyword = kws[2*i];
- PyObject *value = kws[2*i + 1];
- int j;
- if (keyword == NULL || !PyString_Check(keyword)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() keywords must be strings",
- PyString_AsString(co->co_name));
- goto fail;
- }
- /* XXX slow -- speed up using dictionary? */
- for (j = 0; j < co->co_argcount; j++) {
- PyObject *nm = PyTuple_GET_ITEM(
- co->co_varnames, j);
- int cmp = PyObject_RichCompareBool(
- keyword, nm, Py_EQ);
- if (cmp > 0)
- break;
- else if (cmp < 0)
- goto fail;
- }
- /* Check errors from Compare */
- if (PyErr_Occurred())
- goto fail;
- if (j >= co->co_argcount) {
- if (kwdict == NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got an unexpected "
- "keyword argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(keyword));
- goto fail;
- }
- PyDict_SetItem(kwdict, keyword, value);
- }
- else {
- if (GETLOCAL(j) != NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got multiple "
- "values for keyword "
- "argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(keyword));
- goto fail;
- }
- Py_INCREF(value);
- SETLOCAL(j, value);
- }
- }
- if (argcount < co->co_argcount) {
- int m = co->co_argcount - defcount;
- for (i = argcount; i < m; i++) {
- if (GETLOCAL(i) == NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes %s %d "
- "%sargument%s (%d given)",
- PyString_AsString(co->co_name),
- ((co->co_flags & CO_VARARGS) ||
- defcount) ? "at least"
- : "exactly",
- m, kwcount ? "non-keyword " : "",
- m == 1 ? "" : "s", i);
- goto fail;
- }
- }
- if (n > m)
- i = n - m;
- else
- i = 0;
- for (; i < defcount; i++) {
- if (GETLOCAL(m+i) == NULL) {
- PyObject *def = defs[i];
- Py_INCREF(def);
- SETLOCAL(m+i, def);
- }
- }
- }
- }
- else {
- if (argcount > 0 || kwcount > 0) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%d given)",
- PyString_AsString(co->co_name),
- argcount + kwcount);
- goto fail;
- }
- }
- /* Allocate and initialize storage for cell vars, and copy free
- vars into frame. This isn't too efficient right now. */
- if (PyTuple_GET_SIZE(co->co_cellvars)) {
- int i, j, nargs, found;
- char *cellname, *argname;
- PyObject *c;
-
- nargs = co->co_argcount;
- if (co->co_flags & CO_VARARGS)
- nargs++;
- if (co->co_flags & CO_VARKEYWORDS)
- nargs++;
-
- /* Initialize each cell var, taking into account
- cell vars that are initialized from arguments.
-
- Should arrange for the compiler to put cellvars
- that are arguments at the beginning of the cellvars
- list so that we can march over it more efficiently?
- */
- for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
- cellname = PyString_AS_STRING(
- PyTuple_GET_ITEM(co->co_cellvars, i));
- found = 0;
- for (j = 0; j < nargs; j++) {
- argname = PyString_AS_STRING(
- PyTuple_GET_ITEM(co->co_varnames, j));
- if (strcmp(cellname, argname) == 0) {
- c = PyCell_New(GETLOCAL(j));
- if (c == NULL)
- goto fail;
- GETLOCAL(co->co_nlocals + i) = c;
- found = 1;
- break;
- }
- }
- if (found == 0) {
- c = PyCell_New(NULL);
- if (c == NULL)
- goto fail;
- SETLOCAL(co->co_nlocals + i, c);
- }
- }
- }
- if (PyTuple_GET_SIZE(co->co_freevars)) {
- int i;
- for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
- PyObject *o = PyTuple_GET_ITEM(closure, i);
- Py_INCREF(o);
- freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
- }
- }
-
- if (co->co_flags & CO_GENERATOR) {
- /* Don't need to keep the reference to f_back, it will be set
- * when the generator is resumed. */
- Py_XDECREF(f->f_back);
- f->f_back = NULL;
-
- PCALL(PCALL_GENERATOR);
-
- /* Create a new generator that owns the ready to run frame
- * and return that as the value. */
- return PyGen_New(f);
- }
-
- retval = PyEval_EvalFrameEx(f,0);
-
- fail: /* Jump here from prelude on failure */
-
- /* decref'ing the frame can cause __del__ methods to get invoked,
- which can call back into Python. While we're done with the
- current Python frame (f), the associated C stack is still in use,
- so recursion_depth must be boosted for the duration.
- */
- assert(tstate != NULL);
- ++tstate->recursion_depth;
- Py_DECREF(f);
- --tstate->recursion_depth;
- return retval;
-}
-
-
-/* Implementation notes for set_exc_info() and reset_exc_info():
-
-- Below, 'exc_ZZZ' stands for 'exc_type', 'exc_value' and
- 'exc_traceback'. These always travel together.
-
-- tstate->curexc_ZZZ is the "hot" exception that is set by
- PyErr_SetString(), cleared by PyErr_Clear(), and so on.
-
-- Once an exception is caught by an except clause, it is transferred
- from tstate->curexc_ZZZ to tstate->exc_ZZZ, from which sys.exc_info()
- can pick it up. This is the primary task of set_exc_info().
- XXX That can't be right: set_exc_info() doesn't look at tstate->curexc_ZZZ.
-
-- Now let me explain the complicated dance with frame->f_exc_ZZZ.
-
- Long ago, when none of this existed, there were just a few globals:
- one set corresponding to the "hot" exception, and one set
- corresponding to sys.exc_ZZZ. (Actually, the latter weren't C
- globals; they were simply stored as sys.exc_ZZZ. For backwards
- compatibility, they still are!) The problem was that in code like
- this:
-
- try:
- "something that may fail"
- except "some exception":
- "do something else first"
- "print the exception from sys.exc_ZZZ."
-
- if "do something else first" invoked something that raised and caught
- an exception, sys.exc_ZZZ were overwritten. That was a frequent
- cause of subtle bugs. I fixed this by changing the semantics as
- follows:
-
- - Within one frame, sys.exc_ZZZ will hold the last exception caught
- *in that frame*.
-
- - But initially, and as long as no exception is caught in a given
- frame, sys.exc_ZZZ will hold the last exception caught in the
- previous frame (or the frame before that, etc.).
-
- The first bullet fixed the bug in the above example. The second
- bullet was for backwards compatibility: it was (and is) common to
- have a function that is called when an exception is caught, and to
- have that function access the caught exception via sys.exc_ZZZ.
- (Example: traceback.print_exc()).
-
- At the same time I fixed the problem that sys.exc_ZZZ weren't
- thread-safe, by introducing sys.exc_info() which gets it from tstate;
- but that's really a separate improvement.
-
- The reset_exc_info() function in ceval.c restores the tstate->exc_ZZZ
- variables to what they were before the current frame was called. The
- set_exc_info() function saves them on the frame so that
- reset_exc_info() can restore them. The invariant is that
- frame->f_exc_ZZZ is NULL iff the current frame never caught an
- exception (where "catching" an exception applies only to successful
- except clauses); and if the current frame ever caught an exception,
- frame->f_exc_ZZZ is the exception that was stored in tstate->exc_ZZZ
- at the start of the current frame.
-
-*/
-
-static void
-set_exc_info(PyThreadState *tstate,
- PyObject *type, PyObject *value, PyObject *tb)
-{
- PyFrameObject *frame = tstate->frame;
- PyObject *tmp_type, *tmp_value, *tmp_tb;
-
- assert(type != NULL);
- assert(frame != NULL);
- if (frame->f_exc_type == NULL) {
- assert(frame->f_exc_value == NULL);
- assert(frame->f_exc_traceback == NULL);
- /* This frame didn't catch an exception before. */
- /* Save previous exception of this thread in this frame. */
- if (tstate->exc_type == NULL) {
- /* XXX Why is this set to Py_None? */
- Py_INCREF(Py_None);
- tstate->exc_type = Py_None;
- }
- Py_INCREF(tstate->exc_type);
- Py_XINCREF(tstate->exc_value);
- Py_XINCREF(tstate->exc_traceback);
- frame->f_exc_type = tstate->exc_type;
- frame->f_exc_value = tstate->exc_value;
- frame->f_exc_traceback = tstate->exc_traceback;
- }
- /* Set new exception for this thread. */
- tmp_type = tstate->exc_type;
- tmp_value = tstate->exc_value;
- tmp_tb = tstate->exc_traceback;
- Py_INCREF(type);
- Py_XINCREF(value);
- Py_XINCREF(tb);
- tstate->exc_type = type;
- tstate->exc_value = value;
- tstate->exc_traceback = tb;
- Py_XDECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
- /* For b/w compatibility */
- PySys_SetObject("exc_type", type);
- PySys_SetObject("exc_value", value);
- PySys_SetObject("exc_traceback", tb);
-}
-
-static void
-reset_exc_info(PyThreadState *tstate)
-{
- PyFrameObject *frame;
- PyObject *tmp_type, *tmp_value, *tmp_tb;
-
- /* It's a precondition that the thread state's frame caught an
- * exception -- verify in a debug build.
- */
- assert(tstate != NULL);
- frame = tstate->frame;
- assert(frame != NULL);
- assert(frame->f_exc_type != NULL);
-
- /* Copy the frame's exception info back to the thread state. */
- tmp_type = tstate->exc_type;
- tmp_value = tstate->exc_value;
- tmp_tb = tstate->exc_traceback;
- Py_INCREF(frame->f_exc_type);
- Py_XINCREF(frame->f_exc_value);
- Py_XINCREF(frame->f_exc_traceback);
- tstate->exc_type = frame->f_exc_type;
- tstate->exc_value = frame->f_exc_value;
- tstate->exc_traceback = frame->f_exc_traceback;
- Py_XDECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
-
- /* For b/w compatibility */
- PySys_SetObject("exc_type", frame->f_exc_type);
- PySys_SetObject("exc_value", frame->f_exc_value);
- PySys_SetObject("exc_traceback", frame->f_exc_traceback);
-
- /* Clear the frame's exception info. */
- tmp_type = frame->f_exc_type;
- tmp_value = frame->f_exc_value;
- tmp_tb = frame->f_exc_traceback;
- frame->f_exc_type = NULL;
- frame->f_exc_value = NULL;
- frame->f_exc_traceback = NULL;
- Py_DECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
-}
-
-/* Logic for the raise statement (too complicated for inlining).
- This *consumes* a reference count to each of its arguments. */
-static enum why_code
-do_raise(PyObject *type, PyObject *value, PyObject *tb)
-{
- if (type == NULL) {
- /* Reraise */
- PyThreadState *tstate = PyThreadState_GET();
- type = tstate->exc_type == NULL ? Py_None : tstate->exc_type;
- value = tstate->exc_value;
- tb = tstate->exc_traceback;
- Py_XINCREF(type);
- Py_XINCREF(value);
- Py_XINCREF(tb);
- }
-
- /* We support the following forms of raise:
- raise <class>, <classinstance>
- raise <class>, <argument tuple>
- raise <class>, None
- raise <class>, <argument>
- raise <classinstance>, None
- raise <string>, <object>
- raise <string>, None
-
- An omitted second argument is the same as None.
-
- In addition, raise <tuple>, <anything> is the same as
- raising the tuple's first item (and it better have one!);
- this rule is applied recursively.
-
- Finally, an optional third argument can be supplied, which
- gives the traceback to be substituted (useful when
- re-raising an exception after examining it). */
-
- /* First, check the traceback argument, replacing None with
- NULL. */
- if (tb == Py_None) {
- Py_DECREF(tb);
- tb = NULL;
- }
- else if (tb != NULL && !PyTraceBack_Check(tb)) {
- PyErr_SetString(PyExc_TypeError,
- "raise: arg 3 must be a traceback or None");
- goto raise_error;
- }
-
- /* Next, replace a missing value with None */
- if (value == NULL) {
- value = Py_None;
- Py_INCREF(value);
- }
-
- /* Next, repeatedly, replace a tuple exception with its first item */
- while (PyTuple_Check(type) && PyTuple_Size(type) > 0) {
- PyObject *tmp = type;
- type = PyTuple_GET_ITEM(type, 0);
- Py_INCREF(type);
- Py_DECREF(tmp);
- }
-
- if (PyString_CheckExact(type)) {
- /* Raising builtin string is deprecated but still allowed --
- * do nothing. Raising an instance of a new-style str
- * subclass is right out. */
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "raising a string exception is deprecated"))
- goto raise_error;
- }
- else if (PyExceptionClass_Check(type))
- PyErr_NormalizeException(&type, &value, &tb);
-
- else if (PyExceptionInstance_Check(type)) {
- /* Raising an instance. The value should be a dummy. */
- if (value != Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "instance exception may not have a separate value");
- goto raise_error;
- }
- else {
- /* Normalize to raise <class>, <instance> */
- Py_DECREF(value);
- value = type;
- type = PyExceptionInstance_Class(type);
- Py_INCREF(type);
- }
- }
- else {
- /* Not something you can raise. You get an exception
- anyway, just not what you specified :-) */
- PyErr_Format(PyExc_TypeError,
- "exceptions must be classes, instances, or "
- "strings (deprecated), not %s",
- type->ob_type->tp_name);
- goto raise_error;
- }
- PyErr_Restore(type, value, tb);
- if (tb == NULL)
- return WHY_EXCEPTION;
- else
- return WHY_RERAISE;
- raise_error:
- Py_XDECREF(value);
- Py_XDECREF(type);
- Py_XDECREF(tb);
- return WHY_EXCEPTION;
-}
-
-/* Iterate v argcnt times and store the results on the stack (via decreasing
- sp). Return 1 for success, 0 if error. */
-
-static int
-unpack_iterable(PyObject *v, int argcnt, PyObject **sp)
-{
- int i = 0;
- PyObject *it; /* iter(v) */
- PyObject *w;
-
- assert(v != NULL);
-
- it = PyObject_GetIter(v);
- if (it == NULL)
- goto Error;
-
- for (; i < argcnt; i++) {
- w = PyIter_Next(it);
- if (w == NULL) {
- /* Iterator done, via error or exhaustion. */
- if (!PyErr_Occurred()) {
- PyErr_Format(PyExc_ValueError,
- "need more than %d value%s to unpack",
- i, i == 1 ? "" : "s");
- }
- goto Error;
- }
- *--sp = w;
- }
-
- /* We better have exhausted the iterator now. */
- w = PyIter_Next(it);
- if (w == NULL) {
- if (PyErr_Occurred())
- goto Error;
- Py_DECREF(it);
- return 1;
- }
- Py_DECREF(w);
- PyErr_SetString(PyExc_ValueError, "too many values to unpack");
- /* fall through */
-Error:
- for (; i > 0; i--, sp++)
- Py_DECREF(*sp);
- Py_XDECREF(it);
- return 0;
-}
-
-
-#ifdef LLTRACE
-static int
-prtrace(PyObject *v, char *str)
-{
- printf("%s ", str);
- if (PyObject_Print(v, stdout, 0) != 0)
- PyErr_Clear(); /* Don't know what else to do */
- printf("\n");
- return 1;
-}
-#endif
-
-static void
-call_exc_trace(Py_tracefunc func, PyObject *self, PyFrameObject *f)
-{
- PyObject *type, *value, *traceback, *arg;
- int err;
- PyErr_Fetch(&type, &value, &traceback);
- if (value == NULL) {
- value = Py_None;
- Py_INCREF(value);
- }
- arg = PyTuple_Pack(3, type, value, traceback);
- if (arg == NULL) {
- PyErr_Restore(type, value, traceback);
- return;
- }
- err = call_trace(func, self, f, PyTrace_EXCEPTION, arg);
- Py_DECREF(arg);
- if (err == 0)
- PyErr_Restore(type, value, traceback);
- else {
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(traceback);
- }
-}
-
-static void
-call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
- int what, PyObject *arg)
-{
- PyObject *type, *value, *traceback;
- int err;
- PyErr_Fetch(&type, &value, &traceback);
- err = call_trace(func, obj, frame, what, arg);
- if (err == 0)
- PyErr_Restore(type, value, traceback);
- else {
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(traceback);
- }
-}
-
-static int
-call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
- int what, PyObject *arg)
-{
- register PyThreadState *tstate = frame->f_tstate;
- int result;
- if (tstate->tracing)
- return 0;
- tstate->tracing++;
- tstate->use_tracing = 0;
- result = func(obj, frame, what, arg);
- tstate->use_tracing = ((tstate->c_tracefunc != NULL)
- || (tstate->c_profilefunc != NULL));
- tstate->tracing--;
- return result;
-}
-
-PyObject *
-_PyEval_CallTracing(PyObject *func, PyObject *args)
-{
- PyFrameObject *frame = PyEval_GetFrame();
- PyThreadState *tstate = frame->f_tstate;
- int save_tracing = tstate->tracing;
- int save_use_tracing = tstate->use_tracing;
- PyObject *result;
-
- tstate->tracing = 0;
- tstate->use_tracing = ((tstate->c_tracefunc != NULL)
- || (tstate->c_profilefunc != NULL));
- result = PyObject_Call(func, args, NULL);
- tstate->tracing = save_tracing;
- tstate->use_tracing = save_use_tracing;
- return result;
-}
-
-static int
-maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
- PyFrameObject *frame, int *instr_lb, int *instr_ub,
- int *instr_prev)
-{
- int result = 0;
-
- /* If the last instruction executed isn't in the current
- instruction window, reset the window. If the last
- instruction happens to fall at the start of a line or if it
- represents a jump backwards, call the trace function.
- */
- if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) {
- int line;
- PyAddrPair bounds;
-
- line = PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
- &bounds);
- if (line >= 0) {
- frame->f_lineno = line;
- result = call_trace(func, obj, frame,
- PyTrace_LINE, Py_None);
- }
- *instr_lb = bounds.ap_lower;
- *instr_ub = bounds.ap_upper;
- }
- else if (frame->f_lasti <= *instr_prev) {
- result = call_trace(func, obj, frame, PyTrace_LINE, Py_None);
- }
- *instr_prev = frame->f_lasti;
- return result;
-}
-
-void
-PyEval_SetProfile(Py_tracefunc func, PyObject *arg)
-{
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *temp = tstate->c_profileobj;
- Py_XINCREF(arg);
- tstate->c_profilefunc = NULL;
- tstate->c_profileobj = NULL;
- /* Must make sure that tracing is not ignored if 'temp' is freed */
- tstate->use_tracing = tstate->c_tracefunc != NULL;
- Py_XDECREF(temp);
- tstate->c_profilefunc = func;
- tstate->c_profileobj = arg;
- /* Flag that tracing or profiling is turned on */
- tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL);
-}
-
-void
-PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
-{
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *temp = tstate->c_traceobj;
- Py_XINCREF(arg);
- tstate->c_tracefunc = NULL;
- tstate->c_traceobj = NULL;
- /* Must make sure that profiling is not ignored if 'temp' is freed */
- tstate->use_tracing = tstate->c_profilefunc != NULL;
- Py_XDECREF(temp);
- tstate->c_tracefunc = func;
- tstate->c_traceobj = arg;
- /* Flag that tracing or profiling is turned on */
- tstate->use_tracing = ((func != NULL)
- || (tstate->c_profilefunc != NULL));
-}
-
-PyObject *
-PyEval_GetBuiltins(void)
-{
- PyFrameObject *current_frame = PyEval_GetFrame();
- if (current_frame == NULL)
- return PyThreadState_GET()->interp->builtins;
- else
- return current_frame->f_builtins;
-}
-
-PyObject *
-PyEval_GetLocals(void)
-{
- PyFrameObject *current_frame = PyEval_GetFrame();
- if (current_frame == NULL)
- return NULL;
- PyFrame_FastToLocals(current_frame);
- return current_frame->f_locals;
-}
-
-PyObject *
-PyEval_GetGlobals(void)
-{
- PyFrameObject *current_frame = PyEval_GetFrame();
- if (current_frame == NULL)
- return NULL;
- else
- return current_frame->f_globals;
-}
-
-PyFrameObject *
-PyEval_GetFrame(void)
-{
- PyThreadState *tstate = PyThreadState_GET();
- return _PyThreadState_GetFrame(tstate);
-}
-
-int
-PyEval_GetRestricted(void)
-{
- PyFrameObject *current_frame = PyEval_GetFrame();
- return current_frame == NULL ? 0 : PyFrame_IsRestricted(current_frame);
-}
-
-int
-PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
-{
- PyFrameObject *current_frame = PyEval_GetFrame();
- int result = cf->cf_flags != 0;
-
- if (current_frame != NULL) {
- const int codeflags = current_frame->f_code->co_flags;
- const int compilerflags = codeflags & PyCF_MASK;
- if (compilerflags) {
- result = 1;
- cf->cf_flags |= compilerflags;
- }
-#if 0 /* future keyword */
- if (codeflags & CO_GENERATOR_ALLOWED) {
- result = 1;
- cf->cf_flags |= CO_GENERATOR_ALLOWED;
- }
-#endif
- }
- return result;
-}
-
-int
-Py_FlushLine(void)
-{
- PyObject *f = PySys_GetObject("stdout");
- if (f == NULL)
- return 0;
- if (!PyFile_SoftSpace(f, 0))
- return 0;
- return PyFile_WriteString("\n", f);
-}
-
-
-/* External interface to call any callable object.
- The arg must be a tuple or NULL. */
-
-#undef PyEval_CallObject
-/* for backward compatibility: export this interface */
-
-PyObject *
-PyEval_CallObject(PyObject *func, PyObject *arg)
-{
- return PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL);
-}
-#define PyEval_CallObject(func,arg) \
- PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL)
-
-PyObject *
-PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
-{
- PyObject *result;
-
- if (arg == NULL) {
- arg = PyTuple_New(0);
- if (arg == NULL)
- return NULL;
- }
- else if (!PyTuple_Check(arg)) {
- PyErr_SetString(PyExc_TypeError,
- "argument list must be a tuple");
- return NULL;
- }
- else
- Py_INCREF(arg);
-
- if (kw != NULL && !PyDict_Check(kw)) {
- PyErr_SetString(PyExc_TypeError,
- "keyword list must be a dictionary");
- Py_DECREF(arg);
- return NULL;
- }
-
- result = PyObject_Call(func, arg, kw);
- Py_DECREF(arg);
- return result;
-}
-
-const char *
-PyEval_GetFuncName(PyObject *func)
-{
- if (PyMethod_Check(func))
- return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func));
- else if (PyFunction_Check(func))
- return PyString_AsString(((PyFunctionObject*)func)->func_name);
- else if (PyCFunction_Check(func))
- return ((PyCFunctionObject*)func)->m_ml->ml_name;
- else if (PyClass_Check(func))
- return PyString_AsString(((PyClassObject*)func)->cl_name);
- else if (PyInstance_Check(func)) {
- return PyString_AsString(
- ((PyInstanceObject*)func)->in_class->cl_name);
- } else {
- return func->ob_type->tp_name;
- }
-}
-
-const char *
-PyEval_GetFuncDesc(PyObject *func)
-{
- if (PyMethod_Check(func))
- return "()";
- else if (PyFunction_Check(func))
- return "()";
- else if (PyCFunction_Check(func))
- return "()";
- else if (PyClass_Check(func))
- return " constructor";
- else if (PyInstance_Check(func)) {
- return " instance";
- } else {
- return " object";
- }
-}
-
-static void
-err_args(PyObject *func, int flags, int nargs)
-{
- if (flags & METH_NOARGS)
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%d given)",
- ((PyCFunctionObject *)func)->m_ml->ml_name,
- nargs);
- else
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes exactly one argument (%d given)",
- ((PyCFunctionObject *)func)->m_ml->ml_name,
- nargs);
-}
-
-#define C_TRACE(x, call) \
-if (tstate->use_tracing && tstate->c_profilefunc) { \
- if (call_trace(tstate->c_profilefunc, \
- tstate->c_profileobj, \
- tstate->frame, PyTrace_C_CALL, \
- func)) { \
- x = NULL; \
- } \
- else { \
- x = call; \
- if (tstate->c_profilefunc != NULL) { \
- if (x == NULL) { \
- call_trace_protected(tstate->c_profilefunc, \
- tstate->c_profileobj, \
- tstate->frame, PyTrace_C_EXCEPTION, \
- func); \
- /* XXX should pass (type, value, tb) */ \
- } else { \
- if (call_trace(tstate->c_profilefunc, \
- tstate->c_profileobj, \
- tstate->frame, PyTrace_C_RETURN, \
- func)) { \
- Py_DECREF(x); \
- x = NULL; \
- } \
- } \
- } \
- } \
-} else { \
- x = call; \
- }
-
-static PyObject *
-call_function(PyObject ***pp_stack, int oparg
-#ifdef WITH_TSC
- , uint64* pintr0, uint64* pintr1
-#endif
- )
-{
- int na = oparg & 0xff;
- int nk = (oparg>>8) & 0xff;
- int n = na + 2 * nk;
- PyObject **pfunc = (*pp_stack) - n - 1;
- PyObject *func = *pfunc;
- PyObject *x, *w;
-
- /* Always dispatch PyCFunction first, because these are
- presumed to be the most frequent callable object.
- */
- if (PyCFunction_Check(func) && nk == 0) {
- int flags = PyCFunction_GET_FLAGS(func);
- PyThreadState *tstate = PyThreadState_GET();
-
- PCALL(PCALL_CFUNCTION);
- if (flags & (METH_NOARGS | METH_O)) {
- PyCFunction meth = PyCFunction_GET_FUNCTION(func);
- PyObject *self = PyCFunction_GET_SELF(func);
- if (flags & METH_NOARGS && na == 0) {
- C_TRACE(x, (*meth)(self,NULL));
- }
- else if (flags & METH_O && na == 1) {
- PyObject *arg = EXT_POP(*pp_stack);
- C_TRACE(x, (*meth)(self,arg));
- Py_DECREF(arg);
- }
- else {
- err_args(func, flags, na);
- x = NULL;
- }
- }
- else {
- PyObject *callargs;
- callargs = load_args(pp_stack, na);
- READ_TIMESTAMP(*pintr0);
- C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
- READ_TIMESTAMP(*pintr1);
- Py_XDECREF(callargs);
- }
- } else {
- if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
- /* optimize access to bound methods */
- PyObject *self = PyMethod_GET_SELF(func);
- PCALL(PCALL_METHOD);
- PCALL(PCALL_BOUND_METHOD);
- Py_INCREF(self);
- func = PyMethod_GET_FUNCTION(func);
- Py_INCREF(func);
- Py_DECREF(*pfunc);
- *pfunc = self;
- na++;
- n++;
- } else
- Py_INCREF(func);
- READ_TIMESTAMP(*pintr0);
- if (PyFunction_Check(func))
- x = fast_function(func, pp_stack, n, na, nk);
- else
- x = do_call(func, pp_stack, na, nk);
- READ_TIMESTAMP(*pintr1);
- Py_DECREF(func);
- }
-
- /* Clear the stack of the function object. Also removes
- the arguments in case they weren't consumed already
- (fast_function() and err_args() leave them on the stack).
- */
- while ((*pp_stack) > pfunc) {
- w = EXT_POP(*pp_stack);
- Py_DECREF(w);
- PCALL(PCALL_POP);
- }
- return x;
-}
-
-/* The fast_function() function optimize calls for which no argument
- tuple is necessary; the objects are passed directly from the stack.
- For the simplest case -- a function that takes only positional
- arguments and is called with only positional arguments -- it
- inlines the most primitive frame setup code from
- PyEval_EvalCodeEx(), which vastly reduces the checks that must be
- done before evaluating the frame.
-*/
-
-static PyObject *
-fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
-{
- PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
- PyObject *globals = PyFunction_GET_GLOBALS(func);
- PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
- PyObject **d = NULL;
- int nd = 0;
-
- PCALL(PCALL_FUNCTION);
- PCALL(PCALL_FAST_FUNCTION);
- if (argdefs == NULL && co->co_argcount == n && nk==0 &&
- co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
- PyFrameObject *f;
- PyObject *retval = NULL;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject **fastlocals, **stack;
- int i;
-
- PCALL(PCALL_FASTER_FUNCTION);
- assert(globals != NULL);
- /* XXX Perhaps we should create a specialized
- PyFrame_New() that doesn't take locals, but does
- take builtins without sanity checking them.
- */
- assert(tstate != NULL);
- f = PyFrame_New(tstate, co, globals, NULL);
- if (f == NULL)
- return NULL;
-
- fastlocals = f->f_localsplus;
- stack = (*pp_stack) - n;
-
- for (i = 0; i < n; i++) {
- Py_INCREF(*stack);
- fastlocals[i] = *stack++;
- }
- retval = PyEval_EvalFrameEx(f,0);
- ++tstate->recursion_depth;
- Py_DECREF(f);
- --tstate->recursion_depth;
- return retval;
- }
- if (argdefs != NULL) {
- d = &PyTuple_GET_ITEM(argdefs, 0);
- nd = ((PyTupleObject *)argdefs)->ob_size;
- }
- return PyEval_EvalCodeEx(co, globals,
- (PyObject *)NULL, (*pp_stack)-n, na,
- (*pp_stack)-2*nk, nk, d, nd,
- PyFunction_GET_CLOSURE(func));
-}
-
-static PyObject *
-update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack,
- PyObject *func)
-{
- PyObject *kwdict = NULL;
- if (orig_kwdict == NULL)
- kwdict = PyDict_New();
- else {
- kwdict = PyDict_Copy(orig_kwdict);
- Py_DECREF(orig_kwdict);
- }
- if (kwdict == NULL)
- return NULL;
- while (--nk >= 0) {
- int err;
- PyObject *value = EXT_POP(*pp_stack);
- PyObject *key = EXT_POP(*pp_stack);
- if (PyDict_GetItem(kwdict, key) != NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s%s got multiple values "
- "for keyword argument '%.200s'",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func),
- PyString_AsString(key));
- Py_DECREF(key);
- Py_DECREF(value);
- Py_DECREF(kwdict);
- return NULL;
- }
- err = PyDict_SetItem(kwdict, key, value);
- Py_DECREF(key);
- Py_DECREF(value);
- if (err) {
- Py_DECREF(kwdict);
- return NULL;
- }
- }
- return kwdict;
-}
-
-static PyObject *
-update_star_args(int nstack, int nstar, PyObject *stararg,
- PyObject ***pp_stack)
-{
- PyObject *callargs, *w;
-
- callargs = PyTuple_New(nstack + nstar);
- if (callargs == NULL) {
- return NULL;
- }
- if (nstar) {
- int i;
- for (i = 0; i < nstar; i++) {
- PyObject *a = PyTuple_GET_ITEM(stararg, i);
- Py_INCREF(a);
- PyTuple_SET_ITEM(callargs, nstack + i, a);
- }
- }
- while (--nstack >= 0) {
- w = EXT_POP(*pp_stack);
- PyTuple_SET_ITEM(callargs, nstack, w);
- }
- return callargs;
-}
-
-static PyObject *
-load_args(PyObject ***pp_stack, int na)
-{
- PyObject *args = PyTuple_New(na);
- PyObject *w;
-
- if (args == NULL)
- return NULL;
- while (--na >= 0) {
- w = EXT_POP(*pp_stack);
- PyTuple_SET_ITEM(args, na, w);
- }
- return args;
-}
-
-static PyObject *
-do_call(PyObject *func, PyObject ***pp_stack, int na, int nk)
-{
- PyObject *callargs = NULL;
- PyObject *kwdict = NULL;
- PyObject *result = NULL;
-
- if (nk > 0) {
- kwdict = update_keyword_args(NULL, nk, pp_stack, func);
- if (kwdict == NULL)
- goto call_fail;
- }
- callargs = load_args(pp_stack, na);
- if (callargs == NULL)
- goto call_fail;
-#ifdef CALL_PROFILE
- /* At this point, we have to look at the type of func to
- update the call stats properly. Do it here so as to avoid
- exposing the call stats machinery outside ceval.c
- */
- if (PyFunction_Check(func))
- PCALL(PCALL_FUNCTION);
- else if (PyMethod_Check(func))
- PCALL(PCALL_METHOD);
- else if (PyType_Check(func))
- PCALL(PCALL_TYPE);
- else
- PCALL(PCALL_OTHER);
-#endif
- result = PyObject_Call(func, callargs, kwdict);
- call_fail:
- Py_XDECREF(callargs);
- Py_XDECREF(kwdict);
- return result;
-}
-
-static PyObject *
-ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
-{
- int nstar = 0;
- PyObject *callargs = NULL;
- PyObject *stararg = NULL;
- PyObject *kwdict = NULL;
- PyObject *result = NULL;
-
- if (flags & CALL_FLAG_KW) {
- kwdict = EXT_POP(*pp_stack);
- if (!(kwdict && PyDict_Check(kwdict))) {
- PyErr_Format(PyExc_TypeError,
- "%s%s argument after ** "
- "must be a dictionary",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func));
- goto ext_call_fail;
- }
- }
- if (flags & CALL_FLAG_VAR) {
- stararg = EXT_POP(*pp_stack);
- if (!PyTuple_Check(stararg)) {
- PyObject *t = NULL;
- t = PySequence_Tuple(stararg);
- if (t == NULL) {
- if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_Format(PyExc_TypeError,
- "%s%s argument after * "
- "must be a sequence",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func));
- }
- goto ext_call_fail;
- }
- Py_DECREF(stararg);
- stararg = t;
- }
- nstar = PyTuple_GET_SIZE(stararg);
- }
- if (nk > 0) {
- kwdict = update_keyword_args(kwdict, nk, pp_stack, func);
- if (kwdict == NULL)
- goto ext_call_fail;
- }
- callargs = update_star_args(na, nstar, stararg, pp_stack);
- if (callargs == NULL)
- goto ext_call_fail;
-#ifdef CALL_PROFILE
- /* At this point, we have to look at the type of func to
- update the call stats properly. Do it here so as to avoid
- exposing the call stats machinery outside ceval.c
- */
- if (PyFunction_Check(func))
- PCALL(PCALL_FUNCTION);
- else if (PyMethod_Check(func))
- PCALL(PCALL_METHOD);
- else if (PyType_Check(func))
- PCALL(PCALL_TYPE);
- else
- PCALL(PCALL_OTHER);
-#endif
- result = PyObject_Call(func, callargs, kwdict);
- ext_call_fail:
- Py_XDECREF(callargs);
- Py_XDECREF(kwdict);
- Py_XDECREF(stararg);
- return result;
-}
-
-/* Extract a slice index from a PyInt or PyLong or an object with the
- nb_index slot defined, and store in *pi.
- Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
- and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
- Return 0 on error, 1 on success.
-*/
-/* Note: If v is NULL, return success without storing into *pi. This
- is because_PyEval_SliceIndex() is called by apply_slice(), which can be
- called by the SLICE opcode with v and/or w equal to NULL.
-*/
-int
-_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
-{
- if (v != NULL) {
- Py_ssize_t x;
- if (PyInt_Check(v)) {
- /* XXX(nnorwitz): I think PyInt_AS_LONG is correct,
- however, it looks like it should be AsSsize_t.
- There should be a comment here explaining why.
- */
- x = PyInt_AS_LONG(v);
- }
- else if (PyIndex_Check(v)) {
- x = PyNumber_AsSsize_t(v, NULL);
- if (x == -1 && PyErr_Occurred())
- return 0;
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "slice indices must be integers or "
- "None or have an __index__ method");
- return 0;
- }
- *pi = x;
- }
- return 1;
-}
-
-#undef ISINDEX
-#define ISINDEX(x) ((x) == NULL || \
- PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x))
-
-static PyObject *
-apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
-{
- PyTypeObject *tp = u->ob_type;
- PySequenceMethods *sq = tp->tp_as_sequence;
-
- if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
- Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
- if (!_PyEval_SliceIndex(v, &ilow))
- return NULL;
- if (!_PyEval_SliceIndex(w, &ihigh))
- return NULL;
- return PySequence_GetSlice(u, ilow, ihigh);
- }
- else {
- PyObject *slice = PySlice_New(v, w, NULL);
- if (slice != NULL) {
- PyObject *res = PyObject_GetItem(u, slice);
- Py_DECREF(slice);
- return res;
- }
- else
- return NULL;
- }
-}
-
-static int
-assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
- /* u[v:w] = x */
-{
- PyTypeObject *tp = u->ob_type;
- PySequenceMethods *sq = tp->tp_as_sequence;
-
- if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
- Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
- if (!_PyEval_SliceIndex(v, &ilow))
- return -1;
- if (!_PyEval_SliceIndex(w, &ihigh))
- return -1;
- if (x == NULL)
- return PySequence_DelSlice(u, ilow, ihigh);
- else
- return PySequence_SetSlice(u, ilow, ihigh, x);
- }
- else {
- PyObject *slice = PySlice_New(v, w, NULL);
- if (slice != NULL) {
- int res;
- if (x != NULL)
- res = PyObject_SetItem(u, slice, x);
- else
- res = PyObject_DelItem(u, slice);
- Py_DECREF(slice);
- return res;
- }
- else
- return -1;
- }
-}
-
-static PyObject *
-cmp_outcome(int op, register PyObject *v, register PyObject *w)
-{
- int res = 0;
- switch (op) {
- case PyCmp_IS:
- res = (v == w);
- break;
- case PyCmp_IS_NOT:
- res = (v != w);
- break;
- case PyCmp_IN:
- res = PySequence_Contains(w, v);
- if (res < 0)
- return NULL;
- break;
- case PyCmp_NOT_IN:
- res = PySequence_Contains(w, v);
- if (res < 0)
- return NULL;
- res = !res;
- break;
- case PyCmp_EXC_MATCH:
- res = PyErr_GivenExceptionMatches(v, w);
- break;
- default:
- return PyObject_RichCompare(v, w, op);
- }
- v = res ? Py_True : Py_False;
- Py_INCREF(v);
- return v;
-}
-
-static PyObject *
-import_from(PyObject *v, PyObject *name)
-{
- PyObject *x;
-
- x = PyObject_GetAttr(v, name);
- if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Format(PyExc_ImportError,
- "cannot import name %.230s",
- PyString_AsString(name));
- }
- return x;
-}
-
-static int
-import_all_from(PyObject *locals, PyObject *v)
-{
- PyObject *all = PyObject_GetAttrString(v, "__all__");
- PyObject *dict, *name, *value;
- int skip_leading_underscores = 0;
- int pos, err;
-
- if (all == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1; /* Unexpected error */
- PyErr_Clear();
- dict = PyObject_GetAttrString(v, "__dict__");
- if (dict == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_SetString(PyExc_ImportError,
- "from-import-* object has no __dict__ and no __all__");
- return -1;
- }
- all = PyMapping_Keys(dict);
- Py_DECREF(dict);
- if (all == NULL)
- return -1;
- skip_leading_underscores = 1;
- }
-
- for (pos = 0, err = 0; ; pos++) {
- name = PySequence_GetItem(all, pos);
- if (name == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_IndexError))
- err = -1;
- else
- PyErr_Clear();
- break;
- }
- if (skip_leading_underscores &&
- PyString_Check(name) &&
- PyString_AS_STRING(name)[0] == '_')
- {
- Py_DECREF(name);
- continue;
- }
- value = PyObject_GetAttr(v, name);
- if (value == NULL)
- err = -1;
- else
- err = PyDict_SetItem(locals, name, value);
- Py_DECREF(name);
- Py_XDECREF(value);
- if (err != 0)
- break;
- }
- Py_DECREF(all);
- return err;
-}
-
-static PyObject *
-build_class(PyObject *methods, PyObject *bases, PyObject *name)
-{
- PyObject *metaclass = NULL, *result, *base;
-
- if (PyDict_Check(methods))
- metaclass = PyDict_GetItemString(methods, "__metaclass__");
- if (metaclass != NULL)
- Py_INCREF(metaclass);
- else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
- base = PyTuple_GET_ITEM(bases, 0);
- metaclass = PyObject_GetAttrString(base, "__class__");
- if (metaclass == NULL) {
- PyErr_Clear();
- metaclass = (PyObject *)base->ob_type;
- Py_INCREF(metaclass);
- }
- }
- else {
- PyObject *g = PyEval_GetGlobals();
- if (g != NULL && PyDict_Check(g))
- metaclass = PyDict_GetItemString(g, "__metaclass__");
- if (metaclass == NULL)
- metaclass = (PyObject *) &PyClass_Type;
- Py_INCREF(metaclass);
- }
- result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, NULL);
- Py_DECREF(metaclass);
- if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
- /* A type error here likely means that the user passed
- in a base that was not a class (such the random module
- instead of the random.random type). Help them out with
- by augmenting the error message with more information.*/
-
- PyObject *ptype, *pvalue, *ptraceback;
-
- PyErr_Fetch(&ptype, &pvalue, &ptraceback);
- if (PyString_Check(pvalue)) {
- PyObject *newmsg;
- newmsg = PyString_FromFormat(
- "Error when calling the metaclass bases\n %s",
- PyString_AS_STRING(pvalue));
- if (newmsg != NULL) {
- Py_DECREF(pvalue);
- pvalue = newmsg;
- }
- }
- PyErr_Restore(ptype, pvalue, ptraceback);
- }
- return result;
-}
-
-static int
-exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
- PyObject *locals)
-{
- int n;
- PyObject *v;
- int plain = 0;
-
- if (PyTuple_Check(prog) && globals == Py_None && locals == Py_None &&
- ((n = PyTuple_Size(prog)) == 2 || n == 3)) {
- /* Backward compatibility hack */
- globals = PyTuple_GetItem(prog, 1);
- if (n == 3)
- locals = PyTuple_GetItem(prog, 2);
- prog = PyTuple_GetItem(prog, 0);
- }
- if (globals == Py_None) {
- globals = PyEval_GetGlobals();
- if (locals == Py_None) {
- locals = PyEval_GetLocals();
- plain = 1;
- }
- if (!globals || !locals) {
- PyErr_SetString(PyExc_SystemError,
- "globals and locals cannot be NULL");
- return -1;
- }
- }
- else if (locals == Py_None)
- locals = globals;
- if (!PyString_Check(prog) &&
- !PyUnicode_Check(prog) &&
- !PyCode_Check(prog) &&
- !PyFile_Check(prog)) {
- PyErr_SetString(PyExc_TypeError,
- "exec: arg 1 must be a string, file, or code object");
- return -1;
- }
- if (!PyDict_Check(globals)) {
- PyErr_SetString(PyExc_TypeError,
- "exec: arg 2 must be a dictionary or None");
- return -1;
- }
- if (!PyMapping_Check(locals)) {
- PyErr_SetString(PyExc_TypeError,
- "exec: arg 3 must be a mapping or None");
- return -1;
- }
- if (PyDict_GetItemString(globals, "__builtins__") == NULL)
- PyDict_SetItemString(globals, "__builtins__", f->f_builtins);
- if (PyCode_Check(prog)) {
- if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
- PyErr_SetString(PyExc_TypeError,
- "code object passed to exec may not contain free variables");
- return -1;
- }
- v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
- }
- else if (PyFile_Check(prog)) {
- FILE *fp = PyFile_AsFile(prog);
- char *name = PyString_AsString(PyFile_Name(prog));
- PyCompilerFlags cf;
- cf.cf_flags = 0;
- if (PyEval_MergeCompilerFlags(&cf))
- v = PyRun_FileFlags(fp, name, Py_file_input, globals,
- locals, &cf);
- else
- v = PyRun_File(fp, name, Py_file_input, globals,
- locals);
- }
- else {
- PyObject *tmp = NULL;
- char *str;
- PyCompilerFlags cf;
- cf.cf_flags = 0;
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(prog)) {
- tmp = PyUnicode_AsUTF8String(prog);
- if (tmp == NULL)
- return -1;
- prog = tmp;
- cf.cf_flags |= PyCF_SOURCE_IS_UTF8;
- }
-#endif
- if (PyString_AsStringAndSize(prog, &str, NULL))
- return -1;
- if (PyEval_MergeCompilerFlags(&cf))
- v = PyRun_StringFlags(str, Py_file_input, globals,
- locals, &cf);
- else
- v = PyRun_String(str, Py_file_input, globals, locals);
- Py_XDECREF(tmp);
- }
- if (plain)
- PyFrame_LocalsToFast(f, 0);
- if (v == NULL)
- return -1;
- Py_DECREF(v);
- return 0;
-}
-
-static void
-format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj)
-{
- char *obj_str;
-
- if (!obj)
- return;
-
- obj_str = PyString_AsString(obj);
- if (!obj_str)
- return;
-
- PyErr_Format(exc, format_str, obj_str);
-}
-
-static PyObject *
-string_concatenate(PyObject *v, PyObject *w,
- PyFrameObject *f, unsigned char *next_instr)
-{
- /* This function implements 'variable += expr' when both arguments
- are strings. */
- Py_ssize_t v_len = PyString_GET_SIZE(v);
- Py_ssize_t w_len = PyString_GET_SIZE(w);
- Py_ssize_t new_len = v_len + w_len;
- if (new_len < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "strings are too large to concat");
- return NULL;
- }
-
- if (v->ob_refcnt == 2) {
- /* In the common case, there are 2 references to the value
- * stored in 'variable' when the += is performed: one on the
- * value stack (in 'v') and one still stored in the 'variable'.
- * We try to delete the variable now to reduce the refcnt to 1.
- */
- switch (*next_instr) {
- case STORE_FAST:
- {
- int oparg = PEEKARG();
- PyObject **fastlocals = f->f_localsplus;
- if (GETLOCAL(oparg) == v)
- SETLOCAL(oparg, NULL);
- break;
- }
- case STORE_DEREF:
- {
- PyObject **freevars = f->f_localsplus + f->f_code->co_nlocals;
- PyObject *c = freevars[PEEKARG()];
- if (PyCell_GET(c) == v)
- PyCell_Set(c, NULL);
- break;
- }
- case STORE_NAME:
- {
- PyObject *names = f->f_code->co_names;
- PyObject *name = GETITEM(names, PEEKARG());
- PyObject *locals = f->f_locals;
- if (PyDict_CheckExact(locals) &&
- PyDict_GetItem(locals, name) == v) {
- if (PyDict_DelItem(locals, name) != 0) {
- PyErr_Clear();
- }
- }
- break;
- }
- }
- }
-
- if (v->ob_refcnt == 1 && !PyString_CHECK_INTERNED(v)) {
- /* Now we own the last reference to 'v', so we can resize it
- * in-place.
- */
- if (_PyString_Resize(&v, new_len) != 0) {
- /* XXX if _PyString_Resize() fails, 'v' has been
- * deallocated so it cannot be put back into 'variable'.
- * The MemoryError is raised when there is no value in
- * 'variable', which might (very remotely) be a cause
- * of incompatibilities.
- */
- return NULL;
- }
- /* copy 'w' into the newly allocated area of 'v' */
- memcpy(PyString_AS_STRING(v) + v_len,
- PyString_AS_STRING(w), w_len);
- return v;
- }
- else {
- /* When in-place resizing is not an option. */
- PyString_Concat(&v, w);
- return v;
- }
-}
-
-#ifdef DYNAMIC_EXECUTION_PROFILE
-
-static PyObject *
-getarray(long a[256])
-{
- int i;
- PyObject *l = PyList_New(256);
- if (l == NULL) return NULL;
- for (i = 0; i < 256; i++) {
- PyObject *x = PyInt_FromLong(a[i]);
- if (x == NULL) {
- Py_DECREF(l);
- return NULL;
- }
- PyList_SetItem(l, i, x);
- }
- for (i = 0; i < 256; i++)
- a[i] = 0;
- return l;
-}
-
-PyObject *
-_Py_GetDXProfile(PyObject *self, PyObject *args)
-{
-#ifndef DXPAIRS
- return getarray(dxp);
-#else
- int i;
- PyObject *l = PyList_New(257);
- if (l == NULL) return NULL;
- for (i = 0; i < 257; i++) {
- PyObject *x = getarray(dxpairs[i]);
- if (x == NULL) {
- Py_DECREF(l);
- return NULL;
- }
- PyList_SetItem(l, i, x);
- }
- return l;
-#endif
-}
-
-#endif
diff --git a/tests/examplefiles/example.c b/tests/examplefiles/example.c
index 9f9c477d..67b8d17d 100644
--- a/tests/examplefiles/example.c
+++ b/tests/examplefiles/example.c
@@ -4507,5337 +4507,3 @@ bigsub(x, y)
return z;
}
-static VALUE
-bigadd(x, y, sign)
- VALUE x, y;
- char sign;
-{
- VALUE z;
- BDIGIT_DBL num;
- long i, len;
-
- sign = (sign == RBIGNUM(y)->sign);
- if (RBIGNUM(x)->sign != sign) {
- if (sign) return bigsub(y, x);
- return bigsub(x, y);
- }
-
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- len = RBIGNUM(x)->len + 1;
- z = x; x = y; y = z;
- }
- else {
- len = RBIGNUM(y)->len + 1;
- }
- z = bignew(len, sign);
-
- len = RBIGNUM(x)->len;
- for (i = 0, num = 0; i < len; i++) {
- num += (BDIGIT_DBL)BDIGITS(x)[i] + BDIGITS(y)[i];
- BDIGITS(z)[i] = BIGLO(num);
- num = BIGDN(num);
- }
- len = RBIGNUM(y)->len;
- while (num && i < len) {
- num += BDIGITS(y)[i];
- BDIGITS(z)[i++] = BIGLO(num);
- num = BIGDN(num);
- }
- while (i < len) {
- BDIGITS(z)[i] = BDIGITS(y)[i];
- i++;
- }
- BDIGITS(z)[i] = (BDIGIT)num;
-
- return z;
-}
-
-/*
- * call-seq:
- * big + other => Numeric
- *
- * Adds big and other, returning the result.
- */
-
-VALUE
-rb_big_plus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- /* fall through */
- case T_BIGNUM:
- return bignorm(bigadd(x, y, 1));
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) + RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * big - other => Numeric
- *
- * Subtracts other from big, returning the result.
- */
-
-VALUE
-rb_big_minus(x, y)
- VALUE x, y;
-{
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- /* fall through */
- case T_BIGNUM:
- return bignorm(bigadd(x, y, 0));
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) - RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
-}
-
-/*
- * call-seq:
- * big * other => Numeric
- *
- * Multiplies big and other, returning the result.
- */
-
-VALUE
-rb_big_mul(x, y)
- VALUE x, y;
-{
- long i, j;
- BDIGIT_DBL n = 0;
- VALUE z;
- BDIGIT *zds;
-
- if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x));
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) * RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
-
- j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1;
- z = bignew(j, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
- zds = BDIGITS(z);
- while (j--) zds[j] = 0;
- for (i = 0; i < RBIGNUM(x)->len; i++) {
- BDIGIT_DBL dd = BDIGITS(x)[i];
- if (dd == 0) continue;
- n = 0;
- for (j = 0; j < RBIGNUM(y)->len; j++) {
- BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * BDIGITS(y)[j];
- n = zds[i + j] + ee;
- if (ee) zds[i + j] = BIGLO(n);
- n = BIGDN(n);
- }
- if (n) {
- zds[i + j] = n;
- }
- }
-
- return bignorm(z);
-}
-
-static void
-bigdivrem(x, y, divp, modp)
- VALUE x, y;
- VALUE *divp, *modp;
-{
- long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
- long i, j;
- VALUE yy, z;
- BDIGIT *xds, *yds, *zds, *tds;
- BDIGIT_DBL t2;
- BDIGIT_DBL_SIGNED num;
- BDIGIT dd, q;
-
- if (BIGZEROP(y)) rb_num_zerodiv();
- yds = BDIGITS(y);
- if (nx < ny || (nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1])) {
- if (divp) *divp = rb_int2big(0);
- if (modp) *modp = x;
- return;
- }
- xds = BDIGITS(x);
- if (ny == 1) {
- dd = yds[0];
- z = rb_big_clone(x);
- zds = BDIGITS(z);
- t2 = 0; i = nx;
- while (i--) {
- t2 = BIGUP(t2) + zds[i];
- zds[i] = (BDIGIT)(t2 / dd);
- t2 %= dd;
- }
- RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
- if (modp) {
- *modp = rb_uint2big((unsigned long)t2);
- RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
- }
- if (divp) *divp = z;
- return;
- }
- z = bignew(nx==ny?nx+2:nx+1, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
- zds = BDIGITS(z);
- if (nx==ny) zds[nx+1] = 0;
- while (!yds[ny-1]) ny--;
-
- dd = 0;
- q = yds[ny-1];
- while ((q & (1<<(BITSPERDIG-1))) == 0) {
- q <<= 1;
- dd++;
- }
- if (dd) {
- yy = rb_big_clone(y);
- tds = BDIGITS(yy);
- j = 0;
- t2 = 0;
- while (j<ny) {
- t2 += (BDIGIT_DBL)yds[j]<<dd;
- tds[j++] = BIGLO(t2);
- t2 = BIGDN(t2);
- }
- yds = tds;
- j = 0;
- t2 = 0;
- while (j<nx) {
- t2 += (BDIGIT_DBL)xds[j]<<dd;
- zds[j++] = BIGLO(t2);
- t2 = BIGDN(t2);
- }
- zds[j] = (BDIGIT)t2;
- }
- else {
- zds[nx] = 0;
- j = nx;
- while (j--) zds[j] = xds[j];
- }
-
- j = nx==ny?nx+1:nx;
- do {
- if (zds[j] == yds[ny-1]) q = BIGRAD-1;
- else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
- if (q) {
- i = 0; num = 0; t2 = 0;
- do { /* multiply and subtract */
- BDIGIT_DBL ee;
- t2 += (BDIGIT_DBL)yds[i] * q;
- ee = num - BIGLO(t2);
- num = (BDIGIT_DBL)zds[j - ny + i] + ee;
- if (ee) zds[j - ny + i] = BIGLO(num);
- num = BIGDN(num);
- t2 = BIGDN(t2);
- } while (++i < ny);
- num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */
- while (num) { /* "add back" required */
- i = 0; num = 0; q--;
- do {
- BDIGIT_DBL ee = num + yds[i];
- num = (BDIGIT_DBL)zds[j - ny + i] + ee;
- if (ee) zds[j - ny + i] = BIGLO(num);
- num = BIGDN(num);
- } while (++i < ny);
- num--;
- }
- }
- zds[j] = q;
- } while (--j >= ny);
- if (divp) { /* move quotient down in z */
- *divp = rb_big_clone(z);
- zds = BDIGITS(*divp);
- j = (nx==ny ? nx+2 : nx+1) - ny;
- for (i = 0;i < j;i++) zds[i] = zds[i+ny];
- RBIGNUM(*divp)->len = i;
- }
- if (modp) { /* normalize remainder */
- *modp = rb_big_clone(z);
- zds = BDIGITS(*modp);
- while (--ny && !zds[ny]); ++ny;
- if (dd) {
- t2 = 0; i = ny;
- while(i--) {
- t2 = (t2 | zds[i]) >> dd;
- q = zds[i];
- zds[i] = BIGLO(t2);
- t2 = BIGUP(q);
- }
- }
- RBIGNUM(*modp)->len = ny;
- RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
- }
-}
-
-static void
-bigdivmod(x, y, divp, modp)
- VALUE x, y;
- VALUE *divp, *modp;
-{
- VALUE mod;
-
- bigdivrem(x, y, divp, &mod);
- if (RBIGNUM(x)->sign != RBIGNUM(y)->sign && !BIGZEROP(mod)) {
- if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
- if (modp) *modp = bigadd(mod, y, 1);
- }
- else {
- if (divp) *divp = *divp;
- if (modp) *modp = mod;
- }
-}
-
-/*
- * call-seq:
- * big / other => Numeric
- * big.div(other) => Numeric
- *
- * Divides big by other, returning the result.
- */
-
-static VALUE
-rb_big_div(x, y)
- VALUE x, y;
-{
- VALUE z;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) / RFLOAT(y)->value);
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivmod(x, y, &z, 0);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big % other => Numeric
- * big.modulo(other) => Numeric
- *
- * Returns big modulo other. See Numeric.divmod for more
- * information.
- */
-
-static VALUE
-rb_big_modulo(x, y)
- VALUE x, y;
-{
- VALUE z;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivmod(x, y, 0, &z);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big.remainder(numeric) => number
- *
- * Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
- *
- * -1234567890987654321.remainder(13731) #=> -6966
- * -1234567890987654321.remainder(13731.24) #=> -9906.22531493148
- */
-static VALUE
-rb_big_remainder(x, y)
- VALUE x, y;
-{
- VALUE z;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivrem(x, y, 0, &z);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big.divmod(numeric) => array
- *
- * See <code>Numeric#divmod</code>.
- *
- */
-VALUE
-rb_big_divmod(x, y)
- VALUE x, y;
-{
- VALUE div, mod;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- y = rb_int2big(FIX2LONG(y));
- break;
-
- case T_BIGNUM:
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- bigdivmod(x, y, &div, &mod);
-
- return rb_assoc_new(bignorm(div), bignorm(mod));
-}
-
-/*
- * call-seq:
- * big.quo(numeric) -> float
- *
- * Returns the floating point result of dividing <i>big</i> by
- * <i>numeric</i>.
- *
- * -1234567890987654321.quo(13731) #=> -89910996357705.5
- * -1234567890987654321.quo(13731.24) #=> -89909424858035.7
- *
- */
-
-static VALUE
-rb_big_quo(x, y)
- VALUE x, y;
-{
- double dx = rb_big2dbl(x);
- double dy;
-
- switch (TYPE(y)) {
- case T_FIXNUM:
- dy = (double)FIX2LONG(y);
- break;
-
- case T_BIGNUM:
- dy = rb_big2dbl(y);
- break;
-
- case T_FLOAT:
- dy = RFLOAT(y)->value;
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- return rb_float_new(dx / dy);
-}
-
-/*
- * call-seq:
- * big ** exponent #=> numeric
- *
- * Raises _big_ to the _exponent_ power (which may be an integer, float,
- * or anything that will coerce to a number). The result may be
- * a Fixnum, Bignum, or Float
- *
- * 123456789 ** 2 #=> 15241578750190521
- * 123456789 ** 1.2 #=> 5126464716.09932
- * 123456789 ** -2 #=> 6.5610001194102e-17
- */
-
-VALUE
-rb_big_pow(x, y)
- VALUE x, y;
-{
- double d;
- long yy;
-
- if (y == INT2FIX(0)) return INT2FIX(1);
- switch (TYPE(y)) {
- case T_FLOAT:
- d = RFLOAT(y)->value;
- break;
-
- case T_BIGNUM:
- rb_warn("in a**b, b may be too big");
- d = rb_big2dbl(y);
- break;
-
- case T_FIXNUM:
- yy = FIX2LONG(y);
- if (yy > 0) {
- VALUE z = x;
-
- for (;;) {
- yy -= 1;
- if (yy == 0) break;
- while (yy % 2 == 0) {
- yy /= 2;
- x = rb_big_mul(x, x);
- }
- z = rb_big_mul(z, x);
- }
- return bignorm(z);
- }
- d = (double)yy;
- break;
-
- default:
- return rb_num_coerce_bin(x, y);
- }
- return rb_float_new(pow(rb_big2dbl(x), d));
-}
-
-/*
- * call-seq:
- * big & numeric => integer
- *
- * Performs bitwise +and+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_and(xx, yy)
- VALUE xx, yy;
-{
- volatile VALUE x, y, z;
- BDIGIT *ds1, *ds2, *zds;
- long i, l1, l2;
- char sign;
-
- x = xx;
- y = rb_to_int(yy);
- if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
- }
- if (!RBIGNUM(y)->sign) {
- y = rb_big_clone(y);
- get2comp(y, Qtrue);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- l1 = RBIGNUM(y)->len;
- l2 = RBIGNUM(x)->len;
- ds1 = BDIGITS(y);
- ds2 = BDIGITS(x);
- sign = RBIGNUM(y)->sign;
- }
- else {
- l1 = RBIGNUM(x)->len;
- l2 = RBIGNUM(y)->len;
- ds1 = BDIGITS(x);
- ds2 = BDIGITS(y);
- sign = RBIGNUM(x)->sign;
- }
- z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
- zds = BDIGITS(z);
-
- for (i=0; i<l1; i++) {
- zds[i] = ds1[i] & ds2[i];
- }
- for (; i<l2; i++) {
- zds[i] = sign?0:ds2[i];
- }
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big | numeric => integer
- *
- * Performs bitwise +or+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_or(xx, yy)
- VALUE xx, yy;
-{
- volatile VALUE x, y, z;
- BDIGIT *ds1, *ds2, *zds;
- long i, l1, l2;
- char sign;
-
- x = xx;
- y = rb_to_int(yy);
- if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
- }
-
- if (!RBIGNUM(y)->sign) {
- y = rb_big_clone(y);
- get2comp(y, Qtrue);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- l1 = RBIGNUM(y)->len;
- l2 = RBIGNUM(x)->len;
- ds1 = BDIGITS(y);
- ds2 = BDIGITS(x);
- sign = RBIGNUM(y)->sign;
- }
- else {
- l1 = RBIGNUM(x)->len;
- l2 = RBIGNUM(y)->len;
- ds1 = BDIGITS(x);
- ds2 = BDIGITS(y);
- sign = RBIGNUM(x)->sign;
- }
- z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
- zds = BDIGITS(z);
-
- for (i=0; i<l1; i++) {
- zds[i] = ds1[i] | ds2[i];
- }
- for (; i<l2; i++) {
- zds[i] = sign?ds2[i]:(BIGRAD-1);
- }
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
-
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big ^ numeric => integer
- *
- * Performs bitwise +exclusive or+ between _big_ and _numeric_.
- */
-
-VALUE
-rb_big_xor(xx, yy)
- VALUE xx, yy;
-{
- volatile VALUE x, y;
- VALUE z;
- BDIGIT *ds1, *ds2, *zds;
- long i, l1, l2;
- char sign;
-
- x = xx;
- y = rb_to_int(yy);
- if (FIXNUM_P(y)) {
- y = rb_int2big(FIX2LONG(y));
- }
-
- if (!RBIGNUM(y)->sign) {
- y = rb_big_clone(y);
- get2comp(y, Qtrue);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
- l1 = RBIGNUM(y)->len;
- l2 = RBIGNUM(x)->len;
- ds1 = BDIGITS(y);
- ds2 = BDIGITS(x);
- sign = RBIGNUM(y)->sign;
- }
- else {
- l1 = RBIGNUM(x)->len;
- l2 = RBIGNUM(y)->len;
- ds1 = BDIGITS(x);
- ds2 = BDIGITS(y);
- sign = RBIGNUM(x)->sign;
- }
- RBIGNUM(x)->sign = RBIGNUM(x)->sign?1:0;
- RBIGNUM(y)->sign = RBIGNUM(y)->sign?1:0;
- z = bignew(l2, !(RBIGNUM(x)->sign ^ RBIGNUM(y)->sign));
- zds = BDIGITS(z);
-
- for (i=0; i<l1; i++) {
- zds[i] = ds1[i] ^ ds2[i];
- }
- for (; i<l2; i++) {
- zds[i] = sign?ds2[i]:~ds2[i];
- }
- if (!RBIGNUM(z)->sign) get2comp(z, Qfalse);
-
- return bignorm(z);
-}
-
-static VALUE rb_big_rshift _((VALUE,VALUE));
-
-/*
- * call-seq:
- * big << numeric => integer
- *
- * Shifts big left _numeric_ positions (right if _numeric_ is negative).
- */
-
-VALUE
-rb_big_lshift(x, y)
- VALUE x, y;
-{
- BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
- int s1 = shift/BITSPERDIG;
- int s2 = shift%BITSPERDIG;
- VALUE z;
- BDIGIT_DBL num = 0;
- long len, i;
-
- if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
- len = RBIGNUM(x)->len;
- z = bignew(len+s1+1, RBIGNUM(x)->sign);
- zds = BDIGITS(z);
- for (i=0; i<s1; i++) {
- *zds++ = 0;
- }
- xds = BDIGITS(x);
- for (i=0; i<len; i++) {
- num = num | (BDIGIT_DBL)*xds++<<s2;
- *zds++ = BIGLO(num);
- num = BIGDN(num);
- }
- *zds = BIGLO(num);
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big >> numeric => integer
- *
- * Shifts big right _numeric_ positions (left if _numeric_ is negative).
- */
-
-static VALUE
-rb_big_rshift(x, y)
- VALUE x, y;
-{
- BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
- long s1 = shift/BITSPERDIG;
- long s2 = shift%BITSPERDIG;
- VALUE z;
- BDIGIT_DBL num = 0;
- long i, j;
-
- if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
-
- if (s1 > RBIGNUM(x)->len) {
- if (RBIGNUM(x)->sign)
- return INT2FIX(0);
- else
- return INT2FIX(-1);
- }
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- xds = BDIGITS(x);
- i = RBIGNUM(x)->len; j = i - s1;
- z = bignew(j, RBIGNUM(x)->sign);
- if (!RBIGNUM(x)->sign) {
- num = ((BDIGIT_DBL)~0) << BITSPERDIG;
- }
- zds = BDIGITS(z);
- while (i--, j--) {
- num = (num | xds[i]) >> s2;
- zds[j] = BIGLO(num);
- num = BIGUP(xds[i]);
- }
- if (!RBIGNUM(x)->sign) {
- get2comp(z, Qfalse);
- }
- return bignorm(z);
-}
-
-/*
- * call-seq:
- * big[n] -> 0, 1
- *
- * Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
- * representation of <i>big</i>, where <i>big</i>[0] is the least
- * significant bit.
- *
- * a = 9**15
- * 50.downto(0) do |n|
- * print a[n]
- * end
- *
- * <em>produces:</em>
- *
- * 000101110110100000111000011110010100111100010111001
- *
- */
-
-static VALUE
-rb_big_aref(x, y)
- VALUE x, y;
-{
- BDIGIT *xds;
- int shift;
- long s1, s2;
-
- if (TYPE(y) == T_BIGNUM) {
- if (!RBIGNUM(y)->sign || RBIGNUM(x)->sign)
- return INT2FIX(0);
- return INT2FIX(1);
- }
- shift = NUM2INT(y);
- if (shift < 0) return INT2FIX(0);
- s1 = shift/BITSPERDIG;
- s2 = shift%BITSPERDIG;
-
- if (!RBIGNUM(x)->sign) {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = rb_big_clone(x);
- get2comp(x, Qtrue);
- }
- else {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
- }
- xds = BDIGITS(x);
- if (xds[s1] & (1<<s2))
- return INT2FIX(1);
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * big.hash => fixnum
- *
- * Compute a hash based on the value of _big_.
- */
-
-static VALUE
-rb_big_hash(x)
- VALUE x;
-{
- long i, len, key;
- BDIGIT *digits;
-
- key = 0; digits = BDIGITS(x); len = RBIGNUM(x)->len;
- for (i=0; i<len; i++) {
- key ^= *digits++;
- }
- return LONG2FIX(key);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_big_coerce(x, y)
- VALUE x, y;
-{
- if (FIXNUM_P(y)) {
- return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
- }
- else {
- rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
- rb_obj_classname(y));
- }
- /* not reached */
- return Qnil;
-}
-
-/*
- * call-seq:
- * big.abs -> aBignum
- *
- * Returns the absolute value of <i>big</i>.
- *
- * -1234567890987654321.abs #=> 1234567890987654321
- */
-
-static VALUE
-rb_big_abs(x)
- VALUE x;
-{
- if (!RBIGNUM(x)->sign) {
- x = rb_big_clone(x);
- RBIGNUM(x)->sign = 1;
- }
- return x;
-}
-
-VALUE
-rb_big_rand(max, rand_buf)
- VALUE max;
- double *rand_buf;
-{
- VALUE v;
- long len = RBIGNUM(max)->len;
-
- if (BIGZEROP(max)) {
- return rb_float_new(rand_buf[0]);
- }
- v = bignew(len,1);
- len--;
- BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
- while (len--) {
- BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
- }
-
- return v;
-}
-
-/*
- * call-seq:
- * big.size -> integer
- *
- * Returns the number of bytes in the machine representation of
- * <i>big</i>.
- *
- * (256**10 - 1).size #=> 12
- * (256**20 - 1).size #=> 20
- * (256**40 - 1).size #=> 40
- */
-
-static VALUE
-rb_big_size(big)
- VALUE big;
-{
- return LONG2FIX(RBIGNUM(big)->len*SIZEOF_BDIGITS);
-}
-
-/*
- * Bignum objects hold integers outside the range of
- * Fixnum. Bignum objects are created
- * automatically when integer calculations would otherwise overflow a
- * Fixnum. When a calculation involving
- * Bignum objects returns a result that will fit in a
- * Fixnum, the result is automatically converted.
- *
- * For the purposes of the bitwise operations and <code>[]</code>, a
- * Bignum is treated as if it were an infinite-length
- * bitstring with 2's complement representation.
- *
- * While Fixnum values are immediate, Bignum
- * objects are not---assignment and parameter passing work with
- * references to objects, not the objects themselves.
- *
- */
-
-void
-Init_Bignum()
-{
- rb_cBignum = rb_define_class("Bignum", rb_cInteger);
-
- rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
- rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
- rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
- rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
- rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
- rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
- rb_define_method(rb_cBignum, "/", rb_big_div, 1);
- rb_define_method(rb_cBignum, "%", rb_big_modulo, 1);
- rb_define_method(rb_cBignum, "div", rb_big_div, 1);
- rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
- rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
- rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
- rb_define_method(rb_cBignum, "quo", rb_big_quo, 1);
- rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
- rb_define_method(rb_cBignum, "&", rb_big_and, 1);
- rb_define_method(rb_cBignum, "|", rb_big_or, 1);
- rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
- rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
- rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
- rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
- rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
-
- rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
- rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
- rb_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
- rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
- rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
- rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
- rb_define_method(rb_cBignum, "size", rb_big_size, 0);
-}
-/**********************************************************************
-
- class.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Tue Aug 10 15:05:44 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "rubysig.h"
-#include "node.h"
-#include "st.h"
-#include <ctype.h>
-
-extern st_table *rb_class_tbl;
-
-VALUE
-rb_class_boot(super)
- VALUE super;
-{
- NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, rb_cClass, T_CLASS);
-
- klass->super = super;
- klass->iv_tbl = 0;
- klass->m_tbl = 0; /* safe GC */
- klass->m_tbl = st_init_numtable();
-
- OBJ_INFECT(klass, super);
- return (VALUE)klass;
-}
-
-void
-rb_check_inheritable(super)
- VALUE super;
-{
- if (TYPE(super) != T_CLASS) {
- rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
- rb_obj_classname(super));
- }
- if (RBASIC(super)->flags & FL_SINGLETON) {
- rb_raise(rb_eTypeError, "can't make subclass of singleton class");
- }
-}
-
-VALUE
-rb_class_new(super)
- VALUE super;
-{
- Check_Type(super, T_CLASS);
- rb_check_inheritable(super);
- if (super == rb_cClass) {
- rb_raise(rb_eTypeError, "can't make subclass of Class");
- }
- return rb_class_boot(super);
-}
-
-static int
-clone_method(mid, body, tbl)
- ID mid;
- NODE *body;
- st_table *tbl;
-{
- st_insert(tbl, mid, (st_data_t)NEW_METHOD(body->nd_body, body->nd_noex));
- return ST_CONTINUE;
-}
-
-/* :nodoc: */
-VALUE
-rb_mod_init_copy(clone, orig)
- VALUE clone, orig;
-{
- rb_obj_init_copy(clone, orig);
- if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC(clone)->klass = rb_singleton_class_clone(orig);
- }
- RCLASS(clone)->super = RCLASS(orig)->super;
- if (RCLASS(orig)->iv_tbl) {
- ID id;
-
- RCLASS(clone)->iv_tbl = st_copy(RCLASS(orig)->iv_tbl);
- id = rb_intern("__classpath__");
- st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
- id = rb_intern("__classid__");
- st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
- }
- if (RCLASS(orig)->m_tbl) {
- RCLASS(clone)->m_tbl = st_init_numtable();
- st_foreach(RCLASS(orig)->m_tbl, clone_method,
- (st_data_t)RCLASS(clone)->m_tbl);
- }
-
- return clone;
-}
-
-/* :nodoc: */
-VALUE
-rb_class_init_copy(clone, orig)
- VALUE clone, orig;
-{
- if (RCLASS(clone)->super != 0) {
- rb_raise(rb_eTypeError, "already initialized class");
- }
- return rb_mod_init_copy(clone, orig);
-}
-
-VALUE
-rb_singleton_class_clone(obj)
- VALUE obj;
-{
- VALUE klass = RBASIC(obj)->klass;
-
- if (!FL_TEST(klass, FL_SINGLETON))
- return klass;
- else {
- /* copy singleton(unnamed) class */
- NEWOBJ(clone, struct RClass);
- OBJSETUP(clone, 0, RBASIC(klass)->flags);
-
- if (BUILTIN_TYPE(obj) == T_CLASS) {
- RBASIC(clone)->klass = (VALUE)clone;
- }
- else {
- RBASIC(clone)->klass = rb_singleton_class_clone(klass);
- }
-
- clone->super = RCLASS(klass)->super;
- clone->iv_tbl = 0;
- clone->m_tbl = 0;
- if (RCLASS(klass)->iv_tbl) {
- clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
- }
- clone->m_tbl = st_init_numtable();
- st_foreach(RCLASS(klass)->m_tbl, clone_method,
- (st_data_t)clone->m_tbl);
- rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
- FL_SET(clone, FL_SINGLETON);
- return (VALUE)clone;
- }
-}
-
-void
-rb_singleton_class_attached(klass, obj)
- VALUE klass, obj;
-{
- if (FL_TEST(klass, FL_SINGLETON)) {
- if (!RCLASS(klass)->iv_tbl) {
- RCLASS(klass)->iv_tbl = st_init_numtable();
- }
- st_insert(RCLASS(klass)->iv_tbl, rb_intern("__attached__"), obj);
- }
-}
-
-VALUE
-rb_make_metaclass(obj, super)
- VALUE obj, super;
-{
- if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
- return RBASIC(obj)->klass = rb_cClass;
- }
- else {
- VALUE metasuper;
- VALUE klass = rb_class_boot(super);
-
- FL_SET(klass, FL_SINGLETON);
- RBASIC(obj)->klass = klass;
- rb_singleton_class_attached(klass, obj);
-
- metasuper = RBASIC(rb_class_real(super))->klass;
- /* metaclass of a superclass may be NULL at boot time */
- if (metasuper) {
- RBASIC(klass)->klass = metasuper;
- }
- return klass;
- }
-}
-
-VALUE
-rb_define_class_id(id, super)
- ID id;
- VALUE super;
-{
- VALUE klass;
-
- if (!super) super = rb_cObject;
- klass = rb_class_new(super);
- rb_make_metaclass(klass, RBASIC(super)->klass);
-
- return klass;
-}
-
-VALUE
-rb_class_inherited(super, klass)
- VALUE super, klass;
-{
- if (!super) super = rb_cObject;
- return rb_funcall(super, rb_intern("inherited"), 1, klass);
-}
-
-VALUE
-rb_define_class(name, super)
- const char *name;
- VALUE super;
-{
- VALUE klass;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined(rb_cObject, id)) {
- klass = rb_const_get(rb_cObject, id);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class", name);
- }
- if (rb_class_real(RCLASS(klass)->super) != super) {
- rb_name_error(id, "%s is already defined", name);
- }
- return klass;
- }
- if (!super) {
- rb_warn("no super class for `%s', Object assumed", name);
- }
- klass = rb_define_class_id(id, super);
- st_add_direct(rb_class_tbl, id, klass);
- rb_name_class(klass, id);
- rb_const_set(rb_cObject, id, klass);
- rb_class_inherited(super, klass);
-
- return klass;
-}
-
-VALUE
-rb_define_class_under(outer, name, super)
- VALUE outer;
- const char *name;
- VALUE super;
-{
- VALUE klass;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined_at(outer, id)) {
- klass = rb_const_get_at(outer, id);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class", name);
- }
- if (rb_class_real(RCLASS(klass)->super) != super) {
- rb_name_error(id, "%s is already defined", name);
- }
- return klass;
- }
- if (!super) {
- rb_warn("no super class for `%s::%s', Object assumed",
- rb_class2name(outer), name);
- }
- klass = rb_define_class_id(id, super);
- rb_set_class_path(klass, outer, name);
- rb_const_set(outer, id, klass);
- rb_class_inherited(super, klass);
-
- return klass;
-}
-
-VALUE
-rb_module_new()
-{
- NEWOBJ(mdl, struct RClass);
- OBJSETUP(mdl, rb_cModule, T_MODULE);
-
- mdl->super = 0;
- mdl->iv_tbl = 0;
- mdl->m_tbl = 0;
- mdl->m_tbl = st_init_numtable();
-
- return (VALUE)mdl;
-}
-
-VALUE
-rb_define_module_id(id)
- ID id;
-{
- VALUE mdl;
-
- mdl = rb_module_new();
- rb_name_class(mdl, id);
-
- return mdl;
-}
-
-VALUE
-rb_define_module(name)
- const char *name;
-{
- VALUE module;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined(rb_cObject, id)) {
- module = rb_const_get(rb_cObject, id);
- if (TYPE(module) == T_MODULE)
- return module;
- rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
- }
- module = rb_define_module_id(id);
- st_add_direct(rb_class_tbl, id, module);
- rb_const_set(rb_cObject, id, module);
-
- return module;
-}
-
-VALUE
-rb_define_module_under(outer, name)
- VALUE outer;
- const char *name;
-{
- VALUE module;
- ID id;
-
- id = rb_intern(name);
- if (rb_const_defined_at(outer, id)) {
- module = rb_const_get_at(outer, id);
- if (TYPE(module) == T_MODULE)
- return module;
- rb_raise(rb_eTypeError, "%s::%s is not a module",
- rb_class2name(outer), rb_obj_classname(module));
- }
- module = rb_define_module_id(id);
- rb_const_set(outer, id, module);
- rb_set_class_path(module, outer, name);
-
- return module;
-}
-
-static VALUE
-include_class_new(module, super)
- VALUE module, super;
-{
- NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, rb_cClass, T_ICLASS);
-
- if (BUILTIN_TYPE(module) == T_ICLASS) {
- module = RBASIC(module)->klass;
- }
- if (!RCLASS(module)->iv_tbl) {
- RCLASS(module)->iv_tbl = st_init_numtable();
- }
- klass->iv_tbl = RCLASS(module)->iv_tbl;
- klass->m_tbl = RCLASS(module)->m_tbl;
- klass->super = super;
- if (TYPE(module) == T_ICLASS) {
- RBASIC(klass)->klass = RBASIC(module)->klass;
- }
- else {
- RBASIC(klass)->klass = module;
- }
- OBJ_INFECT(klass, module);
- OBJ_INFECT(klass, super);
-
- return (VALUE)klass;
-}
-
-void
-rb_include_module(klass, module)
- VALUE klass, module;
-{
- VALUE p, c;
- int changed = 0;
-
- rb_frozen_class_p(klass);
- if (!OBJ_TAINTED(klass)) {
- rb_secure(4);
- }
-
- if (NIL_P(module)) return;
- if (klass == module) return;
-
- if (TYPE(module) != T_MODULE) {
- Check_Type(module, T_MODULE);
- }
-
- OBJ_INFECT(klass, module);
- c = klass;
- while (module) {
- int superclass_seen = Qfalse;
-
- if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
- rb_raise(rb_eArgError, "cyclic include detected");
- /* ignore if the module included already in superclasses */
- for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
- switch (BUILTIN_TYPE(p)) {
- case T_ICLASS:
- if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
- if (!superclass_seen) {
- c = p; /* move insertion point */
- }
- goto skip;
- }
- break;
- case T_CLASS:
- superclass_seen = Qtrue;
- break;
- }
- }
- c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
- changed = 1;
- skip:
- module = RCLASS(module)->super;
- }
- if (changed) rb_clear_cache();
-}
-
-/*
- * call-seq:
- * mod.included_modules -> array
- *
- * Returns the list of modules included in <i>mod</i>.
- *
- * module Mixin
- * end
- *
- * module Outer
- * include Mixin
- * end
- *
- * Mixin.included_modules #=> []
- * Outer.included_modules #=> [Mixin]
- */
-
-VALUE
-rb_mod_included_modules(mod)
- VALUE mod;
-{
- VALUE ary = rb_ary_new();
- VALUE p;
-
- for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
- }
- return ary;
-}
-
-/*
- * call-seq:
- * mod.include?(module) => true or false
- *
- * Returns <code>true</code> if <i>module</i> is included in
- * <i>mod</i> or one of <i>mod</i>'s ancestors.
- *
- * module A
- * end
- * class B
- * include A
- * end
- * class C < B
- * end
- * B.include?(A) #=> true
- * C.include?(A) #=> true
- * A.include?(A) #=> false
- */
-
-VALUE
-rb_mod_include_p(mod, mod2)
- VALUE mod;
- VALUE mod2;
-{
- VALUE p;
-
- Check_Type(mod2, T_MODULE);
- for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- if (RBASIC(p)->klass == mod2) return Qtrue;
- }
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * mod.ancestors -> array
- *
- * Returns a list of modules included in <i>mod</i> (including
- * <i>mod</i> itself).
- *
- * module Mod
- * include Math
- * include Comparable
- * end
- *
- * Mod.ancestors #=> [Mod, Comparable, Math]
- * Math.ancestors #=> [Math]
- */
-
-VALUE
-rb_mod_ancestors(mod)
- VALUE mod;
-{
- VALUE p, ary = rb_ary_new();
-
- for (p = mod; p; p = RCLASS(p)->super) {
- if (FL_TEST(p, FL_SINGLETON))
- continue;
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
- else {
- rb_ary_push(ary, p);
- }
- }
- return ary;
-}
-
-#define VISI(x) ((x)&NOEX_MASK)
-#define VISI_CHECK(x,f) (VISI(x) == (f))
-
-static int
-ins_methods_push(name, type, ary, visi)
- ID name;
- long type;
- VALUE ary;
- long visi;
-{
- if (type == -1) return ST_CONTINUE;
- switch (visi) {
- case NOEX_PRIVATE:
- case NOEX_PROTECTED:
- case NOEX_PUBLIC:
- visi = (type == visi);
- break;
- default:
- visi = (type != NOEX_PRIVATE);
- break;
- }
- if (visi) {
- rb_ary_push(ary, rb_str_new2(rb_id2name(name)));
- }
- return ST_CONTINUE;
-}
-
-static int
-ins_methods_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, -1); /* everything but private */
-}
-
-static int
-ins_methods_prot_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, NOEX_PROTECTED);
-}
-
-static int
-ins_methods_priv_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, NOEX_PRIVATE);
-}
-
-static int
-ins_methods_pub_i(name, type, ary)
- ID name;
- long type;
- VALUE ary;
-{
- return ins_methods_push(name, type, ary, NOEX_PUBLIC);
-}
-
-static int
-method_entry(key, body, list)
- ID key;
- NODE *body;
- st_table *list;
-{
- long type;
-
- if (key == ID_ALLOCATOR) return ST_CONTINUE;
- if (!st_lookup(list, key, 0)) {
- if (!body->nd_body) type = -1; /* none */
- else type = VISI(body->nd_noex);
- st_add_direct(list, key, type);
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-class_instance_method_list(argc, argv, mod, func)
- int argc;
- VALUE *argv;
- VALUE mod;
- int (*func) _((ID, long, VALUE));
-{
- VALUE ary;
- int recur;
- st_table *list;
-
- if (argc == 0) {
- recur = Qtrue;
- }
- else {
- VALUE r;
- rb_scan_args(argc, argv, "01", &r);
- recur = RTEST(r);
- }
-
- list = st_init_numtable();
- for (; mod; mod = RCLASS(mod)->super) {
- st_foreach(RCLASS(mod)->m_tbl, method_entry, (st_data_t)list);
- if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
- if (FL_TEST(mod, FL_SINGLETON)) continue;
- if (!recur) break;
- }
- ary = rb_ary_new();
- st_foreach(list, func, ary);
- st_free_table(list);
-
- return ary;
-}
-
-/*
- * call-seq:
- * mod.instance_methods(include_super=true) => array
- *
- * Returns an array containing the names of public instance methods in
- * the receiver. For a module, these are the public methods; for a
- * class, they are the instance (not singleton) methods. With no
- * argument, or with an argument that is <code>false</code>, the
- * instance methods in <i>mod</i> are returned, otherwise the methods
- * in <i>mod</i> and <i>mod</i>'s superclasses are returned.
- *
- * module A
- * def method1() end
- * end
- * class B
- * def method2() end
- * end
- * class C < B
- * def method3() end
- * end
- *
- * A.instance_methods #=> ["method1"]
- * B.instance_methods(false) #=> ["method2"]
- * C.instance_methods(false) #=> ["method3"]
- * C.instance_methods(true).length #=> 43
- */
-
-VALUE
-rb_class_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_i);
-}
-
-/*
- * call-seq:
- * mod.protected_instance_methods(include_super=true) => array
- *
- * Returns a list of the protected instance methods defined in
- * <i>mod</i>. If the optional parameter is not <code>false</code>, the
- * methods of any ancestors are included.
- */
-
-VALUE
-rb_class_protected_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_prot_i);
-}
-
-/*
- * call-seq:
- * mod.private_instance_methods(include_super=true) => array
- *
- * Returns a list of the private instance methods defined in
- * <i>mod</i>. If the optional parameter is not <code>false</code>, the
- * methods of any ancestors are included.
- *
- * module Mod
- * def method1() end
- * private :method1
- * def method2() end
- * end
- * Mod.instance_methods #=> ["method2"]
- * Mod.private_instance_methods #=> ["method1"]
- */
-
-VALUE
-rb_class_private_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_priv_i);
-}
-
-/*
- * call-seq:
- * mod.public_instance_methods(include_super=true) => array
- *
- * Returns a list of the public instance methods defined in <i>mod</i>.
- * If the optional parameter is not <code>false</code>, the methods of
- * any ancestors are included.
- */
-
-VALUE
-rb_class_public_instance_methods(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return class_instance_method_list(argc, argv, mod, ins_methods_pub_i);
-}
-
-/*
- * call-seq:
- * obj.singleton_methods(all=true) => array
- *
- * Returns an array of the names of singleton methods for <i>obj</i>.
- * If the optional <i>all</i> parameter is true, the list will include
- * methods in modules included in <i>obj</i>.
- *
- * module Other
- * def three() end
- * end
- *
- * class Single
- * def Single.four() end
- * end
- *
- * a = Single.new
- *
- * def a.one()
- * end
- *
- * class << a
- * include Other
- * def two()
- * end
- * end
- *
- * Single.singleton_methods #=> ["four"]
- * a.singleton_methods(false) #=> ["two", "one"]
- * a.singleton_methods #=> ["two", "one", "three"]
- */
-
-VALUE
-rb_obj_singleton_methods(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE recur, ary, klass;
- st_table *list;
-
- rb_scan_args(argc, argv, "01", &recur);
- if (argc == 0) {
- recur = Qtrue;
- }
- klass = CLASS_OF(obj);
- list = st_init_numtable();
- if (klass && FL_TEST(klass, FL_SINGLETON)) {
- st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list);
- klass = RCLASS(klass)->super;
- }
- if (RTEST(recur)) {
- while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
- st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list);
- klass = RCLASS(klass)->super;
- }
- }
- ary = rb_ary_new();
- st_foreach(list, ins_methods_i, ary);
- st_free_table(list);
-
- return ary;
-}
-
-void
-rb_define_method_id(klass, name, func, argc)
- VALUE klass;
- ID name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC);
-}
-
-void
-rb_define_method(klass, name, func, argc)
- VALUE klass;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
-}
-
-void
-rb_define_protected_method(klass, name, func, argc)
- VALUE klass;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED);
-}
-
-void
-rb_define_private_method(klass, name, func, argc)
- VALUE klass;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
-}
-
-void
-rb_undef_method(klass, name)
- VALUE klass;
- const char *name;
-{
- rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF);
-}
-
-#define SPECIAL_SINGLETON(x,c) do {\
- if (obj == (x)) {\
- return c;\
- }\
-} while (0)
-
-VALUE
-rb_singleton_class(obj)
- VALUE obj;
-{
- VALUE klass;
-
- if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
- rb_raise(rb_eTypeError, "can't define singleton");
- }
- if (rb_special_const_p(obj)) {
- SPECIAL_SINGLETON(Qnil, rb_cNilClass);
- SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
- SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
- rb_bug("unknown immediate %ld", obj);
- }
-
- DEFER_INTS;
- if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
- rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
- klass = RBASIC(obj)->klass;
- }
- else {
- klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
- }
- if (OBJ_TAINTED(obj)) {
- OBJ_TAINT(klass);
- }
- else {
- FL_UNSET(klass, FL_TAINT);
- }
- if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
- ALLOW_INTS;
-
- return klass;
-}
-
-void
-rb_define_singleton_method(obj, name, func, argc)
- VALUE obj;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_method(rb_singleton_class(obj), name, func, argc);
-}
-
-void
-rb_define_module_function(module, name, func, argc)
- VALUE module;
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_private_method(module, name, func, argc);
- rb_define_singleton_method(module, name, func, argc);
-}
-
-void
-rb_define_global_function(name, func, argc)
- const char *name;
- VALUE (*func)();
- int argc;
-{
- rb_define_module_function(rb_mKernel, name, func, argc);
-}
-
-void
-rb_define_alias(klass, name1, name2)
- VALUE klass;
- const char *name1, *name2;
-{
- rb_alias(klass, rb_intern(name1), rb_intern(name2));
-}
-
-void
-rb_define_attr(klass, name, read, write)
- VALUE klass;
- const char *name;
- int read, write;
-{
- rb_attr(klass, rb_intern(name), read, write, Qfalse);
-}
-
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-
-int
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
-#else
-rb_scan_args(argc, argv, fmt, va_alist)
- int argc;
- const VALUE *argv;
- const char *fmt;
- va_dcl
-#endif
-{
- int n, i = 0;
- const char *p = fmt;
- VALUE *var;
- va_list vargs;
-
- va_init_list(vargs, fmt);
-
- if (*p == '*') goto rest_arg;
-
- if (ISDIGIT(*p)) {
- n = *p - '0';
- if (n > argc)
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
- for (i=0; i<n; i++) {
- var = va_arg(vargs, VALUE*);
- if (var) *var = argv[i];
- }
- p++;
- }
- else {
- goto error;
- }
-
- if (ISDIGIT(*p)) {
- n = i + *p - '0';
- for (; i<n; i++) {
- var = va_arg(vargs, VALUE*);
- if (argc > i) {
- if (var) *var = argv[i];
- }
- else {
- if (var) *var = Qnil;
- }
- }
- p++;
- }
-
- if(*p == '*') {
- rest_arg:
- var = va_arg(vargs, VALUE*);
- if (argc > i) {
- if (var) *var = rb_ary_new4(argc-i, argv+i);
- i = argc;
- }
- else {
- if (var) *var = rb_ary_new();
- }
- p++;
- }
-
- if (*p == '&') {
- var = va_arg(vargs, VALUE*);
- if (rb_block_given_p()) {
- *var = rb_block_proc();
- }
- else {
- *var = Qnil;
- }
- p++;
- }
- va_end(vargs);
-
- if (*p != '\0') {
- goto error;
- }
-
- if (argc > i) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
- }
-
- return argc;
-
- error:
- rb_fatal("bad scan arg format: %s", fmt);
- return 0;
-}
-/**********************************************************************
-
- compar.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Thu Aug 26 14:39:48 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-
-VALUE rb_mComparable;
-
-static ID cmp;
-
-int
-rb_cmpint(val, a, b)
- VALUE val, a, b;
-{
- if (NIL_P(val)) {
- rb_cmperr(a, b);
- }
- if (FIXNUM_P(val)) return FIX2INT(val);
- if (TYPE(val) == T_BIGNUM) {
- if (RBIGNUM(val)->sign) return 1;
- return -1;
- }
- if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
- if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
- return 0;
-}
-
-void
-rb_cmperr(x, y)
- VALUE x, y;
-{
- const char *classname;
-
- if (SPECIAL_CONST_P(y)) {
- y = rb_inspect(y);
- classname = StringValuePtr(y);
- }
- else {
- classname = rb_obj_classname(y);
- }
- rb_raise(rb_eArgError, "comparison of %s with %s failed",
- rb_obj_classname(x), classname);
-}
-
-static VALUE
-cmp_eq(a)
- VALUE *a;
-{
- VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
-
- if (NIL_P(c)) return Qnil;
- if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-cmp_failed()
-{
- return Qnil;
-}
-
-/*
- * call-seq:
- * obj == other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns 0. Also returns true if
- * _obj_ and _other_ are the same object.
- */
-
-static VALUE
-cmp_equal(x, y)
- VALUE x, y;
-{
- VALUE a[2];
-
- if (x == y) return Qtrue;
-
- a[0] = x; a[1] = y;
- return rb_rescue(cmp_eq, (VALUE)a, cmp_failed, 0);
-}
-
-/*
- * call-seq:
- * obj > other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns 1.
- */
-
-static VALUE
-cmp_gt(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) > 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj >= other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns 0 or 1.
- */
-
-static VALUE
-cmp_ge(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) >= 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj < other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns -1.
- */
-
-static VALUE
-cmp_lt(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) < 0) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * obj <= other => true or false
- *
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns -1 or 0.
- */
-
-static VALUE
-cmp_le(x, y)
- VALUE x, y;
-{
- VALUE c = rb_funcall(x, cmp, 1, y);
-
- if (rb_cmpint(c, x, y) <= 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * obj.between?(min, max) => true or false
- *
- * Returns <code>false</code> if <i>obj</i> <code><=></code>
- * <i>min</i> is less than zero or if <i>anObject</i> <code><=></code>
- * <i>max</i> is greater than zero, <code>true</code> otherwise.
- *
- * 3.between?(1, 5) #=> true
- * 6.between?(1, 5) #=> false
- * 'cat'.between?('ant', 'dog') #=> true
- * 'gnu'.between?('ant', 'dog') #=> false
- *
- */
-
-static VALUE
-cmp_between(x, min, max)
- VALUE x, min, max;
-{
- if (RTEST(cmp_lt(x, min))) return Qfalse;
- if (RTEST(cmp_gt(x, max))) return Qfalse;
- return Qtrue;
-}
-
-/*
- * The <code>Comparable</code> mixin is used by classes whose objects
- * may be ordered. The class must define the <code><=></code> operator,
- * which compares the receiver against another object, returning -1, 0,
- * or +1 depending on whether the receiver is less than, equal to, or
- * greater than the other object. <code>Comparable</code> uses
- * <code><=></code> to implement the conventional comparison operators
- * (<code><</code>, <code><=</code>, <code>==</code>, <code>>=</code>,
- * and <code>></code>) and the method <code>between?</code>.
- *
- * class SizeMatters
- * include Comparable
- * attr :str
- * def <=>(anOther)
- * str.size <=> anOther.str.size
- * end
- * def initialize(str)
- * @str = str
- * end
- * def inspect
- * @str
- * end
- * end
- *
- * s1 = SizeMatters.new("Z")
- * s2 = SizeMatters.new("YY")
- * s3 = SizeMatters.new("XXX")
- * s4 = SizeMatters.new("WWWW")
- * s5 = SizeMatters.new("VVVVV")
- *
- * s1 < s2 #=> true
- * s4.between?(s1, s3) #=> false
- * s4.between?(s3, s5) #=> true
- * [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
- *
- */
-
-void
-Init_Comparable()
-{
- rb_mComparable = rb_define_module("Comparable");
- rb_define_method(rb_mComparable, "==", cmp_equal, 1);
- rb_define_method(rb_mComparable, ">", cmp_gt, 1);
- rb_define_method(rb_mComparable, ">=", cmp_ge, 1);
- rb_define_method(rb_mComparable, "<", cmp_lt, 1);
- rb_define_method(rb_mComparable, "<=", cmp_le, 1);
- rb_define_method(rb_mComparable, "between?", cmp_between, 2);
-
- cmp = rb_intern("<=>");
-}
-/**********************************************************************
-
- dir.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Wed Jan 5 09:51:01 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#include "ruby.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if defined HAVE_DIRENT_H && !defined _WIN32
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#elif defined HAVE_DIRECT_H && !defined _WIN32
-# include <direct.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# if !defined __NeXT__
-# define NAMLEN(dirent) (dirent)->d_namlen
-# else
-# /* On some versions of NextStep, d_namlen is always zero, so avoid it. */
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-# endif
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-# ifdef _WIN32
-# include "win32/dir.h"
-# endif
-#endif
-
-#include <errno.h>
-
-#ifndef HAVE_STDLIB_H
-char *getenv();
-#endif
-
-#ifndef HAVE_STRING_H
-char *strchr _((char*,char));
-#endif
-
-#include <ctype.h>
-
-#include "util.h"
-
-#if !defined HAVE_LSTAT && !defined lstat
-#define lstat stat
-#endif
-
-#define FNM_NOESCAPE 0x01
-#define FNM_PATHNAME 0x02
-#define FNM_DOTMATCH 0x04
-#define FNM_CASEFOLD 0x08
-
-#define FNM_NOMATCH 1
-#define FNM_ERROR 2
-
-#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
-#define compare(c1, c2) (((unsigned char)(c1)) - ((unsigned char)(c2)))
-
-/* caution: in case *p == '\0'
- Next(p) == p + 1 in single byte environment
- Next(p) == p in multi byte environment
-*/
-#if defined(CharNext)
-# define Next(p) CharNext(p)
-#elif defined(DJGPP)
-# define Next(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-#elif defined(__EMX__)
-# define Next(p) ((p) + emx_mblen(p))
-static inline int
-emx_mblen(p)
- const char *p;
-{
- int n = mblen(p, RUBY_MBCHAR_MAXSIZE);
- return (n < 0) ? 1 : n;
-}
-#endif
-
-#ifndef Next /* single byte environment */
-# define Next(p) ((p) + 1)
-# define Inc(p) (++(p))
-# define Compare(p1, p2) (compare(downcase(*(p1)), downcase(*(p2))))
-#else /* multi byte environment */
-# define Inc(p) ((p) = Next(p))
-# define Compare(p1, p2) (CompareImpl(p1, p2, nocase))
-static int
-CompareImpl(p1, p2, nocase)
- const char *p1;
- const char *p2;
- int nocase;
-{
- const int len1 = Next(p1) - p1;
- const int len2 = Next(p2) - p2;
-#ifdef _WIN32
- char buf1[10], buf2[10]; /* large enough? */
-#endif
-
- if (len1 < 0 || len2 < 0) {
- rb_fatal("CompareImpl: negative len");
- }
-
- if (len1 == 0) return len2;
- if (len2 == 0) return -len1;
-
-#ifdef _WIN32
- if (nocase) {
- if (len1 > 1) {
- if (len1 >= sizeof(buf1)) {
- rb_fatal("CompareImpl: too large len");
- }
- memcpy(buf1, p1, len1);
- buf1[len1] = '\0';
- CharLower(buf1);
- p1 = buf1; /* trick */
- }
- if (len2 > 1) {
- if (len2 >= sizeof(buf2)) {
- rb_fatal("CompareImpl: too large len");
- }
- memcpy(buf2, p2, len2);
- buf2[len2] = '\0';
- CharLower(buf2);
- p2 = buf2; /* trick */
- }
- }
-#endif
- if (len1 == 1)
- if (len2 == 1)
- return compare(downcase(*p1), downcase(*p2));
- else {
- const int ret = compare(downcase(*p1), *p2);
- return ret ? ret : -1;
- }
- else
- if (len2 == 1) {
- const int ret = compare(*p1, downcase(*p2));
- return ret ? ret : 1;
- }
- else {
- const int ret = memcmp(p1, p2, len1 < len2 ? len1 : len2);
- return ret ? ret : len1 - len2;
- }
-}
-#endif /* environment */
-
-static char *
-bracket(p, s, flags)
- const char *p; /* pattern (next to '[') */
- const char *s; /* string */
- int flags;
-{
- const int nocase = flags & FNM_CASEFOLD;
- const int escape = !(flags & FNM_NOESCAPE);
-
- int ok = 0, not = 0;
-
- if (*p == '!' || *p == '^') {
- not = 1;
- p++;
- }
-
- while (*p != ']') {
- const char *t1 = p;
- if (escape && *t1 == '\\')
- t1++;
- if (!*t1)
- return NULL;
- p = Next(t1);
- if (p[0] == '-' && p[1] != ']') {
- const char *t2 = p + 1;
- if (escape && *t2 == '\\')
- t2++;
- if (!*t2)
- return NULL;
- p = Next(t2);
- if (!ok && Compare(t1, s) <= 0 && Compare(s, t2) <= 0)
- ok = 1;
- }
- else
- if (!ok && Compare(t1, s) == 0)
- ok = 1;
- }
-
- return ok == not ? NULL : (char *)p + 1;
-}
-
-/* If FNM_PATHNAME is set, only path element will be matched. (upto '/' or '\0')
- Otherwise, entire string will be matched.
- End marker itself won't be compared.
- And if function succeeds, *pcur reaches end marker.
-*/
-#define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
-#define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
-#define RETURN(val) return *pcur = p, *scur = s, (val);
-
-static int
-fnmatch_helper(pcur, scur, flags)
- const char **pcur; /* pattern */
- const char **scur; /* string */
- int flags;
-{
- const int period = !(flags & FNM_DOTMATCH);
- const int pathname = flags & FNM_PATHNAME;
- const int escape = !(flags & FNM_NOESCAPE);
- const int nocase = flags & FNM_CASEFOLD;
-
- const char *ptmp = 0;
- const char *stmp = 0;
-
- const char *p = *pcur;
- const char *s = *scur;
-
- if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
- RETURN(FNM_NOMATCH);
-
- while (1) {
- switch (*p) {
- case '*':
- do { p++; } while (*p == '*');
- if (ISEND(UNESCAPE(p))) {
- p = UNESCAPE(p);
- RETURN(0);
- }
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- ptmp = p;
- stmp = s;
- continue;
-
- case '?':
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- p++;
- Inc(s);
- continue;
-
- case '[': {
- const char *t;
- if (ISEND(s))
- RETURN(FNM_NOMATCH);
- if (t = bracket(p + 1, s, flags)) {
- p = t;
- Inc(s);
- continue;
- }
- goto failed;
- }
- }
-
- /* ordinary */
- p = UNESCAPE(p);
- if (ISEND(s))
- RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
- if (ISEND(p))
- goto failed;
- if (Compare(p, s) != 0)
- goto failed;
- Inc(p);
- Inc(s);
- continue;
-
- failed: /* try next '*' position */
- if (ptmp && stmp) {
- p = ptmp;
- Inc(stmp); /* !ISEND(*stmp) */
- s = stmp;
- continue;
- }
- RETURN(FNM_NOMATCH);
- }
-}
-
-static int
-fnmatch(p, s, flags)
- const char *p; /* pattern */
- const char *s; /* string */
- int flags;
-{
- const int period = !(flags & FNM_DOTMATCH);
- const int pathname = flags & FNM_PATHNAME;
-
- const char *ptmp = 0;
- const char *stmp = 0;
-
- if (pathname) {
- while (1) {
- if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
- do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
- ptmp = p;
- stmp = s;
- }
- if (fnmatch_helper(&p, &s, flags) == 0) {
- while (*s && *s != '/') Inc(s);
- if (*p && *s) {
- p++;
- s++;
- continue;
- }
- if (!*p && !*s)
- return 0;
- }
- /* failed : try next recursion */
- if (ptmp && stmp && !(period && *stmp == '.')) {
- while (*stmp && *stmp != '/') Inc(stmp);
- if (*stmp) {
- p = ptmp;
- stmp++;
- s = stmp;
- continue;
- }
- }
- return FNM_NOMATCH;
- }
- }
- else
- return fnmatch_helper(&p, &s, flags);
-}
-
-VALUE rb_cDir;
-
-struct dir_data {
- DIR *dir;
- char *path;
-};
-
-static void
-free_dir(dir)
- struct dir_data *dir;
-{
- if (dir) {
- if (dir->dir) closedir(dir->dir);
- if (dir->path) free(dir->path);
- }
- free(dir);
-}
-
-static VALUE dir_close _((VALUE));
-
-static VALUE dir_s_alloc _((VALUE));
-static VALUE
-dir_s_alloc(klass)
- VALUE klass;
-{
- struct dir_data *dirp;
- VALUE obj = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dirp);
-
- dirp->dir = NULL;
- dirp->path = NULL;
-
- return obj;
-}
-
-/*
- * call-seq:
- * Dir.new( string ) -> aDir
- *
- * Returns a new directory object for the named directory.
- */
-static VALUE
-dir_initialize(dir, dirname)
- VALUE dir, dirname;
-{
- struct dir_data *dp;
-
- FilePathValue(dirname);
- Data_Get_Struct(dir, struct dir_data, dp);
- if (dp->dir) closedir(dp->dir);
- if (dp->path) free(dp->path);
- dp->dir = NULL;
- dp->path = NULL;
- dp->dir = opendir(RSTRING(dirname)->ptr);
- if (dp->dir == NULL) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- dp->dir = opendir(RSTRING(dirname)->ptr);
- }
- if (dp->dir == NULL) {
- rb_sys_fail(RSTRING(dirname)->ptr);
- }
- }
- dp->path = strdup(RSTRING(dirname)->ptr);
-
- return dir;
-}
-
-/*
- * call-seq:
- * Dir.open( string ) => aDir
- * Dir.open( string ) {| aDir | block } => anObject
- *
- * With no block, <code>open</code> is a synonym for
- * <code>Dir::new</code>. If a block is present, it is passed
- * <i>aDir</i> as a parameter. The directory is closed at the end of
- * the block, and <code>Dir::open</code> returns the value of the
- * block.
- */
-static VALUE
-dir_s_open(klass, dirname)
- VALUE klass, dirname;
-{
- struct dir_data *dp;
- VALUE dir = Data_Make_Struct(klass, struct dir_data, 0, free_dir, dp);
-
- dir_initialize(dir, dirname);
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, dir, dir_close, dir);
- }
-
- return dir;
-}
-
-static void
-dir_closed()
-{
- rb_raise(rb_eIOError, "closed directory");
-}
-
-#define GetDIR(obj, dirp) do {\
- Data_Get_Struct(obj, struct dir_data, dirp);\
- if (dirp->dir == NULL) dir_closed();\
-} while (0)
-
-/*
- * call-seq:
- * dir.inspect => string
- *
- * Return a string describing this Dir object.
- */
-static VALUE
-dir_inspect(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- if (dirp->path) {
- char *c = rb_obj_classname(dir);
- int len = strlen(c) + strlen(dirp->path) + 4;
- VALUE s = rb_str_new(0, len);
- snprintf(RSTRING(s)->ptr, len+1, "#<%s:%s>", c, dirp->path);
- return s;
- }
- return rb_funcall(dir, rb_intern("to_s"), 0, 0);
-}
-
-/*
- * call-seq:
- * dir.path => string or nil
- *
- * Returns the path parameter passed to <em>dir</em>'s constructor.
- *
- * d = Dir.new("..")
- * d.path #=> ".."
- */
-static VALUE
-dir_path(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- if (!dirp->path) return Qnil;
- return rb_str_new2(dirp->path);
-}
-
-/*
- * call-seq:
- * dir.read => string or nil
- *
- * Reads the next entry from <em>dir</em> and returns it as a string.
- * Returns <code>nil</code> at the end of the stream.
- *
- * d = Dir.new("testdir")
- * d.read #=> "."
- * d.read #=> ".."
- * d.read #=> "config.h"
- */
-static VALUE
-dir_read(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
- struct dirent *dp;
-
- GetDIR(dir, dirp);
- errno = 0;
- dp = readdir(dirp->dir);
- if (dp) {
- return rb_tainted_str_new(dp->d_name, NAMLEN(dp));
- }
- else if (errno == 0) { /* end of stream */
- return Qnil;
- }
- else {
- rb_sys_fail(0);
- }
- return Qnil; /* not reached */
-}
-
-/*
- * call-seq:
- * dir.each { |filename| block } => dir
- *
- * Calls the block once for each entry in this directory, passing the
- * filename of each entry as a parameter to the block.
- *
- * d = Dir.new("testdir")
- * d.each {|x| puts "Got #{x}" }
- *
- * <em>produces:</em>
- *
- * Got .
- * Got ..
- * Got config.h
- * Got main.rb
- */
-static VALUE
-dir_each(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
- struct dirent *dp;
-
- GetDIR(dir, dirp);
- for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
- rb_yield(rb_tainted_str_new(dp->d_name, NAMLEN(dp)));
- if (dirp->dir == NULL) dir_closed();
- }
- return dir;
-}
-
-/*
- * call-seq:
- * dir.pos => integer
- * dir.tell => integer
- *
- * Returns the current position in <em>dir</em>. See also
- * <code>Dir#seek</code>.
- *
- * d = Dir.new("testdir")
- * d.tell #=> 0
- * d.read #=> "."
- * d.tell #=> 12
- */
-static VALUE
-dir_tell(dir)
- VALUE dir;
-{
-#ifdef HAVE_TELLDIR
- struct dir_data *dirp;
- long pos;
-
- GetDIR(dir, dirp);
- pos = telldir(dirp->dir);
- return rb_int2inum(pos);
-#else
- rb_notimplement();
-#endif
-}
-
-/*
- * call-seq:
- * dir.seek( integer ) => dir
- *
- * Seeks to a particular location in <em>dir</em>. <i>integer</i>
- * must be a value returned by <code>Dir#tell</code>.
- *
- * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
- * d.read #=> "."
- * i = d.tell #=> 12
- * d.read #=> ".."
- * d.seek(i) #=> #<Dir:0x401b3c40>
- * d.read #=> ".."
- */
-static VALUE
-dir_seek(dir, pos)
- VALUE dir, pos;
-{
- struct dir_data *dirp;
- off_t p = NUM2OFFT(pos);
-
- GetDIR(dir, dirp);
-#ifdef HAVE_SEEKDIR
- seekdir(dirp->dir, p);
- return dir;
-#else
- rb_notimplement();
-#endif
-}
-
-/*
- * call-seq:
- * dir.pos( integer ) => integer
- *
- * Synonym for <code>Dir#seek</code>, but returns the position
- * parameter.
- *
- * d = Dir.new("testdir") #=> #<Dir:0x401b3c40>
- * d.read #=> "."
- * i = d.pos #=> 12
- * d.read #=> ".."
- * d.pos = i #=> 12
- * d.read #=> ".."
- */
-static VALUE
-dir_set_pos(dir, pos)
- VALUE dir, pos;
-{
- dir_seek(dir, pos);
- return pos;
-}
-
-/*
- * call-seq:
- * dir.rewind => dir
- *
- * Repositions <em>dir</em> to the first entry.
- *
- * d = Dir.new("testdir")
- * d.read #=> "."
- * d.rewind #=> #<Dir:0x401b3fb0>
- * d.read #=> "."
- */
-static VALUE
-dir_rewind(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- rewinddir(dirp->dir);
- return dir;
-}
-
-/*
- * call-seq:
- * dir.close => nil
- *
- * Closes the directory stream. Any further attempts to access
- * <em>dir</em> will raise an <code>IOError</code>.
- *
- * d = Dir.new("testdir")
- * d.close #=> nil
- */
-static VALUE
-dir_close(dir)
- VALUE dir;
-{
- struct dir_data *dirp;
-
- GetDIR(dir, dirp);
- closedir(dirp->dir);
- dirp->dir = NULL;
-
- return Qnil;
-}
-
-static void
-dir_chdir(path)
- VALUE path;
-{
- if (chdir(RSTRING(path)->ptr) < 0)
- rb_sys_fail(RSTRING(path)->ptr);
-}
-
-static int chdir_blocking = 0;
-static VALUE chdir_thread = Qnil;
-
-struct chdir_data {
- VALUE old_path, new_path;
- int done;
-};
-
-static VALUE
-chdir_yield(args)
- struct chdir_data *args;
-{
- dir_chdir(args->new_path);
- args->done = Qtrue;
- chdir_blocking++;
- if (chdir_thread == Qnil)
- chdir_thread = rb_thread_current();
- return rb_yield(args->new_path);
-}
-
-static VALUE
-chdir_restore(args)
- struct chdir_data *args;
-{
- if (args->done) {
- chdir_blocking--;
- if (chdir_blocking == 0)
- chdir_thread = Qnil;
- dir_chdir(args->old_path);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * Dir.chdir( [ string] ) => 0
- * Dir.chdir( [ string] ) {| path | block } => anObject
- *
- * Changes the current working directory of the process to the given
- * string. When called without an argument, changes the directory to
- * the value of the environment variable <code>HOME</code>, or
- * <code>LOGDIR</code>. <code>SystemCallError</code> (probably
- * <code>Errno::ENOENT</code>) if the target directory does not exist.
- *
- * If a block is given, it is passed the name of the new current
- * directory, and the block is executed with that as the current
- * directory. The original working directory is restored when the block
- * exits. The return value of <code>chdir</code> is the value of the
- * block. <code>chdir</code> blocks can be nested, but in a
- * multi-threaded program an error will be raised if a thread attempts
- * to open a <code>chdir</code> block while another thread has one
- * open.
- *
- * Dir.chdir("/var/spool/mail")
- * puts Dir.pwd
- * Dir.chdir("/tmp") do
- * puts Dir.pwd
- * Dir.chdir("/usr") do
- * puts Dir.pwd
- * end
- * puts Dir.pwd
- * end
- * puts Dir.pwd
- *
- * <em>produces:</em>
- *
- * /var/spool/mail
- * /tmp
- * /usr
- * /tmp
- * /var/spool/mail
- */
-static VALUE
-dir_s_chdir(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE path = Qnil;
-
- rb_secure(2);
- if (rb_scan_args(argc, argv, "01", &path) == 1) {
- FilePathValue(path);
- }
- else {
- const char *dist = getenv("HOME");
- if (!dist) {
- dist = getenv("LOGDIR");
- if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
- }
- path = rb_str_new2(dist);
- }
-
- if (chdir_blocking > 0) {
- if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
- rb_warn("conflicting chdir during another chdir block");
- }
-
- if (rb_block_given_p()) {
- struct chdir_data args;
- char *cwd = my_getcwd();
-
- args.old_path = rb_tainted_str_new2(cwd); free(cwd);
- args.new_path = path;
- args.done = Qfalse;
- return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
- }
- dir_chdir(path);
-
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * Dir.getwd => string
- * Dir.pwd => string
- *
- * Returns the path to the current working directory of this process as
- * a string.
- *
- * Dir.chdir("/tmp") #=> 0
- * Dir.getwd #=> "/tmp"
- */
-static VALUE
-dir_s_getwd(dir)
- VALUE dir;
-{
- char *path;
- VALUE cwd;
-
- rb_secure(4);
- path = my_getcwd();
- cwd = rb_tainted_str_new2(path);
-
- free(path);
- return cwd;
-}
-
-static void check_dirname _((volatile VALUE *));
-static void
-check_dirname(dir)
- volatile VALUE *dir;
-{
- char *path, *pend;
-
- rb_secure(2);
- FilePathValue(*dir);
- path = RSTRING(*dir)->ptr;
- if (path && *(pend = rb_path_end(rb_path_skip_prefix(path)))) {
- *dir = rb_str_new(path, pend - path);
- }
-}
-
-/*
- * call-seq:
- * Dir.chroot( string ) => 0
- *
- * Changes this process's idea of the file system root. Only a
- * privileged process may make this call. Not available on all
- * platforms. On Unix systems, see <code>chroot(2)</code> for more
- * information.
- */
-static VALUE
-dir_s_chroot(dir, path)
- VALUE dir, path;
-{
-#if defined(HAVE_CHROOT) && !defined(__CHECKER__)
- check_dirname(&path);
-
- if (chroot(RSTRING(path)->ptr) == -1)
- rb_sys_fail(RSTRING(path)->ptr);
-
- return INT2FIX(0);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-/*
- * call-seq:
- * Dir.mkdir( string [, integer] ) => 0
- *
- * Makes a new directory named by <i>string</i>, with permissions
- * specified by the optional parameter <i>anInteger</i>. The
- * permissions may be modified by the value of
- * <code>File::umask</code>, and are ignored on NT. Raises a
- * <code>SystemCallError</code> if the directory cannot be created. See
- * also the discussion of permissions in the class documentation for
- * <code>File</code>.
- *
- */
-static VALUE
-dir_s_mkdir(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE path, vmode;
- int mode;
-
- if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
- mode = NUM2INT(vmode);
- }
- else {
- mode = 0777;
- }
-
- check_dirname(&path);
- if (mkdir(RSTRING(path)->ptr, mode) == -1)
- rb_sys_fail(RSTRING(path)->ptr);
-
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * Dir.delete( string ) => 0
- * Dir.rmdir( string ) => 0
- * Dir.unlink( string ) => 0
- *
- * Deletes the named directory. Raises a subclass of
- * <code>SystemCallError</code> if the directory isn't empty.
- */
-static VALUE
-dir_s_rmdir(obj, dir)
- VALUE obj, dir;
-{
- check_dirname(&dir);
- if (rmdir(RSTRING(dir)->ptr) < 0)
- rb_sys_fail(RSTRING(dir)->ptr);
-
- return INT2FIX(0);
-}
-
-/* System call with warning */
-static int
-do_stat(path, pst)
- const char *path;
- struct stat *pst;
-{
- int ret = stat(path, pst);
- if (ret < 0 && errno != ENOENT)
- rb_sys_warning(path);
-
- return ret;
-}
-
-static int
-do_lstat(path, pst)
- const char *path;
- struct stat *pst;
-{
- int ret = lstat(path, pst);
- if (ret < 0 && errno != ENOENT)
- rb_sys_warning(path);
-
- return ret;
-}
-
-static DIR *
-do_opendir(path)
- const char *path;
-{
- DIR *dirp = opendir(path);
- if (dirp == NULL && errno != ENOENT && errno != ENOTDIR)
- rb_sys_warning(path);
-
- return dirp;
-}
-
-/* Return nonzero if S has any special globbing chars in it. */
-static int
-has_magic(s, flags)
- const char *s;
- int flags;
-{
- const int escape = !(flags & FNM_NOESCAPE);
-
- register const char *p = s;
- register char c;
-
- while (c = *p++) {
- switch (c) {
- case '*':
- case '?':
- case '[':
- return 1;
-
- case '\\':
- if (escape && !(c = *p++))
- return 0;
- continue;
- }
-
- p = Next(p-1);
- }
-
- return 0;
-}
-
-/* Find separator in globbing pattern. */
-static char *
-find_dirsep(s, flags)
- const char *s;
- int flags;
-{
- const int escape = !(flags & FNM_NOESCAPE);
-
- register const char *p = s;
- register char c;
- int open = 0;
-
- while (c = *p++) {
- switch (c) {
- case '[':
- open = 1;
- continue;
- case ']':
- open = 0;
- continue;
-
- case '/':
- if (!open)
- return (char *)p-1;
- continue;
-
- case '\\':
- if (escape && !(c = *p++))
- return (char *)p-1;
- continue;
- }
-
- p = Next(p-1);
- }
-
- return (char *)p-1;
-}
-
-/* Remove escaping baskclashes */
-static void
-remove_backslashes(p)
- char *p;
-{
- char *t = p;
- char *s = p;
-
- while (*p) {
- if (*p == '\\') {
- if (t != s)
- memmove(t, s, p - s);
- t += p - s;
- s = ++p;
- if (!*p) break;
- }
- Inc(p);
- }
-
- while (*p++);
-
- if (t != s)
- memmove(t, s, p - s); /* move '\0' too */
-}
-
-/* Globing pattern */
-enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
-
-struct glob_pattern {
- char *str;
- enum glob_pattern_type type;
- struct glob_pattern *next;
-};
-
-static struct glob_pattern *
-glob_make_pattern(p, flags)
- const char *p;
- int flags;
-{
- struct glob_pattern *list, *tmp, **tail = &list;
- int dirsep = 0; /* pattern is terminated with '/' */
-
- while (*p) {
- tmp = ALLOC(struct glob_pattern);
- if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
- /* fold continuous RECURSIVEs (needed in glob_helper) */
- do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
- tmp->type = RECURSIVE;
- tmp->str = 0;
- dirsep = 1;
- }
- else {
- const char *m = find_dirsep(p, flags);
- char *buf = ALLOC_N(char, m-p+1);
- memcpy(buf, p, m-p);
- buf[m-p] = '\0';
- tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN;
- tmp->str = buf;
- if (*m) {
- dirsep = 1;
- p = m + 1;
- }
- else {
- dirsep = 0;
- p = m;
- }
- }
- *tail = tmp;
- tail = &tmp->next;
- }
-
- tmp = ALLOC(struct glob_pattern);
- tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
- tmp->str = 0;
- *tail = tmp;
- tmp->next = 0;
-
- return list;
-}
-
-static void
-glob_free_pattern(list)
- struct glob_pattern *list;
-{
- while (list) {
- struct glob_pattern *tmp = list;
- list = list->next;
- if (tmp->str)
- free(tmp->str);
- free(tmp);
- }
-}
-
-static VALUE
-join_path(path, dirsep, name)
- VALUE path;
- int dirsep;
- const char *name;
-{
- long len = RSTRING(path)->len;
- VALUE buf = rb_str_new(0, RSTRING(path)->len+strlen(name)+(dirsep?1:0));
-
- memcpy(RSTRING(buf)->ptr, RSTRING(path)->ptr, len);
- if (dirsep) {
- strcpy(RSTRING(buf)->ptr+len, "/");
- len++;
- }
- strcpy(RSTRING(buf)->ptr+len, name);
- return buf;
-}
-
-enum answer { YES, NO, UNKNOWN };
-
-#ifndef S_ISDIR
-# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#ifndef S_ISLNK
-# ifndef S_IFLNK
-# define S_ISLNK(m) (0)
-# else
-# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
-# endif
-#endif
-
-struct glob_args {
- void (*func) _((VALUE, VALUE));
- VALUE c;
- VALUE v;
-};
-
-static VALUE glob_func_caller _((VALUE));
-
-static VALUE
-glob_func_caller(val)
- VALUE val;
-{
- struct glob_args *args = (struct glob_args *)val;
- VALUE path = args->c;
-
- OBJ_TAINT(path);
- (*args->func)(path, args->v);
- return Qnil;
-}
-
-static int
-glob_call_func(func, path, arg)
- void (*func) _((VALUE, VALUE));
- VALUE path;
- VALUE arg;
-{
- int status;
- struct glob_args args;
-
- args.func = func;
- args.c = path;
- args.v = arg;
-
- rb_protect(glob_func_caller, (VALUE)&args, &status);
- return status;
-}
-
-static int
-glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
- VALUE path;
- int dirsep; /* '/' should be placed before appending child entry's name to 'path'. */
- enum answer exist; /* Does 'path' indicate an existing entry? */
- enum answer isdir; /* Does 'path' indicate a directory or a symlink to a directory? */
- struct glob_pattern **beg;
- struct glob_pattern **end;
- int flags;
- void (*func) _((VALUE, VALUE));
- VALUE arg;
-{
- struct stat st;
- int status = 0;
- struct glob_pattern **cur, **new_beg, **new_end;
- int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
- int escape = !(flags & FNM_NOESCAPE);
-
- for (cur = beg; cur < end; ++cur) {
- struct glob_pattern *p = *cur;
- if (p->type == RECURSIVE) {
- recursive = 1;
- p = p->next;
- }
- switch (p->type) {
- case PLAIN:
- plain = 1;
- break;
- case MAGICAL:
- magical = 1;
- break;
- case MATCH_ALL:
- match_all = 1;
- break;
- case MATCH_DIR:
- match_dir = 1;
- break;
- }
- }
-
- if (RSTRING(path)->len > 0) {
- if (match_all && exist == UNKNOWN) {
- if (do_lstat(RSTRING(path)->ptr, &st) == 0) {
- exist = YES;
- isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
- }
- else {
- exist = NO;
- isdir = NO;
- }
- }
-
- if (match_dir && isdir == UNKNOWN) {
- if (do_stat(RSTRING(path)->ptr, &st) == 0) {
- exist = YES;
- isdir = S_ISDIR(st.st_mode) ? YES : NO;
- }
- else {
- exist = NO;
- isdir = NO;
- }
- }
-
- if (match_all && exist == YES) {
- status = glob_call_func(func, path, arg);
- if (status) return status;
- }
-
- if (match_dir && isdir == YES) {
- status = glob_call_func(func, join_path(path, dirsep, ""), arg);
- if (status) return status;
- }
- }
-
- if (exist == NO || isdir == NO) return 0;
-
- if (magical || recursive) {
- struct dirent *dp;
- DIR *dirp = do_opendir(RSTRING(path)->len > 0 ? RSTRING(path)->ptr : ".");
- if (dirp == NULL) return 0;
-
- for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- VALUE buf = join_path(path, dirsep, dp->d_name);
-
- enum answer new_isdir = UNKNOWN;
- if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
- && fnmatch("*", dp->d_name, flags) == 0) {
-#ifndef _WIN32
- if (do_lstat(RSTRING(buf)->ptr, &st) == 0)
- new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
- else
- new_isdir = NO;
-#else
- new_isdir = dp->d_isdir ? (!dp->d_isrep ? YES : UNKNOWN) : NO;
-#endif
- }
-
- new_beg = new_end = ALLOC_N(struct glob_pattern *, (end - beg) * 2);
-
- for (cur = beg; cur < end; ++cur) {
- struct glob_pattern *p = *cur;
- if (p->type == RECURSIVE) {
- if (new_isdir == YES) /* not symlink but real directory */
- *new_end++ = p; /* append recursive pattern */
- p = p->next; /* 0 times recursion */
- }
- if (p->type == PLAIN || p->type == MAGICAL) {
- if (fnmatch(p->str, dp->d_name, flags) == 0)
- *new_end++ = p->next;
- }
- }
-
- status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg);
- free(new_beg);
- if (status) break;
- }
-
- closedir(dirp);
- }
- else if (plain) {
- struct glob_pattern **copy_beg, **copy_end, **cur2;
-
- copy_beg = copy_end = ALLOC_N(struct glob_pattern *, end - beg);
- for (cur = beg; cur < end; ++cur)
- *copy_end++ = (*cur)->type == PLAIN ? *cur : 0;
-
- for (cur = copy_beg; cur < copy_end; ++cur) {
- if (*cur) {
- VALUE buf;
- char *name;
- name = ALLOC_N(char, strlen((*cur)->str) + 1);
- strcpy(name, (*cur)->str);
- if (escape) remove_backslashes(name);
-
- new_beg = new_end = ALLOC_N(struct glob_pattern *, end - beg);
- *new_end++ = (*cur)->next;
- for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
- if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) {
- *new_end++ = (*cur2)->next;
- *cur2 = 0;
- }
- }
-
- buf = join_path(path, dirsep, name);
- free(name);
- status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
- free(new_beg);
- if (status) break;
- }
- }
-
- free(copy_beg);
- }
-
- return status;
-}
-
-static int
-rb_glob2(path, offset, flags, func, arg)
- VALUE path;
- long offset;
- int flags;
- void (*func) _((VALUE, VALUE));
- VALUE arg;
-{
- struct glob_pattern *list;
- const char *root, *start;
- VALUE buf;
- int n;
- int status;
-
- if (flags & FNM_CASEFOLD) {
- rb_warn("Dir.glob() ignores File::FNM_CASEFOLD");
- }
-
- start = root = StringValuePtr(path) + offset;
-#if defined DOSISH
- flags |= FNM_CASEFOLD;
- root = rb_path_skip_prefix(root);
-#else
- flags &= ~FNM_CASEFOLD;
-#endif
-
- if (root && *root == '/') root++;
-
- n = root - start;
- buf = rb_str_new(start, n);
-
- list = glob_make_pattern(root, flags);
- status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
- glob_free_pattern(list);
-
- return status;
-}
-
-struct rb_glob_args {
- void (*func) _((const char*, VALUE));
- VALUE arg;
-};
-
-static VALUE
-rb_glob_caller(path, a)
- VALUE path, a;
-{
- struct rb_glob_args *args = (struct rb_glob_args *)a;
- (*args->func)(RSTRING(path)->ptr, args->arg);
- return Qnil;
-}
-
-void
-rb_glob(path, func, arg)
- const char *path;
- void (*func) _((const char*, VALUE));
- VALUE arg;
-{
- struct rb_glob_args args;
- int status;
-
- args.func = func;
- args.arg = arg;
- status = rb_glob2(rb_str_new2(path), 0, 0, rb_glob_caller, &args);
-
- if (status) rb_jump_tag(status);
-}
-
-static void
-push_pattern(path, ary)
- VALUE path, ary;
-{
- rb_ary_push(ary, path);
-}
-
-static int
-push_glob(VALUE ary, VALUE s, long offset, int flags);
-
-static int
-push_glob(ary, str, offset, flags)
- VALUE ary;
- VALUE str;
- long offset;
- int flags;
-{
- const int escape = !(flags & FNM_NOESCAPE);
-
- const char *p = RSTRING(str)->ptr + offset;
- const char *s = p;
- const char *lbrace = 0, *rbrace = 0;
- int nest = 0, status = 0;
-
- while (*p) {
- if (*p == '{' && nest++ == 0) {
- lbrace = p;
- }
- if (*p == '}' && --nest <= 0) {
- rbrace = p;
- break;
- }
- if (*p == '\\' && escape) {
- if (!*++p) break;
- }
- Inc(p);
- }
-
- if (lbrace && rbrace) {
- VALUE buffer = rb_str_new(0, strlen(s));
- char *buf;
- long shift;
-
- buf = RSTRING(buffer)->ptr;
- memcpy(buf, s, lbrace-s);
- shift = (lbrace-s);
- p = lbrace;
- while (p < rbrace) {
- const char *t = ++p;
- nest = 0;
- while (p < rbrace && !(*p == ',' && nest == 0)) {
- if (*p == '{') nest++;
- if (*p == '}') nest--;
- if (*p == '\\' && escape) {
- if (++p == rbrace) break;
- }
- Inc(p);
- }
- memcpy(buf+shift, t, p-t);
- strcpy(buf+shift+(p-t), rbrace+1);
- status = push_glob(ary, buffer, offset, flags);
- if (status) break;
- }
- }
- else if (!lbrace && !rbrace) {
- status = rb_glob2(str, offset, flags, push_pattern, ary);
- }
-
- return status;
-}
-
-static VALUE
-rb_push_glob(str, flags) /* '\0' is delimiter */
- VALUE str;
- int flags;
-{
- long offset = 0;
- VALUE ary;
-
- FilePathValue(str);
-
- ary = rb_ary_new();
-
- while (offset < RSTRING(str)->len) {
- int status = push_glob(ary, str, offset, flags);
- char *p, *pend;
- if (status) rb_jump_tag(status);
- p = RSTRING(str)->ptr + offset;
- p += strlen(p) + 1;
- pend = RSTRING(str)->ptr + RSTRING(str)->len;
- while (p < pend && !*p)
- p++;
- offset = p - RSTRING(str)->ptr;
- }
-
- if (rb_block_given_p()) {
- rb_ary_each(ary);
- return Qnil;
- }
- return ary;
-}
-
-/*
- * call-seq:
- * Dir[ string ] => array
- *
- * Equivalent to calling
- * <em>dir</em>.<code>glob(</code><i>string,</i><code>0)</code>.
- *
- */
-static VALUE
-dir_s_aref(obj, str)
- VALUE obj, str;
-{
- return rb_push_glob(str, 0);
-}
-
-/*
- * call-seq:
- * Dir.glob( string, [flags] ) => array
- * Dir.glob( string, [flags] ) {| filename | block } => nil
- *
- * Returns the filenames found by expanding the pattern given in
- * <i>string</i>, either as an <i>array</i> or as parameters to the
- * block. Note that this pattern is not a regexp (it's closer to a
- * shell glob). See <code>File::fnmatch</code> for the meaning of
- * the <i>flags</i> parameter. Note that case sensitivity
- * depends on your system (so <code>File::FNM_CASEFOLD</code> is ignored)
- *
- * <code>*</code>:: Matches any file. Can be restricted by
- * other values in the glob. <code>*</code>
- * will match all files; <code>c*</code> will
- * match all files beginning with
- * <code>c</code>; <code>*c</code> will match
- * all files ending with <code>c</code>; and
- * <code>*c*</code> will match all files that
- * have <code>c</code> in them (including at
- * the beginning or end). Equivalent to
- * <code>/ .* /x</code> in regexp.
- * <code>**</code>:: Matches directories recursively.
- * <code>?</code>:: Matches any one character. Equivalent to
- * <code>/.{1}/</code> in regexp.
- * <code>[set]</code>:: Matches any one character in +set+.
- * Behaves exactly like character sets in
- * Regexp, including set negation
- * (<code>[^a-z]</code>).
- * <code>{p,q}</code>:: Matches either literal <code>p</code> or
- * literal <code>q</code>. Matching literals
- * may be more than one character in length.
- * More than two literals may be specified.
- * Equivalent to pattern alternation in
- * regexp.
- * <code>\</code>:: Escapes the next metacharacter.
- *
- * Dir["config.?"] #=> ["config.h"]
- * Dir.glob("config.?") #=> ["config.h"]
- * Dir.glob("*.[a-z][a-z]") #=> ["main.rb"]
- * Dir.glob("*.[^r]*") #=> ["config.h"]
- * Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"]
- * Dir.glob("*") #=> ["config.h", "main.rb"]
- * Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
- *
- * rbfiles = File.join("**", "*.rb")
- * Dir.glob(rbfiles) #=> ["main.rb",
- * "lib/song.rb",
- * "lib/song/karaoke.rb"]
- * libdirs = File.join("**", "lib")
- * Dir.glob(libdirs) #=> ["lib"]
- *
- * librbfiles = File.join("**", "lib", "**", "*.rb")
- * Dir.glob(librbfiles) #=> ["lib/song.rb",
- * "lib/song/karaoke.rb"]
- *
- * librbfiles = File.join("**", "lib", "*.rb")
- * Dir.glob(librbfiles) #=> ["lib/song.rb"]
- */
-static VALUE
-dir_s_glob(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE str, rflags;
- int flags;
-
- if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
- flags = NUM2INT(rflags);
- else
- flags = 0;
-
- return rb_push_glob(str, flags);
-}
-
-static VALUE
-dir_open_dir(path)
- VALUE path;
-{
- struct dir_data *dp;
- VALUE dir = rb_funcall(rb_cDir, rb_intern("open"), 1, path);
-
- if (TYPE(dir) != T_DATA ||
- RDATA(dir)->dfree != (RUBY_DATA_FUNC)free_dir) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Dir)",
- rb_obj_classname(dir));
- }
- return dir;
-}
-
-
-/*
- * call-seq:
- * Dir.foreach( dirname ) {| filename | block } => nil
- *
- * Calls the block once for each entry in the named directory, passing
- * the filename of each entry as a parameter to the block.
- *
- * Dir.foreach("testdir") {|x| puts "Got #{x}" }
- *
- * <em>produces:</em>
- *
- * Got .
- * Got ..
- * Got config.h
- * Got main.rb
- *
- */
-static VALUE
-dir_foreach(io, dirname)
- VALUE io, dirname;
-{
- VALUE dir;
-
- dir = dir_open_dir(dirname);
- rb_ensure(dir_each, dir, dir_close, dir);
- return Qnil;
-}
-
-/*
- * call-seq:
- * Dir.entries( dirname ) => array
- *
- * Returns an array containing all of the filenames in the given
- * directory. Will raise a <code>SystemCallError</code> if the named
- * directory doesn't exist.
- *
- * Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
- *
- */
-static VALUE
-dir_entries(io, dirname)
- VALUE io, dirname;
-{
- VALUE dir;
-
- dir = dir_open_dir(dirname);
- return rb_ensure(rb_Array, dir, dir_close, dir);
-}
-
-/*
- * call-seq:
- * File.fnmatch( pattern, path, [flags] ) => (true or false)
- * File.fnmatch?( pattern, path, [flags] ) => (true or false)
- *
- * Returns true if <i>path</i> matches against <i>pattern</i> The
- * pattern is not a regular expression; instead it follows rules
- * similar to shell filename globbing. It may contain the following
- * metacharacters:
- *
- * <code>*</code>:: Matches any file. Can be restricted by
- * other values in the glob. <code>*</code>
- * will match all files; <code>c*</code> will
- * match all files beginning with
- * <code>c</code>; <code>*c</code> will match
- * all files ending with <code>c</code>; and
- * <code>*c*</code> will match all files that
- * have <code>c</code> in them (including at
- * the beginning or end). Equivalent to
- * <code>/ .* /x</code> in regexp.
- * <code>**</code>:: Matches directories recursively or files
- * expansively.
- * <code>?</code>:: Matches any one character. Equivalent to
- * <code>/.{1}/</code> in regexp.
- * <code>[set]</code>:: Matches any one character in +set+.
- * Behaves exactly like character sets in
- * Regexp, including set negation
- * (<code>[^a-z]</code>).
- * <code>\</code>:: Escapes the next metacharacter.
- *
- * <i>flags</i> is a bitwise OR of the <code>FNM_xxx</code>
- * parameters. The same glob pattern and flags are used by
- * <code>Dir::glob</code>.
- *
- * File.fnmatch('cat', 'cat') #=> true : match entire string
- * File.fnmatch('cat', 'category') #=> false : only match partial string
- * File.fnmatch('c{at,ub}s', 'cats') #=> false : { } isn't supported
- *
- * File.fnmatch('c?t', 'cat') #=> true : '?' match only 1 character
- * File.fnmatch('c??t', 'cat') #=> false : ditto
- * File.fnmatch('c*', 'cats') #=> true : '*' match 0 or more characters
- * File.fnmatch('c*t', 'c/a/b/t') #=> true : ditto
- * File.fnmatch('ca[a-z]', 'cat') #=> true : inclusive bracket expression
- * File.fnmatch('ca[^t]', 'cat') #=> false : exclusive bracket expression ('^' or '!')
- *
- * File.fnmatch('cat', 'CAT') #=> false : case sensitive
- * File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true : case insensitive
- *
- * File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false : wildcard doesn't match '/' on FNM_PATHNAME
- * File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false : ditto
- * File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false : ditto
- *
- * File.fnmatch('\?', '?') #=> true : escaped wildcard becomes ordinary
- * File.fnmatch('\a', 'a') #=> true : escaped ordinary remains ordinary
- * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true : FNM_NOESACPE makes '\' ordinary
- * File.fnmatch('[\?]', '?') #=> true : can escape inside bracket expression
- *
- * File.fnmatch('*', '.profile') #=> false : wildcard doesn't match leading
- * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true period by default.
- * File.fnmatch('.*', '.profile') #=> true
- *
- * rbfiles = File.join("**", "*.rb")
- * File.fnmatch(rbfiles, 'main.rb') #=> false
- * File.fnmatch(rbfiles, './main.rb') #=> false
- * File.fnmatch(rbfiles, 'lib/song.rb') #=> true
- * File.fnmatch('**.rb', 'main.rb') #=> true
- * File.fnmatch('**.rb', './main.rb') #=> false
- * File.fnmatch('**.rb', 'lib/song.rb') #=> true
- * File.fnmatch('*', 'dave/.profile') #=> true
- *
- * File.fnmatch('* IGNORE /*', 'dave/.profile', File::FNM_PATHNAME) #=> false
- * File.fnmatch('* IGNORE /*', 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
- *
- * File.fnmatch('** IGNORE /foo', 'a/b/c/foo', File::FNM_PATHNAME) #=> true
- * File.fnmatch('** IGNORE /foo', '/a/b/c/foo', File::FNM_PATHNAME) #=> true
- * File.fnmatch('** IGNORE /foo', 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
- * File.fnmatch('** IGNORE /foo', 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
- * File.fnmatch('** IGNORE /foo', 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
- */
-static VALUE
-file_s_fnmatch(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE pattern, path;
- VALUE rflags;
- int flags;
-
- if (rb_scan_args(argc, argv, "21", &pattern, &path, &rflags) == 3)
- flags = NUM2INT(rflags);
- else
- flags = 0;
-
- StringValue(pattern);
- StringValue(path);
-
- if (fnmatch(RSTRING(pattern)->ptr, RSTRING(path)->ptr, flags) == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-/*
- * Objects of class <code>Dir</code> are directory streams representing
- * directories in the underlying file system. They provide a variety of
- * ways to list directories and their contents. See also
- * <code>File</code>.
- *
- * The directory used in these examples contains the two regular files
- * (<code>config.h</code> and <code>main.rb</code>), the parent
- * directory (<code>..</code>), and the directory itself
- * (<code>.</code>).
- */
-void
-Init_Dir()
-{
- rb_cDir = rb_define_class("Dir", rb_cObject);
-
- rb_include_module(rb_cDir, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cDir, dir_s_alloc);
- rb_define_singleton_method(rb_cDir, "open", dir_s_open, 1);
- rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, 1);
- rb_define_singleton_method(rb_cDir, "entries", dir_entries, 1);
-
- rb_define_method(rb_cDir,"initialize", dir_initialize, 1);
- rb_define_method(rb_cDir,"path", dir_path, 0);
- rb_define_method(rb_cDir,"inspect", dir_inspect, 0);
- rb_define_method(rb_cDir,"read", dir_read, 0);
- rb_define_method(rb_cDir,"each", dir_each, 0);
- rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
- rb_define_method(rb_cDir,"tell", dir_tell, 0);
- rb_define_method(rb_cDir,"seek", dir_seek, 1);
- rb_define_method(rb_cDir,"pos", dir_tell, 0);
- rb_define_method(rb_cDir,"pos=", dir_set_pos, 1);
- rb_define_method(rb_cDir,"close", dir_close, 0);
-
- rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
- rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
- rb_define_singleton_method(rb_cDir,"pwd", dir_s_getwd, 0);
- rb_define_singleton_method(rb_cDir,"chroot", dir_s_chroot, 1);
- rb_define_singleton_method(rb_cDir,"mkdir", dir_s_mkdir, -1);
- rb_define_singleton_method(rb_cDir,"rmdir", dir_s_rmdir, 1);
- rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
- rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
-
- rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
- rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, 1);
-
- rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
- rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
-
- rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
- rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
- rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
- rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
-}
-/**********************************************************************
-
- dln.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Tue Jan 18 17:05:06 JST 1994
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "dln.h"
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-#ifdef __CHECKER__
-#undef HAVE_DLOPEN
-#undef USE_DLN_A_OUT
-#undef USE_DLN_DLOPEN
-#endif
-
-#ifdef USE_DLN_A_OUT
-char *dln_argv0;
-#endif
-
-#ifdef _AIX
-#pragma alloca
-#endif
-
-#if defined(HAVE_ALLOCA_H)
-#include <alloca.h>
-#endif
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-
-#ifndef xmalloc
-void *xmalloc();
-void *xcalloc();
-void *xrealloc();
-#endif
-
-#include <stdio.h>
-#if defined(_WIN32) || defined(__VMS)
-#include "missing/file.h"
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifndef S_ISDIR
-# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifndef _WIN32
-char *getenv();
-#endif
-
-#if defined(__VMS)
-#pragma builtins
-#include <dlfcn.h>
-#endif
-
-#ifdef __MACOS__
-# include <TextUtils.h>
-# include <CodeFragments.h>
-# include <Aliases.h>
-# include "macruby_private.h"
-#endif
-
-#ifdef __BEOS__
-# include <image.h>
-#endif
-
-int eaccess();
-
-#ifndef NO_DLN_LOAD
-
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(__APPLE__) && !defined(_UNICOSMP)
-/* dynamic load with dlopen() */
-# define USE_DLN_DLOPEN
-#endif
-
-#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && !defined(__ELF__)) || (defined(__OpenBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
-# define FUNCNAME_PATTERN "_Init_%s"
-# else
-# define FUNCNAME_PATTERN "Init_%s"
-# endif
-#endif
-
-static int
-init_funcname_len(buf, file)
- char **buf;
- const char *file;
-{
- char *p;
- const char *slash;
- int len;
-
- /* Load the file as an object one */
- for (slash = file-1; *file; file++) /* Find position of last '/' */
-#ifdef __MACOS__
- if (*file == ':') slash = file;
-#else
- if (*file == '/') slash = file;
-#endif
-
- len = strlen(FUNCNAME_PATTERN) + strlen(slash + 1);
- *buf = xmalloc(len);
- snprintf(*buf, len, FUNCNAME_PATTERN, slash + 1);
- for (p = *buf; *p; p++) { /* Delete suffix if it exists */
- if (*p == '.') {
- *p = '\0'; break;
- }
- }
- return p - *buf;
-}
-
-#define init_funcname(buf, file) do {\
- int len = init_funcname_len(buf, file);\
- char *tmp = ALLOCA_N(char, len+1);\
- if (!tmp) {\
- free(*buf);\
- rb_memerror();\
- }\
- strcpy(tmp, *buf);\
- free(*buf);\
- *buf = tmp;\
-} while (0)
-
-#ifdef USE_DLN_A_OUT
-
-#ifndef LIBC_NAME
-# define LIBC_NAME "libc.a"
-#endif
-
-#ifndef DLN_DEFAULT_LIB_PATH
-# define DLN_DEFAULT_LIB_PATH "/lib:/usr/lib:/usr/local/lib:."
-#endif
-
-#include <errno.h>
-
-static int dln_errno;
-
-#define DLN_ENOEXEC ENOEXEC /* Exec format error */
-#define DLN_ECONFL 1201 /* Symbol name conflict */
-#define DLN_ENOINIT 1202 /* No initializer given */
-#define DLN_EUNDEF 1203 /* Undefine symbol remains */
-#define DLN_ENOTLIB 1204 /* Not a library file */
-#define DLN_EBADLIB 1205 /* Malformed library file */
-#define DLN_EINIT 1206 /* Not initialized */
-
-static int dln_init_p = 0;
-
-#include <ar.h>
-#include <a.out.h>
-#ifndef N_COMM
-# define N_COMM 0x12
-#endif
-#ifndef N_MAGIC
-# define N_MAGIC(x) (x).a_magic
-#endif
-
-#define INVALID_OBJECT(h) (N_MAGIC(h) != OMAGIC)
-
-#include "util.h"
-#include "st.h"
-
-static st_table *sym_tbl;
-static st_table *undef_tbl;
-
-static int load_lib();
-
-static int
-load_header(fd, hdrp, disp)
- int fd;
- struct exec *hdrp;
- long disp;
-{
- int size;
-
- lseek(fd, disp, 0);
- size = read(fd, hdrp, sizeof(struct exec));
- if (size == -1) {
- dln_errno = errno;
- return -1;
- }
- if (size != sizeof(struct exec) || N_BADMAG(*hdrp)) {
- dln_errno = DLN_ENOEXEC;
- return -1;
- }
- return 0;
-}
-
-#if defined(sequent)
-#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
-#define RELOC_MEMORY_SUB_P(r) ((r)->r_bsr)
-#define RELOC_PCREL_P(r) ((r)->r_pcrel || (r)->r_bsr)
-#define RELOC_TARGET_SIZE(r) ((r)->r_length)
-#endif
-
-/* Default macros */
-#ifndef RELOC_ADDRESS
-#define RELOC_ADDRESS(r) ((r)->r_address)
-#define RELOC_EXTERN_P(r) ((r)->r_extern)
-#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
-#define RELOC_MEMORY_SUB_P(r) 0
-#define RELOC_PCREL_P(r) ((r)->r_pcrel)
-#define RELOC_TARGET_SIZE(r) ((r)->r_length)
-#endif
-
-#if defined(sun) && defined(sparc)
-/* Sparc (Sun 4) macros */
-# undef relocation_info
-# define relocation_info reloc_info_sparc
-# define R_RIGHTSHIFT(r) (reloc_r_rightshift[(r)->r_type])
-# define R_BITSIZE(r) (reloc_r_bitsize[(r)->r_type])
-# define R_LENGTH(r) (reloc_r_length[(r)->r_type])
-static int reloc_r_rightshift[] = {
- 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0,
-};
-static int reloc_r_bitsize[] = {
- 8, 16, 32, 8, 16, 32, 30, 22, 22, 22, 13, 10, 32, 32, 16,
-};
-static int reloc_r_length[] = {
- 0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-};
-# define R_PCREL(r) \
- ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)
-# define R_SYMBOL(r) ((r)->r_index)
-#endif
-
-#if defined(sequent)
-#define R_SYMBOL(r) ((r)->r_symbolnum)
-#define R_MEMORY_SUB(r) ((r)->r_bsr)
-#define R_PCREL(r) ((r)->r_pcrel || (r)->r_bsr)
-#define R_LENGTH(r) ((r)->r_length)
-#endif
-
-#ifndef R_SYMBOL
-# define R_SYMBOL(r) ((r)->r_symbolnum)
-# define R_MEMORY_SUB(r) 0
-# define R_PCREL(r) ((r)->r_pcrel)
-# define R_LENGTH(r) ((r)->r_length)
-#endif
-
-static struct relocation_info *
-load_reloc(fd, hdrp, disp)
- int fd;
- struct exec *hdrp;
- long disp;
-{
- struct relocation_info *reloc;
- int size;
-
- lseek(fd, disp + N_TXTOFF(*hdrp) + hdrp->a_text + hdrp->a_data, 0);
- size = hdrp->a_trsize + hdrp->a_drsize;
- reloc = (struct relocation_info*)xmalloc(size);
- if (reloc == NULL) {
- dln_errno = errno;
- return NULL;
- }
-
- if (read(fd, reloc, size) != size) {
- dln_errno = errno;
- free(reloc);
- return NULL;
- }
-
- return reloc;
-}
-
-static struct nlist *
-load_sym(fd, hdrp, disp)
- int fd;
- struct exec *hdrp;
- long disp;
-{
- struct nlist * buffer;
- struct nlist * sym;
- struct nlist * end;
- long displ;
- int size;
-
- lseek(fd, N_SYMOFF(*hdrp) + hdrp->a_syms + disp, 0);
- if (read(fd, &size, sizeof(int)) != sizeof(int)) {
- goto err_noexec;
- }
-
- buffer = (struct nlist*)xmalloc(hdrp->a_syms + size);
- if (buffer == NULL) {
- dln_errno = errno;
- return NULL;
- }
-
- lseek(fd, disp + N_SYMOFF(*hdrp), 0);
- if (read(fd, buffer, hdrp->a_syms + size) != hdrp->a_syms + size) {
- free(buffer);
- goto err_noexec;
- }
-
- sym = buffer;
- end = sym + hdrp->a_syms / sizeof(struct nlist);
- displ = (long)buffer + (long)(hdrp->a_syms);
-
- while (sym < end) {
- sym->n_un.n_name = (char*)sym->n_un.n_strx + displ;
- sym++;
- }
- return buffer;
-
- err_noexec:
- dln_errno = DLN_ENOEXEC;
- return NULL;
-}
-
-static st_table *
-sym_hash(hdrp, syms)
- struct exec *hdrp;
- struct nlist *syms;
-{
- st_table *tbl;
- struct nlist *sym = syms;
- struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist));
-
- tbl = st_init_strtable();
- if (tbl == NULL) {
- dln_errno = errno;
- return NULL;
- }
-
- while (sym < end) {
- st_insert(tbl, sym->n_un.n_name, sym);
- sym++;
- }
- return tbl;
-}
-
-static int
-dln_init(prog)
- const char *prog;
-{
- char *file;
- int fd;
- struct exec hdr;
- struct nlist *syms;
-
- if (dln_init_p == 1) return 0;
-
- file = dln_find_exe(prog, NULL);
- if (file == NULL || (fd = open(file, O_RDONLY)) < 0) {
- dln_errno = errno;
- return -1;
- }
-
- if (load_header(fd, &hdr, 0) == -1) return -1;
- syms = load_sym(fd, &hdr, 0);
- if (syms == NULL) {
- close(fd);
- return -1;
- }
- sym_tbl = sym_hash(&hdr, syms);
- if (sym_tbl == NULL) { /* file may be start with #! */
- char c = '\0';
- char buf[MAXPATHLEN];
- char *p;
-
- free(syms);
- lseek(fd, 0L, 0);
- if (read(fd, &c, 1) == -1) {
- dln_errno = errno;
- return -1;
- }
- if (c != '#') goto err_noexec;
- if (read(fd, &c, 1) == -1) {
- dln_errno = errno;
- return -1;
- }
- if (c != '!') goto err_noexec;
-
- p = buf;
- /* skip forwarding spaces */
- while (read(fd, &c, 1) == 1) {
- if (c == '\n') goto err_noexec;
- if (c != '\t' && c != ' ') {
- *p++ = c;
- break;
- }
- }
- /* read in command name */
- while (read(fd, p, 1) == 1) {
- if (*p == '\n' || *p == '\t' || *p == ' ') break;
- p++;
- if (p-buf >= MAXPATHLEN) {
- dln_errno = ENAMETOOLONG;
- return -1;
- }
- }
- *p = '\0';
-
- return dln_init(buf);
- }
- dln_init_p = 1;
- undef_tbl = st_init_strtable();
- close(fd);
- return 0;
-
- err_noexec:
- close(fd);
- dln_errno = DLN_ENOEXEC;
- return -1;
-}
-
-static long
-load_text_data(fd, hdrp, bss, disp)
- int fd;
- struct exec *hdrp;
- int bss;
- long disp;
-{
- int size;
- unsigned char* addr;
-
- lseek(fd, disp + N_TXTOFF(*hdrp), 0);
- size = hdrp->a_text + hdrp->a_data;
-
- if (bss == -1) size += hdrp->a_bss;
- else if (bss > 1) size += bss;
-
- addr = (unsigned char*)xmalloc(size);
- if (addr == NULL) {
- dln_errno = errno;
- return 0;
- }
-
- if (read(fd, addr, size) != size) {
- dln_errno = errno;
- free(addr);
- return 0;
- }
-
- if (bss == -1) {
- memset(addr + hdrp->a_text + hdrp->a_data, 0, hdrp->a_bss);
- }
- else if (bss > 0) {
- memset(addr + hdrp->a_text + hdrp->a_data, 0, bss);
- }
-
- return (long)addr;
-}
-
-static int
-undef_print(key, value)
- char *key, *value;
-{
- fprintf(stderr, " %s\n", key);
- return ST_CONTINUE;
-}
-
-static void
-dln_print_undef()
-{
- fprintf(stderr, " Undefined symbols:\n");
- st_foreach(undef_tbl, undef_print, NULL);
-}
-
-static void
-dln_undefined()
-{
- if (undef_tbl->num_entries > 0) {
- fprintf(stderr, "dln: Calling undefined function\n");
- dln_print_undef();
- rb_exit(1);
- }
-}
-
-struct undef {
- char *name;
- struct relocation_info reloc;
- long base;
- char *addr;
- union {
- char c;
- short s;
- long l;
- } u;
-};
-
-static st_table *reloc_tbl = NULL;
-static void
-link_undef(name, base, reloc)
- const char *name;
- long base;
- struct relocation_info *reloc;
-{
- static int u_no = 0;
- struct undef *obj;
- char *addr = (char*)(reloc->r_address + base);
-
- obj = (struct undef*)xmalloc(sizeof(struct undef));
- obj->name = strdup(name);
- obj->reloc = *reloc;
- obj->base = base;
- switch (R_LENGTH(reloc)) {
- case 0: /* byte */
- obj->u.c = *addr;
- break;
- case 1: /* word */
- obj->u.s = *(short*)addr;
- break;
- case 2: /* long */
- obj->u.l = *(long*)addr;
- break;
- }
- if (reloc_tbl == NULL) {
- reloc_tbl = st_init_numtable();
- }
- st_insert(reloc_tbl, u_no++, obj);
-}
-
-struct reloc_arg {
- const char *name;
- long value;
-};
-
-static int
-reloc_undef(no, undef, arg)
- int no;
- struct undef *undef;
- struct reloc_arg *arg;
-{
- int datum;
- char *address;
-#if defined(sun) && defined(sparc)
- unsigned int mask = 0;
-#endif
-
- if (strcmp(arg->name, undef->name) != 0) return ST_CONTINUE;
- address = (char*)(undef->base + undef->reloc.r_address);
- datum = arg->value;
-
- if (R_PCREL(&(undef->reloc))) datum -= undef->base;
-#if defined(sun) && defined(sparc)
- datum += undef->reloc.r_addend;
- datum >>= R_RIGHTSHIFT(&(undef->reloc));
- mask = (1 << R_BITSIZE(&(undef->reloc))) - 1;
- mask |= mask -1;
- datum &= mask;
- switch (R_LENGTH(&(undef->reloc))) {
- case 0:
- *address = undef->u.c;
- *address &= ~mask;
- *address |= datum;
- break;
- case 1:
- *(short *)address = undef->u.s;
- *(short *)address &= ~mask;
- *(short *)address |= datum;
- break;
- case 2:
- *(long *)address = undef->u.l;
- *(long *)address &= ~mask;
- *(long *)address |= datum;
- break;
- }
-#else
- switch (R_LENGTH(&(undef->reloc))) {
- case 0: /* byte */
- if (R_MEMORY_SUB(&(undef->reloc)))
- *address = datum - *address;
- else *address = undef->u.c + datum;
- break;
- case 1: /* word */
- if (R_MEMORY_SUB(&(undef->reloc)))
- *(short*)address = datum - *(short*)address;
- else *(short*)address = undef->u.s + datum;
- break;
- case 2: /* long */
- if (R_MEMORY_SUB(&(undef->reloc)))
- *(long*)address = datum - *(long*)address;
- else *(long*)address = undef->u.l + datum;
- break;
- }
-#endif
- free(undef->name);
- free(undef);
- return ST_DELETE;
-}
-
-static void
-unlink_undef(name, value)
- const char *name;
- long value;
-{
- struct reloc_arg arg;
-
- arg.name = name;
- arg.value = value;
- st_foreach(reloc_tbl, reloc_undef, &arg);
-}
-
-#ifdef N_INDR
-struct indr_data {
- char *name0, *name1;
-};
-
-static int
-reloc_repl(no, undef, data)
- int no;
- struct undef *undef;
- struct indr_data *data;
-{
- if (strcmp(data->name0, undef->name) == 0) {
- free(undef->name);
- undef->name = strdup(data->name1);
- }
- return ST_CONTINUE;
-}
-#endif
-
-static int
-load_1(fd, disp, need_init)
- int fd;
- long disp;
- const char *need_init;
-{
- static char *libc = LIBC_NAME;
- struct exec hdr;
- struct relocation_info *reloc = NULL;
- long block = 0;
- long new_common = 0; /* Length of new common */
- struct nlist *syms = NULL;
- struct nlist *sym;
- struct nlist *end;
- int init_p = 0;
-
- if (load_header(fd, &hdr, disp) == -1) return -1;
- if (INVALID_OBJECT(hdr)) {
- dln_errno = DLN_ENOEXEC;
- return -1;
- }
- reloc = load_reloc(fd, &hdr, disp);
- if (reloc == NULL) return -1;
-
- syms = load_sym(fd, &hdr, disp);
- if (syms == NULL) {
- free(reloc);
- return -1;
- }
-
- sym = syms;
- end = syms + (hdr.a_syms / sizeof(struct nlist));
- while (sym < end) {
- struct nlist *old_sym;
- int value = sym->n_value;
-
-#ifdef N_INDR
- if (sym->n_type == (N_INDR | N_EXT)) {
- char *key = sym->n_un.n_name;
-
- if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) {
- if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
- unlink_undef(key, old_sym->n_value);
- free(key);
- }
- }
- else {
- struct indr_data data;
-
- data.name0 = sym->n_un.n_name;
- data.name1 = sym[1].n_un.n_name;
- st_foreach(reloc_tbl, reloc_repl, &data);
-
- st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL);
- if (st_delete(undef_tbl, (st_data_t*)&key, NULL)) {
- free(key);
- }
- }
- sym += 2;
- continue;
- }
-#endif
- if (sym->n_type == (N_UNDF | N_EXT)) {
- if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) {
- old_sym = NULL;
- }
-
- if (value) {
- if (old_sym) {
- sym->n_type = N_EXT | N_COMM;
- sym->n_value = old_sym->n_value;
- }
- else {
- int rnd =
- value >= sizeof(double) ? sizeof(double) - 1
- : value >= sizeof(long) ? sizeof(long) - 1
- : sizeof(short) - 1;
-
- sym->n_type = N_COMM;
- new_common += rnd;
- new_common &= ~(long)rnd;
- sym->n_value = new_common;
- new_common += value;
- }
- }
- else {
- if (old_sym) {
- sym->n_type = N_EXT | N_COMM;
- sym->n_value = old_sym->n_value;
- }
- else {
- sym->n_value = (long)dln_undefined;
- st_insert(undef_tbl, strdup(sym->n_un.n_name), NULL);
- }
- }
- }
- sym++;
- }
-
- block = load_text_data(fd, &hdr, hdr.a_bss + new_common, disp);
- if (block == 0) goto err_exit;
-
- sym = syms;
- while (sym < end) {
- struct nlist *new_sym;
- char *key;
-
- switch (sym->n_type) {
- case N_COMM:
- sym->n_value += hdr.a_text + hdr.a_data;
- case N_TEXT|N_EXT:
- case N_DATA|N_EXT:
-
- sym->n_value += block;
-
- if (st_lookup(sym_tbl, sym->n_un.n_name, &new_sym) != 0
- && new_sym->n_value != (long)dln_undefined) {
- dln_errno = DLN_ECONFL;
- goto err_exit;
- }
-
- key = sym->n_un.n_name;
- if (st_delete(undef_tbl, (st_data_t*)&key, NULL) != 0) {
- unlink_undef(key, sym->n_value);
- free(key);
- }
-
- new_sym = (struct nlist*)xmalloc(sizeof(struct nlist));
- *new_sym = *sym;
- new_sym->n_un.n_name = strdup(sym->n_un.n_name);
- st_insert(sym_tbl, new_sym->n_un.n_name, new_sym);
- break;
-
- case N_TEXT:
- case N_DATA:
- sym->n_value += block;
- break;
- }
- sym++;
- }
-
- /*
- * First comes the text-relocation
- */
- {
- struct relocation_info * rel = reloc;
- struct relocation_info * rel_beg = reloc +
- (hdr.a_trsize/sizeof(struct relocation_info));
- struct relocation_info * rel_end = reloc +
- (hdr.a_trsize+hdr.a_drsize)/sizeof(struct relocation_info);
-
- while (rel < rel_end) {
- char *address = (char*)(rel->r_address + block);
- long datum = 0;
-#if defined(sun) && defined(sparc)
- unsigned int mask = 0;
-#endif
-
- if(rel >= rel_beg)
- address += hdr.a_text;
-
- if (rel->r_extern) { /* Look it up in symbol-table */
- sym = &(syms[R_SYMBOL(rel)]);
- switch (sym->n_type) {
- case N_EXT|N_UNDF:
- link_undef(sym->n_un.n_name, block, rel);
- case N_EXT|N_COMM:
- case N_COMM:
- datum = sym->n_value;
- break;
- default:
- goto err_exit;
- }
- } /* end.. look it up */
- else { /* is static */
- switch (R_SYMBOL(rel)) {
- case N_TEXT:
- case N_DATA:
- datum = block;
- break;
- case N_BSS:
- datum = block + new_common;
- break;
- case N_ABS:
- break;
- }
- } /* end .. is static */
- if (R_PCREL(rel)) datum -= block;
-
-#if defined(sun) && defined(sparc)
- datum += rel->r_addend;
- datum >>= R_RIGHTSHIFT(rel);
- mask = (1 << R_BITSIZE(rel)) - 1;
- mask |= mask -1;
- datum &= mask;
-
- switch (R_LENGTH(rel)) {
- case 0:
- *address &= ~mask;
- *address |= datum;
- break;
- case 1:
- *(short *)address &= ~mask;
- *(short *)address |= datum;
- break;
- case 2:
- *(long *)address &= ~mask;
- *(long *)address |= datum;
- break;
- }
-#else
- switch (R_LENGTH(rel)) {
- case 0: /* byte */
- if (datum < -128 || datum > 127) goto err_exit;
- *address += datum;
- break;
- case 1: /* word */
- *(short *)address += datum;
- break;
- case 2: /* long */
- *(long *)address += datum;
- break;
- }
-#endif
- rel++;
- }
- }
-
- if (need_init) {
- int len;
- char **libs_to_be_linked = 0;
- char *buf;
-
- if (undef_tbl->num_entries > 0) {
- if (load_lib(libc) == -1) goto err_exit;
- }
-
- init_funcname(&buf, need_init);
- len = strlen(buf);
-
- for (sym = syms; sym<end; sym++) {
- char *name = sym->n_un.n_name;
- if (name[0] == '_' && sym->n_value >= block) {
- if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
- libs_to_be_linked = (char**)sym->n_value;
- }
- else if (strcmp(name+1, buf) == 0) {
- init_p = 1;
- ((int (*)())sym->n_value)();
- }
- }
- }
- if (libs_to_be_linked && undef_tbl->num_entries > 0) {
- while (*libs_to_be_linked) {
- load_lib(*libs_to_be_linked);
- libs_to_be_linked++;
- }
- }
- }
- free(reloc);
- free(syms);
- if (need_init) {
- if (init_p == 0) {
- dln_errno = DLN_ENOINIT;
- return -1;
- }
- if (undef_tbl->num_entries > 0) {
- if (load_lib(libc) == -1) goto err_exit;
- if (undef_tbl->num_entries > 0) {
- dln_errno = DLN_EUNDEF;
- return -1;
- }
- }
- }
- return 0;
-
- err_exit:
- if (syms) free(syms);
- if (reloc) free(reloc);
- if (block) free((char*)block);
- return -1;
-}
-
-static int target_offset;
-static int
-search_undef(key, value, lib_tbl)
- const char *key;
- int value;
- st_table *lib_tbl;
-{
- long offset;
-
- if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE;
- target_offset = offset;
- return ST_STOP;
-}
-
-struct symdef {
- int rb_str_index;
- int lib_offset;
-};
-
-char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
-
-static int
-load_lib(lib)
- const char *lib;
-{
- char *path, *file;
- char armagic[SARMAG];
- int fd, size;
- struct ar_hdr ahdr;
- st_table *lib_tbl = NULL;
- int *data, nsym;
- struct symdef *base;
- char *name_base;
-
- if (dln_init_p == 0) {
- dln_errno = DLN_ENOINIT;
- return -1;
- }
-
- if (undef_tbl->num_entries == 0) return 0;
- dln_errno = DLN_EBADLIB;
-
- if (lib[0] == '-' && lib[1] == 'l') {
- char *p = alloca(strlen(lib) + 4);
- sprintf(p, "lib%s.a", lib+2);
- lib = p;
- }
-
- /* library search path: */
- /* look for environment variable DLN_LIBRARY_PATH first. */
- /* then variable dln_librrb_ary_path. */
- /* if path is still NULL, use "." for path. */
- path = getenv("DLN_LIBRARY_PATH");
- if (path == NULL) path = dln_librrb_ary_path;
-
- file = dln_find_file(lib, path);
- fd = open(file, O_RDONLY);
- if (fd == -1) goto syserr;
- size = read(fd, armagic, SARMAG);
- if (size == -1) goto syserr;
-
- if (size != SARMAG) {
- dln_errno = DLN_ENOTLIB;
- goto badlib;
- }
- size = read(fd, &ahdr, sizeof(ahdr));
- if (size == -1) goto syserr;
- if (size != sizeof(ahdr) || sscanf(ahdr.ar_size, "%d", &size) != 1) {
- goto badlib;
- }
-
- if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) {
- /* make hash table from __.SYMDEF */
-
- lib_tbl = st_init_strtable();
- data = (int*)xmalloc(size);
- if (data == NULL) goto syserr;
- size = read(fd, data, size);
- nsym = *data / sizeof(struct symdef);
- base = (struct symdef*)(data + 1);
- name_base = (char*)(base + nsym) + sizeof(int);
- while (nsym > 0) {
- char *name = name_base + base->rb_str_index;
-
- st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr));
- nsym--;
- base++;
- }
- for (;;) {
- target_offset = -1;
- st_foreach(undef_tbl, search_undef, lib_tbl);
- if (target_offset == -1) break;
- if (load_1(fd, target_offset, 0) == -1) {
- st_free_table(lib_tbl);
- free(data);
- goto badlib;
- }
- if (undef_tbl->num_entries == 0) break;
- }
- free(data);
- st_free_table(lib_tbl);
- }
- else {
- /* linear library, need to scan (FUTURE) */
-
- for (;;) {
- int offset = SARMAG;
- int found = 0;
- struct exec hdr;
- struct nlist *syms, *sym, *end;
-
- while (undef_tbl->num_entries > 0) {
- found = 0;
- lseek(fd, offset, 0);
- size = read(fd, &ahdr, sizeof(ahdr));
- if (size == -1) goto syserr;
- if (size == 0) break;
- if (size != sizeof(ahdr)
- || sscanf(ahdr.ar_size, "%d", &size) != 1) {
- goto badlib;
- }
- offset += sizeof(ahdr);
- if (load_header(fd, &hdr, offset) == -1)
- goto badlib;
- syms = load_sym(fd, &hdr, offset);
- if (syms == NULL) goto badlib;
- sym = syms;
- end = syms + (hdr.a_syms / sizeof(struct nlist));
- while (sym < end) {
- if (sym->n_type == N_EXT|N_TEXT
- && st_lookup(undef_tbl, sym->n_un.n_name, NULL)) {
- break;
- }
- sym++;
- }
- if (sym < end) {
- found++;
- free(syms);
- if (load_1(fd, offset, 0) == -1) {
- goto badlib;
- }
- }
- offset += size;
- if (offset & 1) offset++;
- }
- if (found) break;
- }
- }
- close(fd);
- return 0;
-
- syserr:
- dln_errno = errno;
- badlib:
- if (fd >= 0) close(fd);
- return -1;
-}
-
-static int
-load(file)
- const char *file;
-{
- int fd;
- int result;
-
- if (dln_init_p == 0) {
- if (dln_init(dln_argv0) == -1) return -1;
- }
- result = strlen(file);
- if (file[result-1] == 'a') {
- return load_lib(file);
- }
-
- fd = open(file, O_RDONLY);
- if (fd == -1) {
- dln_errno = errno;
- return -1;
- }
- result = load_1(fd, 0, file);
- close(fd);
-
- return result;
-}
-
-void*
-dln_sym(name)
- const char *name;
-{
- struct nlist *sym;
-
- if (st_lookup(sym_tbl, name, &sym))
- return (void*)sym->n_value;
- return NULL;
-}
-
-#endif /* USE_DLN_A_OUT */
-
-#ifdef USE_DLN_DLOPEN
-# include <dlfcn.h>
-#endif
-
-#ifdef __hpux
-#include <errno.h>
-#include "dl.h"
-#endif
-
-#if defined(_AIX)
-#include <ctype.h> /* for isdigit() */
-#include <errno.h> /* for global errno */
-#include <sys/ldr.h>
-#endif
-
-#ifdef NeXT
-#if NS_TARGET_MAJOR < 4
-#include <mach-o/rld.h>
-#else
-#include <mach-o/dyld.h>
-#ifndef NSLINKMODULE_OPTION_BINDNOW
-#define NSLINKMODULE_OPTION_BINDNOW 1
-#endif
-#endif
-#else
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#endif
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
-#include <windows.h>
-#endif
-
-#ifdef _WIN32_WCE
-#undef FormatMessage
-#define FormatMessage FormatMessageA
-#undef LoadLibrary
-#define LoadLibrary LoadLibraryA
-#undef GetProcAddress
-#define GetProcAddress GetProcAddressA
-#endif
-
-static const char *
-dln_strerror()
-{
-#ifdef USE_DLN_A_OUT
- char *strerror();
-
- switch (dln_errno) {
- case DLN_ECONFL:
- return "Symbol name conflict";
- case DLN_ENOINIT:
- return "No initializer given";
- case DLN_EUNDEF:
- return "Unresolved symbols";
- case DLN_ENOTLIB:
- return "Not a library file";
- case DLN_EBADLIB:
- return "Malformed library file";
- case DLN_EINIT:
- return "Not initialized";
- default:
- return strerror(dln_errno);
- }
-#endif
-
-#ifdef USE_DLN_DLOPEN
- return (char*)dlerror();
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
- static char message[1024];
- int error = GetLastError();
- char *p = message;
- p += sprintf(message, "%d: ", error);
- FormatMessage(
- FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- error,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- p,
- sizeof message - strlen(message),
- NULL);
-
- for (p = message; *p; p++) {
- if (*p == '\n' || *p == '\r')
- *p = ' ';
- }
- return message;
-#endif
-}
-
-
-#if defined(_AIX) && ! defined(_IA64)
-static void
-aix_loaderror(const char *pathname)
-{
- char *message[8], errbuf[1024];
- int i,j;
-
- struct errtab {
- int errnum;
- char *errstr;
- } load_errtab[] = {
- {L_ERROR_TOOMANY, "too many errors, rest skipped."},
- {L_ERROR_NOLIB, "can't load library:"},
- {L_ERROR_UNDEF, "can't find symbol in library:"},
- {L_ERROR_RLDBAD,
- "RLD index out of range or bad relocation type:"},
- {L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
- {L_ERROR_MEMBER,
- "file not an archive or does not contain requested member:"},
- {L_ERROR_TYPE, "symbol table mismatch:"},
- {L_ERROR_ALIGN, "text alignment in file is wrong."},
- {L_ERROR_SYSTEM, "System error:"},
- {L_ERROR_ERRNO, NULL}
- };
-
-#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
-#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
-
- snprintf(errbuf, 1024, "load failed - %s ", pathname);
-
- if (!loadquery(1, &message[0], sizeof(message)))
- ERRBUF_APPEND(strerror(errno));
- for(i = 0; message[i] && *message[i]; i++) {
- int nerr = atoi(message[i]);
- for (j=0; j<LOAD_ERRTAB_LEN; j++) {
- if (nerr == load_errtab[i].errnum && load_errtab[i].errstr)
- ERRBUF_APPEND(load_errtab[i].errstr);
- }
- while (isdigit(*message[i])) message[i]++;
- ERRBUF_APPEND(message[i]);
- ERRBUF_APPEND("\n");
- }
- errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
- rb_loaderror(errbuf);
- return;
-}
-#endif
-
-#endif /* NO_DLN_LOAD */
-
diff --git a/tests/examplefiles/example.cpp b/tests/examplefiles/example.cpp
index 4dffc3f7..334e7ca7 100644
--- a/tests/examplefiles/example.cpp
+++ b/tests/examplefiles/example.cpp
@@ -2361,3884 +2361,3 @@ namespace astyle
#ifdef USES_NAMESPACE
using namespace std;
-namespace astyle
- {
-#endif
-
-
- bool ASFormatter::calledInitStatic = false;
- vector<const string*> ASFormatter::headers;
- vector<const string*> ASFormatter::nonParenHeaders;
- vector<const string*> ASFormatter::preprocessorHeaders;
- vector<const string*> ASFormatter::preDefinitionHeaders;
- vector<const string*> ASFormatter::preCommandHeaders;
- vector<const string*> ASFormatter::operators;
- vector<const string*> ASFormatter::assignmentOperators;
-
-
- /**
- * Constructor of ASFormatter
- */
- ASFormatter::ASFormatter()
- {
- staticInit();
-
- preBracketHeaderStack = NULL;
- bracketTypeStack = NULL;
- parenStack = NULL;
-
- sourceIterator = NULL;
- bracketFormatMode = NONE_MODE;
- shouldPadOperators = false;
- shouldPadParenthesies = false;
- shouldBreakOneLineBlocks = true;
- shouldBreakOneLineStatements = true;
- shouldConvertTabs = false;
- shouldBreakBlocks = false;
- shouldBreakClosingHeaderBlocks = false;
- shouldBreakClosingHeaderBrackets = false;
- shouldBreakElseIfs = false;
- }
-
- /**
- * Destructor of ASFormatter
- */
- ASFormatter::~ASFormatter()
- {
- DELETE_CONTAINER( preBracketHeaderStack );
- }
-
- /**
- * initialization of static data of ASFormatter.
- */
- void ASFormatter::staticInit()
- {
- if (calledInitStatic)
- return;
-
- calledInitStatic = true;
-
- headers.push_back(&AS_IF);
- headers.push_back(&AS_ELSE);
- headers.push_back(&AS_DO);
- headers.push_back(&AS_WHILE);
- headers.push_back(&AS_FOR);
- headers.push_back(&AS_SYNCHRONIZED);
- headers.push_back(&AS_TRY);
- headers.push_back(&AS_CATCH);
- headers.push_back(&AS_FINALLY);
- headers.push_back(&AS_SWITCH);
- headers.push_back(&AS_TEMPLATE);
- headers.push_back(&AS_FOREACH);
- headers.push_back(&AS_LOCK);
- headers.push_back(&AS_UNSAFE);
- headers.push_back(&AS_FIXED);
- headers.push_back(&AS_GET);
- headers.push_back(&AS_SET);
- headers.push_back(&AS_ADD);
- headers.push_back(&AS_REMOVE);
-
- nonParenHeaders.push_back(&AS_ELSE);
- nonParenHeaders.push_back(&AS_DO);
- nonParenHeaders.push_back(&AS_TRY);
- nonParenHeaders.push_back(&AS_FINALLY);
- nonParenHeaders.push_back(&AS_UNSAFE);
- nonParenHeaders.push_back(&AS_GET);
- nonParenHeaders.push_back(&AS_SET);
- nonParenHeaders.push_back(&AS_ADD);
- nonParenHeaders.push_back(&AS_REMOVE);
-
- // nonParenHeaders.push_back(&AS_TEMPLATE);
-
- preDefinitionHeaders.push_back(&AS_CLASS);
- preDefinitionHeaders.push_back(&AS_INTERFACE);
- preDefinitionHeaders.push_back(&AS_NAMESPACE);
- preDefinitionHeaders.push_back(&AS_STRUCT);
-
- preCommandHeaders.push_back(&AS_EXTERN);
- preCommandHeaders.push_back(&AS_THROWS);
- preCommandHeaders.push_back(&AS_CONST);
-
- preprocessorHeaders.push_back(&AS_BAR_DEFINE);
- //// DEVEL: removed the folowing lines
- ////preprocessorHeaders.push_back(&AS_BAR_INCLUDE);
- ////preprocessorHeaders.push_back(&AS_BAR_IF); // #if or #ifdef
- ////preprocessorHeaders.push_back(&AS_BAR_EL); // #else or #elif
- ////preprocessorHeaders.push_back(&AS_BAR_ENDIF);
-
- operators.push_back(&AS_PLUS_ASSIGN);
- operators.push_back(&AS_MINUS_ASSIGN);
- operators.push_back(&AS_MULT_ASSIGN);
- operators.push_back(&AS_DIV_ASSIGN);
- operators.push_back(&AS_MOD_ASSIGN);
- operators.push_back(&AS_OR_ASSIGN);
- operators.push_back(&AS_AND_ASSIGN);
- operators.push_back(&AS_XOR_ASSIGN);
- operators.push_back(&AS_EQUAL);
- operators.push_back(&AS_PLUS_PLUS);
- operators.push_back(&AS_MINUS_MINUS);
- operators.push_back(&AS_NOT_EQUAL);
- operators.push_back(&AS_GR_EQUAL);
- operators.push_back(&AS_GR_GR_GR_ASSIGN);
- operators.push_back(&AS_GR_GR_ASSIGN);
- operators.push_back(&AS_GR_GR_GR);
- operators.push_back(&AS_GR_GR);
- operators.push_back(&AS_LS_EQUAL);
- operators.push_back(&AS_LS_LS_LS_ASSIGN);
- operators.push_back(&AS_LS_LS_ASSIGN);
- operators.push_back(&AS_LS_LS_LS);
- operators.push_back(&AS_LS_LS);
- operators.push_back(&AS_ARROW);
- operators.push_back(&AS_AND);
- operators.push_back(&AS_OR);
- operators.push_back(&AS_COLON_COLON);
-
- //// BUGFIX: removed the folowing lines
- //// operators.push_back(&AS_PAREN_PAREN);
- //// operators.push_back(&AS_BLPAREN_BLPAREN);
-
- operators.push_back(&AS_PLUS);
- operators.push_back(&AS_MINUS);
- operators.push_back(&AS_MULT);
- operators.push_back(&AS_DIV);
- operators.push_back(&AS_MOD);
- operators.push_back(&AS_QUESTION);
- operators.push_back(&AS_COLON);
- operators.push_back(&AS_ASSIGN);
- operators.push_back(&AS_LS);
- operators.push_back(&AS_GR);
- operators.push_back(&AS_NOT);
- operators.push_back(&AS_BIT_OR);
- operators.push_back(&AS_BIT_AND);
- operators.push_back(&AS_BIT_NOT);
- operators.push_back(&AS_BIT_XOR);
- operators.push_back(&AS_OPERATOR);
- operators.push_back(&AS_COMMA);
- //BEGIN Content Patch patch1_ssvb_patch.tar.gz
- operators.push_back(&AS_SEMICOLON);
- //END Content Patch patch1_ssvb_patch.tar.gz
- operators.push_back(&AS_RETURN);
-
- assignmentOperators.push_back(&AS_PLUS_ASSIGN);
- assignmentOperators.push_back(&AS_MINUS_ASSIGN);
- assignmentOperators.push_back(&AS_MULT_ASSIGN);
- assignmentOperators.push_back(&AS_DIV_ASSIGN);
- assignmentOperators.push_back(&AS_MOD_ASSIGN);
- assignmentOperators.push_back(&AS_XOR_ASSIGN);
- assignmentOperators.push_back(&AS_OR_ASSIGN);
- assignmentOperators.push_back(&AS_AND_ASSIGN);
- assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
- assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
- assignmentOperators.push_back(&AS_ASSIGN);
- }
-
- /**
- * initialize the ASFormatter.
- *
- * init() should be called every time a ASFormatter object is to start
- * formatting a NEW source file.
- * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
- * that will be used to iterate through the source code. This object will be
- * deleted during the ASFormatter's destruction, and thus should not be
- * deleted elsewhere.
- *
- * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
- */
- void ASFormatter::init(ASSourceIterator *si)
- {
- ASBeautifier::init(si);
- sourceIterator = si;
-
- INIT_CONTAINER( preBracketHeaderStack, new vector<const string*> );
- INIT_CONTAINER( bracketTypeStack, new vector<BracketType> );
- bracketTypeStack->push_back(DEFINITION_TYPE);
- INIT_CONTAINER( parenStack, new vector<int> );
- parenStack->push_back(0);
-
- currentHeader = NULL;
- currentLine = string("");
- formattedLine = "";
- currentChar = ' ';
- previousCommandChar = ' ';
- previousNonWSChar = ' ';
- quoteChar = '"';
- charNum = 0;
- previousOperator = NULL;
-
- isVirgin = true;
- isInLineComment = false;
- isInComment = false;
- isInPreprocessor = false;
- doesLineStartComment = false;
- isInQuote = false;
- isSpecialChar = false;
- isNonParenHeader = true;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- foundQuestionMark = false;
- isInLineBreak = false;
- endOfCodeReached = false;
- isLineReady = false;
- isPreviousBracketBlockRelated = true;
- isInPotentialCalculation = false;
- //foundOneLineBlock = false;
- shouldReparseCurrentChar = false;
- passedSemicolon = false;
- passedColon = false;
- isInTemplate = false;
- shouldBreakLineAfterComments = false;
- isImmediatelyPostComment = false;
- isImmediatelyPostLineComment = false;
- isImmediatelyPostEmptyBlock = false;
-
- isPrependPostBlockEmptyLineRequested = false;
- isAppendPostBlockEmptyLineRequested = false;
- prependEmptyLine = false;
-
- foundClosingHeader = false;
- previousReadyFormattedLineLength = 0;
-
- isImmediatelyPostHeader = false;
- isInHeader = false;
- }
-
- /**
- * get the next formatted line.
- *
- * @return formatted line.
- */
-
- string ASFormatter::nextLine()
- {
- const string *newHeader;
- bool isCharImmediatelyPostComment = false;
- bool isPreviousCharPostComment = false;
- bool isCharImmediatelyPostLineComment = false;
- bool isInVirginLine = isVirgin;
- bool isCharImmediatelyPostOpenBlock = false;
- bool isCharImmediatelyPostCloseBlock = false;
- bool isCharImmediatelyPostTemplate = false;
- bool isCharImmediatelyPostHeader = false;
-
- if (!isFormattingEnabled())
- return ASBeautifier::nextLine();
-
- while (!isLineReady)
- {
- if (shouldReparseCurrentChar)
- shouldReparseCurrentChar = false;
- else if (!getNextChar())
- {
- breakLine();
- return beautify(readyFormattedLine);
- }
- else // stuff to do when reading a new character...
- {
- // make sure that a virgin '{' at the begining ofthe file will be treated as a block...
- if (isInVirginLine && currentChar == '{')
- previousCommandChar = '{';
- isPreviousCharPostComment = isCharImmediatelyPostComment;
- isCharImmediatelyPostComment = false;
- isCharImmediatelyPostTemplate = false;
- isCharImmediatelyPostHeader = false;
- }
-
- if (isInLineComment)
- {
- appendCurrentChar();
-
- // explicitely break a line when a line comment's end is found.
- if (/*bracketFormatMode == ATTACH_MODE &&*/ charNum+1 == currentLine.length())
- {
- isInLineBreak = true;
- isInLineComment = false;
- isImmediatelyPostLineComment = true;
- currentChar = 0; //make sure it is a neutral char.
- }
- continue;
- }
- else if (isInComment)
- {
- if (isSequenceReached(AS_CLOSE_COMMENT))
- {
- isInComment = false;
- isImmediatelyPostComment = true;
- appendSequence(AS_CLOSE_COMMENT);
- goForward(1);
- }
- else
- appendCurrentChar();
-
- continue;
- }
-
- // not in line comment or comment
-
- else if (isInQuote)
- {
- if (isSpecialChar)
- {
- isSpecialChar = false;
- appendCurrentChar();
- }
- else if (currentChar == '\\')
- {
- isSpecialChar = true;
- appendCurrentChar();
- }
- else if (quoteChar == currentChar)
- {
- isInQuote = false;
- appendCurrentChar();
- }
- else
- {
- appendCurrentChar();
- }
-
- continue;
- }
-
-
-
- // handle white space - needed to simplify the rest.
- if (isWhiteSpace(currentChar) || isInPreprocessor)
- {
- ////// DEVEL: if (isLegalNameChar(previousChar) && isLegalNameChar(peekNextChar()))
- appendCurrentChar();
- continue;
- }
-
- /* not in MIDDLE of quote or comment or white-space of any type ... */
-
- if (isSequenceReached(AS_OPEN_LINE_COMMENT))
- {
- isInLineComment = true;
- if (shouldPadOperators)
- appendSpacePad();
- appendSequence(AS_OPEN_LINE_COMMENT);
- goForward(1);
- continue;
- }
- else if (isSequenceReached(AS_OPEN_COMMENT))
- {
- isInComment = true;
- if (shouldPadOperators)
- appendSpacePad();
- appendSequence(AS_OPEN_COMMENT);
- goForward(1);
- continue;
- }
- else if (currentChar == '"' || currentChar == '\'')
- {
- isInQuote = true;
- quoteChar = currentChar;
- //// if (shouldPadOperators) // BUGFIX: these two lines removed. seem to be unneeded, and interfere with L"
- //// appendSpacePad(); // BUFFIX: TODO make sure the removal of these lines doesn't reopen old bugs...
- appendCurrentChar();
- continue;
- }
-
- /* not in quote or comment or white-space of any type ... */
-
-
- // check if in preprocessor
- // ** isInPreprocessor will be automatically reset at the begining
- // of a new line in getnextChar()
- if (currentChar == '#')
- isInPreprocessor = true;
-
- if (isInPreprocessor)
- {
- appendCurrentChar();
- continue;
- }
-
- /* not in preprocessor ... */
-
- if (isImmediatelyPostComment)
- {
- isImmediatelyPostComment = false;
- isCharImmediatelyPostComment = true;
- }
-
- if (isImmediatelyPostLineComment)
- {
- isImmediatelyPostLineComment = false;
- isCharImmediatelyPostLineComment = true;
- }
-
- if (shouldBreakLineAfterComments)
- {
- shouldBreakLineAfterComments = false;
- shouldReparseCurrentChar = true;
- breakLine();
- continue;
- }
-
- // reset isImmediatelyPostHeader information
- if (isImmediatelyPostHeader)
- {
- isImmediatelyPostHeader = false;
- isCharImmediatelyPostHeader = true;
-
- // Make sure headers are broken from their succeeding blocks
- // (e.g.
- // if (isFoo) DoBar();
- // should become
- // if (isFoo)
- // DoBar;
- // )
- // But treat else if() as a special case which should not be broken!
- if (shouldBreakOneLineStatements)
- {
- // if may break 'else if()'s, ythen simply break the line
-
- if (shouldBreakElseIfs)
- isInLineBreak = true;
-
- else
- {
- // make sure 'else if()'s are not broken.
-
- bool isInElseIf = false;
- const string *upcomingHeader;
-
- upcomingHeader = findHeader(headers);
- if (currentHeader == &AS_ELSE && upcomingHeader == &AS_IF)
- isInElseIf = true;
-
- if (!isInElseIf)
- isInLineBreak = true; ////BUGFIX: SHOULD NOT BE breakLine() !!!
- }
- }
- }
-
- if (passedSemicolon)
- {
- passedSemicolon = false;
- if (parenStack->back() == 0)
- {
- shouldReparseCurrentChar = true;
- isInLineBreak = true;
- continue;
- }
- }
-
- if (passedColon)
- {
- passedColon = false;
- if (parenStack->back() == 0)
- {
- shouldReparseCurrentChar = true;
- isInLineBreak = true;
- continue;
- }
- }
-
- // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
- // If so, set isInTemplate to true
- //
- if (!isInTemplate && currentChar == '<')
- {
- int templateDepth = 0;
- const string *oper;
- for (unsigned int i=charNum;
- i< currentLine.length();
- i += (oper ? oper->length() : 1) )
- {
- oper = ASBeautifier::findHeader(currentLine, i, operators);
-
- if (oper == &AS_LS)
- {
- templateDepth++;
- }
- else if (oper == &AS_GR)
- {
- templateDepth--;
- if (templateDepth == 0)
- {
- // this is a template!
- //
- isInTemplate = true;
- break;
- }
- }
- else if (oper == &AS_COMMA // comma, e.g. A<int, char>
- || oper == &AS_BIT_AND // reference, e.g. A<int&>
- || oper == &AS_MULT // pointer, e.g. A<int*>
- || oper == &AS_COLON_COLON) // ::, e.g. std::string
- {
- continue;
- }
- else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
- {
- // this is not a template -> leave...
- //
- isInTemplate = false;
- break;
- }
- }
- }
-
-
- // handle parenthesies
- //
- if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
- {
- parenStack->back()++;
- }
- else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
- {
- parenStack->back()--;
- if (isInTemplate && parenStack->back() == 0)
- {
- isInTemplate = false;
- isCharImmediatelyPostTemplate = true;
- }
-
- // check if this parenthesis closes a header, e.g. if (...), while (...)
- //
- if (isInHeader && parenStack->back() == 0)
- {
- isInHeader = false;
- isImmediatelyPostHeader = true;
- }
-
- }
-
- // handle brackets
- //
- BracketType bracketType = NULL_TYPE;
-
- if (currentChar == '{')
- {
- bracketType = getBracketType();
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
-
- bracketTypeStack->push_back(bracketType);
- preBracketHeaderStack->push_back(currentHeader);
- currentHeader = NULL;
-
- isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
- }
- else if (currentChar == '}')
- {
- // if a request has been made to append a post block empty line,
- // but the block exists immediately before a closing bracket,
- // then there is not need for the post block empty line.
- //
- isAppendPostBlockEmptyLineRequested = false;
-
- if (!bracketTypeStack->empty())
- {
- bracketType = bracketTypeStack->back();
- bracketTypeStack->pop_back();
-
- isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
- }
-
- if (!preBracketHeaderStack->empty())
- {
- currentHeader = preBracketHeaderStack->back();
- preBracketHeaderStack->pop_back();
- }
- else
- currentHeader = NULL;
- }
-
- if (!IS_A(bracketType, ARRAY_TYPE))
- {
-
- if (currentChar == '{')
- {
- parenStack->push_back(0);
- }
- else if (currentChar == '}')
- {
- if (!parenStack->empty())
- {
- parenStack->pop_back();
- }
- }
-
- if (bracketFormatMode != NONE_MODE)
- {
- if (currentChar == '{')
- {
- if ( ( bracketFormatMode == ATTACH_MODE
- || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
- && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], COMMAND_TYPE) /*&& isInLineBreak*/)
- && !isCharImmediatelyPostLineComment )
- {
- appendSpacePad();
- if (!isCharImmediatelyPostComment // do not attach '{' to lines that end with /**/ comments.
- && previousCommandChar != '{'
- && previousCommandChar != '}'
- && previousCommandChar != ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
- appendCurrentChar(false);
- else
- appendCurrentChar(true);
- continue;
- }
- else if (bracketFormatMode == BREAK_MODE
- || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
- && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], DEFINITION_TYPE))
- {
- if ( shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE) )
- breakLine();
- appendCurrentChar();
- continue;
- }
- }
- else if (currentChar == '}')
- {
- // bool origLineBreak = isInLineBreak;
-
- // mark state of immediately after empty block
- // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
- if (previousCommandChar == '{')
- isImmediatelyPostEmptyBlock = true;
-
- if ( (!(previousCommandChar == '{' && isPreviousBracketBlockRelated) ) // this '{' does not close an empty block
- && (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) // astyle is allowed to break on line blocks
- && !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block
- {
- breakLine();
- appendCurrentChar();
- }
- else
- {
- // Content Patch ASFormatter.cpp.patch.bz2
- // if (!isCharImmediatelyPostComment)
- if (!isCharImmediatelyPostComment &&
- !isCharImmediatelyPostLineComment)
- isInLineBreak = false;
- appendCurrentChar();
- if (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
- shouldBreakLineAfterComments = true;
- }
-
- if (shouldBreakBlocks)
- {
- isAppendPostBlockEmptyLineRequested =true;
- }
-
- continue;
- }
- }
- }
-
- if ( ( (previousCommandChar == '{'
- && isPreviousBracketBlockRelated)
-
- || (previousCommandChar == '}'
- && !isImmediatelyPostEmptyBlock // <--
- && isPreviousBracketBlockRelated
- && !isPreviousCharPostComment // <-- Fixes wrongly appended newlines after '}' immediately after comments... 10/9/1999
- && peekNextChar() != ' '))
-
- && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)) )
- {
- isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
- isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
-
- previousCommandChar = ' ';
- isInLineBreak = true; //<----
- }
-
- // reset block handling flags
- isImmediatelyPostEmptyBlock = false;
-
- // look for headers
- if (!isInTemplate)
- {
- if ( (newHeader = findHeader(headers)) != NULL)
- {
- foundClosingHeader = false;
- const string *previousHeader;
-
- // recognize closing headers of do..while, if..else, try..catch..finally
- if ( (newHeader == &AS_ELSE && currentHeader == &AS_IF)
- || (newHeader == &AS_WHILE && currentHeader == &AS_DO)
- || (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
- || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
- || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
- || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH) )
- foundClosingHeader = true;
-
- previousHeader = currentHeader;
- currentHeader = newHeader;
-
- // If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
- // to their preceding bracket,
- // But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
- if (!shouldBreakClosingHeaderBrackets && foundClosingHeader && (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE) && previousNonWSChar == '}')
- {
- isInLineBreak = false;
- appendSpacePad();
-
- if (shouldBreakBlocks)
- isAppendPostBlockEmptyLineRequested = false;
- }
-
- //Check if a template definition as been reached, e.g. template<class A>
- if (newHeader == &AS_TEMPLATE)
- {
- isInTemplate = true;
- }
-
- // check if the found header is non-paren header
- isNonParenHeader = ( find(nonParenHeaders.begin(), nonParenHeaders.end(),
- newHeader) != nonParenHeaders.end() );
- appendSequence(*currentHeader);
- goForward(currentHeader->length() - 1);
- // if padding is on, and a paren-header is found
- // then add a space pad after it.
- if (shouldPadOperators && !isNonParenHeader)
- appendSpacePad();
-
-
- // Signal that a header has been reached
- // *** But treat a closing while() (as in do...while)
- // as if it where NOT a header since a closing while()
- // should never have a block after it!
- if (!(foundClosingHeader && currentHeader == &AS_WHILE))
- {
- isInHeader = true;
- if (isNonParenHeader)
- {
- isImmediatelyPostHeader = true;
- isInHeader = false;
- }
- }
-
- if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
- isInLineBreak = false;
-
- if (shouldBreakBlocks)
- {
- if (previousHeader == NULL
- && !foundClosingHeader
- && !isCharImmediatelyPostOpenBlock)
- {
- isPrependPostBlockEmptyLineRequested = true;
- }
-
- if (currentHeader == &AS_ELSE
- || currentHeader == &AS_CATCH
- || currentHeader == &AS_FINALLY
- || foundClosingHeader)
- {
- isPrependPostBlockEmptyLineRequested = false;
- }
-
- if (shouldBreakClosingHeaderBlocks
- && isCharImmediatelyPostCloseBlock)
- {
- isPrependPostBlockEmptyLineRequested = true;
- }
-
- }
-
- continue;
- }
- else if ( (newHeader = findHeader(preDefinitionHeaders)) != NULL)
- {
- foundPreDefinitionHeader = true;
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
-
- if (shouldBreakBlocks)
- isPrependPostBlockEmptyLineRequested = true;
-
- continue;
- }
- else if ( (newHeader = findHeader(preCommandHeaders)) != NULL)
- {
- foundPreCommandHeader = true;
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
-
- continue;
- }
- }
-
- if (previousNonWSChar == '}' || currentChar == ';')
- {
- if (shouldBreakOneLineStatements && currentChar == ';'
- && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)))
- {
- passedSemicolon = true;
- }
-
- if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
- {
- isAppendPostBlockEmptyLineRequested = true;
- }
-
- if (currentChar != ';')
- currentHeader = NULL; //DEVEL: is this ok?
-
- foundQuestionMark = false;
- foundPreDefinitionHeader = false;
- foundPreCommandHeader = false;
- isInPotentialCalculation = false;
-
- }
-
- if (currentChar == ':'
- && shouldBreakOneLineStatements
- && !foundQuestionMark // not in a ... ? ... : ... sequence
- && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
- && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
- && previousChar != ':' // not part of '::'
- && peekNextChar() != ':') // not part of '::'
- {
- passedColon = true;
- if (shouldBreakBlocks)
- isPrependPostBlockEmptyLineRequested = true;
- }
-
- if (currentChar == '?')
- foundQuestionMark = true;
-
- if (shouldPadOperators)
- {
- if ((newHeader = findHeader(operators)) != NULL)
- {
- bool shouldPad = (newHeader != &AS_COLON_COLON
- && newHeader != &AS_PAREN_PAREN
- && newHeader != &AS_BLPAREN_BLPAREN
- && newHeader != &AS_PLUS_PLUS
- && newHeader != &AS_MINUS_MINUS
- && newHeader != &AS_NOT
- && newHeader != &AS_BIT_NOT
- && newHeader != &AS_ARROW
- && newHeader != &AS_OPERATOR
- && !(newHeader == &AS_MINUS && isInExponent())
- && !(newHeader == &AS_PLUS && isInExponent())
- && previousOperator != &AS_OPERATOR
- && !((newHeader == &AS_MULT || newHeader == &AS_BIT_AND)
- && isPointerOrReference())
- && !( (isInTemplate || isCharImmediatelyPostTemplate)
- && (newHeader == &AS_LS || newHeader == &AS_GR))
- );
-
- if (!isInPotentialCalculation)
- if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
- != assignmentOperators.end())
- isInPotentialCalculation = true;
-
- // pad before operator
- if (shouldPad
- && !(newHeader == &AS_COLON && !foundQuestionMark)
- && newHeader != &AS_SEMICOLON
- && newHeader != &AS_COMMA)
- appendSpacePad();
- appendSequence(*newHeader);
- goForward(newHeader->length() - 1);
-
- // since this block handles '()' and '[]',
- // the parenStack must be updated here accordingly!
- if (newHeader == &AS_PAREN_PAREN
- || newHeader == &AS_BLPAREN_BLPAREN)
- parenStack->back()--;
-
- currentChar = (*newHeader)[newHeader->length() - 1];
- // pad after operator
- // but do not pad after a '-' that is a urinary-minus.
- if ( shouldPad && !(newHeader == &AS_MINUS && isUrinaryMinus()) )
- appendSpacePad();
-
- previousOperator = newHeader;
- continue;
- }
- }
- //BEGIN Content Patch patch1_ssvb_patch.tar.gz
- if (currentChar == '(' || currentChar == '[' )
- isInPotentialCalculation = true;
- //END Content Patch patch1_ssvb_patch.tar.gz
- if (shouldPadParenthesies)
- {
- if (currentChar == '(' || currentChar == '[' )
- {
- char peekedChar = peekNextChar();
-
- isInPotentialCalculation = true;
- appendCurrentChar();
- if (!(currentChar == '(' && peekedChar == ')')
- && !(currentChar == '[' && peekedChar == ']'))
- appendSpacePad();
- continue;
- }
- else if (currentChar == ')' || currentChar == ']')
- {
- char peekedChar = peekNextChar();
-
- if (!(previousChar == '(' && currentChar == ')')
- && !(previousChar == '[' && currentChar == ']'))
- appendSpacePad();
-
- appendCurrentChar();
-
- if (peekedChar != ';' && peekedChar != ',' && peekedChar != '.'
- && !(currentChar == ']' && peekedChar == '['))
- appendSpacePad();
- continue;
- }
- }
-
- appendCurrentChar();
- }
-
- // return a beautified (i.e. correctly indented) line.
-
- string beautifiedLine;
- int readyFormattedLineLength = trim(readyFormattedLine).length();
-
- if (prependEmptyLine
- && readyFormattedLineLength > 0
- && previousReadyFormattedLineLength > 0)
- {
- isLineReady = true; // signal that a readyFormattedLine is still waiting
- beautifiedLine = beautify("");
- }
- else
- {
- isLineReady = false;
- beautifiedLine = beautify(readyFormattedLine);
- }
-
- prependEmptyLine = false;
- previousReadyFormattedLineLength = readyFormattedLineLength;
-
- return beautifiedLine;
-
- }
-
-
- /**
- * check if there are any indented lines ready to be read by nextLine()
- *
- * @return are there any indented lines ready?
- */
- bool ASFormatter::hasMoreLines() const
- {
- if (!isFormattingEnabled())
- return ASBeautifier::hasMoreLines();
- else
- return !endOfCodeReached;
- }
-
- /**
- * check if formatting options are enabled, in addition to indentation.
- *
- * @return are formatting options enabled?
- */
- bool ASFormatter::isFormattingEnabled() const
- {
- return (bracketFormatMode != NONE_MODE
- || shouldPadOperators
- || shouldConvertTabs);
- }
-
- /**
- * set the bracket formatting mode.
- * options:
- * astyle::NONE_MODE no formatting of brackets.
- * astyle::ATTACH_MODE Java, K&R style bracket placement.
- * astyle::BREAK_MODE ANSI C/C++ style bracket placement.
- *
- * @param mode the bracket formatting mode.
- */
- void ASFormatter::setBracketFormatMode(BracketMode mode)
- {
- bracketFormatMode = mode;
- }
-
- /**
- * set closing header bracket breaking mode
- * options:
- * true brackets just before closing headers (e.g. 'else', 'catch')
- * will be broken, even if standard brackets are attached.
- * false closing header brackets will be treated as standard brackets.
- *
- * @param mode the closing header bracket breaking mode.
- */
- void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
- {
- shouldBreakClosingHeaderBrackets = state;
- }
-
- /**
- * set 'else if()' breaking mode
- * options:
- * true 'else' headers will be broken from their succeeding 'if' headers.
- * false 'else' headers will be attached to their succeeding 'if' headers.
- *
- * @param mode the 'else if()' breaking mode.
- */
- void ASFormatter::setBreakElseIfsMode(bool state)
- {
- shouldBreakElseIfs = state;
- }
-
- /**
- * set operator padding mode.
- * options:
- * true statement operators will be padded with spaces around them.
- * false statement operators will not be padded.
- *
- * @param mode the padding mode.
- */
- void ASFormatter::setOperatorPaddingMode(bool state)
- {
- shouldPadOperators = state;
- }
-
- /**
- * set parentheies padding mode.
- * options:
- * true statement parenthesies will be padded with spaces around them.
- * false statement parenthesies will not be padded.
- *
- * @param mode the padding mode.
- */
- void ASFormatter::setParenthesisPaddingMode(bool state)
- {
- shouldPadParenthesies = state;
- }
-
- /**
- * set option to break/not break one-line blocks
- *
- * @param state true = break, false = don't break.
- */
- void ASFormatter::setBreakOneLineBlocksMode(bool state)
- {
- shouldBreakOneLineBlocks = state;
- }
-
- /**
- * set option to break/not break lines consisting of multiple statements.
- *
- * @param state true = break, false = don't break.
- */
- void ASFormatter::setSingleStatementsMode(bool state)
- {
- shouldBreakOneLineStatements = state;
- }
-
- /**
- * set option to convert tabs to spaces.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setTabSpaceConversionMode(bool state)
- {
- shouldConvertTabs = state;
- }
-
-
- /**
- * set option to break unrelated blocks of code with empty lines.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setBreakBlocksMode(bool state)
- {
- shouldBreakBlocks = state;
- }
-
- /**
- * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
- *
- * @param state true = convert, false = don't convert.
- */
- void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
- {
- shouldBreakClosingHeaderBlocks = state;
- }
-
- /**
- * check if a specific sequence exists in the current placement of the current line
- *
- * @return whether sequence has been reached.
- * @param sequence the sequence to be checked
- */
- bool ASFormatter::isSequenceReached(const string &sequence) const
- {
- return currentLine.COMPARE(charNum, sequence.length(), sequence) == 0;
-
- }
-
- /**
- * jump over several characters.
- *
- * @param i the number of characters to jump over.
- */
- void ASFormatter::goForward(int i)
- {
- while (--i >= 0)
- getNextChar();
- }
-
- /**
- * peek at the next unread character.
- *
- * @return the next unread character.
- */
- char ASFormatter::peekNextChar() const
- {
- int peekNum = charNum + 1;
- int len = currentLine.length();
- char ch = ' ';
-
- while (peekNum < len)
- {
- ch = currentLine[peekNum++];
- if (!isWhiteSpace(ch))
- return ch;
- }
-
- if (shouldConvertTabs && ch == '\t')
- ch = ' ';
-
- return ch;
- }
-
- /**
- * check if current placement is before a comment or line-comment
- *
- * @return is before a comment or line-comment.
- */
- bool ASFormatter::isBeforeComment() const
- {
- int peekNum = charNum + 1;
- int len = currentLine.length();
- // char ch = ' ';
- bool foundComment = false;
-
- for (peekNum = charNum + 1;
- peekNum < len && isWhiteSpace(currentLine[peekNum]);
- ++peekNum)
- ;
-
- if (peekNum < len)
- foundComment = ( currentLine.COMPARE(peekNum, 2, AS_OPEN_COMMENT) == 0
- || currentLine.COMPARE(peekNum, 2, AS_OPEN_LINE_COMMENT) == 0 );
-
- return foundComment;
- }
-
- /**
- * get the next character, increasing the current placement in the process.
- * the new character is inserted into the variable currentChar.
- *
- * @return whether succeded to recieve the new character.
- */
- bool ASFormatter::getNextChar()
- {
- isInLineBreak = false;
- bool isAfterFormattedWhiteSpace = false;
-
- if (shouldPadOperators && !isInComment && !isInLineComment
- && !isInQuote && !doesLineStartComment && !isInPreprocessor
- && !isBeforeComment())
- {
- //BEGIN Content Patch patch1_ssvb_patch.tar.gz
- char prevchar = ' ';
- char nextchar = peekNextChar();
-
- int len = formattedLine.length();
- // if (len > 0 && isWhiteSpace(formattedLine[len-1]))
- if (len > 0) prevchar = formattedLine[len-1];
- if (isWhiteSpace(prevchar) || prevchar == '(' || prevchar == '[' ||
- nextchar == ')' || nextchar == ']')
- {
- isAfterFormattedWhiteSpace = true;
- }
- //END Content Patch patch1_ssvb_patch.tar.gz
- }
-
- previousChar = currentChar;
- if (!isWhiteSpace(currentChar))
- {
- previousNonWSChar = currentChar;
- if (!isInComment && !isInLineComment && !isInQuote
- && !isSequenceReached(AS_OPEN_COMMENT)
- && !isSequenceReached(AS_OPEN_LINE_COMMENT) )
- previousCommandChar = previousNonWSChar;
- }
-
- unsigned int currentLineLength = currentLine.length();
-
- if (charNum+1 < currentLineLength
- && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
- {
- currentChar = currentLine[++charNum];
- if (isAfterFormattedWhiteSpace)
- while (isWhiteSpace(currentChar) && charNum+1 < currentLineLength)
- currentChar = currentLine[++charNum];
-
- if (shouldConvertTabs && currentChar == '\t')
- currentChar = ' ';
-
- return true;
- }
- // BEGIN Content patch ASFormatter450670.patch.bz2
- else if (isInLineComment && (charNum+1 == currentLineLength))
- {
- // fix BUG #450670
- currentChar = ' ';
- return true;
- }
- // END Content patch ASFormatter450670.patch.bz2
- else
- {
- if (sourceIterator->hasMoreLines())
- {
- currentLine = sourceIterator->nextLine();
- if (currentLine.length() == 0)
- {
- /*think*/ currentLine = string(" ");
- }
-
- // unless reading in the first line of the file,
- // break a new line.
- if (!isVirgin)
- isInLineBreak = true;
- else
- isVirgin = false;
-
- if (isInLineComment)
- isImmediatelyPostLineComment = true;
- isInLineComment = false;
-
- trimNewLine();
- currentChar = currentLine[charNum];
-
- // check if is in preprocessor right after the line break and line trimming
- if (previousNonWSChar != '\\')
- isInPreprocessor = false;
-
- if (shouldConvertTabs && currentChar == '\t')
- currentChar = ' ';
-
- return true;
- }
- else
- {
- endOfCodeReached = true;
- return false;
- }
- }
- }
-
- /**
- * jump over the leading white space in the current line,
- * IF the line does not begin a comment or is in a preprocessor definition.
- */
- void ASFormatter::trimNewLine()
- {
- unsigned int len = currentLine.length();
- charNum = 0;
-
- if (isInComment || isInPreprocessor)
- return;
-
- while (isWhiteSpace(currentLine[charNum]) && charNum+1 < len)
- ++charNum;
-
- doesLineStartComment = false;
- if (isSequenceReached(string("/*")))
- {
- charNum = 0;
- doesLineStartComment = true;
- }
- }
-
- /**
- * append a character to the current formatted line.
- * Unless disabled (via canBreakLine == false), first check if a
- * line-break has been registered, and if so break the
- * formatted line, and only then append the character into
- * the next formatted line.
- *
- * @param ch the character to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendChar(char ch, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(1, ch);
- }
-
- /**
- * append the CURRENT character (curentChar)to the current
- * formatted line. Unless disabled (via canBreakLine == false),
- * first check if a line-break has been registered, and if so
- * break the formatted line, and only then append the character
- * into the next formatted line.
- *
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendCurrentChar(bool canBreakLine)
- {
- appendChar(currentChar, canBreakLine);
- }
-
- /**
- * append a string sequence to the current formatted line.
- * Unless disabled (via canBreakLine == false), first check if a
- * line-break has been registered, and if so break the
- * formatted line, and only then append the sequence into
- * the next formatted line.
- *
- * @param sequence the sequence to append.
- * @param canBreakLine if true, a registered line-break
- */
- void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
- {
- if (canBreakLine && isInLineBreak)
- breakLine();
- formattedLine.append(sequence);
- }
-
- /**
- * append a space to the current formattedline, UNLESS the
- * last character is already a white-space character.
- */
- void ASFormatter::appendSpacePad()
- {
- int len = formattedLine.length();
- if (len == 0 || !isWhiteSpace(formattedLine[len-1]))
- formattedLine.append(1, ' ');
- }
-
- /**
- * register a line break for the formatted line.
- */
- void ASFormatter::breakLine()
- {
- isLineReady = true;
- isInLineBreak = false;
-
- // queue an empty line prepend request if one exists
- prependEmptyLine = isPrependPostBlockEmptyLineRequested;
-
- readyFormattedLine = formattedLine;
- if (isAppendPostBlockEmptyLineRequested)
- {
- isAppendPostBlockEmptyLineRequested = false;
- isPrependPostBlockEmptyLineRequested = true;
- }
- else
- {
- isPrependPostBlockEmptyLineRequested = false;
- }
-
- formattedLine = "";
- }
-
- /**
- * check if the currently reached open-bracket (i.e. '{')
- * opens a:
- * - a definition type block (such as a class or namespace),
- * - a command block (such as a method block)
- * - a static array
- * this method takes for granted that the current character
- * is an opening bracket.
- *
- * @return the type of the opened block.
- */
- BracketType ASFormatter::getBracketType() const
- {
- BracketType returnVal;
-
- if (foundPreDefinitionHeader)
- returnVal = DEFINITION_TYPE;
- else
- {
- bool isCommandType;
- isCommandType = ( foundPreCommandHeader
- || ( currentHeader != NULL && isNonParenHeader )
- || ( previousCommandChar == ')' )
- || ( previousCommandChar == ':' && !foundQuestionMark )
- || ( previousCommandChar == ';' )
- || ( ( previousCommandChar == '{' || previousCommandChar == '}')
- && isPreviousBracketBlockRelated ) );
-
- returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
- }
-
- if (isOneLineBlockReached())
- returnVal = (BracketType) (returnVal | SINGLE_LINE_TYPE);
-
- return returnVal;
- }
-
- /**
- * check if the currently reached '*' or '&' character is
- * a pointer-or-reference symbol, or another operator.
- * this method takes for granted that the current character
- * is either a '*' or '&'.
- *
- * @return whether current character is a reference-or-pointer
- */
- bool ASFormatter::isPointerOrReference() const
- {
- bool isPR;
- isPR = ( !isInPotentialCalculation
- || IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
- || (!isLegalNameChar(previousNonWSChar)
- && previousNonWSChar != ')'
- && previousNonWSChar != ']')
- );
-
- if (!isPR)
- {
- char nextChar = peekNextChar();
- isPR |= (!isWhiteSpace(nextChar)
- && nextChar != '-'
- && nextChar != '('
- && nextChar != '['
- && !isLegalNameChar(nextChar));
- }
-
- return isPR;
- }
-
-
- /**
- * check if the currently reached '-' character is
- * a urinary minus
- * this method takes for granted that the current character
- * is a '-'.
- *
- * @return whether the current '-' is a urinary minus.
- */
- bool ASFormatter::isUrinaryMinus() const
- {
- return ( (previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
- && previousCommandChar != '.'
- && previousCommandChar != ')'
- && previousCommandChar != ']' );
- }
-
-
- /**
- * check if the currently reached '-' or '+' character is
- * part of an exponent, i.e. 0.2E-5.
- * this method takes for granted that the current character
- * is a '-' or '+'.
- *
- * @return whether the current '-' is in an exponent.
- */
- bool ASFormatter::isInExponent() const
- {
- int formattedLineLength = formattedLine.length();
- if (formattedLineLength >= 2)
- {
- char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
- char prevFormattedChar = formattedLine[formattedLineLength - 1];
-
- return ( (prevFormattedChar == 'e' || prevFormattedChar == 'E')
- && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)) );
- }
- else
- return false;
- }
-
- /**
- * check if a one-line bracket has been reached,
- * i.e. if the currently reached '{' character is closed
- * with a complimentry '}' elsewhere on the current line,
- *.
- * @return has a one-line bracket been reached?
- */
- bool ASFormatter::isOneLineBlockReached() const
- {
- bool isInComment = false;
- bool isInQuote = false;
- int bracketCount = 1;
- int currentLineLength = currentLine.length();
- int i = 0;
- char ch = ' ';
- char quoteChar = ' ';
-
- for (i = charNum + 1; i < currentLineLength; ++i)
- {
- ch = currentLine[i];
-
- if (isInComment)
- {
- if (currentLine.COMPARE(i, 2, "*/") == 0)
- {
- isInComment = false;
- ++i;
- }
- continue;
- }
-
- if (ch == '\\')
- {
- ++i;
- continue;
- }
-
- if (isInQuote)
- {
- if (ch == quoteChar)
- isInQuote = false;
- continue;
- }
-
- if (ch == '"' || ch == '\'')
- {
- isInQuote = true;
- quoteChar = ch;
- continue;
- }
-
- if (currentLine.COMPARE(i, 2, "//") == 0)
- break;
-
- if (currentLine.COMPARE(i, 2, "/*") == 0)
- {
- isInComment = true;
- ++i;
- continue;
- }
-
- if (ch == '{')
- ++bracketCount;
- else if (ch == '}')
- --bracketCount;
-
- if(bracketCount == 0)
- return true;
- }
-
- return false;
- }
-
-
- /**
- * check if one of a set of headers has been reached in the
- * current position of the current line.
- *
- * @return a pointer to the found header. Or a NULL if no header has been reached.
- * @param headers a vector of headers
- * @param checkBoundry
- */
- const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
- {
- return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
- }
-
-
-
-#ifdef USES_NAMESPACE
-}
-#endif
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASFORMATTER_H
-#define ASFORMATTER_H
-
-#include "ASBeautifier.h"
-//#include "enums.h"
-#include "compiler_defines.h"
-
-namespace astyle {
-
- class ASFormatter : public ASBeautifier
- {
- public:
- ASFormatter();
- virtual ~ASFormatter();
- virtual void init(ASSourceIterator* iter);
- virtual bool hasMoreLines() const;
- virtual string nextLine();
- void setBracketFormatMode(BracketMode mode);
- void setBreakClosingHeaderBracketsMode(bool state);
- void setOperatorPaddingMode(bool mode);
- void setParenthesisPaddingMode(bool mode);
- void setBreakOneLineBlocksMode(bool state);
- void setSingleStatementsMode(bool state);
- void setTabSpaceConversionMode(bool state);
- void setBreakBlocksMode(bool state);
- void setBreakClosingHeaderBlocksMode(bool state);
- void setBreakElseIfsMode(bool state);
-
- private:
- void ASformatter(ASFormatter &copy); // not to be imlpemented
- void operator=(ASFormatter&); // not to be implemented
- void staticInit();
- bool isFormattingEnabled() const;
- void goForward(int i);
- bool getNextChar();
- char peekNextChar() const;
- bool isBeforeComment() const;
- void trimNewLine();
- BracketType getBracketType() const;
- bool isPointerOrReference() const;
- bool isUrinaryMinus() const;
- bool isInExponent() const;
- bool isOneLineBlockReached() const;
- void appendChar(char ch, bool canBreakLine = true);
- void appendCurrentChar(bool canBreakLine = true);
- void appendSequence(const string &sequence, bool canBreakLine = true);
- void appendSpacePad();
- void breakLine();
- inline bool isSequenceReached(const string &sequence) const;
- const string *findHeader(const vector<const string*> &headers, bool checkBoundry = true);
-
- static vector<const string*> headers;
- static vector<const string*> nonParenHeaders;
- static vector<const string*> preprocessorHeaders;
- static vector<const string*> preDefinitionHeaders;
- static vector<const string*> preCommandHeaders;
- static vector<const string*> operators;
- static vector<const string*> assignmentOperators;
- static bool calledInitStatic;
-
- ASSourceIterator *sourceIterator;
- vector<const string*> *preBracketHeaderStack;
- vector<BracketType> *bracketTypeStack;
- vector<int> *parenStack;
- string readyFormattedLine;
- string currentLine;
- string formattedLine;
- const string *currentHeader;
- const string *previousOperator;
- char currentChar;
- char previousChar;
- char previousNonWSChar;
- char previousCommandChar;
- char quoteChar;
- unsigned int charNum;
- BracketMode bracketFormatMode;
- bool isVirgin;
- bool shouldPadOperators;
- bool shouldPadParenthesies;
- bool shouldConvertTabs;
- bool isInLineComment;
- bool isInComment;
- bool isInPreprocessor;
- bool isInTemplate; // true both in template definitions (e.g. template<class A>) and template usage (e.g. F<int>).
- bool doesLineStartComment;
- bool isInQuote;
- bool isSpecialChar;
- bool isNonParenHeader;
- bool foundQuestionMark;
- bool foundPreDefinitionHeader;
- bool foundPreCommandHeader;
- bool isInLineBreak;
- bool isInClosingBracketLineBreak;
- bool endOfCodeReached;
- bool isLineReady;
- bool isPreviousBracketBlockRelated;
- bool isInPotentialCalculation;
- //bool foundOneLineBlock;
- bool shouldBreakOneLineBlocks;
- bool shouldReparseCurrentChar;
- bool shouldBreakOneLineStatements;
- bool shouldBreakLineAfterComments;
- bool shouldBreakClosingHeaderBrackets;
- bool shouldBreakElseIfs;
- bool passedSemicolon;
- bool passedColon;
- bool isImmediatelyPostComment;
- bool isImmediatelyPostLineComment;
- bool isImmediatelyPostEmptyBlock;
-
- bool shouldBreakBlocks;
- bool shouldBreakClosingHeaderBlocks;
- bool isPrependPostBlockEmptyLineRequested;
- bool isAppendPostBlockEmptyLineRequested;
-
- bool prependEmptyLine;
- bool foundClosingHeader;
- int previousReadyFormattedLineLength;
-
- bool isInHeader;
- bool isImmediatelyPostHeader;
-
- };
-
-}
-
-#endif
-/*
-* Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
-*
-* ASResource.cpp
-* by Tal Davidson (davidsont@bigfoot.com)
-* This file is a part of "Artistic Style" - an indentater and reformatter
-* of C, C, C# and Java source files.
-*
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
-*/
-
-#include "compiler_defines.h"
-#include "ASResource.h"
-
-#include <string>
-
-
-#ifdef USES_NAMESPACE
-using namespace std;
-
-namespace astyle
- {
-#endif
-
- const string ASResource::AS_IF = string("if");
- const string ASResource::AS_ELSE = string ("else");
- const string ASResource::AS_FOR = string("for");
- const string ASResource::AS_DO = string("do");
- const string ASResource::AS_WHILE = string("while");
- const string ASResource::AS_SWITCH = string ("switch");
- const string ASResource::AS_CASE = string ("case");
- const string ASResource::AS_DEFAULT = string("default");
- const string ASResource::AS_CLASS = string("class");
- const string ASResource::AS_STRUCT = string("struct");
- const string ASResource::AS_UNION = string("union");
- const string ASResource::AS_INTERFACE = string("interface");
- const string ASResource::AS_NAMESPACE = string("namespace");
- const string ASResource::AS_EXTERN = string("extern");
- const string ASResource::AS_PUBLIC = string("public");
- const string ASResource::AS_PROTECTED = string("protected");
- const string ASResource::AS_PRIVATE = string("private");
- const string ASResource::AS_STATIC = string("static");
- const string ASResource::AS_SYNCHRONIZED = string("synchronized");
- const string ASResource::AS_OPERATOR = string("operator");
- const string ASResource::AS_TEMPLATE = string("template");
- const string ASResource::AS_TRY = string("try");
- const string ASResource::AS_CATCH = string("catch");
- const string ASResource::AS_FINALLY = string("finally");
- const string ASResource::AS_THROWS = string("throws");
- const string ASResource::AS_CONST = string("const");
-
- const string ASResource::AS_ASM = string("asm");
-
- const string ASResource::AS_BAR_DEFINE = string("#define");
- const string ASResource::AS_BAR_INCLUDE = string("#include");
- const string ASResource::AS_BAR_IF = string("#if");
- const string ASResource::AS_BAR_EL = string("#el");
- const string ASResource::AS_BAR_ENDIF = string("#endif");
-
- const string ASResource::AS_OPEN_BRACKET = string("{");
- const string ASResource::AS_CLOSE_BRACKET = string("}");
- const string ASResource::AS_OPEN_LINE_COMMENT = string("//");
- const string ASResource::AS_OPEN_COMMENT = string("/*");
- const string ASResource::AS_CLOSE_COMMENT = string("*/");
-
- const string ASResource::AS_ASSIGN = string("=");
- const string ASResource::AS_PLUS_ASSIGN = string("+=");
- const string ASResource::AS_MINUS_ASSIGN = string("-=");
- const string ASResource::AS_MULT_ASSIGN = string("*=");
- const string ASResource::AS_DIV_ASSIGN = string("/=");
- const string ASResource::AS_MOD_ASSIGN = string("%=");
- const string ASResource::AS_OR_ASSIGN = string("|=");
- const string ASResource::AS_AND_ASSIGN = string("&=");
- const string ASResource::AS_XOR_ASSIGN = string("^=");
- const string ASResource::AS_GR_GR_ASSIGN = string(">>=");
- const string ASResource::AS_LS_LS_ASSIGN = string("<<=");
- const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>=");
- const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<=");
- const string ASResource::AS_RETURN = string("return");
-
- const string ASResource::AS_EQUAL = string("==");
- const string ASResource::AS_PLUS_PLUS = string("++");
- const string ASResource::AS_MINUS_MINUS = string("--");
- const string ASResource::AS_NOT_EQUAL = string("!=");
- const string ASResource::AS_GR_EQUAL = string(">=");
- const string ASResource::AS_GR_GR = string(">>");
- const string ASResource::AS_GR_GR_GR = string(">>>");
- const string ASResource::AS_LS_EQUAL = string("<=");
- const string ASResource::AS_LS_LS = string("<<");
- const string ASResource::AS_LS_LS_LS = string("<<<");
- const string ASResource::AS_ARROW = string("->");
- const string ASResource::AS_AND = string("&&");
- const string ASResource::AS_OR = string("||");
- const string ASResource::AS_COLON_COLON = string("::");
- const string ASResource::AS_PAREN_PAREN = string("()");
- const string ASResource::AS_BLPAREN_BLPAREN = string("[]");
-
- const string ASResource::AS_PLUS = string("+");
- const string ASResource::AS_MINUS = string("-");
- const string ASResource::AS_MULT = string("*");
- const string ASResource::AS_DIV = string("/");
- const string ASResource::AS_MOD = string("%");
- const string ASResource::AS_GR = string(">");
- const string ASResource::AS_LS = string("<");
- const string ASResource::AS_NOT = string("!");
- const string ASResource::AS_BIT_OR = string("|");
- const string ASResource::AS_BIT_AND = string("&");
- const string ASResource::AS_BIT_NOT = string("~");
- const string ASResource::AS_BIT_XOR = string("^");
- const string ASResource::AS_QUESTION = string("?");
- const string ASResource::AS_COLON = string(":");
- const string ASResource::AS_COMMA = string(",");
- const string ASResource::AS_SEMICOLON = string(";");
-
- const string ASResource::AS_FOREACH = string("foreach");
- const string ASResource::AS_LOCK = string("lock");
- const string ASResource::AS_UNSAFE = string("unsafe");
- const string ASResource::AS_FIXED = string("fixed");
- const string ASResource::AS_GET = string("get");
- const string ASResource::AS_SET = string("set");
- const string ASResource::AS_ADD = string("add");
- const string ASResource::AS_REMOVE = string("remove");
-
-#ifdef USES_NAMESPACE
-}
-#endif
-
-
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASRES_H
-#define ASRES_H
-
-#include "compiler_defines.h"
-#include "ASStreamIterator.h"
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-namespace astyle {
-
-class ASResource
- {
- public:
- static const string AS_IF, AS_ELSE;
- static const string AS_DO, AS_WHILE;
- static const string AS_FOR;
- static const string AS_SWITCH, AS_CASE, AS_DEFAULT;
- static const string AS_TRY, AS_CATCH, AS_THROWS, AS_FINALLY;
- static const string AS_PUBLIC, AS_PROTECTED, AS_PRIVATE;
- static const string AS_CLASS, AS_STRUCT, AS_UNION, AS_INTERFACE, AS_NAMESPACE, AS_EXTERN;
- static const string AS_STATIC;
- static const string AS_CONST;
- static const string AS_SYNCHRONIZED;
- static const string AS_OPERATOR, AS_TEMPLATE;
- static const string AS_OPEN_BRACKET, AS_CLOSE_BRACKET;
- static const string AS_OPEN_LINE_COMMENT, AS_OPEN_COMMENT, AS_CLOSE_COMMENT;
- static const string AS_BAR_DEFINE, AS_BAR_INCLUDE, AS_BAR_IF, AS_BAR_EL, AS_BAR_ENDIF;
- static const string AS_RETURN;
- static const string AS_ASSIGN, AS_PLUS_ASSIGN, AS_MINUS_ASSIGN, AS_MULT_ASSIGN;
- static const string AS_DIV_ASSIGN, AS_MOD_ASSIGN, AS_XOR_ASSIGN, AS_OR_ASSIGN, AS_AND_ASSIGN;
- static const string AS_GR_GR_ASSIGN, AS_LS_LS_ASSIGN, AS_GR_GR_GR_ASSIGN, AS_LS_LS_LS_ASSIGN;
- static const string AS_EQUAL, AS_PLUS_PLUS, AS_MINUS_MINUS, AS_NOT_EQUAL, AS_GR_EQUAL, AS_GR_GR_GR, AS_GR_GR;
- static const string AS_LS_EQUAL, AS_LS_LS_LS, AS_LS_LS, AS_ARROW, AS_AND, AS_OR;
- static const string AS_COLON_COLON, AS_PAREN_PAREN, AS_BLPAREN_BLPAREN;
- static const string AS_PLUS, AS_MINUS, AS_MULT, AS_DIV, AS_MOD, AS_GR, AS_LS;
- static const string AS_NOT, AS_BIT_XOR, AS_BIT_OR, AS_BIT_AND, AS_BIT_NOT;
- static const string AS_QUESTION, AS_COLON, AS_SEMICOLON, AS_COMMA;
- static const string AS_ASM;
- static const string AS_FOREACH, AS_LOCK, AS_UNSAFE, AS_FIXED;
- static const string AS_GET, AS_SET, AS_ADD, AS_REMOVE;
- };
-}
-#endif
-
-#ifndef ASSOURCEITERATOR_H
-#define ASSOURCEITERATOR_H
-
-#include <string>
-#include "compiler_defines.h"
-
-namespace astyle
- {
-
- class ASSourceIterator
- {
- public:
- virtual bool hasMoreLines() const = 0;
- virtual std::string nextLine() = 0;
- };
-}
-
-#endif
-#include "compiler_defines.h"
-#include "ASStreamIterator.h"
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-using namespace astyle;
-
-ASStreamIterator::ASStreamIterator(istream *in)
-{
- inStream = in;
-}
-
-ASStreamIterator::~ASStreamIterator()
-{
- delete inStream;
-}
-
-
-bool ASStreamIterator::hasMoreLines() const
- {
- if (*inStream)
- return true;
- else
- return false;
- }
-
-/*
-string ASStreamIterator::nextLine()
-{
- char theInChar;
- char peekedChar;
- int theBufferPosn = 0;
-
- //
- // treat '\n', '\r', '\n\r' and '\r\n' as an endline.
- //
- while (theBufferPosn < 2047 && inStream->get(theInChar))
- // while not eof
- {
- if (theInChar != '\n' && theInChar != '\r')
- {
- buffer[theBufferPosn] = theInChar;
- theBufferPosn++;
- }
- else
- {
- peekedChar = inStream->peek();
- if (peekedChar != theInChar && (peekedChar == '\r' || peekedChar == '\n') )
- {
- inStream->get(theInChar);
- }
- break;
- }
- }
- buffer[theBufferPosn] = '\0';
-
- return string(buffer);
-}
-*/
-
-
-string ASStreamIterator::nextLine()
-{
- char *srcPtr;
- char *filterPtr;
-
- inStream->getline(buffer, 2047);
- srcPtr = filterPtr = buffer;
-
- while (*srcPtr != 0)
- {
- if (*srcPtr != '\r')
- *filterPtr++ = *srcPtr;
- srcPtr++;
- }
- *filterPtr = 0;
-
- return string(buffer);
-}
-
-/*
- * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
- *
- * compiler_defines.h (1 January 1999)
- * by Tal Davidson (davidsont@bigfoot.com)
- * This file is a part of "Artistic Style" - an indentater and reformatter
- * of C, C++, C# and Java source files.
- *
- * The "Artistic Style" project, including all files needed to compile it,
- * is free software; you can redistribute it and/or use it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program.
- */
-
-
-#ifndef ASSTREAMITERATOR_H
-#define ASSTREAMITERATOR_H
-
-#include "ASSourceIterator.h"
-
-using namespace std;
-
-namespace astyle
- {
- class ASStreamIterator :
- public ASSourceIterator
- {
- public:
- ASStreamIterator(istream *in);
- virtual ~ASStreamIterator();
- bool hasMoreLines() const;
- string nextLine();
-
- private:
- istream * inStream;
- char buffer[2048];
- };
-
-}
-
-#endif
-/***************************************************************************
- charcodes.cpp - description
- -------------------
- begin : Wed Nov 24 2003
- copyright : (C) 2003 by André imon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-// FILE SHOULD BE REMOVED FROM PROJECT
-
-#ifndef CHAR_CODES
-#define CHAR_CODES
-
-#ifdef _WIN32
-
-#define AUML_LC 228
-#define OUML_LC 246
-#define UUML_LC 252
-
-#define AUML_UC 196
-#define OUML_UC 214
-#define UUML_UC 220
-
-
-#define AACUTE_LC 225
-#define EACUTE_LC 233
-#define OACUTE_LC 243
-#define UACUTE_LC 250
-
-#define AACUTE_UC 193
-#define EACUTE_UC 201
-#define OACUTE_UC 211
-#define UACUTE_UC 218
-
-#define AGRAVE_LC 224
-#define EGRAVE_LC 232
-#define OGRAVE_LC 242
-#define UGRAVE_LC 249
-
-#define AGRAVE_UC 192
-#define EGRAVE_UC 200
-#define OGRAVE_UC 210
-#define UGRAVE_UC 217
-
-#define SZLIG 223
-
-/* DOS CONSOLE CODES
-#define AUML_LC 132
-#define OUML_LC 148
-#define UUML_LC 129
-
-#define AUML_UC 142
-#define OUML_UC 153
-#define UUML_UC 154
-
-
-#define AACUTE_LC 160
-#define EACUTE_LC 130
-#define OACUTE_LC 162
-#define UACUTE_LC 163
-
-#define AACUTE_UC 181
-#define EACUTE_UC 144
-#define OACUTE_UC 224
-#define UACUTE_UC 233
-
-#define AGRAVE_LC 133
-#define EGRAVE_LC 138
-#define OGRAVE_LC 149
-#define UGRAVE_LC 151
-
-#define AGRAVE_UC 183
-#define EGRAVE_UC 212
-#define OGRAVE_UC 227
-#define UGRAVE_UC 235
-
-#define SZLIG 225
-*/
-
-#else
-
-#define AUML_LC 164
-#define OUML_LC 182
-#define UUML_LC 188
-
-#define AUML_UC 132
-#define OUML_UC 150
-#define UUML_UC 156
-
-
-#define AACUTE_LC 161
-#define EACUTE_LC 169
-#define OACUTE_LC 179
-#define UACUTE_LC 186
-
-#define AACUTE_UC 129
-#define EACUTE_UC 137
-#define OACUTE_UC 147
-#define UACUTE_UC 154
-
-#define AGRAVE_LC 160
-#define EGRAVE_LC 168
-#define OGRAVE_LC 178
-#define UGRAVE_LC 185
-
-#define AGRAVE_UC 128
-#define EGRAVE_UC 136
-#define OGRAVE_UC 146
-#define UGRAVE_UC 153
-
-#define SZLIG 159
-
-#endif
-
-#endif
-/***************************************************************************
- cmdlineoptions.cpp - description
- -------------------
- begin : Sun Nov 25 2001
- copyright : (C) 2001 by André Simon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "cmdlineoptions.h"
-
-using namespace std;
-
-/* Siehe man getopt (3)
- Konstruktor legt Optionen und Argumente fest
-*/
-CmdLineOptions::CmdLineOptions(int argc, char *argv[]):
- numberSpaces(0),
- wrappingStyle(highlight::WRAP_DISABLED),
- outputType (highlight::HTML),
- opt_language (false),
- opt_include_style (false),
- opt_help (false),
- opt_version (false),
- opt_verbose (false),
- opt_linenumbers (false),
- opt_style (false),
- opt_batch_mode (false),
- opt_fragment (false) ,
- opt_attach_line_anchors (false),
- opt_show_themes (false),
- opt_show_langdefs (false),
- opt_printindex(false),
- opt_quiet(false),
- opt_xslfo_fop(false),
- opt_replacequotes(false),
- opt_print_progress(false),
- opt_fill_zeroes(false),
- opt_stylepath_explicit(false),
- opt_force_output(false),
- configFileRead(false),
- helpLang("en"),
- charset("ISO-8859-1")
-{
-
- loadConfigurationFile();
-
- int c, option_index = 0;
- static struct option long_options[] =
- {
- {OPT_OUT, 1, 0, S_OPT_OUT},
- {OPT_IN, 1, 0, S_OPT_IN},
- {OPT_SYNTAX, 1, 0, S_OPT_SYNTAX},
- {OPT_VERBOSE, 0, 0, S_OPT_VERBOSE},
- {OPT_INC_STYLE, 0, 0, S_OPT_INC_STYLE},
- {OPT_HELP, 0, 0, S_OPT_HELP},
- {OPT_HELPINT, 1, 0, S_OPT_HELPINT},
- {OPT_LINENO,0,0,S_OPT_LINENO},
- {OPT_STYLE, 1,0,S_OPT_STYLE},
- {OPT_STYLE_OUT, 1, 0,S_OPT_STYLE_OUT},
- {OPT_STYLE_IN, 1, 0,S_OPT_STYLE_IN},
- {OPT_DELTABS,1,0,S_OPT_DELTABS},
- {OPT_XHTML, 0,0,S_OPT_XHTML},
- {OPT_RTF, 0,0,S_OPT_RTF},
- {OPT_TEX,0, 0,S_OPT_TEX},
- {OPT_LATEX,0, 0,S_OPT_LATEX},
- {OPT_XSLFO,0, 0,S_OPT_XSLFO},
- {OPT_ANSI,0, 0,S_OPT_ANSI},
- {OPT_XML,0, 0,S_OPT_XML},
- {OPT_BATCHREC,1,0,S_OPT_BATCHREC},
- {OPT_FRAGMENT,0,0,S_OPT_FRAGMENT},
- {OPT_ANCHORS, 0,0,S_OPT_ANCHORS },
- {OPT_LISTTHEMES, 0,0,S_OPT_LISTTHEMES },
- {OPT_LISTLANGS, 0,0,S_OPT_LISTLANGS },
- {OPT_OUTDIR,1,0,S_OPT_OUTDIR},
- {OPT_VERSION,0,0,0},
- {OPT_FORMATSTYLE,1,0,S_OPT_FORMATSTYLE},
- {OPT_DATADIR,1,0,S_OPT_DATADIR},
- {OPT_ADDDATADIR,1,0,S_OPT_ADDDATADIR},
- {OPT_INDEXFILE,0,0,S_OPT_INDEXFILE},
- {OPT_WRAP,0,0,S_OPT_WRAP},
- {OPT_WRAPSIMPLE,0,0,S_OPT_WRAPSIMPLE},
- {OPT_QUIET,0,0,S_OPT_QUIET},
- {OPT_REPLACE_QUOTES,0,0,S_OPT_REPLACE_QUOTES},
- {OPT_PROGRESSBAR,0,0,S_OPT_PROGRESSBAR},
- {OPT_FILLZEROES,0,0,S_OPT_FILLZEROES},
- {OPT_ENCODING,1,0,S_OPT_ENCODING},
-
- //remove as soon as APAche fixes the bug in FOP (0.20.5)
- {OPT_FOP,0,0,S_OPT_FOP},
-
- //deprecated
- {OPT_CSSOUT,1,0,0},
- {OPT_CSSIN,1,0,0},
- {OPT_INC_CSS,0,0,0},
- {OPT_FORCE_OUTPUT,0,0,0},
-
- {0, 0, 0, 0}
- };
-
- while (1)
- {
- c = getopt_long (argc, argv,S_OPTIONS_STRING,long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0: // long options
- if (long_options[option_index].name==OPT_VERSION) {
- opt_version = true;
- }
- if (long_options[option_index].name==OPT_CSSOUT) {
- styleOutFilename=string(optarg);
- printDeprecatedWarning(OPT_CSSOUT, OPT_STYLE_OUT);
- }
- if (long_options[option_index].name==OPT_CSSIN) {
- styleInFilename=string(optarg);
- printDeprecatedWarning(OPT_CSSIN, OPT_STYLE_IN);
- }
- if (long_options[option_index].name==OPT_INC_CSS) {
- opt_include_style = true;
- printDeprecatedWarning(OPT_INC_CSS, OPT_INC_STYLE);
- }
- if (long_options[option_index].name==OPT_FORCE_OUTPUT) {
- opt_force_output = true;
- }
- break;
- case S_OPT_OUT:
- outFilename=string(optarg);
- break;
- case S_OPT_IN:
- inputFileNames.push_back(string(optarg));
- break;
- case S_OPT_STYLE_OUT:
- styleOutFilename=string(optarg);
- opt_stylepath_explicit=true;
- break;
- case S_OPT_STYLE_IN:
- styleInFilename=string(optarg);
- break;
- case S_OPT_VERBOSE:
- opt_verbose = true;
- break;
- case S_OPT_QUIET:
- opt_quiet = true;
- break;
- case S_OPT_INC_STYLE:
- opt_include_style = true;
- break;
- case S_OPT_HELPINT:
- helpLang=string(optarg);
- case S_OPT_HELP:
- opt_help = true;
- break;
- case S_OPT_LINENO:
- opt_linenumbers = true;
- break;
- case '?':
- //opt_help = true;
- break;
- case S_OPT_STYLE:
- styleName=string(optarg);
- opt_style = true;
- break;
- case S_OPT_SYNTAX:
- language=string(optarg);
- opt_language = true;
- break;
- case S_OPT_DELTABS:
- numberSpaces = StringTools::str2int (string(optarg));
- break;
- case S_OPT_XHTML:
- outputType=highlight::XHTML;
- break;
- case S_OPT_RTF:
- outputType=highlight::RTF;
- break;
- case S_OPT_TEX:
- outputType=highlight::TEX;
- break;
- case S_OPT_LATEX:
- outputType=highlight::LATEX;
- break;
- case S_OPT_XSLFO:
- outputType=highlight::XSLFO;
- break;
- case S_OPT_ANSI:
- outputType=highlight::ANSI;
- break;
- case S_OPT_XML:
- outputType=highlight::XML;
- break;
- case S_OPT_BATCHREC:
- opt_batch_mode = true;
- readDirectory(string(optarg));
- break;
- case S_OPT_FRAGMENT:
- opt_fragment = true;
- break;
- case S_OPT_ANCHORS:
- opt_attach_line_anchors = true;
- break;
- case S_OPT_LISTTHEMES:
- opt_show_themes = true;
- break;
- case S_OPT_LISTLANGS:
- opt_show_langdefs = true;
- break;
- case S_OPT_OUTDIR:
- outDirectory = validateDirPath(string(optarg));
- break;
- case S_OPT_FORMATSTYLE:
- indentScheme =string(optarg);
- break;
- case S_OPT_ENCODING:
- charset =string(optarg);
- break;
- case S_OPT_DATADIR:
- dataDir=validateDirPath(string(optarg));
- break;
- case S_OPT_ADDDATADIR:
- additionalDataDir=validateDirPath(string(optarg));
- break;
- case S_OPT_INDEXFILE:
- opt_printindex=true;
- break;
- case S_OPT_WRAPSIMPLE:
- wrappingStyle = highlight::WRAP_SIMPLE;
- break;
- case S_OPT_WRAP:
- wrappingStyle = highlight::WRAP_DEFAULT;
- break;
- case S_OPT_FOP:
- opt_xslfo_fop=true;
- break;
- case S_OPT_REPLACE_QUOTES:
- opt_replacequotes=true;
- break;
- case S_OPT_PROGRESSBAR:
- opt_print_progress=true;
- break;
- case S_OPT_FILLZEROES:
- opt_fill_zeroes=true;
- break;
- default:
- cerr <<"higlight: Unknown option " <<c<< endl;
- }
- }
-
- if (optind < argc) //still args left
- {
- if (inputFileNames.empty()) {
- while (optind < argc){
- inputFileNames.push_back(string(argv[optind++]));
- }
- }
- } else if (inputFileNames.empty()) {
- inputFileNames.push_back("");
- }
- if (printDebugInfo() && configFileRead) {
- cout << "Configuration file \""<<configFilePath<<"\" was read.\n";
- }
-}
-
-CmdLineOptions::~CmdLineOptions(){
-}
-
-const string &CmdLineOptions::getSingleOutFilename()
- {
- if (!inputFileNames.empty() && !outDirectory.empty()) {
- if (outFilename.empty()) {
- outFilename = outDirectory;
- int delim = getSingleInFilename().find_last_of(Platform::pathSeparator)+1;
- outFilename += getSingleInFilename().substr((delim>-1)?delim:0)
- + getOutFileSuffix();
- }
- }
- return outFilename;
- }
-
-const string &CmdLineOptions::getSingleInFilename() const
- {
- return inputFileNames[0];
- }
-
-const string &CmdLineOptions::getOutDirectory()
- {
- if (!outFilename.empty() && !enableBatchMode()){
- outDirectory=getDirName(outFilename);
- }
- return outDirectory;
- }
-
-const string CmdLineOptions::getStyleOutFilename() const
- {
- if (!styleOutFilename.empty()) return styleOutFilename;
- return (outputType==highlight::HTML ||
- outputType==highlight::XHTML)? "highlight.css":"highlight.sty";
- }
-const string &CmdLineOptions::getStyleInFilename() const
- {
- return styleInFilename;
- }
-int CmdLineOptions::getNumberSpaces() const
- {
- return numberSpaces;
- }
-bool CmdLineOptions::printVersion()const
- {
- return opt_version;
- }
-bool CmdLineOptions::printHelp()const
- {
- return opt_help;
- }
-bool CmdLineOptions::printDebugInfo()const
- {
- return opt_verbose;
- }
-bool CmdLineOptions::quietMode()const
- {
- return opt_quiet;
- }
-bool CmdLineOptions::includeStyleDef()const
- {
- return opt_include_style;
- }
-
-bool CmdLineOptions::formatSupportsExtStyle(){
- return outputType==highlight::HTML ||
- outputType==highlight::XHTML ||
- outputType==highlight::LATEX ||
- outputType==highlight::TEX;
-}
-
-bool CmdLineOptions::printLineNumbers()const
- {
- return opt_linenumbers;
- }
-
-string CmdLineOptions::getStyleName()const
- {
- return ( ( opt_style) ? styleName+".style" : "kwrite.style" );
- }
-bool CmdLineOptions::enableBatchMode()const{
- return inputFileNames.size()>1 || opt_batch_mode;
-}
-bool CmdLineOptions::fragmentOutput()const{
- return opt_fragment;
-}
-string CmdLineOptions::getOutFileSuffix()const{
- switch (outputType){
- case highlight::XHTML: return ".xhtml";
- case highlight::RTF: return ".rtf";
- case highlight::TEX:
- case highlight::LATEX: return ".tex";
- case highlight::XSLFO: return ".fo";
- case highlight::XML: return ".xml";
- default: return ".html";
- }
-}
-string CmdLineOptions::getDirName(const string & path) {
- size_t dirNameLength=path.rfind(Platform::pathSeparator);
- return (dirNameLength==string::npos)?string():path.substr(0, dirNameLength+1);
-}
-bool CmdLineOptions::attachLineAnchors()const{
- return opt_attach_line_anchors;
-}
-bool CmdLineOptions::showThemes()const{
- return opt_show_themes;
-}
-bool CmdLineOptions::showLangdefs()const{
- return opt_show_langdefs;
-}
-bool CmdLineOptions::outDirGiven()const{
- return !outFilename.empty();
-}
-bool CmdLineOptions::fopCompatible() const {
- return opt_xslfo_fop;
-}
-bool CmdLineOptions::replaceQuotes() const {
- return opt_replacequotes;
-}
-bool CmdLineOptions::getFlag( const string& paramVal){
- return StringTools::lowerCase(paramVal)=="true";
-}
-bool CmdLineOptions::formattingEnabled(){
- return !indentScheme.empty();
-}
-bool CmdLineOptions::dataDirGiven()const {
- return !dataDir.empty();
-}
-bool CmdLineOptions::additionalDataDirGiven()const {
- return !additionalDataDir.empty();
-}
-const string &CmdLineOptions::getDataDir() const {
- return dataDir;
-}
-const string &CmdLineOptions::getIndentScheme() const {
- return indentScheme;
-}
-const string &CmdLineOptions::getAdditionalDataDir()const{
- return additionalDataDir;
-}
-const string &CmdLineOptions::getLanguage() const {
- return language;
-}
-const string&CmdLineOptions::getCharSet() const{
- return charset;
-}
-bool CmdLineOptions::printIndexFile() const{
- return opt_printindex && (outputType==highlight::HTML ||
- outputType==highlight::XHTML);
-}
-bool CmdLineOptions::printProgress() const{
- return opt_print_progress;
-}
-bool CmdLineOptions::fillLineNrZeroes() const{
- return opt_fill_zeroes;
-}
-bool CmdLineOptions::syntaxGiven() const{
- return opt_language;
-}
-bool CmdLineOptions::omitEncodingName() const{
- return StringTools::lowerCase(charset)=="none";
-}
-bool CmdLineOptions::forceOutput() const{
- return opt_force_output;
-}
-const string CmdLineOptions::getHelpLang()const{
- return helpLang+".help";
-}
-highlight::WrapMode CmdLineOptions::getWrappingStyle() const {
- return wrappingStyle;
-}
-const vector <string> & CmdLineOptions::getInputFileNames() const{
- return inputFileNames;
-}
-void CmdLineOptions::readDirectory(const string & wildcard){
- // get matching files, use recursive search
- bool directoryOK=Platform::getDirectoryEntries(inputFileNames, wildcard, true);
- if (!directoryOK)
- {
- cerr << "highlight: No files matched the pattern \""
- << wildcard << "\"."<< endl;
- }
-}
-void CmdLineOptions::loadConfigurationFile()
-{
- #ifndef _WIN32
- #ifdef CONFIG_FILE_PATH
- configFilePath=CONFIG_FILE_PATH;
- #else
- char* homeEnv=getenv("HOME");
- if (homeEnv==NULL) return;
- configFilePath=string(homeEnv)+"/.highlightrc";
- #endif
- #else
- configFilePath = Platform::getAppPath() + "highlight.conf";
- #endif
- ConfigurationReader presets(configFilePath);
-
- if (presets.found())
- {
- string paramVal;
- configFileRead=true;
-
- styleOutFilename = presets.getParameter(OPT_STYLE_OUT);
- styleInFilename = presets.getParameter(OPT_STYLE_IN);
- styleName = presets.getParameter(OPT_STYLE);
- opt_style = !styleName.empty();
- language = presets.getParameter(OPT_SYNTAX);
- opt_language = !language.empty();
- numberSpaces = StringTools::str2int(presets.getParameter(OPT_DELTABS));
- indentScheme = presets.getParameter(OPT_FORMATSTYLE);
-
- paramVal = presets.getParameter(OPT_DATADIR);
- if (!paramVal.empty()) {
- dataDir=validateDirPath( paramVal);
- }
- paramVal = presets.getParameter(OPT_ADDDATADIR);
- if (!paramVal.empty()) {
- additionalDataDir=validateDirPath(paramVal);
- }
- paramVal = presets.getParameter(OPT_OUTDIR);
- if (!paramVal.empty()) {
- outDirectory=validateDirPath(paramVal);
- }
- paramVal = presets.getParameter(OPT_ENCODING);
- if (!paramVal.empty()) {
- charset=paramVal;
- }
-
- opt_include_style=getFlag(presets.getParameter(OPT_INC_STYLE));
- opt_verbose=getFlag(presets.getParameter(OPT_VERBOSE));
- opt_linenumbers=getFlag(presets.getParameter(OPT_LINENO));
- opt_fragment=getFlag(presets.getParameter(OPT_FRAGMENT));
- opt_attach_line_anchors=getFlag(presets.getParameter(OPT_ANCHORS));
- opt_printindex=getFlag(presets.getParameter(OPT_INDEXFILE));
- opt_quiet=getFlag(presets.getParameter(OPT_QUIET));
- opt_xslfo_fop=getFlag(presets.getParameter(OPT_FOP));
- opt_replacequotes=getFlag(presets.getParameter(OPT_REPLACE_QUOTES));
- opt_print_progress=getFlag(presets.getParameter(OPT_PROGRESSBAR));
- opt_fill_zeroes=getFlag(presets.getParameter(OPT_FILLZEROES));
-
- if (getFlag(presets.getParameter(OPT_WRAP))) {
- wrappingStyle=highlight::WRAP_DEFAULT;
- }
- if (getFlag(presets.getParameter(OPT_WRAPSIMPLE))) {
- wrappingStyle=highlight::WRAP_SIMPLE;
- }
- if (getFlag(presets.getParameter(OPT_XHTML))) {
- outputType=highlight::XHTML;
- } else if (getFlag(presets.getParameter(OPT_RTF))) {
- outputType=highlight::RTF;
- } else if (getFlag(presets.getParameter(OPT_TEX))) {
- outputType=highlight::TEX;
- } else if (getFlag(presets.getParameter(OPT_LATEX))) {
- outputType=highlight::LATEX;
- } else if (getFlag(presets.getParameter(OPT_XSLFO))) {
- outputType=highlight::XSLFO;
- } else if (getFlag(presets.getParameter(OPT_ANSI))) {
- outputType=highlight::ANSI;
- } else if (getFlag(presets.getParameter(OPT_XML))) {
- outputType=highlight::XML;
- }
- }
-}
-
-string CmdLineOptions::validateDirPath(const string & path){
- return (path[path.length()-1] !=Platform::pathSeparator)?
- path+Platform::pathSeparator : path;
-}
-
-highlight::OutputType CmdLineOptions::getOutputType() const {
- return outputType;
-}
-
-void CmdLineOptions::printDeprecatedWarning(const char *oldOption, const char *newOption){
- cerr << "Warning: Long option \""<<oldOption << "\" is DEPRECATED.";
- cerr << " Use \""<<newOption << "\" instead.\n";
-}
-/***************************************************************************
- cmdlineoptions.h - description
- -------------------
- begin : Sun Nov 25 2001
- copyright : (C) 2001 by André Simon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef CMDLINEOPTIONS_H
-#define CMDLINEOPTIONS_H
-
-#include <string>
-#include <map>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-
-#include "platform_fs.h"
-#include "configurationreader.h"
-#include "datadir.h"
-#include "enums.h"
-
-#ifdef _WIN32
- #include <windows.h>
-#endif
-
-// If your system does not know getopt_long, define USE_LOCAL_GETOPT
-#if defined(_WIN32) || defined(__SVR4) || defined(__sun__)
- // some compilers don't like redefinitions...
- #ifndef USE_LOCAL_GETOPT
- #define USE_LOCAL_GETOPT
- #endif
-#endif
-
-#ifdef USE_LOCAL_GETOPT
- #include "getopt.h"
-#else
- #include <getopt.h>
-#endif
-
-#define OPT_VERBOSE "verbose"
-#define OPT_INC_STYLE "include-style"
-#define OPT_HELP "help"
-#define OPT_LINENO "linenumbers"
-#define OPT_XHTML "xhtml"
-#define OPT_RTF "rtf"
-#define OPT_TEX "tex"
-#define OPT_LATEX "latex"
-#define OPT_XSLFO "xsl-fo"
-#define OPT_FRAGMENT "fragment"
-#define OPT_ANCHORS "anchors"
-#define OPT_LISTTHEMES "list-themes"
-#define OPT_LISTLANGS "list-langs"
-#define OPT_VERSION "version"
-#define OPT_IN "input"
-#define OPT_OUT "output"
-#define OPT_SYNTAX "syntax"
-#define OPT_STYLE "style"
-#define OPT_STYLE_OUT "style-outfile"
-#define OPT_STYLE_IN "style-infile"
-
-#define OPT_DELTABS "replace-tabs"
-#define OPT_BATCHREC "batch-recursive"
-#define OPT_OUTDIR "outdir"
-#define OPT_FORMATSTYLE "format-style"
-#define OPT_DATADIR "data-dir"
-#define OPT_ADDDATADIR "add-data-dir"
-#define OPT_INDEXFILE "print-index"
-#define OPT_HELPINT "help-int"
-#define OPT_WRAP "wrap"
-#define OPT_WRAPSIMPLE "wrap-simple"
-#define OPT_QUIET "quiet"
-#define OPT_REPLACE_QUOTES "replace-quotes"
-#define OPT_FOP "fop-compatible"
-#define OPT_PROGRESSBAR "progress"
-#define OPT_FILLZEROES "zeroes"
-#define OPT_ANSI "ansi"
-#define OPT_XML "xml"
-#define OPT_ENCODING "encoding"
-#define OPT_FORCE_OUTPUT "force"
-
-#define S_OPT_ANSI 'A'
-#define S_OPT_OUT 'o'
-#define S_OPT_IN 'i'
-#define S_OPT_SYNTAX 'S'
-#define S_OPT_VERBOSE 'v'
-#define S_OPT_INC_STYLE 'I'
-#define S_OPT_HELP 'h'
-#define S_OPT_HELPINT 'H'
-#define S_OPT_LINENO 'l'
-#define S_OPT_STYLE 's'
-#define S_OPT_STYLE_OUT 'c'
-#define S_OPT_STYLE_IN 'e'
-#define S_OPT_DELTABS 't'
-#define S_OPT_XHTML 'X'
-#define S_OPT_RTF 'R'
-#define S_OPT_TEX 'T'
-#define S_OPT_LATEX 'L'
-#define S_OPT_XSLFO 'Y'
-#define S_OPT_XML 'Z'
-#define S_OPT_BATCHREC 'B'
-#define S_OPT_FRAGMENT 'f'
-#define S_OPT_ANCHORS 'a'
-#define S_OPT_LISTTHEMES 'w'
-#define S_OPT_LISTLANGS 'p'
-#define S_OPT_OUTDIR 'O'
-
-#define S_OPT_FORMATSTYLE 'F'
-#define S_OPT_DATADIR 'D'
-#define S_OPT_ADDDATADIR 'E'
-#define S_OPT_INDEXFILE 'C'
-#define S_OPT_WRAP 'W'
-#define S_OPT_WRAPSIMPLE 'V'
-#define S_OPT_QUIET 'q'
-#define S_OPT_FOP 'g'
-#define S_OPT_REPLACE_QUOTES 'r'
-#define S_OPT_VERSION 'Q'
-#define S_OPT_PROGRESSBAR 'P'
-#define S_OPT_FILLZEROES 'z'
-#define S_OPT_ENCODING 'u'
-
-// deprecated:
-#define OPT_CSSOUT "css-outfile"
-#define OPT_CSSIN "css-infile"
-#define OPT_INC_CSS "include-css"
-
-
-#define S_OPTIONS_STRING "o:i:S:B:O:s:c:e:t:u:F:D:H:E:afghlvwpqrzACILYRTZXUV::W::P"
-
-using namespace std;
-
-/**Command line options*/
-
-class CmdLineOptions
- {
- public:
-
- /**Constructor
- \param argc Argument count
- \param argv Argument strings
- */
- CmdLineOptions(int argc, char *argv[]);
- ~CmdLineOptions();
-
- /** \return Single output file name*/
- const string &getSingleOutFilename();
-
- /** \return Single input file name*/
- const string &getSingleInFilename() const;
-
- /** \return Output directory*/
- const string& getOutDirectory() ;
-
- /** \return Style output file name*/
- const string getStyleOutFilename() const;
-
- /** \return Style input file name*/
- const string&getStyleInFilename() const;
-
- /** \return Char set*/
- const string&getCharSet() const;
-
- /** \return Number of spaces to replace a tab*/
- int getNumberSpaces() const;
-
- /** \return True if version information should be printed*/
- bool printVersion() const;
-
- /** \return True if help information should be printed*/
- bool printHelp() const;
-
- /** \return True if debug information should be printed*/
- bool printDebugInfo()const;
-
- /** \return True if Style definition should be included in output*/
- bool includeStyleDef() const;
-
- /** \return True if line numbers should be printed*/
- bool printLineNumbers() const;
-
- /** \return colour theme name */
- string getStyleName()const ;
-
- /** gibt true zurck, falls deutsche Hilfe ausgegeben werden soll */
- int helpLanguage() const;
-
- /** \return True if batch mode is active*/
- bool enableBatchMode() const;
-
- /** \return True if output shluld be fragmented*/
- bool fragmentOutput() const;
-
- /** \return output file suffix */
- string getOutFileSuffix() const;
-
- /** \return True if anchors should be attached to line numbers*/
- bool attachLineAnchors() const;
-
- /** \return True if list of installed themes should be printed*/
- bool showThemes() const;
-
- /** \return True if list of installed language definitions should be printed*/
- bool showLangdefs() const;
-
- /** \return True if loutput directory is given*/
- bool outDirGiven() const;
-
- /** \return True if refomatting is enabled*/
- bool formattingEnabled();
-
- /** \return True if a new data directory is given*/
- bool dataDirGiven()const;
-
- /** \return True if an additional data directory is given*/
- bool additionalDataDirGiven()const;
-
- /** \return True if index file should be printed*/
- bool printIndexFile() const;
-
- /** \return True if quotes should be replaced by /dq in LaTeX*/
- bool replaceQuotes() const;
-
- /** \return Data directory*/
- const string &getDataDir()const;
-
- /** \return Additional data directory*/
- const string &getAdditionalDataDir()const;
-
- /** \return True if language syntax is given*/
- bool syntaxGiven() const;
-
- /** \return True if quiet mode is active*/
- bool quietMode() const;
-
- /** \return True if XSL-FO output should be FOP compatible*/
- bool fopCompatible() const;
-
- /** \return True if progress bar should be printed in batch mode */
- bool printProgress() const;
-
- /** \return True if line numbers are filled with leading zeroes */
- bool fillLineNrZeroes() const;
-
- /** \return name of help message file*/
- const string getHelpLang() const;
-
- /** \return programming language */
- const string &getLanguage()const ;
-
- /** \return Wrapping style*/
- highlight::WrapMode getWrappingStyle() const;
-
- /** \return List of input file names*/
- const vector <string> & getInputFileNames() const;
-
- /** \return Name of indentation scheme file */
- const string &getIndentScheme() const;
-
- /** \return Output file format */
- highlight::OutputType getOutputType() const;
-
- /** \return True if chosen output format supports referenced style files */
- bool formatSupportsExtStyle();
-
- /** \return True if style output path was defined by user*/
- bool styleOutPathDefined() const{
- return opt_stylepath_explicit;
- }
-
- /** \return True if encoding nasme should be omitted in output*/
- bool omitEncodingName() const;
-
- /** \return True if output should be generated if languege type is unknown*/
- bool forceOutput() const;
-
- private:
-
- int numberSpaces; // number of spaces which replace a tab
- highlight::WrapMode wrappingStyle; // line wrapping mode
- highlight::OutputType outputType;
-
- // name of single output file
- string outFilename,
- // output directory
- outDirectory,
- // programming language which will be loaded
- language,
- // name of colour theme
- styleName,
- // name of external style file
- styleOutFilename,
- // name of file to be included in external style file
- styleInFilename,
- // used to define data directories at runtime
- dataDir, additionalDataDir;
- // name of indenation scheme
- string indentScheme;
-
- bool opt_language;
- bool opt_include_style;
- bool opt_help;
- bool opt_version ;
- bool opt_verbose;
- bool opt_linenumbers;
- bool opt_style;
- bool opt_batch_mode;
- bool opt_fragment;
- bool opt_attach_line_anchors;
- bool opt_show_themes;
- bool opt_show_langdefs;
- bool opt_asformat_output;
- bool opt_printindex;
- bool opt_quiet;
- bool opt_xslfo_fop;
- bool opt_replacequotes;
- bool opt_print_progress;
- bool opt_fill_zeroes;
- bool opt_stylepath_explicit;
- bool opt_force_output;
-
- bool configFileRead;
-
- string helpLang, charset;
- string configFilePath;
-
- // list of all input file names
- vector <string> inputFileNames;
-
- /** load highlight configuration file */
- void loadConfigurationFile();
-
- /** \return file suffix */
- string getFileSuffix( const string & fileName) const;
-
- /** \return directory name of path */
- string getDirName( const string & path);
-
- /** get all entries in the directory defined by wildcard */
- void readDirectory(const string & wildcard);
-
- /** \return Boolean value of paramVal */
- bool getFlag(const string& paramVal);
-
- /** \return Valid path name */
- string validateDirPath(const string & path);
-
- void printDeprecatedWarning(const char *oldOption, const char *newOption);
- };
-
-#endif
-/***************************************************************************
- codeparser.cpp - description
- -------------------
- begin : Die Jul 9 2002
- copyright : (C) 2002 by André Simon
- email : andre.simon1@gmx.de
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "codegenerator.h"
-
-#include "htmlgenerator.h"
-#include "xhtmlgenerator.h"
-#include "rtfgenerator.h"
-#include "latexgenerator.h"
-#include "texgenerator.h"
-#include "xslfogenerator.h"
-#include "xmlgenerator.h"
-#ifndef __WXMSW__
- #include "ansigenerator.h"
-#endif
-
-
-using namespace std;
-
-namespace highlight {
-
-CodeGenerator* CodeGenerator::generator=NULL;
-
-CodeGenerator* CodeGenerator::getInstance(OutputType type,
- const string& styleInfoPath,
- const string& styleInPath,
- const string& styleOutPath,
- const string& encoding,
- bool includeStyle,
- bool attachAnchors,
- bool replaceQuotes,
- bool fopCompatible,
- int numSpaces,
- WrapMode lineWrappingMode,
- bool ln,
- bool lnz,
- bool fragment,
- bool omitEncoding
- ) {
- if (generator==NULL){
- switch (type){
- case TEX:
- generator = new TexGenerator (styleInfoPath);
- break;
- case LATEX:
- generator = new LatexGenerator(styleInfoPath, replaceQuotes);
- break;
- case RTF:
- generator = new RtfGenerator (styleInfoPath);
- break;
- case XSLFO:
- generator = new XslFoGenerator(styleInfoPath, encoding, omitEncoding,
- fopCompatible);
- break;
- case XML:
- generator = new XmlGenerator(styleInfoPath,encoding, omitEncoding);
- break;
- case XHTML:
- generator = new XHtmlGenerator(styleInfoPath, encoding, omitEncoding,
- attachAnchors);
- break;
- #ifndef __WXMSW__
- case ANSI:
- generator = new AnsiGenerator (styleInfoPath);
- break;
- #endif
- default:
- generator = new HtmlGenerator(styleInfoPath, encoding, omitEncoding,
- attachAnchors);
- }
- }
- generator->setType(type);
- generator->setStyleInputPath(styleInPath);
- generator->setStyleOutputPath(styleOutPath);
- generator->setIncludeStyle(includeStyle);
- generator->setPrintLineNumbers(ln);
- generator->setPrintZeroes(lnz);
- generator->setFragmentCode(fragment);
- generator->setPreformatting(lineWrappingMode,
- (generator->getPrintLineNumbers()) ?
- MAX_LINE__WIDTH - LINE_NUMBER_WIDTH : MAX_LINE__WIDTH,
- numSpaces );
- return generator;
-}
-
-void CodeGenerator::deleteInstance(){
- delete generator;
- generator=NULL;
-}
-
-
-CodeGenerator::CodeGenerator():
- in(NULL),
- out(NULL),
- maskWs(false),
- excludeWs(false),
- fragmentOutput(false),
- showLineNumbers (false),
- lineNumberFillZeroes(false),
- lineNumber(0),
- includeStyleDef(false),
- lineIndex(0),
- formatter(NULL),
- preFormatter(NULL),
- formattingEnabled(false),
- formattingPossible(false),
- outputType(highlight::HTML)
-{}
-
-CodeGenerator::CodeGenerator(const string &colourTheme)
- :in(NULL),
- out(NULL),
- maskWs(false),
- excludeWs(false),
- fragmentOutput(false),
- showLineNumbers (false),
- lineNumberFillZeroes(false),
- lineNumber(0),
- includeStyleDef(false),
- stylePath(colourTheme),
- lineIndex(0),
- formatter(NULL),
- preFormatter(NULL),
- formattingEnabled(false),
- formattingPossible(false),
- outputType(highlight::HTML)
-{
- line.reserve(100);
- docStyle.load(stylePath);
-}
-
-CodeGenerator::~CodeGenerator()
-{
- delete preFormatter;
- delete formatter;
-}
-
-
-/** Getter and Setter*/
-
-void CodeGenerator::setPrintLineNumbers(bool flag){
- showLineNumbers=flag;
-}
-
-bool CodeGenerator::getPrintLineNumbers(){
- return showLineNumbers;
-}
-
-void CodeGenerator::setPrintZeroes(bool flag){
- lineNumberFillZeroes=flag;
-}
-
-bool CodeGenerator::getPrintZeroes(){
- return lineNumberFillZeroes;
-}
-
-void CodeGenerator::setFragmentCode(bool flag){
- fragmentOutput=flag;
-}
-
-void CodeGenerator::setIncludeStyle(bool flag){
- includeStyleDef = flag;
-}
-
-void CodeGenerator::setStyleInputPath(const string& path){
- styleInputPath = path;
-}
-void CodeGenerator::setStyleOutputPath(const string& path){
- styleOutputPath = path;
-}
-
-const string& CodeGenerator::getStyleInputPath(){
- return styleInputPath;
-}
-const string& CodeGenerator::getStyleOutputPath(){
- return styleOutputPath;
-}
-
-
-bool CodeGenerator::getFragmentCode(){
- return fragmentOutput;
-}
-
-void CodeGenerator::setStyleName(const string& s){
- stylePath=s;
-}
-
-void CodeGenerator::setType(OutputType t){
- outputType = t;
-}
-
-const string& CodeGenerator::getStyleName(){
- return stylePath;
-}
-
-bool CodeGenerator::formattingDisabled(){
- return !formattingEnabled;
-}
-
-bool CodeGenerator::formattingIsPossible(){
- return formattingPossible;
-}
-
-void CodeGenerator::setPreformatting(WrapMode lineWrappingStyle,
- unsigned int lineLength,
- int numberSpaces ){
- bool enableWrap = lineWrappingStyle!=WRAP_DISABLED;
- bool replaceTabs = numberSpaces > 0;
- if (enableWrap || replaceTabs) {
- preFormatter=new PreFormatter(enableWrap, replaceTabs);
- if (enableWrap)
- preFormatter->setWrappingProperties(lineLength, lineWrappingStyle==WRAP_DEFAULT);
- if (replaceTabs)
- preFormatter->setNumberSpaces(numberSpaces);
- }
-}
-
-/*
-WrapMode CodeGenerator::getLineWrapping(){
- if (preFormatter==NULL) return WRAP_DISABLED;
- return (preFormatter->indentCode()?WRAP_DEFAULT:WRAP_SIMPLE);
-}
-*/
-LanguageDefinition &CodeGenerator::getLanguage(){
- return langInfo;
-}
-
-void CodeGenerator::reset()
-{
- lineIndex = lineNumber = 0;
- line.clear();
-}
-
-
-/** sucht vorwaerts ab Position searchPos Ziffer in s und liefert Integerwert
-der gefundenen Zahl zurueck.
-Im SymbolString stehen die den einzelnen Symbolen zugeordneten Konstanten
-immer HINTER diesen Symbolen*/
-State CodeGenerator::getState(const string &s, unsigned int searchPos)
-{
- unsigned int i= searchPos+1, result=0;
-
- // nach Ziffer in s suchen
- do {
- ++i;
- } while ((i<s.length()) && !isdigit(s[i])) ;
-
- // Zahl zusammensetzen
- while ((i<s.length()) && isdigit(s[i])){
- result = result *10 + (s[i]-'0');
- ++i;
- }
- return ((result)? (State)result:_UNKNOWN);
-}
-
-string CodeGenerator::getIdentifier()
-{
- --lineIndex;
- unsigned int startPos=lineIndex;
- char c= line[lineIndex];
-
- while ( ( lineIndex < line.length()
- && ( StringTools::isAlpha(c)
- || isdigit(c))
- || isAllowedChar(c))
- )
- {
- ++lineIndex;
- c= line[lineIndex];
- }
- return string(line, startPos, lineIndex - startPos);
-}
-
-string CodeGenerator::getNumber()
-{
- --lineIndex;
- unsigned int startPos=lineIndex;
- char c=line[lineIndex];
-
- while ( lineIndex < line.length() && (
- isdigit(c)
- // don't highlight methods applied on numbers as part of the number
- // i.e. Ruby: 3.xxx()
- || (c == '.' && isdigit(line[lineIndex+1]))
- // '-' is accepted as first character
- || (c == '-' && lineIndex == startPos)
- || (StringTools::isAlpha(c) && line[lineIndex-1]=='0')
- || (isxdigit(c) || c=='L' || c=='U' || c=='l' || c=='u') ))
- {
- ++lineIndex;
- c= line[lineIndex];
- }
- return string(line,startPos, lineIndex-startPos);
-}
-
-unsigned int CodeGenerator::getLineNumber()
-{
- return lineNumber;
-}
-
-bool CodeGenerator::readNewLine(string &newLine){
- bool eof;
- terminatingChar=newLine[lineIndex-1];
- if (formattingPossible && formattingEnabled)
- {
- eof=!formatter->hasMoreLines();
- if (!eof)
- {
- newLine = formatter->nextLine();
- }
- }
- else // reformatting not enabled
- {
- eof = ! getline( *in, newLine);
- }
- return eof;
-}
-
-unsigned char CodeGenerator::getInputChar()
-{
- bool eol = lineIndex == line.length();
-
- if (eol) {
- bool eof=false;
- if (preFormatter!=NULL){
- if (!preFormatter->hasMoreLines()) {
- eof=readNewLine(line);
- preFormatter->setLine(line);
- }
- line = preFormatter->getNextLine();
- } else {
- eof=readNewLine(line);
- }
- lineIndex=0;
- ++lineNumber;
- line=StringTools::trimRight(line);
- return (eof)?'\0':'\n';
- }
- return line[lineIndex++];
-}
-
-State CodeGenerator::getCurrentState (bool lastStateWasNumber)
-{
- unsigned char c;
-
- if (token.length()==0) {
- c=getInputChar();
- } else {
- lineIndex-= (token.length()-1);
- c=token[0];
- }
- if (c=='\n'){
- return _EOL; // End of line
- }
-
- if (c=='\0') {
- return _EOF; // End of file
- }
-
- if (isspace(c)) {
- token= c;
- return _WS;
- }
-
- // numbers have to be searched before using the symbolstring,
- // as numbers are part of this string
- if (isdigit(c)
- // recognize floats like .5
- || (c=='.' && isdigit(line[lineIndex]))
- // test if '-' belongs to a term like "1-2"
- || ((c == '-')
- && (!lastStateWasNumber)
- && isdigit(StringTools::getNextNonWs(line, lineIndex))) )
- {
- token = getNumber();
- return NUMBER;
- }
- unsigned int symbolLength;
- size_t symbolPos;
- bool found=false;
- string symbols=langInfo.getSymbolString();
-
- symbolPos = symbols.find(c);
- // search symbols (comment delimiters, directives etc.)
- // before keywords, because alphabetic chars may be part of symbols, too
- while ((symbolPos!= string::npos) && (!found))
- {
- symbolLength=symbols.find(' ', symbolPos)-symbolPos;
- token = symbols.substr(symbolPos, symbolLength);
-
- // TODO Ruby =ende, =end bugfix (whitespace after symbol needs to be checked)
-
- // Abfrage nach Leerzeichen in SymbolString verhindert falsches
- // Erkennen von Symbolteilen:
- if (lineIndex && token == line.substr(lineIndex-1, symbolLength)
- && isspace(symbols[symbolPos-1]) ) {
- found = true;
- lineIndex += (symbolLength-1);
- } else {
- symbolPos = symbols.find_first_not_of(' ',symbols.find(' ',symbolPos));
- }
- }
-
- // dirty workaround stuff in here
- if (found) {
- State foundState = getState(symbols, symbolPos);
-
- // get the current keyword class id to apply the corresponding formatting style
- if (foundState==KEYWORD_BEGIN || foundState==TAG_BEGIN ) {
- currentKeywordClass=langInfo.getDelimPrefixClassID(token);
- }
-
- // Full line quotes must start in coloumn 1 (Fortran 77)
- if (langInfo.isFullLineComment() && foundState==SL_COMMENT){
- if (lineIndex==1) {
- return SL_COMMENT;
- }
- }
- // VHDL Workaround: distinguish string delimiters and event markers
- // (same eymbol: ')
- else if (langInfo.isVHDL()
- && foundState==STRING && currentState!=STRING
- && lineIndex > 1
- &&(isdigit(line[lineIndex-2]) || isalpha(line[lineIndex-2]))){
- c=line[lineIndex-1];
- // do not return, continue search...
- } else {
- return foundState;
- }
- }
-
- // Alphanumerisches Token parsen und als Keyword oder Type erkennen
- if (StringTools::isAlpha(c) || langInfo.isPrefix(c) || isAllowedChar(c))
- {
- if (langInfo.isPrefix(c)){
- token = c;
- ++lineIndex;
- token += getIdentifier();
- } else {
- token = getIdentifier();
- }
- string reservedWord=(langInfo.isIgnoreCase()) ?
- StringTools::lowerCase(token):token;
- currentKeywordClass=langInfo.isKeyword(reservedWord);
- return (currentKeywordClass) ? KEYWORD : STANDARD;
- }
-
- // Character not referring to any state
- token = c;
- return STANDARD;
-}
-
-string CodeGenerator::maskString(const string & s)
-{
- ostringstream ss;
- for (unsigned int i=0;i< s.length();i++){
- ss << maskCharacter(s[i]);
- }
- return ss.str();
-}
-
-void CodeGenerator::printMaskedToken(bool flushWhiteSpace)
-{
- if(flushWhiteSpace) flushWs();
- *out << maskString(token);
- token.clear();
-}
-
-bool CodeGenerator::isAllowedChar(char c)
-{
- return ( langInfo.getAllowedChars().find(c)!= string::npos);
-}
-
-bool CodeGenerator::styleFound(){
- return docStyle.found();
-}
-
-bool CodeGenerator::printIndexFile(const vector<string> &fileList,
- const string &outPath){
- return true;
-}
-
-bool CodeGenerator::initIndentationScheme(const string &schemePath){
-
- if (formatter!=NULL){
- return true;
- }
-
- ConfigurationReader indentScheme(schemePath);
- if (indentScheme.found()){
- if (formatter==NULL) {
- formatter=new astyle::ASFormatter();
-
- string brackets=indentScheme.getParameter("brackets");
- if (!brackets.empty()){
- // Break brackets from pre-block code (i.e. ANSI C/C++ style).
- if (brackets=="break"){
- formatter->setBracketFormatMode(astyle::BREAK_MODE);
- }
- //Attach brackets to pre-block code (i.e. Java/K&R style).
- else if (brackets=="attach"){
- formatter->setBracketFormatMode(astyle::ATTACH_MODE);
- }
- // Break definition-block brackets and attach command-block brackets.
- else if (brackets=="linux"){
- formatter->setBracketFormatMode(astyle::BDAC_MODE);
- }
- // Break brackets before closing headers (e.g. 'else', 'catch', ..).
- // Should be appended to --brackets=attach or --brackets=linux.
- else if (brackets=="break-closing-headers"){
- formatter->setBreakClosingHeaderBracketsMode(true);
- }
- }
-
- string pad=indentScheme.getParameter("pad");
- if (!pad.empty()){
- //Insert space paddings around parenthesies only.
- if (pad=="paren"){
- formatter->setParenthesisPaddingMode(true);
- }
- // Insert space paddings around operators only.
- else if (pad=="oper"){
- formatter->setOperatorPaddingMode(true);
- }
- //Insert space paddings around operators AND parenthesies.
- else if (pad=="all"){
- formatter->setOperatorPaddingMode(true);
- formatter->setParenthesisPaddingMode(true);
- }
- }
-
- string oneLine=indentScheme.getParameter("one-line");
- if (!oneLine.empty()){
- // Don't break one-line blocks.
- if (oneLine=="keep-blocks"){
- formatter->setBreakOneLineBlocksMode(false);
- }
- // Don't break complex statements and multiple statements residing in a
- // single line.
- else if (oneLine=="keep-statements"){
- formatter->setSingleStatementsMode(false);
- }
- }
-
- // Insert empty lines around unrelated blocks, labels, classes, ...
- string breakBlocks=indentScheme.getParameter("break-blocks");
- if (!breakBlocks.empty()){
- if (breakBlocks=="all"){
- //Like --break-blocks, except also insert empty lines around closing
- //headers (e.g. 'else', 'catch', ...).
- formatter->setBreakClosingHeaderBlocksMode(true);
- }
- formatter->setBreakBlocksMode(true);
- }
- string trueVal="true";
-
- // Other options...
-
- //Indent using # spaces per indent. Not specifying # will result in a
- //default of 4 spaces per indent.
- string indentSpaces=indentScheme.getParameter("indent-spaces");
-
- // Indent a minimal # spaces in a continuous conditional belonging to a
- //conditional header.
- string minConditionalIndent=indentScheme.getParameter("min-conditional-indent");
-
- // Indent a maximal # spaces in a continuous statement, relatively to the
- // previous line.
- string maxInStatementIndent=indentScheme.getParameter("max-instatement-indent");
-
- // Add extra indentation to '{' and '}' block brackets.
- string indentBrackets=indentScheme.getParameter("indent-brackets");
-
- // Add extra indentation entire blocks (including brackets).
- string indentBlocks=indentScheme.getParameter("indent-blocks");
-
- // Indent the contents of namespace blocks.
- string indentNamespaces=indentScheme.getParameter("indent-namespaces");
-
- // Indent 'class' blocks, so that the inner 'public:','protected:' and
- // 'private: headers are indented inrelation to the class block.
- string indentClasses=indentScheme.getParameter("indent-classes");
-
- // Indent 'switch' blocks, so that the inner 'case XXX:' headers are
- // indented in relation to the switch block.
- string indentSwitches=indentScheme.getParameter("indent-switches");
-
- // Indent 'case XXX:' lines, so that they are flush with their bodies..
- string indentCases=indentScheme.getParameter("indent-cases");
-
- // Indent labels so that they appear one indent less than the current
- // indentation level, rather than being flushed completely to the left
- // (which is the default).
- string indentLabels=indentScheme.getParameter("indent-labels");
-
- // Indent multi-line #define statements
- string indentPreprocessor=indentScheme.getParameter("indent-preprocessor");
-
- // Break 'else if()' statements into two different lines.
- string breakElseIfs = indentScheme.getParameter("break-elseifs");
-
- string javaStyle = indentScheme.getParameter("java-style");
-
- // default values in ASBeautifier are false, it is ok to set them false
- // if parameter does not exist in scheme file
- formatter->setBracketIndent(indentBrackets==trueVal);
- formatter->setBlockIndent(indentBlocks==trueVal);
- formatter->setNamespaceIndent(indentNamespaces==trueVal);
- formatter->setClassIndent(indentClasses==trueVal);
- formatter->setSwitchIndent(indentSwitches==trueVal);
- formatter->setCaseIndent(indentCases==trueVal);
- formatter->setLabelIndent(indentLabels==trueVal);
- formatter->setPreprocessorIndent(indentPreprocessor==trueVal);
- formatter->setBreakElseIfsMode(breakElseIfs==trueVal);
-
- if (javaStyle==trueVal){
- formatter->setJavaStyle();
- }
-
- if (!indentSpaces.empty()){
- formatter->setSpaceIndentation(StringTools::str2int(indentSpaces));
- }
- if (!minConditionalIndent.empty()){
- formatter->setMinConditionalIndentLength(
- StringTools::str2int(minConditionalIndent));
- }
- if (!maxInStatementIndent.empty()){
- formatter->setMinConditionalIndentLength(
- StringTools::str2int(maxInStatementIndent));
- }
- }
- formattingEnabled=(formatter != NULL);
- return true;
- } else {
- return false;
- }
-}
-
-LoadResult CodeGenerator::initLanguage(const string& langDefPath){
- bool reloadNecessary= langInfo.needsReload(langDefPath);
- if (reloadNecessary){
- bool failure = !langInfo.load(langDefPath);
-
- if (failure) {
- return LOAD_FAILED;
- }
-
- formattingPossible=langInfo.enableReformatting();
-
- if (styleTagOpen.size()>NUMBER_BUILTIN_STYLES){
- // remove dynamic keyword tag delimiters of the old language definition
- vector<string>::iterator keyStyleOpenBegin =
- styleTagOpen.begin() + NUMBER_BUILTIN_STYLES;
- vector<string>::iterator keyStyleCloseBegin =
- styleTagClose.begin()+ NUMBER_BUILTIN_STYLES;
- styleTagOpen.erase(keyStyleOpenBegin, styleTagOpen.end());
- styleTagClose.erase(keyStyleCloseBegin, styleTagClose.end());
- }
- // add new keyword delimiters
- for (unsigned int i=0;i< langInfo.getKeywordClasses().size(); i++){
- styleTagOpen.push_back(getMatchingOpenTag(i));
- styleTagClose.push_back(getMatchingCloseTag(i));
- }
- }
- return (reloadNecessary) ? LOAD_NEW : LOAD_NONE;
-}
-
-ParseError CodeGenerator::printOutput (const string & inFileName,
- const string &outFileName)
-{
- if (!docStyle.found()) {
- return BAD_STYLE;
- }
- reset();
-
- ParseError error=PARSE_OK;
-
- in = (inFileName.empty()? &cin :new ifstream (inFileName.c_str()));
- if (!in->fail()) {
- out = (outFileName.empty()? &cout :new ofstream (outFileName.c_str()));
- if ( out->fail()) {
- error=BAD_OUTPUT;
- }
- }
-
- if ( in->fail()){
- error=BAD_INPUT;
- }
-
- if (error==PARSE_OK) {
- if (formatter != NULL){
- formatter->init(new astyle::ASStreamIterator(in));
- }
- if (! fragmentOutput){
- *out << getHeader(inFileName);
- }
- printBody();
- if (! fragmentOutput){
- *out << getFooter();
- }
- }
-
- if (!outFileName.empty()){
- delete out; out=NULL;
- }
- if (!inFileName.empty()) {
- delete in; in=NULL;
- }
- return error;
-}
-
-
-unsigned int CodeGenerator::getStyleID(State s, unsigned int kwClassID){
- if (s==KEYWORD && kwClassID){
- return NUMBER_BUILTIN_STYLES + kwClassID-1;
- }
- return (unsigned int) s ;
-}
-
-void CodeGenerator::closeTag(State s){
- *out << styleTagClose[(unsigned int)s];
- flushWs();
- currentState=_UNKNOWN;
-}
-
-void CodeGenerator::openTag(State s){
- *out << styleTagOpen[(unsigned int)s];
- currentState=s;
-}
-
-void CodeGenerator::closeKWTag(unsigned int kwClassID){
- *out << styleTagClose[getStyleID(KEYWORD, kwClassID)];
-
- flushWs();
- currentState=_UNKNOWN;
-}
-
-void CodeGenerator::openKWTag(unsigned int kwClassID){
- *out << styleTagOpen[getStyleID(KEYWORD, kwClassID)];
- currentState=KEYWORD;
-}
-
diff --git a/tests/examplefiles/example.rb b/tests/examplefiles/example.rb
index 8a3304ba..93f8dc2b 100644
--- a/tests/examplefiles/example.rb
+++ b/tests/examplefiles/example.rb
@@ -1850,5707 +1850,3 @@ module BBCode
end
end
- class Parser
- def Parser.flatten str
- # replace mac & dos newlines with unix style
- str.gsub(/\r\n?/, "\n")
- end
-
- def initialize input = ''
- # input manager
- @scanner = StringScanner.new ''
- # output manager
- @encoder = Encoder.new
- @output = ''
- # tag manager
- @tagstack = TagStack.new(@encoder)
-
- @do_magic = true
- # set the input
- feed input
- end
-
- # if you want, you can feed a parser instance after creating,
- # or even feed it repeatedly.
- def feed food
- @scanner.string = Parser.flatten food
- end
-
- # parse through the string using parse_token
- def parse
- parse_token until @scanner.eos?
- @tagstack.close_all
- @output = parse_magic @encoder.output
- end
-
- def output
- @output
- end
-
- # ok, internals start here
- private
- # the default output functions. everything should use them or the tags.
- def add_text text = @scanner.matched
- @encoder.add_text text
- end
-
- # use this carefully
- def add_html html
- @encoder.add_html html
- end
-
- # highlights the text as error
- def add_garbage garbage
- add_html '<span class="error">' if DEBUG
- add_text garbage
- add_html '</span>' if DEBUG
- end
-
- # unknown and incorrectly nested tags are ignored and
- # sent as plaintext (garbage in - garbage out).
- # in debug mode, garbage is marked with lime background.
- def garbage_out start
- @scanner.pos = start
- garbage = @scanner.scan(/./m)
- debug 'GARBAGE: ' + garbage
- add_garbage garbage
- end
-
- # simple text; everything but [, \[ allowed
- SIMPLE_TEXT_SCAN_ = /
- [^\[\\]* # normal*
- (?: # (
- \\.? # special
- [^\[\\]* # normal*
- )* # )*
- /mx
- SIMPLE_TEXT_SCAN = /[^\[]+/
-
-=begin
-
- WHAT IS A TAG?
- ==============
-
- Tags in BBCode can be much more than just a simple [b].
- I use many terms here to differ the parts of each tag.
-
- Basic scheme:
- [ code ]
- TAG START TAG INFO TAG END
-
- Most tags need a second tag to close the range it opened.
- This is done with CLOSING TAGS:
- [/code]
- or by using empty tags that have no content and close themselfes:
- [url=winamp.com /]
- You surely know this from HTML.
- These slashes define the TAG KIND = normal|closing|empty and
- cannot be used together.
-
- Everything between [ and ] and expluding the slashes is called the
- TAG INFO. This info may contain:
- - TAG ID
- - TAG NAME including the tag id
- - attributes
-
- The TAG ID is the first char of the info:
-
- TAG | ID
- ----------+----
- [quote] | q
- [&plusmn] | &
- ["[b]"] | "
- [/url] | u
- [---] | -
-
- As you can see, the tag id shows the TAG TYPE, it can be a
- normal tag, a formatting tag or an entity.
- Therefor, the parser first scans the id to decide how to go
- on with parsing.
-=end
- # tag
- # TODO more complex expression allowing
- # [quote="[ladico]"] and [quote=\[ladico\]] to be correct tags
- TAG_BEGIN_SCAN = /
- \[ # tag start
- ( \/ )? # $1 = closing tag?
- ( [^\]] ) # $2 = tag id
- /x
- TAG_END_SCAN = /
- [^\]]* # rest that was not handled
- \]? # tag end
- /x
- CLOSE_TAG_SCAN = /
- ( [^\]]* ) # $1 = the rest of the tag info
- ( \/ )? # $2 = empty tag?
- \]? # tag end
- /x
- UNCLOSED_TAG_SCAN = / \[ /x
-
- CLASSIC_TAG_SCAN = / [a-z]* /ix
-
- SEPARATOR_TAG_SCAN = / \** /x
-
- FORMAT_TAG_SCAN = / -- -* /x
-
- QUOTED_SCAN = /
- ( # $1 = quoted text
- [^"\\]* # normal*
- (?: # (
- \\. # special
- [^"\\]* # normal*
- )* # )*
- )
- "? # end quote "
- /mx
-
- ENTITY_SCAN = /
- ( [^;\]]+ ) # $1 = entity code
- ;? # optional ending semicolon
- /ix
-
- SMILEY_SCAN = Smileys::SMILEY_PATTERN
-
- # this is the main parser loop that separates
- # text - everything until "["
- # from
- # tags - starting with "[", ending with "]"
- def parse_token
- if @scanner.scan(SIMPLE_TEXT_SCAN)
- add_text
- else
- handle_tag
- end
- end
-
- def handle_tag
- tag_start = @scanner.pos
-
- unless @scanner.scan TAG_BEGIN_SCAN
- garbage_out tag_start
- return
- end
-
- closing, id = @scanner[1], @scanner[2]
- #debug 'handle_tag(%p)' % @scanner.matched
-
- handled =
- case id
-
- when /[a-z]/i
- if @scanner.scan(CLASSIC_TAG_SCAN)
- if handle_classic_tag(id + @scanner.matched, closing)
- already_closed = true
- end
- end
-
- when '*'
- if @scanner.scan(SEPARATOR_TAG_SCAN)
- handle_asterisk tag_start, id + @scanner.matched
- true
- end
-
- when '-'
- if @scanner.scan(FORMAT_TAG_SCAN)
- #format = id + @scanner.matched
- @encoder.add_html "\n<hr>\n"
- true
- end
-
- when '"'
- if @scanner.scan(QUOTED_SCAN)
- @encoder.add_text unescape(@scanner[1])
- true
- end
-
- when '&'
- if @scanner.scan(ENTITY_SCAN)
- @encoder.add_entity @scanner[1]
- true
- end
-
- when Smileys::SMILEY_START_CHARSET
- @scanner.pos = @scanner.pos - 1 # (ungetch)
- if @scanner.scan(SMILEY_SCAN)
- @encoder.add_html Smileys.smiley_to_image(@scanner.matched)
- true
- end
-
- end # case
-
- return garbage_out(tag_start) unless handled
-
- @scanner.scan(TAG_END_SCAN) unless already_closed
- end
-
- ATTRIBUTES_SCAN = /
- (
- [^\]"\\]*
- (?:
- (?:
- \\.
- |
- "
- [^"\\]*
- (?:
- \\.
- [^"\\]*
- )*
- "?
- )
- [^\]"\\]*
- )*
- )
- \]?
- /x
-
- def handle_classic_tag name, closing
- debug 'TAG: ' + (closing ? '/' : '') + name
- # flatten
- name.downcase!
- tag_class = TAG_LIST[name]
- return unless tag_class
-
- #debug((opening ? 'OPEN ' : 'CLOSE ') + tag_class.name)
-
- # create an attribute object to handle it
- @scanner.scan(ATTRIBUTES_SCAN)
- #debug name + ':' + @scanner[1]
- attr = Attribute.create @scanner[1]
- #debug 'ATTRIBUTES %p ' % attr #unless attr.empty?
-
- #debug 'closing: %p; name=%s, attr=%p' % [closing, name, attr]
-
- # OPEN
- if not closing and tag = @tagstack.try_open_class(tag_class, attr)
- #debug 'opening'
- tag.do_open @scanner
- # this should be done by the tag itself.
- if attr.empty_tag?
- tag.handle_empty
- @tagstack.close_tag
- elsif tag.special_content?
- handle_special_content(tag)
- @tagstack.close_tag
- # # ignore asterisks directly after the opening; these are phpBBCode
- # elsif tag.respond_to? :asterisk
- # debug 'SKIP ASTERISKS: ' if @scanner.skip(ASTERISK_TAGS_SCAN)
- end
-
- # CLOSE
- elsif @tagstack.try_close_class(tag_class)
- #debug 'closing'
- # GARBAGE
- else
- return
- end
-
- true
- end
-
- def handle_asterisk tag_start, stars
- #debug 'ASTERISK: ' + stars.to_s
- # rule for asterisk tags: they belong to the last tag
- # that handles them. tags opened after this tag are closed.
- # if no open tag uses them, all are closed.
- tag = @tagstack.close_all_until { |tag| tag.respond_to? :asterisk }
- unless tag and tag.asterisk stars, @scanner
- garbage_out tag_start
- end
- end
-
- def handle_special_content tag
- scanned = @scanner.scan_until(tag.closing_tag)
- if scanned
- scanned.slice!(-(@scanner.matched.size)..-1)
- else
- scanned = @scanner.scan(/.*/m).to_s
- end
- #debug 'SPECIAL CONTENT: ' + scanned
- tag.handle_content(scanned)
- end
-
- def unescape text
- # input: correctly formatted quoted string (without the quotes)
- text.gsub(/\\(?:(["\\])|.)/) { $1 or $& }
- end
-
-
- # MAGIC FEAUTURES
-
- URL_PATTERN = /(?:(?:www|ftp)\.|(?>\w{3,}):\/\/)\S+/
- EMAIL_PATTERN = /(?>[\w\-_.]+)@[\w\-\.]+\.\w+/
-
- HAS_MAGIC = /[&@#{Smileys::SMILEY_START_CHARS}]|(?i:www|ftp)/
-
- MAGIC_PATTERN = Regexp.new('(\W|^)(%s)' %
- [Smileys::MAGIC_SMILEY_PATTERN, URL_PATTERN, EMAIL_PATTERN].map { |pattern|
- pattern.to_s
- }.join('|') )
-
- IS_SMILEY_PATTERN = Regexp.new('^%s' % Smileys::SMILEY_START_CHARSET.to_s )
- IS_URL_PATTERN = /^(?:(?i:www|ftp)\.|(?>\w+):\/\/)/
- URL_STARTS_WITH_PROTOCOL = /^\w+:\/\//
- IS_EMAIL_PATTERN = /^[\w\-_.]+@/
-
- def to_magic text
- # debug MAGIC_PATTERN.to_s
- text.gsub!(MAGIC_PATTERN) {
- magic = $2
- $1 + case magic
- when IS_SMILEY_PATTERN
- Smileys.smiley_to_img magic
- when IS_URL_PATTERN
- last = magic.slice_punctation! # no punctation in my URL
- href = magic
- href.insert(0, 'http://') unless magic =~ URL_STARTS_WITH_PROTOCOL
- '<a href="' + href + '">' + magic + '</a>' + last
- when IS_EMAIL_PATTERN
- last = magic.slice_punctation!
- '<a href="mailto:' + magic + '">' + magic + '</a>' + last
- else
- raise '{{{' + magic + '}}}'
- end
- }
- text
- end
-
- # handles smileys and urls
- def parse_magic html
- return html unless @do_magic
- scanner = StringScanner.new html
- out = ''
- while scanner.rest?
- if scanner.scan(/ < (?: a\s .*? <\/a> | pre\W .*? <\/pre> | [^>]* > ) /mx)
- out << scanner.matched
- elsif scanner.scan(/ [^<]+ /x)
- out << to_magic(scanner.matched)
-
- # this should never happen
- elsif scanner.scan(/./m)
- raise 'ERROR: else case reached'
- end
- end
- out
- end
- end # Parser
-end
-
-class String
- def slice_punctation!
- slice!(/[.:,!\?]+$/).to_s # return '' instead of nil
- end
-end
-
-#
-# = Grammar
-#
-# An implementation of common algorithms on grammars.
-#
-# This is used by Shinobu, a visualization tool for educating compiler-building.
-#
-# Thanks to Andreas Kunert for his wonderful LR(k) Pamphlet (German, see http://www.informatik.hu-berlin.de/~kunert/papers/lr-analyse), and Aho/Sethi/Ullman for their Dragon Book.
-#
-# Homepage:: http://shinobu.cYcnus.de (not existing yet)
-# Author:: murphy (Kornelius Kalnbach)
-# Copyright:: (cc) 2005 cYcnus
-# License:: GPL
-# Version:: 0.2.0 (2005-03-27)
-
-require 'set_hash'
-require 'ctype'
-require 'tools'
-require 'rules'
-require 'trace'
-
-require 'first'
-require 'follow'
-
-# = Grammar
-#
-# == Syntax
-#
-# === Rules
-#
-# Each line is a rule.
-# The syntax is
-#
-# left - right
-#
-# where +left+ and +right+ can be uppercase and lowercase letters,
-# and <code>-</code> can be any combination of <, >, - or whitespace.
-#
-# === Symbols
-#
-# Uppercase letters stand for meta symbols, lowercase for terminals.
-#
-# You can make epsilon-derivations by leaving <code><right></code> empty.
-#
-# === Example
-# S - Ac
-# A - Sc
-# A - b
-# A -
-class Grammar
-
- attr_reader :tracer
- # Creates a new Grammar.
- # If $trace is true, the algorithms explain (textual) what they do to $stdout.
- def initialize data, tracer = Tracer.new
- @tracer = tracer
- @rules = Rules.new
- @terminals, @meta_symbols = SortedSet.new, Array.new
- @start_symbol = nil
- add_rules data
- end
-
- attr_reader :meta_symbols, :terminals, :rules, :start_symbol
-
- alias_method :sigma, :terminals
- alias_method :alphabet, :terminals
- alias_method :variables, :meta_symbols
- alias_method :nonterminals, :meta_symbols
-
- # A string representation of the grammar for debugging.
- def inspect productions_too = false
- 'Grammar(meta symbols: %s; alphabet: %s; productions: [%s]; start symbol: %s)' %
- [
- meta_symbols.join(', '),
- terminals.join(', '),
- if productions_too
- @rules.inspect
- else
- @rules.size
- end,
- start_symbol
- ]
- end
-
- # Add rules to the grammar. +rules+ should be a String or respond to +scan+ in a similar way.
- #
- # Syntax: see Grammar.
- def add_rules grammar
- @rules = Rules.parse grammar do |rule|
- @start_symbol ||= rule.left
- @meta_symbols << rule.left
- @terminals.merge rule.right.split('').select { |s| terminal? s }
- end
- @meta_symbols.uniq!
- update
- end
-
- # Returns a hash acting as FIRST operator, so that
- # <code>first["ABC"]</code> is FIRST(ABC).
- # See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
- def first
- first_operator
- end
-
- # Returns a hash acting as FOLLOW operator, so that
- # <code>first["A"]</code> is FOLLOW(A).
- # See http://en.wikipedia.org/wiki/LL_parser "Constructing an LL(1) parsing table" for details.
- def follow
- follow_operator
- end
-
- LLError = Class.new(Exception)
- LLErrorType1 = Class.new(LLError)
- LLErrorType2 = Class.new(LLError)
-
- # Tests if the grammar is LL(1).
- def ll1?
- begin
- for meta in @meta_symbols
- first_sets = @rules[meta].map { |alpha| first[alpha] }
- first_sets.inject(Set[]) do |already_used, another_first_set|
- unless already_used.disjoint? another_first_set
- raise LLErrorType1
- end
- already_used.merge another_first_set
- end
-
- if first[meta].include? EPSILON and not first[meta].disjoint? follow[meta]
- raise LLErrorType2
- end
- end
- rescue LLError
- false
- else
- true
- end
- end
-
-private
-
- def first_operator
- @first ||= FirstOperator.new self
- end
-
- def follow_operator
- @follow ||= FollowOperator.new self
- end
-
- def update
- @first = @follow = nil
- end
-
-end
-
-if $0 == __FILE__
- eval DATA.read, nil, $0, __LINE__+4
-end
-
-require 'test/unit'
-
-class TestCaseGrammar < Test::Unit::TestCase
-
- include Grammar::Symbols
-
- def fifo s
- Set[*s.split('')]
- end
-
- def test_fifo
- assert_equal Set[], fifo('')
- assert_equal Set[EPSILON, END_OF_INPUT, 'x', 'Y'], fifo('?xY$')
- end
-
- TEST_GRAMMAR_1 = <<-EOG
-S - ABCD
-A - a
-A -
-B - b
-B -
-C - c
-C -
-D - S
-D -
- EOG
-
- def test_symbols
- assert EPSILON
- assert END_OF_INPUT
- end
-
- def test_first_1
- g = Grammar.new TEST_GRAMMAR_1
-
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', EPSILON], f['A'])
- assert_equal(Set['b', EPSILON], f['B'])
- assert_equal(Set['c', EPSILON], f['C'])
- assert_equal(Set['a', 'b', 'c', EPSILON], f['D'])
- assert_equal(f['D'], f['S'])
- end
-
- def test_follow_1
- g = Grammar.new TEST_GRAMMAR_1
-
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['A'])
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['B'])
- assert_equal(Set['a', 'b', 'c', END_OF_INPUT], f['C'])
- assert_equal(Set[END_OF_INPUT], f['D'])
- assert_equal(Set[END_OF_INPUT], f['S'])
- end
-
-
- TEST_GRAMMAR_2 = <<-EOG
-S - Ed
-E - EpT
-E - EmT
-E - T
-T - TuF
-T - TdF
-T - F
-F - i
-F - n
-F - aEz
- EOG
-
- def test_first_2
- g = Grammar.new TEST_GRAMMAR_2
-
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'n', 'i'], f['E'])
- assert_equal(Set['a', 'n', 'i'], f['F'])
- assert_equal(Set['a', 'n', 'i'], f['T'])
- assert_equal(Set['a', 'n', 'i'], f['S'])
- end
-
- def test_follow_2
- g = Grammar.new TEST_GRAMMAR_2
-
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['m', 'd', 'z', 'p'], f['E'])
- assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['F'])
- assert_equal(Set['m', 'd', 'z', 'p', 'u'], f['T'])
- assert_equal(Set[END_OF_INPUT], f['S'])
- end
-
- LLError = Grammar::LLError
-
- TEST_GRAMMAR_3 = <<-EOG
-E - TD
-D - pTD
-D -
-T - FS
-S - uFS
-S -
-S - p
-F - aEz
-F - i
- EOG
-
- NoError = Class.new(Exception)
-
- def test_first_3
- g = Grammar.new TEST_GRAMMAR_3
-
- # Grammar 3 is LL(1), so all first-sets must be disjoint.
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'i'], f['E'])
- assert_equal(Set[EPSILON, 'p'], f['D'])
- assert_equal(Set['a', 'i'], f['F'])
- assert_equal(Set['a', 'i'], f['T'])
- assert_equal(Set[EPSILON, 'u', 'p'], f['S'])
- for m in g.meta_symbols
- r = g.rules[m]
- firsts = r.map { |x| f[x] }.to_set
- assert_nothing_raised do
- firsts.inject(Set.new) do |already_used, another_first_set|
- raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
- already_used.merge another_first_set
- end
- end
- end
- end
-
- def test_follow_3
- g = Grammar.new TEST_GRAMMAR_3
-
- # Grammar 3 is not LL(1), because epsilon is in FIRST(S),
- # but FIRST(S) and FOLLOW(S) are not disjoint.
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(Set['z', END_OF_INPUT], f['E'])
- assert_equal(Set['z', END_OF_INPUT], f['D'])
- assert_equal(Set['z', 'p', 'u', END_OF_INPUT], f['F'])
- assert_equal(Set['p', 'z', END_OF_INPUT], f['T'])
- assert_equal(Set['p', 'z', END_OF_INPUT], f['S'])
- for m in g.meta_symbols
- first_m = g.first[m]
- next unless first_m.include? EPSILON
- assert_raise(m == 'S' ? LLError : NoError) do
- if first_m.disjoint? f[m]
- raise NoError # this is fun :D
- else
- raise LLError
- end
- end
- end
- end
-
- TEST_GRAMMAR_3b = <<-EOG
-E - TD
-D - pTD
-D - PTD
-D -
-T - FS
-S - uFS
-S -
-F - aEz
-F - i
-P - p
- EOG
-
- def test_first_3b
- g = Grammar.new TEST_GRAMMAR_3b
-
- # Grammar 3b is NOT LL(1), since not all first-sets are disjoint.
- f = nil
- assert_nothing_raised { f = g.first }
- assert_equal(Set['a', 'i'], f['E'])
- assert_equal(Set[EPSILON, 'p'], f['D'])
- assert_equal(Set['p'], f['P'])
- assert_equal(Set['a', 'i'], f['F'])
- assert_equal(Set['a', 'i'], f['T'])
- assert_equal(Set[EPSILON, 'u'], f['S'])
- for m in g.meta_symbols
- r = g.rules[m]
- firsts = r.map { |x| f[x] }
- assert_raise(m == 'D' ? LLError : NoError) do
- firsts.inject(Set.new) do |already_used, another_first_set|
- raise LLError, 'not disjoint!' unless already_used.disjoint? another_first_set
- already_used.merge another_first_set
- end
- raise NoError
- end
- end
- end
-
- def test_follow_3b
- g = Grammar.new TEST_GRAMMAR_3b
-
- # Although Grammar 3b is NOT LL(1), the FOLLOW-condition is satisfied.
- f = nil
- assert_nothing_raised { f = g.follow }
- assert_equal(fifo('z$'), f['E'], 'E')
- assert_equal(fifo('z$'), f['D'], 'D')
- assert_equal(fifo('ai'), f['P'], 'P')
- assert_equal(fifo('z$pu'), f['F'], 'F')
- assert_equal(fifo('z$p'), f['T'], 'T')
- assert_equal(fifo('z$p'), f['S'], 'S')
- for m in g.meta_symbols
- first_m = g.first[m]
- next unless first_m.include? EPSILON
- assert_raise(NoError) do
- if first_m.disjoint? f[m]
- raise NoError # this is fun :D
- else
- raise LLError
- end
- end
- end
- end
-
- def test_ll1?
- assert_equal false, Grammar.new(TEST_GRAMMAR_3).ll1?, 'Grammar 3'
- assert_equal false, Grammar.new(TEST_GRAMMAR_3b).ll1?, 'Grammar 3b'
- end
-
- def test_new
- assert_nothing_raised { Grammar.new '' }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_2 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_3 }
- assert_nothing_raised { Grammar.new TEST_GRAMMAR_1 + TEST_GRAMMAR_2 + TEST_GRAMMAR_3 }
- assert_raise(ArgumentError) { Grammar.new 'S - ?' }
- end
-end
-
-# vim:foldmethod=syntax
-
-#!/usr/bin/env ruby
-
-require 'fox12'
-
-include Fox
-
-class Window < FXMainWindow
- def initialize(app)
- super(app, app.appName + ": First Set Calculation", nil, nil, DECOR_ALL, 0, 0, 800, 600, 0, 0)
-
- # {{{ menubar
- menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
-
- filemenu = FXMenuPane.new(self)
-
- FXMenuCommand.new(filemenu, "&Start\tCtl-S\tStart the application.", nil, getApp()).connect(SEL_COMMAND, method(:start))
- FXMenuCommand.new(filemenu, "&Quit\tAlt-F4\tQuit the application.", nil, getApp(), FXApp::ID_QUIT)
- FXMenuTitle.new(menubar, "&File", nil, filemenu)
- # }}} menubar
-
- # {{{ statusbar
- @statusbar = FXStatusBar.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
- # }}} statusbar
-
- # {{{ window content
- horizontalsplitt = FXSplitter.new(self, SPLITTER_VERTICAL|LAYOUT_SIDE_TOP|LAYOUT_FILL)
-
-
- @productions = FXList.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|LIST_SINGLESELECT)
- @productions.height = 100
-
- @result = FXTable.new(horizontalsplitt, nil, 0, LAYOUT_FILL)
- @result.height = 200
- @result.setTableSize(2, 2, false)
- @result.rowHeaderWidth = 0
-
- header = @result.columnHeader
- header.setItemText 0, 'X'
- header.setItemText 1, 'FIRST(X)'
- for item in header
- item.justification = FXHeaderItem::CENTER_X
- end
-
- @debug = FXText.new(horizontalsplitt, nil, 0, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT)
- @debug.height = 200
-
- # }}} window content
- end
-
- def load_grammar grammar
- @tracer = FirstTracer.new(self)
- @grammar = Grammar.new grammar, @tracer
- @rules_indexes = Hash.new
- @grammar.rules.each_with_index do |rule, i|
- @productions.appendItem rule.inspect
- @rules_indexes[rule] = i
- end
- end
-
- def create
- super
- show(PLACEMENT_SCREEN)
- end
-
- def rule rule
- @productions.selectItem @rules_indexes[rule]
- sleep 0.1
- end
-
- def iterate i
- setTitle i.to_s
- sleep 0.1
- end
-
- def missing what
- @debug.appendText what + "\n"
- sleep 0.1
- end
-
- def start sender, sel, pointer
- Thread.new do
- begin
- @grammar.first
- rescue => boom
- @debug.appendText [boom.to_s, *boom.backtrace].join("\n")
- end
- end
- end
-
-end
-
-$: << 'grammar'
-require 'grammar'
-
-require 'first_tracer'
-
-app = FXApp.new("Shinobu", "cYcnus")
-
-# fenster erzeugen
-window = Window.new app
-
-unless ARGV.empty?
- grammar = File.read(ARGV.first)
-else
- grammar = <<-EOG1
-Z --> S
-S --> Sb
-S --> bAa
-A --> aSc
-A --> a
-A --> aSb
- EOG1
-end
-
-window.load_grammar grammar
-
-app.create
-app.run
-
-require 'erb'
-require 'ftools'
-require 'yaml'
-require 'redcloth'
-
-module WhyTheLuckyStiff
- class Book
- attr_accessor :author, :title, :terms, :image, :teaser,
- :chapters, :expansion_paks, :encoding, :credits
- def [] x
- @lang.fetch(x) do
- warn warning = "[not translated: '#{x}'!]"
- warning
- end
- end
- end
-
- def Book::load( file_name )
- YAML::load( File.open( file_name ) )
- end
-
- class Section
- attr_accessor :index, :header, :content
- def initialize( i, h, c )
- @index, @header, @content = i, h, RedCloth::new( c.to_s )
- end
- end
-
- class Sidebar
- attr_accessor :title, :content
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'sidebar' ) do |taguri, val|
- YAML::object_maker( Sidebar, 'title' => val.keys.first, 'content' => RedCloth::new( val.values.first ) )
- end
- class Chapter
- attr_accessor :index, :title, :sections
- def initialize( i, t, sects )
- @index = i
- @title = t
- i = 0
- @sections = sects.collect do |s|
- if s.respond_to?( :keys )
- i += 1
- Section.new( i, s.keys.first, s.values.first )
- else
- s
- end
- end
- end
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'book' ) do |taguri, val|
- ['chapters', 'expansion_paks'].each do |chaptype|
- i = 0
- val[chaptype].collect! do |c|
- i += 1
- Chapter::new( i, c.keys.first, c.values.first )
- end
- end
- val['teaser'].collect! do |t|
- Section::new( 1, t.keys.first, t.values.first )
- end
- val['terms'] = RedCloth::new( val['terms'] )
- YAML::object_maker( Book, val )
- end
-
- class Image
- attr_accessor :file_name
- end
-
- YAML::add_domain_type( 'whytheluckystiff.net,2003', 'img' ) do |taguri, val|
- YAML::object_maker( Image, 'file_name' => "i/" + val )
- end
-end
-
-#
-# Convert the book to HTML
-#
-if __FILE__ == $0
- unless ARGV[0]
- puts "Usage: #{$0} [/path/to/save/html]"
- exit
- end
-
- site_path = ARGV[0]
- book = WhyTheLuckyStiff::Book::load( 'poignant.yml' )
- chapter = nil
-
- # Write index page
- index_tpl = ERB::new( File.open( 'index.erb' ).read )
- File.open( File.join( site_path, 'index.html' ), 'w' ) do |out|
- out << index_tpl.result
- end
-
- book.chapters = book.chapters[0,3] if ARGV.include? '-fast'
-
- # Write chapter pages
- chapter_tpl = ERB::new( File.open( 'chapter.erb' ).read )
- book.chapters.each do |chapter|
- File.open( File.join( site_path, "chapter-#{ chapter.index }.html" ), 'w' ) do |out|
- out << chapter_tpl.result
- end
- end
- exit if ARGV.include? '-fast'
-
- # Write expansion pak pages
- expak_tpl = ERB::new( File.open( 'expansion-pak.erb' ).read )
- book.expansion_paks.each do |pak|
- File.open( File.join( site_path, "expansion-pak-#{ pak.index }.html" ), 'w' ) do |out|
- out << expak_tpl.result( binding )
- end
- end
-
- # Write printable version
- print_tpl = ERB::new( File.open( 'print.erb' ).read )
- File.open( File.join( site_path, "print.html" ), 'w' ) do |out|
- out << print_tpl.result
- end
-
- # Copy css + images into site
- copy_list = ["guide.css"] +
- Dir["i/*"].find_all { |image| image =~ /\.(gif|jpg|png)$/ }
-
- File.makedirs( File.join( site_path, "i" ) )
- copy_list.each do |copy_file|
- File.copy( copy_file, File.join( site_path, copy_file ) )
- end
-end
-
-#!/usr/bin/env ruby
-
-require 'fox'
-begin
- require 'opengl'
-rescue LoadError
- require 'fox/missingdep'
- MSG = <<EOM
- Sorry, this example depends on the OpenGL extension. Please
- check the Ruby Application Archives for an appropriate
- download site.
-EOM
- missingDependency(MSG)
-end
-
-
-include Fox
-include Math
-
-Deg2Rad = Math::PI / 180
-
-D_MAX = 6
-SQUARE_SIZE = 2.0 / D_MAX
-SQUARE_DISTANCE = 4.0 / D_MAX
-AMPLITUDE = SQUARE_SIZE
-LAMBDA = D_MAX.to_f / 2
-
-class GLTestWindow < FXMainWindow
-
- # How often our timer will fire (in milliseconds)
- TIMER_INTERVAL = 500
-
- # Rotate the boxes when a timer message is received
- def onTimeout(sender, sel, ptr)
- @angle += 10.0
-# @size = 0.5 + 0.2 * Math.cos(Deg2Rad * @angle)
- drawScene()
- @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
- end
-
- # Rotate the boxes when a chore message is received
- def onChore(sender, sel, ptr)
- @angle += 10.0
-# @angle %= 360.0
-# @size = 0.5 + 0.2 * Math.cos(Deg2Rad * @angle)
- drawScene()
- @chore = getApp().addChore(method(:onChore))
- end
-
- # Draw the GL scene
- def drawScene
- lightPosition = [15.0, 10.0, 5.0, 1.0]
- lightAmbient = [ 0.1, 0.1, 0.1, 1.0]
- lightDiffuse = [ 0.9, 0.9, 0.9, 1.0]
- redMaterial = [ 0.0, 0.0, 1.0, 1.0]
- blueMaterial = [ 0.0, 1.0, 0.0, 1.0]
-
- width = @glcanvas.width.to_f
- height = @glcanvas.height.to_f
- aspect = width/height
-
- # Make context current
- @glcanvas.makeCurrent()
-
- GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
-
- GL.ClearColor(1.0/256, 0.0, 5.0/256, 1.0)
- GL.Clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT)
- GL.Enable(GL::DEPTH_TEST)
-
- GL.Disable(GL::DITHER)
-
- GL.MatrixMode(GL::PROJECTION)
- GL.LoadIdentity()
- GLU.Perspective(30.0, aspect, 1.0, 100.0)
-
- GL.MatrixMode(GL::MODELVIEW)
- GL.LoadIdentity()
- GLU.LookAt(5.0, 10.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
-
- GL.ShadeModel(GL::SMOOTH)
- GL.Light(GL::LIGHT0, GL::POSITION, lightPosition)
- GL.Light(GL::LIGHT0, GL::AMBIENT, lightAmbient)
- GL.Light(GL::LIGHT0, GL::DIFFUSE, lightDiffuse)
- GL.Enable(GL::LIGHT0)
- GL.Enable(GL::LIGHTING)
-
- GL.Rotated(0.1*@angle, 0.0, 1.0, 0.0)
- for x in -D_MAX..D_MAX
- for y in -D_MAX..D_MAX
- h1 = (x + y - 2).abs
- h2 = (y - x + 1).abs
- GL.PushMatrix
- c = [1, 0, 0, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- AMPLITUDE * h1,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
-
- GL.PushMatrix
- c = [0, 0, 1, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- AMPLITUDE * h2,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
-
- GL.PushMatrix
- c = [0.0 + (x/10.0), 0.0 + (y/10.0), 0, 1]
- GL.Material(GL::FRONT, GL::AMBIENT, c)
- GL.Material(GL::FRONT, GL::DIFFUSE, c)
-
- GL.Translated(
- y * SQUARE_DISTANCE,
- 0,
- x * SQUARE_DISTANCE
- )
-
- GL.Begin(GL::TRIANGLE_STRIP)
- GL.Normal(1.0, 0.0, 0.0)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(-SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, -SQUARE_SIZE)
- GL.Vertex(+SQUARE_SIZE, +SQUARE_SIZE, +SQUARE_SIZE)
- GL.End
-
- GL.PopMatrix
- end
- end
-
- # Swap if it is double-buffered
- if @glvisual.isDoubleBuffer
- @glcanvas.swapBuffers
- end
-
- # Make context non-current
- @glcanvas.makeNonCurrent
- end
-
- def initialize(app)
- # Invoke the base class initializer
- super(app, "OpenGL Test Application", nil, nil, DECOR_ALL, 0, 0, 1024, 768)
-
- # Construct the main window elements
- frame = FXHorizontalFrame.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
- frame.padLeft, frame.padRight = 0, 0
- frame.padTop, frame.padBottom = 0, 0
-
- # Left pane to contain the glcanvas
- glcanvasFrame = FXVerticalFrame.new(frame,
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- glcanvasFrame.padLeft, glcanvasFrame.padRight = 10, 10
- glcanvasFrame.padTop, glcanvasFrame.padBottom = 10, 10
-
- # Label above the glcanvas
- FXLabel.new(glcanvasFrame, "OpenGL Canvas Frame", nil,
- JUSTIFY_CENTER_X|LAYOUT_FILL_X)
-
- # Horizontal divider line
- FXHorizontalSeparator.new(glcanvasFrame, SEPARATOR_GROOVE|LAYOUT_FILL_X)
-
- # Drawing glcanvas
- glpanel = FXVerticalFrame.new(glcanvasFrame, (FRAME_SUNKEN|FRAME_THICK|
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT))
- glpanel.padLeft, glpanel.padRight = 0, 0
- glpanel.padTop, glpanel.padBottom = 0, 0
-
- # A visual to draw OpenGL
- @glvisual = FXGLVisual.new(getApp(), VISUAL_DOUBLEBUFFER)
-
- # Drawing glcanvas
- @glcanvas = FXGLCanvas.new(glpanel, @glvisual, nil, 0,
- LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- @glcanvas.connect(SEL_PAINT) {
- drawScene
- }
- @glcanvas.connect(SEL_CONFIGURE) {
- if @glcanvas.makeCurrent
- GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
- @glcanvas.makeNonCurrent
- end
- }
-
- # Right pane for the buttons
- buttonFrame = FXVerticalFrame.new(frame, LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_LEFT)
- buttonFrame.padLeft, buttonFrame.padRight = 10, 10
- buttonFrame.padTop, buttonFrame.padBottom = 10, 10
-
- # Label above the buttons
- FXLabel.new(buttonFrame, "Button Frame", nil,
- JUSTIFY_CENTER_X|LAYOUT_FILL_X)
-
- # Horizontal divider line
- FXHorizontalSeparator.new(buttonFrame, SEPARATOR_RIDGE|LAYOUT_FILL_X)
-
- # Spin according to timer
- spinTimerBtn = FXButton.new(buttonFrame,
- "Spin &Timer\tSpin using interval timers\nNote the app
- blocks until the interal has elapsed...", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- spinTimerBtn.padLeft, spinTimerBtn.padRight = 10, 10
- spinTimerBtn.padTop, spinTimerBtn.padBottom = 5, 5
- spinTimerBtn.connect(SEL_COMMAND) {
- @spinning = true
- @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
- }
- spinTimerBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.disable : sender.enable
- }
-
- # Spin according to chore
- spinChoreBtn = FXButton.new(buttonFrame,
- "Spin &Chore\tSpin as fast as possible using chores\nNote even though the
- app is very responsive, it never blocks;\nthere is always something to
- do...", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- spinChoreBtn.padLeft, spinChoreBtn.padRight = 10, 10
- spinChoreBtn.padTop, spinChoreBtn.padBottom = 5, 5
- spinChoreBtn.connect(SEL_COMMAND) {
- @spinning = true
- @chore = getApp().addChore(method(:onChore))
- }
- spinChoreBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.disable : sender.enable
- }
-
- # Stop spinning
- stopBtn = FXButton.new(buttonFrame,
- "&Stop Spin\tStop this mad spinning, I'm getting dizzy", nil,
- nil, 0, FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- stopBtn.padLeft, stopBtn.padRight = 10, 10
- stopBtn.padTop, stopBtn.padBottom = 5, 5
- stopBtn.connect(SEL_COMMAND) {
- @spinning = false
- if @timer
- getApp().removeTimeout(@timer)
- @timer = nil
- end
- if @chore
- getApp().removeChore(@chore)
- @chore = nil
- end
- }
- stopBtn.connect(SEL_UPDATE) { |sender, sel, ptr|
- @spinning ? sender.enable : sender.disable
- }
-
- # Exit button
- exitBtn = FXButton.new(buttonFrame, "&Exit\tExit the application", nil,
- getApp(), FXApp::ID_QUIT,
- FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT)
- exitBtn.padLeft, exitBtn.padRight = 10, 10
- exitBtn.padTop, exitBtn.padBottom = 5, 5
-
- # Make a tooltip
- FXTooltip.new(getApp())
-
- # Initialize private variables
- @spinning = false
- @chore = nil
- @timer = nil
- @angle = 0.0
- @size = 0.5
- end
-
- # Create and initialize
- def create
- super
- show(PLACEMENT_SCREEN)
- end
-end
-
-if __FILE__ == $0
- # Construct the application
- application = FXApp.new("GLTest", "FoxTest")
-
- # To ensure that the chores-based spin will run as fast as possible,
- # we can disable the chore in FXRuby's event loop that tries to schedule
- # other threads. This is OK for this program because there aren't any
- # other Ruby threads running.
-
- #application.disableThreads
-
- # Construct the main window
- GLTestWindow.new(application)
-
- # Create the app's windows
- application.create
-
- # Run the application
- application.run
-end
-
-class Facelet
- attr_accessor :color
- def initialize(color)
- @color = color
- end
-
- def to_s
- @color
- end
-end
-
-class Edge
- attr_accessor :facelets, :colors
-
- def initialize(facelets)
- @facelets = facelets
- @colors = @facelets.map { |fl| fl.color }
- end
-
- def apply(edge)
- @facelets.each_with_index { |fl, i|
- fl.color = edge.colors[i]
- }
- end
-
- def inspect
- "\n%s %s\n%s %s %s" % facelets
- end
-end
-
-class Side
- attr_reader :num, :facelets
- attr_accessor :sides
-
- def initialize(num)
- @num = num
- @sides = []
- @facelets = []
- @fl_by_side = {}
- end
-
- # facelets & sides
- # 0
- # 0 1 2
- # 3 3 4 5 1
- # 6 7 8
- # 2
-
- def facelets=(facelets)
- @facelets = facelets.map { |c| Facelet.new(c) }
- init_facelet 0, 3,0
- init_facelet 1, 0
- init_facelet 2, 0,1
- init_facelet 3, 3
- init_facelet 5, 1
- init_facelet 6, 2,3
- init_facelet 7, 2
- init_facelet 8, 1,2
- end
-
- def <=>(side)
- self.num <=> side.num
- end
-
- def init_facelet(pos, *side_nums)
- sides = side_nums.map { |num| @sides[num] }.sort
- @fl_by_side[sides] = pos
- end
-
- def []=(color, *sides)
- @facelets[@fl_by_side[sides.sort]].color = color
- end
-
- def values_at(*sides)
- sides.map { |sides| @facelets[@fl_by_side[sides.sort]] }
- end
-
- def inspect(range=nil)
- if range
- @facelets.values_at(*(range.to_a)).join(' ')
- else
- <<-EOS.gsub(/\d/) { |num| @facelets[num.to_i] }.gsub(/[ABCD]/) { |side| @sides[side[0]-?A].num.to_s }
- A
- 0 1 2
- D 3 4 5 B
- 6 7 8
- C
- EOS
- end
- end
-
- def get_edge(side)
- trio = (-1..1).map { |x| (side + x) % 4 }
- prev_side, this_side, next_side = @sides.values_at(*trio)
- e = Edge.new(
- self .values_at( [this_side], [this_side, next_side] ) +
- this_side.values_at( [self, prev_side], [self ], [self, next_side] )
- )
- #puts 'Edge created for side %d: ' % side + e.inspect
- e
- end
-
- def turn(dir)
- #p 'turn side %d in %d' % [num, dir]
- edges = (0..3).map { |n| get_edge n }
- for i in 0..3
- edges[i].apply edges[(i-dir) % 4]
- end
- end
-end
-
-class Cube
- def initialize
- @sides = []
- %w(left front right back top bottom).each_with_index { |side, i|
- eval("@sides[#{i}] = @#{side} = Side.new(#{i})")
- }
- @left.sides = [@top, @front, @bottom, @back]
- @front.sides = [@top, @right, @bottom, @left]
- @right.sides = [@top, @back, @bottom, @front]
- @back.sides = [@top, @left, @bottom, @right]
- @top.sides = [@back, @right, @front, @left]
- @bottom.sides = [@front, @right, @back, @left]
- end
-
- def read_facelets(fs)
- pattern = Regexp.new(<<-EOP.gsub(/\w/, '\w').gsub(/\s+/, '\s*'))
- (w w w)
- (w w w)
- (w w w)
-(r r r) (g g g) (b b b) (o o o)
-(r r r) (g g g) (b b b) (o o o)
-(r r r) (g g g) (b b b) (o o o)
- (y y y)
- (y y y)
- (y y y)
- EOP
- md = pattern.match(fs).to_a
-
- @top.facelets = parse_facelets(md.values_at(1,2,3))
- @left.facelets = parse_facelets(md.values_at(4,8,12))
- @front.facelets = parse_facelets(md.values_at(5,9,13))
- @right.facelets = parse_facelets(md.values_at(6,10,14))
- @back.facelets = parse_facelets(md.values_at(7,11,15))
- @bottom.facelets = parse_facelets(md.values_at(16,17,18))
- end
-
- def turn(side, dir)
- #p 'turn %d in %d' % [side, dir]
- @sides[side].turn(dir)
- #puts inspect
- end
-
- def inspect
- <<-EOF.gsub(/(\d):(\d)-(\d)/) { @sides[$1.to_i].inspect(Range.new($2.to_i, $3.to_i)) }
- 4:0-2
- 4:3-5
- 4:6-8
-0:0-2 1:0-2 2:0-2 3:0-2
-0:3-5 1:3-5 2:3-5 3:3-5
-0:6-8 1:6-8 2:6-8 3:6-8
- 5:0-2
- 5:3-5
- 5:6-8
- EOF
- end
-
-private
- def parse_facelets(rows)
- rows.join.delete(' ').split(//)
- end
-end
-
-#$stdin = DATA
-
-gets.to_i.times do |i|
- puts "Scenario ##{i+1}:"
- fs = ''
- 9.times { fs << gets }
- cube = Cube.new
- cube.read_facelets fs
- gets.to_i.times do |t|
- side, dir = gets.split.map {|s| s.to_i}
- cube.turn(side, dir)
- end
- puts cube.inspect
- puts
-end
-
-# 2004 by murphy <korny@cYcnus.de>
-# GPL
-class Scenario
- class TimePoint
- attr_reader :data
- def initialize *data
- @data = data
- end
-
- def [] i
- @data[i] or 0
- end
-
- include Comparable
- def <=> tp
- r = 0
- [@data.size, tp.data.size].max.times do |i|
- r = self[i] <=> tp[i]
- return r if r.nonzero?
- end
- 0
- end
-
- def - tp
- r = []
- [@data.size, tp.data.size].max.times do |i|
- r << self[i] - tp[i]
- end
- r
- end
-
- def inspect
- # 01/01/1800 00:00:00
- '%02d/%02d/%04d %02d:%02d:%02d' % @data.values_at(1, 2, 0, 3, 4, 5)
- end
- end
-
- ONE_HOUR = TimePoint.new 0, 0, 0, 1, 0, 0
-
- APPOINTMENT_PATTERN = /
- ( \d{4} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s
- ( \d{4} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} ) \s ( \d{2} )
- /x
-
- def initialize io
- @team_size = io.gets.to_i
- @data = [ [TimePoint.new(1800, 01, 01, 00, 00, 00), @team_size] ]
- @team_size.times do # each team member
- io.gets.to_i.times do # each appointment
- m = APPOINTMENT_PATTERN.match io.gets
- @data << [TimePoint.new(*m.captures[0,6].map { |x| x.to_i }), -1]
- @data << [TimePoint.new(*m.captures[6,6].map { |x| x.to_i }), +1]
- end
- end
- @data << [TimePoint.new(2200, 01, 01, 00, 00, 00), -@team_size]
- end
-
- def print_time_plan
- n = 0
- appointment = nil
- no_appointment = true
- @data.sort_by { |x| x[0] }.each do |x|
- tp, action = *x
- n += action
- # at any time during the meeting, at least two team members need to be there
- # and at most one team member is allowed to be absent
- if n >= 2 and (@team_size - n) <= 1
- appointment ||= tp
- else
- if appointment
- # the meeting should be at least one hour in length
- if TimePoint.new(*(tp - appointment)) >= ONE_HOUR
- puts 'appointment possible from %p to %p' % [appointment, tp]
- no_appointment = false
- end
- appointment = false
- end
- end
- end
- puts 'no appointment possible' if no_appointment
- end
-end
-
-# read the data
-DATA.gets.to_i.times do |si| # each scenario
- puts 'Scenario #%d:' % (si + 1)
- sc = Scenario.new DATA
- sc.print_time_plan
- puts
-end
-
-#__END__
-2
-3
-3
-2002 06 28 15 00 00 2002 06 28 18 00 00 TUD Contest Practice Session
-2002 06 29 10 00 00 2002 06 29 15 00 00 TUD Contest
-2002 11 15 15 00 00 2002 11 17 23 00 00 NWERC Delft
-4
-2002 06 25 13 30 00 2002 06 25 15 30 00 FIFA World Cup Semifinal I
-2002 06 26 13 30 00 2002 06 26 15 30 00 FIFA World Cup Semifinal II
-2002 06 29 13 00 00 2002 06 29 15 00 00 FIFA World Cup Third Place
-2002 06 30 13 00 00 2002 06 30 15 00 00 FIFA World Cup Final
-1
-2002 06 01 00 00 00 2002 06 29 18 00 00 Preparation of Problem Set
-2
-1
-1800 01 01 00 00 00 2200 01 01 00 00 00 Solving Problem 8
-0
-
-require 'token_consts'
-require 'symbol'
-require 'ctype'
-require 'error'
-
-class Fixnum
- # Treat char as a digit and return it's value as Fixnum.
- # Returns nonsense for non-digits.
- # Examples:
- # <code>
- # RUBY_VERSION[0].digit == '1.8.2'[0].digit == 1
- # </code>
- #
- # <code>
- # ?6.digit == 6
- # </code>
- #
- # <code>
- # ?A.digit == 17
- # </code>
- def digit
- self - ?0
- end
-end
-
-##
-# Stellt einen einfachen Scanner für die lexikalische Analyse der Sprache Pas-0 dar.
-#
-# @author Andreas Kunert
-# Ruby port by murphy
-class Scanner
-
- include TokenConsts
-
- attr_reader :line, :pos
-
- # To allow Scanner.new without parameters.
- DUMMY_INPUT = 'dummy file'
- def DUMMY_INPUT.getc
- nil
- end
-
- ##
- # Erzeugt einen Scanner, der als Eingabe das übergebene IO benutzt.
- def initialize input = DUMMY_INPUT
- @line = 1
- @pos = 0
-
- begin
- @input = input
- @next_char = @input.getc
- rescue IOError # TODO show the reason!
- Error.ioError
- raise
- end
- end
-
- ##
- # Liest das n
- def read_next_char
- begin
- @pos += 1
- @current_char = @next_char
- @next_char = @input.getc
- rescue IOError
- Error.ioError
- raise
- end
- end
-
- ##
- # Sucht das nächste Symbol, identifiziert es, instantiiert ein entsprechendes
- # PascalSymbol-Objekt und gibt es zurück.
- # @see Symbol
- # @return das gefundene Symbol als PascalSymbol-Objekt
- def get_symbol
- current_symbol = nil
- until current_symbol
- read_next_char
-
- if @current_char.alpha?
- identifier = @current_char.chr
- while @next_char.alpha? or @next_char.digit?
- identifier << @next_char
- read_next_char
- end
- current_symbol = handle_identifier(identifier.upcase)
- elsif @current_char.digit?
- current_symbol = number
- else
- case @current_char
- when ?\s
- # ignore
- when ?\n
- new_line
- when nil
- current_symbol = PascalSymbol.new EOP
- when ?{
- comment
-
- when ?:
- if @next_char == ?=
- read_next_char
- current_symbol = PascalSymbol.new BECOMES
- else
- current_symbol = PascalSymbol.new COLON
- end
-
- when ?<
- if (@next_char == ?=)
- read_next_char
- current_symbol = PascalSymbol.new LEQSY
- elsif (@next_char == ?>)
- read_next_char
- current_symbol = PascalSymbol.new NEQSY
- else
- current_symbol = PascalSymbol.new LSSSY
- end
-
- when ?>
- if (@next_char == ?=)
- read_next_char
- current_symbol = PascalSymbol.new GEQSY
- else
- current_symbol = PascalSymbol.new GRTSY
- end
-
- when ?. then current_symbol = PascalSymbol.new PERIOD
- when ?( then current_symbol = PascalSymbol.new LPARENT
- when ?, then current_symbol = PascalSymbol.new COMMA
- when ?* then current_symbol = PascalSymbol.new TIMES
- when ?/ then current_symbol = PascalSymbol.new SLASH
- when ?+ then current_symbol = PascalSymbol.new PLUS
- when ?- then current_symbol = PascalSymbol.new MINUS
- when ?= then current_symbol = PascalSymbol.new EQLSY
- when ?) then current_symbol = PascalSymbol.new RPARENT
- when ?; then current_symbol = PascalSymbol.new SEMICOLON
- else
- Error.error(100, @line, @pos) if @current_char > ?\s
- end
- end
- end
- current_symbol
- end
-
-private
- ##
- # Versucht, in dem gegebenen String ein Schlüsselwort zu erkennen.
- # Sollte dabei ein Keyword gefunden werden, so gibt er ein PascalSymbol-Objekt zurück, das
- # das entsprechende Keyword repräsentiert. Ansonsten besteht die Rückgabe aus
- # einem SymbolIdent-Objekt (abgeleitet von PascalSymbol), das den String 1:1 enthält
- # @see symbol
- # @return falls Keyword gefunden, zugehöriges PascalSymbol, sonst SymbolIdent
- def handle_identifier identifier
- if sym = KEYWORD_SYMBOLS[identifier]
- PascalSymbol.new sym
- else
- SymbolIdent.new identifier
- end
- end
-
- MAXINT = 2**31 - 1
- MAXINT_DIV_10 = MAXINT / 10
- MAXINT_MOD_10 = MAXINT % 10
- ##
- # Versucht, aus dem gegebenen Zeichen und den folgenden eine Zahl zusammenzusetzen.
- # Dabei wird der relativ intuitive Algorithmus benutzt, die endgültige Zahl bei
- # jeder weiteren Ziffer mit 10 zu multiplizieren und diese dann mit der Ziffer zu
- # addieren. Sonderfälle bestehen dann nur noch in der Behandlung von reellen Zahlen.
- # <BR>
- # Treten dabei kein Punkt oder ein E auf, so gibt diese Methode ein SymbolIntCon-Objekt
- # zurück, ansonsten (reelle Zahl) ein SymbolRealCon-Objekt. Beide Symbole enthalten
- # jeweils die Zahlwerte.
- # <BR>
- # Anmerkung: Diese Funktion ist mit Hilfe der Java/Ruby-API deutlich leichter zu realisieren.
- # Sie wurde dennoch so implementiert, um den Algorithmus zu demonstrieren
- # @see symbol
- # @return SymbolIntcon- oder SymbolRealcon-Objekt, das den Zahlwert enthält
- def number
- is_integer = true
- integer_too_long = false
- exponent = 0
- exp_counter = -1
- exp_sign = 1
-
- integer_mantisse = @current_char.digit
-
- while (@next_char.digit? and integer_mantisse < MAXINT_DIV_10) or
- (integer_mantisse == MAXINT_DIV_10 and @next_char.digit <= MAXINT_MOD_10)
- integer_mantisse *= 10
- integer_mantisse += @next_char.digit
- read_next_char
- end
-
- real_mantisse = integer_mantisse
-
- while @next_char.digit?
- integer_too_long = true
- real_mantisse *= 10
- real_mantisse += @next_char.digit
- read_next_char
- end
- if @next_char == ?.
- read_next_char
- is_integer = false
- unless @next_char.digit?
- Error.error 101, @line, @pos
- end
- while @next_char.digit?
- real_mantisse += @next_char.digit * (10 ** exp_counter)
- read_next_char
- exp_counter -= 1
- end
- end
- if @next_char == ?E
- is_integer = false
- read_next_char
- if @next_char == ?-
- exp_sign = -1
- read_next_char
- end
- unless @next_char.digit?
- Error.error 101, @line, @pos
- end
- while @next_char.digit?
- exponent *= 10
- exponent += @next_char.digit
- read_next_char
- end
- end
-
- if is_integer
- if integer_too_long
- Error.error 102, @line, @pos
- end
- SymbolIntcon.new integer_mantisse
- else
- SymbolRealcon.new real_mantisse * (10 ** (exp_sign * exponent))
- end
- end
-
- ##
- # Sorgt für ein Überlesen von Kommentaren.
- # Es werden einfach alle Zeichen bis zu einer schließenden Klammer eingelesen
- # und verworfen.
- def comment
- while @current_char != ?}
- forbid_eop
- new_line if @current_char == ?\n
- read_next_char
- end
- end
-
- def new_line
- @line += 1
- @pos = 0
- end
-
- def forbid_eop
- if eop?
- Error.error 103, @line, @pos
- end
- exit
- end
-
- def eop?
- @current_char.nil?
- end
-end
-
-##
-# Läßt ein Testprogramm ablaufen.
-# Dieses erzeugt sich ein Scanner-Objekt und ruft an diesem kontinuierlich bis zum Dateiende
-# get_symbol auf.
-if $0 == __FILE__
- scan = Scanner.new(File.new(ARGV[0] || 'test.pas'))
- loop do
- c = scan.get_symbol
- puts c
- break if c.typ == TokenConsts::EOP
- end
-end
-# -*- ruby -*-
-
-# Local variables:
-# indent-tabs-mode: nil
-# ruby-indent-level: 4
-# End:
-
-# @@PLEAC@@_NAME
-# @@SKIP@@ Ruby
-
-# @@PLEAC@@_WEB
-# @@SKIP@@ http://www.ruby-lang.org
-
-
-# @@PLEAC@@_1.0
-string = '\n' # two characters, \ and an n
-string = 'Jon \'Maddog\' Orwant' # literal single quotes
-
-string = "\n" # a "newline" character
-string = "Jon \"Maddog\" Orwant" # literal double quotes
-
-string = %q/Jon 'Maddog' Orwant/ # literal single quotes
-
-string = %q[Jon 'Maddog' Orwant] # literal single quotes
-string = %q{Jon 'Maddog' Orwant} # literal single quotes
-string = %q(Jon 'Maddog' Orwant) # literal single quotes
-string = %q<Jon 'Maddog' Orwant> # literal single quotes
-
-a = <<"EOF"
-This is a multiline here document
-terminated by EOF on a line by itself
-EOF
-
-
-# @@PLEAC@@_1.1
-value = string[offset,count]
-value = string[offset..-1]
-
-string[offset,count] = newstring
-string[offset..-1] = newtail
-
-# in Ruby we can also specify intervals by their two offsets
-value = string[offset..offs2]
-string[offset..offs2] = newstring
-
-leading, s1, s2, trailing = data.unpack("A5 x3 A8 A8 A*")
-
-fivers = string.unpack("A5" * (string.length/5))
-
-chars = string.unpack("A1" * string.length)
-
-string = "This is what you have"
-# +012345678901234567890 Indexing forwards (left to right)
-# 109876543210987654321- Indexing backwards (right to left)
-# note that 0 means 10 or 20, etc. above
-
-first = string[0, 1] # "T"
-start = string[5, 2] # "is"
-rest = string[13..-1] # "you have"
-last = string[-1, 1] # "e"
-end_ = string[-4..-1] # "have"
-piece = string[-8, 3] # "you"
-
-string[5, 2] = "wasn't" # change "is" to "wasn't"
-string[-12..-1] = "ondrous" # "This wasn't wondrous"
-string[0, 1] = "" # delete first character
-string[-10..-1] = "" # delete last 10 characters
-
-if string[-10..-1] =~ /pattern/
- puts "Pattern matches in last 10 characters"
-end
-
-string[0, 5].gsub!(/is/, 'at')
-
-a = "make a hat"
-a[0, 1], a[-1, 1] = a[-1, 1], a[0, 1]
-
-a = "To be or not to be"
-b = a.unpack("x6 A6")
-
-b, c = a.unpack("x6 A2 X5 A2")
-puts "#{b}\n#{c}\n"
-
-def cut2fmt(*args)
- template = ''
- lastpos = 1
- for place in args
- template += "A" + (place - lastpos).to_s + " "
- lastpos = place
- end
- template += "A*"
- return template
-end
-
-fmt = cut2fmt(8, 14, 20, 26, 30)
-
-
-# @@PLEAC@@_1.2
-# careful! "b is true" doesn't mean "b != 0" (0 is true in Ruby)
-# thus no problem of "defined" later since only nil is false
-# the following sets to `c' if `b' is nil or false
-a = b || c
-
-# if you need Perl's behaviour (setting to `c' if `b' is 0) the most
-# effective way is to use Numeric#nonzero? (thanks to Dave Thomas!)
-a = b.nonzero? || c
-
-# you will still want to use defined? in order to test
-# for scope existence of a given object
-a = defined?(b) ? b : c
-
-dir = ARGV.shift || "/tmp"
-
-
-# @@PLEAC@@_1.3
-v1, v2 = v2, v1
-
-alpha, beta, production = %w(January March August)
-alpha, beta, production = beta, production, alpha
-
-
-# @@PLEAC@@_1.4
-num = char[0]
-char = num.chr
-
-# Ruby also supports having a char from character constant
-num = ?r
-
-char = sprintf("%c", num)
-printf("Number %d is character %c\n", num, num)
-
-ascii = string.unpack("C*")
-string = ascii.pack("C*")
-
-hal = "HAL"
-ascii = hal.unpack("C*")
-# We can't use Array#each since we can't mutate a Fixnum
-ascii.collect! { |i|
- i + 1 # add one to each ASCII value
-}
-ibm = ascii.pack("C*")
-puts ibm
-
-
-# @@PLEAC@@_1.5
-array = string.split('')
-
-array = string.unpack("C*")
-
-string.scan(/./) { |b|
- # do something with b
-}
-
-string = "an apple a day"
-print "unique chars are: ", string.split('').uniq.sort, "\n"
-
-sum = 0
-for ascval in string.unpack("C*") # or use Array#each for a pure OO style :)
- sum += ascval
-end
-puts "sum is #{sum & 0xffffffff}" # since Ruby will go Bignum if necessary
-
-# @@INCLUDE@@ include/ruby/slowcat.rb
-
-
-# @@PLEAC@@_1.6
-revbytes = string.reverse
-
-revwords = string.split(" ").reverse.join(" ")
-
-revwords = string.split(/(\s+)/).reverse.join
-
-# using the fact that IO is Enumerable, you can directly "select" it
-long_palindromes = File.open("/usr/share/dict/words").
- select { |w| w.chomp!; w.reverse == w && w.length > 5 }
-
-
-# @@PLEAC@@_1.7
-while string.sub!("\t+") { ' ' * ($&.length * 8 - $`.length % 8) }
-end
-
-
-# @@PLEAC@@_1.8
-'You owe #{debt} to me'.gsub(/\#{(\w+)}/) { eval($1) }
-
-rows, cols = 24, 80
-text = %q(I am #{rows} high and #{cols} long)
-text.gsub!(/\#{(\w+)}/) { eval("#{$1}") }
-puts text
-
-'I am 17 years old'.gsub(/\d+/) { 2 * $&.to_i }
-
-
-# @@PLEAC@@_1.9
-e = "bo peep".upcase
-e.downcase!
-e.capitalize!
-
-"thIS is a loNG liNE".gsub!(/\w+/) { $&.capitalize }
-
-
-# @@PLEAC@@_1.10
-"I have #{n+1} guanacos."
-print "I have ", n+1, " guanacos."
-
-
-# @@PLEAC@@_1.11
-var = <<'EOF'.gsub(/^\s+/, '')
- your text
- goes here
-EOF
-
-
-# @@PLEAC@@_1.12
-string = "Folding and splicing is the work of an editor,\n"+
- "not a mere collection of silicon\n"+
- "and\n"+
- "mobile electrons!"
-
-def wrap(str, max_size)
- all = []
- line = ''
- for l in str.split
- if (line+l).length >= max_size
- all.push(line)
- line = ''
- end
- line += line == '' ? l : ' ' + l
- end
- all.push(line).join("\n")
-end
-
-print wrap(string, 20)
-#=> Folding and
-#=> splicing is the
-#=> work of an editor,
-#=> not a mere
-#=> collection of
-#=> silicon and mobile
-#=> electrons!
-
-
-# @@PLEAC@@_1.13
-string = %q(Mom said, "Don't do that.")
-string.gsub(/['"]/) { '\\'+$& }
-string.gsub(/['"]/, '\&\&')
-string.gsub(/[^A-Z]/) { '\\'+$& }
-"is a test!".gsub(/\W/) { '\\'+$& } # no function like quotemeta?
-
-
-# @@PLEAC@@_1.14
-string.strip!
-
-
-# @@PLEAC@@_1.15
-def parse_csv(text)
- new = text.scan(/"([^\"\\]*(?:\\.[^\"\\]*)*)",?|([^,]+),?|,/)
- new << nil if text[-1] == ?,
- new.flatten.compact
-end
-
-line = %q<XYZZY,"","O'Reilly, Inc","Wall, Larry","a \"glug\" bit,",5,"Error, Core Dumped">
-fields = parse_csv(line)
-fields.each_with_index { |v,i|
- print "#{i} : #{v}\n";
-}
-
-
-# @@PLEAC@@_1.16
-# Use the soundex.rb Library from Michael Neumann.
-# http://www.s-direktnet.de/homepages/neumann/rb_prgs/Soundex.rb
-require 'Soundex'
-
-code = Text::Soundex.soundex(string)
-codes = Text::Soundex.soundex(array)
-
-# substitution function for getpwent():
-# returns an array of user entries,
-# each entry contains the username and the full name
-def login_names
- result = []
- File.open("/etc/passwd") { |file|
- file.each_line { |line|
- next if line.match(/^#/)
- cols = line.split(":")
- result.push([cols[0], cols[4]])
- }
- }
- result
-end
-
-puts "Lookup user: "
-user = STDIN.gets
-user.chomp!
-exit unless user
-name_code = Text::Soundex.soundex(user)
-
-splitter = Regexp.new('(\w+)[^,]*\b(\w+)')
-for username, fullname in login_names do
- firstname, lastname = splitter.match(fullname)[1,2]
- if name_code == Text::Soundex.soundex(username)
- || name_code == Text::Soundex.soundex(firstname)
- || name_code == Text::Soundex.soundex(lastname)
- then
- puts "#{username}: #{firstname} #{lastname}"
- end
-end
-
-
-# @@PLEAC@@_1.17
-# @@INCLUDE@@ include/ruby/fixstyle.rb
-
-
-# @@PLEAC@@_1.18
-# @@INCLUDE@@ include/ruby/psgrep.rb
-
-
-# @@PLEAC@@_2.1
-# Matz tells that you can use Integer() for strict checked conversion.
-Integer("abc")
-#=> `Integer': invalid value for Integer: "abc" (ArgumentError)
-Integer("567")
-#=> 567
-
-# You may use Float() for floating point stuff
-Integer("56.7")
-#=> `Integer': invalid value for Integer: "56.7" (ArgumentError)
-Float("56.7")
-#=> 56.7
-
-# You may also use a regexp for that
-if string =~ /^[+-]?\d+$/
- p 'is an integer'
-else
- p 'is not'
-end
-
-if string =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/
- p 'is a decimal number'
-else
- p 'is not'
-end
-
-
-# @@PLEAC@@_2.2
-# equal(num1, num2, accuracy) : returns true if num1 and num2 are
-# equal to accuracy number of decimal places
-def equal(i, j, a)
- sprintf("%.#{a}g", i) == sprintf("%.#{a}g", j)
-end
-
-wage = 536 # $5.36/hour
-week = 40 * wage # $214.40
-printf("One week's wage is: \$%.2f\n", week/100.0)
-
-
-# @@PLEAC@@_2.3
-num.round # rounds to integer
-
-a = 0.255
-b = sprintf("%.2f", a)
-print "Unrounded: #{a}\nRounded: #{b}\n"
-printf "Unrounded: #{a}\nRounded: %.2f\n", a
-
-print "number\tint\tfloor\tceil\n"
-a = [ 3.3 , 3.5 , 3.7, -3.3 ]
-for n in a
- printf("% .1f\t% .1f\t% .1f\t% .1f\n", # at least I don't fake my output :)
- n, n.to_i, n.floor, n.ceil)
-end
-
-
-# @@PLEAC@@_2.4
-def dec2bin(n)
- [n].pack("N").unpack("B32")[0].sub(/^0+(?=\d)/, '')
-end
-
-def bin2dec(n)
- [("0"*32+n.to_s)[-32..-1]].pack("B32").unpack("N")[0]
-end
-
-
-# @@PLEAC@@_2.5
-for i in x .. y
- # i is set to every integer from x to y, inclusive
-end
-
-x.step(y,7) { |i|
- # i is set to every integer from x to y, stepsize = 7
-}
-
-print "Infancy is: "
-(0..2).each { |i|
- print i, " "
-}
-print "\n"
-
-
-# @@PLEAC@@_2.6
-# We can add conversion methods to the Integer class,
-# this makes a roman number just a representation for normal numbers.
-class Integer
-
- @@romanlist = [["M", 1000],
- ["CM", 900],
- ["D", 500],
- ["CD", 400],
- ["C", 100],
- ["XC", 90],
- ["L", 50],
- ["XL", 40],
- ["X", 10],
- ["IX", 9],
- ["V", 5],
- ["IV", 4],
- ["I", 1]]
-
- def to_roman
- remains = self
- roman = ""
- for sym, num in @@romanlist
- while remains >= num
- remains -= num
- roman << sym
- end
- end
- roman
- end
-
- def Integer.from_roman(roman)
- ustr = roman.upcase
- sum = 0
- for entry in @@romanlist
- sym, num = entry[0], entry[1]
- while sym == ustr[0, sym.length]
- sum += num
- ustr.slice!(0, sym.length)
- end
- end
- sum
- end
-
-end
-
-
-roman_fifteen = 15.to_roman
-puts "Roman for fifteen is #{roman_fifteen}"
-i = Integer.from_roman(roman_fifteen)
-puts "Converted back, #{roman_fifteen} is #{i}"
-
-# check
-for i in (1..3900)
- r = i.to_roman
- j = Integer.from_roman(r)
- if i != j
- puts "error: #{i} : #{r} - #{j}"
- end
-end
-
-
-# @@PLEAC@@_2.7
-random = rand(y-x+1)+x
-
-chars = ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!@$%^&*)
-password = (1..8).collect { chars[rand(chars.size)] }.pack("C*")
-
-
-# @@PLEAC@@_2.8
-srand # uses a combination of the time, the process id, and a sequence number
-srand(val) # for repeatable behaviour
-
-
-# @@PLEAC@@_2.9
-# from the randomr lib:
-# http://raa.ruby-lang.org/project/randomr/
-----> http://raa.ruby-lang.org/project/randomr/
-
-require 'random/mersenne_twister'
-mers = Random::MersenneTwister.new 123456789
-puts mers.rand(0) # 0.550321932544541
-puts mers.rand(10) # 2
-
-# using online sources of random data via the realrand package:
-# http://raa.ruby-lang.org/project/realrand/
-# **Note**
-# The following online services are used in this package:
-# http://www.random.org - source: atmospheric noise
-# http://www.fourmilab.ch/hotbits - source: radioactive decay timings
-# http://random.hd.org - source: entropy from local and network noise
-# Please visit the sites and respect the rules of each service.
-
-require 'random/online'
-
-generator1 = Random::RandomOrg.new
-puts generator1.randbyte(5).join(",")
-puts generator1.randnum(10, 1, 6).join(",") # Roll dice 10 times.
-
-generator2 = Random::FourmiLab.new
-puts generator2.randbyte(5).join(",")
-# randnum is not supported.
-
-generator3 = Random::EntropyPool.new
-puts generator3.randbyte(5).join(",")
-# randnum is not supported.
-
-
-# @@PLEAC@@_2.10
-def gaussian_rand
- begin
- u1 = 2 * rand() - 1
- u2 = 2 * rand() - 1
- w = u1*u1 + u2*u2
- end while (w >= 1)
- w = Math.sqrt((-2*Math.log(w))/w)
- [ u2*w, u1*w ]
-end
-
-mean = 25
-sdev = 2
-salary = gaussian_rand[0] * sdev + mean
-printf("You have been hired at \$%.2f\n", salary)
-
-
-# @@PLEAC@@_2.11
-def deg2rad(d)
- (d/180.0)*Math::PI
-end
-
-def rad2deg(r)
- (r/Math::PI)*180
-end
-
-
-# @@PLEAC@@_2.12
-sin_val = Math.sin(angle)
-cos_val = Math.cos(angle)
-tan_val = Math.tan(angle)
-
-# AFAIK Ruby's Math module doesn't provide acos/asin
-# While we're at it, let's also define missing hyperbolic functions
-module Math
- def Math.asin(x)
- atan2(x, sqrt(1 - x**2))
- end
- def Math.acos(x)
- atan2(sqrt(1 - x**2), x)
- end
- def Math.atan(x)
- atan2(x, 1)
- end
- def Math.sinh(x)
- (exp(x) - exp(-x)) / 2
- end
- def Math.cosh(x)
- (exp(x) + exp(-x)) / 2
- end
- def Math.tanh(x)
- sinh(x) / cosh(x)
- end
-end
-
-# The support for Complex numbers is not built-in
-y = Math.acos(3.7)
-#=> in `sqrt': square root for negative number (ArgumentError)
-
-# There is an implementation of Complex numbers in 'complex.rb' in current
-# Ruby distro, but it doesn't support atan2 with complex args, so it doesn't
-# solve this problem.
-
-
-# @@PLEAC@@_2.13
-log_e = Math.log(val)
-log_10 = Math.log10(val)
-
-def log_base(base, val)
- Math.log(val)/Math.log(base)
-end
-
-answer = log_base(10, 10_000)
-puts "log10(10,000) = #{answer}"
-
-
-# @@PLEAC@@_2.14
-require 'matrix.rb'
-
-a = Matrix[[3, 2, 3], [5, 9, 8]]
-b = Matrix[[4, 7], [9, 3], [8, 1]]
-c = a * b
-
-a.row_size
-a.column_size
-
-c.det
-a.transpose
-
-
-# @@PLEAC@@_2.15
-require 'complex.rb'
-require 'rational.rb'
-
-a = Complex(3, 5) # 3 + 5i
-b = Complex(2, -2) # 2 - 2i
-puts "c = #{a*b}"
-
-c = a * b
-d = 3 + 4*Complex::I
-
-printf "sqrt(#{d}) = %s\n", Math.sqrt(d)
-
-
-# @@PLEAC@@_2.16
-number = hexadecimal.hex
-number = octal.oct
-
-print "Gimme a number in decimal, octal, or hex: "
-num = gets.chomp
-exit unless defined?(num)
-num = num.oct if num =~ /^0/ # does both oct and hex
-printf "%d %x %o\n", num, num, num
-
-print "Enter file permission in octal: "
-permissions = gets.chomp
-raise "Exiting ...\n" unless defined?(permissions)
-puts "The decimal value is #{permissions.oct}"
-
-
-# @@PLEAC@@_2.17
-def commify(n)
- n.to_s =~ /([^\.]*)(\..*)?/
- int, dec = $1.reverse, $2 ? $2 : ""
- while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
- end
- int.reverse + dec
-end
-
-
-# @@PLEAC@@_2.18
-printf "It took %d hour%s\n", time, time == 1 ? "" : "s"
-
-# dunno if an equivalent to Lingua::EN::Inflect exists...
-
-
-# @@PLEAC@@_2.19
-#-----------------------------
-#!/usr/bin/ruby
-# bigfact - calculating prime factors
-def factorize(orig)
- factors = {}
- factors.default = 0 # return 0 instead nil if key not found in hash
- n = orig
- i = 2
- sqi = 4 # square of i
- while sqi <= n do
- while n.modulo(i) == 0 do
- n /= i
- factors[i] += 1
- # puts "Found factor #{i}"
- end
- # we take advantage of the fact that (i +1)**2 = i**2 + 2*i +1
- sqi += 2 * i + 1
- i += 1
- end
-
- if (n != 1) && (n != orig)
- factors[n] += 1
- end
- factors
-end
-
-def printfactorhash(orig, factorcount)
- print format("%-10d ", orig)
- if factorcount.length == 0
- print "PRIME"
- else
- # sorts after number, because the hash keys are numbers
- factorcount.sort.each { |factor,exponent|
- print factor
- if exponent > 1
- print "**", exponent
- end
- print " "
- }
- end
- puts
-end
-
-for arg in ARGV
- n = arg.to_i
- mfactors = factorize(n)
- printfactorhash(n, mfactors)
-end
-#-----------------------------
-
-
-# @@PLEAC@@_3.0
-puts Time.now
-
-print "Today is day ", Time.now.yday, " of the current year.\n"
-print "Today is day ", Time.now.day, " of the current month.\n"
-
-
-# @@PLEAC@@_3.1
-day, month, year = Time.now.day, Time.now.month, Time.now.year
-# or
-day, month, year = Time.now.to_a[3..5]
-
-tl = Time.now.localtime
-printf("The current date is %04d %02d %02d\n", tl.year, tl.month, tl.day)
-
-Time.now.localtime.strftime("%Y-%m-%d")
-
-
-# @@PLEAC@@_3.2
-Time.local(year, month, day, hour, minute, second).tv_sec
-Time.gm(year, month, day, hour, minute, second).tv_sec
-
-
-# @@PLEAC@@_3.3
-sec, min, hour, day, month, year, wday, yday, isdst, zone = Time.at(epoch_secs).to_a
-
-
-# @@PLEAC@@_3.4
-when_ = now + difference # now -> Time ; difference -> Numeric (delta in seconds)
-then_ = now - difference
-
-
-# @@PLEAC@@_3.5
-bree = 361535725
-nat = 96201950
-
-difference = bree - nat
-puts "There were #{difference} seconds between Nat and Bree"
-
-seconds = difference % 60
-difference = (difference - seconds) / 60
-minutes = difference % 60
-difference = (difference - minutes) / 60
-hours = difference % 24
-difference = (difference - hours) / 24
-days = difference % 7
-weeks = (difference - days) / 7
-
-puts "(#{weeks} weeks, #{days} days, #{hours}:#{minutes}:#{seconds})"
-
-
-# @@PLEAC@@_3.6
-monthday, weekday, yearday = date.mday, date.wday, date.yday
-
-# AFAIK the week number is not just a division since week boundaries are on sundays
-weeknum = d.strftime("%U").to_i + 1
-
-year = 1981
-month = "jun" # or `6' if you want to emulate a broken language
-day = 16
-t = Time.mktime(year, month, day)
-print "#{month}/#{day}/#{year} was a ", t.strftime("%A"), "\n"
-
-
-# @@PLEAC@@_3.7
-yyyy, mm, dd = $1, $2, $3 if "1998-06-25" =~ /(\d+)-(\d+)-(\d+)/
-
-epoch_seconds = Time.mktime(yyyy, mm, dd).tv_sec
-
-# dunno an equivalent to Date::Manip#ParseDate
-
-
-# @@PLEAC@@_3.8
-string = Time.at(epoch_secs)
-Time.at(1234567890).gmtime # gives: Fri Feb 13 23:31:30 UTC 2009
-
-time = Time.mktime(1973, "jan", 18, 3, 45, 50)
-print "In localtime it gives: ", time.localtime, "\n"
-
-
-# @@PLEAC@@_3.9
-# Ruby provides micro-seconds in Time object
-Time.now.usec
-
-# Ruby gives the seconds in floating format when substracting two Time objects
-before = Time.now
-line = gets
-elapsed = Time.now - before
-puts "You took #{elapsed} seconds."
-
-# On my Celeron-400 with Linux-2.2.19-14mdk, average for three execs are:
-# This Ruby version: average 0.00321 sec
-# Cookbook's Perl version: average 0.00981 sec
-size = 500
-number_of_times = 100
-total_time = 0
-number_of_times.times {
- # populate array
- array = []
- size.times { array << rand }
- # sort it
- begin_ = Time.now
- array.sort!
- time = Time.now - begin_
- total_time += time
-}
-printf "On average, sorting %d random numbers takes %.5f seconds\n",
- size, (total_time/Float(number_of_times))
-
-
-# @@PLEAC@@_3.10
-sleep(0.005) # Ruby is definitely not as broken as Perl :)
-# (may be interrupted by sending the process a SIGALRM)
-
-
-# @@PLEAC@@_3.11
-#!/usr/bin/ruby -w
-# hopdelta - feed mail header, produce lines
-# showing delay at each hop.
-require 'time'
-class MailHopDelta
-
- def initialize(mail)
- @head = mail.gsub(/\n\s+/,' ')
- @topline = %w-Sender Recipient Time Delta-
- @start_from = mail.match(/^From.*\@([^\s>]*)/)[1]
- @date = Time.parse(mail.match(/^Date:\s+(.*)/)[1])
- end
-
- def out(line)
- "%-20.20s %-20.20s %-20.20s %s" % line
- end
-
- def hop_date(day)
- day.strftime("%I:%M:%S %Y/%m/%d")
- end
-
- def puts_hops
- puts out(@topline)
- puts out(['Start', @start_from, hop_date(@date),''])
- @head.split(/\n/).reverse.grep(/^Received:/).each do |hop|
- hop.gsub!(/\bon (.*?) (id.*)/,'; \1')
- whence = hop.match(/;\s+(.*)$/)[1]
- unless whence
- warn "Bad received line: #{hop}"
- next
- end
- from = $+ if hop =~ /from\s+(\S+)|\((.*?)\)/
- by = $1 if hop =~ /by\s+(\S+\.\S+)/
- next unless now = Time.parse(whence).localtime
- delta = now - @date
- puts out([from, by, hop_date(now), hop_time(delta)])
- @date = now
- end
- end
-
- def hop_time(secs)
- sign = secs < 0 ? -1 : 1
- days, secs = secs.abs.divmod(60 * 60 * 24)
- hours,secs = secs.abs.divmod(60 * 60)
- mins, secs = secs.abs.divmod(60)
- rtn = "%3ds" % [secs * sign]
- rtn << "%3dm" % [mins * sign] if mins != 0
- rtn << "%3dh" % [hours * sign] if hours != 0
- rtn << "%3dd" % [days * sign] if days != 0
- rtn
- end
-end
-
-$/ = ""
-mail = MailHopDelta.new(ARGF.gets).puts_hops
-
-
-# @@PLEAC@@_4.0
-single_level = [ "this", "that", "the", "other" ]
-
-# Ruby directly supports nested arrays
-double_level = [ "this", "that", [ "the", "other" ] ]
-still_single_level = [ "this", "that", [ "the", "other" ] ].flatten
-
-
-# @@PLEAC@@_4.1
-a = [ "quick", "brown", "fox" ]
-a = %w(Why are you teasing me?)
-
-lines = <<"END_OF_HERE_DOC".gsub(/^\s*(.+)/, '\1')
- The boy stood on the burning deck,
- It was as hot as glass.
-END_OF_HERE_DOC
-
-bigarray = IO.readlines("mydatafile").collect { |l| l.chomp }
-
-name = "Gandalf"
-banner = %Q(Speak, #{name}, and welcome!)
-
-host_info = `host #{his_host}`
-
-%x(ps #{$$})
-
-banner = 'Costs only $4.95'.split(' ')
-
-rax = %w! ( ) < > { } [ ] !
-
-
-# @@PLEAC@@_4.2
-def commify_series(a)
- a.size == 0 ? '' :
- a.size == 1 ? a[0] :
- a.size == 2 ? a.join(' and ') :
- a[0..-2].join(', ') + ', and ' + a[-1]
-end
-
-array = [ "red", "yellow", "green" ]
-
-print "I have ", array, " marbles\n"
-# -> I have redyellowgreen marbles
-
-# But unlike Perl:
-print "I have #{array} marbles\n"
-# -> I have redyellowgreen marbles
-# So, needs:
-print "I have #{array.join(' ')} marbles\n"
-# -> I have red yellow green marbles
-
-def commify_series(a)
- sepchar = a.select { |p| p =~ /,/ } != [] ? '; ' : ', '
- a.size == 0 ? '' :
- a.size == 1 ? a[0] :
- a.size == 2 ? a.join(' and ') :
- a[0..-2].join(sepchar) + sepchar + 'and ' + a[-1]
-end
-
-
-# @@PLEAC@@_4.3
-# (note: AFAIK Ruby doesn't allow gory change of Array length)
-# grow the array by assigning nil to past the end of array
-ary[new_size-1] = nil
-# shrink the array by slicing it down
-ary.slice!(new_size..-1)
-# init the array with given size
-Array.new(number_of_elems)
-# assign to an element past the original end enlarges the array
-ary[index_new_last_elem] = value
-
-def what_about_that_array(a)
- print "The array now has ", a.size, " elements.\n"
- # Index of last element is not really interesting in Ruby
- print "Element #3 is `#{a[3]}'.\n"
-end
-people = %w(Crosby Stills Nash Young)
-what_about_that_array(people)
-
-
-# @@PLEAC@@_4.4
-# OO style
-bad_users.each { |user|
- complain(user)
-}
-# or, functional style
-for user in bad_users
- complain(user)
-end
-
-for var in ENV.keys.sort
- puts "#{var}=#{ENV[var]}"
-end
-
-for user in all_users
- disk_space = get_usage(user)
- if (disk_space > MAX_QUOTA)
- complain(user)
- end
-end
-
-for l in IO.popen("who").readlines
- print l if l =~ /^gc/
-end
-
-# we can mimic the obfuscated Perl way
-while fh.gets # $_ is set to the line just read
- chomp # $_ has a trailing \n removed, if it had one
- split.each { |w| # $_ is split on whitespace
- # but $_ is not set to each chunk as in Perl
- print w.reverse
- }
-end
-# ...or use a cleaner way
-for l in fh.readlines
- l.chomp.split.each { |w| print w.reverse }
-end
-
-# same drawback as in problem 1.4, we can't mutate a Numeric...
-array.collect! { |v| v - 1 }
-
-a = [ .5, 3 ]; b = [ 0, 1 ]
-for ary in [ a, b ]
- ary.collect! { |v| v * 7 }
-end
-puts "#{a.join(' ')} #{b.join(' ')}"
-
-# we can mutate Strings, cool; we need a trick for the scalar
-for ary in [ [ scalar ], array, hash.values ]
- ary.each { |v| v.strip! } # String#strip rules :)
-end
-
-
-# @@PLEAC@@_4.5
-# not relevant in Ruby since we have always references
-for item in array
- # do somethingh with item
-end
-
-
-# @@PLEAC@@_4.6
-unique = list.uniq
-
-# generate a list of users logged in, removing duplicates
-users = `who`.collect { |l| l =~ /(\w+)/; $1 }.sort.uniq
-puts("users logged in: #{commify_series(users)}") # see 4.2 for commify_series
-
-
-# @@PLEAC@@_4.7
-a - b
-# [ 1, 1, 2, 2, 3, 3, 3, 4, 5 ] - [ 1, 2, 4 ] -> [3, 5]
-
-
-# @@PLEAC@@_4.8
-union = a | b
-intersection = a & b
-difference = a - b
-
-
-# @@PLEAC@@_4.9
-array1.concat(array2)
-# if you will assign to another object, better use:
-new_ary = array1 + array2
-
-members = [ "Time", "Flies" ]
-initiates = [ "An", "Arrow" ]
-members += initiates
-
-members = [ "Time", "Flies" ]
-initiates = [ "An", "Arrow" ]
-members[2,0] = [ "Like", initiates ].flatten
-
-members[0] = "Fruit"
-members[3,2] = "A", "Banana"
-
-
-# @@PLEAC@@_4.10
-reversed = ary.reverse
-
-ary.reverse_each { |e|
- # do something with e
-}
-
-descending = ary.sort.reverse
-descending = ary.sort { |a,b| b <=> a }
-
-
-# @@PLEAC@@_4.11
-# remove n elements from front of ary (shift n)
-front = ary.slice!(0, n)
-
-# remove n elements from the end of ary (pop n)
-end_ = ary.slice!(-n .. -1)
-
-# let's extend the Array class, to make that useful
-class Array
- def shift2()
- slice!(0 .. 1) # more symetric with pop2...
- end
- def pop2()
- slice!(-2 .. -1)
- end
-end
-
-friends = %w(Peter Paul Mary Jim Tim)
-this, that = friends.shift2
-
-beverages = %w(Dew Jolt Cola Sprite Fresca)
-pair = beverages.pop2
-
-
-# @@PLEAC@@_4.12
-# use Enumerable#detect (or the synonym Enumerable#find)
-highest_eng = employees.detect { |emp| emp.category == 'engineer' }
-
-
-# @@PLEAC@@_4.13
-# use Enumerable#select (or the synonym Enumerable#find_all)
-bigs = nums.select { |i| i > 1_000_000 }
-pigs = users.keys.select { |k| users[k] > 1e7 }
-
-matching = `who`.select { |u| u =~ /^gnat / }
-
-engineers = employees.select { |e| e.position == 'Engineer' }
-
-secondary_assistance = applicants.select { |a|
- a.income >= 26_000 && a.income < 30_000
-}
-
-
-# @@PLEAC@@_4.14
-# normally you would have an array of Numeric (Float or
-# Fixnum or Bignum), so you would use:
-sorted = unsorted.sort
-# if you have strings representing Integers or Floats
-# you may specify another sort method:
-sorted = unsorted.sort { |a,b| a.to_f <=> b.to_f }
-
-# let's use the list of my own PID's
-`ps ux`.split("\n")[1..-1].
- select { |i| i =~ /^#{ENV['USER']}/ }.
- collect { |i| i.split[1] }.
- sort { |a,b| a.to_i <=> b.to_i }.each { |i| puts i }
-puts "Select a process ID to kill:"
-pid = gets.chomp
-raise "Exiting ... \n" unless pid && pid =~ /^\d+$/
-Process.kill('TERM', pid.to_i)
-sleep 2
-Process.kill('KILL', pid.to_i)
-
-descending = unsorted.sort { |a,b| b.to_f <=> a.to_f }
-
-
-# @@PLEAC@@_4.15
-ordered = unordered.sort { |a,b| compare(a,b) }
-
-precomputed = unordered.collect { |e| [compute, e] }
-ordered_precomputed = precomputed.sort { |a,b| a[0] <=> b[0] }
-ordered = ordered_precomputed.collect { |e| e[1] }
-
-ordered = unordered.collect { |e| [compute, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-for employee in employees.sort { |a,b| a.name <=> b.name }
- print employee.name, " earns \$ ", employee.salary, "\n"
-end
-
-# Beware! `0' is true in Ruby.
-# For chaining comparisons, you may use Numeric#nonzero?, which
-# returns num if num is not zero, nil otherwise
-sorted = employees.sort { |a,b| (a.name <=> b.name).nonzero? || b.age <=> a.age }
-
-users = []
-# getpwent is not wrapped in Ruby... let's fallback
-IO.readlines('/etc/passwd').each { |u| users << u.split(':') }
-users.sort! { |a,b| a[0] <=> b[0] }
-for user in users
- puts user[0]
-end
-
-sorted = names.sort { |a,b| a[1, 1] <=> b[1, 1] }
-sorted = strings.sort { |a,b| a.length <=> b.length }
-
-# let's show only the compact version
-ordered = strings.collect { |e| [e.length, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-ordered = strings.collect { |e| [/\d+/.match(e)[0].to_i, e] }.
- sort { |a,b| a[0] <=> b[0] }.
- collect { |e| e[1] }
-
-print `cat /etc/passwd`.collect { |e| [e, e.split(':').indexes(3,2,0)].flatten }.
- sort { |a,b| (a[1] <=> b[1]).nonzero? || (a[2] <=> b[2]).nonzero? || a[3] <=> b[3] }.
- collect { |e| e[0] }
-
-
-# @@PLEAC@@_4.16
-circular.unshift(circular.pop) # the last shall be first
-circular.push(circular.shift) # and vice versa
-
-def grab_and_rotate(l)
- l.push(ret = l.shift)
- ret
-end
-
-processes = [1, 2, 3, 4, 5]
-while (1)
- process = grab_and_rotate(processes)
- puts "Handling process #{process}"
- sleep 1
-end
-
-
-# @@PLEAC@@_4.17
-def fisher_yates_shuffle(a)
- (a.size-1).downto(1) { |i|
- j = rand(i+1)
- a[i], a[j] = a[j], a[i] if i != j
- }
-end
-
-def naive_shuffle(a)
- for i in 0...a.size
- j = rand(a.size)
- a[i], a[j] = a[j], a[i]
- end
-end
-
-
-# @@PLEAC@@_4.18
-#!/usr/bin/env ruby
-# example 4-2 words
-# words - gather lines, present in colums
-
-# class to encapsulate the word formatting from the input
-class WordFormatter
- def initialize(cols)
- @cols = cols
- end
-
- # helper to return the length of the longest word in the wordlist
- def maxlen(wordlist)
- max = 1
- for word in wordlist
- if word.length > max
- max = word.length
- end
- end
- max
- end
-
- # process the wordlist and print it formmated into columns
- def output(wordlist)
- collen = maxlen(wordlist) + 1
- columns = @cols / collen
- columns = 1 if columns == 0
- rows = (wordlist.length + columns - 1) / columns
- # now process each item, picking out proper piece for this position
- 0.upto(rows * columns - 1) { |item|
- target = (item % columns) * rows + (item / columns)
- eol = ((item+1) % columns == 0)
- piece = wordlist[target] || ""
- piece = piece.ljust(collen) unless eol
- print piece
- puts if eol
- }
- # no need to finish it up, because eol is always true for the last element
- end
-end
-
-# get nr of chars that fit in window or console, see PLEAC 15.4
-# not portable -- linux only (?)
-def getWinCharWidth()
- buf = "\0" * 8
- $stdout.ioctl(0x5413, buf)
- ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("$4")
- ws_col || 80
-rescue
- 80
-end
-
-# main program
-cols = getWinCharWidth()
-formatter = WordFormatter.new(cols)
-words = readlines()
-words.collect! { |line|
- line.chomp
-}
-formatter.output(words)
-
-
-# @@PLEAC@@_4.19
-# In ruby, Fixnum's are automatically converted to Bignum's when
-# needed, so there is no need for an extra module
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-puts factorial(500)
-
-#---------------------------------------------------------
-# Example 4-3. tsc-permute
-# tsc_permute: permute each word of input
-def permute(items, perms)
- unless items.length > 0
- puts perms.join(" ")
- else
- for i in items
- newitems = items.dup
- newperms = perms.dup
- newperms.unshift(newitems.delete(i))
- permute(newitems, newperms)
- end
- end
-end
-# In ruby the main program must be after all definitions it is using
-permute(ARGV, [])
-
-#---------------------------------------------------------
-# mjd_permute: permute each word of input
-
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-# we use a class with a class variable store the private cache
-# for the results of the factorial function.
-class Factorial
- @@fact = [ 1 ]
- def Factorial.compute(n)
- if @@fact[n]
- @@fact[n]
- else
- @@fact[n] = n * Factorial.compute(n - 1)
- end
- end
-end
-
-#---------------------------------------------------------
-# Example 4-4- mjd-permute
-# n2pat(n, len): produce the N-th pattern of length len
-
-# We must use a lower case letter as parameter N, otherwise it is
-# handled as constant Length is the length of the resulting
-# array, not the index of the last element (length -1) like in
-# the perl example.
-def n2pat(n, length)
- pat = []
- i = 1
- while i <= length
- pat.push(n % i)
- n /= i
- i += 1
- end
- pat
-end
-
-# pat2perm(pat): turn pattern returned by n2pat() into
-# permutation of integers.
-def pat2perm(pat)
- source = (0 .. pat.length - 1).to_a
- perm = []
- perm.push(source.slice!(pat.pop)) while pat.length > 0
- perm
-end
-
-def n2perm(n, len)
- pat2perm(n2pat(n,len))
-end
-
-# In ruby the main program must be after all definitions
-while gets
- data = split
- # the perl solution has used $#data, which is length-1
- num_permutations = Factorial.compute(data.length())
- 0.upto(num_permutations - 1) do |i|
- # in ruby we can not use an array as selector for an array
- # but by exchanging the two arrays, we can use the collect method
- # which returns an array with the result of all block invocations
- permutation = n2perm(i, data.length).collect {
- |j| data[j]
- }
- puts permutation.join(" ")
- end
-end
-
-
-# @@PLEAC@@_5.0
-age = { "Nat", 24,
- "Jules", 25,
- "Josh", 17 }
-
-age["Nat"] = 24
-age["Jules"] = 25
-age["Josh"] = 17
-
-food_color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange"
- }
-
-# In Ruby, you cannot avoid the double or simple quoting
-# while manipulatin hashes
-
-
-# @@PLEAC@@_5.1
-hash[key] = value
-
-food_color["Raspberry"] = "pink"
-puts "Known foods:", food_color.keys
-
-
-# @@PLEAC@@_5.2
-# does hash have a value for key ?
-if (hash.has_key?(key))
- # it exists
-else
- # it doesn't
-end
-
-[ "Banana", "Martini" ].each { |name|
- print name, " is a ", food_color.has_key?(name) ? "food" : "drink", "\n"
-}
-
-age = {}
-age['Toddler'] = 3
-age['Unborn'] = 0
-age['Phantasm'] = nil
-
-for thing in ['Toddler', 'Unborn', 'Phantasm', 'Relic']
- print "#{thing}: "
- print "Has-key " if age.has_key?(thing)
- print "True " if age[thing]
- print "Nonzero " if age[thing] && age[thing].nonzero?
- print "\n"
-end
-
-#=>
-# Toddler: Has-key True Nonzero
-# Unborn: Has-key True
-# Phantasm: Has-key
-# Relic:
-
-# You use Hash#has_key? when you use Perl's exists -> it checks
-# for existence of a key in a hash.
-# All Numeric are "True" in ruby, so the test doesn't have the
-# same semantics as in Perl; you would use Numeric#nonzero? to
-# achieve the same semantics (false if 0, true otherwise).
-
-
-# @@PLEAC@@_5.3
-food_color.delete("Banana")
-
-
-# @@PLEAC@@_5.4
-hash.each { |key, value|
- # do something with key and value
-}
-
-hash.each_key { |key|
- # do something with key
-}
-
-food_color.each { |food, color|
- puts "#{food} is #{color}"
-}
-
-food_color.each_key { |food|
- puts "#{food} is #{food_color[food]}"
-}
-
-# IMO this demonstrates that OO style is by far more readable
-food_color.keys.sort.each { |food|
- puts "#{food} is #{food_color[food]}."
-}
-
-#-----------------------------
-#!/usr/bin/ruby
-# countfrom - count number of messages from each sender
-
-# Default value is 0
-from = Hash.new(0)
-while gets
- /^From: (.*)/ and from[$1] += 1
-end
-
-# More useful to sort by number of received mail by person
-from.sort {|a,b| b[1]<=>a[1]}.each { |v|
- puts "#{v[1]}: #{v[0]}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_5.5
-# You may use the built-in 'inspect' method this way:
-p hash
-
-# Or do it the Cookbook way:
-hash.each { |k,v| puts "#{k} => #{v}" }
-
-# Sorted by keys
-hash.sort.each { |e| puts "#{e[0]} => #{e[1]}" }
-# Sorted by values
-hash.sort{|a,b| a[1]<=>b[1]}.each { |e| puts "#{e[0]} => #{e[1]}" }
-
-
-# @@PLEAC@@_5.7
-ttys = Hash.new
-for i in `who`
- user, tty = i.split
- (ttys[user] ||= []) << tty # see problems_ruby for more infos
-end
-ttys.keys.sort.each { |k|
- puts "#{k}: #{commify_series(ttys[k])}" # from 4.2
-}
-
-
-# @@PLEAC@@_5.8
-surname = { "Mickey" => "Mantle", "Babe" => "Ruth" }
-puts surname.index("Mantle")
-
-# If you really needed to 'invert' the whole hash, use Hash#invert
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# foodfind - find match for food or color
-
-given = ARGV.shift or raise "usage: foodfind food_or_color"
-
-color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange",
-}
-
-if (color.has_key?(given))
- puts "#{given} is a food with color #{color[given]}."
-end
-if (color.has_value?(given))
- puts "#{color.index(given)} is a food with color #{given}."
-end
-#-----------------------------
-
-
-# @@PLEAC@@_5.9
-# Sorted by keys (Hash#sort gives an Array of pairs made of each key,value)
-food_color.sort.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by values
-food_color.sort { |a,b| a[1] <=> b[1] }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by length of values
-food_color.sort { |a,b| a[1].length <=> b[1].length }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-
-# @@PLEAC@@_5.10
-merged = a.clone.update(b) # because Hash#update changes object in place
-
-drink_color = { "Galliano" => "yellow", "Mai Tai" => "blue" }
-ingested_color = drink_color.clone.update(food_color)
-
-substance_color = {}
-for i in [ food_color, drink_color ]
- i.each_key { |k|
- if substance_color.has_key?(k)
- puts "Warning: #{k} seen twice. Using the first definition."
- next
- end
- substance_color[k] = 1
- }
-end
-
-
-# @@PLEAC@@_5.11
-common = hash1.keys & hash2.keys
-
-this_not_that = hash1.keys - hash2.keys
-
-
-# @@PLEAC@@_5.12
-# no problem here, Ruby handles any kind of object for key-ing
-# (it takes Object#hash, which defaults to Object#id)
-
-
-# @@PLEAC@@_5.13
-# AFAIK, not possible in Ruby
-
-
-# @@PLEAC@@_5.14
-# Be careful, the following is possible only because Fixnum objects are
-# special (documentation says: there is effectively only one Fixnum object
-# instance for any given integer value).
-count = Hash.new(0)
-array.each { |e|
- count[e] += 1
-}
-
-
-# @@PLEAC@@_5.15
-father = {
- "Cain" , "Adam",
- "Abel" , "Adam",
- "Seth" , "Adam",
- "Enoch" , "Cain",
- "Irad" , "Enoch",
- "Mehujael" , "Irad",
- "Methusael" , "Mehujael",
- "Lamech" , "Methusael",
- "Jabal" , "Lamech",
- "Jubal" , "Lamech",
- "Tubalcain" , "Lamech",
- "Enos" , "Seth",
-}
-
-while gets
- chomp
- begin
- print $_, " "
- end while $_ = father[$_]
- puts
-end
-
-children = {}
-father.each { |k,v|
- (children[v] ||= []) << k
-}
-while gets
- chomp
- puts "#{$_} begat #{(children[$_] || ['Nobody']).join(', ')}.\n"
-end
-
-includes = {}
-files.each { |f|
- begin
- for l in IO.readlines(f)
- next unless l =~ /^\s*#\s*include\s*<([^>]+)>/
- (includes[$1] ||= []) << f
- end
- rescue SystemCallError
- $stderr.puts "#$! (skipping)"
- end
-}
-
-include_free = includes.values.flatten.uniq - includes.keys
-
-
-# @@PLEAC@@_5.16
-# dutree - print sorted intented rendition of du output
-#% dutree
-#% dutree /usr
-#% dutree -a
-#% dutree -a /bin
-
-# The DuNode class collects all information about a directory,
-# and provides some convenience methods
-class DuNode
-
- attr_reader :name
- attr_accessor :size
- attr_accessor :kids
-
- def initialize(name)
- @name = name
- @kids = []
- @size = 0
- end
-
- # support for sorting nodes with side
- def size_compare(node2)
- @size <=> node2.size
- end
-
- def basename
- @name.sub(/.*\//, "")
- end
-
- #returns substring before last "/", nil if not there
- def parent
- p = @name.sub(/\/[^\/]+$/,"")
- if p == @name
- nil
- else
- p
- end
- end
-
-end
-
-# The DuTree does the acdtual work of
-# getting the input, parsing it, builging up a tree
-# and format it for output
-class Dutree
-
- attr_reader :topdir
-
- def initialize
- @nodes = Hash.new
- @dirsizes = Hash.new(0)
- @kids = Hash.new([])
- end
-
- # get a node by name, create it if it does not exist yet
- def get_create_node(name)
- if @nodes.has_key?(name)
- @nodes[name]
- else
- node = DuNode.new(name)
- @nodes[name] = node
- node
- end
- end
-
- # run du, read in input, save sizes and kids
- # stores last directory read in instance variable topdir
- def input(arguments)
- name = ""
- cmd = "du " + arguments.join(" ")
- IO.popen(cmd) { |pipe|
- pipe.each { |line|
- size, name = line.chomp.split(/\s+/, 2)
- node = get_create_node(name)
- node.size = size.to_i
- @nodes[name] = node
- parent = node.parent
- if parent
- get_create_node(parent).kids.push(node)
- end
- }
- }
- @topdir = @nodes[name]
- end
-
- # figure out how much is taken in each directory
- # that isn't stored in the subdirectories. Add a new
- # fake kid called "." containing that much.
- def get_dots(node)
- cursize = node.size
- for kid in node.kids
- cursize -= kid.size
- get_dots(kid)
- end
- if node.size != cursize
- newnode = get_create_node(node.name + "/.")
- newnode.size = cursize
- node.kids.push(newnode)
- end
- end
-
- # recursively output everything
- # passing padding and number width as well
- # on recursive calls
- def output(node, prefix="", width=0)
- line = sprintf("%#{width}d %s", node.size, node.basename)
- puts(prefix + line)
- prefix += line.sub(/\d /, "| ")
- prefix.gsub!(/[^|]/, " ")
- if node.kids.length > 0 # not a bachelor node
- kids = node.kids
- kids.sort! { |a,b|
- b.size_compare(a)
- }
- width = kids[0].size.to_s.length
- for kid in kids
- output(kid, prefix, width)
- end
- end
- end
-
-end
-
-tree = Dutree.new
-tree.input(ARGV)
-tree.get_dots(tree.topdir)
-tree.output(tree.topdir)
-
-
-# @@PLEAC@@_6.0
-# The verbose version are match, sub, gsub, sub! and gsub!;
-# pattern needs to be a Regexp object; it yields a MatchData
-# object.
-pattern.match(string)
-string.sub(pattern, replacement)
-string.gsub(pattern, replacement)
-# As usual in Ruby, sub! does the same as sub but also modifies
-# the object, the same for gsub!/gsub.
-
-# Sugared syntax yields the position of the match (or nil if no
-# match). Note that the object at the right of the operator needs
-# not to be a Regexp object (it can be a String). The "dont
-# match" operator yields true or false.
-meadow =~ /sheep/ # position of the match, nil if no match
-meadow !~ /sheep/ # true if doesn't match, false if it does
-# There is no sugared version for the substitution
-
-meadow =~ /\bovines?\b/i and print "Here be sheep!"
-
-string = "good food"
-string.sub!(/o*/, 'e')
-
-# % echo ababacaca | ruby -ne 'puts $& if /(a|ba|b)+(a|ac)+/'
-# ababa
-
-# The "global" (or "multiple") match is handled by String#scan
-scan (/(\d+)/) {
- puts "Found number #{$1}"
-}
-
-# String#scan yields an Array if not used with a block
-numbers = scan(/\d+/)
-
-digits = "123456789"
-nonlap = digits.scan(/(\d\d\d)/)
-yeslap = digits.scan(/(?=(\d\d\d))/)
-puts "Non-overlapping: #{nonlap.join(' ')}"
-puts "Overlapping: #{yeslap.join(' ')}";
-# Non-overlapping: 123 456 789
-# Overlapping: 123 234 345 456 567 678 789
-
-string = "And little lambs eat ivy"
-string =~ /l[^s]*s/
-puts "(#$`) (#$&) (#$')"
-# (And ) (little lambs) ( eat ivy)
-
-
-# @@PLEAC@@_6.1
-# Ruby doesn't have the same problem:
-dst = src.sub('this', 'that')
-
-progname = $0.sub('^.*/', '')
-
-bindirs = %w(/usr/bin /bin /usr/local/bin)
-libdirs = bindirs.map { |l| l.sub('bin', 'lib') }
-
-
-# @@PLEAC@@_6.3
-/\S+/ # as many non-whitespace bytes as possible
-/[A-Za-z'-]+/ # as many letters, apostrophes, and hyphens
-
-/\b([A-Za-z]+)\b/ # usually best
-/\s([A-Za-z]+)\s/ # fails at ends or w/ punctuation
-
-
-# @@PLEAC@@_6.4
-require 'socket'
-str = 'www.ruby-lang.org and www.rubygarden.org'
-re = /
- ( # capture the hostname in $1
- (?: # these parens for grouping only
- (?! [-_] ) # lookahead for neither underscore nor dash
- [\w-] + # hostname component
- \. # and the domain dot
- ) + # now repeat that whole thing a bunch of times
- [A-Za-z] # next must be a letter
- [\w-] + # now trailing domain part
- ) # end of $1 capture
- /x # /x for nice formatting
-
-str.gsub! re do # pass a block to execute replacement
- host = TCPsocket.gethostbyname($1)
- "#{$1} [#{host[3]}]"
-end
-
-puts str
-#-----------------------------
-# to match whitespace or #-characters in an extended re you need to escape
-# them.
-
-foo = 42
-str = 'blah #foo# blah'
-str.gsub! %r/ # replace
- \# # a pound sign
- (\w+) # the variable name
- \# # another pound sign
- /x do
- eval $1 # with the value of a local variable
- end
-puts str # => blah 42 blah
-
-
-# @@PLEAC@@_6.5
-# The 'g' modifier doesn't exist in Ruby, a regexp can't be used
-# directly in a while loop; instead, use String#scan { |match| .. }
-fish = 'One fish two fish red fish blue fish'
-WANT = 3
-count = 0
-fish.scan(/(\w+)\s+fish\b/i) {
- if (count += 1) == WANT
- puts "The third fish is a #{$1} one."
- end
-}
-
-if fish =~ /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i
- puts "The third fish is a #{$1} one."
-end
-
-pond = 'One fish two fish red fish blue fish'
-# String#scan without a block gives an array of matches, each match
-# being an array of all the specified groups
-colors = pond.scan(/(\w+)\s+fish\b/i).flatten # get all matches
-color = colors[2] # then the one we want
-# or without a temporary array
-color = pond.scan(/(\w+)\s+fish\b/i).flatten[2] # just grab element 3
-puts "The third fish in the pond is #{color}."
-
-count = 0
-fishes = 'One fish two fish red fish blue fish'
-evens = fishes.scan(/(\w+)\s+fish\b/i).select { (count+=1) % 2 == 0 }
-print "Even numbered fish are #{evens.join(' ')}."
-
-count = 0
-fishes.gsub(/
- \b # makes next \w more efficient
- ( \w+ ) # this is what we\'ll be changing
- (
- \s+ fish \b
- )
- /x) {
- if (count += 1) == 4
- 'sushi' + $2
- else
- $1 + $2
- end
-}
-
-pond = 'One fish two fish red fish blue fish swim here.'
-puts "Last fish is #{pond.scan(/\b(\w+)\s+fish\b/i).flatten[-1]}"
-
-/
- A # find some pattern A
- (?! # mustn\'t be able to find
- .* # something
- A # and A
- )
- $ # through the end of the string
-/x
-
-# The "s" perl modifier is "m" in Ruby (not very nice since there is
-# also an "m" in perl..)
-pond = "One fish two fish red fish blue fish swim here."
-if (pond =~ /
- \b ( \w+) \s+ fish \b
- (?! .* \b fish \b )
- /mix)
- puts "Last fish is #{$1}."
-else
- puts "Failed!"
-end
-
-
-# @@PLEAC@@_6.6
-#-----------------------------
-#!/usr/bin/ruby -w
-# killtags - very bad html killer
-$/ = nil; # each read is whole file
-while file = gets() do
- file.gsub!(/<.*?>/m,''); # strip tags (terribly)
- puts file # print file to STDOUT
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-#headerfy - change certain chapter headers to html
-$/ = ''
-while file = gets() do
- pattern = /
- \A # start of record
- ( # capture in $1
- Chapter # text string
- \s+ # mandatory whitespace
- \d+ # decimal number
- \s* # optional whitespace
- : # a real colon
- . * # anything not a newline till end of line
- )
- /x
- puts file.gsub(pattern,'<H1>\1</H1>')
-end
-#-----------------------------
-#% ruby -00pe "gsub!(/\A(Chapter\s+\d+\s*:.*)/,'<H1>\1</H1>')" datafile
-
-#!/usr/bin/ruby -w
-#-----------------------------
-for file in ARGV
- file = File.open(ARGV.shift)
- while file.gets('') do # each read is a paragraph
- print "chunk #{$.} in $ARGV has <<#{$1}>>\n" while /^START(.*?)^END/m
- end # /m activates the multiline mode
-end
-#-----------------------------
-
-# @@PLEAC@@_6.7
-#-----------------------------
-$/ = nil;
-file = File.open("datafile")
-chunks = file.gets.split(/pattern/)
-#-----------------------------
-# .Ch, .Se and .Ss divide chunks of STDIN
-chunks = gets(nil).split(/^\.(Ch|Se|Ss)$/)
-print "I read #{chunks.size} chunks.\n"
-#-----------------------------
-
-
-# @@PLEAC@@_6.8
-while gets
- if ~/BEGIN/ .. ~/END/
- # line falls between BEGIN and END inclusive
- end
-end
-
-while gets
- if ($. == firstnum) .. ($. == lastnum)
- # operate between firstnum and lastnum line number
- end
-end
-
-# in ruby versions prior to 1.8, the above two conditional
-# expressions could be shortened to:
-# if /BEGIN/ .. /END/
-# and
-# if firstnum .. lastnum
-# but these now only work this way from the command line
-
-#-----------------------------
-
-while gets
- if ~/BEGIN/ ... ~/END/
- # line falls between BEGIN and END on different lines
- end
-end
-
-while gets
- if ($. == first) ... ($. == last)
- # operate between first and last line number on different lines
- end
-end
-
-#-----------------------------
-# command-line to print lines 15 through 17 inclusive (see below)
-ruby -ne 'print if 15 .. 17' datafile
-
-# print out all <XMP> .. </XMP> displays from HTML doc
-while gets
- print if ~%r#<XMP>#i .. ~%r#</XMP>#i;
-end
-
-# same, but as shell command
-# ruby -ne 'print if %r#<XMP>#i .. %r#</XMP>#i' document.html
-#-----------------------------
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $top .. $bottom' /etc/passwd # FAILS
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $. == $top .. $. == $bottom' /etc/passwd # works
-# ruby -ne 'print if 3 .. 5' /etc/passwd # also works
-#-----------------------------
-print if ~/begin/ .. ~/end/;
-print if ~/begin/ ... ~/end/;
-#-----------------------------
-while gets
- $in_header = $. == 1 .. ~/^$/ ? true : false
- $in_body = ~/^$/ .. ARGF.eof ? true : false
-end
-#-----------------------------
-seen = {}
-ARGF.each do |line|
- next unless line =~ /^From:?\s/i .. line =~ /^$/;
- line.scan(%r/([^<>(),;\s]+\@[^<>(),;\s]+)/).each do |addr|
- puts addr unless seen[addr]
- seen[addr] ||= 1
- end
-end
-
-
-# @@PLEAC@@_6.9
-def glob2pat(globstr)
- patmap = {
- '*' => '.*',
- '?' => '.',
- '[' => '[',
- ']' => ']',
- }
- globstr.gsub!(/(.)/) { |c| patmap[c] || Regexp::escape(c) }
- '^' + globstr + '$'
-end
-
-
-# @@PLEAC@@_6.10
-# avoid interpolating patterns like this if the pattern
-# isn't going to change:
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/
-end
-
-# the above creates a new regex each iteration. Instead,
-# use the /o modifier so the regex is compiled only once
-
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/o
-end
-
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep1 - grep for abbreviations of places that say "pop"
-# version 1: slow but obvious way
-popstates = %w(CO ON MI WI MN)
-ARGF.each do |line|
- popstates.each do |state|
- if line =~ /\b#{state}\b/
- print line
- last
- end
- end
-end
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep2 - grep for abbreviations of places that say "pop"
-# version 2: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n"
-popstates.each do |state|
- code += "\tif line =~ /\\b#{state}\\b/; print(line); next; end\n"
-end
-code += "end\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# if line =~ /\bCO\b/; print(line); next; end
-# if line =~ /\bON\b/; print(line); next; end
-# if line =~ /\bMI\b/; print(line); next; end
-# if line =~ /\bWI\b/; print(line); next; end
-# if line =~ /\bMN\b/; print(line); next; end
-# end
-#
-# ---
-
-## alternatively, the same idea as above but compiling
-## to a case statement: (not in perlcookbook)
-#!/usr/bin/ruby -w
-# popgrep2.5 - grep for abbreviations of places that say "pop"
-# version 2.5: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n case line\n"
-popstates.each do |state|
- code += " when /\\b#{state}\\b/ : print line\n"
-end
-code += " end\nend\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# case line
-# when /\bCO\b/ : print line
-# when /\bON\b/ : print line
-# when /\bMI\b/ : print line
-# when /\bWI\b/ : print line
-# when /\bMN\b/ : print line
-# end
-# end
-#
-# ---
-
-# Note: (above) Ruby 1.8+ allows the 'when EXP : EXPR' on one line
-# with the colon separator.
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep3 - grep for abbreviations of places that say "pop"
-# version3: build a match_any function
-popstates = %w(CO ON MI WI MN)
-expr = popstates.map{|e|"line =~ /\\b#{e}\\b/"}.join('||')
-eval "def match_any(line); #{expr};end"
-ARGF.each do |line|
- print line if match_any(line)
-end
-#-----------------------------
-
-## building a match_all function is a trivial
-## substitution of && for ||
-## here is a generalized example:
-#!/usr/bin/ruby -w
-## grepauth - print lines that mention both foo and bar
-class MultiMatch
- def initialize(*patterns)
- _any = build_match('||',patterns)
- _all = build_match('&&',patterns)
- eval "def match_any(line);#{_any};end\n"
- eval "def match_all(line);#{_all};end\n"
- end
- def build_match(sym,args)
- args.map{|e|"line =~ /#{e}/"}.join(sym)
- end
-end
-
-mm = MultiMatch.new('foo','bar')
-ARGF.each do |line|
- print line if mm.match_all(line)
-end
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep4 - grep for abbreviations of places that say "pop"
-# version4: pretty fast, but simple: compile all re's first:
-popstates = %w(CO ON MI WI MN)
-popstates = popstates.map{|re| %r/\b#{re}\b/}
-ARGF.each do |line|
- popstates.each do |state_re|
- if line =~ state_re
- print line
- break
- end
- end
-end
-
-## speeds trials on the jargon file(412): 26006 lines, 1.3MB
-## popgrep1 => 7.040s
-## popgrep2 => 0.656s
-## popgrep2.5 => 0.633s
-## popgrep3 => 0.675s
-## popgrep4 => 1.027s
-
-# unless speed is criticial, the technique in popgrep4 is a
-# reasonable balance between speed and logical simplicity.
-
-
-# @@PLEAC@@_6.11
-begin
- print "Pattern? "
- pat = $stdin.gets.chomp
- Regexp.new(pat)
-rescue
- warn "Invalid Pattern"
- retry
-end
-
-
-# @@PLEAC@@_6.13
-# uses the 'amatch' extension found on:
-# http://raa.ruby-lang.org/project/amatch/
-require 'amatch'
-matcher = Amatch.new('balast')
-#$relative, $distance = 0, 1
-File.open('/usr/share/dict/words').each_line do |line|
- print line if matcher.search(line) <= 1
-end
-__END__
-#CODE
-ballast
-ballasts
-balustrade
-balustrades
-blast
-blasted
-blaster
-blasters
-blasting
-blasts
-
-
-# @@PLEAC@@_6.14
-str.scan(/\G(\d)/).each do |token|
- puts "found #{token}"
-end
-#-----------------------------
-n = " 49 here"
-n.gsub!(/\G /,'0')
-puts n
-#-----------------------------
-str = "3,4,5,9,120"
-str.scan(/\G,?(\d+)/).each do |num|
- puts "Found number: #{num}"
-end
-#-----------------------------
-# Ruby doesn't have the String.pos or a /c re modifier like Perl
-# But it does have StringScanner in the standard library (strscn)
-# which allows similar functionality:
-
-require 'strscan'
-text = 'the year 1752 lost 10 days on the 3rd of September'
-sc = StringScanner.new(text)
-while sc.scan(/.*?(\d+)/)
- print "found: #{sc[1]}\n"
-end
-if sc.scan(/\S+/)
- puts "Found #{sc[0]} after last number"
-end
-#-----------------------------
-# assuming continuing from above:
-puts "The position in 'text' is: #{sc.pos}"
-sc.pos = 30
-puts "The position in 'text' is: #{sc.pos}"
-
-
-# @@PLEAC@@_6.15
-#-----------------------------
-# greedy pattern
-str.gsub!(/<.*>/m,'') # not good
-
-# non-greedy (minimal) pattern
-str.gsub!(/<.*?>/m,'') # not great
-
-
-#-----------------------------
-#<b><i>this</i> and <i>that</i> are important</b> Oh, <b><i>me too!</i></b>
-#-----------------------------
-%r{ <b><i>(.*?)</i></b> }mx
-#-----------------------------
-%r/BEGIN((?:(?!BEGIN).)*)END/
-#-----------------------------
-%r{ <b><i>( (?: (?!</b>|</i>). )* ) </i></b> }mx
-#-----------------------------
-%r{ <b><i>( (?: (?!</[ib]>). )* ) </i></b> }mx
-#-----------------------------
-%r{
- <b><i>
- [^<]* # stuff not possibly bad, and not possibly the end.
- (?:
- # at this point, we can have '<' if not part of something bad
- (?! </?[ib]> ) # what we can't have
- < # okay, so match the '<'
- [^<]* # and continue with more safe stuff
- ) *
- </i></b>
- }mx
-
-
-# @@PLEAC@@_6.16
-#-----------------------------
-$/ = ""
-ARGF.each do |para|
- para.scan %r/
- \b # start at word boundary
- (\S+) # find chunk of non-whitespace
- \b # until a word boundary
- (
- \s+ # followed by whitespace
- \1 # and that same chunk again
- \b # and a word boundary
- ) + # one or more times
- /xi do
- puts "dup word '#{$1}' at paragraph #{$.}"
- end
-end
-#-----------------------------
-astr = 'nobody'
-bstr = 'bodysnatcher'
-if "#{astr} #{bstr}" =~ /^(\w+)(\w+) \2(\w+)$/
- print "#{$2} overlaps in #{$1}-#{$2}-#{$3}"
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# prime_pattern -- find prime factors of argument using patterns
-ARGV << 180
-cap = 'o' * ARGV.shift
-while cap =~ /^(oo+?)\1+$/
- print $1.size, " "
- cap.gsub!(/#{$1}/,'o')
-end
-puts cap.size
-#-----------------------------
-#diophantine
-# solve for 12x + 15y + 16z = 281, maximizing x
-if ('o' * 281).match(/^(o*)\1{11}(o*)\2{14}(o*)\3{15}$/)
- x, y, z = $1.size, $2.size, $3.size
- puts "One solution is: x=#{x}; y=#{y}; z=#{z}"
-else
- puts "No solution."
-end
-# => One solution is: x=17; y=3; z=2
-
-#-----------------------------
-# using different quantifiers:
-('o' * 281).match(/^(o+)\1{11}(o+)\2{14}(o+)\3{15}$/)
-# => One solution is: x=17; y=3; z=2
-
-('o' * 281).match(/^(o*?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=0; y=7; z=11
-
-('o' * 281).match(/^(o+?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=1; y=3; z=14
-
-
-# @@PLEAC@@_6.17
-# alpha OR beta
-%r/alpha|beta/
-
-# alpha AND beta
-%r/(?=.*alpha)(?=.*beta)/m
-
-# alpha AND beta, no overlap
-%r/alpha.*beta|beta.*alpha/m
-
-# NOT beta
-%r/^(?:(?!beta).)*$/m
-
-# NOT bad BUT good
-%r/(?=(?:(?!BAD).)*$)GOOD/m
-#-----------------------------
-
-if !(string =~ /pattern/) # ugly
- something()
-end
-
-if string !~ /pattern/ # preferred
- something()
-end
-
-
-#-----------------------------
-if string =~ /pat1/ && string =~ /pat2/
- something()
-end
-#-----------------------------
-if string =~ /pat1/ || string =~ /pat2/
- something()
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# minigrep - trivial grep
-pat = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pat}/o
-end
-#-----------------------------
- "labelled" =~ /^(?=.*bell)(?=.*lab)/m
-#-----------------------------
-$string =~ /bell/ && $string =~ /lab/
-#-----------------------------
-$murray_hill = "blah bell blah "
-if $murray_hill =~ %r{
- ^ # start of string
- (?= # zero-width lookahead
- .* # any amount of intervening stuff
- bell # the desired bell string
- ) # rewind, since we were only looking
- (?= # and do the same thing
- .* # any amount of intervening stuff
- lab # and the lab part
- )
- }mx # /m means . can match newline
-
- print "Looks like Bell Labs might be in Murray Hill!\n";
-end
-#-----------------------------
-"labelled" =~ /(?:^.*bell.*lab)|(?:^.*lab.*bell)/
-#-----------------------------
-$brand = "labelled";
-if $brand =~ %r{
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- bell # look for a bell
- .*? # followed by any amount of anything
- lab # look for a lab
- ) # end grouper
- | # otherwise, try the other direction
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- lab # look for a lab
- .*? # followed by any amount of anything
- bell # followed by a bell
- ) # end grouper
- }mx # /m means . can match newline
- print "Our brand has bell and lab separate.\n";
-end
-#-----------------------------
-$map =~ /^(?:(?!waldo).)*$/s
-#-----------------------------
-$map = "the great baldo"
-if $map =~ %r{
- ^ # start of string
- (?: # non-capturing grouper
- (?! # look ahead negation
- waldo # is he ahead of us now?
- ) # is so, the negation failed
- . # any character (cuzza /s)
- ) * # repeat that grouping 0 or more
- $ # through the end of the string
- }mx # /m means . can match newline
- print "There's no waldo here!\n";
-end
-=begin
- 7:15am up 206 days, 13:30, 4 users, load average: 1.04, 1.07, 1.04
-
-USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
-
-tchrist tty1 5:16pm 36days 24:43 0.03s xinit
-
-tchrist tty2 5:19pm 6days 0.43s 0.43s -tcsh
-
-tchrist ttyp0 chthon 7:58am 3days 23.44s 0.44s -tcsh
-
-gnat ttyS4 coprolith 2:01pm 13:36m 0.30s 0.30s -tcsh
-=end
-#% w | minigrep '^(?!.*ttyp).*tchrist'
-#-----------------------------
-%r{
- ^ # anchored to the start
- (?! # zero-width look-ahead assertion
- .* # any amount of anything (faster than .*?)
- ttyp # the string you don't want to find
- ) # end look-ahead negation; rewind to start
- .* # any amount of anything (faster than .*?)
- tchrist # now try to find Tom
-}x
-#-----------------------------
-#% w | grep tchrist | grep -v ttyp
-#-----------------------------
-#% grep -i 'pattern' files
-#% minigrep '(?i)pattern' files
-#-----------------------------
-
-
-# @@PLEAC@@_6.20
-ans = $stdin.gets.chomp
-re = %r/^#{Regexp.quote(ans)}/
-case
- when "SEND" =~ re : puts "Action is send"
- when "STOP" =~ re : puts "Action is stop"
- when "ABORT" =~ re : puts "Action is abort"
- when "EDIT" =~ re : puts "Action is edit"
-end
-#-----------------------------
-require 'abbrev'
-table = Abbrev.abbrev %w-send stop abort edit-
-loop do
- print "Action: "
- ans = $stdin.gets.chomp
- puts "Action for #{ans} is #{table[ans.downcase]}"
-end
-
-
-#-----------------------------
-# dummy values are defined for 'file', 'PAGER', and
-# the 'invoke_editor' and 'deliver_message' methods
-# do not do anything interesting in this example.
-#!/usr/bin/ruby -w
-require 'abbrev'
-
-file = 'pleac_ruby.data'
-PAGER = 'less'
-
-def invoke_editor
- puts "invoking editor"
-end
-
-def deliver_message
- puts "delivering message"
-end
-
-actions = {
- 'edit' => self.method(:invoke_editor),
- 'send' => self.method(:deliver_message),
- 'list' => proc {system(PAGER, file)},
- 'abort' => proc {puts "See ya!"; exit},
- "" => proc {puts "Unknown Command"}
-}
-
-dtable = Abbrev.abbrev(actions.keys)
-loop do
- print "Action: "
- ans = $stdin.gets.chomp.delete(" \t")
- actions[ dtable[ans.downcase] || "" ].call
-end
-
-
-# @@PLEAC@@_6.19
-#-----------------------------
-# basically, the Perl Cookbook categorizes this as an
-# unsolvable problem ...
-#-----------------------------
-1 while addr.gsub!(/\([^()]*\)/,'')
-#-----------------------------
-Dear someuser@host.com,
-
-Please confirm the mail address you gave us Wed May 6 09:38:41
-MDT 1998 by replying to this message. Include the string
-"Rumpelstiltskin" in that reply, but spelled in reverse; that is,
-start with "Nik...". Once this is done, your confirmed address will
-be entered into our records.
-
-
-# @@PLEAC@@_6.21
-#-----------------------------
-#% gunzip -c ~/mail/archive.gz | urlify > archive.urlified
-#-----------------------------
-#% urlify ~/mail/*.inbox > ~/allmail.urlified
-#-----------------------------
-#!/usr/bin/ruby -w
-# urlify - wrap HTML links around URL-like constructs
-
-urls = '(https?|telnet|gopher|file|wais|ftp)';
-ltrs = '\w';
-gunk = '/#~:.?+=&%@!\-';
-punc = '.:?\-';
-any = "#{ltrs}#{gunk}#{punc}";
-
-ARGF.each do |line|
- line.gsub! %r/
- \b # start at word boundary
- ( # begin $1 {
- #{urls} : # need resource and a colon
- [#{any}] +? # followed by on or more
- # of any valid character, but
- # be conservative and take only
- # what you need to....
- ) # end $1 }
- (?= # look-ahead non-consumptive assertion
- [#{punc}]* # either 0 or more punctuation
- [^#{any}] # followed by a non-url char
- | # or else
- $ # then end of the string
- )
- /iox do
- %Q|<A HREF="#{$1}">#{$1}</A>|
- end
- print line
-end
-
-
-# @@PLEAC@@_6.23
-%r/^m*(d?c{0,3}|c[dm])(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$/i
-#-----------------------------
-str.sub!(/(\S+)(\s+)(\S+)/, '\3\2\1')
-#-----------------------------
-%r/(\w+)\s*=\s*(.*)\s*$/ # keyword is $1, value is $2
-#-----------------------------
-%r/.{80,}/
-#-----------------------------
-%r|(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)|
-#-----------------------------
-str.gsub!(%r|/usr/bin|,'/usr/local/bin')
-#-----------------------------
-str.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/){ $1.hex.chr }
-#-----------------------------
-str.gsub!(%r{
- /\* # Match the opening delimiter
- .*? # Match a minimal number of characters
- \*/ # Match the closing delimiter
-}xm,'')
-#-----------------------------
-str.sub!(/^\s+/, '')
-str.sub!(/\s+$/, '')
-
-# but really, in Ruby we'd just do:
-str.strip!
-#-----------------------------
-str.gsub!(/\\n/,"\n")
-#-----------------------------
-str.sub!(/^.*::/, '')
-#-----------------------------
-%r/^([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])\.
- ([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])$/x
-#-----------------------------
-str.sub!(%r|^.*/|, '')
-#-----------------------------
-cols = ( (ENV['TERMCAP'] || " ") =~ /:co#(\d+):/ ) ? $1 : 80;
-#-----------------------------
-name = " #{$0} #{ARGV}".gsub(%r| /\S+/|, ' ')
-#-----------------------------
-require 'rbconfig'
-include Config
-raise "This isn't Linux" unless CONFIG['target_os'] =~ /linux/i;
-#-----------------------------
-str.gsub!(%r/\n\s+/, ' ')
-#-----------------------------
-nums = str.scan(/(\d+\.?\d*|\.\d+)/)
-#-----------------------------
-capwords = str.scan(%r/(\b[^\Wa-z0-9_]+\b)/)
-#-----------------------------
-lowords = str.scan(%r/(\b[^\WA-Z0-9_]+\b)/)
-#-----------------------------
-icwords = str.scan(%r/(\b[^\Wa-z0-9_][^\WA-Z0-9_]*\b)/)
-#-----------------------------
-links = str.scan(%r/<A[^>]+?HREF\s*=\s*["']?([^'" >]+?)[ '"]?>/mi)
-#-----------------------------
-initial = str =~ /^\S+\s+(\S)\S*\s+\S/ ? $1 : ""
-#-----------------------------
-str.gsub!(%r/"([^"]*)"/, %q-``\1''-)
-#-----------------------------
-
-$/ = ""
-sentences = []
-ARGF.each do |para|
- para.gsub!(/\n/, ' ')
- para.gsub!(/ {3,}/,' ')
- sentences << para.scan(/(\S.*?[!?.])(?= |\Z)/)
-end
-
-#-----------------------------
-%r/(\d{4})-(\d\d)-(\d\d)/ # YYYY in $1, MM in $2, DD in $3
-#-----------------------------
-%r/ ^
- (?:
- 1 \s (?: \d\d\d \s)? # 1, or 1 and area code
- | # ... or ...
- \(\d\d\d\) \s # area code with parens
- | # ... or ...
- (?: \+\d\d?\d? \s)? # optional +country code
- \d\d\d ([\s\-]) # and area code
- )
- \d\d\d (\s|\1) # prefix (and area code separator)
- \d\d\d\d # exchange
- $
- /x
-#-----------------------------
-%r/\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b/i
-#-----------------------------
-lines = []
-lines << $1 while input.sub!(/^([^\012\015]*)(\012\015?|\015\012?)/,'')
-
-
-# @@PLEAC@@_7.0
-# An IO object being Enumerable, we can use 'each' directly on it
-File.open("/usr/local/widgets/data").each { |line|
- puts line if line =~ /blue/
-}
-
-logfile = File.new("/var/log/rubylog.txt", "w")
-mysub($stdin, logfile)
-
-# The method IO#readline is similar to IO#gets
-# but throws an exception when it reaches EOF
-f = File.new("bla.txt")
-begin
- while (line = f.readline)
- line.chomp
- $stdout.print line if line =~ /blue/
- end
-rescue EOFError
- f.close
-end
-
-while $stdin.gets # reads from STDIN
- unless (/\d/)
- $stderr.puts "No digit found." # writes to STDERR
- end
- puts "Read: #{$_}" # writes to STDOUT
-end
-
-logfile = File.new("/tmp/log", "w")
-
-logfile.close
-
-# $defout (or its synonym '$>') is the destination of output
-# for Kernel#print, Kernel#puts, and family functions
-logfile = File.new("log.txt", "w")
-old = $defout
-$defout = logfile # switch to logfile for output
-puts "Countdown initiated ..."
-$defout = old # return to original output
-puts "You have 30 seconds to reach minimum safety distance."
-
-
-# @@PLEAC@@_7.1
-source = File.new(path, "r") # open file "path" for reading only
-sink = File.new(path, "w") # open file "path" for writing only
-
-source = File.open(path, File::RDONLY) # open file "path" for reading only
-sink = File.open(path, File::WRONLY) # open file "path" for writing only
-
-file = File.open(path, "r+") # open "path" for reading and writing
-file = File.open(path, flags) # open "path" with the flags "flags" (see examples below for flags)
-
-# open file "path" read only
-file = File.open(path, "r")
-file = File.open(path, File::RDONLY)
-
-# open file "path" write only, create it if it does not exist
-# truncate it to zero length if it exists
-file = File.open(path, "w")
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT, 0666) # with permission 0666
-
-# open file "path" write only, fails if file exists
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT)
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT, 0666)
-
-# open file "path" for appending
-file = File.open(path, "a")
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT)
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT, 0666)
-
-# open file "path" for appending only when file exists
-file = File.open(path, File::WRONLY|File::APPEND)
-
-# open file "path" for reading and writing
-file = File.open(path, "r+")
-file = File.open(path, File::RDWR)
-
-# open file for reading and writing, create a new file if it does not exist
-file = File.open(path, File::RDWR|File::CREAT)
-file = File.open(path, File::RDWR|File::CREAT, 0600)
-
-# open file "path" reading and writing, fails if file exists
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT)
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT, 0600)
-
-
-# @@PLEAC@@_7.2
-# No problem with Ruby since the filename doesn't contain characters with
-# special meaning; like Perl's sysopen
-File.open(filename, 'r')
-
-
-# @@PLEAC@@_7.3
-File.expand_path('~root/tmp')
-#=> "/root/tmp"
-File.expand_path('~rpcuser')
-#=> "/var/lib/nfs"
-
-# To expand ~/.. it explicitely needs the environment variable HOME
-File.expand_path('~/tmp')
-#=> "/home/gc/tmp"
-
-
-# @@PLEAC@@_7.4
-# The exception raised in Ruby reports the filename
-File.open('afile')
-
-
-# @@PLEAC@@_7.5
-# Standard Ruby distribution provides the following useful extension
-require 'tempfile'
-# With the Tempfile class, the file is automatically deleted on garbage
-# collection, so you won't need to remove it, later on.
-tf = Tempfile.new('tmp') # a name is required to create the filename
-
-# If you need to pass the filename to an external program you can use
-# File#path, but don't forget to File#flush in order to flush anything
-# living in some buffer somewhere.
-tf.flush
-system("/usr/bin/dowhatever #{tf.path}")
-
-fh = Tempfile.new('tmp')
-fh.sync = true # autoflushes
-10.times { |i| fh.puts i }
-fh.rewind
-puts 'Tmp file has: ', fh.readlines
-
-
-# @@PLEAC@@_7.6
-while (DATA.gets) do
- # process the line
-end
-__END__
-# your data goes here
-# __DATA__ doesn't exist in Ruby
-
-#CODE
-# get info about the script (size, date of last modification)
-kilosize = DATA.stat.size / 1024
-last_modif = DATA.stat.mtime
-puts "<P>Script size is #{kilosize}"
-puts "<P>Last script update: #{last_modif}"
-__END__
-# DO NOT REMOVE THE PRECEEDING LINE.
-# Everything else in this file will be ignored.
-#CODE
-
-
-# @@PLEAC@@_7.7
-while line = gets do
- # do something with line.
-end
-
-# or
-while gets do
- # do something with $_
-end
-
-# or more rubyish
-$stdun.each do |line|
- # do stuff with line
-end
-
-
-# ARGF may makes this more easy
-# this is skipped if ARGV.size==0
-ARGV.each do |filename|
- # closing and exception handling are done by the block
- open(filename) do |fd|
- fd.each do |line|
- # do stuff with line
- end
- end rescue abort("can't open %s" % filename)
-end
-
-# globbing is done in the Dir module
-ARGV = Dir["*.[Cch]"] if ARGV.empty?
-
-# note: optparse is the preferred way to handle this
-if (ARGV[0] == '-c')
- chop_first += 1
- ARGV.shift
-end
-
-
-# processing numerical options
-if ARGV[0] =~ /^-(\d+)$/
- columns = $1
- ARGV.shift
-end
-
-# again, better to use optparse:
-require 'optparse'
-nostdout = 0
-append = 0
-unbuffer = 0
-ignore_ints = 0
-ARGV.options do |opt|
- opt.on('-n') { nostdout +=1 }
- opt.on('-a') { append +=1 }
- opt.on('-u') { unbuffer +=1 }
- opt.on('-i') { ignore_ints +=1 }
- opt.parse!
-end or abort("usage: " + __FILE__ + " [-ainu] [filenames]")
-
-# no need to do undef $/, we have File.read
-str = File.read(ARGV[0])
-
-# again we have File.read
-str = File.read(ARGV[0])
-
-# not sure what this should do:
-# I believe open the file, print filename, lineno and line:
-ARGF.each_with_index do |line, idx|
- print ARGF.filename, ":", idx, ";", line
-end
-
-# print all the lines in every file passed via command line that contains login
-ARGF.each do |line|
- puts line if line =~ /login/
-end
-#
-# even this would fit
-#%ruby -ne "print if /f/" 2.log
-#
-
-ARGF.each { |l| puts l.downcase! }
-
-#------------------
-#!/usr/bin/ruby -p
-# just like perl's -p
-$_.downcase!
-#
-
-# I don't know who should I trust.
-# perl's version splits on \w+ while python's on \w.
-
-chunks = 0
-
-File.read(ARGV[0]).split.each do |word|
- next if word =~ /^#/
- break if ["__DATA__", "__END__"].member? word
- chunks += 1
-end
-
-print "Found ", chunks, " chunks\n"
-
-
-# @@PLEAC@@_7.8
-old = File.open(old_file)
-new = File.open(new_file, "w")
-while old.gets do
- # change $_, then...
- new.print $_
-end
-old.close
-new.close
-File.rename(old_file, "old.orig")
-File.rename(new_file, old_file)
-
-while old.gets do
- if $. == 20 then # we are at the 20th line
- new.puts "Extra line 1"
- new.puts "Extra line 2"
- end
- new.print $_
-end
-
-while old.gets do
- next if 20..30 # skip the 20th line to the 30th
- # Ruby (and Perl) permit to write if 20..30
- # instead of if (20 <= $.) and ($. <= 30)
- new.print $_
-end
-
-
-# @@PLEAC@@_7.9
-#% ruby -i.orig -pe 'FILTER COMMAND' file1 file2 file3 ...
-#
-#-----------------------------
-##!/usr/bin/ruby -i.orig -p
-# filter commands go here
-#-----------------------------
-
-#% ruby -pi.orig -e 'gsub!(/DATE/){Time.now)'
-
-# effectively becomes:
-ARGV << 'I'
-oldfile = ""
-while gets
- if ARGF.filename != oldfile
- newfile = ARGF.filename
- File.rename(newfile, newfile + ".orig")
- $stdout = File.open(newfile,'w')
- oldfile = newfile
- end
- gsub!(/DATE/){Time.now}
- print
-end
-$stdout = STDOUT
-#-----------------------------
-#% ruby -i.old -pe 'gsub!(%r{\bhisvar\b}, 'hervar')' *.[Cchy]
-
-#-----------------------------
-# set up to iterate over the *.c files in the current directory,
-# editing in place and saving the old file with a .orig extension
-$-i = '.orig' # set up -i mode
-ARGV.replace(Dir['*.[Cchy]'])
-while gets
- if $. == 1
- print "This line should appear at the top of each file\n"
- end
- gsub!(/\b(p)earl\b/i, '\1erl') # Correct typos, preserving case
- print
- ARGF.close if ARGF.eof
-end
-
-
-# @@PLEAC@@_7.10
-File.open('itest', 'r+') do |f| # open file for update
- lines = f.readlines # read into array of lines
- lines.each do |it| # modify lines
- it.gsub!(/foo/, 'QQQ')
- end
- f.pos = 0 # back to start
- f.print lines # write out modified lines
- f.truncate(f.pos) # truncate to new length
-end # file is automatically closed
-#-----------------------------
-File.open('itest', 'r+') do |f|
- out = ""
- f.each do |line|
- out << line.gsub(/DATE/) {Time.now}
- end
- f.pos = 0
- f.print out
- f.truncate(f.pos)
-end
-
-# @@PLEAC@@_7.11
-File.open('infile', 'r+') do |f|
- f.flock File::LOCK_EX
- # update file
-end
-#-----------------------------
-File::LOCK_SH # shared lock (for reading)
-File::LOCK_EX # exclusive lock (for writing)
-File::LOCK_NB # non-blocking request
-File::LOCK_UN # free lock
-#-----------------------------
-unless f.flock File::LOCK_EX | File::LOCK_NB
- warn "can't get immediate lock: blocking ..."
- f.flock File::LOCK_EX
-end
-#-----------------------------
-File.open('numfile', File::RDWR|File::CREAT) do |f|
- f.flock(File::LOCK_EX)
- num = f.gets.to_i || 0
- f.pos = 0
- f.truncate 0
- f.puts num + 1q
-end
-
-
-# @@PLEAC@@_7.12
-output_handle.sync = true
-# Please note that like in Perl, $stderr is already unbuffered
-#-----------------------------
-#!/usr/bin/ruby -w
-# seeme - demo stdio output buffering
-$stdout.sync = ARGV.size > 0
-print "Now you don't see it..."
-sleep 2
-puts "now you do"
-#-----------------------------
-$stderr.sync = true
-afile.sync = false
-#-----------------------------
-# assume 'remote_con' is an interactive socket handle,
-# but 'disk_file' is a handle to a regular file.
-remote_con.sync = true # unbuffer for clarity
-disk_file.sync = false # buffered for speed
-#-----------------------------
-require 'socket'
-sock = TCPSocket.new('www.ruby-lang.org', 80)
-sock.sync = true
-sock.puts "GET /en/ HTTP/1.0 \n\n"
-resp = sock.read
-print "DOC IS: #{resp}\n"
-
-
-# @@PLEAC@@_7.13
-#-----------------------------
-# assumes fh1, fh2, fh2 are oen IO objects
-nfound = select([$stdin, fh1, fh2, fh3], nil, nil, 0)
-nfound[0].each do |file|
- case file
- when fh1
- # do something with fh1
- when fh2
- # do something with fh2
- when fh3
- # do something with fh3
- end
-end
-#-----------------------------
-input_files = []
-# repeat next line for all in-files to poll
-input_files << fh1
-if nfound = select(input_files, nil, nil, 0)
- # input ready on files in nfound[0]
-end
-
-
-# @@PLEAC@@_8.0
-#-----------------------------
-# datafile is a file or IO object
-datafile.readlines.each { |line|
- line.chomp!
- size = line.length
- puts size
-}
-#-----------------------------
-datafile.readlines.each { |line|
- puts line.chomp!.length
-}
-#-----------------------------
-lines = datafile.readlines
-#-----------------------------
-whole_file = file.read
-#-----------------------------
-# ruby -040 -e 'word = gets; puts "First word is #{word}"'
-#-----------------------------
-# ruby -ne 'BEGIN { $/="%%\n" }; $_.chomp; puts $_ if( $_=~/Unix/i)' fortune.dat
-#-----------------------------
-handle.print "one", "two", "three" # "onetwothree"
-puts "Baa baa black sheep." # sent to $stdout
-#-----------------------------
-buffer = handle.read(4096)
-rv = buffer.length
-#-----------------------------
-handle.truncate(length)
-open("/tmp#{$$}.pid", 'w') { |handle| handle.truncate(length) }
-#-----------------------------
-pos = datafile.pos # tell is an alias of pos
-puts "I'm #{pos} bytes from the start of datafile"
-#-----------------------------
-logfile.seek(0, IO::SEEK_END)
-datafile.seek(pos) # IO::SEEK_SET is the default
-out.seek(-20, IO::SEEK_CUR)
-#-----------------------------
-written = datafile.syswrite(mystring)
-raise RunTimeError unless written == mystring.length
-block = infile.sysread(256) # no equivalent to perl offset parameter in sysread
-puts "only read #{block.length} bytes" if 256 != block.length
-#-----------------------------
-pos = handle.sysseek(0, IO::SEEK_CUR) # don't change position
-
-
-# @@PLEAC@@_8.1
-while (line = fh.gets)
- line.chomp!
- nextline = nil
- line.gsub!(/\\$/) { |match| nextline = fh.gets; '' }
- if (nextline != nil)
- line += nextline
- redo
- end
- # process full record in line here
-end
-#-----------------------------
-# DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
-# $(TEXINFOS) $(INFOS) $(MANS) $(DATA)
-# DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) \
-# $(TEXINFOS) $(INFO_DEPS) $(MANS) $(DATA) \
-# $(EXTRA_DIST)
-#-----------------------------
-line.gsub!(/\\\s*$/, '') {
- # as before
-}
-
-
-# @@PLEAC@@_8.2
-#-----------------------------
-count = `wc -l < #{filename}`
-fail "wc failed: #{$?}" if $? != 0
-count.chomp!
-#-----------------------------
-count = 0
-File.open(file, 'r') { |fh|
- count += 1 while fh.gets
-}
-# count now holds the number of lines read
-#-----------------------------
-count = 0
-while (chunk = file.sysread(2**16))
- count += chunk.count("\n")
-end rescue EOFError
-#-----------------------------
-File.open(filename,'r') { |fh|
- count += 1 while fh.gets
-}
-# count now holds the number of lines read
-#-----------------------------
-# As ruby doesn't quite have an equivalent to using a for
-# statement as in perl, I threw this in
-count = File.readlines(filename).size
-#-----------------------------
-1 while file.gets
-count = $.
-#-----------------------------
-$/ = ''
-open(filename, 'r') { |fh|
- 1 while fh.gets
- para_count = $.
-} rescue fail("can't open #{filename}: $!")
-#-----------------------------
-
-
-# ^^PLEAC^^_8.3
-#-----------------------------
-while (gets)
- split.each { |chunk|
- # do something with chunk
- }
-end
-#-----------------------------
-while (gets)
- gsub(/(\w[\w'-]*)/) { |word|
- # do something with word
- }
-end
-#-----------------------------
-# Make a word frequency count
-# normally hashes can be created using {} or just Hash.new
-# but we want the default value of an entry to be 0 instead
-# of nil. (nil can't be incremented)
-seen = Hash.new(0)
-while (gets)
- gsub(/(\w[\w'-]*)/) { |word|
- seen[word.downcase] += 1
- }
-end
-# output hash in a descending numeric sort of its values
-seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
- printf("%5d %s\n", v, k )
-end
-
-#-----------------------------
-# Line frequency count
-seen = Hash.new(0)
-while (gets)
- seen[$_.downcase] += 1
-end
-seen.sort { |a,b| b[1] <=> a[1] }.each do |k,v|
- printf("%5d %s\n", v, k )
-end
-#-----------------------------
-
-
-# @@PLEAC@@_8.4
-#-----------------------------
-# instead of file handle FILE, we can just
-# use a string containing the filename
-File.readlines(file).each { |line|
- # do something with line
-}
-#-----------------------------
-File.readlines(file).reverse_each { |line|
- # do something with line
-}
-#-----------------------------
-# the variable lines might have been created
-# this way
-# lines = File.readlines(file)
-#
-# normally one would use the reverse_each, but
-# if you insist on using a numerical index to
-# iterate over the lines array...
-(lines.size - 1).downto(0) { |i|
- line = lines[i]
-}
-#-----------------------------
-# the second readlines argument is a the
-# record separator $/, just like perl, a blank
-# separator splits the records into paragraphs
-File.readlines(file, '').each { |paragraph|
- # do something with paragraph
- puts "->Paragraph #{paragraph}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_8.6
-
-$/ = "%\n";
-srand;
-
-File.open('/usr/share/fortune/humorists').each do |line|
- adage = line if rand($.) < 1
-end
-
-puts adage;
-
-
-# @@PLEAC@@_8.10
-begin
- fh = File.open(file, "r+")
- addr = fh.tell unless fh.eof while fh.gets
- fh.truncate(addr)
-rescue SystemCallError
- $stderr.puts "#$!"
-end
-
-
-# @@PLEAC@@_9.0
-entry = File.stat("/usr/bin/vi")
-entry = File.stat("/usr/bin")
-entry = File.stat(INFILE)
-
-entry = File.stat("/usr/bin/vi")
-ctime = entry.ctime
-size = entry.size
-
-f = File.open(filename, "r")
-
-## There is no -T equivalent in Ruby, but we can still test emptiness
-if test(?s, filename)
- puts "#{filename} doesn't have text in it."
- exit
-end
-
-Dir.new("/usr/bin").each do |filename|
- puts "Inside /usr/bin is something called #{filename}"
-end
-
-
-# @@PLEAC@@_9.1
-file = File.stat("filename")
-readtime, writetime = file.atime, file.mtime
-file.utime(readtime, writetime)
-
-SECONDS_PER_DAY = 60 * 60 * 24
-file = File.stat("filename")
-atime, mtime = file.atime, file.mtime
-
-atime -= 7 * SECONDS_PER_DAY
-mtime -= 7 * SECONDS_PER_DAY
-
-File.utime(atime, mtime, file)
-mtime = File.stat(file).mtime
-File.utime(Time.new, mtime, file)
-File.utime(Time.new, File.stat("testfile").mtime, file)
-
-#-----------------------------
-#!/usr/bin/ruby -w
-## uvi - vi a file without changing it's access times
-
-if ARGV.length != 1
- puts "usage: uvi filename"
- exit
-end
-file = ARGV[0]
-atime, mtime = File.stat(file).atime, File.stat(file).mtime
-system(ENV["EDITOR"] || "vi", file)
-File.utime(atime, mtime, file)
-#-----------------------------
-
-
-# @@PLEAC@@_9.2
-File.unlink(FILENAME)
-
-err_flg = false
-filenames.each do |file|
- begin
- File.unlink(file)
- rescue
- err_flg = $!
- end
-end
-err_flg and raise "Couldn't unlink all of #{filenames.join(" ")}: #{err_flg}"
-
-File.unlink(file)
-
-count = filenames.length
-filenames.each do |file|
- begin
- File.unlink(file)
- rescue
- count -= 1
- end
-end
-if count != filenames.length
- STDERR.puts "could only delete #{count} of #{filenames.length} files"
-end
-
-
-# @@PLEAC@@_9.3
-require "ftools"
-File.copy(oldfile, newfile)
-
-infile = File.open(oldfile, "r")
-outfile = File.open(newfile, "w")
-
-blksize = infile.stat.blksize
-# This doesn't handle partial writes or ^Z
-# like the Perl version does.
-while (line = infile.read(blksize))
- outfile.write(line)
-end
-
-infile.close
-outfile.close
-
-system("cp #{oldfile} #{newfile}") # unix
-system("copy #{oldfile} #{newfile}") # dos, vms
-
-require "ftools"
-File.copy("datafile.dat", "datafile.bak")
-File.move("datafile.new", "datafile.dat")
-
-
-# @@PLEAC@@_9.4
-$seen = {} # must use global var to be seen inside of method below
-
-def do_my_thing(filename)
- dev, ino = File.stat(filename).dev, File.stat(filename).ino
- unless $seen[[dev, ino]]
- # do something with $filename because we haven't
- # seen it before
- end
- $seen[[dev, ino]] = $seen[[dev, ino]].to_i + 1
-end
-
-files.each do |filename|
- dev, ino = File.stat(filename).dev, File.stat(filename).ino
- if !$seen.has_key?([dev, ino])
- $seen[[dev, ino]] = []
- end
- $seen[[dev, ino]].push(filename)
-end
-
-$seen.keys.sort.each do |devino|
- ino, dev = devino
- if $seen[devino].length > 1
- # $seen[devino] is a list of filenames for the same file
- end
-end
-
-
-# @@PLEAC@@_9.5
-Dir.open(dirname) do |dir|
- dir.each do |file|
- # do something with dirname/file
- puts file
- end
-end
-# Dir.close is automatic
-
-# No -T equivalent in Ruby
-
-dir.each do |file|
- next if file =~ /^\.\.?$/
- # ...
-end
-
-def plainfiles(dir)
- dh = Dir.open(dir)
- dh.entries.grep(/^[^.]/).
- map {|file| "#{dir}/#{file}"}.
- find_all {|file| test(?f, file)}.
- sort
-end
-
-
-# @@PLEAC@@_9.6
-list = Dir.glob("*.c")
-
-dir = Dir.open(path)
-files = dir.entries.grep(/\.c$/)
-dir.close
-
-files = Dir.glob("*.c")
-files = Dir.open(path).entries.grep(/\.[ch]$/i)
-
-dir = Dir.new(path)
-files = dir.entries.grep(/\.[ch]$/i)
-
-begin
- d = Dir.open(dir)
-rescue Errno::ENOENT
- raise "Couldn't open #{dir} for reading: #{$!}"
-end
-
-files = []
-d.each do |file|
- puts file
- next unless file =~ /\.[ch]$/i
-
- filename = "#{dir}/#{file}"
- # There is no -T equivalent in Ruby, but we can still test emptiness
- files.push(filename) if test(?s, filename)
-end
-
-dirs.entries.grep(/^\d+$/).
- map { |file| [file, "#{path}/#{file}"]} .
- select { |file| test(?d, file[1]) }.
- sort { |a,b| a[0] <=> b[0] }.
- map { |file| file[1] }
-
-
-# @@PLEAC@@_9.7
-require 'find'
-Find.find(dirlist) do |file|
- # do whatever
-end
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-Find.find(*argv) do |file|
- print file, (test(?d, file) ? "/\n" : "\n")
-end
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-sum = 0
-Find.find(*argv) do |file|
- size = test(?s, file) || 0
- sum += size
-end
-puts "#{argv.join(' ')} contains #{sum} bytes"
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-saved_size, saved_name = -1, ""
-Find.find(*argv) do |file|
- size = test(?s, file) || 0
- next unless test(?f, file) && size > saved_size
- saved_size = size
- saved_name = file
-end
-puts "Biggest file #{saved_name} in #{argv.join(' ')} is #{saved_size}"
-
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-age, name = nil
-Find.find(*argv) do |file|
- mtime = File.stat(file).mtime
- next if age && age > mtime
- age = mtime
- name = file
-end
-puts "#{name} #{age}"
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# fdirs - find all directories
-require 'find'
-argv = ARGV.empty? ? %w{.} : ARGV
-File.find(*argv) { |file| puts file if test(?d, file) }
-#-----------------------------
-
-
-# @@PLEAC@@_9.8
-require 'fileutils'
-
-puts "Usage #{$0} dir ..." if ARGV.empty?
-ARGV.each do |dir|
- FileUtils.rmtree(dir)
-end
-
-
-# @@PLEAC@@_9.9
-require 'ftools'
-names.each do |file|
- newname = file
- begin
- File.move(file, newname)
- rescue Errno::EPERM
- $stderr.puts "Couldn't rename #{file} to #{newname}: #{$!}"
- end
-end
-
-require 'ftools'
-op = ARGV.empty? ? (raise "Usage: rename expr [files]\n") : ARGV.shift
-argv = ARGV.empty? ? $stdin.readlines.map { |f| f.chomp } : ARGV
-argv.each do |file|
- was = file
- file = eval("file.#{op}")
- File.move(was, file) unless was == file
-end
-
-
-# @@PLEAC@@_9.10
-base = File.basename(path)
-dir = File.dirname(path)
-# ruby has no fileparse equivalent
-dir, base = File.split(path)
-ext = base.scan(/\..*$/).to_s
-
-path = '/usr/lib/libc.a'
-file = File.basename(path)
-dir = File.dirname(path)
-
-puts "dir is #{dir}, file is #{file}"
-# dir is /usr/lib, file is libc.a
-
-path = '/usr/lib/libc.a'
-dir, filename = File.split(path)
-name, ext = filename.split(/(?=\.)/)
-puts "dir is #{dir}, name is #{name}, ext is #{ext}"
-# NOTE: The Ruby code prints
-# dir is /usr/lib, name is libc, extension is .a
-# while the Perl code prints a '/' after the directory name
-# dir is /usr/lib/, name is libc, extension is .a
-
-# No fileparse_set_fstype() equivalent in ruby
-
-def extension(path)
- ext = path.scan(/\..*$/).to_s
- ext.sub(/^\./, "")
-end
-
-
-# @@PLEAC@@_9.11
-#-----------------------------
-#!/usr/bin/ruby -w
-# symirror - build spectral forest of symlinks
-
-require 'find'
-require 'fileutils'
-
-raise "usage: #{$0} realdir mirrordir" unless ARGV.size == 2
-
-srcdir,dstdir = ARGV
-srcmode = File::stat(srcdir).mode
-Dir.mkdir(dstdir, srcmode & 07777) unless test(?d, dstdir)
-
-# fix relative paths
-Dir.chdir(srcdir) {srcdir = Dir.pwd}
-Dir.chdir(dstdir) {dstdir = Dir.pwd}
-
-Find.find(srcdir) do |srcfile|
- if test(?d, srcfile)
- dest = srcfile.sub(/^#{srcdir}/, dstdir)
- dmode = File::stat(srcfile).mode & 07777
- Dir.mkdir(dest, dmode) unless test(?d, dest)
- a = Dir["#{srcfile}/*"].reject{|f| test(?d, f)}
- FileUtils.ln_s(a, dest)
- end
-end
-
-
-# @@PLEAC@@_9.12
-# we use the Getopt/Declare library here for convenience:
-# http://raa.ruby-lang.org/project/getoptdeclare/
-#-----------------------------
-#!/usr/bin/ruby -w
-# lst - list sorted directory contents (depth first)
-
-require 'find'
-require 'etc'
-require "Getopt/Declare"
-
-# Note: in the option-spec below there must by at least one hard
-# tab in between each -option and its description. For example
-# -i <tab> read from stdin
-
-opts = Getopt::Declare.new(<<'EOPARAM')
- ============
- Input Format:
- -i read from stdin
- ============
- Output Format:
- -l long listing
- -r reverse listing
- ============
- Sort on: (one of)
- -m mtime (modify time - default)
- {$sort_criteria = :mtime}
- -u atime (access time)
- {$sort_criteria = :atime}
- -c ctime (inode change time)
- {$sort_criteria = :ctime}
- -s size
- {$sort_criteria = :size}
- [mutex: -m -u -c -s]
-
-EOPARAM
-
-$sort_criteria ||= :mtime
-files = {}
-DIRS = opts['-i'] ? $stdin.readlines.map{|f|f.chomp!} : ARGV
-DIRS.each do |dir|
- Find.find(dir) do |ent|
- files[ent] = File::stat(ent)
- end
-end
-entries = files.keys.sort_by{|f| files[f].send($sort_criteria)}
-entries = entries.reverse unless opts['-r']
-
-entries.each do |ent|
- unless opts['-l']
- puts ent
- next
- end
- stats = files[ent]
- ftime = stats.send($sort_criteria == :size ? :mtime : $sort_criteria)
- printf "%6d %04o %6d %8s %8s %8d %s %s\n",
- stats.ino,
- stats.mode & 07777,
- stats.nlink,
- ETC::PASSWD[stats.uid].name,
- ETC::GROUP[stats.gid].name,
- stats.size,
- ftime.strftime("%a %b %d %H:%M:%S %Y"),
- ent
-end
-
-
-# @@PLEAC@@_10.0
-def hello
- $greeted += 1 # in Ruby, a variable beginning with $ is global (can be any type of course)
- puts "hi there!"
-end
-
-# We need to initialize $greeted before it can be used, because "+=" is waiting a Numeric object
-$greeted = 0
-hello # note that appending () is optional to function calls with no parameters
-
-
-# @@PLEAC@@_10.1
-# In Ruby, parameters are named anyway
-def hypotenuse(side1, side2)
- Math.sqrt(side1**2 + side2**2) # the sqrt function comes from the Math module
-end
-diag = hypotenuse(3, 4)
-
-puts hypotenuse(3, 4)
-
-a = [3, 4]
-print hypotenuse(*a) # the star operator will magically convert an Array into a "tuple"
-
-both = men + women
-
-# In Ruby, all objects are references, so the same problem arises; we then return a new object
-nums = [1.4, 3.5, 6.7]
-def int_all(n)
- n.collect { |v| v.to_i }
-end
-ints = int_all(nums)
-
-nums = [1.4, 3.5, 6.7]
-def trunc_em(n)
- n.collect! { |v| v.to_i } # the bang-version of collect modifies the object
-end
-trunc_em(nums)
-
-# Ruby has two chomp version:
-# ``chomp'' chomps the record separator and returns what's expected
-# ``chomp!'' does the same but also modifies the parameter object
-
diff --git a/tests/examplefiles/ltmain.sh b/tests/examplefiles/ltmain.sh
index 8f7a6ac1..5b5f845f 100644
--- a/tests/examplefiles/ltmain.sh
+++ b/tests/examplefiles/ltmain.sh
@@ -2847,4125 +2847,3 @@ EOF
# We're trying link a shared library against a static one
# but the system doesn't support it.
- # Just print a warning and add the library to dependency_libs so
- # that the program can be linked against the static library.
- $echo
- $echo "*** Warning: This system can not link to static lib archive $lib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have."
- if test "$module" = yes; then
- $echo "*** But as you try to build a module library, libtool will still create "
- $echo "*** a static module, that should work as long as the dlopening application"
- $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
- if test -z "$global_symbol_pipe"; then
- $echo
- $echo "*** However, this would only work if libtool was able to extract symbol"
- $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $echo "*** not find such a program. So, this module is probably useless."
- $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- else
- deplibs="$dir/$old_library $deplibs"
- link_static=yes
- fi
- fi # link shared/static library?
-
- if test "$linkmode" = lib; then
- if test -n "$dependency_libs" &&
- { test "$hardcode_into_libs" != yes ||
- test "$build_old_libs" = yes ||
- test "$link_static" = yes; }; then
- # Extract -R from dependency_libs
- temp_deplibs=
- for libdir in $dependency_libs; do
- case $libdir in
- -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
- case " $xrpath " in
- *" $temp_xrpath "*) ;;
- *) xrpath="$xrpath $temp_xrpath";;
- esac;;
- *) temp_deplibs="$temp_deplibs $libdir";;
- esac
- done
- dependency_libs="$temp_deplibs"
- fi
-
- newlib_search_path="$newlib_search_path $absdir"
- # Link against this library
- test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
- # ... and its dependency_libs
- tmp_libs=
- for deplib in $dependency_libs; do
- newdependency_libs="$deplib $newdependency_libs"
- if test "X$duplicate_deps" = "Xyes" ; then
- case "$tmp_libs " in
- *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
- esac
- fi
- tmp_libs="$tmp_libs $deplib"
- done
-
- if test "$link_all_deplibs" != no; then
- # Add the search paths of all dependency libraries
- for deplib in $dependency_libs; do
- case $deplib in
- -L*) path="$deplib" ;;
- *.la)
- dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$deplib" && dir="."
- # We need an absolute path.
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
- *)
- absdir=`cd "$dir" && pwd`
- if test -z "$absdir"; then
- $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
- absdir="$dir"
- fi
- ;;
- esac
- if grep "^installed=no" $deplib > /dev/null; then
- path="$absdir/$objdir"
- else
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- if test "$absdir" != "$libdir"; then
- $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
- fi
- path="$absdir"
- fi
- depdepl=
- case $host in
- *-*-darwin*)
- # we do not want to link against static libs,
- # but need to link against shared
- eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
- if test -n "$deplibrary_names" ; then
- for tmp in $deplibrary_names ; do
- depdepl=$tmp
- done
- if test -f "$path/$depdepl" ; then
- depdepl="$path/$depdepl"
- fi
- # do not add paths which are already there
- case " $newlib_search_path " in
- *" $path "*) ;;
- *) newlib_search_path="$newlib_search_path $path";;
- esac
- fi
- path=""
- ;;
- *)
- path="-L$path"
- ;;
- esac
- ;;
- -l*)
- case $host in
- *-*-darwin*)
- # Again, we only want to link against shared libraries
- eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
- for tmp in $newlib_search_path ; do
- if test -f "$tmp/lib$tmp_libs.dylib" ; then
- eval depdepl="$tmp/lib$tmp_libs.dylib"
- break
- fi
- done
- path=""
- ;;
- *) continue ;;
- esac
- ;;
- *) continue ;;
- esac
- case " $deplibs " in
- *" $path "*) ;;
- *) deplibs="$path $deplibs" ;;
- esac
- case " $deplibs " in
- *" $depdepl "*) ;;
- *) deplibs="$depdepl $deplibs" ;;
- esac
- done
- fi # link_all_deplibs != no
- fi # linkmode = lib
- done # for deplib in $libs
- dependency_libs="$newdependency_libs"
- if test "$pass" = dlpreopen; then
- # Link the dlpreopened libraries before other libraries
- for deplib in $save_deplibs; do
- deplibs="$deplib $deplibs"
- done
- fi
- if test "$pass" != dlopen; then
- if test "$pass" != conv; then
- # Make sure lib_search_path contains only unique directories.
- lib_search_path=
- for dir in $newlib_search_path; do
- case "$lib_search_path " in
- *" $dir "*) ;;
- *) lib_search_path="$lib_search_path $dir" ;;
- esac
- done
- newlib_search_path=
- fi
-
- if test "$linkmode,$pass" != "prog,link"; then
- vars="deplibs"
- else
- vars="compile_deplibs finalize_deplibs"
- fi
- for var in $vars dependency_libs; do
- # Add libraries to $var in reverse order
- eval tmp_libs=\"\$$var\"
- new_libs=
- for deplib in $tmp_libs; do
- # FIXME: Pedantically, this is the right thing to do, so
- # that some nasty dependency loop isn't accidentally
- # broken:
- #new_libs="$deplib $new_libs"
- # Pragmatically, this seems to cause very few problems in
- # practice:
- case $deplib in
- -L*) new_libs="$deplib $new_libs" ;;
- -R*) ;;
- *)
- # And here is the reason: when a library appears more
- # than once as an explicit dependence of a library, or
- # is implicitly linked in more than once by the
- # compiler, it is considered special, and multiple
- # occurrences thereof are not removed. Compare this
- # with having the same library being listed as a
- # dependency of multiple other libraries: in this case,
- # we know (pedantically, we assume) the library does not
- # need to be listed more than once, so we keep only the
- # last copy. This is not always right, but it is rare
- # enough that we require users that really mean to play
- # such unportable linking tricks to link the library
- # using -Wl,-lname, so that libtool does not consider it
- # for duplicate removal.
- case " $specialdeplibs " in
- *" $deplib "*) new_libs="$deplib $new_libs" ;;
- *)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$deplib $new_libs" ;;
- esac
- ;;
- esac
- ;;
- esac
- done
- tmp_libs=
- for deplib in $new_libs; do
- case $deplib in
- -L*)
- case " $tmp_libs " in
- *" $deplib "*) ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- ;;
- *) tmp_libs="$tmp_libs $deplib" ;;
- esac
- done
- eval $var=\"$tmp_libs\"
- done # for var
- fi
- # Last step: remove runtime libs from dependency_libs
- # (they stay in deplibs)
- tmp_libs=
- for i in $dependency_libs ; do
- case " $predeps $postdeps $compiler_lib_search_path " in
- *" $i "*)
- i=""
- ;;
- esac
- if test -n "$i" ; then
- tmp_libs="$tmp_libs $i"
- fi
- done
- dependency_libs=$tmp_libs
- done # for pass
- if test "$linkmode" = prog; then
- dlfiles="$newdlfiles"
- dlprefiles="$newdlprefiles"
- fi
-
- case $linkmode in
- oldlib)
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
- fi
-
- if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
- $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
- fi
-
- # Now set the variables for building old libraries.
- build_libtool_libs=no
- oldlibs="$output"
- objs="$objs$old_deplibs"
- ;;
-
- lib)
- # Make sure we only generate libraries of the form `libNAME.la'.
- case $outputname in
- lib*)
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
- eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- ;;
- *)
- if test "$module" = no; then
- $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
- if test "$need_lib_prefix" != no; then
- # Add the "lib" prefix for modules if required
- name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- eval shared_ext=\"$shrext_cmds\"
- eval libname=\"$libname_spec\"
- else
- libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
- fi
- ;;
- esac
-
- if test -n "$objs"; then
- if test "$deplibs_check_method" != pass_all; then
- $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
- exit $EXIT_FAILURE
- else
- $echo
- $echo "*** Warning: Linking the shared library $output against the non-libtool"
- $echo "*** objects $objs is not portable!"
- libobjs="$libobjs $objs"
- fi
- fi
-
- if test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
- fi
-
- set dummy $rpath
- if test "$#" -gt 2; then
- $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
- fi
- install_libdir="$2"
-
- oldlibs=
- if test -z "$rpath"; then
- if test "$build_libtool_libs" = yes; then
- # Building a libtool convenience library.
- # Some compilers have problems with a `.al' extension so
- # convenience libraries should have the same extension an
- # archive normally would.
- oldlibs="$output_objdir/$libname.$libext $oldlibs"
- build_libtool_libs=convenience
- build_old_libs=yes
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
- fi
- else
-
- # Parse the version information argument.
- save_ifs="$IFS"; IFS=':'
- set dummy $vinfo 0 0 0
- IFS="$save_ifs"
-
- if test -n "$8"; then
- $echo "$modename: too many parameters to \`-version-info'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # convert absolute version numbers to libtool ages
- # this retains compatibility with .la files and attempts
- # to make the code below a bit more comprehensible
-
- case $vinfo_number in
- yes)
- number_major="$2"
- number_minor="$3"
- number_revision="$4"
- #
- # There are really only two kinds -- those that
- # use the current revision as the major version
- # and those that subtract age and use age as
- # a minor version. But, then there is irix
- # which has an extra 1 added just for fun
- #
- case $version_type in
- darwin|linux|osf|windows)
- current=`expr $number_major + $number_minor`
- age="$number_minor"
- revision="$number_revision"
- ;;
- freebsd-aout|freebsd-elf|sunos)
- current="$number_major"
- revision="$number_minor"
- age="0"
- ;;
- irix|nonstopux)
- current=`expr $number_major + $number_minor - 1`
- age="$number_minor"
- revision="$number_minor"
- ;;
- esac
- ;;
- no)
- current="$2"
- revision="$3"
- age="$4"
- ;;
- esac
-
- # Check that each of the things are valid numbers.
- case $current in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- case $revision in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- case $age in
- 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
- *)
- $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- if test "$age" -gt "$current"; then
- $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
- $echo "$modename: \`$vinfo' is not valid version information" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Calculate the version variables.
- major=
- versuffix=
- verstring=
- case $version_type in
- none) ;;
-
- darwin)
- # Like Linux, but with the current version available in
- # verstring for coding it into the library header
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- # Darwin ld doesn't like 0 for these options...
- minor_current=`expr $current + 1`
- verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
- ;;
-
- freebsd-aout)
- major=".$current"
- versuffix=".$current.$revision";
- ;;
-
- freebsd-elf)
- major=".$current"
- versuffix=".$current";
- ;;
-
- irix | nonstopux)
- major=`expr $current - $age + 1`
-
- case $version_type in
- nonstopux) verstring_prefix=nonstopux ;;
- *) verstring_prefix=sgi ;;
- esac
- verstring="$verstring_prefix$major.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$revision
- while test "$loop" -ne 0; do
- iface=`expr $revision - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring_prefix$major.$iface:$verstring"
- done
-
- # Before this point, $major must not contain `.'.
- major=.$major
- versuffix="$major.$revision"
- ;;
-
- linux)
- major=.`expr $current - $age`
- versuffix="$major.$age.$revision"
- ;;
-
- osf)
- major=.`expr $current - $age`
- versuffix=".$current.$age.$revision"
- verstring="$current.$age.$revision"
-
- # Add in all the interfaces that we are compatible with.
- loop=$age
- while test "$loop" -ne 0; do
- iface=`expr $current - $loop`
- loop=`expr $loop - 1`
- verstring="$verstring:${iface}.0"
- done
-
- # Make executables depend on our current version.
- verstring="$verstring:${current}.0"
- ;;
-
- sunos)
- major=".$current"
- versuffix=".$current.$revision"
- ;;
-
- windows)
- # Use '-' rather than '.', since we only want one
- # extension on DOS 8.3 filesystems.
- major=`expr $current - $age`
- versuffix="-$major"
- ;;
-
- *)
- $echo "$modename: unknown library version type \`$version_type'" 1>&2
- $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- # Clear the version info if we defaulted, and they specified a release.
- if test -z "$vinfo" && test -n "$release"; then
- major=
- case $version_type in
- darwin)
- # we can't check for "0.0" in archive_cmds due to quoting
- # problems, so we reset it completely
- verstring=
- ;;
- *)
- verstring="0.0"
- ;;
- esac
- if test "$need_version" = no; then
- versuffix=
- else
- versuffix=".0.0"
- fi
- fi
-
- # Remove version info from name if versioning should be avoided
- if test "$avoid_version" = yes && test "$need_version" = no; then
- major=
- versuffix=
- verstring=""
- fi
-
- # Check to see if the archive will have undefined symbols.
- if test "$allow_undefined" = yes; then
- if test "$allow_undefined_flag" = unsupported; then
- $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
- build_libtool_libs=no
- build_old_libs=yes
- fi
- else
- # Don't allow undefined symbols.
- allow_undefined_flag="$no_undefined_flag"
- fi
- fi
-
- if test "$mode" != relink; then
- # Remove our outputs, but don't remove object files since they
- # may have been created when compiling PIC objects.
- removelist=
- tempremovelist=`$echo "$output_objdir/*"`
- for p in $tempremovelist; do
- case $p in
- *.$objext)
- ;;
- $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
- if test "X$precious_files_regex" != "X"; then
- if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
- then
- continue
- fi
- fi
- removelist="$removelist $p"
- ;;
- *) ;;
- esac
- done
- if test -n "$removelist"; then
- $show "${rm}r $removelist"
- $run ${rm}r $removelist
- fi
- fi
-
- # Now set the variables for building old libraries.
- if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
- oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
- # Transform .lo files to .o files.
- oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
- fi
-
- # Eliminate all temporary directories.
- for path in $notinst_path; do
- lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
- deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
- dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
- done
-
- if test -n "$xrpath"; then
- # If the user specified any rpath flags, then add them.
- temp_xrpath=
- for libdir in $xrpath; do
- temp_xrpath="$temp_xrpath -R$libdir"
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
- dependency_libs="$temp_xrpath $dependency_libs"
- fi
- fi
-
- # Make sure dlfiles contains only unique files that won't be dlpreopened
- old_dlfiles="$dlfiles"
- dlfiles=
- for lib in $old_dlfiles; do
- case " $dlprefiles $dlfiles " in
- *" $lib "*) ;;
- *) dlfiles="$dlfiles $lib" ;;
- esac
- done
-
- # Make sure dlprefiles contains only unique files
- old_dlprefiles="$dlprefiles"
- dlprefiles=
- for lib in $old_dlprefiles; do
- case "$dlprefiles " in
- *" $lib "*) ;;
- *) dlprefiles="$dlprefiles $lib" ;;
- esac
- done
-
- if test "$build_libtool_libs" = yes; then
- if test -n "$rpath"; then
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
- # these systems don't actually have a c library (as such)!
- ;;
- *-*-rhapsody* | *-*-darwin1.[012])
- # Rhapsody C library is in the System framework
- deplibs="$deplibs -framework System"
- ;;
- *-*-netbsd*)
- # Don't link with libc until the a.out ld.so is fixed.
- ;;
- *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
- # Do not include libc due to us having libc/libc_r.
- ;;
- *-*-sco3.2v5* | *-*-sco5v6*)
- # Causes problems with __ctype
- ;;
- *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
- # Compiler inserts libc in the correct place for threads to work
- ;;
- *)
- # Add libc to deplibs on all other systems if necessary.
- if test "$build_libtool_need_lc" = "yes"; then
- deplibs="$deplibs -lc"
- fi
- ;;
- esac
- fi
-
- # Transform deplibs into only deplibs that can be linked in shared.
- name_save=$name
- libname_save=$libname
- release_save=$release
- versuffix_save=$versuffix
- major_save=$major
- # I'm not sure if I'm treating the release correctly. I think
- # release should show up in the -l (ie -lgmp5) so we don't want to
- # add it in twice. Is that correct?
- release=""
- versuffix=""
- major=""
- newdeplibs=
- droppeddeps=no
- case $deplibs_check_method in
- pass_all)
- # Don't check for shared/static. Everything works.
- # This might be a little naive. We might want to check
- # whether the library exists or not. But this is on
- # osf3 & osf4 and I'm not really sure... Just
- # implementing what was already the behavior.
- newdeplibs=$deplibs
- ;;
- test_compile)
- # This code stresses the "libraries are programs" paradigm to its
- # limits. Maybe even breaks it. We compile a program, linking it
- # against the deplibs as a proxy for the library. Then we can check
- # whether they linked in statically or dynamically with ldd.
- $rm conftest.c
- cat > conftest.c <<EOF
- int main() { return 0; }
-EOF
- $rm conftest
- $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
- if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- for i in $deplibs; do
- name=`expr $i : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" -ne "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning: dynamic linker does not accept needed library $i."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which I believe you do not have"
- $echo "*** because a test_compile did reveal that the linker did not use it for"
- $echo "*** its dynamic dependency list that programs get resolved with at runtime."
- fi
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- else
- # Error occurred in the first compile. Let's try to salvage
- # the situation: Compile a separate program for each library.
- for i in $deplibs; do
- name=`expr $i : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" != "0"; then
- $rm conftest
- $LTCC $LTCFLAGS -o conftest conftest.c $i
- # Did it work?
- if test "$?" -eq 0 ; then
- ldd_output=`ldd conftest`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $i "*)
- newdeplibs="$newdeplibs $i"
- i=""
- ;;
- esac
- fi
- if test -n "$i" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- deplib_matches=`eval \\$echo \"$library_names_spec\"`
- set dummy $deplib_matches
- deplib_match=$2
- if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
- newdeplibs="$newdeplibs $i"
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning: dynamic linker does not accept needed library $i."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because a test_compile did reveal that the linker did not use this one"
- $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
- fi
- fi
- else
- droppeddeps=yes
- $echo
- $echo "*** Warning! Library $i is needed by this library but I was not able to"
- $echo "*** make it link in! You will probably need to install it or some"
- $echo "*** library that it depends on before this library will be fully"
- $echo "*** functional. Installing it before continuing would be even better."
- fi
- else
- newdeplibs="$newdeplibs $i"
- fi
- done
- fi
- ;;
- file_magic*)
- set dummy $deplibs_check_method
- file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
- name=`expr $a_deplib : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test "$name" != "" && test "$name" != "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- # Follow soft links.
- if ls -lLd "$potent_lib" 2>/dev/null \
- | grep " -> " >/dev/null; then
- continue
- fi
- # The statement above tries to avoid entering an
- # endless loop below, in case of cyclic links.
- # We might still enter an endless loop, since a link
- # loop can be closed while we follow links,
- # but so what?
- potlib="$potent_lib"
- while test -h "$potlib" 2>/dev/null; do
- potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
- case $potliblink in
- [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
- *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
- esac
- done
- # It is ok to link against an archive when
- # building a shared library.
- if $AR -t $potlib > /dev/null 2>&1; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
- | ${SED} 10q \
- | $EGREP "$file_magic_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $echo
- $echo "*** Warning: linker path does not have real file for library $a_deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $echo "*** with $libname but no candidates were found. (...for file magic test)"
- else
- $echo "*** with $libname and none of the candidates passed a file format test"
- $echo "*** using a file magic. Last file checked: $potlib"
- fi
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- match_pattern*)
- set dummy $deplibs_check_method
- match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
- for a_deplib in $deplibs; do
- name=`expr $a_deplib : '-l\(.*\)'`
- # If $name is empty we are operating on a -L argument.
- if test -n "$name" && test "$name" != "0"; then
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- case " $predeps $postdeps " in
- *" $a_deplib "*)
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- ;;
- esac
- fi
- if test -n "$a_deplib" ; then
- libname=`eval \\$echo \"$libname_spec\"`
- for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
- potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
- for potent_lib in $potential_libs; do
- potlib="$potent_lib" # see symlink-check above in file_magic test
- if eval $echo \"$potent_lib\" 2>/dev/null \
- | ${SED} 10q \
- | $EGREP "$match_pattern_regex" > /dev/null; then
- newdeplibs="$newdeplibs $a_deplib"
- a_deplib=""
- break 2
- fi
- done
- done
- fi
- if test -n "$a_deplib" ; then
- droppeddeps=yes
- $echo
- $echo "*** Warning: linker path does not have real file for library $a_deplib."
- $echo "*** I have the capability to make that library automatically link in when"
- $echo "*** you link to this library. But I can only do this if you have a"
- $echo "*** shared version of the library, which you do not appear to have"
- $echo "*** because I did check the linker path looking for a file starting"
- if test -z "$potlib" ; then
- $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
- else
- $echo "*** with $libname and none of the candidates passed a file format test"
- $echo "*** using a regex pattern. Last file checked: $potlib"
- fi
- fi
- else
- # Add a -L argument.
- newdeplibs="$newdeplibs $a_deplib"
- fi
- done # Gone through all deplibs.
- ;;
- none | unknown | *)
- newdeplibs=""
- tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
- -e 's/ -[LR][^ ]*//g'`
- if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
- for i in $predeps $postdeps ; do
- # can't use Xsed below, because $i might contain '/'
- tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
- done
- fi
- if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
- | grep . >/dev/null; then
- $echo
- if test "X$deplibs_check_method" = "Xnone"; then
- $echo "*** Warning: inter-library dependencies are not supported in this platform."
- else
- $echo "*** Warning: inter-library dependencies are not known to be supported."
- fi
- $echo "*** All declared inter-library dependencies are being dropped."
- droppeddeps=yes
- fi
- ;;
- esac
- versuffix=$versuffix_save
- major=$major_save
- release=$release_save
- libname=$libname_save
- name=$name_save
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
- ;;
- esac
-
- if test "$droppeddeps" = yes; then
- if test "$module" = yes; then
- $echo
- $echo "*** Warning: libtool could not satisfy all declared inter-library"
- $echo "*** dependencies of module $libname. Therefore, libtool will create"
- $echo "*** a static module, that should work as long as the dlopening"
- $echo "*** application is linked with the -dlopen flag."
- if test -z "$global_symbol_pipe"; then
- $echo
- $echo "*** However, this would only work if libtool was able to extract symbol"
- $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
- $echo "*** not find such a program. So, this module is probably useless."
- $echo "*** \`nm' from GNU binutils and a full rebuild may help."
- fi
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- else
- $echo "*** The inter-library dependencies that have been dropped here will be"
- $echo "*** automatically added whenever a program is linked with this library"
- $echo "*** or is declared to -dlopen it."
-
- if test "$allow_undefined" = no; then
- $echo
- $echo "*** Since this library must not contain undefined symbols,"
- $echo "*** because either the platform does not support them or"
- $echo "*** it was explicitly requested with -no-undefined,"
- $echo "*** libtool will only create a static version of it."
- if test "$build_old_libs" = no; then
- oldlibs="$output_objdir/$libname.$libext"
- build_libtool_libs=module
- build_old_libs=yes
- else
- build_libtool_libs=no
- fi
- fi
- fi
- fi
- # Done checking deplibs!
- deplibs=$newdeplibs
- fi
-
-
- # move library search paths that coincide with paths to not yet
- # installed libraries to the beginning of the library search list
- new_libs=
- for path in $notinst_path; do
- case " $new_libs " in
- *" -L$path/$objdir "*) ;;
- *)
- case " $deplibs " in
- *" -L$path/$objdir "*)
- new_libs="$new_libs -L$path/$objdir" ;;
- esac
- ;;
- esac
- done
- for deplib in $deplibs; do
- case $deplib in
- -L*)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- done
- deplibs="$new_libs"
-
-
- # All the library-specific variables (install_libdir is set above).
- library_names=
- old_library=
- dlname=
-
- # Test again, we may have decided not to build it any more
- if test "$build_libtool_libs" = yes; then
- if test "$hardcode_into_libs" = yes; then
- # Hardcode the library paths
- hardcode_libdirs=
- dep_rpath=
- rpath="$finalize_rpath"
- test "$mode" != relink && rpath="$compile_rpath$rpath"
- for libdir in $rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- dep_rpath="$dep_rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- if test -n "$hardcode_libdir_flag_spec_ld"; then
- eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
- else
- eval dep_rpath=\"$hardcode_libdir_flag_spec\"
- fi
- fi
- if test -n "$runpath_var" && test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
- fi
- test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
- fi
-
- shlibpath="$finalize_shlibpath"
- test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
- if test -n "$shlibpath"; then
- eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
- fi
-
- # Get the real and link names of the library.
- eval shared_ext=\"$shrext_cmds\"
- eval library_names=\"$library_names_spec\"
- set dummy $library_names
- realname="$2"
- shift; shift
-
- if test -n "$soname_spec"; then
- eval soname=\"$soname_spec\"
- else
- soname="$realname"
- fi
- if test -z "$dlname"; then
- dlname=$soname
- fi
-
- lib="$output_objdir/$realname"
- linknames=
- for link
- do
- linknames="$linknames $link"
- done
-
- # Use standard objects if they are pic
- test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- cmds=$export_symbols_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- if len=`expr "X$cmd" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- $show "$cmd"
- $run eval "$cmd" || exit $?
- skipped_export=false
- else
- # The command line is too long to execute in one step.
- $show "using reloadable object file for export list..."
- skipped_export=:
- # Break out early, otherwise skipped_export may be
- # set to false by a later but shorter cmd.
- break
- fi
- done
- IFS="$save_ifs"
- if test -n "$export_symbols_regex"; then
- $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
- $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
- $show "$mv \"${export_symbols}T\" \"$export_symbols\""
- $run eval '$mv "${export_symbols}T" "$export_symbols"'
- fi
- fi
- fi
-
- if test -n "$export_symbols" && test -n "$include_expsyms"; then
- $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
- fi
-
- tmp_deplibs=
- for test_deplib in $deplibs; do
- case " $convenience " in
- *" $test_deplib "*) ;;
- *)
- tmp_deplibs="$tmp_deplibs $test_deplib"
- ;;
- esac
- done
- deplibs="$tmp_deplibs"
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $convenience
- libobjs="$libobjs $func_extract_archives_result"
- fi
- fi
-
- if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
- eval flag=\"$thread_safe_flag_spec\"
- linker_flags="$linker_flags $flag"
- fi
-
- # Make a backup of the uninstalled library when relinking
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
- fi
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- eval test_cmds=\"$module_expsym_cmds\"
- cmds=$module_expsym_cmds
- else
- eval test_cmds=\"$module_cmds\"
- cmds=$module_cmds
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- eval test_cmds=\"$archive_expsym_cmds\"
- cmds=$archive_expsym_cmds
- else
- eval test_cmds=\"$archive_cmds\"
- cmds=$archive_cmds
- fi
- fi
-
- if test "X$skipped_export" != "X:" &&
- len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- :
- else
- # The command line is too long to link in one step, link piecewise.
- $echo "creating reloadable object files..."
-
- # Save the value of $output and $libobjs because we want to
- # use them later. If we have whole_archive_flag_spec, we
- # want to use save_libobjs as it was before
- # whole_archive_flag_spec was expanded, because we can't
- # assume the linker understands whole_archive_flag_spec.
- # This may have to be revisited, in case too many
- # convenience libraries get linked in and end up exceeding
- # the spec.
- if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
- save_libobjs=$libobjs
- fi
- save_output=$output
- output_la=`$echo "X$output" | $Xsed -e "$basename"`
-
- # Clear the reloadable object creation command queue and
- # initialize k to one.
- test_cmds=
- concat_cmds=
- objlist=
- delfiles=
- last_robj=
- k=1
- output=$output_objdir/$output_la-${k}.$objext
- # Loop over the list of objects to be linked.
- for obj in $save_libobjs
- do
- eval test_cmds=\"$reload_cmds $objlist $last_robj\"
- if test "X$objlist" = X ||
- { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len"; }; then
- objlist="$objlist $obj"
- else
- # The command $test_cmds is almost too long, add a
- # command to the queue.
- if test "$k" -eq 1 ; then
- # The first file doesn't have a previous command to add.
- eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
- else
- # All subsequent reloadable object files will link in
- # the last one created.
- eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
- fi
- last_robj=$output_objdir/$output_la-${k}.$objext
- k=`expr $k + 1`
- output=$output_objdir/$output_la-${k}.$objext
- objlist=$obj
- len=1
- fi
- done
- # Handle the remaining objects by creating one last
- # reloadable object file. All subsequent reloadable object
- # files will link in the last one created.
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
-
- if ${skipped_export-false}; then
- $show "generating symbol list for \`$libname.la'"
- export_symbols="$output_objdir/$libname.exp"
- $run $rm $export_symbols
- libobjs=$output
- # Append the command to create the export file.
- eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
- fi
-
- # Set up a command to remove the reloadable object files
- # after they are used.
- i=0
- while test "$i" -lt "$k"
- do
- i=`expr $i + 1`
- delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
- done
-
- $echo "creating a temporary reloadable object file: $output"
-
- # Loop through the commands generated above and execute them.
- save_ifs="$IFS"; IFS='~'
- for cmd in $concat_cmds; do
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- libobjs=$output
- # Restore the value of output.
- output=$save_output
-
- if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
- eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
- fi
- # Expand the library linking commands again to reset the
- # value of $libobjs for piecewise linking.
-
- # Do each of the archive commands.
- if test "$module" = yes && test -n "$module_cmds" ; then
- if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
- cmds=$module_expsym_cmds
- else
- cmds=$module_cmds
- fi
- else
- if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
- cmds=$archive_expsym_cmds
- else
- cmds=$archive_cmds
- fi
- fi
-
- # Append the command to remove the reloadable object files
- # to the just-reset $cmds.
- eval cmds=\"\$cmds~\$rm $delfiles\"
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || {
- lt_exit=$?
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
- fi
-
- exit $lt_exit
- }
- done
- IFS="$save_ifs"
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
-
- if test -n "$convenience"; then
- if test -z "$whole_archive_flag_spec"; then
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- fi
- fi
-
- exit $EXIT_SUCCESS
- fi
-
- # Create links to the real library.
- for linkname in $linknames; do
- if test "$realname" != "$linkname"; then
- $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
- $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
- fi
- done
-
- # If -module or -export-dynamic was specified, set the dlname.
- if test "$module" = yes || test "$export_dynamic" = yes; then
- # On all known operating systems, these are identical.
- dlname="$soname"
- fi
- fi
- ;;
-
- obj)
- if test -n "$deplibs"; then
- $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
- fi
-
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
- fi
-
- if test -n "$rpath"; then
- $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
- fi
-
- if test -n "$xrpath"; then
- $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
- fi
-
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
- fi
-
- case $output in
- *.lo)
- if test -n "$objs$old_deplibs"; then
- $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
- exit $EXIT_FAILURE
- fi
- libobj="$output"
- obj=`$echo "X$output" | $Xsed -e "$lo2o"`
- ;;
- *)
- libobj=
- obj="$output"
- ;;
- esac
-
- # Delete the old objects.
- $run $rm $obj $libobj
-
- # Objects from convenience libraries. This assumes
- # single-version convenience libraries. Whenever we create
- # different ones for PIC/non-PIC, this we'll have to duplicate
- # the extraction.
- reload_conv_objs=
- gentop=
- # reload_cmds runs $LD directly, so let us get rid of
- # -Wl from whole_archive_flag_spec
- wl=
-
- if test -n "$convenience"; then
- if test -n "$whole_archive_flag_spec"; then
- eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
- else
- gentop="$output_objdir/${obj}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $convenience
- reload_conv_objs="$reload_objs $func_extract_archives_result"
- fi
- fi
-
- # Create the old-style object.
- reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
-
- output="$obj"
- cmds=$reload_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
-
- # Exit if we aren't doing a library object file.
- if test -z "$libobj"; then
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- exit $EXIT_SUCCESS
- fi
-
- if test "$build_libtool_libs" != yes; then
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- # Create an invalid libtool object if no PIC, so that we don't
- # accidentally link it into a program.
- # $show "echo timestamp > $libobj"
- # $run eval "echo timestamp > $libobj" || exit $?
- exit $EXIT_SUCCESS
- fi
-
- if test -n "$pic_flag" || test "$pic_mode" != default; then
- # Only do commands if we really have different PIC objects.
- reload_objs="$libobjs $reload_conv_objs"
- output="$libobj"
- cmds=$reload_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$gentop"; then
- $show "${rm}r $gentop"
- $run ${rm}r $gentop
- fi
-
- exit $EXIT_SUCCESS
- ;;
-
- prog)
- case $host in
- *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
- esac
- if test -n "$vinfo"; then
- $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
- fi
-
- if test -n "$release"; then
- $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
- fi
-
- if test "$preload" = yes; then
- if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
- test "$dlopen_self_static" = unknown; then
- $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
- fi
- fi
-
- case $host in
- *-*-rhapsody* | *-*-darwin1.[012])
- # On Rhapsody replace the C library is the System framework
- compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
- ;;
- esac
-
- case $host in
- *darwin*)
- # Don't allow lazy linking, it breaks C++ global constructors
- if test "$tagname" = CXX ; then
- compile_command="$compile_command ${wl}-bind_at_load"
- finalize_command="$finalize_command ${wl}-bind_at_load"
- fi
- ;;
- esac
-
-
- # move library search paths that coincide with paths to not yet
- # installed libraries to the beginning of the library search list
- new_libs=
- for path in $notinst_path; do
- case " $new_libs " in
- *" -L$path/$objdir "*) ;;
- *)
- case " $compile_deplibs " in
- *" -L$path/$objdir "*)
- new_libs="$new_libs -L$path/$objdir" ;;
- esac
- ;;
- esac
- done
- for deplib in $compile_deplibs; do
- case $deplib in
- -L*)
- case " $new_libs " in
- *" $deplib "*) ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- ;;
- *) new_libs="$new_libs $deplib" ;;
- esac
- done
- compile_deplibs="$new_libs"
-
-
- compile_command="$compile_command $compile_deplibs"
- finalize_command="$finalize_command $finalize_deplibs"
-
- if test -n "$rpath$xrpath"; then
- # If the user specified any rpath flags, then add them.
- for libdir in $rpath $xrpath; do
- # This is the magic to use -rpath.
- case "$finalize_rpath " in
- *" $libdir "*) ;;
- *) finalize_rpath="$finalize_rpath $libdir" ;;
- esac
- done
- fi
-
- # Now hardcode the library paths
- rpath=
- hardcode_libdirs=
- for libdir in $compile_rpath $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$perm_rpath " in
- *" $libdir "*) ;;
- *) perm_rpath="$perm_rpath $libdir" ;;
- esac
- fi
- case $host in
- *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
- testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
- case :$dllsearchpath: in
- *":$libdir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$libdir";;
- esac
- case :$dllsearchpath: in
- *":$testbindir:"*) ;;
- *) dllsearchpath="$dllsearchpath:$testbindir";;
- esac
- ;;
- esac
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- compile_rpath="$rpath"
-
- rpath=
- hardcode_libdirs=
- for libdir in $finalize_rpath; do
- if test -n "$hardcode_libdir_flag_spec"; then
- if test -n "$hardcode_libdir_separator"; then
- if test -z "$hardcode_libdirs"; then
- hardcode_libdirs="$libdir"
- else
- # Just accumulate the unique libdirs.
- case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
- *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
- ;;
- *)
- hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
- ;;
- esac
- fi
- else
- eval flag=\"$hardcode_libdir_flag_spec\"
- rpath="$rpath $flag"
- fi
- elif test -n "$runpath_var"; then
- case "$finalize_perm_rpath " in
- *" $libdir "*) ;;
- *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
- esac
- fi
- done
- # Substitute the hardcoded libdirs into the rpath.
- if test -n "$hardcode_libdir_separator" &&
- test -n "$hardcode_libdirs"; then
- libdir="$hardcode_libdirs"
- eval rpath=\" $hardcode_libdir_flag_spec\"
- fi
- finalize_rpath="$rpath"
-
- if test -n "$libobjs" && test "$build_old_libs" = yes; then
- # Transform all the library objects into standard objects.
- compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- fi
-
- dlsyms=
- if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
- if test -n "$NM" && test -n "$global_symbol_pipe"; then
- dlsyms="${outputname}S.c"
- else
- $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
- fi
- fi
-
- if test -n "$dlsyms"; then
- case $dlsyms in
- "") ;;
- *.c)
- # Discover the nlist of each of the dlfiles.
- nlist="$output_objdir/${outputname}.nm"
-
- $show "$rm $nlist ${nlist}S ${nlist}T"
- $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
- # Parse the name list into a source file.
- $show "creating $output_objdir/$dlsyms"
-
- test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
- if test "$dlself" = yes; then
- $show "generating symbol list for \`$output'"
-
- test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
- # Add our own program objects to the symbol list.
- progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
- for arg in $progfiles; do
- $show "extracting global C symbols from \`$arg'"
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -n "$exclude_expsyms"; then
- $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- if test -n "$export_symbols_regex"; then
- $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
- $run eval '$mv "$nlist"T "$nlist"'
- fi
-
- # Prepare the list of exported symbols
- if test -z "$export_symbols"; then
- export_symbols="$output_objdir/$outputname.exp"
- $run $rm $export_symbols
- $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
- case $host in
- *cygwin* | *mingw* )
- $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
- $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
- ;;
- esac
- else
- $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
- $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
- $run eval 'mv "$nlist"T "$nlist"'
- case $host in
- *cygwin* | *mingw* )
- $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
- $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
- ;;
- esac
- fi
- fi
-
- for arg in $dlprefiles; do
- $show "extracting global C symbols from \`$arg'"
- name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
- $run eval '$echo ": $name " >> "$nlist"'
- $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
- done
-
- if test -z "$run"; then
- # Make sure we have at least an empty file.
- test -f "$nlist" || : > "$nlist"
-
- if test -n "$exclude_expsyms"; then
- $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
- $mv "$nlist"T "$nlist"
- fi
-
- # Try sorting and uniquifying the output.
- if grep -v "^: " < "$nlist" |
- if sort -k 3 </dev/null >/dev/null 2>&1; then
- sort -k 3
- else
- sort +2
- fi |
- uniq > "$nlist"S; then
- :
- else
- grep -v "^: " < "$nlist" > "$nlist"S
- fi
-
- if test -f "$nlist"S; then
- eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
- else
- $echo '/* NONE */' >> "$output_objdir/$dlsyms"
- fi
-
- $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr void *
-#else
-# define lt_ptr char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-"
-
- case $host in
- *cygwin* | *mingw* )
- $echo >> "$output_objdir/$dlsyms" "\
-/* DATA imports from DLLs on WIN32 can't be const, because
- runtime relocations are performed -- see ld's documentation
- on pseudo-relocs */
-struct {
-"
- ;;
- * )
- $echo >> "$output_objdir/$dlsyms" "\
-const struct {
-"
- ;;
- esac
-
-
- $echo >> "$output_objdir/$dlsyms" "\
- const char *name;
- lt_ptr address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
- eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
-
- $echo >> "$output_objdir/$dlsyms" "\
- {0, (lt_ptr) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
- return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
- fi
-
- pic_flag_for_symtable=
- case $host in
- # compiling the symbol table file with pic_flag works around
- # a FreeBSD bug that causes programs to crash when -lm is
- # linked before any other PIC object. But we must not use
- # pic_flag when linking with -static. The problem exists in
- # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
- *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
- esac;;
- *-*-hpux*)
- case "$compile_command " in
- *" -static "*) ;;
- *) pic_flag_for_symtable=" $pic_flag";;
- esac
- esac
-
- # Now compile the dynamic symbol file.
- $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
- $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
- # Clean up the generated files.
- $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
- $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
- # Transform the symbol file into the correct name.
- case $host in
- *cygwin* | *mingw* )
- if test -f "$output_objdir/${outputname}.def" ; then
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
- else
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- fi
- ;;
- * )
- compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
- ;;
- esac
- ;;
- *)
- $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- else
- # We keep going just in case the user didn't refer to
- # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
- # really was required.
-
- # Nullify the symbol file.
- compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
- finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
- fi
-
- if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
- # Replace the output file specification.
- compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- link_command="$compile_command$compile_rpath"
-
- # We have no uninstalled library dependencies, so finalize right now.
- $show "$link_command"
- $run eval "$link_command"
- exit_status=$?
-
- # Delete the generated files.
- if test -n "$dlsyms"; then
- $show "$rm $output_objdir/${outputname}S.${objext}"
- $run $rm "$output_objdir/${outputname}S.${objext}"
- fi
-
- exit $exit_status
- fi
-
- if test -n "$shlibpath_var"; then
- # We should set the shlibpath_var
- rpath=
- for dir in $temp_rpath; do
- case $dir in
- [\\/]* | [A-Za-z]:[\\/]*)
- # Absolute path.
- rpath="$rpath$dir:"
- ;;
- *)
- # Relative path: add a thisdir entry.
- rpath="$rpath\$thisdir/$dir:"
- ;;
- esac
- done
- temp_rpath="$rpath"
- fi
-
- if test -n "$compile_shlibpath$finalize_shlibpath"; then
- compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
- fi
- if test -n "$finalize_shlibpath"; then
- finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
- fi
-
- compile_var=
- finalize_var=
- if test -n "$runpath_var"; then
- if test -n "$perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $perm_rpath; do
- rpath="$rpath$dir:"
- done
- compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- if test -n "$finalize_perm_rpath"; then
- # We should set the runpath_var.
- rpath=
- for dir in $finalize_perm_rpath; do
- rpath="$rpath$dir:"
- done
- finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
- fi
- fi
-
- if test "$no_install" = yes; then
- # We don't need to create a wrapper script.
- link_command="$compile_var$compile_command$compile_rpath"
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
- # Delete the old output file.
- $run $rm $output
- # Link the executable and exit
- $show "$link_command"
- $run eval "$link_command" || exit $?
- exit $EXIT_SUCCESS
- fi
-
- if test "$hardcode_action" = relink; then
- # Fast installation is not supported
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
-
- $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
- $echo "$modename: \`$output' will be relinked during installation" 1>&2
- else
- if test "$fast_install" != no; then
- link_command="$finalize_var$compile_command$finalize_rpath"
- if test "$fast_install" = yes; then
- relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
- else
- # fast_install is set to needless
- relink_command=
- fi
- else
- link_command="$compile_var$compile_command$compile_rpath"
- relink_command="$finalize_var$finalize_command$finalize_rpath"
- fi
- fi
-
- # Replace the output file specification.
- link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
- # Delete the old output files.
- $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
- $show "$link_command"
- $run eval "$link_command" || exit $?
-
- # Now create the wrapper script.
- $show "creating $output"
-
- # Quote the relink command for shipping.
- if test -n "$relink_command"; then
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
- relink_command="$var=\"$var_value\"; export $var; $relink_command"
- fi
- done
- relink_command="(cd `pwd`; $relink_command)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Quote $echo for shipping.
- if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
- case $progpath in
- [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
- *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
- esac
- qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
- else
- qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
- fi
-
- # Only actually do things if our run command is non-null.
- if test -z "$run"; then
- # win32 will think the script is a binary if it has
- # a .exe suffix, so we strip it off here.
- case $output in
- *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
- esac
- # test for cygwin because mv fails w/o .exe extensions
- case $host in
- *cygwin*)
- exeext=.exe
- outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
- *) exeext= ;;
- esac
- case $host in
- *cygwin* | *mingw* )
- output_name=`basename $output`
- output_path=`dirname $output`
- cwrappersource="$output_path/$objdir/lt-$output_name.c"
- cwrapper="$output_path/$output_name.exe"
- $rm $cwrappersource $cwrapper
- trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
-
- cat > $cwrappersource <<EOF
-
-/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
- Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-
- The $output program cannot be directly executed until all the libtool
- libraries that it depends on are installed.
-
- This wrapper executable should never be moved out of the build directory.
- If it is, it will not operate correctly.
-
- Currently, it simply execs the wrapper *script* "/bin/sh $output",
- but could eventually absorb all of the scripts functionality and
- exec $objdir/$outputname directly.
-*/
-EOF
- cat >> $cwrappersource<<"EOF"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/stat.h>
-
-#if defined(PATH_MAX)
-# define LT_PATHMAX PATH_MAX
-#elif defined(MAXPATHLEN)
-# define LT_PATHMAX MAXPATHLEN
-#else
-# define LT_PATHMAX 1024
-#endif
-
-#ifndef DIR_SEPARATOR
-# define DIR_SEPARATOR '/'
-# define PATH_SEPARATOR ':'
-#endif
-
-#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
- defined (__OS2__)
-# define HAVE_DOS_BASED_FILE_SYSTEM
-# ifndef DIR_SEPARATOR_2
-# define DIR_SEPARATOR_2 '\\'
-# endif
-# ifndef PATH_SEPARATOR_2
-# define PATH_SEPARATOR_2 ';'
-# endif
-#endif
-
-#ifndef DIR_SEPARATOR_2
-# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-#else /* DIR_SEPARATOR_2 */
-# define IS_DIR_SEPARATOR(ch) \
- (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-#endif /* DIR_SEPARATOR_2 */
-
-#ifndef PATH_SEPARATOR_2
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
-#else /* PATH_SEPARATOR_2 */
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
-#endif /* PATH_SEPARATOR_2 */
-
-#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
-#define XFREE(stale) do { \
- if (stale) { free ((void *) stale); stale = 0; } \
-} while (0)
-
-/* -DDEBUG is fairly common in CFLAGS. */
-#undef DEBUG
-#if defined DEBUGWRAPPER
-# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
-#else
-# define DEBUG(format, ...)
-#endif
-
-const char *program_name = NULL;
-
-void * xmalloc (size_t num);
-char * xstrdup (const char *string);
-const char * base_name (const char *name);
-char * find_executable(const char *wrapper);
-int check_executable(const char *path);
-char * strendzap(char *str, const char *pat);
-void lt_fatal (const char *message, ...);
-
-int
-main (int argc, char *argv[])
-{
- char **newargz;
- int i;
-
- program_name = (char *) xstrdup (base_name (argv[0]));
- DEBUG("(main) argv[0] : %s\n",argv[0]);
- DEBUG("(main) program_name : %s\n",program_name);
- newargz = XMALLOC(char *, argc+2);
-EOF
-
- cat >> $cwrappersource <<EOF
- newargz[0] = (char *) xstrdup("$SHELL");
-EOF
-
- cat >> $cwrappersource <<"EOF"
- newargz[1] = find_executable(argv[0]);
- if (newargz[1] == NULL)
- lt_fatal("Couldn't find %s", argv[0]);
- DEBUG("(main) found exe at : %s\n",newargz[1]);
- /* we know the script has the same name, without the .exe */
- /* so make sure newargz[1] doesn't end in .exe */
- strendzap(newargz[1],".exe");
- for (i = 1; i < argc; i++)
- newargz[i+1] = xstrdup(argv[i]);
- newargz[argc+1] = NULL;
-
- for (i=0; i<argc+1; i++)
- {
- DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
- ;
- }
-
-EOF
-
- case $host_os in
- mingw*)
- cat >> $cwrappersource <<EOF
- execv("$SHELL",(char const **)newargz);
-EOF
- ;;
- *)
- cat >> $cwrappersource <<EOF
- execv("$SHELL",newargz);
-EOF
- ;;
- esac
-
- cat >> $cwrappersource <<"EOF"
- return 127;
-}
-
-void *
-xmalloc (size_t num)
-{
- void * p = (void *) malloc (num);
- if (!p)
- lt_fatal ("Memory exhausted");
-
- return p;
-}
-
-char *
-xstrdup (const char *string)
-{
- return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
-;
-}
-
-const char *
-base_name (const char *name)
-{
- const char *base;
-
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- /* Skip over the disk name in MSDOS pathnames. */
- if (isalpha ((unsigned char)name[0]) && name[1] == ':')
- name += 2;
-#endif
-
- for (base = name; *name; name++)
- if (IS_DIR_SEPARATOR (*name))
- base = name + 1;
- return base;
-}
-
-int
-check_executable(const char * path)
-{
- struct stat st;
-
- DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
- if ((!path) || (!*path))
- return 0;
-
- if ((stat (path, &st) >= 0) &&
- (
- /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
-#if defined (S_IXOTH)
- ((st.st_mode & S_IXOTH) == S_IXOTH) ||
-#endif
-#if defined (S_IXGRP)
- ((st.st_mode & S_IXGRP) == S_IXGRP) ||
-#endif
- ((st.st_mode & S_IXUSR) == S_IXUSR))
- )
- return 1;
- else
- return 0;
-}
-
-/* Searches for the full path of the wrapper. Returns
- newly allocated full path name if found, NULL otherwise */
-char *
-find_executable (const char* wrapper)
-{
- int has_slash = 0;
- const char* p;
- const char* p_next;
- /* static buffer for getcwd */
- char tmp[LT_PATHMAX + 1];
- int tmp_len;
- char* concat_name;
-
- DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
-
- if ((wrapper == NULL) || (*wrapper == '\0'))
- return NULL;
-
- /* Absolute path? */
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
- {
- concat_name = xstrdup (wrapper);
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- }
- else
- {
-#endif
- if (IS_DIR_SEPARATOR (wrapper[0]))
- {
- concat_name = xstrdup (wrapper);
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- }
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
- }
-#endif
-
- for (p = wrapper; *p; p++)
- if (*p == '/')
- {
- has_slash = 1;
- break;
- }
- if (!has_slash)
- {
- /* no slashes; search PATH */
- const char* path = getenv ("PATH");
- if (path != NULL)
- {
- for (p = path; *p; p = p_next)
- {
- const char* q;
- size_t p_len;
- for (q = p; *q; q++)
- if (IS_PATH_SEPARATOR(*q))
- break;
- p_len = q - p;
- p_next = (*q == '\0' ? q : q + 1);
- if (p_len == 0)
- {
- /* empty path: current directory */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- tmp_len = strlen(tmp);
- concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
- memcpy (concat_name, tmp, tmp_len);
- concat_name[tmp_len] = '/';
- strcpy (concat_name + tmp_len + 1, wrapper);
- }
- else
- {
- concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
- memcpy (concat_name, p, p_len);
- concat_name[p_len] = '/';
- strcpy (concat_name + p_len + 1, wrapper);
- }
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- }
- }
- /* not found in PATH; assume curdir */
- }
- /* Relative path | not found in path: prepend cwd */
- if (getcwd (tmp, LT_PATHMAX) == NULL)
- lt_fatal ("getcwd failed");
- tmp_len = strlen(tmp);
- concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
- memcpy (concat_name, tmp, tmp_len);
- concat_name[tmp_len] = '/';
- strcpy (concat_name + tmp_len + 1, wrapper);
-
- if (check_executable(concat_name))
- return concat_name;
- XFREE(concat_name);
- return NULL;
-}
-
-char *
-strendzap(char *str, const char *pat)
-{
- size_t len, patlen;
-
- assert(str != NULL);
- assert(pat != NULL);
-
- len = strlen(str);
- patlen = strlen(pat);
-
- if (patlen <= len)
- {
- str += len - patlen;
- if (strcmp(str, pat) == 0)
- *str = '\0';
- }
- return str;
-}
-
-static void
-lt_error_core (int exit_status, const char * mode,
- const char * message, va_list ap)
-{
- fprintf (stderr, "%s: %s: ", program_name, mode);
- vfprintf (stderr, message, ap);
- fprintf (stderr, ".\n");
-
- if (exit_status >= 0)
- exit (exit_status);
-}
-
-void
-lt_fatal (const char *message, ...)
-{
- va_list ap;
- va_start (ap, message);
- lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
- va_end (ap);
-}
-EOF
- # we should really use a build-platform specific compiler
- # here, but OTOH, the wrappers (shell script and this C one)
- # are only useful if you want to execute the "real" binary.
- # Since the "real" binary is built for $host, then this
- # wrapper might as well be built for $host, too.
- $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
- ;;
- esac
- $rm $output
- trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
-
- $echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting. It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='${SED} -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
- # install mode needs the following variable:
- notinst_deplibs='$notinst_deplibs'
-else
- # When we are sourced in execute mode, \$file and \$echo are already set.
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- echo=\"$qecho\"
- file=\"\$0\"
- # Make sure echo works.
- if test \"X\$1\" = X--no-reexec; then
- # Discard the --no-reexec flag, and continue.
- shift
- elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
- # Yippee, \$echo works!
- :
- else
- # Restart under the correct shell, and then maybe \$echo will work.
- exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
- fi
- fi\
-"
- $echo >> $output "\
-
- # Find the directory that this script lives in.
- thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
- test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
- # Follow symbolic links until we get to the real thisdir.
- file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
- while test -n \"\$file\"; do
- destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
- # If there was a directory component, then change thisdir.
- if test \"x\$destdir\" != \"x\$file\"; then
- case \"\$destdir\" in
- [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
- *) thisdir=\"\$thisdir/\$destdir\" ;;
- esac
- fi
-
- file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
- file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
- done
-
- # Try to get the absolute directory name.
- absdir=\`cd \"\$thisdir\" && pwd\`
- test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
- if test "$fast_install" = yes; then
- $echo >> $output "\
- program=lt-'$outputname'$exeext
- progdir=\"\$thisdir/$objdir\"
-
- if test ! -f \"\$progdir/\$program\" || \\
- { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
- test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
- file=\"\$\$-\$program\"
-
- if test ! -d \"\$progdir\"; then
- $mkdir \"\$progdir\"
- else
- $rm \"\$progdir/\$file\"
- fi"
-
- $echo >> $output "\
-
- # relink executable if necessary
- if test -n \"\$relink_command\"; then
- if relink_command_output=\`eval \$relink_command 2>&1\`; then :
- else
- $echo \"\$relink_command_output\" >&2
- $rm \"\$progdir/\$file\"
- exit $EXIT_FAILURE
- fi
- fi
-
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
- { $rm \"\$progdir/\$program\";
- $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
- $rm \"\$progdir/\$file\"
- fi"
- else
- $echo >> $output "\
- program='$outputname'
- progdir=\"\$thisdir/$objdir\"
-"
- fi
-
- $echo >> $output "\
-
- if test -f \"\$progdir/\$program\"; then"
-
- # Export our shlibpath_var if we have one.
- if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
- $echo >> $output "\
- # Add our own library path to $shlibpath_var
- $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
- # Some systems cannot cope with colon-terminated $shlibpath_var
- # The second colon is a workaround for a bug in BeOS R4 sed
- $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
- export $shlibpath_var
-"
- fi
-
- # fixup the dll searchpath if we need to.
- if test -n "$dllsearchpath"; then
- $echo >> $output "\
- # Add the dll search path components to the executable PATH
- PATH=$dllsearchpath:\$PATH
-"
- fi
-
- $echo >> $output "\
- if test \"\$libtool_execute_magic\" != \"$magic\"; then
- # Run the actual program with our arguments.
-
- # Make sure env LD_LIBRARY_PATH does not mess us up
- if test -n \"\${LD_LIBRARY_PATH+set}\"; then
- export LD_LIBRARY_PATH=\$progdir:\$LD_LIBRARY_PATH
- fi
-"
- case $host in
- # Backslashes separate directories on plain windows
- *-*-mingw | *-*-os2*)
- $echo >> $output "\
- exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
-"
- ;;
-
- *)
- $echo >> $output "\
- exec \"\$progdir/\$program\" \${1+\"\$@\"}
-"
- ;;
- esac
- $echo >> $output "\
- \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
- exit $EXIT_FAILURE
- fi
- else
- # The program doesn't exist.
- \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
- \$echo \"This script is just a wrapper for \$program.\" 1>&2
- $echo \"See the $PACKAGE documentation for more information.\" 1>&2
- exit $EXIT_FAILURE
- fi
-fi\
-"
- chmod +x $output
- fi
- exit $EXIT_SUCCESS
- ;;
- esac
-
- # See if we need to build an old-fashioned archive.
- for oldlib in $oldlibs; do
-
- if test "$build_libtool_libs" = convenience; then
- oldobjs="$libobjs_save"
- addlibs="$convenience"
- build_libtool_libs=no
- else
- if test "$build_libtool_libs" = module; then
- oldobjs="$libobjs_save"
- build_libtool_libs=no
- else
- oldobjs="$old_deplibs $non_pic_objects"
- fi
- addlibs="$old_convenience"
- fi
-
- if test -n "$addlibs"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- func_extract_archives $gentop $addlibs
- oldobjs="$oldobjs $func_extract_archives_result"
- fi
-
- # Do each command in the archive commands.
- if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
- cmds=$old_archive_from_new_cmds
- else
- # POSIX demands no paths to be encoded in archives. We have
- # to avoid creating archives with duplicate basenames if we
- # might have to extract them afterwards, e.g., when creating a
- # static archive out of a convenience library, or when linking
- # the entirety of a libtool archive into another (currently
- # not supported by libtool).
- if (for obj in $oldobjs
- do
- $echo "X$obj" | $Xsed -e 's%^.*/%%'
- done | sort | sort -uc >/dev/null 2>&1); then
- :
- else
- $echo "copying selected object files to avoid basename conflicts..."
-
- if test -z "$gentop"; then
- gentop="$output_objdir/${outputname}x"
- generated="$generated $gentop"
-
- $show "${rm}r $gentop"
- $run ${rm}r "$gentop"
- $show "$mkdir $gentop"
- $run $mkdir "$gentop"
- exit_status=$?
- if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
- exit $exit_status
- fi
- fi
-
- save_oldobjs=$oldobjs
- oldobjs=
- counter=1
- for obj in $save_oldobjs
- do
- objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
- case " $oldobjs " in
- " ") oldobjs=$obj ;;
- *[\ /]"$objbase "*)
- while :; do
- # Make sure we don't pick an alternate name that also
- # overlaps.
- newobj=lt$counter-$objbase
- counter=`expr $counter + 1`
- case " $oldobjs " in
- *[\ /]"$newobj "*) ;;
- *) if test ! -f "$gentop/$newobj"; then break; fi ;;
- esac
- done
- $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
- $run ln "$obj" "$gentop/$newobj" ||
- $run cp "$obj" "$gentop/$newobj"
- oldobjs="$oldobjs $gentop/$newobj"
- ;;
- *) oldobjs="$oldobjs $obj" ;;
- esac
- done
- fi
-
- eval cmds=\"$old_archive_cmds\"
-
- if len=`expr "X$cmds" : ".*"` &&
- test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
- cmds=$old_archive_cmds
- else
- # the command line is too long to link in one step, link in parts
- $echo "using piecewise archive linking..."
- save_RANLIB=$RANLIB
- RANLIB=:
- objlist=
- concat_cmds=
- save_oldobjs=$oldobjs
-
- # Is there a better way of finding the last object in the list?
- for obj in $save_oldobjs
- do
- last_oldobj=$obj
- done
- for obj in $save_oldobjs
- do
- oldobjs="$objlist $obj"
- objlist="$objlist $obj"
- eval test_cmds=\"$old_archive_cmds\"
- if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
- test "$len" -le "$max_cmd_len"; then
- :
- else
- # the above command should be used before it gets too long
- oldobjs=$objlist
- if test "$obj" = "$last_oldobj" ; then
- RANLIB=$save_RANLIB
- fi
- test -z "$concat_cmds" || concat_cmds=$concat_cmds~
- eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
- objlist=
- fi
- done
- RANLIB=$save_RANLIB
- oldobjs=$objlist
- if test "X$oldobjs" = "X" ; then
- eval cmds=\"\$concat_cmds\"
- else
- eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
- fi
- fi
- fi
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- eval cmd=\"$cmd\"
- IFS="$save_ifs"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$generated"; then
- $show "${rm}r$generated"
- $run ${rm}r$generated
- fi
-
- # Now create the libtool archive.
- case $output in
- *.la)
- old_library=
- test "$build_old_libs" = yes && old_library="$libname.$libext"
- $show "creating $output"
-
- # Preserve any variables that may affect compiler behavior
- for var in $variables_saved_for_relink; do
- if eval test -z \"\${$var+set}\"; then
- relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
- elif eval var_value=\$$var; test -z "$var_value"; then
- relink_command="$var=; export $var; $relink_command"
- else
- var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
- relink_command="$var=\"$var_value\"; export $var; $relink_command"
- fi
- done
- # Quote the link command for shipping.
- relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
- if test "$hardcode_automatic" = yes ; then
- relink_command=
- fi
-
-
- # Only create the output if not a dry run.
- if test -z "$run"; then
- for installed in no yes; do
- if test "$installed" = yes; then
- if test -z "$install_libdir"; then
- break
- fi
- output="$output_objdir/$outputname"i
- # Replace all uninstalled libtool libraries with the installed ones
- newdependency_libs=
- for deplib in $dependency_libs; do
- case $deplib in
- *.la)
- name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
- if test -z "$libdir"; then
- $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- if test "X$EGREP" = X ; then
- EGREP=egrep
- fi
- # We do not want portage's install root ($D) present. Check only for
- # this if the .la is being installed.
- if test "$installed" = yes && test "$D"; then
- eval mynewdependency_lib=`echo "$libdir/$name" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
- else
- mynewdependency_lib="$libdir/$name"
- fi
- # Do not add duplicates
- if test "$mynewdependency_lib"; then
- my_little_ninja_foo_1=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"`
- if test -z "$my_little_ninja_foo_1"; then
- newdependency_libs="$newdependency_libs $mynewdependency_lib"
- fi
- fi
- ;;
- *)
- if test "$installed" = yes; then
- # Rather use S=WORKDIR if our version of portage supports it.
- # This is because some ebuild (gcc) do not use $S as buildroot.
- if test "$PWORKDIR"; then
- S="$PWORKDIR"
- fi
- # We do not want portage's build root ($S) present.
- my_little_ninja_foo_2=`echo $deplib |$EGREP -e "$S"`
- # We do not want portage's install root ($D) present.
- my_little_ninja_foo_3=`echo $deplib |$EGREP -e "$D"`
- if test -n "$my_little_ninja_foo_2" && test "$S"; then
- mynewdependency_lib=""
- elif test -n "$my_little_ninja_foo_3" && test "$D"; then
- eval mynewdependency_lib=`echo "$deplib" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
- else
- mynewdependency_lib="$deplib"
- fi
- else
- mynewdependency_lib="$deplib"
- fi
- # Do not add duplicates
- if test "$mynewdependency_lib"; then
- my_little_ninja_foo_4=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"`
- if test -z "$my_little_ninja_foo_4"; then
- newdependency_libs="$newdependency_libs $mynewdependency_lib"
- fi
- fi
- ;;
- esac
- done
- dependency_libs="$newdependency_libs"
- newdlfiles=
- for lib in $dlfiles; do
- name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- newdlfiles="$newdlfiles $libdir/$name"
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
- eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
- if test -z "$libdir"; then
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- exit $EXIT_FAILURE
- fi
- newdlprefiles="$newdlprefiles $libdir/$name"
- done
- dlprefiles="$newdlprefiles"
- else
- newdlfiles=
- for lib in $dlfiles; do
- case $lib in
- [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
- *) abs=`pwd`"/$lib" ;;
- esac
- newdlfiles="$newdlfiles $abs"
- done
- dlfiles="$newdlfiles"
- newdlprefiles=
- for lib in $dlprefiles; do
- case $lib in
- [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
- *) abs=`pwd`"/$lib" ;;
- esac
- newdlprefiles="$newdlprefiles $abs"
- done
- dlprefiles="$newdlprefiles"
- fi
- $rm $output
- # place dlname in correct position for cygwin
- tdlname=$dlname
- case $host,$output,$installed,$module,$dlname in
- *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
- esac
- # Do not add duplicates
- if test "$installed" = yes && test "$D"; then
- install_libdir=`echo "$install_libdir" |sed -e "s:$D:/:g" -e 's:/\+:/:g'`
- fi
- $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$tdlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Should we warn about portability when linking against -modules?
-shouldnotlink=$module
-
-# Files to dlopen/dlpreopen
-dlopen='$dlfiles'
-dlpreopen='$dlprefiles'
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'"
- if test "$installed" = no && test "$need_relink" = yes; then
- $echo >> $output "\
-relink_command=\"$relink_command\""
- fi
- done
- fi
-
- # Do a symbolic link so that the libtool archive can be found in
- # LD_LIBRARY_PATH before the program is installed.
- $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
- $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
- ;;
- esac
- exit $EXIT_SUCCESS
- ;;
-
- # libtool install mode
- install)
- modename="$modename: install"
-
- # There may be an optional sh(1) argument at the beginning of
- # install_prog (especially on Windows NT).
- if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
- # Allow the use of GNU shtool's install command.
- $echo "X$nonopt" | grep shtool > /dev/null; then
- # Aesthetically quote it.
- arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- install_prog="$arg "
- arg="$1"
- shift
- else
- install_prog=
- arg=$nonopt
- fi
-
- # The real first argument should be the name of the installation program.
- # Aesthetically quote it.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog$arg"
-
- # We need to accept at least all the BSD install flags.
- dest=
- files=
- opts=
- prev=
- install_type=
- isdir=no
- stripme=
- for arg
- do
- if test -n "$dest"; then
- files="$files $dest"
- dest=$arg
- continue
- fi
-
- case $arg in
- -d) isdir=yes ;;
- -f)
- case " $install_prog " in
- *[\\\ /]cp\ *) ;;
- *) prev=$arg ;;
- esac
- ;;
- -g | -m | -o) prev=$arg ;;
- -s)
- stripme=" -s"
- continue
- ;;
- -*)
- ;;
- *)
- # If the previous option needed an argument, then skip it.
- if test -n "$prev"; then
- prev=
- else
- dest=$arg
- continue
- fi
- ;;
- esac
-
- # Aesthetically quote the argument.
- arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
- case $arg in
- *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
- arg="\"$arg\""
- ;;
- esac
- install_prog="$install_prog $arg"
- done
-
- if test -z "$install_prog"; then
- $echo "$modename: you must specify an install program" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test -n "$prev"; then
- $echo "$modename: the \`$prev' option requires an argument" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test -z "$files"; then
- if test -z "$dest"; then
- $echo "$modename: no file or destination specified" 1>&2
- else
- $echo "$modename: you must specify a destination" 1>&2
- fi
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Strip any trailing slash from the destination.
- dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
- # Check to see that the destination is a directory.
- test -d "$dest" && isdir=yes
- if test "$isdir" = yes; then
- destdir="$dest"
- destname=
- else
- destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
- test "X$destdir" = "X$dest" && destdir=.
- destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
- # Not a directory, so check to see that there is only one file specified.
- set dummy $files
- if test "$#" -gt 2; then
- $echo "$modename: \`$dest' is not a directory" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
- fi
- case $destdir in
- [\\/]* | [A-Za-z]:[\\/]*) ;;
- *)
- for file in $files; do
- case $file in
- *.lo) ;;
- *)
- $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
- done
- ;;
- esac
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- staticlibs=
- future_libdirs=
- current_libdirs=
- for file in $files; do
-
- # Do each installation.
- case $file in
- *.$libext)
- # Do the static libraries later.
- staticlibs="$staticlibs $file"
- ;;
-
- *.la)
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- library_names=
- old_library=
- relink_command=
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Add the libdir to current_libdirs if it is the destination.
- if test "X$destdir" = "X$libdir"; then
- case "$current_libdirs " in
- *" $libdir "*) ;;
- *) current_libdirs="$current_libdirs $libdir" ;;
- esac
- else
- # Note the libdir as a future libdir.
- case "$future_libdirs " in
- *" $libdir "*) ;;
- *) future_libdirs="$future_libdirs $libdir" ;;
- esac
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
- test "X$dir" = "X$file/" && dir=
- dir="$dir$objdir"
-
- if test -n "$relink_command"; then
- # Determine the prefix the user has applied to our future dir.
- inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
-
- # Don't allow the user to place us outside of our expected
- # location b/c this prevents finding dependent libraries that
- # are installed to the same prefix.
- # At present, this check doesn't affect windows .dll's that
- # are installed into $libdir/../bin (currently, that works fine)
- # but it's something to keep an eye on.
- if test "$inst_prefix_dir" = "$destdir"; then
- $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
- exit $EXIT_FAILURE
- fi
-
- if test -n "$inst_prefix_dir"; then
- # Stick the inst_prefix_dir data into the link command.
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
- else
- relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
- fi
-
- $echo "$modename: warning: relinking \`$file'" 1>&2
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- exit $EXIT_FAILURE
- fi
- fi
-
- # See the names of the shared library.
- set dummy $library_names
- if test -n "$2"; then
- realname="$2"
- shift
- shift
-
- srcname="$realname"
- test -n "$relink_command" && srcname="$realname"T
-
- # Install the shared library and build the symlinks.
- $show "$install_prog $dir/$srcname $destdir/$realname"
- $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
- if test -n "$stripme" && test -n "$striplib"; then
- $show "$striplib $destdir/$realname"
- $run eval "$striplib $destdir/$realname" || exit $?
- fi
-
- if test "$#" -gt 0; then
- # Delete the old symlinks, and create new ones.
- # Try `ln -sf' first, because the `ln' binary might depend on
- # the symlink we replace! Solaris /bin/ln does not understand -f,
- # so we also need to try rm && ln -s.
- for linkname
- do
- if test "$linkname" != "$realname"; then
- $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
- $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
- fi
- done
- fi
-
- # Do each command in the postinstall commands.
- lib="$destdir/$realname"
- cmds=$postinstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || {
- lt_exit=$?
-
- # Restore the uninstalled library and exit
- if test "$mode" = relink; then
- $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
- fi
-
- exit $lt_exit
- }
- done
- IFS="$save_ifs"
- fi
-
- # Install the pseudo-library for information purposes.
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- instname="$dir/$name"i
- $show "$install_prog $instname $destdir/$name"
- $run eval "$install_prog $instname $destdir/$name" || exit $?
-
- # Maybe install the static library, too.
- test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
- ;;
-
- *.lo)
- # Install (i.e. copy) a libtool object.
-
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # Deduce the name of the destination old-style object file.
- case $destfile in
- *.lo)
- staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
- ;;
- *.$objext)
- staticdest="$destfile"
- destfile=
- ;;
- *)
- $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- # Install the libtool object if requested.
- if test -n "$destfile"; then
- $show "$install_prog $file $destfile"
- $run eval "$install_prog $file $destfile" || exit $?
- fi
-
- # Install the old object if enabled.
- if test "$build_old_libs" = yes; then
- # Deduce the name of the old-style object file.
- staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
- $show "$install_prog $staticobj $staticdest"
- $run eval "$install_prog \$staticobj \$staticdest" || exit $?
- fi
- exit $EXIT_SUCCESS
- ;;
-
- *)
- # Figure out destination file name, if it wasn't already specified.
- if test -n "$destname"; then
- destfile="$destdir/$destname"
- else
- destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- destfile="$destdir/$destfile"
- fi
-
- # If the file is missing, and there is a .exe on the end, strip it
- # because it is most likely a libtool script we actually want to
- # install
- stripped_ext=""
- case $file in
- *.exe)
- if test ! -f "$file"; then
- file=`$echo $file|${SED} 's,.exe$,,'`
- stripped_ext=".exe"
- fi
- ;;
- esac
-
- # Do a test to see if this is really a libtool program.
- case $host in
- *cygwin*|*mingw*)
- wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
- ;;
- *)
- wrapper=$file
- ;;
- esac
- if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
- notinst_deplibs=
- relink_command=
-
- # Note that it is not necessary on cygwin/mingw to append a dot to
- # foo even if both foo and FILE.exe exist: automatic-append-.exe
- # behavior happens only for exec(3), not for open(2)! Also, sourcing
- # `FILE.' does not work on cygwin managed mounts.
- #
- # If there is no directory component, then add one.
- case $wrapper in
- */* | *\\*) . ${wrapper} ;;
- *) . ./${wrapper} ;;
- esac
-
- # Check the variables that should have been set.
- if test -z "$notinst_deplibs"; then
- $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
- exit $EXIT_FAILURE
- fi
-
- finalize=yes
- for lib in $notinst_deplibs; do
- # Check to see that each library is installed.
- libdir=
- if test -f "$lib"; then
- # If there is no directory component, then add one.
- case $lib in
- */* | *\\*) . $lib ;;
- *) . ./$lib ;;
- esac
- fi
- libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
- if test -n "$libdir" && test ! -f "$libfile"; then
- $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
- finalize=no
- fi
- done
-
- relink_command=
- # Note that it is not necessary on cygwin/mingw to append a dot to
- # foo even if both foo and FILE.exe exist: automatic-append-.exe
- # behavior happens only for exec(3), not for open(2)! Also, sourcing
- # `FILE.' does not work on cygwin managed mounts.
- #
- # If there is no directory component, then add one.
- case $wrapper in
- */* | *\\*) . ${wrapper} ;;
- *) . ./${wrapper} ;;
- esac
-
- outputname=
- if test "$fast_install" = no && test -n "$relink_command"; then
- if test "$finalize" = yes && test -z "$run"; then
- tmpdir=`func_mktempdir`
- file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
- outputname="$tmpdir/$file"
- # Replace the output file specification.
- relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
- $show "$relink_command"
- if $run eval "$relink_command"; then :
- else
- $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
- ${rm}r "$tmpdir"
- continue
- fi
- file="$outputname"
- else
- $echo "$modename: warning: cannot relink \`$file'" 1>&2
- fi
- else
- # Install the binary that we compiled earlier.
- file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
- fi
- fi
-
- # remove .exe since cygwin /usr/bin/install will append another
- # one anyway
- case $install_prog,$host in
- */usr/bin/install*,*cygwin*)
- case $file:$destfile in
- *.exe:*.exe)
- # this is ok
- ;;
- *.exe:*)
- destfile=$destfile.exe
- ;;
- *:*.exe)
- destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
- ;;
- esac
- ;;
- esac
- $show "$install_prog$stripme $file $destfile"
- $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
- test -n "$outputname" && ${rm}r "$tmpdir"
- ;;
- esac
- done
-
- for file in $staticlibs; do
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
- # Set up the ranlib parameters.
- oldlib="$destdir/$name"
-
- $show "$install_prog $file $oldlib"
- $run eval "$install_prog \$file \$oldlib" || exit $?
-
- if test -n "$stripme" && test -n "$old_striplib"; then
- $show "$old_striplib $oldlib"
- $run eval "$old_striplib $oldlib" || exit $?
- fi
-
- # Do each command in the postinstall commands.
- cmds=$old_postinstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || exit $?
- done
- IFS="$save_ifs"
- done
-
- if test -n "$future_libdirs"; then
- $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
- fi
-
- if test -n "$current_libdirs"; then
- # Maybe just do a dry run.
- test -n "$run" && current_libdirs=" -n$current_libdirs"
- exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
- else
- exit $EXIT_SUCCESS
- fi
- ;;
-
- # libtool finish mode
- finish)
- modename="$modename: finish"
- libdirs="$nonopt"
- admincmds=
-
- if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
- for dir
- do
- libdirs="$libdirs $dir"
- done
-
- for libdir in $libdirs; do
- if test -n "$finish_cmds"; then
- # Do each command in the finish commands.
- cmds=$finish_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd" || admincmds="$admincmds
- $cmd"
- done
- IFS="$save_ifs"
- fi
- if test -n "$finish_eval"; then
- # Do the single finish_eval.
- eval cmds=\"$finish_eval\"
- $run eval "$cmds" || admincmds="$admincmds
- $cmds"
- fi
- done
- fi
-
- # Exit here if they wanted silent mode.
- test "$show" = : && exit $EXIT_SUCCESS
-
- $echo "X----------------------------------------------------------------------" | $Xsed
- $echo "Libraries have been installed in:"
- for libdir in $libdirs; do
- $echo " $libdir"
- done
- $echo
- $echo "If you ever happen to want to link against installed libraries"
- $echo "in a given directory, LIBDIR, you must either use libtool, and"
- $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
- $echo "flag during linking and do at least one of the following:"
- if test -n "$shlibpath_var"; then
- $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
- $echo " during execution"
- fi
- if test -n "$runpath_var"; then
- $echo " - add LIBDIR to the \`$runpath_var' environment variable"
- $echo " during linking"
- fi
- if test -n "$hardcode_libdir_flag_spec"; then
- libdir=LIBDIR
- eval flag=\"$hardcode_libdir_flag_spec\"
-
- $echo " - use the \`$flag' linker flag"
- fi
- if test -n "$admincmds"; then
- $echo " - have your system administrator run these commands:$admincmds"
- fi
- if test -f /etc/ld.so.conf; then
- $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
- fi
- $echo
- $echo "See any operating system documentation about shared libraries for"
- $echo "more information, such as the ld(1) and ld.so(8) manual pages."
- $echo "X----------------------------------------------------------------------" | $Xsed
- exit $EXIT_SUCCESS
- ;;
-
- # libtool execute mode
- execute)
- modename="$modename: execute"
-
- # The first argument is the command name.
- cmd="$nonopt"
- if test -z "$cmd"; then
- $echo "$modename: you must specify a COMMAND" 1>&2
- $echo "$help"
- exit $EXIT_FAILURE
- fi
-
- # Handle -dlopen flags immediately.
- for file in $execute_dlfiles; do
- if test ! -f "$file"; then
- $echo "$modename: \`$file' is not a file" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- dir=
- case $file in
- *.la)
- # Check to see that this really is a libtool archive.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
- else
- $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- # Read the libtool library.
- dlname=
- library_names=
-
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Skip this library if it cannot be dlopened.
- if test -z "$dlname"; then
- # Warn if it was a shared library.
- test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
- continue
- fi
-
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
-
- if test -f "$dir/$objdir/$dlname"; then
- dir="$dir/$objdir"
- else
- $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
- exit $EXIT_FAILURE
- fi
- ;;
-
- *.lo)
- # Just add the directory containing the .lo file.
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- test "X$dir" = "X$file" && dir=.
- ;;
-
- *)
- $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
- continue
- ;;
- esac
-
- # Get the absolute pathname.
- absdir=`cd "$dir" && pwd`
- test -n "$absdir" && dir="$absdir"
-
- # Now add the directory to shlibpath_var.
- if eval "test -z \"\$$shlibpath_var\""; then
- eval "$shlibpath_var=\"\$dir\""
- else
- eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
- fi
- done
-
- # This variable tells wrapper scripts just to set shlibpath_var
- # rather than running their programs.
- libtool_execute_magic="$magic"
-
- # Check if any of the arguments is a wrapper script.
- args=
- for file
- do
- case $file in
- -*) ;;
- *)
- # Do a test to see if this is really a libtool program.
- if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- # If there is no directory component, then add one.
- case $file in
- */* | *\\*) . $file ;;
- *) . ./$file ;;
- esac
-
- # Transform arg to wrapped name.
- file="$progdir/$program"
- fi
- ;;
- esac
- # Quote arguments (to preserve shell metacharacters).
- file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
- args="$args \"$file\""
- done
-
- if test -z "$run"; then
- if test -n "$shlibpath_var"; then
- # Export the shlibpath_var.
- eval "export $shlibpath_var"
- fi
-
- # Restore saved environment variables
- if test "${save_LC_ALL+set}" = set; then
- LC_ALL="$save_LC_ALL"; export LC_ALL
- fi
- if test "${save_LANG+set}" = set; then
- LANG="$save_LANG"; export LANG
- fi
-
- # Now prepare to actually exec the command.
- exec_cmd="\$cmd$args"
- else
- # Display what would be done.
- if test -n "$shlibpath_var"; then
- eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
- $echo "export $shlibpath_var"
- fi
- $echo "$cmd$args"
- exit $EXIT_SUCCESS
- fi
- ;;
-
- # libtool clean and uninstall mode
- clean | uninstall)
- modename="$modename: $mode"
- rm="$nonopt"
- files=
- rmforce=
- exit_status=0
-
- # This variable tells wrapper scripts just to set variables rather
- # than running their programs.
- libtool_install_magic="$magic"
-
- for arg
- do
- case $arg in
- -f) rm="$rm $arg"; rmforce=yes ;;
- -*) rm="$rm $arg" ;;
- *) files="$files $arg" ;;
- esac
- done
-
- if test -z "$rm"; then
- $echo "$modename: you must specify an RM program" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- fi
-
- rmdirs=
-
- origobjdir="$objdir"
- for file in $files; do
- dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
- if test "X$dir" = "X$file"; then
- dir=.
- objdir="$origobjdir"
- else
- objdir="$dir/$origobjdir"
- fi
- name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
- test "$mode" = uninstall && objdir="$dir"
-
- # Remember objdir for removal later, being careful to avoid duplicates
- if test "$mode" = clean; then
- case " $rmdirs " in
- *" $objdir "*) ;;
- *) rmdirs="$rmdirs $objdir" ;;
- esac
- fi
-
- # Don't error if the file doesn't exist and rm -f was used.
- if (test -L "$file") >/dev/null 2>&1 \
- || (test -h "$file") >/dev/null 2>&1 \
- || test -f "$file"; then
- :
- elif test -d "$file"; then
- exit_status=1
- continue
- elif test "$rmforce" = yes; then
- continue
- fi
-
- rmfiles="$file"
-
- case $name in
- *.la)
- # Possibly a libtool archive, so verify it.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- . $dir/$name
-
- # Delete the libtool libraries and symlinks.
- for n in $library_names; do
- rmfiles="$rmfiles $objdir/$n"
- done
- test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-
- case "$mode" in
- clean)
- case " $library_names " in
- # " " in the beginning catches empty $dlname
- *" $dlname "*) ;;
- *) rmfiles="$rmfiles $objdir/$dlname" ;;
- esac
- test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
- ;;
- uninstall)
- if test -n "$library_names"; then
- # Do each command in the postuninstall commands.
- cmds=$postuninstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd"
- if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
-
- if test -n "$old_library"; then
- # Do each command in the old_postuninstall commands.
- cmds=$old_postuninstall_cmds
- save_ifs="$IFS"; IFS='~'
- for cmd in $cmds; do
- IFS="$save_ifs"
- eval cmd=\"$cmd\"
- $show "$cmd"
- $run eval "$cmd"
- if test "$?" -ne 0 && test "$rmforce" != yes; then
- exit_status=1
- fi
- done
- IFS="$save_ifs"
- fi
- # FIXME: should reinstall the best remaining shared library.
- ;;
- esac
- fi
- ;;
-
- *.lo)
- # Possibly a libtool object, so verify it.
- if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-
- # Read the .lo file
- . $dir/$name
-
- # Add PIC object to the list of files to remove.
- if test -n "$pic_object" \
- && test "$pic_object" != none; then
- rmfiles="$rmfiles $dir/$pic_object"
- fi
-
- # Add non-PIC object to the list of files to remove.
- if test -n "$non_pic_object" \
- && test "$non_pic_object" != none; then
- rmfiles="$rmfiles $dir/$non_pic_object"
- fi
- fi
- ;;
-
- *)
- if test "$mode" = clean ; then
- noexename=$name
- case $file in
- *.exe)
- file=`$echo $file|${SED} 's,.exe$,,'`
- noexename=`$echo $name|${SED} 's,.exe$,,'`
- # $file with .exe has already been added to rmfiles,
- # add $file without .exe
- rmfiles="$rmfiles $file"
- ;;
- esac
- # Do a test to see if this is a libtool program.
- if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
- relink_command=
- . $dir/$noexename
-
- # note $name still contains .exe if it was in $file originally
- # as does the version of $file that was added into $rmfiles
- rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
- if test "$fast_install" = yes && test -n "$relink_command"; then
- rmfiles="$rmfiles $objdir/lt-$name"
- fi
- if test "X$noexename" != "X$name" ; then
- rmfiles="$rmfiles $objdir/lt-${noexename}.c"
- fi
- fi
- fi
- ;;
- esac
- $show "$rm $rmfiles"
- $run $rm $rmfiles || exit_status=1
- done
- objdir="$origobjdir"
-
- # Try to remove the ${objdir}s in the directories where we deleted files
- for dir in $rmdirs; do
- if test -d "$dir"; then
- $show "rmdir $dir"
- $run rmdir $dir >/dev/null 2>&1
- fi
- done
-
- exit $exit_status
- ;;
-
- "")
- $echo "$modename: you must specify a MODE" 1>&2
- $echo "$generic_help" 1>&2
- exit $EXIT_FAILURE
- ;;
- esac
-
- if test -z "$exec_cmd"; then
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$generic_help" 1>&2
- exit $EXIT_FAILURE
- fi
-fi # test -z "$show_help"
-
-if test -n "$exec_cmd"; then
- eval exec $exec_cmd
- exit $EXIT_FAILURE
-fi
-
-# We need to display help for each of the modes.
-case $mode in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
- --config show all configuration variables
- --debug enable verbose shell tracing
--n, --dry-run display commands without modifying any files
- --features display basic configuration information and exit
- --finish same as \`--mode=finish'
- --help display this help message and exit
- --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
- --quiet same as \`--silent'
- --silent don't print informational messages
- --tag=TAG use configuration variables from tag TAG
- --version print version information
-
-MODE must be one of the following:
-
- clean remove files from the build directory
- compile compile a source file into a libtool object
- execute automatically set library path, then run a program
- finish complete the installation of libtool libraries
- install install libraries or executables
- link create a library or an executable
- uninstall remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE.
-
-Report bugs to <bug-libtool@gnu.org>."
- exit $EXIT_SUCCESS
- ;;
-
-clean)
- $echo \
-"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
-
-Remove files from the build directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, object or program, all the files associated
-with it are deleted. Otherwise, only FILE itself is deleted using RM."
- ;;
-
-compile)
- $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
- -o OUTPUT-FILE set the output file name to OUTPUT-FILE
- -prefer-pic try to building PIC objects only
- -prefer-non-pic try to building non-PIC objects only
- -static always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
- ;;
-
-execute)
- $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
- -dlopen FILE add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
- ;;
-
-finish)
- $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges. Use
-the \`--dry-run' option if you just want to see what would be executed."
- ;;
-
-install)
- $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command. The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
- ;;
-
-link)
- $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
- -all-static do not do any dynamic linking at all
- -avoid-version do not add a version suffix if possible
- -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
- -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
- -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
- -export-symbols SYMFILE
- try to export only the symbols listed in SYMFILE
- -export-symbols-regex REGEX
- try to export only the symbols matching REGEX
- -LLIBDIR search LIBDIR for required installed libraries
- -lNAME OUTPUT-FILE requires the installed library libNAME
- -module build a library that can dlopened
- -no-fast-install disable the fast-install mode
- -no-install link a not-installable executable
- -no-undefined declare that a library does not refer to external symbols
- -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
- -objectlist FILE Use a list of object files found in FILE to specify objects
- -precious-files-regex REGEX
- don't remove output files matching REGEX
- -release RELEASE specify package release information
- -rpath LIBDIR the created library will eventually be installed in LIBDIR
- -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
- -static do not do any dynamic linking of libtool libraries
- -version-info CURRENT[:REVISION[:AGE]]
- specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename. Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
- ;;
-
-uninstall)
- $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
- ;;
-
-*)
- $echo "$modename: invalid operation mode \`$mode'" 1>&2
- $echo "$help" 1>&2
- exit $EXIT_FAILURE
- ;;
-esac
-
-$echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit $?
-
-# The TAGs below are defined such that we never get into a situation
-# in which we disable both kinds of libraries. Given conflicting
-# choices, we go for a static library, that is the most portable,
-# since we can't tell whether shared libraries were disabled because
-# the user asked for that or because the platform doesn't support
-# them. This is particularly important on AIX, because we don't
-# support having both static and shared libraries enabled at the same
-# time on that platform, so we default to a shared-only configuration.
-# If a disable-shared tag is given, we'll fallback to a static-only
-# configuration. But we'll never go from static-only to shared-only.
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-disable_libs=shared
-# ### END LIBTOOL TAG CONFIG: disable-shared
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-disable_libs=static
-# ### END LIBTOOL TAG CONFIG: disable-static
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/tests/examplefiles/perlfunc.1 b/tests/examplefiles/perlfunc.1
index 43fcd88b..01413c99 100644
--- a/tests/examplefiles/perlfunc.1
+++ b/tests/examplefiles/perlfunc.1
@@ -3367,4505 +3367,4 @@ conversion assumes base 10.)
.IP "open \s-1FILEHANDLE\s0" 8
.IX Item "open FILEHANDLE"
.PD
-Opens the file whose filename is given by \s-1EXPR\s0, and associates it with
-\&\s-1FILEHANDLE\s0.
-.Sp
-(The following is a comprehensive reference to \fIopen()\fR: for a gentler
-introduction you may consider perlopentut.)
-.Sp
-If \s-1FILEHANDLE\s0 is an undefined scalar variable (or array or hash element)
-the variable is assigned a reference to a new anonymous filehandle,
-otherwise if \s-1FILEHANDLE\s0 is an expression, its value is used as the name of
-the real filehandle wanted. (This is considered a symbolic reference, so
-\&\f(CW\*(C`use strict 'refs'\*(C'\fR should \fInot\fR be in effect.)
-.Sp
-If \s-1EXPR\s0 is omitted, the scalar variable of the same name as the
-\&\s-1FILEHANDLE\s0 contains the filename. (Note that lexical variables\*(--those
-declared with \f(CW\*(C`my\*(C'\fR\-\-will not work for this purpose; so if you're
-using \f(CW\*(C`my\*(C'\fR, specify \s-1EXPR\s0 in your call to open.)
-.Sp
-If three or more arguments are specified then the mode of opening and
-the file name are separate. If \s-1MODE\s0 is \f(CW'<'\fR or nothing, the file
-is opened for input. If \s-1MODE\s0 is \f(CW'>'\fR, the file is truncated and
-opened for output, being created if necessary. If \s-1MODE\s0 is \f(CW'>>'\fR,
-the file is opened for appending, again being created if necessary.
-.Sp
-You can put a \f(CW'+'\fR in front of the \f(CW'>'\fR or \f(CW'<'\fR to
-indicate that you want both read and write access to the file; thus
-\&\f(CW'+<'\fR is almost always preferred for read/write updates\*(--the \f(CW'+>'\fR mode would clobber the file first. You can't usually use
-either read-write mode for updating textfiles, since they have
-variable length records. See the \fB\-i\fR switch in perlrun for a
-better approach. The file is created with permissions of \f(CW0666\fR
-modified by the process' \f(CW\*(C`umask\*(C'\fR value.
-.Sp
-These various prefixes correspond to the \fIfopen\fR\|(3) modes of \f(CW'r'\fR,
-\&\f(CW'r+'\fR, \f(CW'w'\fR, \f(CW'w+'\fR, \f(CW'a'\fR, and \f(CW'a+'\fR.
-.Sp
-In the 2\-arguments (and 1\-argument) form of the call the mode and
-filename should be concatenated (in this order), possibly separated by
-spaces. It is possible to omit the mode in these forms if the mode is
-\&\f(CW'<'\fR.
-.Sp
-If the filename begins with \f(CW'|'\fR, the filename is interpreted as a
-command to which output is to be piped, and if the filename ends with a
-\&\f(CW'|'\fR, the filename is interpreted as a command which pipes output to
-us. See \*(L"Using \fIopen()\fR for \s-1IPC\s0\*(R" in perlipc
-for more examples of this. (You are not allowed to \f(CW\*(C`open\*(C'\fR to a command
-that pipes both in \fIand\fR out, but see IPC::Open2, IPC::Open3,
-and \*(L"Bidirectional Communication with Another Process\*(R" in perlipc
-for alternatives.)
-.Sp
-For three or more arguments if \s-1MODE\s0 is \f(CW'|\-'\fR, the filename is
-interpreted as a command to which output is to be piped, and if \s-1MODE\s0
-is \f(CW'\-|'\fR, the filename is interpreted as a command which pipes
-output to us. In the 2\-arguments (and 1\-argument) form one should
-replace dash (\f(CW'\-'\fR) with the command.
-See \*(L"Using \fIopen()\fR for \s-1IPC\s0\*(R" in perlipc for more examples of this.
-(You are not allowed to \f(CW\*(C`open\*(C'\fR to a command that pipes both in \fIand\fR
-out, but see IPC::Open2, IPC::Open3, and
-\&\*(L"Bidirectional Communication\*(R" in perlipc for alternatives.)
-.Sp
-In the three-or-more argument form of pipe opens, if \s-1LIST\s0 is specified
-(extra arguments after the command name) then \s-1LIST\s0 becomes arguments
-to the command invoked if the platform supports it. The meaning of
-\&\f(CW\*(C`open\*(C'\fR with more than three arguments for non-pipe modes is not yet
-specified. Experimental \*(L"layers\*(R" may give extra \s-1LIST\s0 arguments
-meaning.
-.Sp
-In the 2\-arguments (and 1\-argument) form opening \f(CW'\-'\fR opens \s-1STDIN\s0
-and opening \f(CW'>\-'\fR opens \s-1STDOUT\s0.
-.Sp
-You may use the three-argument form of open to specify \s-1IO\s0 \*(L"layers\*(R"
-(sometimes also referred to as \*(L"disciplines\*(R") to be applied to the handle
-that affect how the input and output are processed (see open and
-PerlIO for more details). For example
-.Sp
-.Vb 1
-\& open(FH, "<:utf8", "file")
-.Ve
-.Sp
-will open the \s-1UTF\-8\s0 encoded file containing Unicode characters,
-see perluniintro. Note that if layers are specified in the
-three-arg form then default layers stored in ${^OPEN} (see perlvar;
-usually set by the \fBopen\fR pragma or the switch \fB\-CioD\fR) are ignored.
-.Sp
-Open returns nonzero upon success, the undefined value otherwise. If
-the \f(CW\*(C`open\*(C'\fR involved a pipe, the return value happens to be the pid of
-the subprocess.
-.Sp
-If you're running Perl on a system that distinguishes between text
-files and binary files, then you should check out \*(L"binmode\*(R" for tips
-for dealing with this. The key distinction between systems that need
-\&\f(CW\*(C`binmode\*(C'\fR and those that don't is their text file formats. Systems
-like Unix, Mac \s-1OS\s0, and Plan 9, which delimit lines with a single
-character, and which encode that character in C as \f(CW"\en"\fR, do not
-need \f(CW\*(C`binmode\*(C'\fR. The rest need it.
-.Sp
-When opening a file, it's usually a bad idea to continue normal execution
-if the request failed, so \f(CW\*(C`open\*(C'\fR is frequently used in connection with
-\&\f(CW\*(C`die\*(C'\fR. Even if \f(CW\*(C`die\*(C'\fR won't do what you want (say, in a \s-1CGI\s0 script,
-where you want to make a nicely formatted error message (but there are
-modules that can help with that problem)) you should always check
-the return value from opening a file. The infrequent exception is when
-working with an unopened filehandle is actually what you want to do.
-.Sp
-As a special case the 3\-arg form with a read/write mode and the third
-argument being \f(CW\*(C`undef\*(C'\fR:
-.Sp
-.Vb 1
-\& open(TMP, "+>", undef) or die ...
-.Ve
-.Sp
-opens a filehandle to an anonymous temporary file. Also using \*(L"+<\*(R"
-works for symmetry, but you really should consider writing something
-to the temporary file first. You will need to \fIseek()\fR to do the
-reading.
-.Sp
-Since v5.8.0, perl has built using PerlIO by default. Unless you've
-changed this (i.e. Configure \-Uuseperlio), you can open file handles to
-\&\*(L"in memory\*(R" files held in Perl scalars via:
-.Sp
-.Vb 1
-\& open($fh, '>', \e$variable) || ..
-.Ve
-.Sp
-Though if you try to re-open \f(CW\*(C`STDOUT\*(C'\fR or \f(CW\*(C`STDERR\*(C'\fR as an \*(L"in memory\*(R"
-file, you have to close it first:
-.Sp
-.Vb 2
-\& close STDOUT;
-\& open STDOUT, '>', \e$variable or die "Can't open STDOUT: $!";
-.Ve
-.Sp
-Examples:
-.Sp
-.Vb 3
-\& $ARTICLE = 100;
-\& open ARTICLE or die "Can't find article $ARTICLE: $!\en";
-\& while (<ARTICLE>) {...
-.Ve
-.Sp
-.Vb 2
-\& open(LOG, '>>/usr/spool/news/twitlog'); # (log is reserved)
-\& # if the open fails, output is discarded
-.Ve
-.Sp
-.Vb 2
-\& open(DBASE, '+<', 'dbase.mine') # open for update
-\& or die "Can't open 'dbase.mine' for update: $!";
-.Ve
-.Sp
-.Vb 2
-\& open(DBASE, '+<dbase.mine') # ditto
-\& or die "Can't open 'dbase.mine' for update: $!";
-.Ve
-.Sp
-.Vb 2
-\& open(ARTICLE, '-|', "caesar <$article") # decrypt article
-\& or die "Can't start caesar: $!";
-.Ve
-.Sp
-.Vb 2
-\& open(ARTICLE, "caesar <$article |") # ditto
-\& or die "Can't start caesar: $!";
-.Ve
-.Sp
-.Vb 2
-\& open(EXTRACT, "|sort >Tmp$$") # $$ is our process id
-\& or die "Can't start sort: $!";
-.Ve
-.Sp
-.Vb 4
-\& # in memory files
-\& open(MEMORY,'>', \e$var)
-\& or die "Can't open memory file: $!";
-\& print MEMORY "foo!\en"; # output will end up in $var
-.Ve
-.Sp
-.Vb 1
-\& # process argument list of files along with any includes
-.Ve
-.Sp
-.Vb 3
-\& foreach $file (@ARGV) {
-\& process($file, 'fh00');
-\& }
-.Ve
-.Sp
-.Vb 7
-\& sub process {
-\& my($filename, $input) = @_;
-\& $input++; # this is a string increment
-\& unless (open($input, $filename)) {
-\& print STDERR "Can't open $filename: $!\en";
-\& return;
-\& }
-.Ve
-.Sp
-.Vb 9
-\& local $_;
-\& while (<$input>) { # note use of indirection
-\& if (/^#include "(.*)"/) {
-\& process($1, $input);
-\& next;
-\& }
-\& #... # whatever
-\& }
-\& }
-.Ve
-.Sp
-See perliol for detailed info on PerlIO.
-.Sp
-You may also, in the Bourne shell tradition, specify an \s-1EXPR\s0 beginning
-with \f(CW'>&'\fR, in which case the rest of the string is interpreted
-as the name of a filehandle (or file descriptor, if numeric) to be
-duped (as \fIdup\fR\|(2)) and opened. You may use \f(CW\*(C`&\*(C'\fR after \f(CW\*(C`>\*(C'\fR,
-\&\f(CW\*(C`>>\*(C'\fR, \f(CW\*(C`<\*(C'\fR, \f(CW\*(C`+>\*(C'\fR, \f(CW\*(C`+>>\*(C'\fR, and \f(CW\*(C`+<\*(C'\fR.
-The mode you specify should match the mode of the original filehandle.
-(Duping a filehandle does not take into account any existing contents
-of \s-1IO\s0 buffers.) If you use the 3\-arg form then you can pass either a
-number, the name of a filehandle or the normal \*(L"reference to a glob\*(R".
-.Sp
-Here is a script that saves, redirects, and restores \f(CW\*(C`STDOUT\*(C'\fR and
-\&\f(CW\*(C`STDERR\*(C'\fR using various methods:
-.Sp
-.Vb 3
-\& #!/usr/bin/perl
-\& open my $oldout, ">&STDOUT" or die "Can't dup STDOUT: $!";
-\& open OLDERR, ">&", \e*STDERR or die "Can't dup STDERR: $!";
-.Ve
-.Sp
-.Vb 2
-\& open STDOUT, '>', "foo.out" or die "Can't redirect STDOUT: $!";
-\& open STDERR, ">&STDOUT" or die "Can't dup STDOUT: $!";
-.Ve
-.Sp
-.Vb 2
-\& select STDERR; $| = 1; # make unbuffered
-\& select STDOUT; $| = 1; # make unbuffered
-.Ve
-.Sp
-.Vb 2
-\& print STDOUT "stdout 1\en"; # this works for
-\& print STDERR "stderr 1\en"; # subprocesses too
-.Ve
-.Sp
-.Vb 2
-\& open STDOUT, ">&", $oldout or die "Can't dup \e$oldout: $!";
-\& open STDERR, ">&OLDERR" or die "Can't dup OLDERR: $!";
-.Ve
-.Sp
-.Vb 2
-\& print STDOUT "stdout 2\en";
-\& print STDERR "stderr 2\en";
-.Ve
-.Sp
-If you specify \f(CW'<&=X'\fR, where \f(CW\*(C`X\*(C'\fR is a file descriptor number
-or a filehandle, then Perl will do an equivalent of C's \f(CW\*(C`fdopen\*(C'\fR of
-that file descriptor (and not call \fIdup\fR\|(2)); this is more
-parsimonious of file descriptors. For example:
-.Sp
-.Vb 2
-\& # open for input, reusing the fileno of $fd
-\& open(FILEHANDLE, "<&=$fd")
-.Ve
-.Sp
-or
-.Sp
-.Vb 1
-\& open(FILEHANDLE, "<&=", $fd)
-.Ve
-.Sp
-or
-.Sp
-.Vb 2
-\& # open for append, using the fileno of OLDFH
-\& open(FH, ">>&=", OLDFH)
-.Ve
-.Sp
-or
-.Sp
-.Vb 1
-\& open(FH, ">>&=OLDFH")
-.Ve
-.Sp
-Being parsimonious on filehandles is also useful (besides being
-parsimonious) for example when something is dependent on file
-descriptors, like for example locking using \fIflock()\fR. If you do just
-\&\f(CW\*(C`open(A, '>>&B')\*(C'\fR, the filehandle A will not have the same file
-descriptor as B, and therefore flock(A) will not flock(B), and vice
-versa. But with \f(CW\*(C`open(A, '>>&=B')\*(C'\fR the filehandles will share
-the same file descriptor.
-.Sp
-Note that if you are using Perls older than 5.8.0, Perl will be using
-the standard C libraries' \fIfdopen()\fR to implement the \*(L"=\*(R" functionality.
-On many \s-1UNIX\s0 systems \fIfdopen()\fR fails when file descriptors exceed a
-certain value, typically 255. For Perls 5.8.0 and later, PerlIO is
-most often the default.
-.Sp
-You can see whether Perl has been compiled with PerlIO or not by
-running \f(CW\*(C`perl \-V\*(C'\fR and looking for \f(CW\*(C`useperlio=\*(C'\fR line. If \f(CW\*(C`useperlio\*(C'\fR
-is \f(CW\*(C`define\*(C'\fR, you have PerlIO, otherwise you don't.
-.Sp
-If you open a pipe on the command \f(CW'\-'\fR, i.e., either \f(CW'|\-'\fR or \f(CW'\-|'\fR
-with 2\-arguments (or 1\-argument) form of \fIopen()\fR, then
-there is an implicit fork done, and the return value of open is the pid
-of the child within the parent process, and \f(CW0\fR within the child
-process. (Use \f(CW\*(C`defined($pid)\*(C'\fR to determine whether the open was successful.)
-The filehandle behaves normally for the parent, but i/o to that
-filehandle is piped from/to the \s-1STDOUT/STDIN\s0 of the child process.
-In the child process the filehandle isn't opened\*(--i/o happens from/to
-the new \s-1STDOUT\s0 or \s-1STDIN\s0. Typically this is used like the normal
-piped open when you want to exercise more control over just how the
-pipe command gets executed, such as when you are running setuid, and
-don't want to have to scan shell commands for metacharacters.
-The following triples are more or less equivalent:
-.Sp
-.Vb 4
-\& open(FOO, "|tr '[a-z]' '[A-Z]'");
-\& open(FOO, '|-', "tr '[a-z]' '[A-Z]'");
-\& open(FOO, '|-') || exec 'tr', '[a-z]', '[A-Z]';
-\& open(FOO, '|-', "tr", '[a-z]', '[A-Z]');
-.Ve
-.Sp
-.Vb 4
-\& open(FOO, "cat -n '$file'|");
-\& open(FOO, '-|', "cat -n '$file'");
-\& open(FOO, '-|') || exec 'cat', '-n', $file;
-\& open(FOO, '-|', "cat", '-n', $file);
-.Ve
-.Sp
-The last example in each block shows the pipe as \*(L"list form\*(R", which is
-not yet supported on all platforms. A good rule of thumb is that if
-your platform has true \f(CW\*(C`fork()\*(C'\fR (in other words, if your platform is
-\&\s-1UNIX\s0) you can use the list form.
-.Sp
-See \*(L"Safe Pipe Opens\*(R" in perlipc for more examples of this.
-.Sp
-Beginning with v5.6.0, Perl will attempt to flush all files opened for
-output before any operation that may do a fork, but this may not be
-supported on some platforms (see perlport). To be safe, you may need
-to set \f(CW$|\fR ($AUTOFLUSH in English) or call the \f(CW\*(C`autoflush()\*(C'\fR method
-of \f(CW\*(C`IO::Handle\*(C'\fR on any open handles.
-.Sp
-On systems that support a close-on-exec flag on files, the flag will
-be set for the newly opened file descriptor as determined by the value
-of $^F. See \*(L"$^F\*(R" in perlvar.
-.Sp
-Closing any piped filehandle causes the parent process to wait for the
-child to finish, and returns the status value in \f(CW$?\fR.
-.Sp
-The filename passed to 2\-argument (or 1\-argument) form of \fIopen()\fR will
-have leading and trailing whitespace deleted, and the normal
-redirection characters honored. This property, known as \*(L"magic open\*(R",
-can often be used to good effect. A user could specify a filename of
-\&\fI\*(L"rsh cat file |\*(R"\fR, or you could change certain filenames as needed:
-.Sp
-.Vb 2
-\& $filename =~ s/(.*\e.gz)\es*$/gzip -dc < $1|/;
-\& open(FH, $filename) or die "Can't open $filename: $!";
-.Ve
-.Sp
-Use 3\-argument form to open a file with arbitrary weird characters in it,
-.Sp
-.Vb 1
-\& open(FOO, '<', $file);
-.Ve
-.Sp
-otherwise it's necessary to protect any leading and trailing whitespace:
-.Sp
-.Vb 2
-\& $file =~ s#^(\es)#./$1#;
-\& open(FOO, "< $file\e0");
-.Ve
-.Sp
-(this may not work on some bizarre filesystems). One should
-conscientiously choose between the \fImagic\fR and 3\-arguments form
-of \fIopen()\fR:
-.Sp
-.Vb 1
-\& open IN, $ARGV[0];
-.Ve
-.Sp
-will allow the user to specify an argument of the form \f(CW"rsh cat file |"\fR,
-but will not work on a filename which happens to have a trailing space, while
-.Sp
-.Vb 1
-\& open IN, '<', $ARGV[0];
-.Ve
-.Sp
-will have exactly the opposite restrictions.
-.Sp
-If you want a \*(L"real\*(R" C \f(CW\*(C`open\*(C'\fR (see \fIopen\fR\|(2) on your system), then you
-should use the \f(CW\*(C`sysopen\*(C'\fR function, which involves no such magic (but
-may use subtly different filemodes than Perl \fIopen()\fR, which is mapped
-to C \fIfopen()\fR). This is
-another way to protect your filenames from interpretation. For example:
-.Sp
-.Vb 7
-\& use IO::Handle;
-\& sysopen(HANDLE, $path, O_RDWR|O_CREAT|O_EXCL)
-\& or die "sysopen $path: $!";
-\& $oldfh = select(HANDLE); $| = 1; select($oldfh);
-\& print HANDLE "stuff $$\en";
-\& seek(HANDLE, 0, 0);
-\& print "File contains: ", <HANDLE>;
-.Ve
-.Sp
-Using the constructor from the \f(CW\*(C`IO::Handle\*(C'\fR package (or one of its
-subclasses, such as \f(CW\*(C`IO::File\*(C'\fR or \f(CW\*(C`IO::Socket\*(C'\fR), you can generate anonymous
-filehandles that have the scope of whatever variables hold references to
-them, and automatically close whenever and however you leave that scope:
-.Sp
-.Vb 12
-\& use IO::File;
-\& #...
-\& sub read_myfile_munged {
-\& my $ALL = shift;
-\& my $handle = new IO::File;
-\& open($handle, "myfile") or die "myfile: $!";
-\& $first = <$handle>
-\& or return (); # Automatically closed here.
-\& mung $first or die "mung failed"; # Or here.
-\& return $first, <$handle> if $ALL; # Or here.
-\& $first; # Or here.
-\& }
-.Ve
-.Sp
-See \*(L"seek\*(R" for some details about mixing reading and writing.
-.IP "opendir \s-1DIRHANDLE\s0,EXPR" 8
-.IX Xref "opendir"
-.IX Item "opendir DIRHANDLE,EXPR"
-Opens a directory named \s-1EXPR\s0 for processing by \f(CW\*(C`readdir\*(C'\fR, \f(CW\*(C`telldir\*(C'\fR,
-\&\f(CW\*(C`seekdir\*(C'\fR, \f(CW\*(C`rewinddir\*(C'\fR, and \f(CW\*(C`closedir\*(C'\fR. Returns true if successful.
-\&\s-1DIRHANDLE\s0 may be an expression whose value can be used as an indirect
-dirhandle, usually the real dirhandle name. If \s-1DIRHANDLE\s0 is an undefined
-scalar variable (or array or hash element), the variable is assigned a
-reference to a new anonymous dirhandle.
-DIRHANDLEs have their own namespace separate from FILEHANDLEs.
-.IP "ord \s-1EXPR\s0" 8
-.IX Xref "ord encoding"
-.IX Item "ord EXPR"
-.PD 0
-.IP "ord" 8
-.IX Item "ord"
-.PD
-Returns the numeric (the native 8\-bit encoding, like \s-1ASCII\s0 or \s-1EBCDIC\s0,
-or Unicode) value of the first character of \s-1EXPR\s0. If \s-1EXPR\s0 is omitted,
-uses \f(CW$_\fR.
-.Sp
-For the reverse, see \*(L"chr\*(R".
-See perlunicode and encoding for more about Unicode.
-.IP "our \s-1EXPR\s0" 8
-.IX Xref "our global"
-.IX Item "our EXPR"
-.PD 0
-.IP "our \s-1EXPR\s0 \s-1TYPE\s0" 8
-.IX Item "our EXPR TYPE"
-.IP "our \s-1EXPR\s0 : \s-1ATTRS\s0" 8
-.IX Item "our EXPR : ATTRS"
-.IP "our \s-1TYPE\s0 \s-1EXPR\s0 : \s-1ATTRS\s0" 8
-.IX Item "our TYPE EXPR : ATTRS"
-.PD
-\&\f(CW\*(C`our\*(C'\fR associates a simple name with a package variable in the current
-package for use within the current scope. When \f(CW\*(C`use strict 'vars'\*(C'\fR is in
-effect, \f(CW\*(C`our\*(C'\fR lets you use declared global variables without qualifying
-them with package names, within the lexical scope of the \f(CW\*(C`our\*(C'\fR declaration.
-In this way \f(CW\*(C`our\*(C'\fR differs from \f(CW\*(C`use vars\*(C'\fR, which is package scoped.
-.Sp
-Unlike \f(CW\*(C`my\*(C'\fR, which both allocates storage for a variable and associates
-a simple name with that storage for use within the current scope, \f(CW\*(C`our\*(C'\fR
-associates a simple name with a package variable in the current package,
-for use within the current scope. In other words, \f(CW\*(C`our\*(C'\fR has the same
-scoping rules as \f(CW\*(C`my\*(C'\fR, but does not necessarily create a
-variable.
-.Sp
-If more than one value is listed, the list must be placed
-in parentheses.
-.Sp
-.Vb 2
-\& our $foo;
-\& our($bar, $baz);
-.Ve
-.Sp
-An \f(CW\*(C`our\*(C'\fR declaration declares a global variable that will be visible
-across its entire lexical scope, even across package boundaries. The
-package in which the variable is entered is determined at the point
-of the declaration, not at the point of use. This means the following
-behavior holds:
-.Sp
-.Vb 3
-\& package Foo;
-\& our $bar; # declares $Foo::bar for rest of lexical scope
-\& $bar = 20;
-.Ve
-.Sp
-.Vb 2
-\& package Bar;
-\& print $bar; # prints 20, as it refers to $Foo::bar
-.Ve
-.Sp
-Multiple \f(CW\*(C`our\*(C'\fR declarations with the same name in the same lexical
-scope are allowed if they are in different packages. If they happen
-to be in the same package, Perl will emit warnings if you have asked
-for them, just like multiple \f(CW\*(C`my\*(C'\fR declarations. Unlike a second
-\&\f(CW\*(C`my\*(C'\fR declaration, which will bind the name to a fresh variable, a
-second \f(CW\*(C`our\*(C'\fR declaration in the same package, in the same scope, is
-merely redundant.
-.Sp
-.Vb 4
-\& use warnings;
-\& package Foo;
-\& our $bar; # declares $Foo::bar for rest of lexical scope
-\& $bar = 20;
-.Ve
-.Sp
-.Vb 3
-\& package Bar;
-\& our $bar = 30; # declares $Bar::bar for rest of lexical scope
-\& print $bar; # prints 30
-.Ve
-.Sp
-.Vb 2
-\& our $bar; # emits warning but has no other effect
-\& print $bar; # still prints 30
-.Ve
-.Sp
-An \f(CW\*(C`our\*(C'\fR declaration may also have a list of attributes associated
-with it.
-.Sp
-The exact semantics and interface of \s-1TYPE\s0 and \s-1ATTRS\s0 are still
-evolving. \s-1TYPE\s0 is currently bound to the use of \f(CW\*(C`fields\*(C'\fR pragma,
-and attributes are handled using the \f(CW\*(C`attributes\*(C'\fR pragma, or starting
-from Perl 5.8.0 also via the \f(CW\*(C`Attribute::Handlers\*(C'\fR module. See
-\&\*(L"Private Variables via \fImy()\fR\*(R" in perlsub for details, and fields,
-attributes, and Attribute::Handlers.
-.Sp
-The only currently recognized \f(CW\*(C`our()\*(C'\fR attribute is \f(CW\*(C`unique\*(C'\fR which
-indicates that a single copy of the global is to be used by all
-interpreters should the program happen to be running in a
-multi-interpreter environment. (The default behaviour would be for
-each interpreter to have its own copy of the global.) Examples:
-.Sp
-.Vb 3
-\& our @EXPORT : unique = qw(foo);
-\& our %EXPORT_TAGS : unique = (bar => [qw(aa bb cc)]);
-\& our $VERSION : unique = "1.00";
-.Ve
-.Sp
-Note that this attribute also has the effect of making the global
-readonly when the first new interpreter is cloned (for example,
-when the first new thread is created).
-.Sp
-Multi-interpreter environments can come to being either through the
-\&\fIfork()\fR emulation on Windows platforms, or by embedding perl in a
-multi-threaded application. The \f(CW\*(C`unique\*(C'\fR attribute does nothing in
-all other environments.
-.Sp
-Warning: the current implementation of this attribute operates on the
-typeglob associated with the variable; this means that \f(CW\*(C`our $x : unique\*(C'\fR
-also has the effect of \f(CW\*(C`our @x : unique; our %x : unique\*(C'\fR. This may be
-subject to change.
-.IP "pack \s-1TEMPLATE\s0,LIST" 8
-.IX Xref "pack"
-.IX Item "pack TEMPLATE,LIST"
-Takes a \s-1LIST\s0 of values and converts it into a string using the rules
-given by the \s-1TEMPLATE\s0. The resulting string is the concatenation of
-the converted values. Typically, each converted value looks
-like its machine-level representation. For example, on 32\-bit machines
-a converted integer may be represented by a sequence of 4 bytes.
-.Sp
-The \s-1TEMPLATE\s0 is a sequence of characters that give the order and type
-of values, as follows:
-.Sp
-.Vb 3
-\& a A string with arbitrary binary data, will be null padded.
-\& A A text (ASCII) string, will be space padded.
-\& Z A null terminated (ASCIZ) string, will be null padded.
-.Ve
-.Sp
-.Vb 4
-\& b A bit string (ascending bit order inside each byte, like vec()).
-\& B A bit string (descending bit order inside each byte).
-\& h A hex string (low nybble first).
-\& H A hex string (high nybble first).
-.Ve
-.Sp
-.Vb 2
-\& c A signed char value.
-\& C An unsigned char value. Only does bytes. See U for Unicode.
-.Ve
-.Sp
-.Vb 5
-\& s A signed short value.
-\& S An unsigned short value.
-\& (This 'short' is _exactly_ 16 bits, which may differ from
-\& what a local C compiler calls 'short'. If you want
-\& native-length shorts, use the '!' suffix.)
-.Ve
-.Sp
-.Vb 6
-\& i A signed integer value.
-\& I An unsigned integer value.
-\& (This 'integer' is _at_least_ 32 bits wide. Its exact
-\& size depends on what a local C compiler calls 'int',
-\& and may even be larger than the 'long' described in
-\& the next item.)
-.Ve
-.Sp
-.Vb 5
-\& l A signed long value.
-\& L An unsigned long value.
-\& (This 'long' is _exactly_ 32 bits, which may differ from
-\& what a local C compiler calls 'long'. If you want
-\& native-length longs, use the '!' suffix.)
-.Ve
-.Sp
-.Vb 6
-\& n An unsigned short in "network" (big-endian) order.
-\& N An unsigned long in "network" (big-endian) order.
-\& v An unsigned short in "VAX" (little-endian) order.
-\& V An unsigned long in "VAX" (little-endian) order.
-\& (These 'shorts' and 'longs' are _exactly_ 16 bits and
-\& _exactly_ 32 bits, respectively.)
-.Ve
-.Sp
-.Vb 5
-\& q A signed quad (64-bit) value.
-\& Q An unsigned quad value.
-\& (Quads are available only if your system supports 64-bit
-\& integer values _and_ if Perl has been compiled to support those.
-\& Causes a fatal error otherwise.)
-.Ve
-.Sp
-.Vb 2
-\& j A signed integer value (a Perl internal integer, IV).
-\& J An unsigned integer value (a Perl internal unsigned integer, UV).
-.Ve
-.Sp
-.Vb 2
-\& f A single-precision float in the native format.
-\& d A double-precision float in the native format.
-.Ve
-.Sp
-.Vb 6
-\& F A floating point value in the native native format
-\& (a Perl internal floating point value, NV).
-\& D A long double-precision float in the native format.
-\& (Long doubles are available only if your system supports long
-\& double values _and_ if Perl has been compiled to support those.
-\& Causes a fatal error otherwise.)
-.Ve
-.Sp
-.Vb 2
-\& p A pointer to a null-terminated string.
-\& P A pointer to a structure (fixed-length string).
-.Ve
-.Sp
-.Vb 3
-\& u A uuencoded string.
-\& U A Unicode character number. Encodes to UTF-8 internally
-\& (or UTF-EBCDIC in EBCDIC platforms).
-.Ve
-.Sp
-.Vb 4
-\& w A BER compressed integer (not an ASN.1 BER, see perlpacktut for
-\& details). Its bytes represent an unsigned integer in base 128,
-\& most significant digit first, with as few digits as possible. Bit
-\& eight (the high bit) is set on each byte except the last.
-.Ve
-.Sp
-.Vb 5
-\& x A null byte.
-\& X Back up a byte.
-\& @ Null fill to absolute position, counted from the start of
-\& the innermost ()-group.
-\& ( Start of a ()-group.
-.Ve
-.Sp
-The following rules apply:
-.RS 8
-.IP "*" 8
-Each letter may optionally be followed by a number giving a repeat
-count. With all types except \f(CW\*(C`a\*(C'\fR, \f(CW\*(C`A\*(C'\fR, \f(CW\*(C`Z\*(C'\fR, \f(CW\*(C`b\*(C'\fR, \f(CW\*(C`B\*(C'\fR, \f(CW\*(C`h\*(C'\fR,
-\&\f(CW\*(C`H\*(C'\fR, \f(CW\*(C`@\*(C'\fR, \f(CW\*(C`x\*(C'\fR, \f(CW\*(C`X\*(C'\fR and \f(CW\*(C`P\*(C'\fR the pack function will gobble up that
-many values from the \s-1LIST\s0. A \f(CW\*(C`*\*(C'\fR for the repeat count means to use
-however many items are left, except for \f(CW\*(C`@\*(C'\fR, \f(CW\*(C`x\*(C'\fR, \f(CW\*(C`X\*(C'\fR, where it is
-equivalent to \f(CW0\fR, and \f(CW\*(C`u\*(C'\fR, where it is equivalent to 1 (or 45, what
-is the same). A numeric repeat count may optionally be enclosed in
-brackets, as in \f(CW\*(C`pack 'C[80]', @arr\*(C'\fR.
-.Sp
-One can replace the numeric repeat count by a template enclosed in brackets;
-then the packed length of this template in bytes is used as a count.
-For example, \f(CW\*(C`x[L]\*(C'\fR skips a long (it skips the number of bytes in a long);
-the template \f(CW\*(C`$t X[$t] $t\*(C'\fR \fIunpack()\fRs twice what \f(CW$t\fR unpacks.
-If the template in brackets contains alignment commands (such as \f(CW\*(C`x![d]\*(C'\fR),
-its packed length is calculated as if the start of the template has the maximal
-possible alignment.
-.Sp
-When used with \f(CW\*(C`Z\*(C'\fR, \f(CW\*(C`*\*(C'\fR results in the addition of a trailing null
-byte (so the packed result will be one longer than the byte \f(CW\*(C`length\*(C'\fR
-of the item).
-.Sp
-The repeat count for \f(CW\*(C`u\*(C'\fR is interpreted as the maximal number of bytes
-to encode per line of output, with 0 and 1 replaced by 45.
-.IP "*" 8
-The \f(CW\*(C`a\*(C'\fR, \f(CW\*(C`A\*(C'\fR, and \f(CW\*(C`Z\*(C'\fR types gobble just one value, but pack it as a
-string of length count, padding with nulls or spaces as necessary. When
-unpacking, \f(CW\*(C`A\*(C'\fR strips trailing spaces and nulls, \f(CW\*(C`Z\*(C'\fR strips everything
-after the first null, and \f(CW\*(C`a\*(C'\fR returns data verbatim. When packing,
-\&\f(CW\*(C`a\*(C'\fR, and \f(CW\*(C`Z\*(C'\fR are equivalent.
-.Sp
-If the value-to-pack is too long, it is truncated. If too long and an
-explicit count is provided, \f(CW\*(C`Z\*(C'\fR packs only \f(CW\*(C`$count\-1\*(C'\fR bytes, followed
-by a null byte. Thus \f(CW\*(C`Z\*(C'\fR always packs a trailing null byte under
-all circumstances.
-.IP "*" 8
-Likewise, the \f(CW\*(C`b\*(C'\fR and \f(CW\*(C`B\*(C'\fR fields pack a string that many bits long.
-Each byte of the input field of \fIpack()\fR generates 1 bit of the result.
-Each result bit is based on the least-significant bit of the corresponding
-input byte, i.e., on \f(CW\*(C`ord($byte)%2\*(C'\fR. In particular, bytes \f(CW"0"\fR and
-\&\f(CW"1"\fR generate bits 0 and 1, as do bytes \f(CW"\e0"\fR and \f(CW"\e1"\fR.
-.Sp
-Starting from the beginning of the input string of \fIpack()\fR, each 8\-tuple
-of bytes is converted to 1 byte of output. With format \f(CW\*(C`b\*(C'\fR
-the first byte of the 8\-tuple determines the least-significant bit of a
-byte, and with format \f(CW\*(C`B\*(C'\fR it determines the most-significant bit of
-a byte.
-.Sp
-If the length of the input string is not exactly divisible by 8, the
-remainder is packed as if the input string were padded by null bytes
-at the end. Similarly, during \fIunpack()\fRing the \*(L"extra\*(R" bits are ignored.
-.Sp
-If the input string of \fIpack()\fR is longer than needed, extra bytes are ignored.
-A \f(CW\*(C`*\*(C'\fR for the repeat count of \fIpack()\fR means to use all the bytes of
-the input field. On \fIunpack()\fRing the bits are converted to a string
-of \f(CW"0"\fRs and \f(CW"1"\fRs.
-.IP "*" 8
-The \f(CW\*(C`h\*(C'\fR and \f(CW\*(C`H\*(C'\fR fields pack a string that many nybbles (4\-bit groups,
-representable as hexadecimal digits, 0\-9a\-f) long.
-.Sp
-Each byte of the input field of \fIpack()\fR generates 4 bits of the result.
-For non-alphabetical bytes the result is based on the 4 least-significant
-bits of the input byte, i.e., on \f(CW\*(C`ord($byte)%16\*(C'\fR. In particular,
-bytes \f(CW"0"\fR and \f(CW"1"\fR generate nybbles 0 and 1, as do bytes
-\&\f(CW"\e0"\fR and \f(CW"\e1"\fR. For bytes \f(CW"a".."f"\fR and \f(CW"A".."F"\fR the result
-is compatible with the usual hexadecimal digits, so that \f(CW"a"\fR and
-\&\f(CW"A"\fR both generate the nybble \f(CW\*(C`0xa==10\*(C'\fR. The result for bytes
-\&\f(CW"g".."z"\fR and \f(CW"G".."Z"\fR is not well\-defined.
-.Sp
-Starting from the beginning of the input string of \fIpack()\fR, each pair
-of bytes is converted to 1 byte of output. With format \f(CW\*(C`h\*(C'\fR the
-first byte of the pair determines the least-significant nybble of the
-output byte, and with format \f(CW\*(C`H\*(C'\fR it determines the most-significant
-nybble.
-.Sp
-If the length of the input string is not even, it behaves as if padded
-by a null byte at the end. Similarly, during \fIunpack()\fRing the \*(L"extra\*(R"
-nybbles are ignored.
-.Sp
-If the input string of \fIpack()\fR is longer than needed, extra bytes are ignored.
-A \f(CW\*(C`*\*(C'\fR for the repeat count of \fIpack()\fR means to use all the bytes of
-the input field. On \fIunpack()\fRing the bits are converted to a string
-of hexadecimal digits.
-.IP "*" 8
-The \f(CW\*(C`p\*(C'\fR type packs a pointer to a null-terminated string. You are
-responsible for ensuring the string is not a temporary value (which can
-potentially get deallocated before you get around to using the packed result).
-The \f(CW\*(C`P\*(C'\fR type packs a pointer to a structure of the size indicated by the
-length. A \s-1NULL\s0 pointer is created if the corresponding value for \f(CW\*(C`p\*(C'\fR or
-\&\f(CW\*(C`P\*(C'\fR is \f(CW\*(C`undef\*(C'\fR, similarly for \fIunpack()\fR.
-.IP "*" 8
-The \f(CW\*(C`/\*(C'\fR template character allows packing and unpacking of strings where
-the packed structure contains a byte count followed by the string itself.
-You write \fIlength-item\fR\f(CW\*(C`/\*(C'\fR\fIstring-item\fR.
-.Sp
-The \fIlength-item\fR can be any \f(CW\*(C`pack\*(C'\fR template letter, and describes
-how the length value is packed. The ones likely to be of most use are
-integer-packing ones like \f(CW\*(C`n\*(C'\fR (for Java strings), \f(CW\*(C`w\*(C'\fR (for \s-1ASN\s0.1 or
-\&\s-1SNMP\s0) and \f(CW\*(C`N\*(C'\fR (for Sun \s-1XDR\s0).
-.Sp
-For \f(CW\*(C`pack\*(C'\fR, the \fIstring-item\fR must, at present, be \f(CW"A*"\fR, \f(CW"a*"\fR or
-\&\f(CW"Z*"\fR. For \f(CW\*(C`unpack\*(C'\fR the length of the string is obtained from the
-\&\fIlength-item\fR, but if you put in the '*' it will be ignored. For all other
-codes, \f(CW\*(C`unpack\*(C'\fR applies the length value to the next item, which must not
-have a repeat count.
-.Sp
-.Vb 3
-\& unpack 'C/a', "\e04Gurusamy"; gives 'Guru'
-\& unpack 'a3/A* A*', '007 Bond J '; gives (' Bond','J')
-\& pack 'n/a* w/a*','hello,','world'; gives "\e000\e006hello,\e005world"
-.Ve
-.Sp
-The \fIlength-item\fR is not returned explicitly from \f(CW\*(C`unpack\*(C'\fR.
-.Sp
-Adding a count to the \fIlength-item\fR letter is unlikely to do anything
-useful, unless that letter is \f(CW\*(C`A\*(C'\fR, \f(CW\*(C`a\*(C'\fR or \f(CW\*(C`Z\*(C'\fR. Packing with a
-\&\fIlength-item\fR of \f(CW\*(C`a\*(C'\fR or \f(CW\*(C`Z\*(C'\fR may introduce \f(CW"\e000"\fR characters,
-which Perl does not regard as legal in numeric strings.
-.IP "*" 8
-The integer types \f(CW\*(C`s\*(C'\fR, \f(CW\*(C`S\*(C'\fR, \f(CW\*(C`l\*(C'\fR, and \f(CW\*(C`L\*(C'\fR may be
-immediately followed by a \f(CW\*(C`!\*(C'\fR suffix to signify native shorts or
-longs\*(--as you can see from above for example a bare \f(CW\*(C`l\*(C'\fR does mean
-exactly 32 bits, the native \f(CW\*(C`long\*(C'\fR (as seen by the local C compiler)
-may be larger. This is an issue mainly in 64\-bit platforms. You can
-see whether using \f(CW\*(C`!\*(C'\fR makes any difference by
-.Sp
-.Vb 2
-\& print length(pack("s")), " ", length(pack("s!")), "\en";
-\& print length(pack("l")), " ", length(pack("l!")), "\en";
-.Ve
-.Sp
-\&\f(CW\*(C`i!\*(C'\fR and \f(CW\*(C`I!\*(C'\fR also work but only because of completeness;
-they are identical to \f(CW\*(C`i\*(C'\fR and \f(CW\*(C`I\*(C'\fR.
-.Sp
-The actual sizes (in bytes) of native shorts, ints, longs, and long
-longs on the platform where Perl was built are also available via
-Config:
-.Sp
-.Vb 5
-\& use Config;
-\& print $Config{shortsize}, "\en";
-\& print $Config{intsize}, "\en";
-\& print $Config{longsize}, "\en";
-\& print $Config{longlongsize}, "\en";
-.Ve
-.Sp
-(The \f(CW$Config{longlongsize}\fR will be undefined if your system does
-not support long longs.)
-.IP "*" 8
-The integer formats \f(CW\*(C`s\*(C'\fR, \f(CW\*(C`S\*(C'\fR, \f(CW\*(C`i\*(C'\fR, \f(CW\*(C`I\*(C'\fR, \f(CW\*(C`l\*(C'\fR, \f(CW\*(C`L\*(C'\fR, \f(CW\*(C`j\*(C'\fR, and \f(CW\*(C`J\*(C'\fR
-are inherently non-portable between processors and operating systems
-because they obey the native byteorder and endianness. For example a
-4\-byte integer 0x12345678 (305419896 decimal) would be ordered natively
-(arranged in and handled by the \s-1CPU\s0 registers) into bytes as
-.Sp
-.Vb 2
-\& 0x12 0x34 0x56 0x78 # big-endian
-\& 0x78 0x56 0x34 0x12 # little-endian
-.Ve
-.Sp
-Basically, the Intel and \s-1VAX\s0 CPUs are little\-endian, while everybody
-else, for example Motorola m68k/88k, \s-1PPC\s0, Sparc, \s-1HP\s0 \s-1PA\s0, Power, and
-Cray are big\-endian. Alpha and \s-1MIPS\s0 can be either: Digital/Compaq
-used/uses them in little-endian mode; SGI/Cray uses them in big-endian
-mode.
-.Sp
-The names `big\-endian' and `little\-endian' are comic references to
-the classic \*(L"Gulliver's Travels\*(R" (via the paper \*(L"On Holy Wars and a
-Plea for Peace\*(R" by Danny Cohen, \s-1USC/ISI\s0 \s-1IEN\s0 137, April 1, 1980) and
-the egg-eating habits of the Lilliputians.
-.Sp
-Some systems may have even weirder byte orders such as
-.Sp
-.Vb 2
-\& 0x56 0x78 0x12 0x34
-\& 0x34 0x12 0x78 0x56
-.Ve
-.Sp
-You can see your system's preference with
-.Sp
-.Vb 2
-\& print join(" ", map { sprintf "%#02x", $_ }
-\& unpack("C*",pack("L",0x12345678))), "\en";
-.Ve
-.Sp
-The byteorder on the platform where Perl was built is also available
-via Config:
-.Sp
-.Vb 2
-\& use Config;
-\& print $Config{byteorder}, "\en";
-.Ve
-.Sp
-Byteorders \f(CW'1234'\fR and \f(CW'12345678'\fR are little\-endian, \f(CW'4321'\fR
-and \f(CW'87654321'\fR are big\-endian.
-.Sp
-If you want portable packed integers use the formats \f(CW\*(C`n\*(C'\fR, \f(CW\*(C`N\*(C'\fR,
-\&\f(CW\*(C`v\*(C'\fR, and \f(CW\*(C`V\*(C'\fR, their byte endianness and size are known.
-See also perlport.
-.IP "*" 8
-Real numbers (floats and doubles) are in the native machine format only;
-due to the multiplicity of floating formats around, and the lack of a
-standard \*(L"network\*(R" representation, no facility for interchange has been
-made. This means that packed floating point data written on one machine
-may not be readable on another \- even if both use \s-1IEEE\s0 floating point
-arithmetic (as the endian-ness of the memory representation is not part
-of the \s-1IEEE\s0 spec). See also perlport.
-.Sp
-Note that Perl uses doubles internally for all numeric calculation, and
-converting from double into float and thence back to double again will
-lose precision (i.e., \f(CW\*(C`unpack("f", pack("f", $foo)\*(C'\fR) will not in general
-equal \f(CW$foo\fR).
-.IP "*" 8
-If the pattern begins with a \f(CW\*(C`U\*(C'\fR, the resulting string will be
-treated as UTF\-8\-encoded Unicode. You can force \s-1UTF\-8\s0 encoding on in a
-string with an initial \f(CW\*(C`U0\*(C'\fR, and the bytes that follow will be
-interpreted as Unicode characters. If you don't want this to happen,
-you can begin your pattern with \f(CW\*(C`C0\*(C'\fR (or anything else) to force Perl
-not to \s-1UTF\-8\s0 encode your string, and then follow this with a \f(CW\*(C`U*\*(C'\fR
-somewhere in your pattern.
-.IP "*" 8
-You must yourself do any alignment or padding by inserting for example
-enough \f(CW'x'\fRes while packing. There is no way to \fIpack()\fR and \fIunpack()\fR
-could know where the bytes are going to or coming from. Therefore
-\&\f(CW\*(C`pack\*(C'\fR (and \f(CW\*(C`unpack\*(C'\fR) handle their output and input as flat
-sequences of bytes.
-.IP "*" 8
-A ()\-group is a sub-TEMPLATE enclosed in parentheses. A group may
-take a repeat count, both as postfix, and for \fIunpack()\fR also via the \f(CW\*(C`/\*(C'\fR
-template character. Within each repetition of a group, positioning with
-\&\f(CW\*(C`@\*(C'\fR starts again at 0. Therefore, the result of
-.Sp
-.Vb 1
-\& pack( '@1A((@2A)@3A)', 'a', 'b', 'c' )
-.Ve
-.Sp
-is the string \*(L"\e0a\e0\e0bc\*(R".
-.IP "*" 8
-\&\f(CW\*(C`x\*(C'\fR and \f(CW\*(C`X\*(C'\fR accept \f(CW\*(C`!\*(C'\fR modifier. In this case they act as
-alignment commands: they jump forward/back to the closest position
-aligned at a multiple of \f(CW\*(C`count\*(C'\fR bytes. For example, to \fIpack()\fR or
-\&\fIunpack()\fR C's \f(CW\*(C`struct {char c; double d; char cc[2]}\*(C'\fR one may need to
-use the template \f(CW\*(C`C x![d] d C[2]\*(C'\fR; this assumes that doubles must be
-aligned on the double's size.
-.Sp
-For alignment commands \f(CW\*(C`count\*(C'\fR of 0 is equivalent to \f(CW\*(C`count\*(C'\fR of 1;
-both result in no\-ops.
-.IP "*" 8
-A comment in a \s-1TEMPLATE\s0 starts with \f(CW\*(C`#\*(C'\fR and goes to the end of line.
-White space may be used to separate pack codes from each other, but
-a \f(CW\*(C`!\*(C'\fR modifier and a repeat count must follow immediately.
-.IP "*" 8
-If \s-1TEMPLATE\s0 requires more arguments to \fIpack()\fR than actually given, \fIpack()\fR
-assumes additional \f(CW""\fR arguments. If \s-1TEMPLATE\s0 requires fewer arguments
-to \fIpack()\fR than actually given, extra arguments are ignored.
-.RE
-.RS 8
-.Sp
-Examples:
-.Sp
-.Vb 6
-\& $foo = pack("CCCC",65,66,67,68);
-\& # foo eq "ABCD"
-\& $foo = pack("C4",65,66,67,68);
-\& # same thing
-\& $foo = pack("U4",0x24b6,0x24b7,0x24b8,0x24b9);
-\& # same thing with Unicode circled letters
-.Ve
-.Sp
-.Vb 2
-\& $foo = pack("ccxxcc",65,66,67,68);
-\& # foo eq "AB\e0\e0CD"
-.Ve
-.Sp
-.Vb 4
-\& # note: the above examples featuring "C" and "c" are true
-\& # only on ASCII and ASCII-derived systems such as ISO Latin 1
-\& # and UTF-8. In EBCDIC the first example would be
-\& # $foo = pack("CCCC",193,194,195,196);
-.Ve
-.Sp
-.Vb 3
-\& $foo = pack("s2",1,2);
-\& # "\e1\e0\e2\e0" on little-endian
-\& # "\e0\e1\e0\e2" on big-endian
-.Ve
-.Sp
-.Vb 2
-\& $foo = pack("a4","abcd","x","y","z");
-\& # "abcd"
-.Ve
-.Sp
-.Vb 2
-\& $foo = pack("aaaa","abcd","x","y","z");
-\& # "axyz"
-.Ve
-.Sp
-.Vb 2
-\& $foo = pack("a14","abcdefg");
-\& # "abcdefg\e0\e0\e0\e0\e0\e0\e0"
-.Ve
-.Sp
-.Vb 2
-\& $foo = pack("i9pl", gmtime);
-\& # a real struct tm (on my system anyway)
-.Ve
-.Sp
-.Vb 3
-\& $utmp_template = "Z8 Z8 Z16 L";
-\& $utmp = pack($utmp_template, @utmp1);
-\& # a struct utmp (BSDish)
-.Ve
-.Sp
-.Vb 2
-\& @utmp2 = unpack($utmp_template, $utmp);
-\& # "@utmp1" eq "@utmp2"
-.Ve
-.Sp
-.Vb 3
-\& sub bintodec {
-\& unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
-\& }
-.Ve
-.Sp
-.Vb 5
-\& $foo = pack('sx2l', 12, 34);
-\& # short 12, two zero bytes padding, long 34
-\& $bar = pack('s@4l', 12, 34);
-\& # short 12, zero fill to position 4, long 34
-\& # $foo eq $bar
-.Ve
-.Sp
-The same template may generally also be used in \fIunpack()\fR.
-.RE
-.IP "package \s-1NAMESPACE\s0" 8
-.IX Xref "package module namespace"
-.IX Item "package NAMESPACE"
-.PD 0
-.IP "package" 8
-.IX Item "package"
-.PD
-Declares the compilation unit as being in the given namespace. The scope
-of the package declaration is from the declaration itself through the end
-of the enclosing block, file, or eval (the same as the \f(CW\*(C`my\*(C'\fR operator).
-All further unqualified dynamic identifiers will be in this namespace.
-A package statement affects only dynamic variables\*(--including those
-you've used \f(CW\*(C`local\*(C'\fR on\*(--but \fInot\fR lexical variables, which are created
-with \f(CW\*(C`my\*(C'\fR. Typically it would be the first declaration in a file to
-be included by the \f(CW\*(C`require\*(C'\fR or \f(CW\*(C`use\*(C'\fR operator. You can switch into a
-package in more than one place; it merely influences which symbol table
-is used by the compiler for the rest of that block. You can refer to
-variables and filehandles in other packages by prefixing the identifier
-with the package name and a double colon: \f(CW$Package::Variable\fR.
-If the package name is null, the \f(CW\*(C`main\*(C'\fR package as assumed. That is,
-\&\f(CW$::sail\fR is equivalent to \f(CW$main::sail\fR (as well as to \f(CW$main'sail\fR,
-still seen in older code).
-.Sp
-If \s-1NAMESPACE\s0 is omitted, then there is no current package, and all
-identifiers must be fully qualified or lexicals. However, you are
-strongly advised not to make use of this feature. Its use can cause
-unexpected behaviour, even crashing some versions of Perl. It is
-deprecated, and will be removed from a future release.
-.Sp
-See \*(L"Packages\*(R" in perlmod for more information about packages, modules,
-and classes. See perlsub for other scoping issues.
-.IP "pipe \s-1READHANDLE\s0,WRITEHANDLE" 8
-.IX Xref "pipe"
-.IX Item "pipe READHANDLE,WRITEHANDLE"
-Opens a pair of connected pipes like the corresponding system call.
-Note that if you set up a loop of piped processes, deadlock can occur
-unless you are very careful. In addition, note that Perl's pipes use
-\&\s-1IO\s0 buffering, so you may need to set \f(CW$|\fR to flush your \s-1WRITEHANDLE\s0
-after each command, depending on the application.
-.Sp
-See IPC::Open2, IPC::Open3, and \*(L"Bidirectional Communication\*(R" in perlipc
-for examples of such things.
-.Sp
-On systems that support a close-on-exec flag on files, the flag will be set
-for the newly opened file descriptors as determined by the value of $^F.
-See \*(L"$^F\*(R" in perlvar.
-.IP "pop \s-1ARRAY\s0" 8
-.IX Xref "pop stack"
-.IX Item "pop ARRAY"
-.PD 0
-.IP "pop" 8
-.IX Item "pop"
-.PD
-Pops and returns the last value of the array, shortening the array by
-one element. Has an effect similar to
-.Sp
-.Vb 1
-\& $ARRAY[$#ARRAY--]
-.Ve
-.Sp
-If there are no elements in the array, returns the undefined value
-(although this may happen at other times as well). If \s-1ARRAY\s0 is
-omitted, pops the \f(CW@ARGV\fR array in the main program, and the \f(CW@_\fR
-array in subroutines, just like \f(CW\*(C`shift\*(C'\fR.
-.IP "pos \s-1SCALAR\s0" 8
-.IX Xref "pos match, position"
-.IX Item "pos SCALAR"
-.PD 0
-.IP "pos" 8
-.IX Item "pos"
-.PD
-Returns the offset of where the last \f(CW\*(C`m//g\*(C'\fR search left off for the variable
-in question (\f(CW$_\fR is used when the variable is not specified). Note that
-0 is a valid match offset. \f(CW\*(C`undef\*(C'\fR indicates that the search position
-is reset (usually due to match failure, but can also be because no match has
-yet been performed on the scalar). \f(CW\*(C`pos\*(C'\fR directly accesses the location used
-by the regexp engine to store the offset, so assigning to \f(CW\*(C`pos\*(C'\fR will change
-that offset, and so will also influence the \f(CW\*(C`\eG\*(C'\fR zero-width assertion in
-regular expressions. Because a failed \f(CW\*(C`m//gc\*(C'\fR match doesn't reset the offset,
-the return from \f(CW\*(C`pos\*(C'\fR won't change either in this case. See perlre and
-perlop.
-.IP "print \s-1FILEHANDLE\s0 \s-1LIST\s0" 8
-.IX Xref "print"
-.IX Item "print FILEHANDLE LIST"
-.PD 0
-.IP "print \s-1LIST\s0" 8
-.IX Item "print LIST"
-.IP "print" 8
-.IX Item "print"
-.PD
-Prints a string or a list of strings. Returns true if successful.
-\&\s-1FILEHANDLE\s0 may be a scalar variable name, in which case the variable
-contains the name of or a reference to the filehandle, thus introducing
-one level of indirection. (\s-1NOTE:\s0 If \s-1FILEHANDLE\s0 is a variable and
-the next token is a term, it may be misinterpreted as an operator
-unless you interpose a \f(CW\*(C`+\*(C'\fR or put parentheses around the arguments.)
-If \s-1FILEHANDLE\s0 is omitted, prints by default to standard output (or
-to the last selected output channel\*(--see \*(L"select\*(R"). If \s-1LIST\s0 is
-also omitted, prints \f(CW$_\fR to the currently selected output channel.
-To set the default output channel to something other than \s-1STDOUT\s0
-use the select operation. The current value of \f(CW$,\fR (if any) is
-printed between each \s-1LIST\s0 item. The current value of \f(CW\*(C`$\e\*(C'\fR (if
-any) is printed after the entire \s-1LIST\s0 has been printed. Because
-print takes a \s-1LIST\s0, anything in the \s-1LIST\s0 is evaluated in list
-context, and any subroutine that you call will have one or more of
-its expressions evaluated in list context. Also be careful not to
-follow the print keyword with a left parenthesis unless you want
-the corresponding right parenthesis to terminate the arguments to
-the print\*(--interpose a \f(CW\*(C`+\*(C'\fR or put parentheses around all the
-arguments.
-.Sp
-Note that if you're storing FILEHANDLEs in an array, or if you're using
-any other expression more complex than a scalar variable to retrieve it,
-you will have to use a block returning the filehandle value instead:
-.Sp
-.Vb 2
-\& print { $files[$i] } "stuff\en";
-\& print { $OK ? STDOUT : STDERR } "stuff\en";
-.Ve
-.IP "printf \s-1FILEHANDLE\s0 \s-1FORMAT\s0, \s-1LIST\s0" 8
-.IX Xref "printf"
-.IX Item "printf FILEHANDLE FORMAT, LIST"
-.PD 0
-.IP "printf \s-1FORMAT\s0, \s-1LIST\s0" 8
-.IX Item "printf FORMAT, LIST"
-.PD
-Equivalent to \f(CW\*(C`print FILEHANDLE sprintf(FORMAT, LIST)\*(C'\fR, except that \f(CW\*(C`$\e\*(C'\fR
-(the output record separator) is not appended. The first argument
-of the list will be interpreted as the \f(CW\*(C`printf\*(C'\fR format. See \f(CW\*(C`sprintf\*(C'\fR
-for an explanation of the format argument. If \f(CW\*(C`use locale\*(C'\fR is in effect,
-the character used for the decimal point in formatted real numbers is
-affected by the \s-1LC_NUMERIC\s0 locale. See perllocale.
-.Sp
-Don't fall into the trap of using a \f(CW\*(C`printf\*(C'\fR when a simple
-\&\f(CW\*(C`print\*(C'\fR would do. The \f(CW\*(C`print\*(C'\fR is more efficient and less
-error prone.
-.IP "prototype \s-1FUNCTION\s0" 8
-.IX Xref "prototype"
-.IX Item "prototype FUNCTION"
-Returns the prototype of a function as a string (or \f(CW\*(C`undef\*(C'\fR if the
-function has no prototype). \s-1FUNCTION\s0 is a reference to, or the name of,
-the function whose prototype you want to retrieve.
-.Sp
-If \s-1FUNCTION\s0 is a string starting with \f(CW\*(C`CORE::\*(C'\fR, the rest is taken as a
-name for Perl builtin. If the builtin is not \fIoverridable\fR (such as
-\&\f(CW\*(C`qw//\*(C'\fR) or its arguments cannot be expressed by a prototype (such as
-\&\f(CW\*(C`system\*(C'\fR) returns \f(CW\*(C`undef\*(C'\fR because the builtin does not really behave
-like a Perl function. Otherwise, the string describing the equivalent
-prototype is returned.
-.IP "push \s-1ARRAY\s0,LIST ," 8
-.IX Xref "push stack"
-.IX Item "push ARRAY,LIST ,"
-Treats \s-1ARRAY\s0 as a stack, and pushes the values of \s-1LIST\s0
-onto the end of \s-1ARRAY\s0. The length of \s-1ARRAY\s0 increases by the length of
-\&\s-1LIST\s0. Has the same effect as
-.Sp
-.Vb 3
-\& for $value (LIST) {
-\& $ARRAY[++$#ARRAY] = $value;
-\& }
-.Ve
-.Sp
-but is more efficient. Returns the number of elements in the array following
-the completed \f(CW\*(C`push\*(C'\fR.
-.IP "q/STRING/" 8
-.IX Item "q/STRING/"
-.PD 0
-.IP "qq/STRING/" 8
-.IX Item "qq/STRING/"
-.IP "qr/STRING/" 8
-.IX Item "qr/STRING/"
-.IP "qx/STRING/" 8
-.IX Item "qx/STRING/"
-.IP "qw/STRING/" 8
-.IX Item "qw/STRING/"
-.PD
-Generalized quotes. See \*(L"Regexp Quote-Like Operators\*(R" in perlop.
-.IP "quotemeta \s-1EXPR\s0" 8
-.IX Xref "quotemeta metacharacter"
-.IX Item "quotemeta EXPR"
-.PD 0
-.IP "quotemeta" 8
-.IX Item "quotemeta"
-.PD
-Returns the value of \s-1EXPR\s0 with all non\-\*(L"word\*(R"
-characters backslashed. (That is, all characters not matching
-\&\f(CW\*(C`/[A\-Za\-z_0\-9]/\*(C'\fR will be preceded by a backslash in the
-returned string, regardless of any locale settings.)
-This is the internal function implementing
-the \f(CW\*(C`\eQ\*(C'\fR escape in double-quoted strings.
-.Sp
-If \s-1EXPR\s0 is omitted, uses \f(CW$_\fR.
-.IP "rand \s-1EXPR\s0" 8
-.IX Xref "rand random"
-.IX Item "rand EXPR"
-.PD 0
-.IP "rand" 8
-.IX Item "rand"
-.PD
-Returns a random fractional number greater than or equal to \f(CW0\fR and less
-than the value of \s-1EXPR\s0. (\s-1EXPR\s0 should be positive.) If \s-1EXPR\s0 is
-omitted, the value \f(CW1\fR is used. Currently \s-1EXPR\s0 with the value \f(CW0\fR is
-also special-cased as \f(CW1\fR \- this has not been documented before perl 5.8.0
-and is subject to change in future versions of perl. Automatically calls
-\&\f(CW\*(C`srand\*(C'\fR unless \f(CW\*(C`srand\*(C'\fR has already been called. See also \f(CW\*(C`srand\*(C'\fR.
-.Sp
-Apply \f(CW\*(C`int()\*(C'\fR to the value returned by \f(CW\*(C`rand()\*(C'\fR if you want random
-integers instead of random fractional numbers. For example,
-.Sp
-.Vb 1
-\& int(rand(10))
-.Ve
-.Sp
-returns a random integer between \f(CW0\fR and \f(CW9\fR, inclusive.
-.Sp
-(Note: If your rand function consistently returns numbers that are too
-large or too small, then your version of Perl was probably compiled
-with the wrong number of \s-1RANDBITS\s0.)
-.IP "read \s-1FILEHANDLE\s0,SCALAR,LENGTH,OFFSET" 8
-.IX Xref "read"
-.IX Item "read FILEHANDLE,SCALAR,LENGTH,OFFSET"
-.PD 0
-.IP "read \s-1FILEHANDLE\s0,SCALAR,LENGTH" 8
-.IX Item "read FILEHANDLE,SCALAR,LENGTH"
-.PD
-Attempts to read \s-1LENGTH\s0 \fIcharacters\fR of data into variable \s-1SCALAR\s0
-from the specified \s-1FILEHANDLE\s0. Returns the number of characters
-actually read, \f(CW0\fR at end of file, or undef if there was an error (in
-the latter case \f(CW$!\fR is also set). \s-1SCALAR\s0 will be grown or shrunk
-so that the last character actually read is the last character of the
-scalar after the read.
-.Sp
-An \s-1OFFSET\s0 may be specified to place the read data at some place in the
-string other than the beginning. A negative \s-1OFFSET\s0 specifies
-placement at that many characters counting backwards from the end of
-the string. A positive \s-1OFFSET\s0 greater than the length of \s-1SCALAR\s0
-results in the string being padded to the required size with \f(CW"\e0"\fR
-bytes before the result of the read is appended.
-.Sp
-The call is actually implemented in terms of either Perl's or system's
-\&\fIfread()\fR call. To get a true \fIread\fR\|(2) system call, see \f(CW\*(C`sysread\*(C'\fR.
-.Sp
-Note the \fIcharacters\fR: depending on the status of the filehandle,
-either (8\-bit) bytes or characters are read. By default all
-filehandles operate on bytes, but for example if the filehandle has
-been opened with the \f(CW\*(C`:utf8\*(C'\fR I/O layer (see \*(L"open\*(R", and the \f(CW\*(C`open\*(C'\fR
-pragma, open), the I/O will operate on \s-1UTF\-8\s0 encoded Unicode
-characters, not bytes. Similarly for the \f(CW\*(C`:encoding\*(C'\fR pragma:
-in that case pretty much any characters can be read.
-.IP "readdir \s-1DIRHANDLE\s0" 8
-.IX Xref "readdir"
-.IX Item "readdir DIRHANDLE"
-Returns the next directory entry for a directory opened by \f(CW\*(C`opendir\*(C'\fR.
-If used in list context, returns all the rest of the entries in the
-directory. If there are no more entries, returns an undefined value in
-scalar context or a null list in list context.
-.Sp
-If you're planning to filetest the return values out of a \f(CW\*(C`readdir\*(C'\fR, you'd
-better prepend the directory in question. Otherwise, because we didn't
-\&\f(CW\*(C`chdir\*(C'\fR there, it would have been testing the wrong file.
-.Sp
-.Vb 3
-\& opendir(DIR, $some_dir) || die "can't opendir $some_dir: $!";
-\& @dots = grep { /^\e./ && -f "$some_dir/$_" } readdir(DIR);
-\& closedir DIR;
-.Ve
-.IP "readline \s-1EXPR\s0" 8
-.IX Xref "readline gets fgets"
-.IX Item "readline EXPR"
-Reads from the filehandle whose typeglob is contained in \s-1EXPR\s0. In scalar
-context, each call reads and returns the next line, until end-of-file is
-reached, whereupon the subsequent call returns undef. In list context,
-reads until end-of-file is reached and returns a list of lines. Note that
-the notion of \*(L"line\*(R" used here is however you may have defined it
-with \f(CW$/\fR or \f(CW$INPUT_RECORD_SEPARATOR\fR). See \*(L"$/\*(R" in perlvar.
-.Sp
-When \f(CW$/\fR is set to \f(CW\*(C`undef\*(C'\fR, when \fIreadline()\fR is in scalar
-context (i.e. file slurp mode), and when an empty file is read, it
-returns \f(CW''\fR the first time, followed by \f(CW\*(C`undef\*(C'\fR subsequently.
-.Sp
-This is the internal function implementing the \f(CW\*(C`<EXPR>\*(C'\fR
-operator, but you can use it directly. The \f(CW\*(C`<EXPR>\*(C'\fR
-operator is discussed in more detail in \*(L"I/O Operators\*(R" in perlop.
-.Sp
-.Vb 2
-\& $line = <STDIN>;
-\& $line = readline(*STDIN); # same thing
-.Ve
-.Sp
-If readline encounters an operating system error, \f(CW$!\fR will be set with the
-corresponding error message. It can be helpful to check \f(CW$!\fR when you are
-reading from filehandles you don't trust, such as a tty or a socket. The
-following example uses the operator form of \f(CW\*(C`readline\*(C'\fR, and takes the necessary
-steps to ensure that \f(CW\*(C`readline\*(C'\fR was successful.
-.Sp
-.Vb 8
-\& for (;;) {
-\& undef $!;
-\& unless (defined( $line = <> )) {
-\& die $! if $!;
-\& last; # reached EOF
-\& }
-\& # ...
-\& }
-.Ve
-.IP "readlink \s-1EXPR\s0" 8
-.IX Xref "readlink"
-.IX Item "readlink EXPR"
-.PD 0
-.IP "readlink" 8
-.IX Item "readlink"
-.PD
-Returns the value of a symbolic link, if symbolic links are
-implemented. If not, gives a fatal error. If there is some system
-error, returns the undefined value and sets \f(CW$!\fR (errno). If \s-1EXPR\s0 is
-omitted, uses \f(CW$_\fR.
-.IP "readpipe \s-1EXPR\s0" 8
-.IX Xref "readpipe"
-.IX Item "readpipe EXPR"
-\&\s-1EXPR\s0 is executed as a system command.
-The collected standard output of the command is returned.
-In scalar context, it comes back as a single (potentially
-multi\-line) string. In list context, returns a list of lines
-(however you've defined lines with \f(CW$/\fR or \f(CW$INPUT_RECORD_SEPARATOR\fR).
-This is the internal function implementing the \f(CW\*(C`qx/EXPR/\*(C'\fR
-operator, but you can use it directly. The \f(CW\*(C`qx/EXPR/\*(C'\fR
-operator is discussed in more detail in \*(L"I/O Operators\*(R" in perlop.
-.IP "recv \s-1SOCKET\s0,SCALAR,LENGTH,FLAGS" 8
-.IX Xref "recv"
-.IX Item "recv SOCKET,SCALAR,LENGTH,FLAGS"
-Receives a message on a socket. Attempts to receive \s-1LENGTH\s0 characters
-of data into variable \s-1SCALAR\s0 from the specified \s-1SOCKET\s0 filehandle.
-\&\s-1SCALAR\s0 will be grown or shrunk to the length actually read. Takes the
-same flags as the system call of the same name. Returns the address
-of the sender if \s-1SOCKET\s0's protocol supports this; returns an empty
-string otherwise. If there's an error, returns the undefined value.
-This call is actually implemented in terms of \fIrecvfrom\fR\|(2) system call.
-See \*(L"\s-1UDP:\s0 Message Passing\*(R" in perlipc for examples.
-.Sp
-Note the \fIcharacters\fR: depending on the status of the socket, either
-(8\-bit) bytes or characters are received. By default all sockets
-operate on bytes, but for example if the socket has been changed using
-\&\fIbinmode()\fR to operate with the \f(CW\*(C`:utf8\*(C'\fR I/O layer (see the \f(CW\*(C`open\*(C'\fR
-pragma, open), the I/O will operate on \s-1UTF\-8\s0 encoded Unicode
-characters, not bytes. Similarly for the \f(CW\*(C`:encoding\*(C'\fR pragma:
-in that case pretty much any characters can be read.
-.IP "redo \s-1LABEL\s0" 8
-.IX Xref "redo"
-.IX Item "redo LABEL"
-.PD 0
-.IP "redo" 8
-.IX Item "redo"
-.PD
-The \f(CW\*(C`redo\*(C'\fR command restarts the loop block without evaluating the
-conditional again. The \f(CW\*(C`continue\*(C'\fR block, if any, is not executed. If
-the \s-1LABEL\s0 is omitted, the command refers to the innermost enclosing
-loop. Programs that want to lie to themselves about what was just input
-normally use this command:
-.Sp
-.Vb 16
-\& # a simpleminded Pascal comment stripper
-\& # (warning: assumes no { or } in strings)
-\& LINE: while (<STDIN>) {
-\& while (s|({.*}.*){.*}|$1 |) {}
-\& s|{.*}| |;
-\& if (s|{.*| |) {
-\& $front = $_;
-\& while (<STDIN>) {
-\& if (/}/) { # end of comment?
-\& s|^|$front\e{|;
-\& redo LINE;
-\& }
-\& }
-\& }
-\& print;
-\& }
-.Ve
-.Sp
-\&\f(CW\*(C`redo\*(C'\fR cannot be used to retry a block which returns a value such as
-\&\f(CW\*(C`eval {}\*(C'\fR, \f(CW\*(C`sub {}\*(C'\fR or \f(CW\*(C`do {}\*(C'\fR, and should not be used to exit
-a \fIgrep()\fR or \fImap()\fR operation.
-.Sp
-Note that a block by itself is semantically identical to a loop
-that executes once. Thus \f(CW\*(C`redo\*(C'\fR inside such a block will effectively
-turn it into a looping construct.
-.Sp
-See also \*(L"continue\*(R" for an illustration of how \f(CW\*(C`last\*(C'\fR, \f(CW\*(C`next\*(C'\fR, and
-\&\f(CW\*(C`redo\*(C'\fR work.
-.IP "ref \s-1EXPR\s0" 8
-.IX Xref "ref reference"
-.IX Item "ref EXPR"
-.PD 0
-.IP "ref" 8
-.IX Item "ref"
-.PD
-Returns a non-empty string if \s-1EXPR\s0 is a reference, the empty
-string otherwise. If \s-1EXPR\s0
-is not specified, \f(CW$_\fR will be used. The value returned depends on the
-type of thing the reference is a reference to.
-Builtin types include:
-.Sp
-.Vb 7
-\& SCALAR
-\& ARRAY
-\& HASH
-\& CODE
-\& REF
-\& GLOB
-\& LVALUE
-.Ve
-.Sp
-If the referenced object has been blessed into a package, then that package
-name is returned instead. You can think of \f(CW\*(C`ref\*(C'\fR as a \f(CW\*(C`typeof\*(C'\fR operator.
-.Sp
-.Vb 6
-\& if (ref($r) eq "HASH") {
-\& print "r is a reference to a hash.\en";
-\& }
-\& unless (ref($r)) {
-\& print "r is not a reference at all.\en";
-\& }
-.Ve
-.Sp
-See also perlref.
-.IP "rename \s-1OLDNAME\s0,NEWNAME" 8
-.IX Xref "rename move mv ren"
-.IX Item "rename OLDNAME,NEWNAME"
-Changes the name of a file; an existing file \s-1NEWNAME\s0 will be
-clobbered. Returns true for success, false otherwise.
-.Sp
-Behavior of this function varies wildly depending on your system
-implementation. For example, it will usually not work across file system
-boundaries, even though the system \fImv\fR command sometimes compensates
-for this. Other restrictions include whether it works on directories,
-open files, or pre-existing files. Check perlport and either the
-\&\fIrename\fR\|(2) manpage or equivalent system documentation for details.
-.IP "require \s-1VERSION\s0" 8
-.IX Xref "require"
-.IX Item "require VERSION"
-.PD 0
-.IP "require \s-1EXPR\s0" 8
-.IX Item "require EXPR"
-.IP "require" 8
-.IX Item "require"
-.PD
-Demands a version of Perl specified by \s-1VERSION\s0, or demands some semantics
-specified by \s-1EXPR\s0 or by \f(CW$_\fR if \s-1EXPR\s0 is not supplied.
-.Sp
-\&\s-1VERSION\s0 may be either a numeric argument such as 5.006, which will be
-compared to \f(CW$]\fR, or a literal of the form v5.6.1, which will be compared
-to \f(CW$^V\fR (aka \f(CW$PERL_VERSION\fR). A fatal error is produced at run time if
-\&\s-1VERSION\s0 is greater than the version of the current Perl interpreter.
-Compare with \*(L"use\*(R", which can do a similar check at compile time.
-.Sp
-Specifying \s-1VERSION\s0 as a literal of the form v5.6.1 should generally be
-avoided, because it leads to misleading error messages under earlier
-versions of Perl that do not support this syntax. The equivalent numeric
-version should be used instead.
-.Sp
-.Vb 3
-\& require v5.6.1; # run time version check
-\& require 5.6.1; # ditto
-\& require 5.006_001; # ditto; preferred for backwards compatibility
-.Ve
-.Sp
-Otherwise, \f(CW\*(C`require\*(C'\fR demands that a library file be included if it
-hasn't already been included. The file is included via the do-FILE
-mechanism, which is essentially just a variety of \f(CW\*(C`eval\*(C'\fR. Has
-semantics similar to the following subroutine:
-.Sp
-.Vb 28
-\& sub require {
-\& my ($filename) = @_;
-\& if (exists $INC{$filename}) {
-\& return 1 if $INC{$filename};
-\& die "Compilation failed in require";
-\& }
-\& my ($realfilename,$result);
-\& ITER: {
-\& foreach $prefix (@INC) {
-\& $realfilename = "$prefix/$filename";
-\& if (-f $realfilename) {
-\& $INC{$filename} = $realfilename;
-\& $result = do $realfilename;
-\& last ITER;
-\& }
-\& }
-\& die "Can't find $filename in \e@INC";
-\& }
-\& if ($@) {
-\& $INC{$filename} = undef;
-\& die $@;
-\& } elsif (!$result) {
-\& delete $INC{$filename};
-\& die "$filename did not return true value";
-\& } else {
-\& return $result;
-\& }
-\& }
-.Ve
-.Sp
-Note that the file will not be included twice under the same specified
-name.
-.Sp
-The file must return true as the last statement to indicate
-successful execution of any initialization code, so it's customary to
-end such a file with \f(CW\*(C`1;\*(C'\fR unless you're sure it'll return true
-otherwise. But it's better just to put the \f(CW\*(C`1;\*(C'\fR, in case you add more
-statements.
-.Sp
-If \s-1EXPR\s0 is a bareword, the require assumes a "\fI.pm\fR\*(L" extension and
-replaces \*(R"\fI::\fR\*(L" with \*(R"\fI/\fR" in the filename for you,
-to make it easy to load standard modules. This form of loading of
-modules does not risk altering your namespace.
-.Sp
-In other words, if you try this:
-.Sp
-.Vb 1
-\& require Foo::Bar; # a splendid bareword
-.Ve
-.Sp
-The require function will actually look for the "\fIFoo/Bar.pm\fR" file in the
-directories specified in the \f(CW@INC\fR array.
-.Sp
-But if you try this:
-.Sp
-.Vb 4
-\& $class = 'Foo::Bar';
-\& require $class; # $class is not a bareword
-\& #or
-\& require "Foo::Bar"; # not a bareword because of the ""
-.Ve
-.Sp
-The require function will look for the "\fIFoo::Bar\fR\*(L" file in the \f(CW@INC\fR array and
-will complain about not finding \*(R"\fIFoo::Bar\fR" there. In this case you can do:
-.Sp
-.Vb 1
-\& eval "require $class";
-.Ve
-.Sp
-Now that you understand how \f(CW\*(C`require\*(C'\fR looks for files in the case of
-a bareword argument, there is a little extra functionality going on
-behind the scenes. Before \f(CW\*(C`require\*(C'\fR looks for a "\fI.pm\fR\*(L" extension,
-it will first look for a filename with a \*(R"\fI.pmc\fR" extension. A file
-with this extension is assumed to be Perl bytecode generated by
-B::Bytecode. If this file is found, and its modification
-time is newer than a coinciding "\fI.pm\fR\*(L" non-compiled file, it will be
-loaded in place of that non-compiled file ending in a \*(R"\fI.pm\fR" extension.
-.Sp
-You can also insert hooks into the import facility, by putting directly
-Perl code into the \f(CW@INC\fR array. There are three forms of hooks: subroutine
-references, array references and blessed objects.
-.Sp
-Subroutine references are the simplest case. When the inclusion system
-walks through \f(CW@INC\fR and encounters a subroutine, this subroutine gets
-called with two parameters, the first being a reference to itself, and the
-second the name of the file to be included (e.g. "\fIFoo/Bar.pm\fR"). The
-subroutine should return \f(CW\*(C`undef\*(C'\fR or a filehandle, from which the file to
-include will be read. If \f(CW\*(C`undef\*(C'\fR is returned, \f(CW\*(C`require\*(C'\fR will look at
-the remaining elements of \f(CW@INC\fR.
-.Sp
-If the hook is an array reference, its first element must be a subroutine
-reference. This subroutine is called as above, but the first parameter is
-the array reference. This enables to pass indirectly some arguments to
-the subroutine.
-.Sp
-In other words, you can write:
-.Sp
-.Vb 5
-\& push @INC, \e&my_sub;
-\& sub my_sub {
-\& my ($coderef, $filename) = @_; # $coderef is \e&my_sub
-\& ...
-\& }
-.Ve
-.Sp
-or:
-.Sp
-.Vb 7
-\& push @INC, [ \e&my_sub, $x, $y, ... ];
-\& sub my_sub {
-\& my ($arrayref, $filename) = @_;
-\& # Retrieve $x, $y, ...
-\& my @parameters = @$arrayref[1..$#$arrayref];
-\& ...
-\& }
-.Ve
-.Sp
-If the hook is an object, it must provide an \s-1INC\s0 method that will be
-called as above, the first parameter being the object itself. (Note that
-you must fully qualify the sub's name, as it is always forced into package
-\&\f(CW\*(C`main\*(C'\fR.) Here is a typical code layout:
-.Sp
-.Vb 7
-\& # In Foo.pm
-\& package Foo;
-\& sub new { ... }
-\& sub Foo::INC {
-\& my ($self, $filename) = @_;
-\& ...
-\& }
-.Ve
-.Sp
-.Vb 2
-\& # In the main program
-\& push @INC, new Foo(...);
-.Ve
-.Sp
-Note that these hooks are also permitted to set the \f(CW%INC\fR entry
-corresponding to the files they have loaded. See \*(L"%INC\*(R" in perlvar.
-.Sp
-For a yet-more-powerful import facility, see \*(L"use\*(R" and perlmod.
-.IP "reset \s-1EXPR\s0" 8
-.IX Xref "reset"
-.IX Item "reset EXPR"
-.PD 0
-.IP "reset" 8
-.IX Item "reset"
-.PD
-Generally used in a \f(CW\*(C`continue\*(C'\fR block at the end of a loop to clear
-variables and reset \f(CW\*(C`??\*(C'\fR searches so that they work again. The
-expression is interpreted as a list of single characters (hyphens
-allowed for ranges). All variables and arrays beginning with one of
-those letters are reset to their pristine state. If the expression is
-omitted, one-match searches (\f(CW\*(C`?pattern?\*(C'\fR) are reset to match again. Resets
-only variables or searches in the current package. Always returns
-1. Examples:
-.Sp
-.Vb 3
-\& reset 'X'; # reset all X variables
-\& reset 'a-z'; # reset lower case variables
-\& reset; # just reset ?one-time? searches
-.Ve
-.Sp
-Resetting \f(CW"A\-Z"\fR is not recommended because you'll wipe out your
-\&\f(CW@ARGV\fR and \f(CW@INC\fR arrays and your \f(CW%ENV\fR hash. Resets only package
-variables\*(--lexical variables are unaffected, but they clean themselves
-up on scope exit anyway, so you'll probably want to use them instead.
-See \*(L"my\*(R".
-.IP "return \s-1EXPR\s0" 8
-.IX Xref "return"
-.IX Item "return EXPR"
-.PD 0
-.IP "return" 8
-.IX Item "return"
-.PD
-Returns from a subroutine, \f(CW\*(C`eval\*(C'\fR, or \f(CW\*(C`do FILE\*(C'\fR with the value
-given in \s-1EXPR\s0. Evaluation of \s-1EXPR\s0 may be in list, scalar, or void
-context, depending on how the return value will be used, and the context
-may vary from one execution to the next (see \f(CW\*(C`wantarray\*(C'\fR). If no \s-1EXPR\s0
-is given, returns an empty list in list context, the undefined value in
-scalar context, and (of course) nothing at all in a void context.
-.Sp
-(Note that in the absence of an explicit \f(CW\*(C`return\*(C'\fR, a subroutine, eval,
-or do \s-1FILE\s0 will automatically return the value of the last expression
-evaluated.)
-.IP "reverse \s-1LIST\s0" 8
-.IX Xref "reverse rev invert"
-.IX Item "reverse LIST"
-In list context, returns a list value consisting of the elements
-of \s-1LIST\s0 in the opposite order. In scalar context, concatenates the
-elements of \s-1LIST\s0 and returns a string value with all characters
-in the opposite order.
-.Sp
-.Vb 1
-\& print reverse <>; # line tac, last line first
-.Ve
-.Sp
-.Vb 2
-\& undef $/; # for efficiency of <>
-\& print scalar reverse <>; # character tac, last line tsrif
-.Ve
-.Sp
-Used without arguments in scalar context, \fIreverse()\fR reverses \f(CW$_\fR.
-.Sp
-This operator is also handy for inverting a hash, although there are some
-caveats. If a value is duplicated in the original hash, only one of those
-can be represented as a key in the inverted hash. Also, this has to
-unwind one hash and build a whole new one, which may take some time
-on a large hash, such as from a \s-1DBM\s0 file.
-.Sp
-.Vb 1
-\& %by_name = reverse %by_address; # Invert the hash
-.Ve
-.IP "rewinddir \s-1DIRHANDLE\s0" 8
-.IX Xref "rewinddir"
-.IX Item "rewinddir DIRHANDLE"
-Sets the current position to the beginning of the directory for the
-\&\f(CW\*(C`readdir\*(C'\fR routine on \s-1DIRHANDLE\s0.
-.IP "rindex \s-1STR\s0,SUBSTR,POSITION" 8
-.IX Xref "rindex"
-.IX Item "rindex STR,SUBSTR,POSITION"
-.PD 0
-.IP "rindex \s-1STR\s0,SUBSTR" 8
-.IX Item "rindex STR,SUBSTR"
-.PD
-Works just like \fIindex()\fR except that it returns the position of the \fIlast\fR
-occurrence of \s-1SUBSTR\s0 in \s-1STR\s0. If \s-1POSITION\s0 is specified, returns the
-last occurrence beginning at or before that position.
-.IP "rmdir \s-1FILENAME\s0" 8
-.IX Xref "rmdir rd directory, remove"
-.IX Item "rmdir FILENAME"
-.PD 0
-.IP "rmdir" 8
-.IX Item "rmdir"
-.PD
-Deletes the directory specified by \s-1FILENAME\s0 if that directory is
-empty. If it succeeds it returns true, otherwise it returns false and
-sets \f(CW$!\fR (errno). If \s-1FILENAME\s0 is omitted, uses \f(CW$_\fR.
-.IP "s///" 8
-.IX Item "s///"
-The substitution operator. See perlop.
-.IP "scalar \s-1EXPR\s0" 8
-.IX Xref "scalar context"
-.IX Item "scalar EXPR"
-Forces \s-1EXPR\s0 to be interpreted in scalar context and returns the value
-of \s-1EXPR\s0.
-.Sp
-.Vb 1
-\& @counts = ( scalar @a, scalar @b, scalar @c );
-.Ve
-.Sp
-There is no equivalent operator to force an expression to
-be interpolated in list context because in practice, this is never
-needed. If you really wanted to do so, however, you could use
-the construction \f(CW\*(C`@{[ (some expression) ]}\*(C'\fR, but usually a simple
-\&\f(CW\*(C`(some expression)\*(C'\fR suffices.
-.Sp
-Because \f(CW\*(C`scalar\*(C'\fR is unary operator, if you accidentally use for \s-1EXPR\s0 a
-parenthesized list, this behaves as a scalar comma expression, evaluating
-all but the last element in void context and returning the final element
-evaluated in scalar context. This is seldom what you want.
-.Sp
-The following single statement:
-.Sp
-.Vb 1
-\& print uc(scalar(&foo,$bar)),$baz;
-.Ve
-.Sp
-is the moral equivalent of these two:
-.Sp
-.Vb 2
-\& &foo;
-\& print(uc($bar),$baz);
-.Ve
-.Sp
-See perlop for more details on unary operators and the comma operator.
-.IP "seek \s-1FILEHANDLE\s0,POSITION,WHENCE" 8
-.IX Xref "seek fseek filehandle, position"
-.IX Item "seek FILEHANDLE,POSITION,WHENCE"
-Sets \s-1FILEHANDLE\s0's position, just like the \f(CW\*(C`fseek\*(C'\fR call of \f(CW\*(C`stdio\*(C'\fR.
-\&\s-1FILEHANDLE\s0 may be an expression whose value gives the name of the
-filehandle. The values for \s-1WHENCE\s0 are \f(CW0\fR to set the new position
-\&\fIin bytes\fR to \s-1POSITION\s0, \f(CW1\fR to set it to the current position plus
-\&\s-1POSITION\s0, and \f(CW2\fR to set it to \s-1EOF\s0 plus \s-1POSITION\s0 (typically
-negative). For \s-1WHENCE\s0 you may use the constants \f(CW\*(C`SEEK_SET\*(C'\fR,
-\&\f(CW\*(C`SEEK_CUR\*(C'\fR, and \f(CW\*(C`SEEK_END\*(C'\fR (start of the file, current position, end
-of the file) from the Fcntl module. Returns \f(CW1\fR upon success, \f(CW0\fR
-otherwise.
-.Sp
-Note the \fIin bytes\fR: even if the filehandle has been set to
-operate on characters (for example by using the \f(CW\*(C`:utf8\*(C'\fR open
-layer), \fItell()\fR will return byte offsets, not character offsets
-(because implementing that would render \fIseek()\fR and \fItell()\fR rather slow).
-.Sp
-If you want to position file for \f(CW\*(C`sysread\*(C'\fR or \f(CW\*(C`syswrite\*(C'\fR, don't use
-\&\f(CW\*(C`seek\*(C'\fR\-\-buffering makes its effect on the file's system position
-unpredictable and non\-portable. Use \f(CW\*(C`sysseek\*(C'\fR instead.
-.Sp
-Due to the rules and rigors of \s-1ANSI\s0 C, on some systems you have to do a
-seek whenever you switch between reading and writing. Amongst other
-things, this may have the effect of calling stdio's \fIclearerr\fR\|(3).
-A \s-1WHENCE\s0 of \f(CW1\fR (\f(CW\*(C`SEEK_CUR\*(C'\fR) is useful for not moving the file position:
-.Sp
-.Vb 1
-\& seek(TEST,0,1);
-.Ve
-.Sp
-This is also useful for applications emulating \f(CW\*(C`tail \-f\*(C'\fR. Once you hit
-\&\s-1EOF\s0 on your read, and then sleep for a while, you might have to stick in a
-\&\fIseek()\fR to reset things. The \f(CW\*(C`seek\*(C'\fR doesn't change the current position,
-but it \fIdoes\fR clear the end-of-file condition on the handle, so that the
-next \f(CW\*(C`<FILE>\*(C'\fR makes Perl try again to read something. We hope.
-.Sp
-If that doesn't work (some \s-1IO\s0 implementations are particularly
-cantankerous), then you may need something more like this:
-.Sp
-.Vb 8
-\& for (;;) {
-\& for ($curpos = tell(FILE); $_ = <FILE>;
-\& $curpos = tell(FILE)) {
-\& # search for some stuff and put it into files
-\& }
-\& sleep($for_a_while);
-\& seek(FILE, $curpos, 0);
-\& }
-.Ve
-.IP "seekdir \s-1DIRHANDLE\s0,POS" 8
-.IX Xref "seekdir"
-.IX Item "seekdir DIRHANDLE,POS"
-Sets the current position for the \f(CW\*(C`readdir\*(C'\fR routine on \s-1DIRHANDLE\s0. \s-1POS\s0
-must be a value returned by \f(CW\*(C`telldir\*(C'\fR. \f(CW\*(C`seekdir\*(C'\fR also has the same caveats
-about possible directory compaction as the corresponding system library
-routine.
-.IP "select \s-1FILEHANDLE\s0" 8
-.IX Xref "select filehandle, default"
-.IX Item "select FILEHANDLE"
-.PD 0
-.IP "select" 8
-.IX Item "select"
-.PD
-Returns the currently selected filehandle. Sets the current default
-filehandle for output, if \s-1FILEHANDLE\s0 is supplied. This has two
-effects: first, a \f(CW\*(C`write\*(C'\fR or a \f(CW\*(C`print\*(C'\fR without a filehandle will
-default to this \s-1FILEHANDLE\s0. Second, references to variables related to
-output will refer to this output channel. For example, if you have to
-set the top of form format for more than one output channel, you might
-do the following:
-.Sp
-.Vb 4
-\& select(REPORT1);
-\& $^ = 'report1_top';
-\& select(REPORT2);
-\& $^ = 'report2_top';
-.Ve
-.Sp
-\&\s-1FILEHANDLE\s0 may be an expression whose value gives the name of the
-actual filehandle. Thus:
-.Sp
-.Vb 1
-\& $oldfh = select(STDERR); $| = 1; select($oldfh);
-.Ve
-.Sp
-Some programmers may prefer to think of filehandles as objects with
-methods, preferring to write the last example as:
-.Sp
-.Vb 2
-\& use IO::Handle;
-\& STDERR->autoflush(1);
-.Ve
-.IP "select \s-1RBITS\s0,WBITS,EBITS,TIMEOUT" 8
-.IX Xref "select"
-.IX Item "select RBITS,WBITS,EBITS,TIMEOUT"
-This calls the \fIselect\fR\|(2) system call with the bit masks specified, which
-can be constructed using \f(CW\*(C`fileno\*(C'\fR and \f(CW\*(C`vec\*(C'\fR, along these lines:
-.Sp
-.Vb 4
-\& $rin = $win = $ein = '';
-\& vec($rin,fileno(STDIN),1) = 1;
-\& vec($win,fileno(STDOUT),1) = 1;
-\& $ein = $rin | $win;
-.Ve
-.Sp
-If you want to select on many filehandles you might wish to write a
-subroutine:
-.Sp
-.Vb 9
-\& sub fhbits {
-\& my(@fhlist) = split(' ',$_[0]);
-\& my($bits);
-\& for (@fhlist) {
-\& vec($bits,fileno($_),1) = 1;
-\& }
-\& $bits;
-\& }
-\& $rin = fhbits('STDIN TTY SOCK');
-.Ve
-.Sp
-The usual idiom is:
-.Sp
-.Vb 2
-\& ($nfound,$timeleft) =
-\& select($rout=$rin, $wout=$win, $eout=$ein, $timeout);
-.Ve
-.Sp
-or to block until something becomes ready just do this
-.Sp
-.Vb 1
-\& $nfound = select($rout=$rin, $wout=$win, $eout=$ein, undef);
-.Ve
-.Sp
-Most systems do not bother to return anything useful in \f(CW$timeleft\fR, so
-calling \fIselect()\fR in scalar context just returns \f(CW$nfound\fR.
-.Sp
-Any of the bit masks can also be undef. The timeout, if specified, is
-in seconds, which may be fractional. Note: not all implementations are
-capable of returning the \f(CW$timeleft\fR. If not, they always return
-\&\f(CW$timeleft\fR equal to the supplied \f(CW$timeout\fR.
-.Sp
-You can effect a sleep of 250 milliseconds this way:
-.Sp
-.Vb 1
-\& select(undef, undef, undef, 0.25);
-.Ve
-.Sp
-Note that whether \f(CW\*(C`select\*(C'\fR gets restarted after signals (say, \s-1SIGALRM\s0)
-is implementation\-dependent. See also perlport for notes on the
-portability of \f(CW\*(C`select\*(C'\fR.
-.Sp
-On error, \f(CW\*(C`select\*(C'\fR behaves like the \fIselect\fR\|(2) system call : it returns
-\&\-1 and sets \f(CW$!\fR.
-.Sp
-Note: on some Unixes, the \fIselect\fR\|(2) system call may report a socket file
-descriptor as \*(L"ready for reading\*(R", when actually no data is available,
-thus a subsequent read blocks. It can be avoided using always the
-O_NONBLOCK flag on the socket. See \fIselect\fR\|(2) and \fIfcntl\fR\|(2) for further
-details.
-.Sp
-\&\fB\s-1WARNING\s0\fR: One should not attempt to mix buffered I/O (like \f(CW\*(C`read\*(C'\fR
-or <\s-1FH\s0>) with \f(CW\*(C`select\*(C'\fR, except as permitted by \s-1POSIX\s0, and even
-then only on \s-1POSIX\s0 systems. You have to use \f(CW\*(C`sysread\*(C'\fR instead.
-.IP "semctl \s-1ID\s0,SEMNUM,CMD,ARG" 8
-.IX Xref "semctl"
-.IX Item "semctl ID,SEMNUM,CMD,ARG"
-Calls the System V \s-1IPC\s0 function \f(CW\*(C`semctl\*(C'\fR. You'll probably have to say
-.Sp
-.Vb 1
-\& use IPC::SysV;
-.Ve
-.Sp
-first to get the correct constant definitions. If \s-1CMD\s0 is \s-1IPC_STAT\s0 or
-\&\s-1GETALL\s0, then \s-1ARG\s0 must be a variable that will hold the returned
-semid_ds structure or semaphore value array. Returns like \f(CW\*(C`ioctl\*(C'\fR:
-the undefined value for error, "\f(CW\*(C`0 but true\*(C'\fR" for zero, or the actual
-return value otherwise. The \s-1ARG\s0 must consist of a vector of native
-short integers, which may be created with \f(CW\*(C`pack("s!",(0)x$nsem)\*(C'\fR.
-See also \*(L"SysV \s-1IPC\s0\*(R" in perlipc, \f(CW\*(C`IPC::SysV\*(C'\fR, \f(CW\*(C`IPC::Semaphore\*(C'\fR
-documentation.
-.IP "semget \s-1KEY\s0,NSEMS,FLAGS" 8
-.IX Xref "semget"
-.IX Item "semget KEY,NSEMS,FLAGS"
-Calls the System V \s-1IPC\s0 function semget. Returns the semaphore id, or
-the undefined value if there is an error. See also
-\&\*(L"SysV \s-1IPC\s0\*(R" in perlipc, \f(CW\*(C`IPC::SysV\*(C'\fR, \f(CW\*(C`IPC::SysV::Semaphore\*(C'\fR
-documentation.
-.IP "semop \s-1KEY\s0,OPSTRING" 8
-.IX Xref "semop"
-.IX Item "semop KEY,OPSTRING"
-Calls the System V \s-1IPC\s0 function semop to perform semaphore operations
-such as signalling and waiting. \s-1OPSTRING\s0 must be a packed array of
-semop structures. Each semop structure can be generated with
-\&\f(CW\*(C`pack("s!3", $semnum, $semop, $semflag)\*(C'\fR. The length of \s-1OPSTRING\s0
-implies the number of semaphore operations. Returns true if
-successful, or false if there is an error. As an example, the
-following code waits on semaphore \f(CW$semnum\fR of semaphore id \f(CW$semid:\fR
-.Sp
-.Vb 2
-\& $semop = pack("s!3", $semnum, -1, 0);
-\& die "Semaphore trouble: $!\en" unless semop($semid, $semop);
-.Ve
-.Sp
-To signal the semaphore, replace \f(CW\*(C`\-1\*(C'\fR with \f(CW1\fR. See also
-\&\*(L"SysV \s-1IPC\s0\*(R" in perlipc, \f(CW\*(C`IPC::SysV\*(C'\fR, and \f(CW\*(C`IPC::SysV::Semaphore\*(C'\fR
-documentation.
-.IP "send \s-1SOCKET\s0,MSG,FLAGS,TO" 8
-.IX Xref "send"
-.IX Item "send SOCKET,MSG,FLAGS,TO"
-.PD 0
-.IP "send \s-1SOCKET\s0,MSG,FLAGS" 8
-.IX Item "send SOCKET,MSG,FLAGS"
-.PD
-Sends a message on a socket. Attempts to send the scalar \s-1MSG\s0 to the
-\&\s-1SOCKET\s0 filehandle. Takes the same flags as the system call of the
-same name. On unconnected sockets you must specify a destination to
-send \s-1TO\s0, in which case it does a C \f(CW\*(C`sendto\*(C'\fR. Returns the number of
-characters sent, or the undefined value if there is an error. The C
-system call \fIsendmsg\fR\|(2) is currently unimplemented. See
-\&\*(L"\s-1UDP:\s0 Message Passing\*(R" in perlipc for examples.
-.Sp
-Note the \fIcharacters\fR: depending on the status of the socket, either
-(8\-bit) bytes or characters are sent. By default all sockets operate
-on bytes, but for example if the socket has been changed using
-\&\fIbinmode()\fR to operate with the \f(CW\*(C`:utf8\*(C'\fR I/O layer (see \*(L"open\*(R", or the
-\&\f(CW\*(C`open\*(C'\fR pragma, open), the I/O will operate on \s-1UTF\-8\s0 encoded
-Unicode characters, not bytes. Similarly for the \f(CW\*(C`:encoding\*(C'\fR pragma:
-in that case pretty much any characters can be sent.
-.IP "setpgrp \s-1PID\s0,PGRP" 8
-.IX Xref "setpgrp group"
-.IX Item "setpgrp PID,PGRP"
-Sets the current process group for the specified \s-1PID\s0, \f(CW0\fR for the current
-process. Will produce a fatal error if used on a machine that doesn't
-implement \s-1POSIX\s0 \fIsetpgid\fR\|(2) or \s-1BSD\s0 \fIsetpgrp\fR\|(2). If the arguments are omitted,
-it defaults to \f(CW\*(C`0,0\*(C'\fR. Note that the \s-1BSD\s0 4.2 version of \f(CW\*(C`setpgrp\*(C'\fR does not
-accept any arguments, so only \f(CW\*(C`setpgrp(0,0)\*(C'\fR is portable. See also
-\&\f(CW\*(C`POSIX::setsid()\*(C'\fR.
-.IP "setpriority \s-1WHICH\s0,WHO,PRIORITY" 8
-.IX Xref "setpriority priority nice renice"
-.IX Item "setpriority WHICH,WHO,PRIORITY"
-Sets the current priority for a process, a process group, or a user.
-(See \fIsetpriority\fR\|(2).) Will produce a fatal error if used on a machine
-that doesn't implement \fIsetpriority\fR\|(2).
-.IP "setsockopt \s-1SOCKET\s0,LEVEL,OPTNAME,OPTVAL" 8
-.IX Xref "setsockopt"
-.IX Item "setsockopt SOCKET,LEVEL,OPTNAME,OPTVAL"
-Sets the socket option requested. Returns undefined if there is an
-error. Use integer constants provided by the \f(CW\*(C`Socket\*(C'\fR module for
-\&\s-1LEVEL\s0 and \s-1OPNAME\s0. Values for \s-1LEVEL\s0 can also be obtained from
-getprotobyname. \s-1OPTVAL\s0 might either be a packed string or an integer.
-An integer \s-1OPTVAL\s0 is shorthand for pack(\*(L"i\*(R", \s-1OPTVAL\s0).
-.Sp
-An example disabling the Nagle's algorithm for a socket:
-.Sp
-.Vb 2
-\& use Socket qw(IPPROTO_TCP TCP_NODELAY);
-\& setsockopt($socket, IPPROTO_TCP, TCP_NODELAY, 1);
-.Ve
-.IP "shift \s-1ARRAY\s0" 8
-.IX Xref "shift"
-.IX Item "shift ARRAY"
-.PD 0
-.IP "shift" 8
-.IX Item "shift"
-.PD
-Shifts the first value of the array off and returns it, shortening the
-array by 1 and moving everything down. If there are no elements in the
-array, returns the undefined value. If \s-1ARRAY\s0 is omitted, shifts the
-\&\f(CW@_\fR array within the lexical scope of subroutines and formats, and the
-\&\f(CW@ARGV\fR array at file scopes or within the lexical scopes established by
-the \f(CW\*(C`eval ''\*(C'\fR, \f(CW\*(C`BEGIN {}\*(C'\fR, \f(CW\*(C`INIT {}\*(C'\fR, \f(CW\*(C`CHECK {}\*(C'\fR, and \f(CW\*(C`END {}\*(C'\fR
-constructs.
-.Sp
-See also \f(CW\*(C`unshift\*(C'\fR, \f(CW\*(C`push\*(C'\fR, and \f(CW\*(C`pop\*(C'\fR. \f(CW\*(C`shift\*(C'\fR and \f(CW\*(C`unshift\*(C'\fR do the
-same thing to the left end of an array that \f(CW\*(C`pop\*(C'\fR and \f(CW\*(C`push\*(C'\fR do to the
-right end.
-.IP "shmctl \s-1ID\s0,CMD,ARG" 8
-.IX Xref "shmctl"
-.IX Item "shmctl ID,CMD,ARG"
-Calls the System V \s-1IPC\s0 function shmctl. You'll probably have to say
-.Sp
-.Vb 1
-\& use IPC::SysV;
-.Ve
-.Sp
-first to get the correct constant definitions. If \s-1CMD\s0 is \f(CW\*(C`IPC_STAT\*(C'\fR,
-then \s-1ARG\s0 must be a variable that will hold the returned \f(CW\*(C`shmid_ds\*(C'\fR
-structure. Returns like ioctl: the undefined value for error, "\f(CW0\fR but
-true" for zero, or the actual return value otherwise.
-See also \*(L"SysV \s-1IPC\s0\*(R" in perlipc and \f(CW\*(C`IPC::SysV\*(C'\fR documentation.
-.IP "shmget \s-1KEY\s0,SIZE,FLAGS" 8
-.IX Xref "shmget"
-.IX Item "shmget KEY,SIZE,FLAGS"
-Calls the System V \s-1IPC\s0 function shmget. Returns the shared memory
-segment id, or the undefined value if there is an error.
-See also \*(L"SysV \s-1IPC\s0\*(R" in perlipc and \f(CW\*(C`IPC::SysV\*(C'\fR documentation.
-.IP "shmread \s-1ID\s0,VAR,POS,SIZE" 8
-.IX Xref "shmread shmwrite"
-.IX Item "shmread ID,VAR,POS,SIZE"
-.PD 0
-.IP "shmwrite \s-1ID\s0,STRING,POS,SIZE" 8
-.IX Item "shmwrite ID,STRING,POS,SIZE"
-.PD
-Reads or writes the System V shared memory segment \s-1ID\s0 starting at
-position \s-1POS\s0 for size \s-1SIZE\s0 by attaching to it, copying in/out, and
-detaching from it. When reading, \s-1VAR\s0 must be a variable that will
-hold the data read. When writing, if \s-1STRING\s0 is too long, only \s-1SIZE\s0
-bytes are used; if \s-1STRING\s0 is too short, nulls are written to fill out
-\&\s-1SIZE\s0 bytes. Return true if successful, or false if there is an error.
-\&\fIshmread()\fR taints the variable. See also \*(L"SysV \s-1IPC\s0\*(R" in perlipc,
-\&\f(CW\*(C`IPC::SysV\*(C'\fR documentation, and the \f(CW\*(C`IPC::Shareable\*(C'\fR module from \s-1CPAN\s0.
-.IP "shutdown \s-1SOCKET\s0,HOW" 8
-.IX Xref "shutdown"
-.IX Item "shutdown SOCKET,HOW"
-Shuts down a socket connection in the manner indicated by \s-1HOW\s0, which
-has the same interpretation as in the system call of the same name.
-.Sp
-.Vb 3
-\& shutdown(SOCKET, 0); # I/we have stopped reading data
-\& shutdown(SOCKET, 1); # I/we have stopped writing data
-\& shutdown(SOCKET, 2); # I/we have stopped using this socket
-.Ve
-.Sp
-This is useful with sockets when you want to tell the other
-side you're done writing but not done reading, or vice versa.
-It's also a more insistent form of close because it also
-disables the file descriptor in any forked copies in other
-processes.
-.IP "sin \s-1EXPR\s0" 8
-.IX Xref "sin sine asin arcsine"
-.IX Item "sin EXPR"
-.PD 0
-.IP "sin" 8
-.IX Item "sin"
-.PD
-Returns the sine of \s-1EXPR\s0 (expressed in radians). If \s-1EXPR\s0 is omitted,
-returns sine of \f(CW$_\fR.
-.Sp
-For the inverse sine operation, you may use the \f(CW\*(C`Math::Trig::asin\*(C'\fR
-function, or use this relation:
-.Sp
-.Vb 1
-\& sub asin { atan2($_[0], sqrt(1 - $_[0] * $_[0])) }
-.Ve
-.IP "sleep \s-1EXPR\s0" 8
-.IX Xref "sleep pause"
-.IX Item "sleep EXPR"
-.PD 0
-.IP "sleep" 8
-.IX Item "sleep"
-.PD
-Causes the script to sleep for \s-1EXPR\s0 seconds, or forever if no \s-1EXPR\s0.
-May be interrupted if the process receives a signal such as \f(CW\*(C`SIGALRM\*(C'\fR.
-Returns the number of seconds actually slept. You probably cannot
-mix \f(CW\*(C`alarm\*(C'\fR and \f(CW\*(C`sleep\*(C'\fR calls, because \f(CW\*(C`sleep\*(C'\fR is often implemented
-using \f(CW\*(C`alarm\*(C'\fR.
-.Sp
-On some older systems, it may sleep up to a full second less than what
-you requested, depending on how it counts seconds. Most modern systems
-always sleep the full amount. They may appear to sleep longer than that,
-however, because your process might not be scheduled right away in a
-busy multitasking system.
-.Sp
-For delays of finer granularity than one second, you may use Perl's
-\&\f(CW\*(C`syscall\*(C'\fR interface to access \fIsetitimer\fR\|(2) if your system supports
-it, or else see \*(L"select\*(R" above. The Time::HiRes module (from \s-1CPAN\s0,
-and starting from Perl 5.8 part of the standard distribution) may also
-help.
-.Sp
-See also the \s-1POSIX\s0 module's \f(CW\*(C`pause\*(C'\fR function.
-.IP "socket \s-1SOCKET\s0,DOMAIN,TYPE,PROTOCOL" 8
-.IX Xref "socket"
-.IX Item "socket SOCKET,DOMAIN,TYPE,PROTOCOL"
-Opens a socket of the specified kind and attaches it to filehandle
-\&\s-1SOCKET\s0. \s-1DOMAIN\s0, \s-1TYPE\s0, and \s-1PROTOCOL\s0 are specified the same as for
-the system call of the same name. You should \f(CW\*(C`use Socket\*(C'\fR first
-to get the proper definitions imported. See the examples in
-\&\*(L"Sockets: Client/Server Communication\*(R" in perlipc.
-.Sp
-On systems that support a close-on-exec flag on files, the flag will
-be set for the newly opened file descriptor, as determined by the
-value of $^F. See \*(L"$^F\*(R" in perlvar.
-.IP "socketpair \s-1SOCKET1\s0,SOCKET2,DOMAIN,TYPE,PROTOCOL" 8
-.IX Xref "socketpair"
-.IX Item "socketpair SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL"
-Creates an unnamed pair of sockets in the specified domain, of the
-specified type. \s-1DOMAIN\s0, \s-1TYPE\s0, and \s-1PROTOCOL\s0 are specified the same as
-for the system call of the same name. If unimplemented, yields a fatal
-error. Returns true if successful.
-.Sp
-On systems that support a close-on-exec flag on files, the flag will
-be set for the newly opened file descriptors, as determined by the value
-of $^F. See \*(L"$^F\*(R" in perlvar.
-.Sp
-Some systems defined \f(CW\*(C`pipe\*(C'\fR in terms of \f(CW\*(C`socketpair\*(C'\fR, in which a call
-to \f(CW\*(C`pipe(Rdr, Wtr)\*(C'\fR is essentially:
-.Sp
-.Vb 4
-\& use Socket;
-\& socketpair(Rdr, Wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
-\& shutdown(Rdr, 1); # no more writing for reader
-\& shutdown(Wtr, 0); # no more reading for writer
-.Ve
-.Sp
-See perlipc for an example of socketpair use. Perl 5.8 and later will
-emulate socketpair using \s-1IP\s0 sockets to localhost if your system implements
-sockets but not socketpair.
-.IP "sort \s-1SUBNAME\s0 \s-1LIST\s0" 8
-.IX Xref "sort qsort quicksort mergesort"
-.IX Item "sort SUBNAME LIST"
-.PD 0
-.IP "sort \s-1BLOCK\s0 \s-1LIST\s0" 8
-.IX Item "sort BLOCK LIST"
-.IP "sort \s-1LIST\s0" 8
-.IX Item "sort LIST"
-.PD
-In list context, this sorts the \s-1LIST\s0 and returns the sorted list value.
-In scalar context, the behaviour of \f(CW\*(C`sort()\*(C'\fR is undefined.
-.Sp
-If \s-1SUBNAME\s0 or \s-1BLOCK\s0 is omitted, \f(CW\*(C`sort\*(C'\fRs in standard string comparison
-order. If \s-1SUBNAME\s0 is specified, it gives the name of a subroutine
-that returns an integer less than, equal to, or greater than \f(CW0\fR,
-depending on how the elements of the list are to be ordered. (The \f(CW\*(C`<=>\*(C'\fR and \f(CW\*(C`cmp\*(C'\fR operators are extremely useful in such routines.)
-\&\s-1SUBNAME\s0 may be a scalar variable name (unsubscripted), in which case
-the value provides the name of (or a reference to) the actual
-subroutine to use. In place of a \s-1SUBNAME\s0, you can provide a \s-1BLOCK\s0 as
-an anonymous, in-line sort subroutine.
-.Sp
-If the subroutine's prototype is \f(CW\*(C`($$)\*(C'\fR, the elements to be compared
-are passed by reference in \f(CW@_\fR, as for a normal subroutine. This is
-slower than unprototyped subroutines, where the elements to be
-compared are passed into the subroutine
-as the package global variables \f(CW$a\fR and \f(CW$b\fR (see example below). Note that
-in the latter case, it is usually counter-productive to declare \f(CW$a\fR and
-\&\f(CW$b\fR as lexicals.
-.Sp
-In either case, the subroutine may not be recursive. The values to be
-compared are always passed by reference and should not be modified.
-.Sp
-You also cannot exit out of the sort block or subroutine using any of the
-loop control operators described in perlsyn or with \f(CW\*(C`goto\*(C'\fR.
-.Sp
-When \f(CW\*(C`use locale\*(C'\fR is in effect, \f(CW\*(C`sort LIST\*(C'\fR sorts \s-1LIST\s0 according to the
-current collation locale. See perllocale.
-.Sp
-\&\fIsort()\fR returns aliases into the original list, much as a for loop's index
-variable aliases the list elements. That is, modifying an element of a
-list returned by \fIsort()\fR (for example, in a \f(CW\*(C`foreach\*(C'\fR, \f(CW\*(C`map\*(C'\fR or \f(CW\*(C`grep\*(C'\fR)
-actually modifies the element in the original list. This is usually
-something to be avoided when writing clear code.
-.Sp
-Perl 5.6 and earlier used a quicksort algorithm to implement sort.
-That algorithm was not stable, and \fIcould\fR go quadratic. (A \fIstable\fR sort
-preserves the input order of elements that compare equal. Although
-quicksort's run time is O(NlogN) when averaged over all arrays of
-length N, the time can be O(N**2), \fIquadratic\fR behavior, for some
-inputs.) In 5.7, the quicksort implementation was replaced with
-a stable mergesort algorithm whose worst-case behavior is O(NlogN).
-But benchmarks indicated that for some inputs, on some platforms,
-the original quicksort was faster. 5.8 has a sort pragma for
-limited control of the sort. Its rather blunt control of the
-underlying algorithm may not persist into future Perls, but the
-ability to characterize the input or output in implementation
-independent ways quite probably will. See sort.
-.Sp
-Examples:
-.Sp
-.Vb 2
-\& # sort lexically
-\& @articles = sort @files;
-.Ve
-.Sp
-.Vb 2
-\& # same thing, but with explicit sort routine
-\& @articles = sort {$a cmp $b} @files;
-.Ve
-.Sp
-.Vb 2
-\& # now case-insensitively
-\& @articles = sort {uc($a) cmp uc($b)} @files;
-.Ve
-.Sp
-.Vb 2
-\& # same thing in reversed order
-\& @articles = sort {$b cmp $a} @files;
-.Ve
-.Sp
-.Vb 2
-\& # sort numerically ascending
-\& @articles = sort {$a <=> $b} @files;
-.Ve
-.Sp
-.Vb 2
-\& # sort numerically descending
-\& @articles = sort {$b <=> $a} @files;
-.Ve
-.Sp
-.Vb 3
-\& # this sorts the %age hash by value instead of key
-\& # using an in-line function
-\& @eldest = sort { $age{$b} <=> $age{$a} } keys %age;
-.Ve
-.Sp
-.Vb 5
-\& # sort using explicit subroutine name
-\& sub byage {
-\& $age{$a} <=> $age{$b}; # presuming numeric
-\& }
-\& @sortedclass = sort byage @class;
-.Ve
-.Sp
-.Vb 9
-\& sub backwards { $b cmp $a }
-\& @harry = qw(dog cat x Cain Abel);
-\& @george = qw(gone chased yz Punished Axed);
-\& print sort @harry;
-\& # prints AbelCaincatdogx
-\& print sort backwards @harry;
-\& # prints xdogcatCainAbel
-\& print sort @george, 'to', @harry;
-\& # prints AbelAxedCainPunishedcatchaseddoggonetoxyz
-.Ve
-.Sp
-.Vb 3
-\& # inefficiently sort by descending numeric compare using
-\& # the first integer after the first = sign, or the
-\& # whole record case-insensitively otherwise
-.Ve
-.Sp
-.Vb 5
-\& @new = sort {
-\& ($b =~ /=(\ed+)/)[0] <=> ($a =~ /=(\ed+)/)[0]
-\& ||
-\& uc($a) cmp uc($b)
-\& } @old;
-.Ve
-.Sp
-.Vb 8
-\& # same thing, but much more efficiently;
-\& # we'll build auxiliary indices instead
-\& # for speed
-\& @nums = @caps = ();
-\& for (@old) {
-\& push @nums, /=(\ed+)/;
-\& push @caps, uc($_);
-\& }
-.Ve
-.Sp
-.Vb 6
-\& @new = @old[ sort {
-\& $nums[$b] <=> $nums[$a]
-\& ||
-\& $caps[$a] cmp $caps[$b]
-\& } 0..$#old
-\& ];
-.Ve
-.Sp
-.Vb 6
-\& # same thing, but without any temps
-\& @new = map { $_->[0] }
-\& sort { $b->[1] <=> $a->[1]
-\& ||
-\& $a->[2] cmp $b->[2]
-\& } map { [$_, /=(\ed+)/, uc($_)] } @old;
-.Ve
-.Sp
-.Vb 4
-\& # using a prototype allows you to use any comparison subroutine
-\& # as a sort subroutine (including other package's subroutines)
-\& package other;
-\& sub backwards ($$) { $_[1] cmp $_[0]; } # $a and $b are not set here
-.Ve
-.Sp
-.Vb 2
-\& package main;
-\& @new = sort other::backwards @old;
-.Ve
-.Sp
-.Vb 3
-\& # guarantee stability, regardless of algorithm
-\& use sort 'stable';
-\& @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
-.Ve
-.Sp
-.Vb 3
-\& # force use of mergesort (not portable outside Perl 5.8)
-\& use sort '_mergesort'; # note discouraging _
-\& @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
-.Ve
-.Sp
-If you're using strict, you \fImust not\fR declare \f(CW$a\fR
-and \f(CW$b\fR as lexicals. They are package globals. That means
-if you're in the \f(CW\*(C`main\*(C'\fR package and type
-.Sp
-.Vb 1
-\& @articles = sort {$b <=> $a} @files;
-.Ve
-.Sp
-then \f(CW$a\fR and \f(CW$b\fR are \f(CW$main::a\fR and \f(CW$main::b\fR (or \f(CW$::a\fR and \f(CW$::b\fR),
-but if you're in the \f(CW\*(C`FooPack\*(C'\fR package, it's the same as typing
-.Sp
-.Vb 1
-\& @articles = sort {$FooPack::b <=> $FooPack::a} @files;
-.Ve
-.Sp
-The comparison function is required to behave. If it returns
-inconsistent results (sometimes saying \f(CW$x[1]\fR is less than \f(CW$x[2]\fR and
-sometimes saying the opposite, for example) the results are not
-well\-defined.
-.Sp
-Because \f(CW\*(C`<=>\*(C'\fR returns \f(CW\*(C`undef\*(C'\fR when either operand is \f(CW\*(C`NaN\*(C'\fR
-(not\-a\-number), and because \f(CW\*(C`sort\*(C'\fR will trigger a fatal error unless the
-result of a comparison is defined, when sorting with a comparison function
-like \f(CW\*(C`$a <=> $b\*(C'\fR, be careful about lists that might contain a \f(CW\*(C`NaN\*(C'\fR.
-The following example takes advantage of the fact that \f(CW\*(C`NaN != NaN\*(C'\fR to
-eliminate any \f(CW\*(C`NaN\*(C'\fRs from the input.
-.Sp
-.Vb 1
-\& @result = sort { $a <=> $b } grep { $_ == $_ } @input;
-.Ve
-.IP "splice \s-1ARRAY\s0,OFFSET,LENGTH,LIST" 8
-.IX Xref "splice"
-.IX Item "splice ARRAY,OFFSET,LENGTH,LIST"
-.PD 0
-.IP "splice \s-1ARRAY\s0,OFFSET,LENGTH" 8
-.IX Item "splice ARRAY,OFFSET,LENGTH"
-.IP "splice \s-1ARRAY\s0,OFFSET" 8
-.IX Item "splice ARRAY,OFFSET"
-.IP "splice \s-1ARRAY\s0" 8
-.IX Item "splice ARRAY"
-.PD
-Removes the elements designated by \s-1OFFSET\s0 and \s-1LENGTH\s0 from an array, and
-replaces them with the elements of \s-1LIST\s0, if any. In list context,
-returns the elements removed from the array. In scalar context,
-returns the last element removed, or \f(CW\*(C`undef\*(C'\fR if no elements are
-removed. The array grows or shrinks as necessary.
-If \s-1OFFSET\s0 is negative then it starts that far from the end of the array.
-If \s-1LENGTH\s0 is omitted, removes everything from \s-1OFFSET\s0 onward.
-If \s-1LENGTH\s0 is negative, removes the elements from \s-1OFFSET\s0 onward
-except for \-LENGTH elements at the end of the array.
-If both \s-1OFFSET\s0 and \s-1LENGTH\s0 are omitted, removes everything. If \s-1OFFSET\s0 is
-past the end of the array, perl issues a warning, and splices at the
-end of the array.
-.Sp
-The following equivalences hold (assuming \f(CW\*(C`$[ == 0 and $#a >= $i\*(C'\fR )
-.Sp
-.Vb 5
-\& push(@a,$x,$y) splice(@a,@a,0,$x,$y)
-\& pop(@a) splice(@a,-1)
-\& shift(@a) splice(@a,0,1)
-\& unshift(@a,$x,$y) splice(@a,0,0,$x,$y)
-\& $a[$i] = $y splice(@a,$i,1,$y)
-.Ve
-.Sp
-Example, assuming array lengths are passed before arrays:
-.Sp
-.Vb 10
-\& sub aeq { # compare two list values
-\& my(@a) = splice(@_,0,shift);
-\& my(@b) = splice(@_,0,shift);
-\& return 0 unless @a == @b; # same len?
-\& while (@a) {
-\& return 0 if pop(@a) ne pop(@b);
-\& }
-\& return 1;
-\& }
-\& if (&aeq($len,@foo[1..$len],0+@bar,@bar)) { ... }
-.Ve
-.IP "split /PATTERN/,EXPR,LIMIT" 8
-.IX Xref "split"
-.IX Item "split /PATTERN/,EXPR,LIMIT"
-.PD 0
-.IP "split /PATTERN/,EXPR" 8
-.IX Item "split /PATTERN/,EXPR"
-.IP "split /PATTERN/" 8
-.IX Item "split /PATTERN/"
-.IP "split" 8
-.IX Item "split"
-.PD
-Splits the string \s-1EXPR\s0 into a list of strings and returns that list. By
-default, empty leading fields are preserved, and empty trailing ones are
-deleted. (If all fields are empty, they are considered to be trailing.)
-.Sp
-In scalar context, returns the number of fields found and splits into
-the \f(CW@_\fR array. Use of split in scalar context is deprecated, however,
-because it clobbers your subroutine arguments.
-.Sp
-If \s-1EXPR\s0 is omitted, splits the \f(CW$_\fR string. If \s-1PATTERN\s0 is also omitted,
-splits on whitespace (after skipping any leading whitespace). Anything
-matching \s-1PATTERN\s0 is taken to be a delimiter separating the fields. (Note
-that the delimiter may be longer than one character.)
-.Sp
-If \s-1LIMIT\s0 is specified and positive, it represents the maximum number
-of fields the \s-1EXPR\s0 will be split into, though the actual number of
-fields returned depends on the number of times \s-1PATTERN\s0 matches within
-\&\s-1EXPR\s0. If \s-1LIMIT\s0 is unspecified or zero, trailing null fields are
-stripped (which potential users of \f(CW\*(C`pop\*(C'\fR would do well to remember).
-If \s-1LIMIT\s0 is negative, it is treated as if an arbitrarily large \s-1LIMIT\s0
-had been specified. Note that splitting an \s-1EXPR\s0 that evaluates to the
-empty string always returns the empty list, regardless of the \s-1LIMIT\s0
-specified.
-.Sp
-A pattern matching the null string (not to be confused with
-a null pattern \f(CW\*(C`//\*(C'\fR, which is just one member of the set of patterns
-matching a null string) will split the value of \s-1EXPR\s0 into separate
-characters at each point it matches that way. For example:
-.Sp
-.Vb 1
-\& print join(':', split(/ */, 'hi there'));
-.Ve
-.Sp
-produces the output 'h:i:t:h:e:r:e'.
-.Sp
-As a special case for \f(CW\*(C`split\*(C'\fR, using the empty pattern \f(CW\*(C`//\*(C'\fR specifically
-matches only the null string, and is not be confused with the regular use
-of \f(CW\*(C`//\*(C'\fR to mean \*(L"the last successful pattern match\*(R". So, for \f(CW\*(C`split\*(C'\fR,
-the following:
-.Sp
-.Vb 1
-\& print join(':', split(//, 'hi there'));
-.Ve
-.Sp
-produces the output 'h:i: :t:h:e:r:e'.
-.Sp
-Empty leading (or trailing) fields are produced when there are positive
-width matches at the beginning (or end) of the string; a zero-width match
-at the beginning (or end) of the string does not produce an empty field.
-For example:
-.Sp
-.Vb 1
-\& print join(':', split(/(?=\ew)/, 'hi there!'));
-.Ve
-.Sp
-produces the output 'h:i :t:h:e:r:e!'.
-.Sp
-The \s-1LIMIT\s0 parameter can be used to split a line partially
-.Sp
-.Vb 1
-\& ($login, $passwd, $remainder) = split(/:/, $_, 3);
-.Ve
-.Sp
-When assigning to a list, if \s-1LIMIT\s0 is omitted, or zero, Perl supplies
-a \s-1LIMIT\s0 one larger than the number of variables in the list, to avoid
-unnecessary work. For the list above \s-1LIMIT\s0 would have been 4 by
-default. In time critical applications it behooves you not to split
-into more fields than you really need.
-.Sp
-If the \s-1PATTERN\s0 contains parentheses, additional list elements are
-created from each matching substring in the delimiter.
-.Sp
-.Vb 1
-\& split(/([,-])/, "1-10,20", 3);
-.Ve
-.Sp
-produces the list value
-.Sp
-.Vb 1
-\& (1, '-', 10, ',', 20)
-.Ve
-.Sp
-If you had the entire header of a normal Unix email message in \f(CW$header\fR,
-you could split it up into fields and their values this way:
-.Sp
-.Vb 2
-\& $header =~ s/\en\es+/ /g; # fix continuation lines
-\& %hdrs = (UNIX_FROM => split /^(\eS*?):\es*/m, $header);
-.Ve
-.Sp
-The pattern \f(CW\*(C`/PATTERN/\*(C'\fR may be replaced with an expression to specify
-patterns that vary at runtime. (To do runtime compilation only once,
-use \f(CW\*(C`/$variable/o\*(C'\fR.)
-.Sp
-As a special case, specifying a \s-1PATTERN\s0 of space (\f(CW'\ '\fR) will split on
-white space just as \f(CW\*(C`split\*(C'\fR with no arguments does. Thus, \f(CW\*(C`split('\ ')\*(C'\fR can
-be used to emulate \fBawk\fR's default behavior, whereas \f(CW\*(C`split(/\ /)\*(C'\fR
-will give you as many null initial fields as there are leading spaces.
-A \f(CW\*(C`split\*(C'\fR on \f(CW\*(C`/\es+/\*(C'\fR is like a \f(CW\*(C`split('\ ')\*(C'\fR except that any leading
-whitespace produces a null first field. A \f(CW\*(C`split\*(C'\fR with no arguments
-really does a \f(CW\*(C`split('\ ',\ $_)\*(C'\fR internally.
-.Sp
-A \s-1PATTERN\s0 of \f(CW\*(C`/^/\*(C'\fR is treated as if it were \f(CW\*(C`/^/m\*(C'\fR, since it isn't
-much use otherwise.
-.Sp
-Example:
-.Sp
-.Vb 7
-\& open(PASSWD, '/etc/passwd');
-\& while (<PASSWD>) {
-\& chomp;
-\& ($login, $passwd, $uid, $gid,
-\& $gcos, $home, $shell) = split(/:/);
-\& #...
-\& }
-.Ve
-.Sp
-As with regular pattern matching, any capturing parentheses that are not
-matched in a \f(CW\*(C`split()\*(C'\fR will be set to \f(CW\*(C`undef\*(C'\fR when returned:
-.Sp
-.Vb 2
-\& @fields = split /(A)|B/, "1A2B3";
-\& # @fields is (1, 'A', 2, undef, 3)
-.Ve
-.IP "sprintf \s-1FORMAT\s0, \s-1LIST\s0" 8
-.IX Xref "sprintf"
-.IX Item "sprintf FORMAT, LIST"
-Returns a string formatted by the usual \f(CW\*(C`printf\*(C'\fR conventions of the C
-library function \f(CW\*(C`sprintf\*(C'\fR. See below for more details
-and see \fIsprintf\fR\|(3) or \fIprintf\fR\|(3) on your system for an explanation of
-the general principles.
-.Sp
-For example:
-.Sp
-.Vb 2
-\& # Format number with up to 8 leading zeroes
-\& $result = sprintf("%08d", $number);
-.Ve
-.Sp
-.Vb 2
-\& # Round number to 3 digits after decimal point
-\& $rounded = sprintf("%.3f", $number);
-.Ve
-.Sp
-Perl does its own \f(CW\*(C`sprintf\*(C'\fR formatting\*(--it emulates the C
-function \f(CW\*(C`sprintf\*(C'\fR, but it doesn't use it (except for floating-point
-numbers, and even then only the standard modifiers are allowed). As a
-result, any non-standard extensions in your local \f(CW\*(C`sprintf\*(C'\fR are not
-available from Perl.
-.Sp
-Unlike \f(CW\*(C`printf\*(C'\fR, \f(CW\*(C`sprintf\*(C'\fR does not do what you probably mean when you
-pass it an array as your first argument. The array is given scalar context,
-and instead of using the 0th element of the array as the format, Perl will
-use the count of elements in the array as the format, which is almost never
-useful.
-.Sp
-Perl's \f(CW\*(C`sprintf\*(C'\fR permits the following universally-known conversions:
-.Sp
-.Vb 10
-\& %% a percent sign
-\& %c a character with the given number
-\& %s a string
-\& %d a signed integer, in decimal
-\& %u an unsigned integer, in decimal
-\& %o an unsigned integer, in octal
-\& %x an unsigned integer, in hexadecimal
-\& %e a floating-point number, in scientific notation
-\& %f a floating-point number, in fixed decimal notation
-\& %g a floating-point number, in %e or %f notation
-.Ve
-.Sp
-In addition, Perl permits the following widely-supported conversions:
-.Sp
-.Vb 7
-\& %X like %x, but using upper-case letters
-\& %E like %e, but using an upper-case "E"
-\& %G like %g, but with an upper-case "E" (if applicable)
-\& %b an unsigned integer, in binary
-\& %p a pointer (outputs the Perl value's address in hexadecimal)
-\& %n special: *stores* the number of characters output so far
-\& into the next variable in the parameter list
-.Ve
-.Sp
-Finally, for backward (and we do mean \*(L"backward\*(R") compatibility, Perl
-permits these unnecessary but widely-supported conversions:
-.Sp
-.Vb 5
-\& %i a synonym for %d
-\& %D a synonym for %ld
-\& %U a synonym for %lu
-\& %O a synonym for %lo
-\& %F a synonym for %f
-.Ve
-.Sp
-Note that the number of exponent digits in the scientific notation produced
-by \f(CW%e\fR, \f(CW%E\fR, \f(CW%g\fR and \f(CW%G\fR for numbers with the modulus of the
-exponent less than 100 is system\-dependent: it may be three or less
-(zero\-padded as necessary). In other words, 1.23 times ten to the
-99th may be either \*(L"1.23e99\*(R" or \*(L"1.23e099\*(R".
-.Sp
-Between the \f(CW\*(C`%\*(C'\fR and the format letter, you may specify a number of
-additional attributes controlling the interpretation of the format.
-In order, these are:
-.RS 8
-.IP "format parameter index" 4
-.IX Item "format parameter index"
-An explicit format parameter index, such as \f(CW\*(C`2$\*(C'\fR. By default sprintf
-will format the next unused argument in the list, but this allows you
-to take the arguments out of order, e.g.:
-.Sp
-.Vb 2
-\& printf '%2$d %1$d', 12, 34; # prints "34 12"
-\& printf '%3$d %d %1$d', 1, 2, 3; # prints "3 1 1"
-.Ve
-.IP "flags" 4
-.IX Item "flags"
-one or more of:
- space prefix positive number with a space
- + prefix positive number with a plus sign
- \- left-justify within the field
- 0 use zeros, not spaces, to right-justify
- # prefix non-zero octal with \*(L"0\*(R", non-zero hex with \*(L"0x\*(R",
- non-zero binary with \*(L"0b\*(R"
-.Sp
-For example:
-.Sp
-.Vb 6
-\& printf '<% d>', 12; # prints "< 12>"
-\& printf '<%+d>', 12; # prints "<+12>"
-\& printf '<%6s>', 12; # prints "< 12>"
-\& printf '<%-6s>', 12; # prints "<12 >"
-\& printf '<%06s>', 12; # prints "<000012>"
-\& printf '<%#x>', 12; # prints "<0xc>"
-.Ve
-.IP "vector flag" 4
-.IX Item "vector flag"
-This flag tells perl to interpret the supplied string as a vector of
-integers, one for each character in the string. Perl applies the format to
-each integer in turn, then joins the resulting strings with a separator (a
-dot \f(CW\*(C`.\*(C'\fR by default). This can be useful for displaying ordinal values of
-characters in arbitrary strings:
-.Sp
-.Vb 2
-\& printf "%vd", "AB\ex{100}"; # prints "65.66.256"
-\& printf "version is v%vd\en", $^V; # Perl's version
-.Ve
-.Sp
-Put an asterisk \f(CW\*(C`*\*(C'\fR before the \f(CW\*(C`v\*(C'\fR to override the string to
-use to separate the numbers:
-.Sp
-.Vb 2
-\& printf "address is %*vX\en", ":", $addr; # IPv6 address
-\& printf "bits are %0*v8b\en", " ", $bits; # random bitstring
-.Ve
-.Sp
-You can also explicitly specify the argument number to use for
-the join string using e.g. \f(CW\*(C`*2$v\*(C'\fR:
-.Sp
-.Vb 1
-\& printf '%*4$vX %*4$vX %*4$vX', @addr[1..3], ":"; # 3 IPv6 addresses
-.Ve
-.IP "(minimum) width" 4
-.IX Item "(minimum) width"
-Arguments are usually formatted to be only as wide as required to
-display the given value. You can override the width by putting
-a number here, or get the width from the next argument (with \f(CW\*(C`*\*(C'\fR)
-or from a specified argument (with e.g. \f(CW\*(C`*2$\*(C'\fR):
-.Sp
-.Vb 5
-\& printf '<%s>', "a"; # prints "<a>"
-\& printf '<%6s>', "a"; # prints "< a>"
-\& printf '<%*s>', 6, "a"; # prints "< a>"
-\& printf '<%*2$s>', "a", 6; # prints "< a>"
-\& printf '<%2s>', "long"; # prints "<long>" (does not truncate)
-.Ve
-.Sp
-If a field width obtained through \f(CW\*(C`*\*(C'\fR is negative, it has the same
-effect as the \f(CW\*(C`\-\*(C'\fR flag: left\-justification.
-.IP "precision, or maximum width" 4
-.IX Xref "precision"
-.IX Item "precision, or maximum width"
-You can specify a precision (for numeric conversions) or a maximum
-width (for string conversions) by specifying a \f(CW\*(C`.\*(C'\fR followed by a number.
-For floating point formats, with the exception of 'g' and 'G', this specifies
-the number of decimal places to show (the default being 6), e.g.:
-.Sp
-.Vb 6
-\& # these examples are subject to system-specific variation
-\& printf '<%f>', 1; # prints "<1.000000>"
-\& printf '<%.1f>', 1; # prints "<1.0>"
-\& printf '<%.0f>', 1; # prints "<1>"
-\& printf '<%e>', 10; # prints "<1.000000e+01>"
-\& printf '<%.1e>', 10; # prints "<1.0e+01>"
-.Ve
-.Sp
-For 'g' and 'G', this specifies the maximum number of digits to show,
-including prior to the decimal point as well as after it, e.g.:
-.Sp
-.Vb 8
-\& # these examples are subject to system-specific variation
-\& printf '<%g>', 1; # prints "<1>"
-\& printf '<%.10g>', 1; # prints "<1>"
-\& printf '<%g>', 100; # prints "<100>"
-\& printf '<%.1g>', 100; # prints "<1e+02>"
-\& printf '<%.2g>', 100.01; # prints "<1e+02>"
-\& printf '<%.5g>', 100.01; # prints "<100.01>"
-\& printf '<%.4g>', 100.01; # prints "<100>"
-.Ve
-.Sp
-For integer conversions, specifying a precision implies that the
-output of the number itself should be zero-padded to this width:
-.Sp
-.Vb 3
-\& printf '<%.6x>', 1; # prints "<000001>"
-\& printf '<%#.6x>', 1; # prints "<0x000001>"
-\& printf '<%-10.6x>', 1; # prints "<000001 >"
-.Ve
-.Sp
-For string conversions, specifying a precision truncates the string
-to fit in the specified width:
-.Sp
-.Vb 2
-\& printf '<%.5s>', "truncated"; # prints "<trunc>"
-\& printf '<%10.5s>', "truncated"; # prints "< trunc>"
-.Ve
-.Sp
-You can also get the precision from the next argument using \f(CW\*(C`.*\*(C'\fR:
-.Sp
-.Vb 2
-\& printf '<%.6x>', 1; # prints "<000001>"
-\& printf '<%.*x>', 6, 1; # prints "<000001>"
-.Ve
-.Sp
-You cannot currently get the precision from a specified number,
-but it is intended that this will be possible in the future using
-e.g. \f(CW\*(C`.*2$\*(C'\fR:
-.Sp
-.Vb 1
-\& printf '<%.*2$x>', 1, 6; # INVALID, but in future will print "<000001>"
-.Ve
-.IP "size" 4
-.IX Item "size"
-For numeric conversions, you can specify the size to interpret the
-number as using \f(CW\*(C`l\*(C'\fR, \f(CW\*(C`h\*(C'\fR, \f(CW\*(C`V\*(C'\fR, \f(CW\*(C`q\*(C'\fR, \f(CW\*(C`L\*(C'\fR, or \f(CW\*(C`ll\*(C'\fR. For integer
-conversions (\f(CW\*(C`d u o x X b i D U O\*(C'\fR), numbers are usually assumed to be
-whatever the default integer size is on your platform (usually 32 or 64
-bits), but you can override this to use instead one of the standard C types,
-as supported by the compiler used to build Perl:
-.Sp
-.Vb 4
-\& l interpret integer as C type "long" or "unsigned long"
-\& h interpret integer as C type "short" or "unsigned short"
-\& q, L or ll interpret integer as C type "long long", "unsigned long long".
-\& or "quads" (typically 64-bit integers)
-.Ve
-.Sp
-The last will produce errors if Perl does not understand \*(L"quads\*(R" in your
-installation. (This requires that either the platform natively supports quads
-or Perl was specifically compiled to support quads.) You can find out
-whether your Perl supports quads via Config:
-.Sp
-.Vb 3
-\& use Config;
-\& ($Config{use64bitint} eq 'define' || $Config{longsize} >= 8) &&
-\& print "quads\en";
-.Ve
-.Sp
-For floating point conversions (\f(CW\*(C`e f g E F G\*(C'\fR), numbers are usually assumed
-to be the default floating point size on your platform (double or long double),
-but you can force 'long double' with \f(CW\*(C`q\*(C'\fR, \f(CW\*(C`L\*(C'\fR, or \f(CW\*(C`ll\*(C'\fR if your
-platform supports them. You can find out whether your Perl supports long
-doubles via Config:
-.Sp
-.Vb 2
-\& use Config;
-\& $Config{d_longdbl} eq 'define' && print "long doubles\en";
-.Ve
-.Sp
-You can find out whether Perl considers 'long double' to be the default
-floating point size to use on your platform via Config:
-.Sp
-.Vb 3
-\& use Config;
-\& ($Config{uselongdouble} eq 'define') &&
-\& print "long doubles by default\en";
-.Ve
-.Sp
-It can also be the case that long doubles and doubles are the same thing:
-.Sp
-.Vb 3
-\& use Config;
-\& ($Config{doublesize} == $Config{longdblsize}) &&
-\& print "doubles are long doubles\en";
-.Ve
-.Sp
-The size specifier \f(CW\*(C`V\*(C'\fR has no effect for Perl code, but it is supported
-for compatibility with \s-1XS\s0 code; it means 'use the standard size for
-a Perl integer (or floating-point number)', which is already the
-default for Perl code.
-.IP "order of arguments" 4
-.IX Item "order of arguments"
-Normally, sprintf takes the next unused argument as the value to
-format for each format specification. If the format specification
-uses \f(CW\*(C`*\*(C'\fR to require additional arguments, these are consumed from
-the argument list in the order in which they appear in the format
-specification \fIbefore\fR the value to format. Where an argument is
-specified using an explicit index, this does not affect the normal
-order for the arguments (even when the explicitly specified index
-would have been the next argument in any case).
-.Sp
-So:
-.Sp
-.Vb 1
-\& printf '<%*.*s>', $a, $b, $c;
-.Ve
-.Sp
-would use \f(CW$a\fR for the width, \f(CW$b\fR for the precision and \f(CW$c\fR
-as the value to format, while:
-.Sp
-.Vb 1
-\& print '<%*1$.*s>', $a, $b;
-.Ve
-.Sp
-would use \f(CW$a\fR for the width and the precision, and \f(CW$b\fR as the
-value to format.
-.Sp
-Here are some more examples \- beware that when using an explicit
-index, the \f(CW\*(C`$\*(C'\fR may need to be escaped:
-.Sp
-.Vb 4
-\& printf "%2\e$d %d\en", 12, 34; # will print "34 12\en"
-\& printf "%2\e$d %d %d\en", 12, 34; # will print "34 12 34\en"
-\& printf "%3\e$d %d %d\en", 12, 34, 56; # will print "56 12 34\en"
-\& printf "%2\e$*3\e$d %d\en", 12, 34, 3; # will print " 34 12\en"
-.Ve
-.RE
-.RS 8
-.Sp
-If \f(CW\*(C`use locale\*(C'\fR is in effect, the character used for the decimal
-point in formatted real numbers is affected by the \s-1LC_NUMERIC\s0 locale.
-See perllocale.
-.RE
-.IP "sqrt \s-1EXPR\s0" 8
-.IX Xref "sqrt root square root"
-.IX Item "sqrt EXPR"
-.PD 0
-.IP "sqrt" 8
-.IX Item "sqrt"
-.PD
-Return the square root of \s-1EXPR\s0. If \s-1EXPR\s0 is omitted, returns square
-root of \f(CW$_\fR. Only works on non-negative operands, unless you've
-loaded the standard Math::Complex module.
-.Sp
-.Vb 2
-\& use Math::Complex;
-\& print sqrt(-2); # prints 1.4142135623731i
-.Ve
-.IP "srand \s-1EXPR\s0" 8
-.IX Xref "srand seed randseed"
-.IX Item "srand EXPR"
-.PD 0
-.IP "srand" 8
-.IX Item "srand"
-.PD
-Sets the random number seed for the \f(CW\*(C`rand\*(C'\fR operator.
-.Sp
-The point of the function is to \*(L"seed\*(R" the \f(CW\*(C`rand\*(C'\fR function so that
-\&\f(CW\*(C`rand\*(C'\fR can produce a different sequence each time you run your
-program.
-.Sp
-If \fIsrand()\fR is not called explicitly, it is called implicitly at the
-first use of the \f(CW\*(C`rand\*(C'\fR operator. However, this was not the case in
-versions of Perl before 5.004, so if your script will run under older
-Perl versions, it should call \f(CW\*(C`srand\*(C'\fR.
-.Sp
-Most programs won't even call \fIsrand()\fR at all, except those that
-need a cryptographically-strong starting point rather than the
-generally acceptable default, which is based on time of day,
-process \s-1ID\s0, and memory allocation, or the \fI/dev/urandom\fR device,
-if available.
-.Sp
-You can call srand($seed) with the same \f(CW$seed\fR to reproduce the
-\&\fIsame\fR sequence from \fIrand()\fR, but this is usually reserved for
-generating predictable results for testing or debugging.
-Otherwise, don't call \fIsrand()\fR more than once in your program.
-.Sp
-Do \fBnot\fR call \fIsrand()\fR (i.e. without an argument) more than once in
-a script. The internal state of the random number generator should
-contain more entropy than can be provided by any seed, so calling
-\&\fIsrand()\fR again actually \fIloses\fR randomness.
-.Sp
-Most implementations of \f(CW\*(C`srand\*(C'\fR take an integer and will silently
-truncate decimal numbers. This means \f(CW\*(C`srand(42)\*(C'\fR will usually
-produce the same results as \f(CW\*(C`srand(42.1)\*(C'\fR. To be safe, always pass
-\&\f(CW\*(C`srand\*(C'\fR an integer.
-.Sp
-In versions of Perl prior to 5.004 the default seed was just the
-current \f(CW\*(C`time\*(C'\fR. This isn't a particularly good seed, so many old
-programs supply their own seed value (often \f(CW\*(C`time ^ $$\*(C'\fR or \f(CW\*(C`time ^
-($$ + ($$ << 15))\*(C'\fR), but that isn't necessary any more.
-.Sp
-For cryptographic purposes, however, you need something much more random
-than the default seed. Checksumming the compressed output of one or more
-rapidly changing operating system status programs is the usual method. For
-example:
-.Sp
-.Vb 1
-\& srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
-.Ve
-.Sp
-If you're particularly concerned with this, see the \f(CW\*(C`Math::TrulyRandom\*(C'\fR
-module in \s-1CPAN\s0.
-.Sp
-Frequently called programs (like \s-1CGI\s0 scripts) that simply use
-.Sp
-.Vb 1
-\& time ^ $$
-.Ve
-.Sp
-for a seed can fall prey to the mathematical property that
-.Sp
-.Vb 1
-\& a^b == (a+1)^(b+1)
-.Ve
-.Sp
-one-third of the time. So don't do that.
-.IP "stat \s-1FILEHANDLE\s0" 8
-.IX Xref "stat file, status"
-.IX Item "stat FILEHANDLE"
-.PD 0
-.IP "stat \s-1EXPR\s0" 8
-.IX Item "stat EXPR"
-.IP "stat" 8
-.IX Item "stat"
-.PD
-Returns a 13\-element list giving the status info for a file, either
-the file opened via \s-1FILEHANDLE\s0, or named by \s-1EXPR\s0. If \s-1EXPR\s0 is omitted,
-it stats \f(CW$_\fR. Returns a null list if the stat fails. Typically used
-as follows:
-.Sp
-.Vb 3
-\& ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
-\& $atime,$mtime,$ctime,$blksize,$blocks)
-\& = stat($filename);
-.Ve
-.Sp
-Not all fields are supported on all filesystem types. Here are the
-meanings of the fields:
-.Sp
-.Vb 13
-\& 0 dev device number of filesystem
-\& 1 ino inode number
-\& 2 mode file mode (type and permissions)
-\& 3 nlink number of (hard) links to the file
-\& 4 uid numeric user ID of file's owner
-\& 5 gid numeric group ID of file's owner
-\& 6 rdev the device identifier (special files only)
-\& 7 size total size of file, in bytes
-\& 8 atime last access time in seconds since the epoch
-\& 9 mtime last modify time in seconds since the epoch
-\& 10 ctime inode change time in seconds since the epoch (*)
-\& 11 blksize preferred block size for file system I/O
-\& 12 blocks actual number of blocks allocated
-.Ve
-.Sp
-(The epoch was at 00:00 January 1, 1970 \s-1GMT\s0.)
-.Sp
-(*) Not all fields are supported on all filesystem types. Notably, the
-ctime field is non\-portable. In particular, you cannot expect it to be a
-\&\*(L"creation time\*(R", see \*(L"Files and Filesystems\*(R" in perlport for details.
-.Sp
-If \f(CW\*(C`stat\*(C'\fR is passed the special filehandle consisting of an underline, no
-stat is done, but the current contents of the stat structure from the
-last \f(CW\*(C`stat\*(C'\fR, \f(CW\*(C`lstat\*(C'\fR, or filetest are returned. Example:
-.Sp
-.Vb 3
-\& if (-x $file && (($d) = stat(_)) && $d < 0) {
-\& print "$file is executable NFS file\en";
-\& }
-.Ve
-.Sp
-(This works on machines only for which the device number is negative
-under \s-1NFS\s0.)
-.Sp
-Because the mode contains both the file type and its permissions, you
-should mask off the file type portion and (s)printf using a \f(CW"%o"\fR
-if you want to see the real permissions.
-.Sp
-.Vb 2
-\& $mode = (stat($filename))[2];
-\& printf "Permissions are %04o\en", $mode & 07777;
-.Ve
-.Sp
-In scalar context, \f(CW\*(C`stat\*(C'\fR returns a boolean value indicating success
-or failure, and, if successful, sets the information associated with
-the special filehandle \f(CW\*(C`_\*(C'\fR.
-.Sp
-The File::stat module provides a convenient, by-name access mechanism:
-.Sp
-.Vb 5
-\& use File::stat;
-\& $sb = stat($filename);
-\& printf "File is %s, size is %s, perm %04o, mtime %s\en",
-\& $filename, $sb->size, $sb->mode & 07777,
-\& scalar localtime $sb->mtime;
-.Ve
-.Sp
-You can import symbolic mode constants (\f(CW\*(C`S_IF*\*(C'\fR) and functions
-(\f(CW\*(C`S_IS*\*(C'\fR) from the Fcntl module:
-.Sp
-.Vb 1
-\& use Fcntl ':mode';
-.Ve
-.Sp
-.Vb 1
-\& $mode = (stat($filename))[2];
-.Ve
-.Sp
-.Vb 3
-\& $user_rwx = ($mode & S_IRWXU) >> 6;
-\& $group_read = ($mode & S_IRGRP) >> 3;
-\& $other_execute = $mode & S_IXOTH;
-.Ve
-.Sp
-.Vb 1
-\& printf "Permissions are %04o\en", S_IMODE($mode), "\en";
-.Ve
-.Sp
-.Vb 2
-\& $is_setuid = $mode & S_ISUID;
-\& $is_setgid = S_ISDIR($mode);
-.Ve
-.Sp
-You could write the last two using the \f(CW\*(C`\-u\*(C'\fR and \f(CW\*(C`\-d\*(C'\fR operators.
-The commonly available \f(CW\*(C`S_IF*\*(C'\fR constants are
-.Sp
-.Vb 1
-\& # Permissions: read, write, execute, for user, group, others.
-.Ve
-.Sp
-.Vb 3
-\& S_IRWXU S_IRUSR S_IWUSR S_IXUSR
-\& S_IRWXG S_IRGRP S_IWGRP S_IXGRP
-\& S_IRWXO S_IROTH S_IWOTH S_IXOTH
-.Ve
-.Sp
-.Vb 2
-\& # Setuid/Setgid/Stickiness/SaveText.
-\& # Note that the exact meaning of these is system dependent.
-.Ve
-.Sp
-.Vb 1
-\& S_ISUID S_ISGID S_ISVTX S_ISTXT
-.Ve
-.Sp
-.Vb 1
-\& # File types. Not necessarily all are available on your system.
-.Ve
-.Sp
-.Vb 1
-\& S_IFREG S_IFDIR S_IFLNK S_IFBLK S_IFCHR S_IFIFO S_IFSOCK S_IFWHT S_ENFMT
-.Ve
-.Sp
-.Vb 1
-\& # The following are compatibility aliases for S_IRUSR, S_IWUSR, S_IXUSR.
-.Ve
-.Sp
-.Vb 1
-\& S_IREAD S_IWRITE S_IEXEC
-.Ve
-.Sp
-and the \f(CW\*(C`S_IF*\*(C'\fR functions are
-.Sp
-.Vb 2
-\& S_IMODE($mode) the part of $mode containing the permission bits
-\& and the setuid/setgid/sticky bits
-.Ve
-.Sp
-.Vb 3
-\& S_IFMT($mode) the part of $mode containing the file type
-\& which can be bit-anded with e.g. S_IFREG
-\& or with the following functions
-.Ve
-.Sp
-.Vb 1
-\& # The operators -f, -d, -l, -b, -c, -p, and -S.
-.Ve
-.Sp
-.Vb 2
-\& S_ISREG($mode) S_ISDIR($mode) S_ISLNK($mode)
-\& S_ISBLK($mode) S_ISCHR($mode) S_ISFIFO($mode) S_ISSOCK($mode)
-.Ve
-.Sp
-.Vb 3
-\& # No direct -X operator counterpart, but for the first one
-\& # the -g operator is often equivalent. The ENFMT stands for
-\& # record flocking enforcement, a platform-dependent feature.
-.Ve
-.Sp
-.Vb 1
-\& S_ISENFMT($mode) S_ISWHT($mode)
-.Ve
-.Sp
-See your native \fIchmod\fR\|(2) and \fIstat\fR\|(2) documentation for more details
-about the \f(CW\*(C`S_*\*(C'\fR constants. To get status info for a symbolic link
-instead of the target file behind the link, use the \f(CW\*(C`lstat\*(C'\fR function.
-.IP "study \s-1SCALAR\s0" 8
-.IX Xref "study"
-.IX Item "study SCALAR"
-.PD 0
-.IP "study" 8
-.IX Item "study"
-.PD
-Takes extra time to study \s-1SCALAR\s0 (\f(CW$_\fR if unspecified) in anticipation of
-doing many pattern matches on the string before it is next modified.
-This may or may not save time, depending on the nature and number of
-patterns you are searching on, and on the distribution of character
-frequencies in the string to be searched\*(--you probably want to compare
-run times with and without it to see which runs faster. Those loops
-that scan for many short constant strings (including the constant
-parts of more complex patterns) will benefit most. You may have only
-one \f(CW\*(C`study\*(C'\fR active at a time\*(--if you study a different scalar the first
-is \*(L"unstudied\*(R". (The way \f(CW\*(C`study\*(C'\fR works is this: a linked list of every
-character in the string to be searched is made, so we know, for
-example, where all the \f(CW'k'\fR characters are. From each search string,
-the rarest character is selected, based on some static frequency tables
-constructed from some C programs and English text. Only those places
-that contain this \*(L"rarest\*(R" character are examined.)
-.Sp
-For example, here is a loop that inserts index producing entries
-before any line containing a certain pattern:
-.Sp
-.Vb 8
-\& while (<>) {
-\& study;
-\& print ".IX foo\en" if /\ebfoo\eb/;
-\& print ".IX bar\en" if /\ebbar\eb/;
-\& print ".IX blurfl\en" if /\ebblurfl\eb/;
-\& # ...
-\& print;
-\& }
-.Ve
-.Sp
-In searching for \f(CW\*(C`/\ebfoo\eb/\*(C'\fR, only those locations in \f(CW$_\fR that contain \f(CW\*(C`f\*(C'\fR
-will be looked at, because \f(CW\*(C`f\*(C'\fR is rarer than \f(CW\*(C`o\*(C'\fR. In general, this is
-a big win except in pathological cases. The only question is whether
-it saves you more time than it took to build the linked list in the
-first place.
-.Sp
-Note that if you have to look for strings that you don't know till
-runtime, you can build an entire loop as a string and \f(CW\*(C`eval\*(C'\fR that to
-avoid recompiling all your patterns all the time. Together with
-undefining \f(CW$/\fR to input entire files as one record, this can be very
-fast, often faster than specialized programs like \fIfgrep\fR\|(1). The following
-scans a list of files (\f(CW@files\fR) for a list of words (\f(CW@words\fR), and prints
-out the names of those files that contain a match:
-.Sp
-.Vb 12
-\& $search = 'while (<>) { study;';
-\& foreach $word (@words) {
-\& $search .= "++\e$seen{\e$ARGV} if /\e\eb$word\e\eb/;\en";
-\& }
-\& $search .= "}";
-\& @ARGV = @files;
-\& undef $/;
-\& eval $search; # this screams
-\& $/ = "\en"; # put back to normal input delimiter
-\& foreach $file (sort keys(%seen)) {
-\& print $file, "\en";
-\& }
-.Ve
-.IP "sub \s-1NAME\s0 \s-1BLOCK\s0" 8
-.IX Xref "sub"
-.IX Item "sub NAME BLOCK"
-.PD 0
-.IP "sub \s-1NAME\s0 (\s-1PROTO\s0) \s-1BLOCK\s0" 8
-.IX Item "sub NAME (PROTO) BLOCK"
-.IP "sub \s-1NAME\s0 : \s-1ATTRS\s0 \s-1BLOCK\s0" 8
-.IX Item "sub NAME : ATTRS BLOCK"
-.IP "sub \s-1NAME\s0 (\s-1PROTO\s0) : \s-1ATTRS\s0 \s-1BLOCK\s0" 8
-.IX Item "sub NAME (PROTO) : ATTRS BLOCK"
-.PD
-This is subroutine definition, not a real function \fIper se\fR.
-Without a \s-1BLOCK\s0 it's just a forward declaration. Without a \s-1NAME\s0,
-it's an anonymous function declaration, and does actually return
-a value: the \s-1CODE\s0 ref of the closure you just created.
-.Sp
-See perlsub and perlref for details about subroutines and
-references, and attributes and Attribute::Handlers for more
-information about attributes.
-.IP "substr \s-1EXPR\s0,OFFSET,LENGTH,REPLACEMENT" 8
-.IX Xref "substr substring mid left right"
-.IX Item "substr EXPR,OFFSET,LENGTH,REPLACEMENT"
-.PD 0
-.IP "substr \s-1EXPR\s0,OFFSET,LENGTH" 8
-.IX Item "substr EXPR,OFFSET,LENGTH"
-.IP "substr \s-1EXPR\s0,OFFSET" 8
-.IX Item "substr EXPR,OFFSET"
-.PD
-Extracts a substring out of \s-1EXPR\s0 and returns it. First character is at
-offset \f(CW0\fR, or whatever you've set \f(CW$[\fR to (but don't do that).
-If \s-1OFFSET\s0 is negative (or more precisely, less than \f(CW$[\fR), starts
-that far from the end of the string. If \s-1LENGTH\s0 is omitted, returns
-everything to the end of the string. If \s-1LENGTH\s0 is negative, leaves that
-many characters off the end of the string.
-.Sp
-You can use the \fIsubstr()\fR function as an lvalue, in which case \s-1EXPR\s0
-must itself be an lvalue. If you assign something shorter than \s-1LENGTH\s0,
-the string will shrink, and if you assign something longer than \s-1LENGTH\s0,
-the string will grow to accommodate it. To keep the string the same
-length you may need to pad or chop your value using \f(CW\*(C`sprintf\*(C'\fR.
-.Sp
-If \s-1OFFSET\s0 and \s-1LENGTH\s0 specify a substring that is partly outside the
-string, only the part within the string is returned. If the substring
-is beyond either end of the string, \fIsubstr()\fR returns the undefined
-value and produces a warning. When used as an lvalue, specifying a
-substring that is entirely outside the string is a fatal error.
-Here's an example showing the behavior for boundary cases:
-.Sp
-.Vb 5
-\& my $name = 'fred';
-\& substr($name, 4) = 'dy'; # $name is now 'freddy'
-\& my $null = substr $name, 6, 2; # returns '' (no warning)
-\& my $oops = substr $name, 7; # returns undef, with warning
-\& substr($name, 7) = 'gap'; # fatal error
-.Ve
-.Sp
-An alternative to using \fIsubstr()\fR as an lvalue is to specify the
-replacement string as the 4th argument. This allows you to replace
-parts of the \s-1EXPR\s0 and return what was there before in one operation,
-just as you can with \fIsplice()\fR.
-.IP "symlink \s-1OLDFILE\s0,NEWFILE" 8
-.IX Xref "symlink link symbolic link link, symbolic"
-.IX Item "symlink OLDFILE,NEWFILE"
-Creates a new filename symbolically linked to the old filename.
-Returns \f(CW1\fR for success, \f(CW0\fR otherwise. On systems that don't support
-symbolic links, produces a fatal error at run time. To check for that,
-use eval:
-.Sp
-.Vb 1
-\& $symlink_exists = eval { symlink("",""); 1 };
-.Ve
-.IP "syscall \s-1NUMBER\s0, \s-1LIST\s0" 8
-.IX Xref "syscall system call"
-.IX Item "syscall NUMBER, LIST"
-Calls the system call specified as the first element of the list,
-passing the remaining elements as arguments to the system call. If
-unimplemented, produces a fatal error. The arguments are interpreted
-as follows: if a given argument is numeric, the argument is passed as
-an int. If not, the pointer to the string value is passed. You are
-responsible to make sure a string is pre-extended long enough to
-receive any result that might be written into a string. You can't use a
-string literal (or other read-only string) as an argument to \f(CW\*(C`syscall\*(C'\fR
-because Perl has to assume that any string pointer might be written
-through. If your
-integer arguments are not literals and have never been interpreted in a
-numeric context, you may need to add \f(CW0\fR to them to force them to look
-like numbers. This emulates the \f(CW\*(C`syswrite\*(C'\fR function (or vice versa):
-.Sp
-.Vb 3
-\& require 'syscall.ph'; # may need to run h2ph
-\& $s = "hi there\en";
-\& syscall(&SYS_write, fileno(STDOUT), $s, length $s);
-.Ve
-.Sp
-Note that Perl supports passing of up to only 14 arguments to your system call,
-which in practice should usually suffice.
-.Sp
-Syscall returns whatever value returned by the system call it calls.
-If the system call fails, \f(CW\*(C`syscall\*(C'\fR returns \f(CW\*(C`\-1\*(C'\fR and sets \f(CW$!\fR (errno).
-Note that some system calls can legitimately return \f(CW\*(C`\-1\*(C'\fR. The proper
-way to handle such calls is to assign \f(CW\*(C`$!=0;\*(C'\fR before the call and
-check the value of \f(CW$!\fR if syscall returns \f(CW\*(C`\-1\*(C'\fR.
-.Sp
-There's a problem with \f(CW\*(C`syscall(&SYS_pipe)\*(C'\fR: it returns the file
-number of the read end of the pipe it creates. There is no way
-to retrieve the file number of the other end. You can avoid this
-problem by using \f(CW\*(C`pipe\*(C'\fR instead.
-.IP "sysopen \s-1FILEHANDLE\s0,FILENAME,MODE" 8
-.IX Xref "sysopen"
-.IX Item "sysopen FILEHANDLE,FILENAME,MODE"
-.PD 0
-.IP "sysopen \s-1FILEHANDLE\s0,FILENAME,MODE,PERMS" 8
-.IX Item "sysopen FILEHANDLE,FILENAME,MODE,PERMS"
-.PD
-Opens the file whose filename is given by \s-1FILENAME\s0, and associates it
-with \s-1FILEHANDLE\s0. If \s-1FILEHANDLE\s0 is an expression, its value is used as
-the name of the real filehandle wanted. This function calls the
-underlying operating system's \f(CW\*(C`open\*(C'\fR function with the parameters
-\&\s-1FILENAME\s0, \s-1MODE\s0, \s-1PERMS\s0.
-.Sp
-The possible values and flag bits of the \s-1MODE\s0 parameter are
-system\-dependent; they are available via the standard module \f(CW\*(C`Fcntl\*(C'\fR.
-See the documentation of your operating system's \f(CW\*(C`open\*(C'\fR to see which
-values and flag bits are available. You may combine several flags
-using the \f(CW\*(C`|\*(C'\fR\-operator.
-.Sp
-Some of the most common values are \f(CW\*(C`O_RDONLY\*(C'\fR for opening the file in
-read-only mode, \f(CW\*(C`O_WRONLY\*(C'\fR for opening the file in write-only mode,
-and \f(CW\*(C`O_RDWR\*(C'\fR for opening the file in read-write mode.
-.IX Xref "O_RDONLY O_RDWR O_WRONLY"
-.Sp
-For historical reasons, some values work on almost every system
-supported by perl: zero means read\-only, one means write\-only, and two
-means read/write. We know that these values do \fInot\fR work under
-\&\s-1OS/390\s0 & \s-1VM/ESA\s0 Unix and on the Macintosh; you probably don't want to
-use them in new code.
-.Sp
-If the file named by \s-1FILENAME\s0 does not exist and the \f(CW\*(C`open\*(C'\fR call creates
-it (typically because \s-1MODE\s0 includes the \f(CW\*(C`O_CREAT\*(C'\fR flag), then the value of
-\&\s-1PERMS\s0 specifies the permissions of the newly created file. If you omit
-the \s-1PERMS\s0 argument to \f(CW\*(C`sysopen\*(C'\fR, Perl uses the octal value \f(CW0666\fR.
-These permission values need to be in octal, and are modified by your
-process's current \f(CW\*(C`umask\*(C'\fR.
-.IX Xref "O_CREAT"
-.Sp
-In many systems the \f(CW\*(C`O_EXCL\*(C'\fR flag is available for opening files in
-exclusive mode. This is \fBnot\fR locking: exclusiveness means here that
-if the file already exists, \fIsysopen()\fR fails. \f(CW\*(C`O_EXCL\*(C'\fR may not work
-on network filesystems, and has no effect unless the \f(CW\*(C`O_CREAT\*(C'\fR flag
-is set as well. Setting \f(CW\*(C`O_CREAT|O_EXCL\*(C'\fR prevents the file from
-being opened if it is a symbolic link. It does not protect against
-symbolic links in the file's path.
-.IX Xref "O_EXCL"
-.Sp
-Sometimes you may want to truncate an already-existing file. This
-can be done using the \f(CW\*(C`O_TRUNC\*(C'\fR flag. The behavior of
-\&\f(CW\*(C`O_TRUNC\*(C'\fR with \f(CW\*(C`O_RDONLY\*(C'\fR is undefined.
-.IX Xref "O_TRUNC"
-.Sp
-You should seldom if ever use \f(CW0644\fR as argument to \f(CW\*(C`sysopen\*(C'\fR, because
-that takes away the user's option to have a more permissive umask.
-Better to omit it. See the \fIperlfunc\fR\|(1) entry on \f(CW\*(C`umask\*(C'\fR for more
-on this.
-.Sp
-Note that \f(CW\*(C`sysopen\*(C'\fR depends on the \fIfdopen()\fR C library function.
-On many \s-1UNIX\s0 systems, \fIfdopen()\fR is known to fail when file descriptors
-exceed a certain value, typically 255. If you need more file
-descriptors than that, consider rebuilding Perl to use the \f(CW\*(C`sfio\*(C'\fR
-library, or perhaps using the \fIPOSIX::open()\fR function.
-.Sp
-See perlopentut for a kinder, gentler explanation of opening files.
-.IP "sysread \s-1FILEHANDLE\s0,SCALAR,LENGTH,OFFSET" 8
-.IX Xref "sysread"
-.IX Item "sysread FILEHANDLE,SCALAR,LENGTH,OFFSET"
-.PD 0
-.IP "sysread \s-1FILEHANDLE\s0,SCALAR,LENGTH" 8
-.IX Item "sysread FILEHANDLE,SCALAR,LENGTH"
-.PD
-Attempts to read \s-1LENGTH\s0 bytes of data into variable \s-1SCALAR\s0 from the
-specified \s-1FILEHANDLE\s0, using the system call \fIread\fR\|(2). It bypasses
-buffered \s-1IO\s0, so mixing this with other kinds of reads, \f(CW\*(C`print\*(C'\fR,
-\&\f(CW\*(C`write\*(C'\fR, \f(CW\*(C`seek\*(C'\fR, \f(CW\*(C`tell\*(C'\fR, or \f(CW\*(C`eof\*(C'\fR can cause confusion because the
-perlio or stdio layers usually buffers data. Returns the number of
-bytes actually read, \f(CW0\fR at end of file, or undef if there was an
-error (in the latter case \f(CW$!\fR is also set). \s-1SCALAR\s0 will be grown or
-shrunk so that the last byte actually read is the last byte of the
-scalar after the read.
-.Sp
-An \s-1OFFSET\s0 may be specified to place the read data at some place in the
-string other than the beginning. A negative \s-1OFFSET\s0 specifies
-placement at that many characters counting backwards from the end of
-the string. A positive \s-1OFFSET\s0 greater than the length of \s-1SCALAR\s0
-results in the string being padded to the required size with \f(CW"\e0"\fR
-bytes before the result of the read is appended.
-.Sp
-There is no \fIsyseof()\fR function, which is ok, since \fIeof()\fR doesn't work
-very well on device files (like ttys) anyway. Use \fIsysread()\fR and check
-for a return value for 0 to decide whether you're done.
-.Sp
-Note that if the filehandle has been marked as \f(CW\*(C`:utf8\*(C'\fR Unicode
-characters are read instead of bytes (the \s-1LENGTH\s0, \s-1OFFSET\s0, and the
-return value of \fIsysread()\fR are in Unicode characters).
-The \f(CW\*(C`:encoding(...)\*(C'\fR layer implicitly introduces the \f(CW\*(C`:utf8\*(C'\fR layer.
-See \*(L"binmode\*(R", \*(L"open\*(R", and the \f(CW\*(C`open\*(C'\fR pragma, open.
-.IP "sysseek \s-1FILEHANDLE\s0,POSITION,WHENCE" 8
-.IX Xref "sysseek lseek"
-.IX Item "sysseek FILEHANDLE,POSITION,WHENCE"
-Sets \s-1FILEHANDLE\s0's system position in bytes using the system call
-\&\fIlseek\fR\|(2). \s-1FILEHANDLE\s0 may be an expression whose value gives the name
-of the filehandle. The values for \s-1WHENCE\s0 are \f(CW0\fR to set the new
-position to \s-1POSITION\s0, \f(CW1\fR to set the it to the current position plus
-\&\s-1POSITION\s0, and \f(CW2\fR to set it to \s-1EOF\s0 plus \s-1POSITION\s0 (typically
-negative).
-.Sp
-Note the \fIin bytes\fR: even if the filehandle has been set to operate
-on characters (for example by using the \f(CW\*(C`:utf8\*(C'\fR I/O layer), \fItell()\fR
-will return byte offsets, not character offsets (because implementing
-that would render \fIsysseek()\fR very slow).
-.Sp
-\&\fIsysseek()\fR bypasses normal buffered \s-1IO\s0, so mixing this with reads (other
-than \f(CW\*(C`sysread\*(C'\fR, for example \f(CW\*(C`<>\*(C'\fR or \fIread()\fR) \f(CW\*(C`print\*(C'\fR, \f(CW\*(C`write\*(C'\fR,
-\&\f(CW\*(C`seek\*(C'\fR, \f(CW\*(C`tell\*(C'\fR, or \f(CW\*(C`eof\*(C'\fR may cause confusion.
-.Sp
-For \s-1WHENCE\s0, you may also use the constants \f(CW\*(C`SEEK_SET\*(C'\fR, \f(CW\*(C`SEEK_CUR\*(C'\fR,
-and \f(CW\*(C`SEEK_END\*(C'\fR (start of the file, current position, end of the file)
-from the Fcntl module. Use of the constants is also more portable
-than relying on 0, 1, and 2. For example to define a \*(L"systell\*(R" function:
-.Sp
-.Vb 2
-\& use Fcntl 'SEEK_CUR';
-\& sub systell { sysseek($_[0], 0, SEEK_CUR) }
-.Ve
-.Sp
-Returns the new position, or the undefined value on failure. A position
-of zero is returned as the string \f(CW"0 but true"\fR; thus \f(CW\*(C`sysseek\*(C'\fR returns
-true on success and false on failure, yet you can still easily determine
-the new position.
-.IP "system \s-1LIST\s0" 8
-.IX Xref "system shell"
-.IX Item "system LIST"
-.PD 0
-.IP "system \s-1PROGRAM\s0 \s-1LIST\s0" 8
-.IX Item "system PROGRAM LIST"
-.PD
-Does exactly the same thing as \f(CW\*(C`exec LIST\*(C'\fR, except that a fork is
-done first, and the parent process waits for the child process to
-complete. Note that argument processing varies depending on the
-number of arguments. If there is more than one argument in \s-1LIST\s0,
-or if \s-1LIST\s0 is an array with more than one value, starts the program
-given by the first element of the list with arguments given by the
-rest of the list. If there is only one scalar argument, the argument
-is checked for shell metacharacters, and if there are any, the
-entire argument is passed to the system's command shell for parsing
-(this is \f(CW\*(C`/bin/sh \-c\*(C'\fR on Unix platforms, but varies on other
-platforms). If there are no shell metacharacters in the argument,
-it is split into words and passed directly to \f(CW\*(C`execvp\*(C'\fR, which is
-more efficient.
-.Sp
-Beginning with v5.6.0, Perl will attempt to flush all files opened for
-output before any operation that may do a fork, but this may not be
-supported on some platforms (see perlport). To be safe, you may need
-to set \f(CW$|\fR ($AUTOFLUSH in English) or call the \f(CW\*(C`autoflush()\*(C'\fR method
-of \f(CW\*(C`IO::Handle\*(C'\fR on any open handles.
-.Sp
-The return value is the exit status of the program as returned by the
-\&\f(CW\*(C`wait\*(C'\fR call. To get the actual exit value, shift right by eight (see
-below). See also \*(L"exec\*(R". This is \fInot\fR what you want to use to capture
-the output from a command, for that you should use merely backticks or
-\&\f(CW\*(C`qx//\*(C'\fR, as described in \*(L"`STRING`\*(R" in perlop. Return value of \-1
-indicates a failure to start the program or an error of the \fIwait\fR\|(2) system
-call (inspect $! for the reason).
-.Sp
-Like \f(CW\*(C`exec\*(C'\fR, \f(CW\*(C`system\*(C'\fR allows you to lie to a program about its name if
-you use the \f(CW\*(C`system PROGRAM LIST\*(C'\fR syntax. Again, see \*(L"exec\*(R".
-.Sp
-Since \f(CW\*(C`SIGINT\*(C'\fR and \f(CW\*(C`SIGQUIT\*(C'\fR are ignored during the execution of
-\&\f(CW\*(C`system\*(C'\fR, if you expect your program to terminate on receipt of these
-signals you will need to arrange to do so yourself based on the return
-value.
-.Sp
-.Vb 3
-\& @args = ("command", "arg1", "arg2");
-\& system(@args) == 0
-\& or die "system @args failed: $?"
-.Ve
-.Sp
-You can check all the failure possibilities by inspecting
-\&\f(CW$?\fR like this:
-.Sp
-.Vb 10
-\& if ($? == -1) {
-\& print "failed to execute: $!\en";
-\& }
-\& elsif ($? & 127) {
-\& printf "child died with signal %d, %s coredump\en",
-\& ($? & 127), ($? & 128) ? 'with' : 'without';
-\& }
-\& else {
-\& printf "child exited with value %d\en", $? >> 8;
-\& }
-.Ve
-.Sp
-or more portably by using the W*() calls of the \s-1POSIX\s0 extension;
-see perlport for more information.
-.Sp
-When the arguments get executed via the system shell, results
-and return codes will be subject to its quirks and capabilities.
-See \*(L"`STRING`\*(R" in perlop and \*(L"exec\*(R" for details.
-.IP "syswrite \s-1FILEHANDLE\s0,SCALAR,LENGTH,OFFSET" 8
-.IX Xref "syswrite"
-.IX Item "syswrite FILEHANDLE,SCALAR,LENGTH,OFFSET"
-.PD 0
-.IP "syswrite \s-1FILEHANDLE\s0,SCALAR,LENGTH" 8
-.IX Item "syswrite FILEHANDLE,SCALAR,LENGTH"
-.IP "syswrite \s-1FILEHANDLE\s0,SCALAR" 8
-.IX Item "syswrite FILEHANDLE,SCALAR"
-.PD
-Attempts to write \s-1LENGTH\s0 bytes of data from variable \s-1SCALAR\s0 to the
-specified \s-1FILEHANDLE\s0, using the system call \fIwrite\fR\|(2). If \s-1LENGTH\s0 is
-not specified, writes whole \s-1SCALAR\s0. It bypasses buffered \s-1IO\s0, so
-mixing this with reads (other than \f(CWsysread())\fR, \f(CW\*(C`print\*(C'\fR, \f(CW\*(C`write\*(C'\fR,
-\&\f(CW\*(C`seek\*(C'\fR, \f(CW\*(C`tell\*(C'\fR, or \f(CW\*(C`eof\*(C'\fR may cause confusion because the perlio and
-stdio layers usually buffers data. Returns the number of bytes
-actually written, or \f(CW\*(C`undef\*(C'\fR if there was an error (in this case the
-errno variable \f(CW$!\fR is also set). If the \s-1LENGTH\s0 is greater than the
-available data in the \s-1SCALAR\s0 after the \s-1OFFSET\s0, only as much data as is
-available will be written.
-.Sp
-An \s-1OFFSET\s0 may be specified to write the data from some part of the
-string other than the beginning. A negative \s-1OFFSET\s0 specifies writing
-that many characters counting backwards from the end of the string.
-In the case the \s-1SCALAR\s0 is empty you can use \s-1OFFSET\s0 but only zero offset.
-.Sp
-Note that if the filehandle has been marked as \f(CW\*(C`:utf8\*(C'\fR, Unicode
-characters are written instead of bytes (the \s-1LENGTH\s0, \s-1OFFSET\s0, and the
-return value of \fIsyswrite()\fR are in \s-1UTF\-8\s0 encoded Unicode characters).
-The \f(CW\*(C`:encoding(...)\*(C'\fR layer implicitly introduces the \f(CW\*(C`:utf8\*(C'\fR layer.
-See \*(L"binmode\*(R", \*(L"open\*(R", and the \f(CW\*(C`open\*(C'\fR pragma, open.
-.IP "tell \s-1FILEHANDLE\s0" 8
-.IX Xref "tell"
-.IX Item "tell FILEHANDLE"
-.PD 0
-.IP "tell" 8
-.IX Item "tell"
-.PD
-Returns the current position \fIin bytes\fR for \s-1FILEHANDLE\s0, or \-1 on
-error. \s-1FILEHANDLE\s0 may be an expression whose value gives the name of
-the actual filehandle. If \s-1FILEHANDLE\s0 is omitted, assumes the file
-last read.
-.Sp
-Note the \fIin bytes\fR: even if the filehandle has been set to
-operate on characters (for example by using the \f(CW\*(C`:utf8\*(C'\fR open
-layer), \fItell()\fR will return byte offsets, not character offsets
-(because that would render \fIseek()\fR and \fItell()\fR rather slow).
-.Sp
-The return value of \fItell()\fR for the standard streams like the \s-1STDIN\s0
-depends on the operating system: it may return \-1 or something else.
-\&\fItell()\fR on pipes, fifos, and sockets usually returns \-1.
-.Sp
-There is no \f(CW\*(C`systell\*(C'\fR function. Use \f(CW\*(C`sysseek(FH, 0, 1)\*(C'\fR for that.
-.Sp
-Do not use \fItell()\fR (or other buffered I/O operations) on a file handle
-that has been manipulated by \fIsysread()\fR, \fIsyswrite()\fR or \fIsysseek()\fR.
-Those functions ignore the buffering, while \fItell()\fR does not.
-.IP "telldir \s-1DIRHANDLE\s0" 8
-.IX Xref "telldir"
-.IX Item "telldir DIRHANDLE"
-Returns the current position of the \f(CW\*(C`readdir\*(C'\fR routines on \s-1DIRHANDLE\s0.
-Value may be given to \f(CW\*(C`seekdir\*(C'\fR to access a particular location in a
-directory. \f(CW\*(C`telldir\*(C'\fR has the same caveats about possible directory
-compaction as the corresponding system library routine.
-.IP "tie \s-1VARIABLE\s0,CLASSNAME,LIST" 8
-.IX Xref "tie"
-.IX Item "tie VARIABLE,CLASSNAME,LIST"
-This function binds a variable to a package class that will provide the
-implementation for the variable. \s-1VARIABLE\s0 is the name of the variable
-to be enchanted. \s-1CLASSNAME\s0 is the name of a class implementing objects
-of correct type. Any additional arguments are passed to the \f(CW\*(C`new\*(C'\fR
-method of the class (meaning \f(CW\*(C`TIESCALAR\*(C'\fR, \f(CW\*(C`TIEHANDLE\*(C'\fR, \f(CW\*(C`TIEARRAY\*(C'\fR,
-or \f(CW\*(C`TIEHASH\*(C'\fR). Typically these are arguments such as might be passed
-to the \f(CW\*(C`dbm_open()\*(C'\fR function of C. The object returned by the \f(CW\*(C`new\*(C'\fR
-method is also returned by the \f(CW\*(C`tie\*(C'\fR function, which would be useful
-if you want to access other methods in \s-1CLASSNAME\s0.
-.Sp
-Note that functions such as \f(CW\*(C`keys\*(C'\fR and \f(CW\*(C`values\*(C'\fR may return huge lists
-when used on large objects, like \s-1DBM\s0 files. You may prefer to use the
-\&\f(CW\*(C`each\*(C'\fR function to iterate over such. Example:
-.Sp
-.Vb 7
-\& # print out history file offsets
-\& use NDBM_File;
-\& tie(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
-\& while (($key,$val) = each %HIST) {
-\& print $key, ' = ', unpack('L',$val), "\en";
-\& }
-\& untie(%HIST);
-.Ve
-.Sp
-A class implementing a hash should have the following methods:
-.Sp
-.Vb 11
-\& TIEHASH classname, LIST
-\& FETCH this, key
-\& STORE this, key, value
-\& DELETE this, key
-\& CLEAR this
-\& EXISTS this, key
-\& FIRSTKEY this
-\& NEXTKEY this, lastkey
-\& SCALAR this
-\& DESTROY this
-\& UNTIE this
-.Ve
-.Sp
-A class implementing an ordinary array should have the following methods:
-.Sp
-.Vb 14
-\& TIEARRAY classname, LIST
-\& FETCH this, key
-\& STORE this, key, value
-\& FETCHSIZE this
-\& STORESIZE this, count
-\& CLEAR this
-\& PUSH this, LIST
-\& POP this
-\& SHIFT this
-\& UNSHIFT this, LIST
-\& SPLICE this, offset, length, LIST
-\& EXTEND this, count
-\& DESTROY this
-\& UNTIE this
-.Ve
-.Sp
-A class implementing a file handle should have the following methods:
-.Sp
-.Vb 16
-\& TIEHANDLE classname, LIST
-\& READ this, scalar, length, offset
-\& READLINE this
-\& GETC this
-\& WRITE this, scalar, length, offset
-\& PRINT this, LIST
-\& PRINTF this, format, LIST
-\& BINMODE this
-\& EOF this
-\& FILENO this
-\& SEEK this, position, whence
-\& TELL this
-\& OPEN this, mode, LIST
-\& CLOSE this
-\& DESTROY this
-\& UNTIE this
-.Ve
-.Sp
-A class implementing a scalar should have the following methods:
-.Sp
-.Vb 5
-\& TIESCALAR classname, LIST
-\& FETCH this,
-\& STORE this, value
-\& DESTROY this
-\& UNTIE this
-.Ve
-.Sp
-Not all methods indicated above need be implemented. See perltie,
-Tie::Hash, Tie::Array, Tie::Scalar, and Tie::Handle.
-.Sp
-Unlike \f(CW\*(C`dbmopen\*(C'\fR, the \f(CW\*(C`tie\*(C'\fR function will not use or require a module
-for you\*(--you need to do that explicitly yourself. See DB_File
-or the \fIConfig\fR module for interesting \f(CW\*(C`tie\*(C'\fR implementations.
-.Sp
-For further details see perltie, \*(L"tied \s-1VARIABLE\s0\*(R".
-.IP "tied \s-1VARIABLE\s0" 8
-.IX Xref "tied"
-.IX Item "tied VARIABLE"
-Returns a reference to the object underlying \s-1VARIABLE\s0 (the same value
-that was originally returned by the \f(CW\*(C`tie\*(C'\fR call that bound the variable
-to a package.) Returns the undefined value if \s-1VARIABLE\s0 isn't tied to a
-package.
-.IP "time" 8
-.IX Xref "time epoch"
-.IX Item "time"
-Returns the number of non-leap seconds since whatever time the system
-considers to be the epoch, suitable for feeding to \f(CW\*(C`gmtime\*(C'\fR and
-\&\f(CW\*(C`localtime\*(C'\fR. On most systems the epoch is 00:00:00 \s-1UTC\s0, January 1, 1970;
-a prominent exception being Mac \s-1OS\s0 Classic which uses 00:00:00, January 1,
-1904 in the current local time zone for its epoch.
-.Sp
-For measuring time in better granularity than one second,
-you may use either the Time::HiRes module (from \s-1CPAN\s0, and starting from
-Perl 5.8 part of the standard distribution), or if you have
-\&\fIgettimeofday\fR\|(2), you may be able to use the \f(CW\*(C`syscall\*(C'\fR interface of Perl.
-See perlfaq8 for details.
-.IP "times" 8
-.IX Xref "times"
-.IX Item "times"
-Returns a four-element list giving the user and system times, in
-seconds, for this process and the children of this process.
-.Sp
-.Vb 1
-\& ($user,$system,$cuser,$csystem) = times;
-.Ve
-.Sp
-In scalar context, \f(CW\*(C`times\*(C'\fR returns \f(CW$user\fR.
-.IP "tr///" 8
-.IX Item "tr///"
-The transliteration operator. Same as \f(CW\*(C`y///\*(C'\fR. See perlop.
-.IP "truncate \s-1FILEHANDLE\s0,LENGTH" 8
-.IX Xref "truncate"
-.IX Item "truncate FILEHANDLE,LENGTH"
-.PD 0
-.IP "truncate \s-1EXPR\s0,LENGTH" 8
-.IX Item "truncate EXPR,LENGTH"
-.PD
-Truncates the file opened on \s-1FILEHANDLE\s0, or named by \s-1EXPR\s0, to the
-specified length. Produces a fatal error if truncate isn't implemented
-on your system. Returns true if successful, the undefined value
-otherwise.
-.Sp
-The behavior is undefined if \s-1LENGTH\s0 is greater than the length of the
-file.
-.IP "uc \s-1EXPR\s0" 8
-.IX Xref "uc uppercase toupper"
-.IX Item "uc EXPR"
-.PD 0
-.IP "uc" 8
-.IX Item "uc"
-.PD
-Returns an uppercased version of \s-1EXPR\s0. This is the internal function
-implementing the \f(CW\*(C`\eU\*(C'\fR escape in double-quoted strings. Respects
-current \s-1LC_CTYPE\s0 locale if \f(CW\*(C`use locale\*(C'\fR in force. See perllocale
-and perlunicode for more details about locale and Unicode support.
-It does not attempt to do titlecase mapping on initial letters. See
-\&\f(CW\*(C`ucfirst\*(C'\fR for that.
-.Sp
-If \s-1EXPR\s0 is omitted, uses \f(CW$_\fR.
-.IP "ucfirst \s-1EXPR\s0" 8
-.IX Xref "ucfirst uppercase"
-.IX Item "ucfirst EXPR"
-.PD 0
-.IP "ucfirst" 8
-.IX Item "ucfirst"
-.PD
-Returns the value of \s-1EXPR\s0 with the first character in uppercase
-(titlecase in Unicode). This is the internal function implementing
-the \f(CW\*(C`\eu\*(C'\fR escape in double-quoted strings. Respects current \s-1LC_CTYPE\s0
-locale if \f(CW\*(C`use locale\*(C'\fR in force. See perllocale and perlunicode
-for more details about locale and Unicode support.
-.Sp
-If \s-1EXPR\s0 is omitted, uses \f(CW$_\fR.
-.IP "umask \s-1EXPR\s0" 8
-.IX Xref "umask"
-.IX Item "umask EXPR"
-.PD 0
-.IP "umask" 8
-.IX Item "umask"
-.PD
-Sets the umask for the process to \s-1EXPR\s0 and returns the previous value.
-If \s-1EXPR\s0 is omitted, merely returns the current umask.
-.Sp
-The Unix permission \f(CW\*(C`rwxr\-x\-\-\-\*(C'\fR is represented as three sets of three
-bits, or three octal digits: \f(CW0750\fR (the leading 0 indicates octal
-and isn't one of the digits). The \f(CW\*(C`umask\*(C'\fR value is such a number
-representing disabled permissions bits. The permission (or \*(L"mode\*(R")
-values you pass \f(CW\*(C`mkdir\*(C'\fR or \f(CW\*(C`sysopen\*(C'\fR are modified by your umask, so
-even if you tell \f(CW\*(C`sysopen\*(C'\fR to create a file with permissions \f(CW0777\fR,
-if your umask is \f(CW0022\fR then the file will actually be created with
-permissions \f(CW0755\fR. If your \f(CW\*(C`umask\*(C'\fR were \f(CW0027\fR (group can't
-write; others can't read, write, or execute), then passing
-\&\f(CW\*(C`sysopen\*(C'\fR \f(CW0666\fR would create a file with mode \f(CW0640\fR (\f(CW\*(C`0666 &~
-027\*(C'\fR is \f(CW0640\fR).
-.Sp
-Here's some advice: supply a creation mode of \f(CW0666\fR for regular
-files (in \f(CW\*(C`sysopen\*(C'\fR) and one of \f(CW0777\fR for directories (in
-\&\f(CW\*(C`mkdir\*(C'\fR) and executable files. This gives users the freedom of
-choice: if they want protected files, they might choose process umasks
-of \f(CW022\fR, \f(CW027\fR, or even the particularly antisocial mask of \f(CW077\fR.
-Programs should rarely if ever make policy decisions better left to
-the user. The exception to this is when writing files that should be
-kept private: mail files, web browser cookies, \fI.rhosts\fR files, and
-so on.
-.Sp
-If \fIumask\fR\|(2) is not implemented on your system and you are trying to
-restrict access for \fIyourself\fR (i.e., (\s-1EXPR\s0 & 0700) > 0), produces a
-fatal error at run time. If \fIumask\fR\|(2) is not implemented and you are
-not trying to restrict access for yourself, returns \f(CW\*(C`undef\*(C'\fR.
-.Sp
-Remember that a umask is a number, usually given in octal; it is \fInot\fR a
-string of octal digits. See also \*(L"oct\*(R", if all you have is a string.
-.IP "undef \s-1EXPR\s0" 8
-.IX Xref "undef undefine"
-.IX Item "undef EXPR"
-.PD 0
-.IP "undef" 8
-.IX Item "undef"
-.PD
-Undefines the value of \s-1EXPR\s0, which must be an lvalue. Use only on a
-scalar value, an array (using \f(CW\*(C`@\*(C'\fR), a hash (using \f(CW\*(C`%\*(C'\fR), a subroutine
-(using \f(CW\*(C`&\*(C'\fR), or a typeglob (using \f(CW\*(C`*\*(C'\fR). (Saying \f(CW\*(C`undef $hash{$key}\*(C'\fR
-will probably not do what you expect on most predefined variables or
-\&\s-1DBM\s0 list values, so don't do that; see delete.) Always returns the
-undefined value. You can omit the \s-1EXPR\s0, in which case nothing is
-undefined, but you still get an undefined value that you could, for
-instance, return from a subroutine, assign to a variable or pass as a
-parameter. Examples:
-.Sp
-.Vb 9
-\& undef $foo;
-\& undef $bar{'blurfl'}; # Compare to: delete $bar{'blurfl'};
-\& undef @ary;
-\& undef %hash;
-\& undef &mysub;
-\& undef *xyz; # destroys $xyz, @xyz, %xyz, &xyz, etc.
-\& return (wantarray ? (undef, $errmsg) : undef) if $they_blew_it;
-\& select undef, undef, undef, 0.25;
-\& ($a, $b, undef, $c) = &foo; # Ignore third value returned
-.Ve
-.Sp
-Note that this is a unary operator, not a list operator.
-.IP "unlink \s-1LIST\s0" 8
-.IX Xref "unlink delete remove rm"
-.IX Item "unlink LIST"
-.PD 0
-.IP "unlink" 8
-.IX Item "unlink"
-.PD
-Deletes a list of files. Returns the number of files successfully
-deleted.
-.Sp
-.Vb 3
-\& $cnt = unlink 'a', 'b', 'c';
-\& unlink @goners;
-\& unlink <*.bak>;
-.Ve
-.Sp
-Note: \f(CW\*(C`unlink\*(C'\fR will not attempt to delete directories unless you are superuser
-and the \fB\-U\fR flag is supplied to Perl. Even if these conditions are
-met, be warned that unlinking a directory can inflict damage on your
-filesystem. Finally, using \f(CW\*(C`unlink\*(C'\fR on directories is not supported on
-many operating systems. Use \f(CW\*(C`rmdir\*(C'\fR instead.
-.Sp
-If \s-1LIST\s0 is omitted, uses \f(CW$_\fR.
-.IP "unpack \s-1TEMPLATE\s0,EXPR" 8
-.IX Xref "unpack"
-.IX Item "unpack TEMPLATE,EXPR"
-\&\f(CW\*(C`unpack\*(C'\fR does the reverse of \f(CW\*(C`pack\*(C'\fR: it takes a string
-and expands it out into a list of values.
-(In scalar context, it returns merely the first value produced.)
-.Sp
-The string is broken into chunks described by the \s-1TEMPLATE\s0. Each chunk
-is converted separately to a value. Typically, either the string is a result
-of \f(CW\*(C`pack\*(C'\fR, or the bytes of the string represent a C structure of some
-kind.
-.Sp
-The \s-1TEMPLATE\s0 has the same format as in the \f(CW\*(C`pack\*(C'\fR function.
-Here's a subroutine that does substring:
-.Sp
-.Vb 4
-\& sub substr {
-\& my($what,$where,$howmuch) = @_;
-\& unpack("x$where a$howmuch", $what);
-\& }
-.Ve
-.Sp
-and then there's
-.Sp
-.Vb 1
-\& sub ordinal { unpack("c",$_[0]); } # same as ord()
-.Ve
-.Sp
-In addition to fields allowed in \fIpack()\fR, you may prefix a field with
-a %<number> to indicate that
-you want a <number>\-bit checksum of the items instead of the items
-themselves. Default is a 16\-bit checksum. Checksum is calculated by
-summing numeric values of expanded values (for string fields the sum of
-\&\f(CW\*(C`ord($char)\*(C'\fR is taken, for bit fields the sum of zeroes and ones).
-.Sp
-For example, the following
-computes the same number as the System V sum program:
-.Sp
-.Vb 4
-\& $checksum = do {
-\& local $/; # slurp!
-\& unpack("%32C*",<>) % 65535;
-\& };
-.Ve
-.Sp
-The following efficiently counts the number of set bits in a bit vector:
-.Sp
-.Vb 1
-\& $setbits = unpack("%32b*", $selectmask);
-.Ve
-.Sp
-The \f(CW\*(C`p\*(C'\fR and \f(CW\*(C`P\*(C'\fR formats should be used with care. Since Perl
-has no way of checking whether the value passed to \f(CW\*(C`unpack()\*(C'\fR
-corresponds to a valid memory location, passing a pointer value that's
-not known to be valid is likely to have disastrous consequences.
-.Sp
-If there are more pack codes or if the repeat count of a field or a group
-is larger than what the remainder of the input string allows, the result
-is not well defined: in some cases, the repeat count is decreased, or
-\&\f(CW\*(C`unpack()\*(C'\fR will produce null strings or zeroes, or terminate with an
-error. If the input string is longer than one described by the \s-1TEMPLATE\s0,
-the rest is ignored.
-.Sp
-See \*(L"pack\*(R" for more examples and notes.
-.IP "untie \s-1VARIABLE\s0" 8
-.IX Xref "untie"
-.IX Item "untie VARIABLE"
-Breaks the binding between a variable and a package. (See \f(CW\*(C`tie\*(C'\fR.)
-Has no effect if the variable is not tied.
-.IP "unshift \s-1ARRAY\s0,LIST" 8
-.IX Xref "unshift"
-.IX Item "unshift ARRAY,LIST"
-Does the opposite of a \f(CW\*(C`shift\*(C'\fR. Or the opposite of a \f(CW\*(C`push\*(C'\fR,
-depending on how you look at it. Prepends list to the front of the
-array, and returns the new number of elements in the array.
-.Sp
-.Vb 1
-\& unshift(@ARGV, '-e') unless $ARGV[0] =~ /^-/;
-.Ve
-.Sp
-Note the \s-1LIST\s0 is prepended whole, not one element at a time, so the
-prepended elements stay in the same order. Use \f(CW\*(C`reverse\*(C'\fR to do the
-reverse.
-.IP "use Module \s-1VERSION\s0 \s-1LIST\s0" 8
-.IX Xref "use module import"
-.IX Item "use Module VERSION LIST"
-.PD 0
-.IP "use Module \s-1VERSION\s0" 8
-.IX Item "use Module VERSION"
-.IP "use Module \s-1LIST\s0" 8
-.IX Item "use Module LIST"
-.IP "use Module" 8
-.IX Item "use Module"
-.IP "use \s-1VERSION\s0" 8
-.IX Item "use VERSION"
-.PD
-Imports some semantics into the current package from the named module,
-generally by aliasing certain subroutine or variable names into your
-package. It is exactly equivalent to
-.Sp
-.Vb 1
-\& BEGIN { require Module; import Module LIST; }
-.Ve
-.Sp
-except that Module \fImust\fR be a bareword.
-.Sp
-\&\s-1VERSION\s0 may be either a numeric argument such as 5.006, which will be
-compared to \f(CW$]\fR, or a literal of the form v5.6.1, which will be compared
-to \f(CW$^V\fR (aka \f(CW$PERL_VERSION\fR. A fatal error is produced if \s-1VERSION\s0 is
-greater than the version of the current Perl interpreter; Perl will not
-attempt to parse the rest of the file. Compare with \*(L"require\*(R", which can
-do a similar check at run time.
-.Sp
-Specifying \s-1VERSION\s0 as a literal of the form v5.6.1 should generally be
-avoided, because it leads to misleading error messages under earlier
-versions of Perl that do not support this syntax. The equivalent numeric
-version should be used instead.
-.Sp
-.Vb 3
-\& use v5.6.1; # compile time version check
-\& use 5.6.1; # ditto
-\& use 5.006_001; # ditto; preferred for backwards compatibility
-.Ve
-.Sp
-This is often useful if you need to check the current Perl version before
-\&\f(CW\*(C`use\*(C'\fRing library modules that have changed in incompatible ways from
-older versions of Perl. (We try not to do this more than we have to.)
-.Sp
-The \f(CW\*(C`BEGIN\*(C'\fR forces the \f(CW\*(C`require\*(C'\fR and \f(CW\*(C`import\*(C'\fR to happen at compile time. The
-\&\f(CW\*(C`require\*(C'\fR makes sure the module is loaded into memory if it hasn't been
-yet. The \f(CW\*(C`import\*(C'\fR is not a builtin\*(--it's just an ordinary static method
-call into the \f(CW\*(C`Module\*(C'\fR package to tell the module to import the list of
-features back into the current package. The module can implement its
-\&\f(CW\*(C`import\*(C'\fR method any way it likes, though most modules just choose to
-derive their \f(CW\*(C`import\*(C'\fR method via inheritance from the \f(CW\*(C`Exporter\*(C'\fR class that
-is defined in the \f(CW\*(C`Exporter\*(C'\fR module. See Exporter. If no \f(CW\*(C`import\*(C'\fR
-method can be found then the call is skipped.
-.Sp
-If you do not want to call the package's \f(CW\*(C`import\*(C'\fR method (for instance,
-to stop your namespace from being altered), explicitly supply the empty list:
-.Sp
-.Vb 1
-\& use Module ();
-.Ve
-.Sp
-That is exactly equivalent to
-.Sp
-.Vb 1
-\& BEGIN { require Module }
-.Ve
-.Sp
-If the \s-1VERSION\s0 argument is present between Module and \s-1LIST\s0, then the
-\&\f(CW\*(C`use\*(C'\fR will call the \s-1VERSION\s0 method in class Module with the given
-version as an argument. The default \s-1VERSION\s0 method, inherited from
-the \s-1UNIVERSAL\s0 class, croaks if the given version is larger than the
-value of the variable \f(CW$Module::VERSION\fR.
-.Sp
-Again, there is a distinction between omitting \s-1LIST\s0 (\f(CW\*(C`import\*(C'\fR called
-with no arguments) and an explicit empty \s-1LIST\s0 \f(CW\*(C`()\*(C'\fR (\f(CW\*(C`import\*(C'\fR not
-called). Note that there is no comma after \s-1VERSION\s0!
-.Sp
-Because this is a wide-open interface, pragmas (compiler directives)
-are also implemented this way. Currently implemented pragmas are:
-.Sp
-.Vb 8
-\& use constant;
-\& use diagnostics;
-\& use integer;
-\& use sigtrap qw(SEGV BUS);
-\& use strict qw(subs vars refs);
-\& use subs qw(afunc blurfl);
-\& use warnings qw(all);
-\& use sort qw(stable _quicksort _mergesort);
-.Ve
-.Sp
-Some of these pseudo-modules import semantics into the current
-block scope (like \f(CW\*(C`strict\*(C'\fR or \f(CW\*(C`integer\*(C'\fR, unlike ordinary modules,
-which import symbols into the current package (which are effective
-through the end of the file).
-.Sp
-There's a corresponding \f(CW\*(C`no\*(C'\fR command that unimports meanings imported
-by \f(CW\*(C`use\*(C'\fR, i.e., it calls \f(CW\*(C`unimport Module LIST\*(C'\fR instead of \f(CW\*(C`import\*(C'\fR.
-.Sp
-.Vb 3
-\& no integer;
-\& no strict 'refs';
-\& no warnings;
-.Ve
-.Sp
-See perlmodlib for a list of standard modules and pragmas. See perlrun
-for the \f(CW\*(C`\-M\*(C'\fR and \f(CW\*(C`\-m\*(C'\fR command-line options to perl that give \f(CW\*(C`use\*(C'\fR
-functionality from the command\-line.
-.IP "utime \s-1LIST\s0" 8
-.IX Xref "utime"
-.IX Item "utime LIST"
-Changes the access and modification times on each file of a list of
-files. The first two elements of the list must be the \s-1NUMERICAL\s0 access
-and modification times, in that order. Returns the number of files
-successfully changed. The inode change time of each file is set
-to the current time. For example, this code has the same effect as the
-Unix \fItouch\fR\|(1) command when the files \fIalready exist\fR and belong to
-the user running the program:
-.Sp
-.Vb 3
-\& #!/usr/bin/perl
-\& $atime = $mtime = time;
-\& utime $atime, $mtime, @ARGV;
-.Ve
-.Sp
-Since perl 5.7.2, if the first two elements of the list are \f(CW\*(C`undef\*(C'\fR, then
-the \fIutime\fR\|(2) function in the C library will be called with a null second
-argument. On most systems, this will set the file's access and
-modification times to the current time (i.e. equivalent to the example
-above) and will even work on other users' files where you have write
-permission:
-.Sp
-.Vb 1
-\& utime undef, undef, @ARGV;
-.Ve
-.Sp
-Under \s-1NFS\s0 this will use the time of the \s-1NFS\s0 server, not the time of
-the local machine. If there is a time synchronization problem, the
-\&\s-1NFS\s0 server and local machine will have different times. The Unix
-\&\fItouch\fR\|(1) command will in fact normally use this form instead of the
-one shown in the first example.
-.Sp
-Note that only passing one of the first two elements as \f(CW\*(C`undef\*(C'\fR will
-be equivalent of passing it as 0 and will not have the same effect as
-described when they are both \f(CW\*(C`undef\*(C'\fR. This case will also trigger an
-uninitialized warning.
-.IP "values \s-1HASH\s0" 8
-.IX Xref "values"
-.IX Item "values HASH"
-Returns a list consisting of all the values of the named hash.
-(In a scalar context, returns the number of values.)
-.Sp
-The values are returned in an apparently random order. The actual
-random order is subject to change in future versions of perl, but it
-is guaranteed to be the same order as either the \f(CW\*(C`keys\*(C'\fR or \f(CW\*(C`each\*(C'\fR
-function would produce on the same (unmodified) hash. Since Perl
-5.8.1 the ordering is different even between different runs of Perl
-for security reasons (see \*(L"Algorithmic Complexity Attacks\*(R" in perlsec).
-.Sp
-As a side effect, calling \fIvalues()\fR resets the \s-1HASH\s0's internal iterator,
-see \*(L"each\*(R". (In particular, calling \fIvalues()\fR in void context resets
-the iterator with no other overhead.)
-.Sp
-Note that the values are not copied, which means modifying them will
-modify the contents of the hash:
-.Sp
-.Vb 2
-\& for (values %hash) { s/foo/bar/g } # modifies %hash values
-\& for (@hash{keys %hash}) { s/foo/bar/g } # same
-.Ve
-.Sp
-See also \f(CW\*(C`keys\*(C'\fR, \f(CW\*(C`each\*(C'\fR, and \f(CW\*(C`sort\*(C'\fR.
-.IP "vec \s-1EXPR\s0,OFFSET,BITS" 8
-.IX Xref "vec bit bit vector"
-.IX Item "vec EXPR,OFFSET,BITS"
-Treats the string in \s-1EXPR\s0 as a bit vector made up of elements of
-width \s-1BITS\s0, and returns the value of the element specified by \s-1OFFSET\s0
-as an unsigned integer. \s-1BITS\s0 therefore specifies the number of bits
-that are reserved for each element in the bit vector. This must
-be a power of two from 1 to 32 (or 64, if your platform supports
-that).
-.Sp
-If \s-1BITS\s0 is 8, \*(L"elements\*(R" coincide with bytes of the input string.
-.Sp
-If \s-1BITS\s0 is 16 or more, bytes of the input string are grouped into chunks
-of size \s-1BITS/8\s0, and each group is converted to a number as with
-\&\fIpack()\fR/\fIunpack()\fR with big-endian formats \f(CW\*(C`n\*(C'\fR/\f(CW\*(C`N\*(C'\fR (and analogously
-for BITS==64). See \*(L"pack\*(R" for details.
-.Sp
-If bits is 4 or less, the string is broken into bytes, then the bits
-of each byte are broken into 8/BITS groups. Bits of a byte are
-numbered in a little-endian-ish way, as in \f(CW0x01\fR, \f(CW0x02\fR,
-\&\f(CW0x04\fR, \f(CW0x08\fR, \f(CW0x10\fR, \f(CW0x20\fR, \f(CW0x40\fR, \f(CW0x80\fR. For example,
-breaking the single input byte \f(CW\*(C`chr(0x36)\*(C'\fR into two groups gives a list
-\&\f(CW\*(C`(0x6, 0x3)\*(C'\fR; breaking it into 4 groups gives \f(CW\*(C`(0x2, 0x1, 0x3, 0x0)\*(C'\fR.
-.Sp
-\&\f(CW\*(C`vec\*(C'\fR may also be assigned to, in which case parentheses are needed
-to give the expression the correct precedence as in
-.Sp
-.Vb 1
-\& vec($image, $max_x * $x + $y, 8) = 3;
-.Ve
-.Sp
-If the selected element is outside the string, the value 0 is returned.
-If an element off the end of the string is written to, Perl will first
-extend the string with sufficiently many zero bytes. It is an error
-to try to write off the beginning of the string (i.e. negative \s-1OFFSET\s0).
-.Sp
-The string should not contain any character with the value > 255 (which
-can only happen if you're using \s-1UTF\-8\s0 encoding). If it does, it will be
-treated as something that is not \s-1UTF\-8\s0 encoded. When the \f(CW\*(C`vec\*(C'\fR was
-assigned to, other parts of your program will also no longer consider the
-string to be \s-1UTF\-8\s0 encoded. In other words, if you do have such characters
-in your string, \fIvec()\fR will operate on the actual byte string, and not the
-conceptual character string.
-.Sp
-Strings created with \f(CW\*(C`vec\*(C'\fR can also be manipulated with the logical
-operators \f(CW\*(C`|\*(C'\fR, \f(CW\*(C`&\*(C'\fR, \f(CW\*(C`^\*(C'\fR, and \f(CW\*(C`~\*(C'\fR. These operators will assume a bit
-vector operation is desired when both operands are strings.
-See \*(L"Bitwise String Operators\*(R" in perlop.
-.Sp
-The following code will build up an \s-1ASCII\s0 string saying \f(CW'PerlPerlPerl'\fR.
-The comments show the string after each step. Note that this code works
-in the same way on big-endian or little-endian machines.
-.Sp
-.Vb 2
-\& my $foo = '';
-\& vec($foo, 0, 32) = 0x5065726C; # 'Perl'
-.Ve
-.Sp
-.Vb 2
-\& # $foo eq "Perl" eq "\ex50\ex65\ex72\ex6C", 32 bits
-\& print vec($foo, 0, 8); # prints 80 == 0x50 == ord('P')
-.Ve
-.Sp
-.Vb 11
-\& vec($foo, 2, 16) = 0x5065; # 'PerlPe'
-\& vec($foo, 3, 16) = 0x726C; # 'PerlPerl'
-\& vec($foo, 8, 8) = 0x50; # 'PerlPerlP'
-\& vec($foo, 9, 8) = 0x65; # 'PerlPerlPe'
-\& vec($foo, 20, 4) = 2; # 'PerlPerlPe' . "\ex02"
-\& vec($foo, 21, 4) = 7; # 'PerlPerlPer'
-\& # 'r' is "\ex72"
-\& vec($foo, 45, 2) = 3; # 'PerlPerlPer' . "\ex0c"
-\& vec($foo, 93, 1) = 1; # 'PerlPerlPer' . "\ex2c"
-\& vec($foo, 94, 1) = 1; # 'PerlPerlPerl'
-\& # 'l' is "\ex6c"
-.Ve
-.Sp
-To transform a bit vector into a string or list of 0's and 1's, use these:
-.Sp
-.Vb 2
-\& $bits = unpack("b*", $vector);
-\& @bits = split(//, unpack("b*", $vector));
-.Ve
-.Sp
-If you know the exact length in bits, it can be used in place of the \f(CW\*(C`*\*(C'\fR.
-.Sp
-Here is an example to illustrate how the bits actually fall in place:
-.Sp
-.Vb 1
-\& #!/usr/bin/perl -wl
-.Ve
-.Sp
-.Vb 5
-\& print <<'EOT';
-\& 0 1 2 3
-\& unpack("V",$_) 01234567890123456789012345678901
-\& ------------------------------------------------------------------
-\& EOT
-.Ve
-.Sp
-.Vb 13
-\& for $w (0..3) {
-\& $width = 2**$w;
-\& for ($shift=0; $shift < $width; ++$shift) {
-\& for ($off=0; $off < 32/$width; ++$off) {
-\& $str = pack("B*", "0"x32);
-\& $bits = (1<<$shift);
-\& vec($str, $off, $width) = $bits;
-\& $res = unpack("b*",$str);
-\& $val = unpack("V", $str);
-\& write;
-\& }
-\& }
-\& }
-.Ve
-.Sp
-.Vb 5
-\& format STDOUT =
-\& vec($_,@#,@#) = @<< == @######### @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-\& $off, $width, $bits, $val, $res
-\& .
-\& __END__
-.Ve
-.Sp
-Regardless of the machine architecture on which it is run, the above
-example should print the following table:
-.Sp
-.Vb 131
-\& 0 1 2 3
-\& unpack("V",$_) 01234567890123456789012345678901
-\& ------------------------------------------------------------------
-\& vec($_, 0, 1) = 1 == 1 10000000000000000000000000000000
-\& vec($_, 1, 1) = 1 == 2 01000000000000000000000000000000
-\& vec($_, 2, 1) = 1 == 4 00100000000000000000000000000000
-\& vec($_, 3, 1) = 1 == 8 00010000000000000000000000000000
-\& vec($_, 4, 1) = 1 == 16 00001000000000000000000000000000
-\& vec($_, 5, 1) = 1 == 32 00000100000000000000000000000000
-\& vec($_, 6, 1) = 1 == 64 00000010000000000000000000000000
-\& vec($_, 7, 1) = 1 == 128 00000001000000000000000000000000
-\& vec($_, 8, 1) = 1 == 256 00000000100000000000000000000000
-\& vec($_, 9, 1) = 1 == 512 00000000010000000000000000000000
-\& vec($_,10, 1) = 1 == 1024 00000000001000000000000000000000
-\& vec($_,11, 1) = 1 == 2048 00000000000100000000000000000000
-\& vec($_,12, 1) = 1 == 4096 00000000000010000000000000000000
-\& vec($_,13, 1) = 1 == 8192 00000000000001000000000000000000
-\& vec($_,14, 1) = 1 == 16384 00000000000000100000000000000000
-\& vec($_,15, 1) = 1 == 32768 00000000000000010000000000000000
-\& vec($_,16, 1) = 1 == 65536 00000000000000001000000000000000
-\& vec($_,17, 1) = 1 == 131072 00000000000000000100000000000000
-\& vec($_,18, 1) = 1 == 262144 00000000000000000010000000000000
-\& vec($_,19, 1) = 1 == 524288 00000000000000000001000000000000
-\& vec($_,20, 1) = 1 == 1048576 00000000000000000000100000000000
-\& vec($_,21, 1) = 1 == 2097152 00000000000000000000010000000000
-\& vec($_,22, 1) = 1 == 4194304 00000000000000000000001000000000
-\& vec($_,23, 1) = 1 == 8388608 00000000000000000000000100000000
-\& vec($_,24, 1) = 1 == 16777216 00000000000000000000000010000000
-\& vec($_,25, 1) = 1 == 33554432 00000000000000000000000001000000
-\& vec($_,26, 1) = 1 == 67108864 00000000000000000000000000100000
-\& vec($_,27, 1) = 1 == 134217728 00000000000000000000000000010000
-\& vec($_,28, 1) = 1 == 268435456 00000000000000000000000000001000
-\& vec($_,29, 1) = 1 == 536870912 00000000000000000000000000000100
-\& vec($_,30, 1) = 1 == 1073741824 00000000000000000000000000000010
-\& vec($_,31, 1) = 1 == 2147483648 00000000000000000000000000000001
-\& vec($_, 0, 2) = 1 == 1 10000000000000000000000000000000
-\& vec($_, 1, 2) = 1 == 4 00100000000000000000000000000000
-\& vec($_, 2, 2) = 1 == 16 00001000000000000000000000000000
-\& vec($_, 3, 2) = 1 == 64 00000010000000000000000000000000
-\& vec($_, 4, 2) = 1 == 256 00000000100000000000000000000000
-\& vec($_, 5, 2) = 1 == 1024 00000000001000000000000000000000
-\& vec($_, 6, 2) = 1 == 4096 00000000000010000000000000000000
-\& vec($_, 7, 2) = 1 == 16384 00000000000000100000000000000000
-\& vec($_, 8, 2) = 1 == 65536 00000000000000001000000000000000
-\& vec($_, 9, 2) = 1 == 262144 00000000000000000010000000000000
-\& vec($_,10, 2) = 1 == 1048576 00000000000000000000100000000000
-\& vec($_,11, 2) = 1 == 4194304 00000000000000000000001000000000
-\& vec($_,12, 2) = 1 == 16777216 00000000000000000000000010000000
-\& vec($_,13, 2) = 1 == 67108864 00000000000000000000000000100000
-\& vec($_,14, 2) = 1 == 268435456 00000000000000000000000000001000
-\& vec($_,15, 2) = 1 == 1073741824 00000000000000000000000000000010
-\& vec($_, 0, 2) = 2 == 2 01000000000000000000000000000000
-\& vec($_, 1, 2) = 2 == 8 00010000000000000000000000000000
-\& vec($_, 2, 2) = 2 == 32 00000100000000000000000000000000
-\& vec($_, 3, 2) = 2 == 128 00000001000000000000000000000000
-\& vec($_, 4, 2) = 2 == 512 00000000010000000000000000000000
-\& vec($_, 5, 2) = 2 == 2048 00000000000100000000000000000000
-\& vec($_, 6, 2) = 2 == 8192 00000000000001000000000000000000
-\& vec($_, 7, 2) = 2 == 32768 00000000000000010000000000000000
-\& vec($_, 8, 2) = 2 == 131072 00000000000000000100000000000000
-\& vec($_, 9, 2) = 2 == 524288 00000000000000000001000000000000
-\& vec($_,10, 2) = 2 == 2097152 00000000000000000000010000000000
-\& vec($_,11, 2) = 2 == 8388608 00000000000000000000000100000000
-\& vec($_,12, 2) = 2 == 33554432 00000000000000000000000001000000
-\& vec($_,13, 2) = 2 == 134217728 00000000000000000000000000010000
-\& vec($_,14, 2) = 2 == 536870912 00000000000000000000000000000100
-\& vec($_,15, 2) = 2 == 2147483648 00000000000000000000000000000001
-\& vec($_, 0, 4) = 1 == 1 10000000000000000000000000000000
-\& vec($_, 1, 4) = 1 == 16 00001000000000000000000000000000
-\& vec($_, 2, 4) = 1 == 256 00000000100000000000000000000000
-\& vec($_, 3, 4) = 1 == 4096 00000000000010000000000000000000
-\& vec($_, 4, 4) = 1 == 65536 00000000000000001000000000000000
-\& vec($_, 5, 4) = 1 == 1048576 00000000000000000000100000000000
-\& vec($_, 6, 4) = 1 == 16777216 00000000000000000000000010000000
-\& vec($_, 7, 4) = 1 == 268435456 00000000000000000000000000001000
-\& vec($_, 0, 4) = 2 == 2 01000000000000000000000000000000
-\& vec($_, 1, 4) = 2 == 32 00000100000000000000000000000000
-\& vec($_, 2, 4) = 2 == 512 00000000010000000000000000000000
-\& vec($_, 3, 4) = 2 == 8192 00000000000001000000000000000000
-\& vec($_, 4, 4) = 2 == 131072 00000000000000000100000000000000
-\& vec($_, 5, 4) = 2 == 2097152 00000000000000000000010000000000
-\& vec($_, 6, 4) = 2 == 33554432 00000000000000000000000001000000
-\& vec($_, 7, 4) = 2 == 536870912 00000000000000000000000000000100
-\& vec($_, 0, 4) = 4 == 4 00100000000000000000000000000000
-\& vec($_, 1, 4) = 4 == 64 00000010000000000000000000000000
-\& vec($_, 2, 4) = 4 == 1024 00000000001000000000000000000000
-\& vec($_, 3, 4) = 4 == 16384 00000000000000100000000000000000
-\& vec($_, 4, 4) = 4 == 262144 00000000000000000010000000000000
-\& vec($_, 5, 4) = 4 == 4194304 00000000000000000000001000000000
-\& vec($_, 6, 4) = 4 == 67108864 00000000000000000000000000100000
-\& vec($_, 7, 4) = 4 == 1073741824 00000000000000000000000000000010
-\& vec($_, 0, 4) = 8 == 8 00010000000000000000000000000000
-\& vec($_, 1, 4) = 8 == 128 00000001000000000000000000000000
-\& vec($_, 2, 4) = 8 == 2048 00000000000100000000000000000000
-\& vec($_, 3, 4) = 8 == 32768 00000000000000010000000000000000
-\& vec($_, 4, 4) = 8 == 524288 00000000000000000001000000000000
-\& vec($_, 5, 4) = 8 == 8388608 00000000000000000000000100000000
-\& vec($_, 6, 4) = 8 == 134217728 00000000000000000000000000010000
-\& vec($_, 7, 4) = 8 == 2147483648 00000000000000000000000000000001
-\& vec($_, 0, 8) = 1 == 1 10000000000000000000000000000000
-\& vec($_, 1, 8) = 1 == 256 00000000100000000000000000000000
-\& vec($_, 2, 8) = 1 == 65536 00000000000000001000000000000000
-\& vec($_, 3, 8) = 1 == 16777216 00000000000000000000000010000000
-\& vec($_, 0, 8) = 2 == 2 01000000000000000000000000000000
-\& vec($_, 1, 8) = 2 == 512 00000000010000000000000000000000
-\& vec($_, 2, 8) = 2 == 131072 00000000000000000100000000000000
-\& vec($_, 3, 8) = 2 == 33554432 00000000000000000000000001000000
-\& vec($_, 0, 8) = 4 == 4 00100000000000000000000000000000
-\& vec($_, 1, 8) = 4 == 1024 00000000001000000000000000000000
-\& vec($_, 2, 8) = 4 == 262144 00000000000000000010000000000000
-\& vec($_, 3, 8) = 4 == 67108864 00000000000000000000000000100000
-\& vec($_, 0, 8) = 8 == 8 00010000000000000000000000000000
-\& vec($_, 1, 8) = 8 == 2048 00000000000100000000000000000000
-\& vec($_, 2, 8) = 8 == 524288 00000000000000000001000000000000
-\& vec($_, 3, 8) = 8 == 134217728 00000000000000000000000000010000
-\& vec($_, 0, 8) = 16 == 16 00001000000000000000000000000000
-\& vec($_, 1, 8) = 16 == 4096 00000000000010000000000000000000
-\& vec($_, 2, 8) = 16 == 1048576 00000000000000000000100000000000
-\& vec($_, 3, 8) = 16 == 268435456 00000000000000000000000000001000
-\& vec($_, 0, 8) = 32 == 32 00000100000000000000000000000000
-\& vec($_, 1, 8) = 32 == 8192 00000000000001000000000000000000
-\& vec($_, 2, 8) = 32 == 2097152 00000000000000000000010000000000
-\& vec($_, 3, 8) = 32 == 536870912 00000000000000000000000000000100
-\& vec($_, 0, 8) = 64 == 64 00000010000000000000000000000000
-\& vec($_, 1, 8) = 64 == 16384 00000000000000100000000000000000
-\& vec($_, 2, 8) = 64 == 4194304 00000000000000000000001000000000
-\& vec($_, 3, 8) = 64 == 1073741824 00000000000000000000000000000010
-\& vec($_, 0, 8) = 128 == 128 00000001000000000000000000000000
-\& vec($_, 1, 8) = 128 == 32768 00000000000000010000000000000000
-\& vec($_, 2, 8) = 128 == 8388608 00000000000000000000000100000000
-\& vec($_, 3, 8) = 128 == 2147483648 00000000000000000000000000000001
-.Ve
-.IP "wait" 8
-.IX Xref "wait"
-.IX Item "wait"
-Behaves like the \fIwait\fR\|(2) system call on your system: it waits for a child
-process to terminate and returns the pid of the deceased process, or
-\&\f(CW\*(C`\-1\*(C'\fR if there are no child processes. The status is returned in \f(CW$?\fR.
-Note that a return value of \f(CW\*(C`\-1\*(C'\fR could mean that child processes are
-being automatically reaped, as described in perlipc.
-.IP "waitpid \s-1PID\s0,FLAGS" 8
-.IX Xref "waitpid"
-.IX Item "waitpid PID,FLAGS"
-Waits for a particular child process to terminate and returns the pid of
-the deceased process, or \f(CW\*(C`\-1\*(C'\fR if there is no such child process. On some
-systems, a value of 0 indicates that there are processes still running.
-The status is returned in \f(CW$?\fR. If you say
-.Sp
-.Vb 5
-\& use POSIX ":sys_wait_h";
-\& #...
-\& do {
-\& $kid = waitpid(-1, WNOHANG);
-\& } until $kid > 0;
-.Ve
-.Sp
-then you can do a non-blocking wait for all pending zombie processes.
-Non-blocking wait is available on machines supporting either the
-\&\fIwaitpid\fR\|(2) or \fIwait4\fR\|(2) system calls. However, waiting for a particular
-pid with \s-1FLAGS\s0 of \f(CW0\fR is implemented everywhere. (Perl emulates the
-system call by remembering the status values of processes that have
-exited but have not been harvested by the Perl script yet.)
-.Sp
-Note that on some systems, a return value of \f(CW\*(C`\-1\*(C'\fR could mean that child
-processes are being automatically reaped. See perlipc for details,
-and for other examples.
-.IP "wantarray" 8
-.IX Xref "wantarray context"
-.IX Item "wantarray"
-Returns true if the context of the currently executing subroutine or
-\&\f(CW\*(C`eval\*(C'\fR is looking for a list value. Returns false if the context is
-looking for a scalar. Returns the undefined value if the context is
-looking for no value (void context).
-.Sp
-.Vb 3
-\& return unless defined wantarray; # don't bother doing more
-\& my @a = complex_calculation();
-\& return wantarray ? @a : "@a";
-.Ve
-.Sp
-\&\f(CW\*(C`wantarray()\*(C'\fR's result is unspecified in the top level of a file,
-in a \f(CW\*(C`BEGIN\*(C'\fR, \f(CW\*(C`CHECK\*(C'\fR, \f(CW\*(C`INIT\*(C'\fR or \f(CW\*(C`END\*(C'\fR block, or in a \f(CW\*(C`DESTROY\*(C'\fR
-method.
-.Sp
-This function should have been named \fIwantlist()\fR instead.
-.IP "warn \s-1LIST\s0" 8
-.IX Xref "warn warning STDERR"
-.IX Item "warn LIST"
-Produces a message on \s-1STDERR\s0 just like \f(CW\*(C`die\*(C'\fR, but doesn't exit or throw
-an exception.
-.Sp
-If \s-1LIST\s0 is empty and \f(CW$@\fR already contains a value (typically from a
-previous eval) that value is used after appending \f(CW"\et...caught"\fR
-to \f(CW$@\fR. This is useful for staying almost, but not entirely similar to
-\&\f(CW\*(C`die\*(C'\fR.
-.Sp
-If \f(CW$@\fR is empty then the string \f(CW"Warning: Something's wrong"\fR is used.
-.Sp
-No message is printed if there is a \f(CW$SIG{_\|_WARN_\|_}\fR handler
-installed. It is the handler's responsibility to deal with the message
-as it sees fit (like, for instance, converting it into a \f(CW\*(C`die\*(C'\fR). Most
-handlers must therefore make arrangements to actually display the
-warnings that they are not prepared to deal with, by calling \f(CW\*(C`warn\*(C'\fR
-again in the handler. Note that this is quite safe and will not
-produce an endless loop, since \f(CW\*(C`_\|_WARN_\|_\*(C'\fR hooks are not called from
-inside one.
-.Sp
-You will find this behavior is slightly different from that of
-\&\f(CW$SIG{_\|_DIE_\|_}\fR handlers (which don't suppress the error text, but can
-instead call \f(CW\*(C`die\*(C'\fR again to change it).
-.Sp
-Using a \f(CW\*(C`_\|_WARN_\|_\*(C'\fR handler provides a powerful way to silence all
-warnings (even the so-called mandatory ones). An example:
-.Sp
-.Vb 7
-\& # wipe out *all* compile-time warnings
-\& BEGIN { $SIG{'__WARN__'} = sub { warn $_[0] if $DOWARN } }
-\& my $foo = 10;
-\& my $foo = 20; # no warning about duplicate my $foo,
-\& # but hey, you asked for it!
-\& # no compile-time or run-time warnings before here
-\& $DOWARN = 1;
-.Ve
-.Sp
-.Vb 2
-\& # run-time warnings enabled after here
-\& warn "\e$foo is alive and $foo!"; # does show up
-.Ve
-.Sp
-See perlvar for details on setting \f(CW%SIG\fR entries, and for more
-examples. See the Carp module for other kinds of warnings using its
-\&\fIcarp()\fR and \fIcluck()\fR functions.
-.IP "write \s-1FILEHANDLE\s0" 8
-.IX Xref "write"
-.IX Item "write FILEHANDLE"
-.PD 0
-.IP "write \s-1EXPR\s0" 8
-.IX Item "write EXPR"
-.IP "write" 8
-.IX Item "write"
-.PD
-Writes a formatted record (possibly multi\-line) to the specified \s-1FILEHANDLE\s0,
-using the format associated with that file. By default the format for
-a file is the one having the same name as the filehandle, but the
-format for the current output channel (see the \f(CW\*(C`select\*(C'\fR function) may be set
-explicitly by assigning the name of the format to the \f(CW$~\fR variable.
-.Sp
-Top of form processing is handled automatically: if there is
-insufficient room on the current page for the formatted record, the
-page is advanced by writing a form feed, a special top-of-page format
-is used to format the new page header, and then the record is written.
-By default the top-of-page format is the name of the filehandle with
-\&\*(L"_TOP\*(R" appended, but it may be dynamically set to the format of your
-choice by assigning the name to the \f(CW$^\fR variable while the filehandle is
-selected. The number of lines remaining on the current page is in
-variable \f(CW\*(C`$\-\*(C'\fR, which can be set to \f(CW0\fR to force a new page.
-.Sp
-If \s-1FILEHANDLE\s0 is unspecified, output goes to the current default output
-channel, which starts out as \s-1STDOUT\s0 but may be changed by the
-\&\f(CW\*(C`select\*(C'\fR operator. If the \s-1FILEHANDLE\s0 is an \s-1EXPR\s0, then the expression
-is evaluated and the resulting string is used to look up the name of
-the \s-1FILEHANDLE\s0 at run time. For more on formats, see perlform.
-.Sp
-Note that write is \fInot\fR the opposite of \f(CW\*(C`read\*(C'\fR. Unfortunately.
-.IP "y///" 8
-.IX Item "y///"
-The transliteration operator. Same as \f(CW\*(C`tr///\*(C'\fR. See perlop.
+
diff --git a/tests/examplefiles/pleac.in.rb b/tests/examplefiles/pleac.in.rb
index d74944ad..d1dea9f4 100644
--- a/tests/examplefiles/pleac.in.rb
+++ b/tests/examplefiles/pleac.in.rb
@@ -1221,1739 +1221,3 @@ def naive_shuffle(a)
end
-# @@PLEAC@@_4.18
-#!/usr/bin/env ruby
-# example 4-2 words
-# words - gather lines, present in colums
-
-# class to encapsulate the word formatting from the input
-class WordFormatter
- def initialize(cols)
- @cols = cols
- end
-
- # helper to return the length of the longest word in the wordlist
- def maxlen(wordlist)
- max = 1
- for word in wordlist
- if word.length > max
- max = word.length
- end
- end
- max
- end
-
- # process the wordlist and print it formmated into columns
- def output(wordlist)
- collen = maxlen(wordlist) + 1
- columns = @cols / collen
- columns = 1 if columns == 0
- rows = (wordlist.length + columns - 1) / columns
- # now process each item, picking out proper piece for this position
- 0.upto(rows * columns - 1) { |item|
- target = (item % columns) * rows + (item / columns)
- eol = ((item+1) % columns == 0)
- piece = wordlist[target] || ""
- piece = piece.ljust(collen) unless eol
- print piece
- puts if eol
- }
- # no need to finish it up, because eol is always true for the last element
- end
-end
-
-# get nr of chars that fit in window or console, see PLEAC 15.4
-# not portable -- linux only (?)
-def getWinCharWidth()
- buf = "\0" * 8
- $stdout.ioctl(0x5413, buf)
- ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("$4")
- ws_col || 80
-rescue
- 80
-end
-
-# main program
-cols = getWinCharWidth()
-formatter = WordFormatter.new(cols)
-words = readlines()
-words.collect! { |line|
- line.chomp
-}
-formatter.output(words)
-
-
-# @@PLEAC@@_4.19
-# In ruby, Fixnum's are automatically converted to Bignum's when
-# needed, so there is no need for an extra module
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-puts factorial(500)
-
-#---------------------------------------------------------
-# Example 4-3. tsc-permute
-# tsc_permute: permute each word of input
-def permute(items, perms)
- unless items.length > 0
- puts perms.join(" ")
- else
- for i in items
- newitems = items.dup
- newperms = perms.dup
- newperms.unshift(newitems.delete(i))
- permute(newitems, newperms)
- end
- end
-end
-# In ruby the main program must be after all definitions it is using
-permute(ARGV, [])
-
-#---------------------------------------------------------
-# mjd_permute: permute each word of input
-
-def factorial(n)
- s = 1
- while n > 0
- s *= n
- n -= 1
- end
- s
-end
-
-# we use a class with a class variable store the private cache
-# for the results of the factorial function.
-class Factorial
- @@fact = [ 1 ]
- def Factorial.compute(n)
- if @@fact[n]
- @@fact[n]
- else
- @@fact[n] = n * Factorial.compute(n - 1)
- end
- end
-end
-
-#---------------------------------------------------------
-# Example 4-4- mjd-permute
-# n2pat(n, len): produce the N-th pattern of length len
-
-# We must use a lower case letter as parameter N, otherwise it is
-# handled as constant Length is the length of the resulting
-# array, not the index of the last element (length -1) like in
-# the perl example.
-def n2pat(n, length)
- pat = []
- i = 1
- while i <= length
- pat.push(n % i)
- n /= i
- i += 1
- end
- pat
-end
-
-# pat2perm(pat): turn pattern returned by n2pat() into
-# permutation of integers.
-def pat2perm(pat)
- source = (0 .. pat.length - 1).to_a
- perm = []
- perm.push(source.slice!(pat.pop)) while pat.length > 0
- perm
-end
-
-def n2perm(n, len)
- pat2perm(n2pat(n,len))
-end
-
-# In ruby the main program must be after all definitions
-while gets
- data = split
- # the perl solution has used $#data, which is length-1
- num_permutations = Factorial.compute(data.length())
- 0.upto(num_permutations - 1) do |i|
- # in ruby we can not use an array as selector for an array
- # but by exchanging the two arrays, we can use the collect method
- # which returns an array with the result of all block invocations
- permutation = n2perm(i, data.length).collect {
- |j| data[j]
- }
- puts permutation.join(" ")
- end
-end
-
-
-# @@PLEAC@@_5.0
-age = { "Nat", 24,
- "Jules", 25,
- "Josh", 17 }
-
-age["Nat"] = 24
-age["Jules"] = 25
-age["Josh"] = 17
-
-food_color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange"
- }
-
-# In Ruby, you cannot avoid the double or simple quoting
-# while manipulatin hashes
-
-
-# @@PLEAC@@_5.1
-hash[key] = value
-
-food_color["Raspberry"] = "pink"
-puts "Known foods:", food_color.keys
-
-
-# @@PLEAC@@_5.2
-# does hash have a value for key ?
-if (hash.has_key?(key))
- # it exists
-else
- # it doesn't
-end
-
-[ "Banana", "Martini" ].each { |name|
- print name, " is a ", food_color.has_key?(name) ? "food" : "drink", "\n"
-}
-
-age = {}
-age['Toddler'] = 3
-age['Unborn'] = 0
-age['Phantasm'] = nil
-
-for thing in ['Toddler', 'Unborn', 'Phantasm', 'Relic']
- print "#{thing}: "
- print "Has-key " if age.has_key?(thing)
- print "True " if age[thing]
- print "Nonzero " if age[thing] && age[thing].nonzero?
- print "\n"
-end
-
-#=>
-# Toddler: Has-key True Nonzero
-# Unborn: Has-key True
-# Phantasm: Has-key
-# Relic:
-
-# You use Hash#has_key? when you use Perl's exists -> it checks
-# for existence of a key in a hash.
-# All Numeric are "True" in ruby, so the test doesn't have the
-# same semantics as in Perl; you would use Numeric#nonzero? to
-# achieve the same semantics (false if 0, true otherwise).
-
-
-# @@PLEAC@@_5.3
-food_color.delete("Banana")
-
-
-# @@PLEAC@@_5.4
-hash.each { |key, value|
- # do something with key and value
-}
-
-hash.each_key { |key|
- # do something with key
-}
-
-food_color.each { |food, color|
- puts "#{food} is #{color}"
-}
-
-food_color.each_key { |food|
- puts "#{food} is #{food_color[food]}"
-}
-
-# IMO this demonstrates that OO style is by far more readable
-food_color.keys.sort.each { |food|
- puts "#{food} is #{food_color[food]}."
-}
-
-#-----------------------------
-#!/usr/bin/ruby
-# countfrom - count number of messages from each sender
-
-# Default value is 0
-from = Hash.new(0)
-while gets
- /^From: (.*)/ and from[$1] += 1
-end
-
-# More useful to sort by number of received mail by person
-from.sort {|a,b| b[1]<=>a[1]}.each { |v|
- puts "#{v[1]}: #{v[0]}"
-}
-#-----------------------------
-
-
-# @@PLEAC@@_5.5
-# You may use the built-in 'inspect' method this way:
-p hash
-
-# Or do it the Cookbook way:
-hash.each { |k,v| puts "#{k} => #{v}" }
-
-# Sorted by keys
-hash.sort.each { |e| puts "#{e[0]} => #{e[1]}" }
-# Sorted by values
-hash.sort{|a,b| a[1]<=>b[1]}.each { |e| puts "#{e[0]} => #{e[1]}" }
-
-
-# @@PLEAC@@_5.7
-ttys = Hash.new
-for i in `who`
- user, tty = i.split
- (ttys[user] ||= []) << tty # see problems_ruby for more infos
-end
-ttys.keys.sort.each { |k|
- puts "#{k}: #{commify_series(ttys[k])}" # from 4.2
-}
-
-
-# @@PLEAC@@_5.8
-surname = { "Mickey" => "Mantle", "Babe" => "Ruth" }
-puts surname.index("Mantle")
-
-# If you really needed to 'invert' the whole hash, use Hash#invert
-
-#-----------------------------
-#!/usr/bin/ruby -w
-# foodfind - find match for food or color
-
-given = ARGV.shift or raise "usage: foodfind food_or_color"
-
-color = {
- "Apple" => "red",
- "Banana" => "yellow",
- "Lemon" => "yellow",
- "Carrot" => "orange",
-}
-
-if (color.has_key?(given))
- puts "#{given} is a food with color #{color[given]}."
-end
-if (color.has_value?(given))
- puts "#{color.index(given)} is a food with color #{given}."
-end
-#-----------------------------
-
-
-# @@PLEAC@@_5.9
-# Sorted by keys (Hash#sort gives an Array of pairs made of each key,value)
-food_color.sort.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by values
-food_color.sort { |a,b| a[1] <=> b[1] }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-# Sorted by length of values
-food_color.sort { |a,b| a[1].length <=> b[1].length }.each { |f|
- puts "#{f[0]} is #{f[1]}."
-}
-
-
-# @@PLEAC@@_5.10
-merged = a.clone.update(b) # because Hash#update changes object in place
-
-drink_color = { "Galliano" => "yellow", "Mai Tai" => "blue" }
-ingested_color = drink_color.clone.update(food_color)
-
-substance_color = {}
-for i in [ food_color, drink_color ]
- i.each_key { |k|
- if substance_color.has_key?(k)
- puts "Warning: #{k} seen twice. Using the first definition."
- next
- end
- substance_color[k] = 1
- }
-end
-
-
-# @@PLEAC@@_5.11
-common = hash1.keys & hash2.keys
-
-this_not_that = hash1.keys - hash2.keys
-
-
-# @@PLEAC@@_5.12
-# no problem here, Ruby handles any kind of object for key-ing
-# (it takes Object#hash, which defaults to Object#id)
-
-
-# @@PLEAC@@_5.13
-# AFAIK, not possible in Ruby
-
-
-# @@PLEAC@@_5.14
-# Be careful, the following is possible only because Fixnum objects are
-# special (documentation says: there is effectively only one Fixnum object
-# instance for any given integer value).
-count = Hash.new(0)
-array.each { |e|
- count[e] += 1
-}
-
-
-# @@PLEAC@@_5.15
-father = {
- "Cain" , "Adam",
- "Abel" , "Adam",
- "Seth" , "Adam",
- "Enoch" , "Cain",
- "Irad" , "Enoch",
- "Mehujael" , "Irad",
- "Methusael" , "Mehujael",
- "Lamech" , "Methusael",
- "Jabal" , "Lamech",
- "Jubal" , "Lamech",
- "Tubalcain" , "Lamech",
- "Enos" , "Seth",
-}
-
-while gets
- chomp
- begin
- print $_, " "
- end while $_ = father[$_]
- puts
-end
-
-children = {}
-father.each { |k,v|
- (children[v] ||= []) << k
-}
-while gets
- chomp
- puts "#{$_} begat #{(children[$_] || ['Nobody']).join(', ')}.\n"
-end
-
-includes = {}
-files.each { |f|
- begin
- for l in IO.readlines(f)
- next unless l =~ /^\s*#\s*include\s*<([^>]+)>/
- (includes[$1] ||= []) << f
- end
- rescue SystemCallError
- $stderr.puts "#$! (skipping)"
- end
-}
-
-include_free = includes.values.flatten.uniq - includes.keys
-
-
-# @@PLEAC@@_5.16
-# dutree - print sorted intented rendition of du output
-#% dutree
-#% dutree /usr
-#% dutree -a
-#% dutree -a /bin
-
-# The DuNode class collects all information about a directory,
-# and provides some convenience methods
-class DuNode
-
- attr_reader :name
- attr_accessor :size
- attr_accessor :kids
-
- def initialize(name)
- @name = name
- @kids = []
- @size = 0
- end
-
- # support for sorting nodes with side
- def size_compare(node2)
- @size <=> node2.size
- end
-
- def basename
- @name.sub(/.*\//, "")
- end
-
- #returns substring before last "/", nil if not there
- def parent
- p = @name.sub(/\/[^\/]+$/,"")
- if p == @name
- nil
- else
- p
- end
- end
-
-end
-
-# The DuTree does the acdtual work of
-# getting the input, parsing it, builging up a tree
-# and format it for output
-class Dutree
-
- attr_reader :topdir
-
- def initialize
- @nodes = Hash.new
- @dirsizes = Hash.new(0)
- @kids = Hash.new([])
- end
-
- # get a node by name, create it if it does not exist yet
- def get_create_node(name)
- if @nodes.has_key?(name)
- @nodes[name]
- else
- node = DuNode.new(name)
- @nodes[name] = node
- node
- end
- end
-
- # run du, read in input, save sizes and kids
- # stores last directory read in instance variable topdir
- def input(arguments)
- name = ""
- cmd = "du " + arguments.join(" ")
- IO.popen(cmd) { |pipe|
- pipe.each { |line|
- size, name = line.chomp.split(/\s+/, 2)
- node = get_create_node(name)
- node.size = size.to_i
- @nodes[name] = node
- parent = node.parent
- if parent
- get_create_node(parent).kids.push(node)
- end
- }
- }
- @topdir = @nodes[name]
- end
-
- # figure out how much is taken in each directory
- # that isn't stored in the subdirectories. Add a new
- # fake kid called "." containing that much.
- def get_dots(node)
- cursize = node.size
- for kid in node.kids
- cursize -= kid.size
- get_dots(kid)
- end
- if node.size != cursize
- newnode = get_create_node(node.name + "/.")
- newnode.size = cursize
- node.kids.push(newnode)
- end
- end
-
- # recursively output everything
- # passing padding and number width as well
- # on recursive calls
- def output(node, prefix="", width=0)
- line = sprintf("%#{width}d %s", node.size, node.basename)
- puts(prefix + line)
- prefix += line.sub(/\d /, "| ")
- prefix.gsub!(/[^|]/, " ")
- if node.kids.length > 0 # not a bachelor node
- kids = node.kids
- kids.sort! { |a,b|
- b.size_compare(a)
- }
- width = kids[0].size.to_s.length
- for kid in kids
- output(kid, prefix, width)
- end
- end
- end
-
-end
-
-tree = Dutree.new
-tree.input(ARGV)
-tree.get_dots(tree.topdir)
-tree.output(tree.topdir)
-
-
-# @@PLEAC@@_6.0
-# The verbose version are match, sub, gsub, sub! and gsub!;
-# pattern needs to be a Regexp object; it yields a MatchData
-# object.
-pattern.match(string)
-string.sub(pattern, replacement)
-string.gsub(pattern, replacement)
-# As usual in Ruby, sub! does the same as sub but also modifies
-# the object, the same for gsub!/gsub.
-
-# Sugared syntax yields the position of the match (or nil if no
-# match). Note that the object at the right of the operator needs
-# not to be a Regexp object (it can be a String). The "dont
-# match" operator yields true or false.
-meadow =~ /sheep/ # position of the match, nil if no match
-meadow !~ /sheep/ # true if doesn't match, false if it does
-# There is no sugared version for the substitution
-
-meadow =~ /\bovines?\b/i and print "Here be sheep!"
-
-string = "good food"
-string.sub!(/o*/, 'e')
-
-# % echo ababacaca | ruby -ne 'puts $& if /(a|ba|b)+(a|ac)+/'
-# ababa
-
-# The "global" (or "multiple") match is handled by String#scan
-scan (/(\d+)/) {
- puts "Found number #{$1}"
-}
-
-# String#scan yields an Array if not used with a block
-numbers = scan(/\d+/)
-
-digits = "123456789"
-nonlap = digits.scan(/(\d\d\d)/)
-yeslap = digits.scan(/(?=(\d\d\d))/)
-puts "Non-overlapping: #{nonlap.join(' ')}"
-puts "Overlapping: #{yeslap.join(' ')}";
-# Non-overlapping: 123 456 789
-# Overlapping: 123 234 345 456 567 678 789
-
-string = "And little lambs eat ivy"
-string =~ /l[^s]*s/
-puts "(#$`) (#$&) (#$')"
-# (And ) (little lambs) ( eat ivy)
-
-
-# @@PLEAC@@_6.1
-# Ruby doesn't have the same problem:
-dst = src.sub('this', 'that')
-
-progname = $0.sub('^.*/', '')
-
-bindirs = %w(/usr/bin /bin /usr/local/bin)
-libdirs = bindirs.map { |l| l.sub('bin', 'lib') }
-
-
-# @@PLEAC@@_6.3
-/\S+/ # as many non-whitespace bytes as possible
-/[A-Za-z'-]+/ # as many letters, apostrophes, and hyphens
-
-/\b([A-Za-z]+)\b/ # usually best
-/\s([A-Za-z]+)\s/ # fails at ends or w/ punctuation
-
-
-# @@PLEAC@@_6.4
-require 'socket'
-str = 'www.ruby-lang.org and www.rubygarden.org'
-re = /
- ( # capture the hostname in $1
- (?: # these parens for grouping only
- (?! [-_] ) # lookahead for neither underscore nor dash
- [\w-] + # hostname component
- \. # and the domain dot
- ) + # now repeat that whole thing a bunch of times
- [A-Za-z] # next must be a letter
- [\w-] + # now trailing domain part
- ) # end of $1 capture
- /x # /x for nice formatting
-
-str.gsub! re do # pass a block to execute replacement
- host = TCPsocket.gethostbyname($1)
- "#{$1} [#{host[3]}]"
-end
-
-puts str
-#-----------------------------
-# to match whitespace or #-characters in an extended re you need to escape
-# them.
-
-foo = 42
-str = 'blah #foo# blah'
-str.gsub! %r/ # replace
- \# # a pound sign
- (\w+) # the variable name
- \# # another pound sign
- /x do
- eval $1 # with the value of a local variable
- end
-puts str # => blah 42 blah
-
-
-# @@PLEAC@@_6.5
-# The 'g' modifier doesn't exist in Ruby, a regexp can't be used
-# directly in a while loop; instead, use String#scan { |match| .. }
-fish = 'One fish two fish red fish blue fish'
-WANT = 3
-count = 0
-fish.scan(/(\w+)\s+fish\b/i) {
- if (count += 1) == WANT
- puts "The third fish is a #{$1} one."
- end
-}
-
-if fish =~ /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i
- puts "The third fish is a #{$1} one."
-end
-
-pond = 'One fish two fish red fish blue fish'
-# String#scan without a block gives an array of matches, each match
-# being an array of all the specified groups
-colors = pond.scan(/(\w+)\s+fish\b/i).flatten # get all matches
-color = colors[2] # then the one we want
-# or without a temporary array
-color = pond.scan(/(\w+)\s+fish\b/i).flatten[2] # just grab element 3
-puts "The third fish in the pond is #{color}."
-
-count = 0
-fishes = 'One fish two fish red fish blue fish'
-evens = fishes.scan(/(\w+)\s+fish\b/i).select { (count+=1) % 2 == 0 }
-print "Even numbered fish are #{evens.join(' ')}."
-
-count = 0
-fishes.gsub(/
- \b # makes next \w more efficient
- ( \w+ ) # this is what we\'ll be changing
- (
- \s+ fish \b
- )
- /x) {
- if (count += 1) == 4
- 'sushi' + $2
- else
- $1 + $2
- end
-}
-
-pond = 'One fish two fish red fish blue fish swim here.'
-puts "Last fish is #{pond.scan(/\b(\w+)\s+fish\b/i).flatten[-1]}"
-
-/
- A # find some pattern A
- (?! # mustn\'t be able to find
- .* # something
- A # and A
- )
- $ # through the end of the string
-/x
-
-# The "s" perl modifier is "m" in Ruby (not very nice since there is
-# also an "m" in perl..)
-pond = "One fish two fish red fish blue fish swim here."
-if (pond =~ /
- \b ( \w+) \s+ fish \b
- (?! .* \b fish \b )
- /mix)
- puts "Last fish is #{$1}."
-else
- puts "Failed!"
-end
-
-
-# @@PLEAC@@_6.6
-#-----------------------------
-#!/usr/bin/ruby -w
-# killtags - very bad html killer
-$/ = nil; # each read is whole file
-while file = gets() do
- file.gsub!(/<.*?>/m,''); # strip tags (terribly)
- puts file # print file to STDOUT
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-#headerfy - change certain chapter headers to html
-$/ = ''
-while file = gets() do
- pattern = /
- \A # start of record
- ( # capture in $1
- Chapter # text string
- \s+ # mandatory whitespace
- \d+ # decimal number
- \s* # optional whitespace
- : # a real colon
- . * # anything not a newline till end of line
- )
- /x
- puts file.gsub(pattern,'<H1>\1</H1>')
-end
-#-----------------------------
-#% ruby -00pe "gsub!(/\A(Chapter\s+\d+\s*:.*)/,'<H1>\1</H1>')" datafile
-
-#!/usr/bin/ruby -w
-#-----------------------------
-for file in ARGV
- file = File.open(ARGV.shift)
- while file.gets('') do # each read is a paragraph
- print "chunk #{$.} in $ARGV has <<#{$1}>>\n" while /^START(.*?)^END/m
- end # /m activates the multiline mode
-end
-#-----------------------------
-
-# @@PLEAC@@_6.7
-#-----------------------------
-$/ = nil;
-file = File.open("datafile")
-chunks = file.gets.split(/pattern/)
-#-----------------------------
-# .Ch, .Se and .Ss divide chunks of STDIN
-chunks = gets(nil).split(/^\.(Ch|Se|Ss)$/)
-print "I read #{chunks.size} chunks.\n"
-#-----------------------------
-
-
-# @@PLEAC@@_6.8
-while gets
- if ~/BEGIN/ .. ~/END/
- # line falls between BEGIN and END inclusive
- end
-end
-
-while gets
- if ($. == firstnum) .. ($. == lastnum)
- # operate between firstnum and lastnum line number
- end
-end
-
-# in ruby versions prior to 1.8, the above two conditional
-# expressions could be shortened to:
-# if /BEGIN/ .. /END/
-# and
-# if firstnum .. lastnum
-# but these now only work this way from the command line
-
-#-----------------------------
-
-while gets
- if ~/BEGIN/ ... ~/END/
- # line falls between BEGIN and END on different lines
- end
-end
-
-while gets
- if ($. == first) ... ($. == last)
- # operate between first and last line number on different lines
- end
-end
-
-#-----------------------------
-# command-line to print lines 15 through 17 inclusive (see below)
-ruby -ne 'print if 15 .. 17' datafile
-
-# print out all <XMP> .. </XMP> displays from HTML doc
-while gets
- print if ~%r#<XMP>#i .. ~%r#</XMP>#i;
-end
-
-# same, but as shell command
-# ruby -ne 'print if %r#<XMP>#i .. %r#</XMP>#i' document.html
-#-----------------------------
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $top .. $bottom' /etc/passwd # FAILS
-# ruby -ne 'BEGIN { $top=3; $bottom=5 }; \
-# print if $. == $top .. $. == $bottom' /etc/passwd # works
-# ruby -ne 'print if 3 .. 5' /etc/passwd # also works
-#-----------------------------
-print if ~/begin/ .. ~/end/;
-print if ~/begin/ ... ~/end/;
-#-----------------------------
-while gets
- $in_header = $. == 1 .. ~/^$/ ? true : false
- $in_body = ~/^$/ .. ARGF.eof ? true : false
-end
-#-----------------------------
-seen = {}
-ARGF.each do |line|
- next unless line =~ /^From:?\s/i .. line =~ /^$/;
- line.scan(%r/([^<>(),;\s]+\@[^<>(),;\s]+)/).each do |addr|
- puts addr unless seen[addr]
- seen[addr] ||= 1
- end
-end
-
-
-# @@PLEAC@@_6.9
-def glob2pat(globstr)
- patmap = {
- '*' => '.*',
- '?' => '.',
- '[' => '[',
- ']' => ']',
- }
- globstr.gsub!(/(.)/) { |c| patmap[c] || Regexp::escape(c) }
- '^' + globstr + '$'
-end
-
-
-# @@PLEAC@@_6.10
-# avoid interpolating patterns like this if the pattern
-# isn't going to change:
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/
-end
-
-# the above creates a new regex each iteration. Instead,
-# use the /o modifier so the regex is compiled only once
-
-pattern = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pattern}/o
-end
-
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep1 - grep for abbreviations of places that say "pop"
-# version 1: slow but obvious way
-popstates = %w(CO ON MI WI MN)
-ARGF.each do |line|
- popstates.each do |state|
- if line =~ /\b#{state}\b/
- print line
- last
- end
- end
-end
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep2 - grep for abbreviations of places that say "pop"
-# version 2: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n"
-popstates.each do |state|
- code += "\tif line =~ /\\b#{state}\\b/; print(line); next; end\n"
-end
-code += "end\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# if line =~ /\bCO\b/; print(line); next; end
-# if line =~ /\bON\b/; print(line); next; end
-# if line =~ /\bMI\b/; print(line); next; end
-# if line =~ /\bWI\b/; print(line); next; end
-# if line =~ /\bMN\b/; print(line); next; end
-# end
-#
-# ---
-
-## alternatively, the same idea as above but compiling
-## to a case statement: (not in perlcookbook)
-#!/usr/bin/ruby -w
-# popgrep2.5 - grep for abbreviations of places that say "pop"
-# version 2.5: eval strings; fast but hard to quote
-popstates = %w(CO ON MI WI MN)
-code = "ARGF.each do |line|\n case line\n"
-popstates.each do |state|
- code += " when /\\b#{state}\\b/ : print line\n"
-end
-code += " end\nend\n"
-print "CODE IS\n---\n#{code}\n---\n" if false # turn on for debugging
-eval code
-
-# CODE IS
-# ---
-# ARGF.each do |line|
-# case line
-# when /\bCO\b/ : print line
-# when /\bON\b/ : print line
-# when /\bMI\b/ : print line
-# when /\bWI\b/ : print line
-# when /\bMN\b/ : print line
-# end
-# end
-#
-# ---
-
-# Note: (above) Ruby 1.8+ allows the 'when EXP : EXPR' on one line
-# with the colon separator.
-
-#-----------------------------
-#!/usr/bin/ruby
-# popgrep3 - grep for abbreviations of places that say "pop"
-# version3: build a match_any function
-popstates = %w(CO ON MI WI MN)
-expr = popstates.map{|e|"line =~ /\\b#{e}\\b/"}.join('||')
-eval "def match_any(line); #{expr};end"
-ARGF.each do |line|
- print line if match_any(line)
-end
-#-----------------------------
-
-## building a match_all function is a trivial
-## substitution of && for ||
-## here is a generalized example:
-#!/usr/bin/ruby -w
-## grepauth - print lines that mention both foo and bar
-class MultiMatch
- def initialize(*patterns)
- _any = build_match('||',patterns)
- _all = build_match('&&',patterns)
- eval "def match_any(line);#{_any};end\n"
- eval "def match_all(line);#{_all};end\n"
- end
- def build_match(sym,args)
- args.map{|e|"line =~ /#{e}/"}.join(sym)
- end
-end
-
-mm = MultiMatch.new('foo','bar')
-ARGF.each do |line|
- print line if mm.match_all(line)
-end
-#-----------------------------
-
-#!/usr/bin/ruby
-# popgrep4 - grep for abbreviations of places that say "pop"
-# version4: pretty fast, but simple: compile all re's first:
-popstates = %w(CO ON MI WI MN)
-popstates = popstates.map{|re| %r/\b#{re}\b/}
-ARGF.each do |line|
- popstates.each do |state_re|
- if line =~ state_re
- print line
- break
- end
- end
-end
-
-## speeds trials on the jargon file(412): 26006 lines, 1.3MB
-## popgrep1 => 7.040s
-## popgrep2 => 0.656s
-## popgrep2.5 => 0.633s
-## popgrep3 => 0.675s
-## popgrep4 => 1.027s
-
-# unless speed is criticial, the technique in popgrep4 is a
-# reasonable balance between speed and logical simplicity.
-
-
-# @@PLEAC@@_6.11
-begin
- print "Pattern? "
- pat = $stdin.gets.chomp
- Regexp.new(pat)
-rescue
- warn "Invalid Pattern"
- retry
-end
-
-
-# @@PLEAC@@_6.13
-# uses the 'amatch' extension found on:
-# http://raa.ruby-lang.org/project/amatch/
-require 'amatch'
-matcher = Amatch.new('balast')
-#$relative, $distance = 0, 1
-File.open('/usr/share/dict/words').each_line do |line|
- print line if matcher.search(line) <= 1
-end
-__END__
-#CODE
-ballast
-ballasts
-balustrade
-balustrades
-blast
-blasted
-blaster
-blasters
-blasting
-blasts
-
-
-# @@PLEAC@@_6.14
-str.scan(/\G(\d)/).each do |token|
- puts "found #{token}"
-end
-#-----------------------------
-n = " 49 here"
-n.gsub!(/\G /,'0')
-puts n
-#-----------------------------
-str = "3,4,5,9,120"
-str.scan(/\G,?(\d+)/).each do |num|
- puts "Found number: #{num}"
-end
-#-----------------------------
-# Ruby doesn't have the String.pos or a /c re modifier like Perl
-# But it does have StringScanner in the standard library (strscn)
-# which allows similar functionality:
-
-require 'strscan'
-text = 'the year 1752 lost 10 days on the 3rd of September'
-sc = StringScanner.new(text)
-while sc.scan(/.*?(\d+)/)
- print "found: #{sc[1]}\n"
-end
-if sc.scan(/\S+/)
- puts "Found #{sc[0]} after last number"
-end
-#-----------------------------
-# assuming continuing from above:
-puts "The position in 'text' is: #{sc.pos}"
-sc.pos = 30
-puts "The position in 'text' is: #{sc.pos}"
-
-
-# @@PLEAC@@_6.15
-#-----------------------------
-# greedy pattern
-str.gsub!(/<.*>/m,'') # not good
-
-# non-greedy (minimal) pattern
-str.gsub!(/<.*?>/m,'') # not great
-
-
-#-----------------------------
-#<b><i>this</i> and <i>that</i> are important</b> Oh, <b><i>me too!</i></b>
-#-----------------------------
-%r{ <b><i>(.*?)</i></b> }mx
-#-----------------------------
-%r/BEGIN((?:(?!BEGIN).)*)END/
-#-----------------------------
-%r{ <b><i>( (?: (?!</b>|</i>). )* ) </i></b> }mx
-#-----------------------------
-%r{ <b><i>( (?: (?!</[ib]>). )* ) </i></b> }mx
-#-----------------------------
-%r{
- <b><i>
- [^<]* # stuff not possibly bad, and not possibly the end.
- (?:
- # at this point, we can have '<' if not part of something bad
- (?! </?[ib]> ) # what we can't have
- < # okay, so match the '<'
- [^<]* # and continue with more safe stuff
- ) *
- </i></b>
- }mx
-
-
-# @@PLEAC@@_6.16
-#-----------------------------
-$/ = ""
-ARGF.each do |para|
- para.scan %r/
- \b # start at word boundary
- (\S+) # find chunk of non-whitespace
- \b # until a word boundary
- (
- \s+ # followed by whitespace
- \1 # and that same chunk again
- \b # and a word boundary
- ) + # one or more times
- /xi do
- puts "dup word '#{$1}' at paragraph #{$.}"
- end
-end
-#-----------------------------
-astr = 'nobody'
-bstr = 'bodysnatcher'
-if "#{astr} #{bstr}" =~ /^(\w+)(\w+) \2(\w+)$/
- print "#{$2} overlaps in #{$1}-#{$2}-#{$3}"
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# prime_pattern -- find prime factors of argument using patterns
-ARGV << 180
-cap = 'o' * ARGV.shift
-while cap =~ /^(oo+?)\1+$/
- print $1.size, " "
- cap.gsub!(/#{$1}/,'o')
-end
-puts cap.size
-#-----------------------------
-#diophantine
-# solve for 12x + 15y + 16z = 281, maximizing x
-if ('o' * 281).match(/^(o*)\1{11}(o*)\2{14}(o*)\3{15}$/)
- x, y, z = $1.size, $2.size, $3.size
- puts "One solution is: x=#{x}; y=#{y}; z=#{z}"
-else
- puts "No solution."
-end
-# => One solution is: x=17; y=3; z=2
-
-#-----------------------------
-# using different quantifiers:
-('o' * 281).match(/^(o+)\1{11}(o+)\2{14}(o+)\3{15}$/)
-# => One solution is: x=17; y=3; z=2
-
-('o' * 281).match(/^(o*?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=0; y=7; z=11
-
-('o' * 281).match(/^(o+?)\1{11}(o*)\2{14}(o*)\3{15}$/)
-# => One solution is: x=1; y=3; z=14
-
-
-# @@PLEAC@@_6.17
-# alpha OR beta
-%r/alpha|beta/
-
-# alpha AND beta
-%r/(?=.*alpha)(?=.*beta)/m
-
-# alpha AND beta, no overlap
-%r/alpha.*beta|beta.*alpha/m
-
-# NOT beta
-%r/^(?:(?!beta).)*$/m
-
-# NOT bad BUT good
-%r/(?=(?:(?!BAD).)*$)GOOD/m
-#-----------------------------
-
-if !(string =~ /pattern/) # ugly
- something()
-end
-
-if string !~ /pattern/ # preferred
- something()
-end
-
-
-#-----------------------------
-if string =~ /pat1/ && string =~ /pat2/
- something()
-end
-#-----------------------------
-if string =~ /pat1/ || string =~ /pat2/
- something()
-end
-#-----------------------------
-#!/usr/bin/ruby -w
-# minigrep - trivial grep
-pat = ARGV.shift
-ARGF.each do |line|
- print line if line =~ /#{pat}/o
-end
-#-----------------------------
- "labelled" =~ /^(?=.*bell)(?=.*lab)/m
-#-----------------------------
-$string =~ /bell/ && $string =~ /lab/
-#-----------------------------
-$murray_hill = "blah bell blah "
-if $murray_hill =~ %r{
- ^ # start of string
- (?= # zero-width lookahead
- .* # any amount of intervening stuff
- bell # the desired bell string
- ) # rewind, since we were only looking
- (?= # and do the same thing
- .* # any amount of intervening stuff
- lab # and the lab part
- )
- }mx # /m means . can match newline
-
- print "Looks like Bell Labs might be in Murray Hill!\n";
-end
-#-----------------------------
-"labelled" =~ /(?:^.*bell.*lab)|(?:^.*lab.*bell)/
-#-----------------------------
-$brand = "labelled";
-if $brand =~ %r{
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- bell # look for a bell
- .*? # followed by any amount of anything
- lab # look for a lab
- ) # end grouper
- | # otherwise, try the other direction
- (?: # non-capturing grouper
- ^ .*? # any amount of stuff at the front
- lab # look for a lab
- .*? # followed by any amount of anything
- bell # followed by a bell
- ) # end grouper
- }mx # /m means . can match newline
- print "Our brand has bell and lab separate.\n";
-end
-#-----------------------------
-$map =~ /^(?:(?!waldo).)*$/s
-#-----------------------------
-$map = "the great baldo"
-if $map =~ %r{
- ^ # start of string
- (?: # non-capturing grouper
- (?! # look ahead negation
- waldo # is he ahead of us now?
- ) # is so, the negation failed
- . # any character (cuzza /s)
- ) * # repeat that grouping 0 or more
- $ # through the end of the string
- }mx # /m means . can match newline
- print "There's no waldo here!\n";
-end
-=begin
- 7:15am up 206 days, 13:30, 4 users, load average: 1.04, 1.07, 1.04
-
-USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
-
-tchrist tty1 5:16pm 36days 24:43 0.03s xinit
-
-tchrist tty2 5:19pm 6days 0.43s 0.43s -tcsh
-
-tchrist ttyp0 chthon 7:58am 3days 23.44s 0.44s -tcsh
-
-gnat ttyS4 coprolith 2:01pm 13:36m 0.30s 0.30s -tcsh
-=end
-#% w | minigrep '^(?!.*ttyp).*tchrist'
-#-----------------------------
-%r{
- ^ # anchored to the start
- (?! # zero-width look-ahead assertion
- .* # any amount of anything (faster than .*?)
- ttyp # the string you don't want to find
- ) # end look-ahead negation; rewind to start
- .* # any amount of anything (faster than .*?)
- tchrist # now try to find Tom
-}x
-#-----------------------------
-#% w | grep tchrist | grep -v ttyp
-#-----------------------------
-#% grep -i 'pattern' files
-#% minigrep '(?i)pattern' files
-#-----------------------------
-
-
-# @@PLEAC@@_6.20
-ans = $stdin.gets.chomp
-re = %r/^#{Regexp.quote(ans)}/
-case
- when "SEND" =~ re : puts "Action is send"
- when "STOP" =~ re : puts "Action is stop"
- when "ABORT" =~ re : puts "Action is abort"
- when "EDIT" =~ re : puts "Action is edit"
-end
-#-----------------------------
-require 'abbrev'
-table = Abbrev.abbrev %w-send stop abort edit-
-loop do
- print "Action: "
- ans = $stdin.gets.chomp
- puts "Action for #{ans} is #{table[ans.downcase]}"
-end
-
-
-#-----------------------------
-# dummy values are defined for 'file', 'PAGER', and
-# the 'invoke_editor' and 'deliver_message' methods
-# do not do anything interesting in this example.
-#!/usr/bin/ruby -w
-require 'abbrev'
-
-file = 'pleac_ruby.data'
-PAGER = 'less'
-
-def invoke_editor
- puts "invoking editor"
-end
-
-def deliver_message
- puts "delivering message"
-end
-
-actions = {
- 'edit' => self.method(:invoke_editor),
- 'send' => self.method(:deliver_message),
- 'list' => proc {system(PAGER, file)},
- 'abort' => proc {puts "See ya!"; exit},
- "" => proc {puts "Unknown Command"}
-}
-
-dtable = Abbrev.abbrev(actions.keys)
-loop do
- print "Action: "
- ans = $stdin.gets.chomp.delete(" \t")
- actions[ dtable[ans.downcase] || "" ].call
-end
-
-
-# @@PLEAC@@_6.19
-#-----------------------------
-# basically, the Perl Cookbook categorizes this as an
-# unsolvable problem ...
-#-----------------------------
-1 while addr.gsub!(/\([^()]*\)/,'')
-#-----------------------------
-Dear someuser@host.com,
-
-Please confirm the mail address you gave us Wed May 6 09:38:41
-MDT 1998 by replying to this message. Include the string
-"Rumpelstiltskin" in that reply, but spelled in reverse; that is,
-start with "Nik...". Once this is done, your confirmed address will
-be entered into our records.
-
-
-# @@PLEAC@@_6.21
-#-----------------------------
-#% gunzip -c ~/mail/archive.gz | urlify > archive.urlified
-#-----------------------------
-#% urlify ~/mail/*.inbox > ~/allmail.urlified
-#-----------------------------
-#!/usr/bin/ruby -w
-# urlify - wrap HTML links around URL-like constructs
-
-urls = '(https?|telnet|gopher|file|wais|ftp)';
-ltrs = '\w';
-gunk = '/#~:.?+=&%@!\-';
-punc = '.:?\-';
-any = "#{ltrs}#{gunk}#{punc}";
-
-ARGF.each do |line|
- line.gsub! %r/
- \b # start at word boundary
- ( # begin $1 {
- #{urls} : # need resource and a colon
- [#{any}] +? # followed by on or more
- # of any valid character, but
- # be conservative and take only
- # what you need to....
- ) # end $1 }
- (?= # look-ahead non-consumptive assertion
- [#{punc}]* # either 0 or more punctuation
- [^#{any}] # followed by a non-url char
- | # or else
- $ # then end of the string
- )
- /iox do
- %Q|<A HREF="#{$1}">#{$1}</A>|
- end
- print line
-end
-
-
-# @@PLEAC@@_6.23
-%r/^m*(d?c{0,3}|c[dm])(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$/i
-#-----------------------------
-str.sub!(/(\S+)(\s+)(\S+)/, '\3\2\1')
-#-----------------------------
-%r/(\w+)\s*=\s*(.*)\s*$/ # keyword is $1, value is $2
-#-----------------------------
-%r/.{80,}/
-#-----------------------------
-%r|(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)|
-#-----------------------------
-str.gsub!(%r|/usr/bin|,'/usr/local/bin')
-#-----------------------------
-str.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/){ $1.hex.chr }
-#-----------------------------
-str.gsub!(%r{
- /\* # Match the opening delimiter
- .*? # Match a minimal number of characters
- \*/ # Match the closing delimiter
-}xm,'')
-#-----------------------------
-str.sub!(/^\s+/, '')
-str.sub!(/\s+$/, '')
-
-# but really, in Ruby we'd just do:
-str.strip!
-#-----------------------------
-str.gsub!(/\\n/,"\n")
-#-----------------------------
-str.sub!(/^.*::/, '')
-#-----------------------------
-%r/^([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])\.
- ([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])$/x
-#-----------------------------
-str.sub!(%r|^.*/|, '')
-#-----------------------------
-cols = ( (ENV['TERMCAP'] || " ") =~ /:co#(\d+):/ ) ? $1 : 80;
-#-----------------------------
-name = " #{$0} #{ARGV}".gsub(%r| /\S+/|, ' ')
-#-----------------------------
-require 'rbconfig'
-include Config
-raise "This isn't Linux" unless CONFIG['target_os'] =~ /linux/i;
-#-----------------------------
-str.gsub!(%r/\n\s+/, ' ')
-#-----------------------------
-nums = str.scan(/(\d+\.?\d*|\.\d+)/)
-#-----------------------------
-capwords = str.scan(%r/(\b[^\Wa-z0-9_]+\b)/)
-#-----------------------------
-lowords = str.scan(%r/(\b[^\WA-Z0-9_]+\b)/)
-#-----------------------------
-icwords = str.scan(%r/(\b[^\Wa-z0-9_][^\WA-Z0-9_]*\b)/)
-#-----------------------------
-links = str.scan(%r/<A[^>]+?HREF\s*=\s*["']?([^'" >]+?)[ '"]?>/mi)
-#-----------------------------
-initial = str =~ /^\S+\s+(\S)\S*\s+\S/ ? $1 : ""
-#-----------------------------
-str.gsub!(%r/"([^"]*)"/, %q-``\1''-)
-#-----------------------------
-
-$/ = ""
-sentences = []
-ARGF.each do |para|
- para.gsub!(/\n/, ' ')
- para.gsub!(/ {3,}/,' ')
- sentences << para.scan(/(\S.*?[!?.])(?= |\Z)/)
-end
-
-#-----------------------------
-%r/(\d{4})-(\d\d)-(\d\d)/ # YYYY in $1, MM in $2, DD in $3
-#-----------------------------
-%r/ ^
- (?:
- 1 \s (?: \d\d\d \s)? # 1, or 1 and area code
- | # ... or ...
- \(\d\d\d\) \s # area code with parens
- | # ... or ...
- (?: \+\d\d?\d? \s)? # optional +country code
- \d\d\d ([\s\-]) # and area code
- )
- \d\d\d (\s|\1) # prefix (and area code separator)
- \d\d\d\d # exchange
- $
- /x
-#-----------------------------
-%r/\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b/i
-#-----------------------------
-lines = []
-lines << $1 while input.sub!(/^([^\012\015]*)(\012\015?|\015\012?)/,'')
-
-
-# @@PLEAC@@_7.0
-# An IO object being Enumerable, we can use 'each' directly on it
-File.open("/usr/local/widgets/data").each { |line|
- puts line if line =~ /blue/
-}
-
-logfile = File.new("/var/log/rubylog.txt", "w")
-mysub($stdin, logfile)
-
-# The method IO#readline is similar to IO#gets
-# but throws an exception when it reaches EOF
-f = File.new("bla.txt")
-begin
- while (line = f.readline)
- line.chomp
- $stdout.print line if line =~ /blue/
- end
-rescue EOFError
- f.close
-end
-
-while $stdin.gets # reads from STDIN
- unless (/\d/)
- $stderr.puts "No digit found." # writes to STDERR
- end
- puts "Read: #{$_}" # writes to STDOUT
-end
-
-logfile = File.new("/tmp/log", "w")
-
-logfile.close
-
-# $defout (or its synonym '$>') is the destination of output
-# for Kernel#print, Kernel#puts, and family functions
-logfile = File.new("log.txt", "w")
-old = $defout
-$defout = logfile # switch to logfile for output
-puts "Countdown initiated ..."
-$defout = old # return to original output
-puts "You have 30 seconds to reach minimum safety distance."
-
-
-# @@PLEAC@@_7.1
-source = File.new(path, "r") # open file "path" for reading only
-sink = File.new(path, "w") # open file "path" for writing only
-
-source = File.open(path, File::RDONLY) # open file "path" for reading only
-sink = File.open(path, File::WRONLY) # open file "path" for writing only
-
-file = File.open(path, "r+") # open "path" for reading and writing
-file = File.open(path, flags) # open "path" with the flags "flags" (see examples below for flags)
-
-# open file "path" read only
-file = File.open(path, "r")
-file = File.open(path, File::RDONLY)
-
-# open file "path" write only, create it if it does not exist
-# truncate it to zero length if it exists
-file = File.open(path, "w")
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
-file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT, 0666) # with permission 0666
-
-# open file "path" write only, fails if file exists
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT)
-file = File.open(path, File::WRONLY|File::EXCL|File::CREAT, 0666)
-
-# open file "path" for appending
-file = File.open(path, "a")
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT)
-file = File.open(path, File::WRONLY|File::APPEND|File::CREAT, 0666)
-
-# open file "path" for appending only when file exists
-file = File.open(path, File::WRONLY|File::APPEND)
-
-# open file "path" for reading and writing
-file = File.open(path, "r+")
-file = File.open(path, File::RDWR)
-
-# open file for reading and writing, create a new file if it does not exist
-file = File.open(path, File::RDWR|File::CREAT)
-file = File.open(path, File::RDWR|File::CREAT, 0600)
-
-# open file "path" reading and writing, fails if file exists
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT)
-file = File.open(path, File::RDWR|File::EXCL|File::CREAT, 0600)
-
-
-# @@PLEAC@@_7.2
-# No problem with Ruby since the filename doesn't contain characters with
-# special meaning; like Perl's sysopen
-File.open(filename, 'r')
-
-
-# @@PLEAC@@_7.3
-File.expand_path('~root/tmp')
-#=> "/root/tmp"
-File.expand_path('~rpcuser')
-#=> "/var/lib/nfs"
-
-# To expand ~/.. it explicitely needs the environment variable HOME
-File.expand_path('~/tmp')
-#=> "/home/gc/tmp"
-
-
-# @@PLEAC@@_7.4
-# The exception raised in Ruby reports the filename
-File.open('afile')
-
-
-# @@PLEAC@@_7.5
-# Standard Ruby distribution provides the following useful extension
-require 'tempfile'
-# With the Tempfile class, the file is automatically deleted on garbage
-# collection, so you won't need to remove it, later on.
-tf = Tempfile.new('tmp') # a name is required to create the filename
-
-# If you need to pass the filename to an external program you can use
-# File#path, but don't forget to File#flush in order to flush anything
-# living in some buffer somewhere.
-tf.flush
-system("/usr/bin/dowhatever #{tf.path}")
-
-fh = Tempfile.new('tmp')
-fh.sync = true # autoflushes
-10.times { |i| fh.puts i }
-fh.rewind
-puts 'Tmp file has: ', fh.readlines
-
-
-# @@PLEAC@@_7.6
-while (DATA.gets) do
- # process the line
-end
-__END__
-# your data goes here
-# __DATA__ doesn't exist in Ruby
-
-#CODE
-# get info about the script (size, date of last modification)
-kilosize = DATA.stat.size / 1024
-last_modif = DATA.stat.mtime
-puts "<P>Script size is #{kilosize}"
-puts "<P>Last script update: #{last_modif}"
-__END__
-# DO NOT REMOVE THE PRECEEDING LINE.
-# Everything else in this file will be ignored.
-#CODE
-
-
-# @@PLEAC@@_7.7
-while line = gets do
- # do something with line.
-end
-
-# or
-while gets do
- # do something with $_
-end
-
-# or more rubyish
-$stdin.each do |line|
- # do stuff with line
-end
-
-
-# ARGF may makes this more easy
-# this is skipped if ARGV.size==0
-ARGV.each do |filename|
- # closing and exception handling are done by the block
- open(filename) do |fd|
- fd.each do |line|
- # do stuff with line
- end
- end rescue abort("can't open %s" % filename)
-end
-
-# globbing is done in the Dir module
-ARGV = Dir["*.[Cch]"] if ARGV.empty?
-
-# note: optparse is the preferred way to handle this
-if (ARGV[0] == '-c')
- chop_first += 1
- ARGV.shift
-end
-
-
-# processing numerical options
-if ARGV[0] =~ /^-(\d+)$/
- columns = $1
- ARGV.shift
-end
-
-# again, better to use optparse:
-require 'optparse'
-nostdout = 0
-append = 0
-unbuffer = 0
-ignore_ints = 0
-ARGV.options do |opt|
- opt.on('-n') { nostdout +=1 }
- opt.on('-a') { append +=1 }
- opt.on('-u') { unbuffer +=1 }
- opt.on('-i') { ignore_ints +=1 }
- opt.parse!
-end or abort("usage: " + __FILE__ + " [-ainu] [filenames]")
-
-# no need to do undef $/, we have File.read
-str = File.read(ARGV[0])
-
-# again we have File.read
-str = File.read(ARGV[0])
-
-# not sure what this should do:
-# I believe open the file, print filename, lineno and line:
-ARGF.each_with_index do |line, idx|
- print ARGF.filename, ":", idx, ";", line
-end
-
-# print all the lines in every file passed via command line that contains login
-ARGF.each do |line|
- puts line if line =~ /login/
-end
-#
-# even this would fit
-#%ruby -ne "print if /f/" 2.log
-#
-
-ARGF.each { |l| puts l.downcase! }
-
diff --git a/tests/examplefiles/test.html b/tests/examplefiles/test.html
index 72cba437..ea723232 100644
--- a/tests/examplefiles/test.html
+++ b/tests/examplefiles/test.html
@@ -1119,1671 +1119,3 @@ pre.syntax { padding: 5px; margin-top: 0px; }
<span class="kw">else</span>:
<span class="kw">raise</span> <span class="name">PocooRuntimeError</span>(<span class="st st-sg">&#39;</span><span class="st">req.cache_control invalid</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">resp</span>
-
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.captcha
- ~~~~~~~~~~~~~~~~~~~~~~
-
- Captcha URL Handler.
-
- Displays a random captcha picture (debugging only).
-
- :copyright: 2006-2007 by Armin Ronacher.
- :license: GNU GPL, see LICENSE for more details.
-</span><span class="st st-db">&quot;&quot;&quot;</span>
-<span class="kw">from </span><span class="cls">pocoo.application</span><span class="kw"> import</span> <span class="name">RequestHandler</span>
-<span class="kw">from </span><span class="cls">pocoo.http</span><span class="kw"> import</span> <span class="name">Response</span>
-
-
-<span class="kw">class </span><span class="cls">CaptchaImage</span>(<span class="name">RequestHandler</span>):
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">&#39;</span><span class="st">!captcha$</span><span class="st st-sg">&#39;</span>]
-
- <span class="kw">def </span><span class="fun">handle_request</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="kw">from </span><span class="cls">pocoo.utils.captcha</span><span class="kw"> import</span> <span class="name">Captcha</span>
-
- <span class="name">c</span> <span class="op">=</span> <span class="name">Captcha</span>()
- <span class="name">response</span> <span class="op">=</span> <span class="name">Response</span>(<span class="name">c</span>.<span class="name">generate_image</span>())
- <span class="name">response</span>[<span class="st st-sg">&#39;</span><span class="st">Content-Type</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">image/png</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">return</span> <span class="name">response</span>
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.cobalt
- ~~~~~~~~~~~~~~~~~~~~~
-
- Provides static content serving like mozilla&#39;s chrome:// scheme.
-
- :copyright: 2006-2007 by Armin Ronacher, Georg Brandl.
- :license: GNU GPL, see LICENSE for more details.
-</span><span class="st st-db">&quot;&quot;&quot;</span>
-<span class="kw">import </span><span class="cls">os</span>
-<span class="kw">import </span><span class="cls">time</span>
-
-<span class="kw">from </span><span class="cls">mimetypes</span><span class="kw"> import</span> <span class="name">guess_type</span>
-<span class="kw">from </span><span class="cls">pocoo.template</span><span class="kw"> import</span> <span class="name">FileRequirements</span>
-
-
-<span class="kw">class </span><span class="cls">CobaltMiddleware</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- The Cobalt middleware serves static files.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">__init__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">app</span>, <span class="name">ctx</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">app</span> <span class="op">=</span> <span class="name">app</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span> <span class="op">=</span> <span class="name">ctx</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">cache_enabled</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">cfg</span>.<span class="name">get_bool</span>(<span class="st st-sg">&#39;</span><span class="st">cache</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">static_cache</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_stylesheet_imports</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">cache_enabled</span> <span class="op op-word">or</span> <span class="st st-sg">&#39;</span><span class="st">cobalt/stylesheet_imports</span><span class="st st-sg">&#39;</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">_cache</span>:
- <span class="name">handled</span> <span class="op">=</span> <span class="name">set</span>()
- <span class="name">lines</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">FileRequirements</span>):
- <span class="kw">for</span> <span class="name">name</span> <span class="op op-word">in</span> <span class="name">comp</span>.<span class="name">get_stylesheet_imports</span>():
- <span class="name">item</span> <span class="op">=</span> (<span class="name">comp</span>.<span class="name">package</span>, <span class="name">name</span>)
- <span class="kw">if</span> <span class="name">item</span> <span class="op op-word">in</span> <span class="name">handled</span>:
- <span class="kw">continue</span>
-
- <span class="name">handled</span>.<span class="name">add</span>(<span class="name">item</span>)
- <span class="name">url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">!cobalt/</span><span class="st st-int">%s</span><span class="st">/</span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">item</span>
-
- <span class="name">lines</span>.<span class="name">append</span>(<span class="st st-sg">&#39;</span><span class="st">@import url(</span><span class="st st-int">%s</span><span class="st">);</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn">str</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="name">url</span>)))
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">_cache</span>[<span class="st st-sg">&#39;</span><span class="st">cobalt/stylesheet_imports</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st st-esc">\n</span><span class="st st-sg">&#39;</span>.<span class="name">join</span>(<span class="name">lines</span>)
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">_cache</span>[<span class="st st-sg">&#39;</span><span class="st">cobalt/stylesheet_imports</span><span class="st st-sg">&#39;</span>]
-
- <span class="kw">def </span><span class="fun">get_javascript_imports</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">cache_enabled</span> <span class="op op-word">or</span> <span class="st st-sg">&#39;</span><span class="st">cobalt/javascript_imports</span><span class="st st-sg">&#39;</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">_cache</span>:
- <span class="name">handled</span> <span class="op">=</span> <span class="name">set</span>()
- <span class="name">lines</span> <span class="op">=</span> []
- <span class="name">onload</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">FileRequirements</span>):
- <span class="kw">for</span> <span class="name">name</span> <span class="op op-word">in</span> <span class="name">comp</span>.<span class="name">get_javascript_imports</span>():
- <span class="name">item</span> <span class="op">=</span> (<span class="name">comp</span>.<span class="name">package</span>, <span class="name">name</span>)
- <span class="kw">if</span> <span class="name">item</span> <span class="op op-word">in</span> <span class="name">handled</span>:
- <span class="kw">continue</span>
-
- <span class="name">handled</span>.<span class="name">add</span>(<span class="name">item</span>)
- <span class="name">imp</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">pkgmanager</span>.<span class="name">importers</span>[<span class="name">comp</span>.<span class="name">package</span>]
- <span class="name">lines</span>.<span class="name">append</span>(<span class="name">imp</span>.<span class="name">get_data</span>(<span class="name">os</span>.<span class="name">path</span>.<span class="name">join</span>(<span class="st st-sg">&#39;</span><span class="st">static</span><span class="st st-sg">&#39;</span>, <span class="name">name</span>)))
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">_cache</span>[<span class="st st-sg">&#39;</span><span class="st">cobalt/javascript_imports</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st st-esc">\n\n</span><span class="st st-sg">&#39;</span>.<span class="name">join</span>(<span class="name">lines</span>)
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">_cache</span>[<span class="st st-sg">&#39;</span><span class="st">cobalt/javascript_imports</span><span class="st st-sg">&#39;</span>]
-
- <span class="kw">def </span><span class="fun">__call__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">environ</span>, <span class="name">start_response</span>):
- <span class="name">path</span> <span class="op">=</span> <span class="name">environ</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">PATH_INFO</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">/</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">path</span>.<span class="name">startswith</span>(<span class="st st-sg">&#39;</span><span class="st">/!cobalt/</span><span class="st st-sg">&#39;</span>):
- <span class="name">mime_type</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">try</span>:
- <span class="name">pkgname</span>, <span class="name">fname</span> <span class="op">=</span> <span class="name">path</span>[<span class="nb nb-int">9</span>:].<span class="name">split</span>(<span class="st st-sg">&#39;</span><span class="st">/</span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">1</span>)
- <span class="kw">if</span> <span class="name">pkgname</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">_import_</span><span class="st st-sg">&#39;</span>:
- <span class="kw">if</span> <span class="name">fname</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">styles.css</span><span class="st st-sg">&#39;</span>:
- <span class="name">mime_type</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">text/css</span><span class="st st-sg">&#39;</span>
-
- <span class="name">content</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">get_stylesheet_imports</span>()
- <span class="kw">elif</span> <span class="name">fname</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">script.js</span><span class="st st-sg">&#39;</span>:
- <span class="name">mime_type</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">application/x-javascript</span><span class="st st-sg">&#39;</span>
-
- <span class="name">content</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">get_javascript_imports</span>()
- <span class="kw">else</span>:
- <span class="name">guessed_type</span> <span class="op">=</span> <span class="name">guess_type</span>(<span class="name">fname</span>)
- <span class="name">mime_type</span> <span class="op">=</span> <span class="name">guessed_type</span>[<span class="nb nb-int">0</span>] <span class="op op-word">or</span> <span class="st st-sg">&#39;</span><span class="st">text/plain</span><span class="st st-sg">&#39;</span>
-
- <span class="name">imp</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">pkgmanager</span>.<span class="name">importers</span>[<span class="name">pkgname</span>]
- <span class="name">content</span> <span class="op">=</span> <span class="name">imp</span>.<span class="name">get_data</span>(<span class="name">os</span>.<span class="name">path</span>.<span class="name">join</span>(<span class="st st-sg">&#39;</span><span class="st">static</span><span class="st st-sg">&#39;</span>, <span class="name">fname</span>))
- <span class="kw">if</span> <span class="name">mime_type</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">expiry</span> <span class="op">=</span> <span class="name">time</span>.<span class="name">time</span>() <span class="op">+</span> <span class="nb nb-int">3600</span> <span class="cm"># cache for one hour</span>
-
- <span class="name">expiry</span> <span class="op">=</span> <span class="name">time</span>.<span class="name">asctime</span>(<span class="name">time</span>.<span class="name">gmtime</span>(<span class="name">expiry</span>))
- <span class="name">headers</span> <span class="op">=</span> [(<span class="st st-sg">&#39;</span><span class="st">Content-Type</span><span class="st st-sg">&#39;</span>, <span class="name">mime_type</span>),
- (<span class="st st-sg">&#39;</span><span class="st">Cache-Control</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">public</span><span class="st st-sg">&#39;</span>),
- (<span class="st st-sg">&#39;</span><span class="st">Expires</span><span class="st st-sg">&#39;</span>, <span class="name">expiry</span>)]
- <span class="name">start_response</span>(<span class="st st-sg">&#39;</span><span class="st">200 OK</span><span class="st st-sg">&#39;</span>, <span class="name">headers</span>)
- <span class="kw">if</span> <span class="name">environ</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">REQUEST_METHOD</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">GET</span><span class="st st-sg">&#39;</span>) <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">HEAD</span><span class="st st-sg">&#39;</span>:
- <span class="kw">return</span> []
- <span class="kw">else</span>:
- <span class="kw">return</span> [<span class="name">content</span>]
- <span class="kw">except</span> (<span class="exc">ValueError</span>, <span class="exc">KeyError</span>, <span class="exc">IOError</span>):
- <span class="cm"># XXX: output custom error message?</span>
-
- <span class="kw">pass</span>
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">app</span>(<span class="name">environ</span>, <span class="name">start_response</span>)
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- pocoo.pkg.core.db
- ~~~~~~~~~~~~~~~~~
-
- Pocoo core database definition.
-
- :copyright: 2006-2007 by Armin Ronacher, Georg Brandl.
- :license: GNU GPL, see LICENSE for more details.
-</span><span class="st st-db">&quot;&quot;&quot;</span>
-<span class="kw">from </span><span class="cls">pocoo.db</span><span class="kw"> import</span> <span class="name">meta</span>, <span class="name">DatabaseObserver</span>
-
-
-<span class="name">ANONYMOUS_USER_ID</span> <span class="op">=</span> <span class="op">-</span><span class="nb nb-int">1</span>
-
-<span class="name">DEFAULT_USER_ID</span> <span class="op">=</span> <span class="nb nb-int">0</span>
-
-
-<span class="name">sessions</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_sessions</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">session_key</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">40</span>), <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">ip_addr</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">15</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">expires</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">DateTime</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">last_reload</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">DateTime</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">data</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Pickled</span>(<span class="bn">dict</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">action</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>),
-)
-
-
-<span class="name">users</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_users</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">subject_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_subjects.subject_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">40</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">250</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">pwhash</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">60</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">act_key</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">8</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">language</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">2</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Pickled</span>(<span class="bn">dict</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">settings</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Pickled</span>(<span class="bn">dict</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">last_login</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">DateTime</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">DateTime</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">read_threads</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Binary</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">read_posts</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Binary</span>),
-)
-
-
-<span class="name">groups</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_groups</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">group_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">subject_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_subjects.subject_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">40</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">public</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Boolean</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">hidden</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Boolean</span>)
-)
-
-
-<span class="name">group_members</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_group_members</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_users.user_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">group_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_groups.group_id</span><span class="st st-sg">&#39;</span>))
-)
-
-
-<span class="name">forums</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_forums</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_forums.forum_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">object_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_objects.object_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">100</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">position</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">100</span>)),
- <span class="cm">#XXX: foreign key doesn&#39;t work</span>
-
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">last_post_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">thread_count</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>)
-)
-
-
-<span class="name">posts</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_posts</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_forums.forum_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_posts.post_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">root_post_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_posts.post_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">object_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_objects.object_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">view_count</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">author_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_users.user_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">200</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">200</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">DateTime</span>)
-)
-
-
-<span class="name">privileges</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_privileges</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">priv_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Unicode</span>(<span class="nb nb-int">100</span>))
-)
-
-
-<span class="name">acl_mapping</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_mapping</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">priv_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_privileges.priv_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">subject_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_subjects.subject_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">object_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>,
- <span class="name">meta</span>.<span class="name">ForeignKey</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_objects.object_id</span><span class="st st-sg">&#39;</span>)),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">state</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>)
-)
-
-
-<span class="name">acl_subjects</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_subjects</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">subject_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">subject_type</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">String</span>(<span class="nb nb-int">10</span>))
-)
-
-
-<span class="name">acl_objects</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">Table</span>(<span class="st st-sg">&#39;</span><span class="st">core_acl_objects</span><span class="st st-sg">&#39;</span>,
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">object_id</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">Integer</span>, <span class="name">primary_key</span><span class="op">=</span><span class="bn bn-pseudo">True</span>),
- <span class="name">meta</span>.<span class="name">Column</span>(<span class="st st-sg">&#39;</span><span class="st">object_type</span><span class="st st-sg">&#39;</span>, <span class="name">meta</span>.<span class="name">String</span>(<span class="nb nb-int">10</span>))
-)
-
-
-<span class="name">acl_subject_join</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">polymorphic_union</span>({
- <span class="st st-sg">&#39;</span><span class="st">user</span><span class="st st-sg">&#39;</span>: <span class="name">users</span>,
- <span class="st st-sg">&#39;</span><span class="st">group</span><span class="st st-sg">&#39;</span>: <span class="name">groups</span>
-}, <span class="st st-sg">&#39;</span><span class="st">subject_type</span><span class="st st-sg">&#39;</span>)
-
-
-<span class="name">acl_object_join</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">polymorphic_union</span>({
- <span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>: <span class="name">forums</span>,
- <span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>: <span class="name">posts</span>
-}, <span class="st st-sg">&#39;</span><span class="st">object_type</span><span class="st st-sg">&#39;</span>)
-
-
-<span class="kw">class </span><span class="cls">CoreTableObserver</span>(<span class="name">DatabaseObserver</span>):
-
- <span class="kw">def </span><span class="fun">after_table_creation</span>(<span class="bn bn-pseudo">self</span>, <span class="name">table</span>):
- <span class="kw">if</span> <span class="name">table</span> <span class="op op-word">is</span> <span class="name">users</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>
-
- <span class="name">e</span>(<span class="name">users</span>.<span class="name">insert</span>(), <span class="name">user_id</span><span class="op">=</span><span class="name">ANONYMOUS_USER_ID</span>, <span class="name">username</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">anonymous</span><span class="st st-sg">&#39;</span>)
- <span class="name">e</span>(<span class="name">users</span>.<span class="name">insert</span>(), <span class="name">user_id</span><span class="op">=</span><span class="name">DEFAULT_USER_ID</span>, <span class="name">username</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">default</span><span class="st st-sg">&#39;</span>)
-
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.feeds
- ~~~~~~~~~~~~~~~~~~~~
-
- Provides RSS Feeds.
-
- :copyright: 2006-2007 by Armin Ronacher.
- :license: GNU GPL, see LICENSE for more details.
-</span><span class="st st-db">&quot;&quot;&quot;</span>
-<span class="kw">from </span><span class="cls">pocoo</span><span class="kw"> import</span> <span class="name">Component</span>
-<span class="kw">from </span><span class="cls">pocoo.http</span><span class="kw"> import</span> <span class="name">PageNotFound</span>, <span class="name">Response</span>
-
-<span class="kw">from </span><span class="cls">pocoo.application</span><span class="kw"> import</span> <span class="name">RequestHandler</span>
-<span class="kw">from </span><span class="cls">pocoo.db</span><span class="kw"> import</span> <span class="name">meta</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.feed</span><span class="kw"> import</span> <span class="name">Feed</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.db</span><span class="kw"> import</span> <span class="name">forums</span>, <span class="name">posts</span>, <span class="name">users</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.textfmt</span><span class="kw"> import</span> <span class="name">parse_and_render</span>
-
-
-<span class="kw">class </span><span class="cls">FeedProvider</span>(<span class="name">Component</span>):
- <span class="cm">#: identifier for this feed. must be lowercase</span>
- <span class="name">identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">unknown</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_feed</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">parameter</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a dict in the following form::
-
- {&#39;title&#39;: &#39;Title of this feed&#39;,
- &#39;description&#39;: &#39;Description of this feed&#39;,
- &#39;items&#39;: [{
- &#39;title&#39;: &#39;title of this item&#39;,
- &#39;link&#39;: &#39;relative link of this item&#39;,
- &#39;author&#39;: &#39;author of this item&#39;,
- &#39;description&#39;: &#39;description of this item&#39;,
- &#39;pub_date&#39;: &#39;date of this item&#39;
-
- }]}
-
- Can raise a `FeedNotFound` exception.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="deco">@property</span>
- <span class="kw">def </span><span class="fun">url</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">feeds/</span><span class="st st-int">%s</span><span class="st">.xml</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">identifier</span>)
-
-
-
-<span class="kw">class </span><span class="cls">FeedNotFound</span>(<span class="exc">Exception</span>):
- <span class="kw">pass</span>
-
-
-<span class="kw">class </span><span class="cls">ThreadFeed</span>(<span class="name">FeedProvider</span>):
- <span class="name">identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">thread</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_feed</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">post_id</span>):
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">try</span>:
- <span class="name">post_id</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">post_id</span>)
- <span class="kw">except</span>:
- <span class="kw">raise</span> <span class="name">FeedNotFound</span>()
- <span class="name">row</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span>],
- (<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>)
- )).<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">raise</span> <span class="name">FeedNotFound</span>()
- <span class="name">root_post_id</span> <span class="op">=</span> <span class="name">row</span>[<span class="nb nb-int">0</span>]
- <span class="cm"># select data</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(
- [<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>, <span class="name">posts</span>.<span class="name">c</span>.<span class="name">title</span>, <span class="name">posts</span>.<span class="name">c</span>.<span class="name">text</span>,
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">timestamp</span>, <span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span>],
- (<span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">posts</span>.<span class="name">c</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="nb nb-int">10</span>
-
- ))
- <span class="kw">return</span> {
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Last Posts in Thread </span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">root_post_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>: <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The last 10 posts in Thread </span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">root_post_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">items</span><span class="st st-sg">&#39;</span>: [{
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>: <span class="st st-sg">&#39;</span><span class="st">post/</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>: <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>]),
- <span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">pub_date</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>]
- } <span class="kw">for</span> <span class="name">post</span> <span class="op op-word">in</span> <span class="name">result</span>]
- }
-
-
-
-<span class="kw">class </span><span class="cls">ForumFeed</span>(<span class="name">FeedProvider</span>):
- <span class="name">identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_feed</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">forum_id</span>):
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">try</span>:
- <span class="name">forum_id</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">forum_id</span>)
- <span class="kw">except</span>:
- <span class="kw">raise</span> <span class="name">FeedNotFound</span>()
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span>],
- (<span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">forum_id</span>)
- )).<span class="name">fetchone</span>() <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">raise</span> <span class="name">FeedNotFound</span>()
- <span class="cm"># select data</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(
- [<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>, <span class="name">posts</span>.<span class="name">c</span>.<span class="name">title</span>, <span class="name">posts</span>.<span class="name">c</span>.<span class="name">text</span>,
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">timestamp</span>, <span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span>],
- (<span class="name">posts</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">forum_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">posts</span>.<span class="name">c</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="nb nb-int">10</span>
-
- ))
- <span class="kw">return</span> {
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Last Posts in Forum </span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">forum_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>: <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The last 10 posts of forum </span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">forum_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">items</span><span class="st st-sg">&#39;</span>: [{
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>: <span class="st st-sg">&#39;</span><span class="st">post/</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>: <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>]),
- <span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">pub_date</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>]
- } <span class="kw">for</span> <span class="name">post</span> <span class="op op-word">in</span> <span class="name">result</span>]
- }
-
-
-
-<span class="kw">class </span><span class="cls">RecentChangesFeed</span>(<span class="name">FeedProvider</span>):
- <span class="name">identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">recent</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_title</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Recent Changes</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_description</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The recent posts</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_feed</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">parameter</span>):
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">if</span> <span class="name">parameter</span>:
- <span class="kw">raise</span> <span class="name">FeedNotFound</span>()
- <span class="name">result</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(
- [<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>, <span class="name">posts</span>.<span class="name">c</span>.<span class="name">title</span>, <span class="name">posts</span>.<span class="name">c</span>.<span class="name">text</span>,
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">timestamp</span>, <span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span>],
- (<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">posts</span>.<span class="name">c</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="nb nb-int">10</span>
-
- ))
- <span class="kw">return</span> {
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Recent Changes</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>: <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The most recent posts</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">items</span><span class="st st-sg">&#39;</span>: [{
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>: <span class="st st-sg">&#39;</span><span class="st">post/</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>: <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>]),
- <span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">pub_date</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>]
- } <span class="kw">for</span> <span class="name">post</span> <span class="op op-word">in</span> <span class="name">result</span>]
- }
-
-
-
-<span class="kw">class </span><span class="cls">FeedDisplay</span>(<span class="name">RequestHandler</span>):
- <span class="name">handler_regexes</span> <span class="op">=</span> [
- <span class="st st-sg">r&#39;</span><span class="st">^feeds/(?P&lt;feed&gt;[a-z0-9_-]+)\.xml$</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">r&#39;</span><span class="st">^feeds/(?P&lt;feed&gt;[a-z0-9_-]+)/(?P&lt;parameter&gt;.+)\.xml$</span><span class="st st-sg">&#39;</span>
-
- ]
-
- <span class="kw">def </span><span class="fun">handle_request</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">feed</span>, <span class="name">parameter</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="kw">for</span> <span class="name">feed_provider</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">FeedProvider</span>):
- <span class="kw">if</span> <span class="name">feed_provider</span>.<span class="name">identifier</span> <span class="op">==</span> <span class="name">feed</span>:
- <span class="name">data</span> <span class="op">=</span> <span class="name">feed_provider</span>.<span class="name">get_feed</span>(<span class="name">req</span>, <span class="name">parameter</span>)
- <span class="name">feed</span> <span class="op">=</span> <span class="name">Feed</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">data</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>],
- <span class="name">data</span>[<span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>],
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">make_external_url</span>(<span class="st st-sg">&#39;&#39;</span>))
- <span class="kw">try</span>:
- <span class="kw">for</span> <span class="name">item</span> <span class="op op-word">in</span> <span class="name">data</span>[<span class="st st-sg">&#39;</span><span class="st">items</span><span class="st st-sg">&#39;</span>]:
- <span class="name">feed</span>.<span class="name">add_item</span>(<span class="op">**</span><span class="name">item</span>)
- <span class="kw">except</span> <span class="name">FeedNotFound</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="name">resp</span> <span class="op">=</span> <span class="name">Response</span>(<span class="name">feed</span>.<span class="name">generate</span>())
- <span class="name">resp</span>[<span class="st st-sg">&#39;</span><span class="st">Content-Type</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">text/xml</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">return</span> <span class="name">resp</span>
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.forum
- ~~~~~~~~~~~~~~~~~~~~
-
- Forum Utilities.
-
- :copyright: 2006-2007 by Armin Ronacher, Benjamin Wiegand.
- :license: GNU GPL, see LICENSE for more details.
-</span><span class="st st-db">&quot;&quot;&quot;</span>
-<span class="kw">from </span><span class="cls">datetime</span><span class="kw"> import</span> <span class="name">datetime</span>
-
-<span class="kw">from </span><span class="cls">math</span><span class="kw"> import</span> <span class="name">ceil</span>
-
-<span class="kw">from </span><span class="cls">pocoo</span><span class="kw"> import</span> <span class="name">Component</span>
-<span class="kw">from </span><span class="cls">pocoo.db</span><span class="kw"> import</span> <span class="name">meta</span>, <span class="name">DatabaseModel</span>, <span class="name">lazy_column</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.user</span><span class="kw"> import</span> <span class="name">User</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.db</span><span class="kw"> import</span> <span class="name">forums</span>, <span class="name">posts</span>, <span class="name">users</span>, <span class="name">ANONYMOUS_USER_ID</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.template</span><span class="kw"> import</span> <span class="name">Pagination</span>, <span class="name">LazyPagination</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.textfmt</span><span class="kw"> import</span> <span class="name">parse_and_render</span>, <span class="name">quote_text</span>
-
-<span class="kw">from </span><span class="cls">pocoo.utils.uri</span><span class="kw"> import</span> <span class="name">urlencode</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.iterators</span><span class="kw"> import</span> <span class="name">inciter</span>
-
-<span class="cm"># for default arguments in Thread</span>
-
-<span class="name">_missing</span> <span class="op">=</span> <span class="bn">object</span>()
-
-
-<span class="kw">class </span><span class="cls">PostProcessor</span>(<span class="name">Component</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Process a posting before it is stored in the database.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">process_post</span>(<span class="bn bn-pseudo">self</span>, <span class="name">text</span>, <span class="name">title</span>, <span class="name">reason</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Process a posting.
-
- :param text: Text of the posting, possibly changed by
- another PostProcessor.
- :param title: The subject of the posting
- :param reason: Can be ``&#39;new&#39;`` or ``&#39;edit&#39;``.
-
- :returns:
- * ``True``: store the posting as-is, or
- * ``False``: refuse to store the posting, or
- * a string: use as the new posting text, or
- * a tuple: (text, title) for the posting
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> <span class="bn bn-pseudo">True</span>
-
-
-<span class="kw">def </span><span class="fun">apply_post_processors</span>(<span class="name">ctx</span>, <span class="name">text</span>, <span class="name">title</span>, <span class="name">reason</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Apply all `PostProcessor` components to the posting.
-
- Return (``text``, ``title``) tuple.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">PostProcessor</span>):
- <span class="name">rv</span> <span class="op">=</span> <span class="name">comp</span>.<span class="name">process_post</span>(<span class="name">text</span>, <span class="name">title</span>, <span class="st st-sg">&#39;</span><span class="st">new</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">rv</span>:
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">creation of posting denied</span><span class="st st-sg">&#39;</span>)
- <span class="kw">elif</span> <span class="bn">isinstance</span>(<span class="name">rv</span>, <span class="bn">basestring</span>):
- <span class="name">text</span> <span class="op">=</span> <span class="bn">unicode</span>(<span class="name">rv</span>)
- <span class="kw">elif</span> <span class="bn">isinstance</span>(<span class="name">rv</span>, <span class="bn">tuple</span>):
- <span class="name">text</span> <span class="op">=</span> <span class="bn">unicode</span>(<span class="name">rv</span>[<span class="nb nb-int">0</span>])
- <span class="name">title</span> <span class="op">=</span> <span class="bn">unicode</span>(<span class="name">rv</span>[<span class="nb nb-int">1</span>])
- <span class="kw">return</span> <span class="name">text</span>, <span class="name">title</span>
-
-
-<span class="kw">def </span><span class="fun">get_forum_index</span>(<span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a list of dicts with forum information so that
- the template can use it.
-
- If the request object has an identified user object attached
- the returned dict will include status information. (read,
- unread)
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">ctx</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>
-
- <span class="name">f</span> <span class="op">=</span> <span class="name">forums</span>.<span class="name">c</span>
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
-
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
- <span class="name">columns</span> <span class="op">=</span> [<span class="name">f</span>.<span class="name">forum_id</span>, <span class="name">f</span>.<span class="name">description</span>, <span class="name">f</span>.<span class="name">name</span>, <span class="name">f</span>.<span class="name">link</span>, <span class="name">f</span>.<span class="name">post_count</span>,
- <span class="name">f</span>.<span class="name">thread_count</span>]
-
- <span class="name">categories</span> <span class="op">=</span> []
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>):
- <span class="kw">for</span> <span class="name">category</span> <span class="op op-word">in</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(<span class="name">columns</span>,
- <span class="name">f</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="bn bn-pseudo">None</span>)):
- <span class="name">category</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">category</span>)
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_link</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">bool</span>(<span class="name">category</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>))
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">forums</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">forum</span> <span class="op op-word">in</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(<span class="name">columns</span> <span class="op">+</span> [<span class="name">f</span>.<span class="name">last_post_id</span>],
- <span class="name">f</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])):
- <span class="name">forum</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">forum</span>)
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_link</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">bool</span>(<span class="name">forum</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>))
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])
- <span class="cm"># get last post</span>
-
- <span class="name">last_post_id</span> <span class="op">=</span> <span class="name">forum</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">last_post_id</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">last_post_id</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">result</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>,
- <span class="name">p</span>.<span class="name">timestamp</span>,
- <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">last_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">!=</span> <span class="bn bn-pseudo">None</span>) <span class="op">&amp;</span>
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>)
- ))
- <span class="name">last_post</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">result</span>.<span class="name">fetchone</span>())
- <span class="name">username</span> <span class="op">=</span> <span class="name">urlencode</span>(<span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])
- <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>) <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span>\
- <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">username</span>)
- }
- <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="kw">else</span>:
- <span class="name">last_post</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">last_post</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">last_post</span>
- <span class="name">subforums</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">sf</span> <span class="op op-word">in</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">f</span>.<span class="name">forum_id</span>, <span class="name">f</span>.<span class="name">name</span>, <span class="name">f</span>.<span class="name">link</span>],
- <span class="name">f</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])):
- <span class="name">sf</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">sf</span>)
- <span class="name">sf</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">bool</span>(<span class="name">sf</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">sf</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">sf</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>))
- <span class="name">subforums</span>.<span class="name">append</span>(<span class="name">sf</span>)
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">subforums</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">subforums</span>
-
- <span class="name">forums</span>.<span class="name">append</span>(<span class="name">forum</span>)
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forums</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">forums</span>
- <span class="name">categories</span>.<span class="name">append</span>(<span class="name">category</span>)
- <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">transaction</span>(<span class="name">do</span>)
- <span class="kw">return</span> <span class="name">categories</span>
-
-
-<span class="kw">def </span><span class="fun">get_forum</span>(<span class="name">req</span>, <span class="name">forum_id</span>, <span class="name">page</span><span class="op">=</span><span class="nb nb-int">1</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a list of dicts so that the template can use it.
-
- Return ``None`` if the forum does not exist.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">ctx</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>
- <span class="name">f</span> <span class="op">=</span> <span class="name">forums</span>.<span class="name">c</span>
-
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
-
- <span class="name">columns</span> <span class="op">=</span> [<span class="name">f</span>.<span class="name">forum_id</span>, <span class="name">f</span>.<span class="name">description</span>, <span class="name">f</span>.<span class="name">name</span>, <span class="name">f</span>.<span class="name">link</span>, <span class="name">f</span>.<span class="name">post_count</span>,
- <span class="name">f</span>.<span class="name">thread_count</span>]
- <span class="name">forum_columns</span> <span class="op">=</span> [<span class="name">f</span>.<span class="name">forum_id</span>, <span class="name">f</span>.<span class="name">name</span>, <span class="name">f</span>.<span class="name">description</span>, <span class="name">f</span>.<span class="name">link</span>,
- <span class="name">f</span>.<span class="name">post_count</span>, <span class="name">f</span>.<span class="name">thread_count</span>, <span class="name">f</span>.<span class="name">last_post_id</span>]
- <span class="name">sf_columns</span> <span class="op">=</span> [<span class="name">f</span>.<span class="name">forum_id</span>, <span class="name">f</span>.<span class="name">name</span>, <span class="name">f</span>.<span class="name">link</span>]
- <span class="name">thread_columns</span> <span class="op">=</span> [<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">p</span>.<span class="name">post_count</span>, <span class="name">p</span>.<span class="name">view_count</span>, <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)]
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>):
- <span class="name">category</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(<span class="name">columns</span>,
- <span class="name">f</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">forum_id</span>
-
- )).<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">category</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span>
- <span class="name">category</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">category</span>)
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])
- <span class="cm"># wo don&#39;t pop link here so that the ForumPage request handler</span>
-
- <span class="cm"># can use the link key for redirecting. That means we don&#39;t</span>
- <span class="cm"># need a second query. But template designers shouldn&#39;t</span>
- <span class="cm"># ever access {{ forum.link }}</span>
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">bool</span>(<span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>])
- <span class="name">forums</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">forum</span> <span class="op op-word">in</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(<span class="name">forum_columns</span>,
- <span class="name">f</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])):
- <span class="name">forum</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">forum</span>)
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])
- <span class="cm"># wo don&#39;t pop that here so that the ForumPage request handler</span>
-
- <span class="cm"># can use the link key for redirecting. That means we don&#39;t</span>
- <span class="cm"># need a second query. But template designers shouldn&#39;t</span>
- <span class="cm"># ever access {{ forum.link }}</span>
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_link</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">bool</span>(<span class="name">forum</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>))
- <span class="name">subforums</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">sf</span> <span class="op op-word">in</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(<span class="name">sf_columns</span>,
- <span class="name">f</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])):
- <span class="name">sf</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">sf</span>)
- <span class="name">sf</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_link</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">bool</span>(<span class="name">sf</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>))
- <span class="name">sf</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">sf</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">subforums</span>.<span class="name">append</span>(<span class="name">sf</span>)
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">subforums</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">subforums</span>
-
- <span class="cm"># get last post</span>
- <span class="name">last_post_id</span> <span class="op">=</span> <span class="name">forum</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">last_post_id</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">last_post_id</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">result</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>,
- <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>),
- <span class="name">p</span>.<span class="name">timestamp</span>],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">last_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">!=</span> <span class="bn bn-pseudo">None</span>) <span class="op">&amp;</span>
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>)
- ))
- <span class="name">last_post</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="name">last_post</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">last_post</span>)
- <span class="name">username</span> <span class="op">=</span> <span class="name">urlencode</span>(<span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])
- <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>] <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span>\
- <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">username</span>),
- }
- <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="kw">else</span>:
- <span class="name">last_post</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">last_post</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">last_post</span>
- <span class="name">forums</span>.<span class="name">append</span>(<span class="name">forum</span>)
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forums</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">forums</span>
-
- <span class="cm"># pagination</span>
- <span class="kw">def </span><span class="fun">get_page_link</span>(<span class="name">number</span>):
- <span class="name">link</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">forum/</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">forum_id</span>
-
- <span class="kw">if</span> <span class="name">number</span> <span class="op">&gt;</span> <span class="nb nb-int">1</span>:
- <span class="name">link</span> <span class="op">+=</span> <span class="st st-sg">&#39;</span><span class="st">?page=</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">number</span>
-
- <span class="kw">return</span> <span class="name">link</span>
- <span class="name">threads_per_page</span> <span class="op">=</span> <span class="name">get_threads_per_page</span>(<span class="name">req</span>)
- <span class="name">page_count</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">ceil</span>(<span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">thread_count</span><span class="st st-sg">&#39;</span>] <span class="op">/</span> (<span class="name">threads_per_page</span> <span class="op">*</span> <span class="nb nb-flt">1.0</span>)))
- <span class="name">pagination</span> <span class="op">=</span> <span class="name">LazyPagination</span>(<span class="name">req</span>, <span class="name">page</span>, <span class="name">threads_per_page</span>, <span class="name">page_count</span>,
- <span class="name">get_page_link</span>)
-
- <span class="name">threads</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">thread</span> <span class="op op-word">in</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>(<span class="name">thread_columns</span>,
- (<span class="name">p</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>]) <span class="op">&amp;</span>
-
- (<span class="name">p</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="bn bn-pseudo">None</span>) <span class="op">&amp;</span>
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">p</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="name">threads_per_page</span>,
- <span class="name">offset</span><span class="op">=</span><span class="name">threads_per_page</span> <span class="op">*</span> (<span class="name">page</span> <span class="op">-</span> <span class="nb nb-int">1</span>)
- )):
- <span class="name">thread</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">thread</span>)
- <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>] <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">thread</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">thread</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">thread</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>)))
- }
- <span class="cm"># get last post</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>, <span class="name">p</span>.<span class="name">post_id</span>,
- <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">timestamp</span>,
- <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>]) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">p</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="nb nb-int">1</span>
-
- ))
- <span class="name">last_post</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">last_post</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">last_post</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">last_post</span>)
- <span class="name">username</span> <span class="op">=</span> <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>)
- <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>] <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">last_post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">username</span>,
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">username</span>)),
- }
- <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">last_post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">last_post</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">last_post</span>
-
- <span class="name">threads</span>.<span class="name">append</span>(<span class="name">thread</span>)
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">threads</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">threads</span>
- <span class="name">category</span>[<span class="st st-sg">&#39;</span><span class="st">pagination</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">pagination</span>
-
- <span class="kw">return</span> <span class="name">category</span>
- <span class="kw">return</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">transaction</span>(<span class="name">do</span>)
-
-
-<span class="kw">def </span><span class="fun">get_forum_pathbar</span>(<span class="name">ctx</span>, <span class="name">forum_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return the pathbar for a given forum.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">f</span> <span class="op">=</span> <span class="name">forums</span>.<span class="name">c</span>
- <span class="name">pathbar</span> <span class="op">=</span> []
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>, <span class="name">fid</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="kw">if</span> <span class="name">fid</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">fid</span> <span class="op">=</span> <span class="name">forum_id</span>
-
- <span class="name">row</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">f</span>.<span class="name">parent_id</span>, <span class="name">f</span>.<span class="name">name</span>],
- <span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">fid</span>
-
- )).<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">l</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">forum/</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">fid</span>
-
- <span class="name">pathbar</span>.<span class="name">append</span>({
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="name">l</span>),
- <span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>: <span class="name">fid</span>,
- <span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>]
- })
- <span class="kw">if</span> <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>] <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">do</span>(<span class="name">con</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">transaction</span>(<span class="name">do</span>)
- <span class="name">pathbar</span>.<span class="name">reverse</span>()
- <span class="kw">return</span> <span class="name">pathbar</span>
-
-
-<span class="kw">def </span><span class="fun">get_post_pathbar</span>(<span class="name">ctx</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Returns the pathbar for a given post including all forums and subforums</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">thread</span> <span class="op">=</span> <span class="name">Thread</span>.<span class="name">by_child</span>(<span class="name">ctx</span>, <span class="name">post_id</span>)
- <span class="name">pathbar</span> <span class="op">=</span> <span class="name">get_forum_pathbar</span>(<span class="name">ctx</span>, <span class="name">thread</span>.<span class="name">forum_id</span>)
- <span class="name">post_list</span> <span class="op">=</span> [ <span class="name">thread</span>.<span class="name">root_post_id</span> ]
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
-
- <span class="kw">if</span> <span class="name">thread</span>.<span class="name">root_post_id</span> <span class="op">!=</span> <span class="bn">int</span>(<span class="name">post_id</span>):
- <span class="name">post_list</span>.<span class="name">append</span>(<span class="name">post_id</span>)
-
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>):
- <span class="kw">for</span> <span class="bn">id</span> <span class="op op-word">in</span> <span class="name">post_list</span>:
- <span class="name">row</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">title</span>],
- <span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="bn">id</span>
-
- )).<span class="name">fetchone</span>()
- <span class="name">pathbar</span>.<span class="name">append</span>({
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post/</span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn">id</span>),
- <span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-db">&quot;</span><span class="st">title</span><span class="st st-db">&quot;</span>]
- })
- <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">transaction</span>(<span class="name">do</span>)
- <span class="kw">return</span> <span class="name">pathbar</span>
-
-
-<span class="kw">def </span><span class="fun">get_post_tree</span>(<span class="name">req</span>, <span class="name">post_id</span>, <span class="name">inc_view_count</span><span class="op">=</span><span class="bn bn-pseudo">True</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a dict with the thread information and a tree of posts.
-
- Per default it will increment the view counter of the
- thread requested. If you don&#39;t want that set ``inc_view_count``
- to ``False``.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">ctx</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
-
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
- <span class="name">f</span> <span class="op">=</span> <span class="name">forums</span>.<span class="name">c</span>
-
- <span class="cm"># load the post requested and lookup root_post_id</span>
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">root_post_id</span>, <span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>,
- <span class="name">p</span>.<span class="name">text</span>, <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">user_id</span>,
- <span class="name">u</span>.<span class="name">register_date</span>,
- <span class="name">u</span>.<span class="name">username</span>, <span class="name">u</span>.<span class="name">profile</span>, <span class="name">u</span>.<span class="name">post_count</span>,
- <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="cm"># XXX: need error return here</span>
-
- <span class="kw">return</span>
- <span class="name">post</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">row</span>)
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">self</span><span class="st st-sg">&#39;</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>) <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>))),
- <span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>),
- }
- <span class="name">signature</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>].<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>):
- <span class="name">signature</span> <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>],
- <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">True</span>)
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">signature</span>
-
- <span class="cm">#XXX: cache here</span>
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">parsed_text</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>])
- <span class="name">root_post_id</span> <span class="op">=</span> <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">root_post_id</span><span class="st st-sg">&#39;</span>)
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">root_post_id</span>, <span class="name">p</span>.<span class="name">title</span>,
- <span class="name">p</span>.<span class="name">parent_id</span>, <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">u</span>.<span class="name">user_id</span>, <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>)
- ))
-
- <span class="kw">def </span><span class="fun">prepare</span>(<span class="name">row</span>):
- <span class="name">d</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">row</span>)
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">self</span><span class="st st-sg">&#39;</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>) <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>))),
- }
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">active</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>] <span class="op">==</span> <span class="name">post_id</span>
-
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="kw">return</span> <span class="name">d</span>
-
- <span class="cm"># map threads by their parents and prepare the context</span>
- <span class="name">mapping</span> <span class="op">=</span> {}
- <span class="name">flat_posts</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">row</span> <span class="op op-word">in</span> <span class="name">result</span>:
- <span class="name">tmp</span> <span class="op">=</span> <span class="name">prepare</span>(<span class="name">row</span>)
- <span class="name">mapping</span>.<span class="name">setdefault</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>], []).<span class="name">append</span>(<span class="name">tmp</span>)
- <span class="name">flat_posts</span>.<span class="name">append</span>(<span class="name">tmp</span>)
- <span class="name">root</span> <span class="op">=</span> <span class="name">mapping</span>.<span class="name">pop</span>(<span class="bn bn-pseudo">None</span>, <span class="bn bn-pseudo">None</span>)
- <span class="kw">if</span> <span class="name">root</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span>
-
- <span class="kw">assert</span> <span class="bn">len</span>(<span class="name">root</span>) <span class="op">==</span> <span class="nb nb-int">1</span>, <span class="st st-sg">&#39;</span><span class="st">something went seriously wrong</span><span class="st st-sg">&#39;</span>
-
- <span class="cm"># reassamble thread</span>
-
- <span class="kw">def </span><span class="fun">reassamble</span>(<span class="name">nodes</span>):
- <span class="kw">for</span> <span class="name">node</span> <span class="op op-word">in</span> <span class="name">nodes</span>:
- <span class="name">node</span>[<span class="st st-sg">&#39;</span><span class="st">children</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">n</span> <span class="op">=</span> <span class="name">mapping</span>.<span class="name">pop</span>(<span class="name">node</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>], [])
- <span class="name">reassamble</span>(<span class="name">n</span>)
- <span class="name">reassamble</span>(<span class="name">root</span>)
-
- <span class="cm"># increment view_count</span>
-
- <span class="kw">if</span> <span class="name">inc_view_count</span>:
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">view_count</span>],
- <span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>))
- <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">update</span>(<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>),
- <span class="name">view_count</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>
-
- )
-
-
- <span class="cm"># fetch overall information for whole thread</span>
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">forum_id</span>,
- <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">f</span>.<span class="name">name</span>, <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>) <span class="op">&amp;</span>
- (<span class="name">f</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">forum_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">return</span> {
- <span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>]),
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>: {
- <span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>]),
- },
- <span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>: {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>] <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>] <span class="op op-word">or</span> <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])),
- },
- <span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>: <span class="name">root</span>,
- <span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>
-
- }
-
-
-<span class="kw">def </span><span class="fun">get_post</span>(<span class="name">req</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return exactly one post. If the post does not exist the result
- will be ``None``.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">ctx</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>
-
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
-
- <span class="name">r</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">text</span>, <span class="name">p</span>.<span class="name">timestamp</span>,
- <span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>, <span class="name">u</span>.<span class="name">profile</span>,
- <span class="name">u</span>.<span class="name">register_date</span>,
- <span class="name">u</span>.<span class="name">post_count</span>, <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">r</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span>
-
- <span class="name">post</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">row</span>)
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">self</span><span class="st st-sg">&#39;</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>) <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>))),
- <span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>)
- }
- <span class="name">signature</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>].<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>):
- <span class="name">signature</span> <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>])
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">signature</span>
-
- <span class="cm">#XXX: cache here</span>
- <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">parsed_text</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">post</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>])
- <span class="kw">return</span> <span class="name">post</span>
-
-
-<span class="kw">def </span><span class="fun">get_last_posts</span>(<span class="name">req</span>, <span class="name">root_post_id</span>, <span class="name">n</span><span class="op">=</span><span class="nb nb-int">1</span>, <span class="name">offset</span><span class="op">=</span><span class="nb nb-int">0</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Returns a flat view of the n latest posts that are
- children of root_post_id.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">text</span>,
- <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">profile</span>,
- <span class="name">u</span>.<span class="name">post_count</span>, <span class="name">u</span>.<span class="name">register_date</span>,
- <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">p</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="name">n</span>,
- <span class="name">offset</span><span class="op">=</span><span class="name">offset</span>
-
- ))
-
- <span class="kw">def </span><span class="fun">prepare</span>(<span class="name">row</span>):
- <span class="name">d</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">row</span>)
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">user_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">user_id</span> <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">self</span><span class="st st-sg">&#39;</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])),
- }
- <span class="name">signature</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>].<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>):
- <span class="name">signature</span> <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>],
- <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">True</span>)
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">signature</span>
-
- <span class="cm">#XXX: this doesn&#39;t cache by now</span>
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">parsed_text</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>])
- <span class="kw">return</span> <span class="name">d</span>
-
- <span class="name">post_list</span> <span class="op">=</span> [<span class="name">prepare</span>(<span class="name">row</span>) <span class="kw">for</span> <span class="name">row</span> <span class="op op-word">in</span> <span class="name">result</span>]
- <span class="kw">return</span> <span class="name">post_list</span>
-
-
-<span class="kw">def </span><span class="fun">get_flat_view</span>(<span class="name">req</span>, <span class="name">post_id</span>, <span class="name">inc_view_count</span><span class="op">=</span><span class="bn bn-pseudo">True</span>, <span class="name">order</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">asc</span><span class="st st-sg">&#39;</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Returns the flat view of an post and the next n posts so
- that the template can render a page. n is the number of
- posts per page defined in either the user settings or the
- global forum configuration.
-
- Per default it will increment the view counter of the
- thread requested. If you don&#39;t want that set ``inc_view_count``
- to ``False``.
-
- If you want to get the latest post first, set ``order``
- to ``&#39;desc&#39;``.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">ctx</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
-
- <span class="name">f</span> <span class="op">=</span> <span class="name">forums</span>.<span class="name">c</span>
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
-
- <span class="cm"># find root_post_id</span>
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">root_post_id</span>],
- <span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>
-
- ))
- <span class="cm"># XXX: This raises TypeError on failure.</span>
- <span class="name">root_post_id</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>]
-
- <span class="cm"># select all post ids to calculate the position of the post on a page</span>
-
- <span class="cm"># the purpose of this calculation is to find the first and last post</span>
- <span class="cm"># on the page if the post_id given the function</span>
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>],
- <span class="name">p</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>
-
- ))
- <span class="name">posts_per_page</span> <span class="op">=</span> <span class="name">get_posts_per_page</span>(<span class="name">req</span>)
- <span class="name">postlist</span> <span class="op">=</span> [<span class="name">row</span>[<span class="nb nb-int">0</span>] <span class="kw">for</span> <span class="name">row</span> <span class="op op-word">in</span> <span class="name">result</span>]
- <span class="name">post_index</span> <span class="op">=</span> <span class="name">postlist</span>.<span class="name">index</span>(<span class="name">post_id</span>)
- <span class="name">page</span> <span class="op">=</span> <span class="name">post_index</span> <span class="op">//</span> <span class="name">posts_per_page</span>
-
- <span class="name">page_start</span> <span class="op">=</span> <span class="name">page</span> <span class="op">*</span> <span class="name">posts_per_page</span>
- <span class="name">post_range_low</span> <span class="op">=</span> <span class="name">postlist</span>[<span class="name">page_start</span>]
- <span class="name">post_range_high</span> <span class="op">=</span> <span class="name">postlist</span>[<span class="name">page_start</span>:<span class="name">page_start</span> <span class="op">+</span> <span class="name">posts_per_page</span>][<span class="op">-</span><span class="nb nb-int">1</span>]
-
- <span class="name">pagination</span> <span class="op">=</span> <span class="name">Pagination</span>(<span class="name">req</span>, <span class="name">postlist</span>, <span class="name">page_start</span>, <span class="name">posts_per_page</span>,
- <span class="kw">lambda</span> <span class="name">x</span>: <span class="st st-sg">&#39;</span><span class="st">post/</span><span class="st st-int">%d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">x</span>)
-
- <span class="name">orderfunc</span> <span class="op">=</span> (<span class="name">order</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">desc</span><span class="st st-sg">&#39;</span> <span class="op op-word">and</span> <span class="name">meta</span>.<span class="name">desc</span> <span class="op op-word">or</span> <span class="name">meta</span>.<span class="name">asc</span>)
- <span class="cm"># select matching posts</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">root_post_id</span>, <span class="name">p</span>.<span class="name">title</span>,
- <span class="name">p</span>.<span class="name">forum_id</span>, <span class="name">p</span>.<span class="name">parent_id</span>, <span class="name">p</span>.<span class="name">text</span>,
- <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">username</span>, <span class="name">u</span>.<span class="name">user_id</span>,
- <span class="name">u</span>.<span class="name">profile</span>, <span class="name">u</span>.<span class="name">post_count</span>, <span class="name">u</span>.<span class="name">register_date</span>,
- <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">&gt;=</span> <span class="name">post_range_low</span>) <span class="op">&amp;</span>
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">&lt;=</span> <span class="name">post_range_high</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">orderfunc</span>(<span class="name">p</span>.<span class="name">post_id</span>)]
- ))
-
- <span class="kw">def </span><span class="fun">prepare</span>(<span class="name">number</span>, <span class="name">row</span>):
- <span class="name">d</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">row</span>)
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">post_number</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">number</span>
-
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>])
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">user_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">registered</span><span class="st st-sg">&#39;</span>: <span class="name">user_id</span> <span class="op">&gt;</span> <span class="nb nb-int">0</span>,
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">self</span><span class="st st-sg">&#39;</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">post_count</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">register_date</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])),
- }
- <span class="name">signature</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>].<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>):
- <span class="name">signature</span> <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>],
- <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">True</span>)
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>][<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">signature</span>
-
- <span class="cm">#XXX: this doesn&#39;t cache by now</span>
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">parsed_text</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>])
- <span class="kw">return</span> <span class="name">d</span>
-
- <span class="name">real_posts</span> <span class="op">=</span> [<span class="name">prepare</span>(<span class="name">num</span>, <span class="name">row</span>) <span class="kw">for</span> <span class="name">num</span>, <span class="name">row</span> <span class="op op-word">in</span> <span class="name">inciter</span>(<span class="name">result</span>, <span class="name">page_start</span>)]
-
- <span class="cm"># increment view_count</span>
-
- <span class="kw">if</span> <span class="name">inc_view_count</span>:
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">view_count</span>],
- <span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>))
- <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">update</span>(<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>),
- <span class="name">view_count</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>
-
- )
-
- <span class="cm"># and another query for the overview page</span>
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">post_id</span>, <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">forum_id</span>,
- <span class="name">p</span>.<span class="name">timestamp</span>, <span class="name">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">username</span>,
- <span class="name">f</span>.<span class="name">name</span>, <span class="name">p</span>.<span class="name">username</span>.<span class="name">label</span>(<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>)],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">root_post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>) <span class="op">&amp;</span>
- (<span class="name">f</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">forum_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">return</span> {
- <span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>]),
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>: {
- <span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">forum</span><span class="st st-sg">&#39;</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>]),
- },
- <span class="st st-sg">&#39;</span><span class="st">author</span><span class="st st-sg">&#39;</span>: {
- <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">guestname</span><span class="st st-sg">&#39;</span>] <span class="op op-word">or</span> <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="name">ctx</span>.<span class="name">make_url</span>(<span class="st st-sg">&#39;</span><span class="st">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])),
- },
- <span class="st st-sg">&#39;</span><span class="st">pagination</span><span class="st st-sg">&#39;</span>: <span class="name">pagination</span>,
- <span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>: <span class="name">real_posts</span>
-
- }
-
-
-<span class="kw">def </span><span class="fun">get_last_thread_change</span>(<span class="name">req</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the timestamp of the last change in the thread.
- ``post_id`` must be the root_post_id, there is no further
- check done.
-
- Return ``None`` if something in the query went wrong (eg.
- no thread with the requested root_post_id exists)
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="cm">#XXX: doesn&#39;t cover edits</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">posts</span>.<span class="name">c</span>.<span class="name">timestamp</span>],
- (<span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">post_id</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">meta</span>.<span class="name">desc</span>(<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span>)],
- <span class="name">limit</span><span class="op">=</span><span class="nb nb-int">1</span>
-
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span>
-
- <span class="kw">return</span> <span class="name">row</span>[<span class="nb nb-int">0</span>]
-
-
-<span class="kw">def </span><span class="fun">get_posts_per_page</span>(<span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the number of posts a user wishes to display on the
- flat view page.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">try</span>:
- <span class="name">posts_per_page</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">settings</span>[<span class="st st-sg">&#39;</span><span class="st">posts_per_page</span><span class="st st-sg">&#39;</span>]
- <span class="kw">if</span> <span class="name">posts_per_page</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">posts_per_page</span>
-
- <span class="kw">except</span> <span class="exc">KeyError</span>:
- <span class="kw">pass</span>
- <span class="kw">return</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">cfg</span>.<span class="name">get_int</span>(<span class="st st-sg">&#39;</span><span class="st">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">posts_per_page</span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">15</span>)
-
-
-
-<span class="kw">def </span><span class="fun">get_threads_per_page</span>(<span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the number of posts a users whishes to display on the
- viewforum page.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">try</span>:
- <span class="name">threads_per_page</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">settings</span>[<span class="st st-sg">&#39;</span><span class="st">threads_per_page</span><span class="st st-sg">&#39;</span>]
- <span class="kw">if</span> <span class="name">threads_per_page</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">threads_per_page</span>
-
- <span class="kw">except</span> <span class="exc">KeyError</span>:
- <span class="kw">pass</span>
- <span class="kw">return</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">cfg</span>.<span class="name">get_int</span>(<span class="st st-sg">&#39;</span><span class="st">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">threads_per_page</span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">20</span>)
-
-
-
-<span class="kw">def </span><span class="fun">get_view_mode</span>(<span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the display mode a user has defined in the user settings
- or fall back to the default mode from the pocoo.conf.
-
- :return: either ``&#39;flat&#39;`` or ``&#39;threaded&#39;``.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">val</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">settings</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">view_mode</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">val</span> <span class="op op-word">in</span> (<span class="st st-sg">&#39;</span><span class="st">flat</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">threaded</span><span class="st st-sg">&#39;</span>):
- <span class="kw">return</span> <span class="name">val</span>
-
- <span class="name">val</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">cfg</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">default_view</span><span class="st st-sg">&#39;</span>, <span class="bn bn-pseudo">None</span>)
- <span class="kw">return</span> (<span class="name">val</span> <span class="op op-word">in</span> (<span class="st st-sg">&#39;</span><span class="st">flat</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">threaded</span><span class="st st-sg">&#39;</span>)) <span class="op op-word">and</span> <span class="name">val</span> <span class="op op-word">or</span> <span class="st st-sg">&#39;</span><span class="st">threaded</span><span class="st st-sg">&#39;</span>
-
-
-<span class="kw">def </span><span class="fun">quote_post</span>(<span class="name">req</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a tuple in the form ``(text, title)`` which is useful
- for replying and quoting existing posts. The title is
- prefixed with a local representation of &#39;Re:&#39; and the text
- is quoted with the selected markup.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
-
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">text</span>, <span class="name">u</span>.<span class="name">username</span>],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">p</span>.<span class="name">author_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="cm"># XXX: ValueError?</span>
-
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">post </span><span class="st st-int">%s</span><span class="st"> does not exist</span><span class="st st-sg">&#39;</span>)
-
- <span class="name">suffix</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Re:</span><span class="st st-sg">&#39;</span>)
- <span class="name">title</span> <span class="op">=</span> <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>]
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">title</span>.<span class="name">startswith</span>(<span class="name">suffix</span>):
- <span class="name">title</span> <span class="op">=</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st st-int">%s</span><span class="st"> </span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> (<span class="name">suffix</span>, <span class="name">title</span>)
- <span class="name">text</span> <span class="op">=</span> <span class="name">quote_text</span>(<span class="name">req</span>, <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>], <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])
- <span class="kw">return</span> <span class="name">text</span>, <span class="name">title</span>
-
-
-<span class="kw">def </span><span class="fun">edit_post</span>(<span class="name">req</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a tuple in the form (``text``, ``title``, ``username``)
- for the edit view.
-
- :see: `quote_post`
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">p</span>.<span class="name">text</span>, <span class="name">p</span>.<span class="name">title</span>, <span class="name">p</span>.<span class="name">username</span>],
- (<span class="name">p</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="cm"># XXX: ValueError?</span>
-
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">post </span><span class="st st-int">%s</span><span class="st"> does not exist</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="bn">tuple</span>(<span class="name">row</span>)
-
-
-<span class="kw">class </span><span class="cls">_Site</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">A special singleton representing a whole site.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">object_id</span> <span class="op">=</span> <span class="nb nb-int">0</span>
-
- <span class="kw">def </span><span class="fun">__repr__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">&lt;</span><span class="st st-int">%s</span><span class="st">&gt;</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>
-
-<span class="name">Site</span> <span class="op">=</span> <span class="name">_Site</span>()
-
-
-<span class="kw">class </span><span class="cls">Forum</span>(<span class="name">DatabaseModel</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This class represents one forum. Don&#39;t pass instances of this
- class to templates, therefore there are some other functions
- in this module.
-
- The main purpose of this class is the creation and management
- of forums. You can also use this class for the ACL functions.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">__init__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">ctx</span>, <span class="name">forum_id</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span> <span class="op">=</span> <span class="name">ctx</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span> <span class="op">=</span> <span class="name">forum_id</span>
- <span class="bn">super</span>(<span class="name">Forum</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">ctx</span>, <span class="name">forums</span>, <span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>)
-
- <span class="name">parent_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">object_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">object_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">name</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">name</span><span class="st st-sg">&#39;</span>)
- <span class="name">description</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">description</span><span class="st st-sg">&#39;</span>)
- <span class="name">position</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">position</span><span class="st st-sg">&#39;</span>)
- <span class="name">link</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>)
-
- <span class="deco">@staticmethod</span>
-
- <span class="kw">def </span><span class="fun">create</span>(<span class="name">ctx</span>, <span class="name">name</span>, <span class="name">description</span><span class="op">=</span><span class="st st-db">&quot;&quot;</span>, <span class="name">parent</span><span class="op">=</span><span class="bn bn-pseudo">None</span>, <span class="name">position</span><span class="op">=</span><span class="bn bn-pseudo">None</span>,
- <span class="name">link</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Create a new forum.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">parent</span>, <span class="name">Forum</span>):
- <span class="name">parent</span> <span class="op">=</span> <span class="name">parent</span>.<span class="name">forum_id</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">forums</span>.<span class="name">insert</span>(),
- <span class="name">parent_id</span><span class="op">=</span><span class="name">parent</span>,
- <span class="name">name</span><span class="op">=</span><span class="name">name</span>,
- <span class="name">description</span><span class="op">=</span><span class="name">description</span>,
- <span class="name">position</span><span class="op">=</span><span class="name">position</span>,
- <span class="name">link</span><span class="op">=</span><span class="name">link</span>,
- <span class="name">post_count</span><span class="op">=</span><span class="nb nb-int">0</span>,
- <span class="name">thread_count</span><span class="op">=</span><span class="nb nb-int">0</span>
-
- )
- <span class="kw">return</span> <span class="name">Forum</span>(<span class="name">ctx</span>, <span class="name">result</span>.<span class="name">last_inserted_ids</span>()[<span class="nb nb-int">0</span>])
-
- <span class="kw">def </span><span class="fun">parent_get</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="name">Forum</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="bn bn-pseudo">self</span>.<span class="name">parent_id</span>)
- <span class="kw">def </span><span class="fun">parent_set</span>(<span class="bn bn-pseudo">self</span>, <span class="name">value</span>):
- <span class="kw">if</span> <span class="name">value</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">parent_id</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">value</span>, <span class="name">Forum</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">parent_id</span> <span class="op">=</span> <span class="name">value</span>.<span class="name">forum_id</span>
-
- <span class="name">parent</span> <span class="op">=</span> <span class="bn">property</span>(<span class="name">parent_get</span>, <span class="name">parent_set</span>)
- <span class="kw">del</span> <span class="name">parent_get</span>, <span class="name">parent_set</span>
-
- <span class="kw">def </span><span class="fun">__repr__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">&lt;</span><span class="st st-int">%s</span><span class="st"> </span><span class="st st-int">%d</span><span class="st">: </span><span class="st st-int">%r</span><span class="st">&gt;</span><span class="st st-sg">&#39;</span> <span class="op">%</span> (
- <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>,
- <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span>,
- <span class="bn bn-pseudo">self</span>.<span class="name">name</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">Thread</span>(<span class="name">DatabaseModel</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This class represents a root post with all of its children.
- You can use this class to manage a thread, add a new reply
- or edit one of its children.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">__init__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">ctx</span>, <span class="name">root_post_id</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span> <span class="op">=</span> <span class="name">ctx</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span> <span class="op">=</span> <span class="name">root_post_id</span>
- <span class="bn">super</span>(<span class="name">Thread</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">ctx</span>, <span class="name">posts</span>, <span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>,
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">parent_id</span> <span class="op">==</span> <span class="bn bn-pseudo">None</span>
-
- )
-
- <span class="name">forum_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">forum_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">parent_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">root_post_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">root_post_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">object_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">object_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">author_id</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">author_id</span><span class="st st-sg">&#39;</span>)
- <span class="name">title</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>)
- <span class="name">text</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>)
- <span class="name">timestamp</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>)
-
- <span class="deco">@staticmethod</span>
-
- <span class="kw">def </span><span class="fun">create</span>(<span class="name">ctx</span>, <span class="name">forum</span>, <span class="name">author</span>, <span class="name">title</span>, <span class="name">text</span>, <span class="name">timestamp</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Create a new thread.
- If author is a string it will be an anonymous posting.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">username</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">forum</span>, <span class="name">Forum</span>):
- <span class="name">forum</span> <span class="op">=</span> <span class="name">forum</span>.<span class="name">forum_id</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">author</span>, <span class="name">User</span>):
- <span class="name">author</span> <span class="op">=</span> <span class="name">author</span>.<span class="name">user_id</span>
-
- <span class="kw">elif</span> <span class="bn">isinstance</span>(<span class="name">author</span>, <span class="bn">basestring</span>):
- <span class="name">username</span> <span class="op">=</span> <span class="name">author</span>
- <span class="name">author</span> <span class="op">=</span> <span class="name">ANONYMOUS_USER_ID</span>
-
- <span class="kw">if</span> <span class="name">timestamp</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">timestamp</span> <span class="op">=</span> <span class="name">datetime</span>.<span class="name">utcnow</span>()
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>):
- <span class="name">result</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">insert</span>(),
- <span class="name">forum_id</span> <span class="op">=</span> <span class="name">forum</span>,
- <span class="name">author_id</span> <span class="op">=</span> <span class="name">author</span>,
- <span class="name">username</span> <span class="op">=</span> <span class="name">username</span>,
- <span class="name">title</span> <span class="op">=</span> <span class="name">title</span>,
- <span class="name">text</span> <span class="op">=</span> <span class="name">text</span>,
- <span class="name">timestamp</span> <span class="op">=</span> <span class="name">timestamp</span>,
- <span class="name">post_count</span> <span class="op">=</span> <span class="nb nb-int">1</span>,
- <span class="name">view_count</span> <span class="op">=</span> <span class="nb nb-int">0</span>
-
- )
- <span class="name">thread_id</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">last_inserted_ids</span>()[<span class="op">-</span><span class="nb nb-int">1</span>]
- <span class="cm"># increment author post count</span>
- <span class="kw">if</span> <span class="name">author</span> <span class="op">&gt;</span> <span class="op">-</span><span class="nb nb-int">1</span>:
- <span class="name">old</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">select</span>([<span class="name">users</span>.<span class="name">c</span>.<span class="name">post_count</span>], <span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">author</span>)
- <span class="name">con</span>.<span class="name">execute</span>(<span class="name">users</span>.<span class="name">update</span>(<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">author</span>),
- <span class="name">post_count</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">old</span>).<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>
-
- )
- <span class="cm"># increment forum post and thread count</span>
- <span class="name">old</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">select</span>([<span class="name">forums</span>.<span class="name">c</span>.<span class="name">post_count</span>, <span class="name">forums</span>.<span class="name">c</span>.<span class="name">thread_count</span>],
- <span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">forum</span>)
- <span class="name">row</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">old</span>).<span class="name">fetchone</span>()
- <span class="name">con</span>.<span class="name">execute</span>(<span class="name">forums</span>.<span class="name">update</span>(<span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="name">forum</span>),
- <span class="name">post_count</span> <span class="op">=</span> <span class="name">row</span>[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>,
- <span class="name">thread_count</span> <span class="op">=</span> <span class="name">row</span>[<span class="nb nb-int">1</span>] <span class="op">+</span> <span class="nb nb-int">1</span>,
- <span class="name">last_post_id</span> <span class="op">=</span> <span class="name">thread_id</span>
-
- )
- <span class="kw">return</span> <span class="name">thread_id</span>
- <span class="name">thread_id</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">transaction</span>(<span class="name">do</span>)
- <span class="cm"># XXX: this feels a bit strange</span>
-
- <span class="name">t</span> <span class="op">=</span> <span class="name">Thread</span>(<span class="name">ctx</span>, <span class="name">thread_id</span>)
- <span class="name">t</span>.<span class="name">root_post_id</span> <span class="op">=</span> <span class="name">t</span>.<span class="name">post_id</span>
-
- <span class="name">t</span>.<span class="name">save</span>()
- <span class="kw">return</span> <span class="name">t</span>
-
- <span class="deco">@staticmethod</span>
- <span class="kw">def </span><span class="fun">by_child</span>(<span class="name">ctx</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Return the thread of a given ``post_id``.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">result</span> <span class="op">=</span> <span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span>],
- (<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>)
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="cm"># XXX: ValueError?</span>
-
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">post </span><span class="st st-int">%s</span><span class="st"> does not exist</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">post_id</span>)
- <span class="kw">return</span> <span class="name">Thread</span>(<span class="name">ctx</span>, <span class="name">row</span>[<span class="nb nb-int">0</span>])
-
- <span class="kw">def </span><span class="fun">reply</span>(<span class="bn bn-pseudo">self</span>, <span class="name">post_id</span>, <span class="name">author</span>, <span class="name">title</span>, <span class="name">text</span>, <span class="name">timestamp</span><span class="op">=</span><span class="bn bn-pseudo">None</span>,
- <span class="name">no_processor</span><span class="op">=</span><span class="bn bn-pseudo">False</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Reply to post ``post_id`` which is a child of the thread.
- Return the id of the new post.
-
- If ``author`` is a string it will be an anonymous posting.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">username</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
- <span class="kw">if</span> <span class="name">post_id</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">post_id</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">author</span>, <span class="name">User</span>):
- <span class="name">author</span> <span class="op">=</span> <span class="name">author</span>.<span class="name">user_id</span>
-
- <span class="kw">elif</span> <span class="bn">isinstance</span>(<span class="name">author</span>, <span class="bn">basestring</span>):
- <span class="name">username</span> <span class="op">=</span> <span class="name">author</span>
- <span class="name">author</span> <span class="op">=</span> <span class="name">ANONYMOUS_USER_ID</span>
-
- <span class="kw">if</span> <span class="name">timestamp</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">timestamp</span> <span class="op">=</span> <span class="name">datetime</span>.<span class="name">utcnow</span>()
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">no_processor</span>:
- <span class="name">text</span>, <span class="name">title</span> <span class="op">=</span> <span class="name">apply_post_processors</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">text</span>,
- <span class="name">title</span>, <span class="st st-sg">&#39;</span><span class="st">new</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>):
- <span class="name">result</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span>],
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>
-
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span> <span class="op op-word">or</span> <span class="name">row</span>[<span class="nb nb-int">0</span>] <span class="op">!=</span> <span class="bn">int</span>(<span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>):
- <span class="cm"># XXX: ValueError?</span>
-
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">The post either does not exist or does not </span><span class="st st-sg">&#39;</span>
- <span class="st st-sg">&#39;</span><span class="st">belong to this thread</span><span class="st st-sg">&#39;</span>)
- <span class="name">new_post_id</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">insert</span>(),
- <span class="name">forum_id</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span>,
- <span class="name">parent_id</span> <span class="op">=</span> <span class="name">post_id</span>,
- <span class="name">root_post_id</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>,
- <span class="name">author_id</span> <span class="op">=</span> <span class="name">author</span>,
- <span class="name">username</span> <span class="op">=</span> <span class="name">username</span>,
- <span class="name">title</span> <span class="op">=</span> <span class="name">title</span>,
- <span class="name">text</span> <span class="op">=</span> <span class="name">text</span>,
- <span class="name">timestamp</span> <span class="op">=</span> <span class="name">timestamp</span>
-
- ).<span class="name">last_inserted_ids</span>()[<span class="nb nb-int">0</span>]
-
- <span class="cm"># increment author post count</span>
- <span class="kw">if</span> <span class="name">author</span> <span class="op">&gt;</span> <span class="op">-</span><span class="nb nb-int">1</span>:
- <span class="name">old</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">select</span>([<span class="name">users</span>.<span class="name">c</span>.<span class="name">post_count</span>], <span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">author</span>)
- <span class="name">con</span>.<span class="name">execute</span>(<span class="name">users</span>.<span class="name">update</span>(<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">author</span>),
- <span class="name">post_count</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">old</span>).<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>
-
- )
- <span class="cm"># increment forum post count and update last_post_id</span>
- <span class="name">old</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">select</span>([<span class="name">forums</span>.<span class="name">c</span>.<span class="name">post_count</span>],
- <span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span>)
- <span class="name">con</span>.<span class="name">execute</span>(<span class="name">forums</span>.<span class="name">update</span>(<span class="name">forums</span>.<span class="name">c</span>.<span class="name">forum_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span>),
- <span class="name">post_count</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">old</span>).<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>,
- <span class="name">last_post_id</span> <span class="op">=</span> <span class="name">new_post_id</span>
-
- )
- <span class="cm"># increment thread post count</span>
- <span class="name">old</span> <span class="op">=</span> <span class="name">meta</span>.<span class="name">select</span>([<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_count</span>],
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>)
- <span class="name">con</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">update</span>(<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>),
- <span class="name">post_count</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">old</span>).<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>] <span class="op">+</span> <span class="nb nb-int">1</span>
-
- )
- <span class="kw">return</span> <span class="name">new_post_id</span>
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">transaction</span>(<span class="name">do</span>)
-
- <span class="kw">def </span><span class="fun">edit_reply</span>(<span class="bn bn-pseudo">self</span>, <span class="name">post_id</span>, <span class="name">author</span><span class="op">=</span><span class="name">_missing</span>, <span class="name">title</span><span class="op">=</span><span class="name">_missing</span>,
- <span class="name">text</span><span class="op">=</span><span class="name">_missing</span>, <span class="name">timestamp</span><span class="op">=</span><span class="name">_missing</span>,
- <span class="name">no_processor</span><span class="op">=</span><span class="bn bn-pseudo">False</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Edit a reply.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">d</span> <span class="op">=</span> {}
- <span class="kw">if</span> <span class="name">author</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="name">_missing</span>:
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">author</span>, <span class="name">User</span>):
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author_id</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">author</span>.<span class="name">user_id</span> <span class="cm"># pylint: disable-msg=E1101</span>
-
- <span class="kw">else</span>:
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">author_id</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">author</span>
- <span class="kw">if</span> <span class="name">title</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="name">_missing</span>:
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">title</span>
-
- <span class="kw">if</span> <span class="name">text</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="name">_missing</span>:
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">text</span>
-
- <span class="kw">if</span> <span class="name">timestamp</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="name">_missing</span>:
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">timestamp</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">timestamp</span>
-
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">no_processor</span> <span class="op op-word">and</span> <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">d</span> <span class="op op-word">and</span> <span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">d</span>:
- <span class="name">rv</span> <span class="op">=</span> <span class="name">apply_post_processors</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>], <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>], <span class="st st-sg">&#39;</span><span class="st">edit</span><span class="st st-sg">&#39;</span>)
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>], <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">rv</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">update</span>(<span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>), <span class="op">**</span><span class="name">d</span>)
-
- <span class="kw">def </span><span class="fun">has_child</span>(<span class="bn bn-pseudo">self</span>, <span class="name">post_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Check if a post_id is a child of this thread.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">result</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span>],
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">post_id</span>
-
- ))
- <span class="name">row</span> <span class="op">=</span> <span class="name">result</span>.<span class="name">fetchone</span>()
- <span class="kw">return</span> <span class="name">row</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span> <span class="op op-word">and</span> <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">root_post_id</span><span class="st st-sg">&#39;</span>] <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>
-
- <span class="kw">def </span><span class="fun">get_post_list</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a flat list of all posts in this thread sorted by their post_id.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">result</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">posts</span>.<span class="name">select</span>(
- <span class="name">posts</span>.<span class="name">c</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>
-
- ))
- <span class="kw">return</span> <span class="bn">map</span>(<span class="bn">dict</span>, <span class="name">result</span>)
-
- <span class="kw">def </span><span class="fun">count_children</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the number of direct or indirect children of this thread.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">p</span> <span class="op">=</span> <span class="name">posts</span>.<span class="name">c</span>
- <span class="name">result</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">engine</span>.<span class="name">execute</span>(<span class="name">meta</span>.<span class="name">select</span>([<span class="name">meta</span>.<span class="name">func</span>.<span class="name">count</span>(<span class="name">p</span>.<span class="name">post_id</span>)],
- <span class="name">p</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>
-
- ))
- <span class="kw">return</span> <span class="name">result</span>.<span class="name">fetchone</span>()[<span class="nb nb-int">0</span>]
-
- <span class="name">__len__</span> <span class="op">=</span> <span class="name">count_children</span>
-
- <span class="kw">def </span><span class="fun">forum_get</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span> <span class="op op-word">is</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">Forum</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span>)
- <span class="kw">def </span><span class="fun">forum_set</span>(<span class="bn bn-pseudo">self</span>, <span class="name">value</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn">isinstance</span>(<span class="name">value</span>, <span class="name">Forum</span>):
- <span class="kw">raise</span> <span class="exc">TypeError</span>(<span class="st st-sg">&#39;</span><span class="st">Can only set Forum instances</span><span class="st st-sg">&#39;</span>)
- <span class="bn bn-pseudo">self</span>.<span class="name">forum_id</span> <span class="op">=</span> <span class="name">value</span>.<span class="name">forum_id</span>
-
- <span class="name">forum</span> <span class="op">=</span> <span class="bn">property</span>(<span class="name">forum_get</span>, <span class="name">forum_set</span>)
- <span class="kw">del</span> <span class="name">forum_get</span>, <span class="name">forum_set</span>
-
- <span class="kw">def </span><span class="fun">__eq__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">other</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="name">other</span>.<span class="name">post_id</span>
-
- <span class="kw">def </span><span class="fun">__ne__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">other</span>):
- <span class="kw">return</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">__eq__</span>(<span class="name">other</span>)
-
- <span class="kw">def </span><span class="fun">__repr__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">&lt;</span><span class="st st-int">%s</span><span class="st"> </span><span class="st st-int">%d</span><span class="st">: </span><span class="st st-int">%r</span><span class="st">&gt;</span><span class="st st-sg">&#39;</span> <span class="op">%</span> (
- <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>,
- <span class="bn bn-pseudo">self</span>.<span class="name">post_id</span>,
- <span class="bn bn-pseudo">self</span>.<span class="name">title</span>
-
- )
-<span class="cm"># -*- coding: utf-8 -*-</span>
-</pre>
-<script type="text/javascript">initCodeBlock('code-block')</script>
-</body>
-</html>
diff --git a/tests/test_examplefiles.py b/tests/test_examplefiles.py
index 93bbab16..ee9c78af 100644
--- a/tests/test_examplefiles.py
+++ b/tests/test_examplefiles.py
@@ -7,8 +7,8 @@
:license: BSD, see LICENSE for more details.
"""
-import unittest
import os
+import unittest
from pygments import highlight
from pygments.lexers import get_lexer_for_filename, get_lexer_by_name
diff --git a/tests/test_latex_formatter.py b/tests/test_latex_formatter.py
new file mode 100644
index 00000000..376abb81
--- /dev/null
+++ b/tests/test_latex_formatter.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+"""
+ Pygments LaTeX formatter tests
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ :copyright: 2006-2007 by Georg Brandl.
+ :license: BSD, see LICENSE for more details.
+"""
+
+import os
+import unittest
+import StringIO
+import tempfile
+
+from pygments import lexers, formatters
+from pygments.token import _TokenType
+from pygments.formatters import LatexFormatter
+from pygments.lexers import PythonLexer
+
+
+class LatexFormatterTest(unittest.TestCase):
+
+ def test_valid_output(self):
+ tokensource = list(PythonLexer().get_tokens(file(os.path.join(testdir, testfile)).read()))
+ fmt = LatexFormatter(full=True)
+
+ handle, pathname = tempfile.mkstemp('.tex')
+ # place all output files in /tmp too
+ old_wd = os.getcwd()
+ os.chdir(os.path.dirname(pathname))
+ tfile = os.fdopen(handle, 'w+b')
+ fmt.format(tokensource, tfile)
+ tfile.close()
+ try:
+ try:
+ import subprocess
+ ret = subprocess.Popen(['latex', '-interaction=nonstopmode', pathname],
+ stdout=subprocess.PIPE).wait()
+ except ImportError:
+ # Python 2.3 - no subprocess module
+ ret = os.popen('latex -interaction=nonstopmode "%s"' % pathname).close()
+ if ret == 32512: raise OSError # not found
+ except OSError:
+ # latex not available
+ pass
+ else:
+ self.failIf(ret, 'latex run reported errors')
+
+ os.unlink(pathname)
+ os.chdir(old_wd)