summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--pygments/lexers/__init__.py2
-rw-r--r--pygments/lexers/special.py25
-rw-r--r--tests/examplefiles/example.c20146
-rw-r--r--tests/examplefiles/example.cpp7300
-rw-r--r--tests/examplefiles/example.rb2514
-rw-r--r--tests/examplefiles/pleac.in.rb3409
-rw-r--r--tests/examplefiles/test.html3553
-rw-r--r--tests/test_basic_api.py80
-rw-r--r--tests/test_clexer.py2
10 files changed, 96 insertions, 36937 deletions
diff --git a/Makefile b/Makefile
index 86938799..daf11ed8 100644
--- a/Makefile
+++ b/Makefile
@@ -64,4 +64,4 @@ reindent:
@$(PYTHON) scripts/reindent.py -r -B .
test:
- @$(PYTHON) tests/run.py
+ @$(PYTHON) tests/run.py $(TESTS)
diff --git a/pygments/lexers/__init__.py b/pygments/lexers/__init__.py
index 3b405f88..96e68a28 100644
--- a/pygments/lexers/__init__.py
+++ b/pygments/lexers/__init__.py
@@ -91,7 +91,7 @@ def _iter_lexerclasses():
"""
Returns an iterator over all lexer classes.
"""
- for module_name, name, _, _ in LEXERS.itervalues():
+ for module_name, name, _, _, _ in LEXERS.itervalues():
if name not in _lexer_cache:
_load_lexers(module_name)
yield _lexer_cache[name]
diff --git a/pygments/lexers/special.py b/pygments/lexers/special.py
index 621145a2..dcf9899c 100644
--- a/pygments/lexers/special.py
+++ b/pygments/lexers/special.py
@@ -13,7 +13,7 @@ import re
import cStringIO
from pygments.lexer import Lexer, RegexLexer
-from pygments.token import Token, \
+from pygments.token import Token, Error, \
Text, Comment, Operator, Keyword, Name, String, Number
@@ -66,14 +66,19 @@ class RawTokenLexer(Lexer):
def get_tokens_unprocessed(self, text):
length = 0
for match in line_re.finditer(text):
- ttypestr, val = match.group().split('\t', 1)
- ttype = _ttype_cache.get(ttypestr)
- if not ttype:
- ttype = Token
- ttypes = ttypestr.split('.')[1:]
- for ttype_ in ttypes:
- ttype = getattr(ttype, ttype_)
- _ttype_cache[ttypestr] = ttype
- val = val[1:-2].decode('string-escape')
+ try:
+ ttypestr, val = match.group().split('\t', 1)
+ except ValueError:
+ val = match.group()
+ ttype = Error
+ else:
+ ttype = _ttype_cache.get(ttypestr)
+ if not ttype:
+ ttype = Token
+ ttypes = ttypestr.split('.')[1:]
+ for ttype_ in ttypes:
+ ttype = getattr(ttype, ttype_)
+ _ttype_cache[ttypestr] = ttype
+ val = val[1:-2].decode('string-escape')
yield length, ttype, val
length += len(val)
diff --git a/tests/examplefiles/example.c b/tests/examplefiles/example.c
index bbd1a75c..9f9c477d 100644
--- a/tests/examplefiles/example.c
+++ b/tests/examplefiles/example.c
@@ -9841,20149 +9841,3 @@ aix_loaderror(const char *pathname)
#endif /* NO_DLN_LOAD */
-void*
-dln_load(file)
- const char *file;
-{
-#ifdef NO_DLN_LOAD
- rb_raise(rb_eLoadError, "this executable file can't load extension libraries");
-#else
-
-#if !defined(_AIX) && !defined(NeXT)
- const char *error = 0;
-#define DLN_ERROR() (error = dln_strerror(), strcpy(ALLOCA_N(char, strlen(error) + 1), error))
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
- HINSTANCE handle;
- char winfile[MAXPATHLEN];
- void (*init_fct)();
- char *buf;
-
- if (strlen(file) >= MAXPATHLEN) rb_loaderror("filename too long");
-
- /* Load the file as an object one */
- init_funcname(&buf, file);
-
- strcpy(winfile, file);
-
- /* Load file */
- if ((handle = LoadLibrary(winfile)) == NULL) {
- error = dln_strerror();
- goto failed;
- }
-
- if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) {
- rb_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
- }
-
- /* Call the init code */
- (*init_fct)();
- return handle;
-#else
-#ifdef USE_DLN_A_OUT
- if (load(file) == -1) {
- error = dln_strerror();
- goto failed;
- }
- return 0;
-#else
-
- char *buf;
- /* Load the file as an object one */
- init_funcname(&buf, file);
-
-#ifdef USE_DLN_DLOPEN
-#define DLN_DEFINED
- {
- void *handle;
- void (*init_fct)();
-
-#ifndef RTLD_LAZY
-# define RTLD_LAZY 1
-#endif
-#ifdef __INTERIX
-# undef RTLD_GLOBAL
-#endif
-#ifndef RTLD_GLOBAL
-# define RTLD_GLOBAL 0
-#endif
-
- /* Load file */
- if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
- error = dln_strerror();
- goto failed;
- }
-
- init_fct = (void(*)())dlsym(handle, buf);
- if (init_fct == NULL) {
- error = DLN_ERROR();
- dlclose(handle);
- goto failed;
- }
- /* Call the init code */
- (*init_fct)();
-
- return handle;
- }
-#endif /* USE_DLN_DLOPEN */
-
-#ifdef __hpux
-#define DLN_DEFINED
- {
- shl_t lib = NULL;
- int flags;
- void (*init_fct)();
-
- flags = BIND_DEFERRED;
- lib = shl_load(file, flags, 0);
- if (lib == NULL) {
- extern int errno;
- rb_loaderror("%s - %s", strerror(errno), file);
- }
- shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
- if (init_fct == NULL) {
- shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
- if (init_fct == NULL) {
- errno = ENOSYM;
- rb_loaderror("%s - %s", strerror(ENOSYM), file);
- }
- }
- (*init_fct)();
- return (void*)lib;
- }
-#endif /* hpux */
-
-#if defined(_AIX) && ! defined(_IA64)
-#define DLN_DEFINED
- {
- void (*init_fct)();
-
- init_fct = (void(*)())load((char*)file, 1, 0);
- if (init_fct == NULL) {
- aix_loaderror(file);
- }
- if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
- aix_loaderror(file);
- }
- (*init_fct)();
- return (void*)init_fct;
- }
-#endif /* _AIX */
-
-#if defined(NeXT) || defined(__APPLE__)
-#define DLN_DEFINED
-/*----------------------------------------------------
- By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
-
- Special Thanks...
- Yu tomoak-i@is.aist-nara.ac.jp,
- Mi hisho@tasihara.nest.or.jp,
- sunshine@sunshineco.com,
- and... Miss ARAI Akino(^^;)
- ----------------------------------------------------*/
-#if defined(NeXT) && (NS_TARGET_MAJOR < 4)/* NeXTSTEP rld functions */
-
- {
- NXStream* s;
- unsigned long init_address;
- char *object_files[2] = {NULL, NULL};
-
- void (*init_fct)();
-
- object_files[0] = (char*)file;
-
- s = NXOpenFile(2,NX_WRITEONLY);
-
- /* Load object file, if return value ==0 , load failed*/
- if(rld_load(s, NULL, object_files, NULL) == 0) {
- NXFlush(s);
- NXClose(s);
- rb_loaderror("Failed to load %.200s", file);
- }
-
- /* lookup the initial function */
- if(rld_lookup(s, buf, &init_address) == 0) {
- NXFlush(s);
- NXClose(s);
- rb_loaderror("Failed to lookup Init function %.200s", file);
- }
-
- NXFlush(s);
- NXClose(s);
-
- /* Cannot call *init_address directory, so copy this value to
- funtion pointer */
- init_fct = (void(*)())init_address;
- (*init_fct)();
- return (void*)init_address;
- }
-#else/* OPENSTEP dyld functions */
- {
- int dyld_result;
- NSObjectFileImage obj_file; /* handle, but not use it */
- /* "file" is module file name .
- "buf" is pointer to initial function name with "_" . */
-
- void (*init_fct)();
-
-
- dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
-
- if (dyld_result != NSObjectFileImageSuccess) {
- rb_loaderror("Failed to load %.200s", file);
- }
-
- NSLinkModule(obj_file, file, NSLINKMODULE_OPTION_BINDNOW);
-
- /* lookup the initial function */
- if(!NSIsSymbolNameDefined(buf)) {
- rb_loaderror("Failed to lookup Init function %.200s",file);
- }
- init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
- (*init_fct)();
-
- return (void*)init_fct;
- }
-#endif /* rld or dyld */
-#endif
-
-#ifdef __BEOS__
-# define DLN_DEFINED
- {
- status_t err_stat; /* BeOS error status code */
- image_id img_id; /* extention module unique id */
- void (*init_fct)(); /* initialize function for extention module */
-
- /* load extention module */
- img_id = load_add_on(file);
- if (img_id <= 0) {
- rb_loaderror("Failed to load %.200s", file);
- }
-
- /* find symbol for module initialize function. */
- /* The Be Book KernelKit Images section described to use
- B_SYMBOL_TYPE_TEXT for symbol of function, not
- B_SYMBOL_TYPE_CODE. Why ? */
- /* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
- /* "__Fv" dont need! The Be Book Bug ? */
- err_stat = get_image_symbol(img_id, buf,
- B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
-
- if (err_stat != B_NO_ERROR) {
- char real_name[MAXPATHLEN];
-
- strcpy(real_name, buf);
- strcat(real_name, "__Fv");
- err_stat = get_image_symbol(img_id, real_name,
- B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
- }
-
- if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
- unload_add_on(img_id);
- rb_loaderror("Failed to lookup Init function %.200s", file);
- }
- else if (B_NO_ERROR != err_stat) {
- char errmsg[] = "Internal of BeOS version. %.200s (symbol_name = %s)";
- unload_add_on(img_id);
- rb_loaderror(errmsg, strerror(err_stat), buf);
- }
-
- /* call module initialize function. */
- (*init_fct)();
- return (void*)img_id;
- }
-#endif /* __BEOS__*/
-
-#ifdef __MACOS__
-# define DLN_DEFINED
- {
- OSErr err;
- FSSpec libspec;
- CFragConnectionID connID;
- Ptr mainAddr;
- char errMessage[1024];
- Boolean isfolder, didsomething;
- Str63 fragname;
- Ptr symAddr;
- CFragSymbolClass class;
- void (*init_fct)();
- char fullpath[MAXPATHLEN];
-
- strcpy(fullpath, file);
-
- /* resolve any aliases to find the real file */
- c2pstr(fullpath);
- (void)FSMakeFSSpec(0, 0, fullpath, &libspec);
- err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
- if (err) {
- rb_loaderror("Unresolved Alias - %s", file);
- }
-
- /* Load the fragment (or return the connID if it is already loaded */
- fragname[0] = 0;
- err = GetDiskFragment(&libspec, 0, 0, fragname,
- kLoadCFrag, &connID, &mainAddr,
- errMessage);
- if (err) {
- p2cstr(errMessage);
- rb_loaderror("%s - %s",errMessage , file);
- }
-
- /* Locate the address of the correct init function */
- c2pstr(buf);
- err = FindSymbol(connID, buf, &symAddr, &class);
- if (err) {
- rb_loaderror("Unresolved symbols - %s" , file);
- }
- init_fct = (void (*)())symAddr;
- (*init_fct)();
- return (void*)init_fct;
- }
-#endif /* __MACOS__ */
-
-#if defined(__VMS)
-#define DLN_DEFINED
- {
- void *handle, (*init_fct)();
- char *fname, *p1, *p2;
-
- fname = (char *)__alloca(strlen(file)+1);
- strcpy(fname,file);
- if (p1 = strrchr(fname,'/'))
- fname = p1 + 1;
- if (p2 = strrchr(fname,'.'))
- *p2 = '\0';
-
- if ((handle = (void*)dlopen(fname, 0)) == NULL) {
- error = dln_strerror();
- goto failed;
- }
-
- if ((init_fct = (void (*)())dlsym(handle, buf)) == NULL) {
- error = DLN_ERROR();
- dlclose(handle);
- goto failed;
- }
- /* Call the init code */
- (*init_fct)();
- return handle;
- }
-#endif /* __VMS */
-
-#ifndef DLN_DEFINED
- rb_notimplement();
-#endif
-
-#endif /* USE_DLN_A_OUT */
-#endif
-#if !defined(_AIX) && !defined(NeXT)
- failed:
- rb_loaderror("%s - %s", error, file);
-#endif
-
-#endif /* NO_DLN_LOAD */
- return 0; /* dummy return */
-}
-
-static char *dln_find_1();
-
-char *
-dln_find_exe(fname, path)
- const char *fname;
- const char *path;
-{
- if (!path) {
- path = getenv(PATH_ENV);
- }
-
- if (!path) {
-#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__MACOS__)
- path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;.";
-#else
- path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
-#endif
- }
- return dln_find_1(fname, path, 1);
-}
-
-char *
-dln_find_file(fname, path)
- const char *fname;
- const char *path;
-{
-#ifndef __MACOS__
- if (!path) path = ".";
- return dln_find_1(fname, path, 0);
-#else
- if (!path) path = ".";
- return _macruby_path_conv_posix_to_macos(dln_find_1(fname, path, 0));
-#endif
-}
-
-#if defined(__CYGWIN32__)
-const char *
-conv_to_posix_path(win32, posix, len)
- char *win32;
- char *posix;
- int len;
-{
- char *first = win32;
- char *p = win32;
- char *dst = posix;
-
- for (p = win32; *p; p++)
- if (*p == ';') {
- *p = 0;
- cygwin32_conv_to_posix_path(first, posix);
- posix += strlen(posix);
- *posix++ = ':';
- first = p + 1;
- *p = ';';
- }
- if (len < strlen(first))
- fprintf(stderr, "PATH length too long: %s\n", first);
- else
- cygwin32_conv_to_posix_path(first, posix);
- return dst;
-}
-#endif
-
-static char fbuf[MAXPATHLEN];
-
-static char *
-dln_find_1(fname, path, exe_flag)
- char *fname;
- char *path;
- int exe_flag; /* non 0 if looking for executable. */
-{
- register char *dp;
- register char *ep;
- register char *bp;
- struct stat st;
-#ifdef __MACOS__
- const char* mac_fullpath;
-#endif
-
- if (!fname) return fname;
- if (fname[0] == '/') return fname;
- if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
- return fname;
- if (exe_flag && strchr(fname, '/')) return fname;
-#ifdef DOSISH
- if (fname[0] == '\\') return fname;
-# ifdef DOSISH_DRIVE_LETTER
- if (strlen(fname) > 2 && fname[1] == ':') return fname;
-# endif
- if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
- return fname;
- if (exe_flag && strchr(fname, '\\')) return fname;
-#endif
-
- for (dp = path;; dp = ++ep) {
- register int l;
- int i;
- int fspace;
-
- /* extract a component */
- ep = strchr(dp, PATH_SEP[0]);
- if (ep == NULL)
- ep = dp+strlen(dp);
-
- /* find the length of that component */
- l = ep - dp;
- bp = fbuf;
- fspace = sizeof fbuf - 2;
- if (l > 0) {
- /*
- ** If the length of the component is zero length,
- ** start from the current directory. If the
- ** component begins with "~", start from the
- ** user's $HOME environment variable. Otherwise
- ** take the path literally.
- */
-
- if (*dp == '~' && (l == 1 ||
-#if defined(DOSISH)
- dp[1] == '\\' ||
-#endif
- dp[1] == '/')) {
- char *home;
-
- home = getenv("HOME");
- if (home != NULL) {
- i = strlen(home);
- if ((fspace -= i) < 0)
- goto toolong;
- memcpy(bp, home, i);
- bp += i;
- }
- dp++;
- l--;
- }
- if (l > 0) {
- if ((fspace -= l) < 0)
- goto toolong;
- memcpy(bp, dp, l);
- bp += l;
- }
-
- /* add a "/" between directory and filename */
- if (ep[-1] != '/')
- *bp++ = '/';
- }
-
- /* now append the file name */
- i = strlen(fname);
- if ((fspace -= i) < 0) {
- toolong:
- fprintf(stderr, "openpath: pathname too long (ignored)\n");
- *bp = '\0';
- fprintf(stderr, "\tDirectory \"%s\"\n", fbuf);
- fprintf(stderr, "\tFile \"%s\"\n", fname);
- goto next;
- }
- memcpy(bp, fname, i + 1);
-
-#ifndef __MACOS__
- if (stat(fbuf, &st) == 0) {
- if (exe_flag == 0) return fbuf;
- /* looking for executable */
- if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
- return fbuf;
- }
-#else
- if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
- if (exe_flag == 0) return mac_fullpath;
- /* looking for executable */
- if (stat(mac_fullpath, &st) == 0) {
- if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
- return mac_fullpath;
- }
- }
-#endif
-#if defined(DOSISH)
- if (exe_flag) {
- static const char *extension[] = {
-#if defined(MSDOS)
- ".com", ".exe", ".bat",
-#if defined(DJGPP)
- ".btm", ".sh", ".ksh", ".pl", ".sed",
-#endif
-#elif defined(__EMX__) || defined(_WIN32)
- ".exe", ".com", ".cmd", ".bat",
-/* end of __EMX__ or _WIN32 */
-#else
- ".r", ".R", ".x", ".X", ".bat", ".BAT",
-/* __human68k__ */
-#endif
- (char *) NULL
- };
- int j;
-
- for (j = 0; extension[j]; j++) {
- if (fspace < strlen(extension[j])) {
- fprintf(stderr, "openpath: pathname too long (ignored)\n");
- fprintf(stderr, "\tDirectory \"%.*s\"\n", (int) (bp - fbuf), fbuf);
- fprintf(stderr, "\tFile \"%s%s\"\n", fname, extension[j]);
- continue;
- }
- strcpy(bp + i, extension[j]);
-#ifndef __MACOS__
- if (stat(fbuf, &st) == 0)
- return fbuf;
-#else
- if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf))
- return mac_fullpath;
-
-#endif
- }
- }
-#endif /* MSDOS or _WIN32 or __human68k__ or __EMX__ */
-
- next:
- /* if not, and no other alternatives, life is bleak */
- if (*ep == '\0') {
- return NULL;
- }
-
- /* otherwise try the next component in the search path */
- }
-}
-#define NO_DLN_LOAD 1
-#include "dln.c"
-void
-Init_ext()
-{
-}
-/**********************************************************************
-
- enum.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Fri Oct 1 15:15:19 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "node.h"
-#include "util.h"
-
-VALUE rb_mEnumerable;
-static ID id_each, id_eqq, id_cmp;
-
-VALUE
-rb_each(obj)
- VALUE obj;
-{
- return rb_funcall(obj, id_each, 0, 0);
-}
-
-static VALUE
-grep_i(i, arg)
- VALUE i, *arg;
-{
- if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
- rb_ary_push(arg[1], i);
- }
- return Qnil;
-}
-
-static VALUE
-grep_iter_i(i, arg)
- VALUE i, *arg;
-{
- if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
- rb_ary_push(arg[1], rb_yield(i));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.grep(pattern) => array
- * enum.grep(pattern) {| obj | block } => array
- *
- * Returns an array of every element in <i>enum</i> for which
- * <code>Pattern === element</code>. If the optional <em>block</em> is
- * supplied, each matching element is passed to it, and the block's
- * result is stored in the output array.
- *
- * (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
- * c = IO.constants
- * c.grep(/SEEK/) #=> ["SEEK_END", "SEEK_SET", "SEEK_CUR"]
- * res = c.grep(/SEEK/) {|v| IO.const_get(v) }
- * res #=> [2, 0, 1]
- *
- */
-
-static VALUE
-enum_grep(obj, pat)
- VALUE obj, pat;
-{
- VALUE ary = rb_ary_new();
- VALUE arg[2];
-
- arg[0] = pat;
- arg[1] = ary;
-
- rb_iterate(rb_each, obj, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
-
- return ary;
-}
-
-static VALUE
-find_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- if (RTEST(rb_yield(i))) {
- memo->u2.value = Qtrue;
- memo->u1.value = i;
- rb_iter_break();
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.detect(ifnone = nil) {| obj | block } => obj or nil
- * enum.find(ifnone = nil) {| obj | block } => obj or nil
- *
- * Passes each entry in <i>enum</i> to <em>block</em>. Returns the
- * first for which <em>block</em> is not <code>false</code>. If no
- * object matches, calls <i>ifnone</i> and returns its result when it
- * is specified, or returns <code>nil</code>
- *
- * (1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
- * (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
- *
- */
-
-static VALUE
-enum_find(argc, argv, obj)
- int argc;
- VALUE* argv;
- VALUE obj;
-{
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, Qfalse, 0);
- VALUE if_none;
-
- rb_scan_args(argc, argv, "01", &if_none);
- rb_iterate(rb_each, obj, find_i, (VALUE)memo);
- if (memo->u2.value) {
- return memo->u1.value;
- }
- if (!NIL_P(if_none)) {
- return rb_funcall(if_none, rb_intern("call"), 0, 0);
- }
- return Qnil;
-}
-
-static VALUE
-find_all_i(i, ary)
- VALUE i, ary;
-{
- if (RTEST(rb_yield(i))) {
- rb_ary_push(ary, i);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.find_all {| obj | block } => array
- * enum.select {| obj | block } => array
- *
- * Returns an array containing all elements of <i>enum</i> for which
- * <em>block</em> is not <code>false</code> (see also
- * <code>Enumerable#reject</code>).
- *
- * (1..10).find_all {|i| i % 3 == 0 } #=> [3, 6, 9]
- *
- */
-
-static VALUE
-enum_find_all(obj)
- VALUE obj;
-{
- VALUE ary = rb_ary_new();
-
- rb_iterate(rb_each, obj, find_all_i, ary);
-
- return ary;
-}
-
-static VALUE
-reject_i(i, ary)
- VALUE i, ary;
-{
- if (!RTEST(rb_yield(i))) {
- rb_ary_push(ary, i);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.reject {| obj | block } => array
- *
- * Returns an array for all elements of <i>enum</i> for which
- * <em>block</em> is false (see also <code>Enumerable#find_all</code>).
- *
- * (1..10).reject {|i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
- *
- */
-
-static VALUE
-enum_reject(obj)
- VALUE obj;
-{
- VALUE ary = rb_ary_new();
-
- rb_iterate(rb_each, obj, reject_i, ary);
-
- return ary;
-}
-
-static VALUE
-collect_i(i, ary)
- VALUE i, ary;
-{
- rb_ary_push(ary, rb_yield(i));
-
- return Qnil;
-}
-
-static VALUE
-collect_all(i, ary)
- VALUE i, ary;
-{
- rb_ary_push(ary, i);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.collect {| obj | block } => array
- * enum.map {| obj | block } => array
- *
- * Returns a new array with the results of running <em>block</em> once
- * for every element in <i>enum</i>.
- *
- * (1..4).collect {|i| i*i } #=> [1, 4, 9, 16]
- * (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
- *
- */
-
-static VALUE
-enum_collect(obj)
- VALUE obj;
-{
- VALUE ary = rb_ary_new();
-
- rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary);
-
- return ary;
-}
-
-/*
- * call-seq:
- * enum.to_a => array
- * enum.entries => array
- *
- * Returns an array containing the items in <i>enum</i>.
- *
- * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
- * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
- */
-static VALUE
-enum_to_a(obj)
- VALUE obj;
-{
- VALUE ary = rb_ary_new();
-
- rb_iterate(rb_each, obj, collect_all, ary);
-
- return ary;
-}
-
-static VALUE
-inject_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- if (memo->u2.value) {
- memo->u2.value = Qfalse;
- memo->u1.value = i;
- }
- else {
- memo->u1.value = rb_yield_values(2, memo->u1.value, i);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.inject(initial) {| memo, obj | block } => obj
- * enum.inject {| memo, obj | block } => obj
- *
- * Combines the elements of <i>enum</i> by applying the block to an
- * accumulator value (<i>memo</i>) and each element in turn. At each
- * step, <i>memo</i> is set to the value returned by the block. The
- * first form lets you supply an initial value for <i>memo</i>. The
- * second form uses the first element of the collection as a the
- * initial value (and skips that element while iterating).
- *
- * # Sum some numbers
- * (5..10).inject {|sum, n| sum + n } #=> 45
- * # Multiply some numbers
- * (5..10).inject(1) {|product, n| product * n } #=> 151200
- *
- * # find the longest word
- * longest = %w{ cat sheep bear }.inject do |memo,word|
- * memo.length > word.length ? memo : word
- * end
- * longest #=> "sheep"
- *
- * # find the length of the longest word
- * longest = %w{ cat sheep bear }.inject(0) do |memo,word|
- * memo >= word.length ? memo : word.length
- * end
- * longest #=> 5
- *
- */
-
-static VALUE
-enum_inject(argc, argv, obj)
- int argc;
- VALUE *argv, obj;
-{
- NODE *memo;
- VALUE n;
-
- if (rb_scan_args(argc, argv, "01", &n) == 1) {
- memo = rb_node_newnode(NODE_MEMO, n, Qfalse, 0);
- }
- else {
- memo = rb_node_newnode(NODE_MEMO, Qnil, Qtrue, 0);
- }
- rb_iterate(rb_each, obj, inject_i, (VALUE)memo);
- n = memo->u1.value;
- return n;
-}
-
-static VALUE
-partition_i(i, ary)
- VALUE i, *ary;
-{
- if (RTEST(rb_yield(i))) {
- rb_ary_push(ary[0], i);
- }
- else {
- rb_ary_push(ary[1], i);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.partition {| obj | block } => [ true_array, false_array ]
- *
- * Returns two arrays, the first containing the elements of
- * <i>enum</i> for which the block evaluates to true, the second
- * containing the rest.
- *
- * (1..6).partition {|i| (i&1).zero?} #=> [[2, 4, 6], [1, 3, 5]]
- *
- */
-
-static VALUE
-enum_partition(obj)
- VALUE obj;
-{
- VALUE ary[2];
-
- ary[0] = rb_ary_new();
- ary[1] = rb_ary_new();
- rb_iterate(rb_each, obj, partition_i, (VALUE)ary);
-
- return rb_assoc_new(ary[0], ary[1]);
-}
-
-/*
- * call-seq:
- * enum.sort => array
- * enum.sort {| a, b | block } => array
- *
- * Returns an array containing the items in <i>enum</i> sorted,
- * either according to their own <code><=></code> method, or by using
- * the results of the supplied block. The block should return -1, 0, or
- * +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
- * Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
- * built-in Schwartzian Transform, useful when key computation or
- * comparison is expensive..
- *
- * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
- * (1..10).sort {|a,b| b <=> a} #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
- */
-
-static VALUE
-enum_sort(obj)
- VALUE obj;
-{
- return rb_ary_sort(enum_to_a(obj));
-}
-
-static VALUE
-sort_by_i(i, ary)
- VALUE i, ary;
-{
- VALUE v;
- NODE *memo;
-
- v = rb_yield(i);
- if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort_by reentered");
- }
- memo = rb_node_newnode(NODE_MEMO, v, i, 0);
- rb_ary_push(ary, (VALUE)memo);
- return Qnil;
-}
-
-static int
-sort_by_cmp(aa, bb)
- NODE **aa, **bb;
-{
- VALUE a = aa[0]->u1.value;
- VALUE b = bb[0]->u1.value;
-
- return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
-}
-
-/*
- * call-seq:
- * enum.sort_by {| obj | block } => array
- *
- * Sorts <i>enum</i> using a set of keys generated by mapping the
- * values in <i>enum</i> through the given block.
- *
- * %w{ apple pear fig }.sort_by {|word| word.length}
- #=> ["fig", "pear", "apple"]
- *
- * The current implementation of <code>sort_by</code> generates an
- * array of tuples containing the original collection element and the
- * mapped value. This makes <code>sort_by</code> fairly expensive when
- * the keysets are simple
- *
- * require 'benchmark'
- * include Benchmark
- *
- * a = (1..100000).map {rand(100000)}
- *
- * bm(10) do |b|
- * b.report("Sort") { a.sort }
- * b.report("Sort by") { a.sort_by {|a| a} }
- * end
- *
- * <em>produces:</em>
- *
- * user system total real
- * Sort 0.180000 0.000000 0.180000 ( 0.175469)
- * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
- *
- * However, consider the case where comparing the keys is a non-trivial
- * operation. The following code sorts some files on modification time
- * using the basic <code>sort</code> method.
- *
- * files = Dir["*"]
- * sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
- * sorted #=> ["mon", "tues", "wed", "thurs"]
- *
- * This sort is inefficient: it generates two new <code>File</code>
- * objects during every comparison. A slightly better technique is to
- * use the <code>Kernel#test</code> method to generate the modification
- * times directly.
- *
- * files = Dir["*"]
- * sorted = files.sort { |a,b|
- * test(?M, a) <=> test(?M, b)
- * }
- * sorted #=> ["mon", "tues", "wed", "thurs"]
- *
- * This still generates many unnecessary <code>Time</code> objects. A
- * more efficient technique is to cache the sort keys (modification
- * times in this case) before the sort. Perl users often call this
- * approach a Schwartzian Transform, after Randal Schwartz. We
- * construct a temporary array, where each element is an array
- * containing our sort key along with the filename. We sort this array,
- * and then extract the filename from the result.
- *
- * sorted = Dir["*"].collect { |f|
- * [test(?M, f), f]
- * }.sort.collect { |f| f[1] }
- * sorted #=> ["mon", "tues", "wed", "thurs"]
- *
- * This is exactly what <code>sort_by</code> does internally.
- *
- * sorted = Dir["*"].sort_by {|f| test(?M, f)}
- * sorted #=> ["mon", "tues", "wed", "thurs"]
- */
-
-static VALUE
-enum_sort_by(obj)
- VALUE obj;
-{
- VALUE ary;
- long i;
-
- if (TYPE(obj) == T_ARRAY) {
- ary = rb_ary_new2(RARRAY(obj)->len);
- }
- else {
- ary = rb_ary_new();
- }
- RBASIC(ary)->klass = 0;
- rb_iterate(rb_each, obj, sort_by_i, ary);
- if (RARRAY(ary)->len > 1) {
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp, 0);
- }
- if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort_by reentered");
- }
- for (i=0; i<RARRAY(ary)->len; i++) {
- RARRAY(ary)->ptr[i] = RNODE(RARRAY(ary)->ptr[i])->u2.value;
- }
- RBASIC(ary)->klass = rb_cArray;
- return ary;
-}
-
-static VALUE
-all_iter_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- if (!RTEST(rb_yield(i))) {
- memo->u1.value = Qfalse;
- rb_iter_break();
- }
- return Qnil;
-}
-
-static VALUE
-all_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- if (!RTEST(i)) {
- memo->u1.value = Qfalse;
- rb_iter_break();
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.all? [{|obj| block } ] => true or false
- *
- * Passes each element of the collection to the given block. The method
- * returns <code>true</code> if the block never returns
- * <code>false</code> or <code>nil</code>. If the block is not given,
- * Ruby adds an implicit block of <code>{|obj| obj}</code> (that is
- * <code>all?</code> will return <code>true</code> only if none of the
- * collection members are <code>false</code> or <code>nil</code>.)
- *
- * %w{ ant bear cat}.all? {|word| word.length >= 3} #=> true
- * %w{ ant bear cat}.all? {|word| word.length >= 4} #=> false
- * [ nil, true, 99 ].all? #=> false
- *
- */
-
-static VALUE
-enum_all(obj)
- VALUE obj;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-
- memo->u1.value = Qtrue;
- rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)memo);
- result = memo->u1.value;
- return result;
-}
-
-static VALUE
-any_iter_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- if (RTEST(rb_yield(i))) {
- memo->u1.value = Qtrue;
- rb_iter_break();
- }
- return Qnil;
-}
-
-static VALUE
-any_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- if (RTEST(i)) {
- memo->u1.value = Qtrue;
- rb_iter_break();
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.any? [{|obj| block } ] => true or false
- *
- * Passes each element of the collection to the given block. The method
- * returns <code>true</code> if the block ever returns a value other
- * that <code>false</code> or <code>nil</code>. If the block is not
- * given, Ruby adds an implicit block of <code>{|obj| obj}</code> (that
- * is <code>any?</code> will return <code>true</code> if at least one
- * of the collection members is not <code>false</code> or
- * <code>nil</code>.
- *
- * %w{ ant bear cat}.any? {|word| word.length >= 3} #=> true
- * %w{ ant bear cat}.any? {|word| word.length >= 4} #=> true
- * [ nil, true, 99 ].any? #=> true
- *
- */
-
-static VALUE
-enum_any(obj)
- VALUE obj;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-
- memo->u1.value = Qfalse;
- rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)memo);
- result = memo->u1.value;
- return result;
-}
-
-static VALUE
-min_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- VALUE cmp;
-
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
- }
- else {
- cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
- memo->u1.value = i;
- }
- }
- return Qnil;
-}
-
-static VALUE
-min_ii(i, memo)
- VALUE i;
- NODE *memo;
-{
- VALUE cmp;
-
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
- }
- else {
- cmp = rb_yield_values(2, i, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
- memo->u1.value = i;
- }
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * enum.min => obj
- * enum.min {| a,b | block } => obj
- *
- * Returns the object in <i>enum</i> with the minimum value. The
- * first form assumes all objects implement <code>Comparable</code>;
- * the second uses the block to return <em>a <=> b</em>.
- *
- * a = %w(albatross dog horse)
- * a.min #=> "albatross"
- * a.min {|a,b| a.length <=> b.length } #=> "dog"
- */
-
-static VALUE
-enum_min(obj)
- VALUE obj;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-
- rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)memo);
- result = memo->u1.value;
- return result;
-}
-
-static VALUE
-max_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- VALUE cmp;
-
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
- }
- else {
- cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
- memo->u1.value = i;
- }
- }
- return Qnil;
-}
-
-static VALUE
-max_ii(i, memo)
- VALUE i;
- NODE *memo;
-{
- VALUE cmp;
-
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = i;
- }
- else {
- cmp = rb_yield_values(2, i, memo->u1.value);
- if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
- memo->u1.value = i;
- }
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.max => obj
- * enum.max {|a,b| block } => obj
- *
- * Returns the object in _enum_ with the maximum value. The
- * first form assumes all objects implement <code>Comparable</code>;
- * the second uses the block to return <em>a <=> b</em>.
- *
- * a = %w(albatross dog horse)
- * a.max #=> "horse"
- * a.max {|a,b| a.length <=> b.length } #=> "albatross"
- */
-
-static VALUE
-enum_max(obj)
- VALUE obj;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-
- rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)memo);
- result = memo->u1.value;
- return result;
-}
-
-static VALUE
-min_by_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- VALUE v;
-
- v = rb_yield(i);
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = v;
- memo->u2.value = i;
- }
- else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) {
- memo->u1.value = v;
- memo->u2.value = i;
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.min_by {| obj| block } => obj
- *
- * Returns the object in <i>enum</i> that gives the minimum
- * value from the given block.
- *
- * a = %w(albatross dog horse)
- * a.min_by {|x| x.length } #=> "dog"
- */
-
-static VALUE
-enum_min_by(obj)
- VALUE obj;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-
- rb_iterate(rb_each, obj, min_by_i, (VALUE)memo);
- result = memo->u2.value;
- return result;
-}
-
-static VALUE
-max_by_i(i, memo)
- VALUE i;
- NODE *memo;
-{
- VALUE v;
-
- v = rb_yield(i);
- if (NIL_P(memo->u1.value)) {
- memo->u1.value = v;
- memo->u2.value = i;
- }
- else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) {
- memo->u1.value = v;
- memo->u2.value = i;
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.max_by {| obj| block } => obj
- *
- * Returns the object in <i>enum</i> that gives the maximum
- * value from the given block.
- *
- * a = %w(albatross dog horse)
- * a.max_by {|x| x.length } #=> "albatross"
- */
-
-static VALUE
-enum_max_by(obj)
- VALUE obj;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-
- rb_iterate(rb_each, obj, max_by_i, (VALUE)memo);
- result = memo->u2.value;
- return result;
-}
-
-static VALUE
-member_i(item, memo)
- VALUE item;
- NODE *memo;
-{
- if (rb_equal(item, memo->u1.value)) {
- memo->u2.value = Qtrue;
- rb_iter_break();
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.include?(obj) => true or false
- * enum.member?(obj) => true or false
- *
- * Returns <code>true</code> if any member of <i>enum</i> equals
- * <i>obj</i>. Equality is tested using <code>==</code>.
- *
- * IO.constants.include? "SEEK_SET" #=> true
- * IO.constants.include? "SEEK_NO_FURTHER" #=> false
- *
- */
-
-static VALUE
-enum_member(obj, val)
- VALUE obj, val;
-{
- VALUE result;
- NODE *memo = rb_node_newnode(NODE_MEMO, val, Qfalse, 0);
-
- rb_iterate(rb_each, obj, member_i, (VALUE)memo);
- result = memo->u2.value;
- return result;
-}
-
-static VALUE
-each_with_index_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- rb_yield_values(2, val, INT2FIX(memo->u3.cnt));
- memo->u3.cnt++;
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.each_with_index {|obj, i| block } -> enum
- *
- * Calls <em>block</em> with two arguments, the item and its index, for
- * each item in <i>enum</i>.
- *
- * hash = Hash.new
- * %w(cat dog wombat).each_with_index {|item, index|
- * hash[item] = index
- * }
- * hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
- *
- */
-
-static VALUE
-enum_each_with_index(obj)
- VALUE obj;
-{
- NODE *memo = rb_node_newnode(NODE_MEMO, 0, 0, 0);
-
- rb_iterate(rb_each, obj, each_with_index_i, (VALUE)memo);
- return obj;
-}
-
-static VALUE
-zip_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE result = memo->u1.value;
- VALUE args = memo->u2.value;
- int idx = memo->u3.cnt++;
- VALUE tmp;
- int i;
-
- tmp = rb_ary_new2(RARRAY(args)->len + 1);
- rb_ary_store(tmp, 0, val);
- for (i=0; i<RARRAY(args)->len; i++) {
- rb_ary_push(tmp, rb_ary_entry(RARRAY(args)->ptr[i], idx));
- }
- if (rb_block_given_p()) {
- rb_yield(tmp);
- }
- else {
- rb_ary_push(result, tmp);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * enum.zip(arg, ...) => array
- * enum.zip(arg, ...) {|arr| block } => nil
- *
- * Converts any arguments to arrays, then merges elements of
- * <i>enum</i> with corresponding elements from each argument. This
- * generates a sequence of <code>enum#size</code> <em>n</em>-element
- * arrays, where <em>n</em> is one more that the count of arguments. If
- * the size of any argument is less than <code>enum#size</code>,
- * <code>nil</code> values are supplied. If a block given, it is
- * invoked for each output array, otherwise an array of arrays is
- * returned.
- *
- * a = [ 4, 5, 6 ]
- * b = [ 7, 8, 9 ]
- *
- * (1..3).zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- * "cat\ndog".zip([1]) #=> [["cat\n", 1], ["dog", nil]]
- * (1..3).zip #=> [[1], [2], [3]]
- *
- */
-
-static VALUE
-enum_zip(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- int i;
- VALUE result;
- NODE *memo;
-
- for (i=0; i<argc; i++) {
- argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_a");
- }
- result = rb_block_given_p() ? Qnil : rb_ary_new();
- memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0);
- rb_iterate(rb_each, obj, zip_i, (VALUE)memo);
-
- return result;
-}
-
-/*
- * The <code>Enumerable</code> mixin provides collection classes with
- * several traversal and searching methods, and with the ability to
- * sort. The class must provide a method <code>each</code>, which
- * yields successive members of the collection. If
- * <code>Enumerable#max</code>, <code>#min</code>, or
- * <code>#sort</code> is used, the objects in the collection must also
- * implement a meaningful <code><=></code> operator, as these methods
- * rely on an ordering between members of the collection.
- */
-
-void
-Init_Enumerable()
-{
- rb_mEnumerable = rb_define_module("Enumerable");
-
- rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
- rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
-
- rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
- rb_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
- rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
- rb_define_method(rb_mEnumerable,"find", enum_find, -1);
- rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
- rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
- rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
- rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
- rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
- rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
- rb_define_method(rb_mEnumerable,"inject", enum_inject, -1);
- rb_define_method(rb_mEnumerable,"partition", enum_partition, 0);
- rb_define_method(rb_mEnumerable,"all?", enum_all, 0);
- rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
- rb_define_method(rb_mEnumerable,"min", enum_min, 0);
- rb_define_method(rb_mEnumerable,"max", enum_max, 0);
- rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0);
- rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0);
- rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
- rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
- rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
- rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
-
- id_eqq = rb_intern("===");
- id_each = rb_intern("each");
- id_cmp = rb_intern("<=>");
-}
-
-/**********************************************************************
-
- error.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Mon Aug 9 16:11:34 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby.h"
-#include "env.h"
-#include "st.h"
-
-#include <stdio.h>
-#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
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-
-extern const char ruby_version[], ruby_release_date[], ruby_platform[];
-
-int ruby_nerrs;
-
-static int
-err_position(buf, len)
- char *buf;
- long len;
-{
- ruby_set_current_source();
- if (!ruby_sourcefile) {
- return 0;
- }
- else if (ruby_sourceline == 0) {
- return snprintf(buf, len, "%s: ", ruby_sourcefile);
- }
- else {
- return snprintf(buf, len, "%s:%d: ", ruby_sourcefile, ruby_sourceline);
- }
-}
-
-static void
-err_snprintf(buf, len, fmt, args)
- char *buf;
- long len;
- const char *fmt;
- va_list args;
-{
- long n;
-
- n = err_position(buf, len);
- if (len > n) {
- vsnprintf((char*)buf+n, len-n, fmt, args);
- }
-}
-
-static void err_append _((const char*));
-static void
-err_print(fmt, args)
- const char *fmt;
- va_list args;
-{
- char buf[BUFSIZ];
-
- err_snprintf(buf, BUFSIZ, fmt, args);
- err_append(buf);
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_compile_error(const char *fmt, ...)
-#else
-rb_compile_error(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
-
- va_init_list(args, fmt);
- err_print(fmt, args);
- va_end(args);
- ruby_nerrs++;
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_compile_error_append(const char *fmt, ...)
-#else
-rb_compile_error_append(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- char buf[BUFSIZ];
-
- va_init_list(args, fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
- err_append(buf);
-}
-
-static void
-warn_print(fmt, args)
- const char *fmt;
- va_list args;
-{
- char buf[BUFSIZ];
- int len;
-
- err_snprintf(buf, BUFSIZ, fmt, args);
- len = strlen(buf);
- buf[len++] = '\n';
- rb_write_error2(buf, len);
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_warn(const char *fmt, ...)
-#else
-rb_warn(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- char buf[BUFSIZ];
- va_list args;
-
- if (NIL_P(ruby_verbose)) return;
-
- snprintf(buf, BUFSIZ, "warning: %s", fmt);
-
- va_init_list(args, fmt);
- warn_print(buf, args);
- va_end(args);
-}
-
-/* rb_warning() reports only in verbose mode */
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_warning(const char *fmt, ...)
-#else
-rb_warning(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- char buf[BUFSIZ];
- va_list args;
-
- if (!RTEST(ruby_verbose)) return;
-
- snprintf(buf, BUFSIZ, "warning: %s", fmt);
-
- va_init_list(args, fmt);
- warn_print(buf, args);
- va_end(args);
-}
-
-/*
- * call-seq:
- * warn(msg) => nil
- *
- * Display the given message (followed by a newline) on STDERR unless
- * warnings are disabled (for example with the <code>-W0</code> flag).
- */
-
-static VALUE
-rb_warn_m(self, mesg)
- VALUE self, mesg;
-{
- if (!NIL_P(ruby_verbose)) {
- rb_io_write(rb_stderr, mesg);
- rb_io_write(rb_stderr, rb_default_rs);
- }
- return Qnil;
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_bug(const char *fmt, ...)
-#else
-rb_bug(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- char buf[BUFSIZ];
- va_list args;
- FILE *out = stderr;
- int len = err_position(buf, BUFSIZ);
-
- if (fwrite(buf, 1, len, out) == len ||
- fwrite(buf, 1, len, (out = stdout)) == len) {
- fputs("[BUG] ", out);
- va_init_list(args, fmt);
- vfprintf(out, fmt, args);
- va_end(args);
- fprintf(out, "\nruby %s (%s) [%s]\n\n",
- ruby_version, ruby_release_date, ruby_platform);
- }
- abort();
-}
-
-static struct types {
- int type;
- const char *name;
-} builtin_types[] = {
- {T_NIL, "nil"},
- {T_OBJECT, "Object"},
- {T_CLASS, "Class"},
- {T_ICLASS, "iClass"}, /* internal use: mixed-in module holder */
- {T_MODULE, "Module"},
- {T_FLOAT, "Float"},
- {T_STRING, "String"},
- {T_REGEXP, "Regexp"},
- {T_ARRAY, "Array"},
- {T_FIXNUM, "Fixnum"},
- {T_HASH, "Hash"},
- {T_STRUCT, "Struct"},
- {T_BIGNUM, "Bignum"},
- {T_FILE, "File"},
- {T_TRUE, "true"},
- {T_FALSE, "false"},
- {T_SYMBOL, "Symbol"}, /* :symbol */
- {T_DATA, "Data"}, /* internal use: wrapped C pointers */
- {T_MATCH, "MatchData"}, /* data of $~ */
- {T_VARMAP, "Varmap"}, /* internal use: dynamic variables */
- {T_SCOPE, "Scope"}, /* internal use: variable scope */
- {T_NODE, "Node"}, /* internal use: syntax tree node */
- {T_UNDEF, "undef"}, /* internal use: #undef; should not happen */
- {-1, 0}
-};
-
-void
-rb_check_type(x, t)
- VALUE x;
- int t;
-{
- struct types *type = builtin_types;
-
- if (x == Qundef) {
- rb_bug("undef leaked to the Ruby space");
- }
-
- if (TYPE(x) != t) {
- while (type->type >= 0) {
- if (type->type == t) {
- char *etype;
-
- if (NIL_P(x)) {
- etype = "nil";
- }
- else if (FIXNUM_P(x)) {
- etype = "Fixnum";
- }
- else if (SYMBOL_P(x)) {
- etype = "Symbol";
- }
- else if (rb_special_const_p(x)) {
- etype = RSTRING(rb_obj_as_string(x))->ptr;
- }
- else {
- etype = rb_obj_classname(x);
- }
- rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
- etype, type->name);
- }
- type++;
- }
- rb_bug("unknown type 0x%x (0x%x given)", t, TYPE(x));
- }
-}
-
-/* exception classes */
-#include <errno.h>
-
-VALUE rb_eException;
-VALUE rb_eSystemExit;
-VALUE rb_eInterrupt;
-VALUE rb_eSignal;
-VALUE rb_eFatal;
-VALUE rb_eStandardError;
-VALUE rb_eRuntimeError;
-VALUE rb_eTypeError;
-VALUE rb_eArgError;
-VALUE rb_eIndexError;
-VALUE rb_eKeyError;
-VALUE rb_eRangeError;
-VALUE rb_eNameError;
-VALUE rb_eNoMethodError;
-VALUE rb_eSecurityError;
-VALUE rb_eNotImpError;
-VALUE rb_eNoMemError;
-static VALUE rb_cNameErrorMesg;
-
-VALUE rb_eScriptError;
-VALUE rb_eSyntaxError;
-VALUE rb_eLoadError;
-
-VALUE rb_eSystemCallError;
-VALUE rb_mErrno;
-static VALUE eNOERROR;
-
-VALUE
-rb_exc_new(etype, ptr, len)
- VALUE etype;
- const char *ptr;
- long len;
-{
- return rb_funcall(etype, rb_intern("new"), 1, rb_str_new(ptr, len));
-}
-
-VALUE
-rb_exc_new2(etype, s)
- VALUE etype;
- const char *s;
-{
- return rb_exc_new(etype, s, strlen(s));
-}
-
-VALUE
-rb_exc_new3(etype, str)
- VALUE etype, str;
-{
- StringValue(str);
- return rb_funcall(etype, rb_intern("new"), 1, str);
-}
-
-/*
- * call-seq:
- * Exception.new(msg = nil) => exception
- *
- * Construct a new Exception object, optionally passing in
- * a message.
- */
-
-static VALUE
-exc_initialize(argc, argv, exc)
- int argc;
- VALUE *argv;
- VALUE exc;
-{
- VALUE arg;
-
- rb_scan_args(argc, argv, "01", &arg);
- rb_iv_set(exc, "mesg", arg);
- rb_iv_set(exc, "bt", Qnil);
-
- return exc;
-}
-
-/*
- * Document-method: exception
- *
- * call-seq:
- * exc.exception(string) -> an_exception or exc
- *
- * With no argument, or if the argument is the same as the receiver,
- * return the receiver. Otherwise, create a new
- * exception object of the same class as the receiver, but with a
- * message equal to <code>string.to_str</code>.
- *
- */
-
-static VALUE
-exc_exception(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE exc;
-
- if (argc == 0) return self;
- if (argc == 1 && self == argv[0]) return self;
- exc = rb_obj_clone(self);
- exc_initialize(argc, argv, exc);
-
- return exc;
-}
-
-/*
- * call-seq:
- * exception.to_s => string
- *
- * Returns exception's message (or the name of the exception if
- * no message is set).
- */
-
-static VALUE
-exc_to_s(exc)
- VALUE exc;
-{
- VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
-
- if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
- if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
- return mesg;
-}
-
-/*
- * call-seq:
- * exception.message => string
- *
- * Returns the result of invoking <code>exception.to_s</code>.
- * Normally this returns the exception's message or name. By
- * supplying a to_str method, exceptions are agreeing to
- * be used where Strings are expected.
- */
-
-static VALUE
-exc_message(exc)
- VALUE exc;
-{
- return rb_funcall(exc, rb_intern("to_s"), 0, 0);
-}
-
-/*
- * call-seq:
- * exception.inspect => string
- *
- * Return this exception's class name an message
- */
-
-static VALUE
-exc_inspect(exc)
- VALUE exc;
-{
- VALUE str, klass;
-
- klass = CLASS_OF(exc);
- exc = rb_obj_as_string(exc);
- if (RSTRING(exc)->len == 0) {
- return rb_str_dup(rb_class_name(klass));
- }
-
- str = rb_str_buf_new2("#<");
- klass = rb_class_name(klass);
- rb_str_buf_append(str, klass);
- rb_str_buf_cat(str, ": ", 2);
- rb_str_buf_append(str, exc);
- rb_str_buf_cat(str, ">", 1);
-
- return str;
-}
-
-/*
- * call-seq:
- * exception.backtrace => array
- *
- * Returns any backtrace associated with the exception. The backtrace
- * is an array of strings, each containing either ``filename:lineNo: in
- * `method''' or ``filename:lineNo.''
- *
- * def a
- * raise "boom"
- * end
- *
- * def b
- * a()
- * end
- *
- * begin
- * b()
- * rescue => detail
- * print detail.backtrace.join("\n")
- * end
- *
- * <em>produces:</em>
- *
- * prog.rb:2:in `a'
- * prog.rb:6:in `b'
- * prog.rb:10
-*/
-
-static VALUE
-exc_backtrace(exc)
- VALUE exc;
-{
- ID bt = rb_intern("bt");
-
- if (!rb_ivar_defined(exc, bt)) return Qnil;
- return rb_ivar_get(exc, bt);
-}
-
-static VALUE
-check_backtrace(bt)
- VALUE bt;
-{
- long i;
- static char *err = "backtrace must be Array of String";
-
- if (!NIL_P(bt)) {
- int t = TYPE(bt);
-
- if (t == T_STRING) return rb_ary_new3(1, bt);
- if (t != T_ARRAY) {
- rb_raise(rb_eTypeError, err);
- }
- for (i=0;i<RARRAY(bt)->len;i++) {
- if (TYPE(RARRAY(bt)->ptr[i]) != T_STRING) {
- rb_raise(rb_eTypeError, err);
- }
- }
- }
- return bt;
-}
-
-/*
- * call-seq:
- * exc.set_backtrace(array) => array
- *
- * Sets the backtrace information associated with <i>exc</i>. The
- * argument must be an array of <code>String</code> objects in the
- * format described in <code>Exception#backtrace</code>.
- *
- */
-
-static VALUE
-exc_set_backtrace(exc, bt)
- VALUE exc;
- VALUE bt;
-{
- return rb_iv_set(exc, "bt", check_backtrace(bt));
-}
-
-/*
- * call-seq:
- * exc == obj => true or false
- *
- * Equality---If <i>obj</i> is not an <code>Exception</code>, returns
- * <code>false</code>. Otherwise, returns <code>true</code> if <i>exc</i> and
- * <i>obj</i> share same class, messages, and backtrace.
- */
-
-static VALUE
-exc_equal(exc, obj)
- VALUE exc;
- VALUE obj;
-{
- ID id_mesg = rb_intern("mesg");
-
- if (exc == obj) return Qtrue;
- if (rb_obj_class(exc) != rb_obj_class(obj))
- return Qfalse;
- if (!rb_equal(rb_attr_get(exc, id_mesg), rb_attr_get(obj, id_mesg)))
- return Qfalse;
- if (!rb_equal(exc_backtrace(exc), exc_backtrace(obj)))
- return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * SystemExit.new(status=0) => system_exit
- *
- * Create a new +SystemExit+ exception with the given status.
- */
-
-static VALUE
-exit_initialize(argc, argv, exc)
- int argc;
- VALUE *argv;
- VALUE exc;
-{
- VALUE status = INT2FIX(EXIT_SUCCESS);
- if (argc > 0 && FIXNUM_P(argv[0])) {
- status = *argv++;
- --argc;
- }
- exc_initialize(argc, argv, exc);
- rb_iv_set(exc, "status", status);
- return exc;
-}
-
-
-/*
- * call-seq:
- * system_exit.status => fixnum
- *
- * Return the status value associated with this system exit.
- */
-
-static VALUE
-exit_status(exc)
- VALUE exc;
-{
- return rb_attr_get(exc, rb_intern("status"));
-}
-
-
-/*
- * call-seq:
- * system_exit.success? => true or false
- *
- * Returns +true+ if exiting successful, +false+ if not.
- */
-
-static VALUE
-exit_success_p(exc)
- VALUE exc;
-{
- VALUE status = rb_attr_get(exc, rb_intern("status"));
- if (NIL_P(status)) return Qtrue;
- if (status == INT2FIX(EXIT_SUCCESS)) return Qtrue;
- return Qfalse;
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_name_error(ID id, const char *fmt, ...)
-#else
-rb_name_error(id, fmt, va_alist)
- ID id;
- const char *fmt;
- va_dcl
-#endif
-{
- VALUE exc, argv[2];
- va_list args;
- char buf[BUFSIZ];
-
- va_init_list(args, fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
-
- argv[0] = rb_str_new2(buf);
- argv[1] = ID2SYM(id);
- exc = rb_class_new_instance(2, argv, rb_eNameError);
- rb_exc_raise(exc);
-}
-
-/*
- * call-seq:
- * NameError.new(msg [, name]) => name_error
- *
- * Construct a new NameError exception. If given the <i>name</i>
- * parameter may subsequently be examined using the <code>NameError.name</code>
- * method.
- */
-
-static VALUE
-name_err_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE name;
-
- name = (argc > 1) ? argv[--argc] : Qnil;
- exc_initialize(argc, argv, self);
- rb_iv_set(self, "name", name);
- return self;
-}
-
-/*
- * call-seq:
- * name_error.name => string or nil
- *
- * Return the name associated with this NameError exception.
- */
-
-static VALUE
-name_err_name(self)
- VALUE self;
-{
- return rb_attr_get(self, rb_intern("name"));
-}
-
-/*
- * call-seq:
- * name_error.to_s => string
- *
- * Produce a nicely-formated string representing the +NameError+.
- */
-
-static VALUE
-name_err_to_s(exc)
- VALUE exc;
-{
- VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
- VALUE str = mesg;
-
- if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
- StringValue(str);
- if (str != mesg) {
- rb_iv_set(exc, "mesg", mesg = str);
- }
- if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
- return mesg;
-}
-
-/*
- * call-seq:
- * NoMethodError.new(msg, name [, args]) => no_method_error
- *
- * Construct a NoMethodError exception for a method of the given name
- * called with the given arguments. The name may be accessed using
- * the <code>#name</code> method on the resulting object, and the
- * arguments using the <code>#args</code> method.
- */
-
-static VALUE
-nometh_err_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE args = (argc > 2) ? argv[--argc] : Qnil;
- name_err_initialize(argc, argv, self);
- rb_iv_set(self, "args", args);
- return self;
-}
-
-/* :nodoc: */
-static void
-name_err_mesg_mark(ptr)
- VALUE *ptr;
-{
- rb_gc_mark_locations(ptr, ptr+3);
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_new(obj, mesg, recv, method)
- VALUE obj, mesg, recv, method;
-{
- VALUE *ptr = ALLOC_N(VALUE, 3);
-
- ptr[0] = mesg;
- ptr[1] = recv;
- ptr[2] = method;
- return Data_Wrap_Struct(rb_cNameErrorMesg, name_err_mesg_mark, -1, ptr);
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_equal(obj1, obj2)
- VALUE obj1, obj2;
-{
- VALUE *ptr1, *ptr2;
- int i;
-
- if (obj1 == obj2) return Qtrue;
- if (rb_obj_class(obj2) != rb_cNameErrorMesg)
- return Qfalse;
-
- Data_Get_Struct(obj1, VALUE, ptr1);
- Data_Get_Struct(obj2, VALUE, ptr2);
- for (i=0; i<3; i++) {
- if (!rb_equal(ptr1[i], ptr2[i]))
- return Qfalse;
- }
- return Qtrue;
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_to_str(obj)
- VALUE obj;
-{
- VALUE *ptr, mesg;
- Data_Get_Struct(obj, VALUE, ptr);
-
- mesg = ptr[0];
- if (NIL_P(mesg)) return Qnil;
- else {
- char *desc = 0;
- VALUE d = 0, args[3];
-
- obj = ptr[1];
- switch (TYPE(obj)) {
- case T_NIL:
- desc = "nil";
- break;
- case T_TRUE:
- desc = "true";
- break;
- case T_FALSE:
- desc = "false";
- break;
- default:
- d = rb_protect(rb_inspect, obj, 0);
- if (NIL_P(d) || RSTRING(d)->len > 65) {
- d = rb_any_to_s(obj);
- }
- desc = RSTRING(d)->ptr;
- break;
- }
- if (desc && desc[0] != '#') {
- d = rb_str_new2(desc);
- rb_str_cat2(d, ":");
- rb_str_cat2(d, rb_obj_classname(obj));
- }
- args[0] = mesg;
- args[1] = ptr[2];
- args[2] = d;
- mesg = rb_f_sprintf(3, args);
- }
- if (OBJ_TAINTED(obj)) OBJ_TAINT(mesg);
- return mesg;
-}
-
-/* :nodoc: */
-static VALUE
-name_err_mesg_load(klass, str)
- VALUE klass, str;
-{
- return str;
-}
-
-/*
- * call-seq:
- * no_method_error.args => obj
- *
- * Return the arguments passed in as the third parameter to
- * the constructor.
- */
-
-static VALUE
-nometh_err_args(self)
- VALUE self;
-{
- return rb_attr_get(self, rb_intern("args"));
-}
-
-void
-rb_invalid_str(str, type)
- const char *str, *type;
-{
- VALUE s = rb_str_inspect(rb_str_new2(str));
-
- rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING(s)->ptr);
-}
-
-/*
- * Document-module: Errno
- *
- * Ruby exception objects are subclasses of <code>Exception</code>.
- * However, operating systems typically report errors using plain
- * integers. Module <code>Errno</code> is created dynamically to map
- * these operating system errors to Ruby classes, with each error
- * number generating its own subclass of <code>SystemCallError</code>.
- * As the subclass is created in module <code>Errno</code>, its name
- * will start <code>Errno::</code>.
- *
- * The names of the <code>Errno::</code> classes depend on
- * the environment in which Ruby runs. On a typical Unix or Windows
- * platform, there are <code>Errno</code> classes such as
- * <code>Errno::EACCES</code>, <code>Errno::EAGAIN</code>,
- * <code>Errno::EINTR</code>, and so on.
- *
- * The integer operating system error number corresponding to a
- * particular error is available as the class constant
- * <code>Errno::</code><em>error</em><code>::Errno</code>.
- *
- * Errno::EACCES::Errno #=> 13
- * Errno::EAGAIN::Errno #=> 11
- * Errno::EINTR::Errno #=> 4
- *
- * The full list of operating system errors on your particular platform
- * are available as the constants of <code>Errno</code>.
- *
- * Errno.constants #=> E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL, ...
- */
-
-static st_table *syserr_tbl;
-
-static VALUE
-set_syserr(n, name)
- int n;
- const char *name;
-{
- VALUE error;
-
- if (!st_lookup(syserr_tbl, n, &error)) {
- error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
- rb_define_const(error, "Errno", INT2NUM(n));
- st_add_direct(syserr_tbl, n, error);
- }
- else {
- rb_define_const(rb_mErrno, name, error);
- }
- return error;
-}
-
-static VALUE
-get_syserr(n)
- int n;
-{
- VALUE error;
-
- if (!st_lookup(syserr_tbl, n, &error)) {
- char name[8]; /* some Windows' errno have 5 digits. */
-
- snprintf(name, sizeof(name), "E%03d", n);
- error = set_syserr(n, name);
- }
- return error;
-}
-
-/*
- * call-seq:
- * SystemCallError.new(msg, errno) => system_call_error_subclass
- *
- * If _errno_ corresponds to a known system error code, constructs
- * the appropriate <code>Errno</code> class for that error, otherwise
- * constructs a generic <code>SystemCallError</code> object. The
- * error number is subsequently available via the <code>errno</code>
- * method.
- */
-
-static VALUE
-syserr_initialize(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
-#if !defined(_WIN32) && !defined(__VMS)
- char *strerror();
-#endif
- char *err;
- VALUE mesg, error;
- VALUE klass = rb_obj_class(self);
-
- if (klass == rb_eSystemCallError) {
- rb_scan_args(argc, argv, "11", &mesg, &error);
- if (argc == 1 && FIXNUM_P(mesg)) {
- error = mesg; mesg = Qnil;
- }
- if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &klass)) {
- /* change class */
- if (TYPE(self) != T_OBJECT) { /* insurance to avoid type crash */
- rb_raise(rb_eTypeError, "invalid instance type");
- }
- RBASIC(self)->klass = klass;
- }
- }
- else {
- rb_scan_args(argc, argv, "01", &mesg);
- error = rb_const_get(klass, rb_intern("Errno"));
- }
- if (!NIL_P(error)) err = strerror(NUM2LONG(error));
- else err = "unknown error";
- if (!NIL_P(mesg)) {
- VALUE str = mesg;
- StringValue(str);
- mesg = rb_str_new(0, strlen(err)+RSTRING(str)->len+3);
- sprintf(RSTRING(mesg)->ptr, "%s - %.*s", err,
- (int)RSTRING(str)->len, RSTRING(str)->ptr);
- rb_str_resize(mesg, strlen(RSTRING(mesg)->ptr));
- }
- else {
- mesg = rb_str_new2(err);
- }
- exc_initialize(1, &mesg, self);
- rb_iv_set(self, "errno", error);
- return self;
-}
-
-/*
- * call-seq:
- * system_call_error.errno => fixnum
- *
- * Return this SystemCallError's error number.
- */
-
-static VALUE
-syserr_errno(self)
- VALUE self;
-{
- return rb_attr_get(self, rb_intern("errno"));
-}
-
-/*
- * call-seq:
- * system_call_error === other => true or false
- *
- * Return +true+ if the receiver is a generic +SystemCallError+, or
- * if the error numbers _self_ and _other_ are the same.
- */
-
-static VALUE
-syserr_eqq(self, exc)
- VALUE self, exc;
-{
- VALUE num, e;
-
- if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) return Qfalse;
- if (self == rb_eSystemCallError) return Qtrue;
-
- num = rb_attr_get(exc, rb_intern("errno"));
- if (NIL_P(num)) {
- VALUE klass = CLASS_OF(exc);
-
- while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
- klass = (VALUE)RCLASS(klass)->super;
- }
- num = rb_const_get(klass, rb_intern("Errno"));
- }
- e = rb_const_get(self, rb_intern("Errno"));
- if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
- return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * Errno.const_missing => SystemCallError
- *
- * Returns default SystemCallError class.
- */
-static VALUE
-errno_missing(self, id)
- VALUE self, id;
-{
- return eNOERROR;
-}
-
-/*
- * Descendents of class <code>Exception</code> are used to communicate
- * between <code>raise</code> methods and <code>rescue</code>
- * statements in <code>begin/end</code> blocks. <code>Exception</code>
- * objects carry information about the exception---its type (the
- * exception's class name), an optional descriptive string, and
- * optional traceback information. Programs may subclass
- * <code>Exception</code> to add additional information.
- */
-
-void
-Init_Exception()
-{
- rb_eException = rb_define_class("Exception", rb_cObject);
- rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
- rb_define_method(rb_eException, "exception", exc_exception, -1);
- rb_define_method(rb_eException, "initialize", exc_initialize, -1);
- rb_define_method(rb_eException, "==", exc_equal, 1);
- rb_define_method(rb_eException, "to_s", exc_to_s, 0);
- rb_define_method(rb_eException, "message", exc_message, 0);
- rb_define_method(rb_eException, "inspect", exc_inspect, 0);
- rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
- rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
-
- rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
- rb_define_method(rb_eSystemExit, "initialize", exit_initialize, -1);
- rb_define_method(rb_eSystemExit, "status", exit_status, 0);
- rb_define_method(rb_eSystemExit, "success?", exit_success_p, 0);
-
- rb_eFatal = rb_define_class("fatal", rb_eException);
- rb_eSignal = rb_define_class("SignalException", rb_eException);
- rb_eInterrupt = rb_define_class("Interrupt", rb_eSignal);
-
- rb_eStandardError = rb_define_class("StandardError", rb_eException);
- rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
- rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
- rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
- rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
- rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
- rb_eNameError = rb_define_class("NameError", rb_eStandardError);
- rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
- rb_define_method(rb_eNameError, "name", name_err_name, 0);
- rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
- rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
- rb_define_singleton_method(rb_cNameErrorMesg, "!", name_err_mesg_new, 3);
- rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
- rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
- rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1);
- rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1);
- rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
- rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
- rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
-
- rb_eScriptError = rb_define_class("ScriptError", rb_eException);
- rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
- rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
- rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
-
- rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
- rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError);
- rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
-
- syserr_tbl = st_init_numtable();
- rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
- rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1);
- rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
- rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
-
- rb_mErrno = rb_define_module("Errno");
- rb_define_singleton_method(rb_mErrno, "const_missing", errno_missing, 1);
-
- rb_define_global_function("warn", rb_warn_m, 1);
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_raise(VALUE exc, const char *fmt, ...)
-#else
-rb_raise(exc, fmt, va_alist)
- VALUE exc;
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- char buf[BUFSIZ];
-
- va_init_list(args,fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
- rb_exc_raise(rb_exc_new2(exc, buf));
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_loaderror(const char *fmt, ...)
-#else
-rb_loaderror(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- char buf[BUFSIZ];
-
- va_init_list(args, fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
- rb_exc_raise(rb_exc_new2(rb_eLoadError, buf));
-}
-
-void
-rb_notimplement()
-{
- rb_raise(rb_eNotImpError,
- "The %s() function is unimplemented on this machine",
- rb_id2name(ruby_frame->callee));
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_fatal(const char *fmt, ...)
-#else
-rb_fatal(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- va_list args;
- char buf[BUFSIZ];
-
- va_init_list(args, fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
-
- ruby_in_eval = 0;
- rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
-}
-
-void
-rb_sys_fail(mesg)
- const char *mesg;
-{
- extern int errno;
- int n = errno;
- VALUE arg;
-
- errno = 0;
- if (n == 0) {
- rb_bug("rb_sys_fail(%s) - errno == 0", mesg ? mesg : "");
- }
-
- arg = mesg ? rb_str_new2(mesg) : Qnil;
- rb_exc_raise(rb_class_new_instance(1, &arg, get_syserr(n)));
-}
-
-void
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_sys_warning(const char *fmt, ...)
-#else
-rb_sys_warning(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- char buf[BUFSIZ];
- va_list args;
- int errno_save;
-
- errno_save = errno;
-
- if (!RTEST(ruby_verbose)) return;
-
- snprintf(buf, BUFSIZ, "warning: %s", fmt);
- snprintf(buf+strlen(buf), BUFSIZ-strlen(buf), ": %s", strerror(errno_save));
-
- va_init_list(args, fmt);
- warn_print(buf, args);
- va_end(args);
- errno = errno_save;
-}
-
-void
-rb_load_fail(path)
- const char *path;
-{
- rb_loaderror("%s -- %s", strerror(errno), path);
-}
-
-void
-rb_error_frozen(what)
- const char *what;
-{
- rb_raise(rb_eRuntimeError, "can't modify frozen %s", what);
-}
-
-void
-rb_check_frozen(obj)
- VALUE obj;
-{
- if (OBJ_FROZEN(obj)) rb_error_frozen(rb_obj_classname(obj));
-}
-
-void
-Init_syserr()
-{
-#ifdef EPERM
- set_syserr(EPERM, "EPERM");
-#endif
-#ifdef ENOENT
- set_syserr(ENOENT, "ENOENT");
-#endif
-#ifdef ESRCH
- set_syserr(ESRCH, "ESRCH");
-#endif
-#ifdef EINTR
- set_syserr(EINTR, "EINTR");
-#endif
-#ifdef EIO
- set_syserr(EIO, "EIO");
-#endif
-#ifdef ENXIO
- set_syserr(ENXIO, "ENXIO");
-#endif
-#ifdef E2BIG
- set_syserr(E2BIG, "E2BIG");
-#endif
-#ifdef ENOEXEC
- set_syserr(ENOEXEC, "ENOEXEC");
-#endif
-#ifdef EBADF
- set_syserr(EBADF, "EBADF");
-#endif
-#ifdef ECHILD
- set_syserr(ECHILD, "ECHILD");
-#endif
-#ifdef EAGAIN
- set_syserr(EAGAIN, "EAGAIN");
-#endif
-#ifdef ENOMEM
- set_syserr(ENOMEM, "ENOMEM");
-#endif
-#ifdef EACCES
- set_syserr(EACCES, "EACCES");
-#endif
-#ifdef EFAULT
- set_syserr(EFAULT, "EFAULT");
-#endif
-#ifdef ENOTBLK
- set_syserr(ENOTBLK, "ENOTBLK");
-#endif
-#ifdef EBUSY
- set_syserr(EBUSY, "EBUSY");
-#endif
-#ifdef EEXIST
- set_syserr(EEXIST, "EEXIST");
-#endif
-#ifdef EXDEV
- set_syserr(EXDEV, "EXDEV");
-#endif
-#ifdef ENODEV
- set_syserr(ENODEV, "ENODEV");
-#endif
-#ifdef ENOTDIR
- set_syserr(ENOTDIR, "ENOTDIR");
-#endif
-#ifdef EISDIR
- set_syserr(EISDIR, "EISDIR");
-#endif
-#ifdef EINVAL
- set_syserr(EINVAL, "EINVAL");
-#endif
-#ifdef ENFILE
- set_syserr(ENFILE, "ENFILE");
-#endif
-#ifdef EMFILE
- set_syserr(EMFILE, "EMFILE");
-#endif
-#ifdef ENOTTY
- set_syserr(ENOTTY, "ENOTTY");
-#endif
-#ifdef ETXTBSY
- set_syserr(ETXTBSY, "ETXTBSY");
-#endif
-#ifdef EFBIG
- set_syserr(EFBIG, "EFBIG");
-#endif
-#ifdef ENOSPC
- set_syserr(ENOSPC, "ENOSPC");
-#endif
-#ifdef ESPIPE
- set_syserr(ESPIPE, "ESPIPE");
-#endif
-#ifdef EROFS
- set_syserr(EROFS, "EROFS");
-#endif
-#ifdef EMLINK
- set_syserr(EMLINK, "EMLINK");
-#endif
-#ifdef EPIPE
- set_syserr(EPIPE, "EPIPE");
-#endif
-#ifdef EDOM
- set_syserr(EDOM, "EDOM");
-#endif
-#ifdef ERANGE
- set_syserr(ERANGE, "ERANGE");
-#endif
-#ifdef EDEADLK
- set_syserr(EDEADLK, "EDEADLK");
-#endif
-#ifdef ENAMETOOLONG
- set_syserr(ENAMETOOLONG, "ENAMETOOLONG");
-#endif
-#ifdef ENOLCK
- set_syserr(ENOLCK, "ENOLCK");
-#endif
-#ifdef ENOSYS
- set_syserr(ENOSYS, "ENOSYS");
-#endif
-#ifdef ENOTEMPTY
- set_syserr(ENOTEMPTY, "ENOTEMPTY");
-#endif
-#ifdef ELOOP
- set_syserr(ELOOP, "ELOOP");
-#endif
-#ifdef EWOULDBLOCK
- set_syserr(EWOULDBLOCK, "EWOULDBLOCK");
-#endif
-#ifdef ENOMSG
- set_syserr(ENOMSG, "ENOMSG");
-#endif
-#ifdef EIDRM
- set_syserr(EIDRM, "EIDRM");
-#endif
-#ifdef ECHRNG
- set_syserr(ECHRNG, "ECHRNG");
-#endif
-#ifdef EL2NSYNC
- set_syserr(EL2NSYNC, "EL2NSYNC");
-#endif
-#ifdef EL3HLT
- set_syserr(EL3HLT, "EL3HLT");
-#endif
-#ifdef EL3RST
- set_syserr(EL3RST, "EL3RST");
-#endif
-#ifdef ELNRNG
- set_syserr(ELNRNG, "ELNRNG");
-#endif
-#ifdef EUNATCH
- set_syserr(EUNATCH, "EUNATCH");
-#endif
-#ifdef ENOCSI
- set_syserr(ENOCSI, "ENOCSI");
-#endif
-#ifdef EL2HLT
- set_syserr(EL2HLT, "EL2HLT");
-#endif
-#ifdef EBADE
- set_syserr(EBADE, "EBADE");
-#endif
-#ifdef EBADR
- set_syserr(EBADR, "EBADR");
-#endif
-#ifdef EXFULL
- set_syserr(EXFULL, "EXFULL");
-#endif
-#ifdef ENOANO
- set_syserr(ENOANO, "ENOANO");
-#endif
-#ifdef EBADRQC
- set_syserr(EBADRQC, "EBADRQC");
-#endif
-#ifdef EBADSLT
- set_syserr(EBADSLT, "EBADSLT");
-#endif
-#ifdef EDEADLOCK
- set_syserr(EDEADLOCK, "EDEADLOCK");
-#endif
-#ifdef EBFONT
- set_syserr(EBFONT, "EBFONT");
-#endif
-#ifdef ENOSTR
- set_syserr(ENOSTR, "ENOSTR");
-#endif
-#ifdef ENODATA
- set_syserr(ENODATA, "ENODATA");
-#endif
-#ifdef ETIME
- set_syserr(ETIME, "ETIME");
-#endif
-#ifdef ENOSR
- set_syserr(ENOSR, "ENOSR");
-#endif
-#ifdef ENONET
- set_syserr(ENONET, "ENONET");
-#endif
-#ifdef ENOPKG
- set_syserr(ENOPKG, "ENOPKG");
-#endif
-#ifdef EREMOTE
- set_syserr(EREMOTE, "EREMOTE");
-#endif
-#ifdef ENOLINK
- set_syserr(ENOLINK, "ENOLINK");
-#endif
-#ifdef EADV
- set_syserr(EADV, "EADV");
-#endif
-#ifdef ESRMNT
- set_syserr(ESRMNT, "ESRMNT");
-#endif
-#ifdef ECOMM
- set_syserr(ECOMM, "ECOMM");
-#endif
-#ifdef EPROTO
- set_syserr(EPROTO, "EPROTO");
-#endif
-#ifdef EMULTIHOP
- set_syserr(EMULTIHOP, "EMULTIHOP");
-#endif
-#ifdef EDOTDOT
- set_syserr(EDOTDOT, "EDOTDOT");
-#endif
-#ifdef EBADMSG
- set_syserr(EBADMSG, "EBADMSG");
-#endif
-#ifdef EOVERFLOW
- set_syserr(EOVERFLOW, "EOVERFLOW");
-#endif
-#ifdef ENOTUNIQ
- set_syserr(ENOTUNIQ, "ENOTUNIQ");
-#endif
-#ifdef EBADFD
- set_syserr(EBADFD, "EBADFD");
-#endif
-#ifdef EREMCHG
- set_syserr(EREMCHG, "EREMCHG");
-#endif
-#ifdef ELIBACC
- set_syserr(ELIBACC, "ELIBACC");
-#endif
-#ifdef ELIBBAD
- set_syserr(ELIBBAD, "ELIBBAD");
-#endif
-#ifdef ELIBSCN
- set_syserr(ELIBSCN, "ELIBSCN");
-#endif
-#ifdef ELIBMAX
- set_syserr(ELIBMAX, "ELIBMAX");
-#endif
-#ifdef ELIBEXEC
- set_syserr(ELIBEXEC, "ELIBEXEC");
-#endif
-#ifdef EILSEQ
- set_syserr(EILSEQ, "EILSEQ");
-#endif
-#ifdef ERESTART
- set_syserr(ERESTART, "ERESTART");
-#endif
-#ifdef ESTRPIPE
- set_syserr(ESTRPIPE, "ESTRPIPE");
-#endif
-#ifdef EUSERS
- set_syserr(EUSERS, "EUSERS");
-#endif
-#ifdef ENOTSOCK
- set_syserr(ENOTSOCK, "ENOTSOCK");
-#endif
-#ifdef EDESTADDRREQ
- set_syserr(EDESTADDRREQ, "EDESTADDRREQ");
-#endif
-#ifdef EMSGSIZE
- set_syserr(EMSGSIZE, "EMSGSIZE");
-#endif
-#ifdef EPROTOTYPE
- set_syserr(EPROTOTYPE, "EPROTOTYPE");
-#endif
-#ifdef ENOPROTOOPT
- set_syserr(ENOPROTOOPT, "ENOPROTOOPT");
-#endif
-#ifdef EPROTONOSUPPORT
- set_syserr(EPROTONOSUPPORT, "EPROTONOSUPPORT");
-#endif
-#ifdef ESOCKTNOSUPPORT
- set_syserr(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT");
-#endif
-#ifdef EOPNOTSUPP
- set_syserr(EOPNOTSUPP, "EOPNOTSUPP");
-#endif
-#ifdef EPFNOSUPPORT
- set_syserr(EPFNOSUPPORT, "EPFNOSUPPORT");
-#endif
-#ifdef EAFNOSUPPORT
- set_syserr(EAFNOSUPPORT, "EAFNOSUPPORT");
-#endif
-#ifdef EADDRINUSE
- set_syserr(EADDRINUSE, "EADDRINUSE");
-#endif
-#ifdef EADDRNOTAVAIL
- set_syserr(EADDRNOTAVAIL, "EADDRNOTAVAIL");
-#endif
-#ifdef ENETDOWN
- set_syserr(ENETDOWN, "ENETDOWN");
-#endif
-#ifdef ENETUNREACH
- set_syserr(ENETUNREACH, "ENETUNREACH");
-#endif
-#ifdef ENETRESET
- set_syserr(ENETRESET, "ENETRESET");
-#endif
-#ifdef ECONNABORTED
- set_syserr(ECONNABORTED, "ECONNABORTED");
-#endif
-#ifdef ECONNRESET
- set_syserr(ECONNRESET, "ECONNRESET");
-#endif
-#ifdef ENOBUFS
- set_syserr(ENOBUFS, "ENOBUFS");
-#endif
-#ifdef EISCONN
- set_syserr(EISCONN, "EISCONN");
-#endif
-#ifdef ENOTCONN
- set_syserr(ENOTCONN, "ENOTCONN");
-#endif
-#ifdef ESHUTDOWN
- set_syserr(ESHUTDOWN, "ESHUTDOWN");
-#endif
-#ifdef ETOOMANYREFS
- set_syserr(ETOOMANYREFS, "ETOOMANYREFS");
-#endif
-#ifdef ETIMEDOUT
- set_syserr(ETIMEDOUT, "ETIMEDOUT");
-#endif
-#ifdef ECONNREFUSED
- set_syserr(ECONNREFUSED, "ECONNREFUSED");
-#endif
-#ifdef EHOSTDOWN
- set_syserr(EHOSTDOWN, "EHOSTDOWN");
-#endif
-#ifdef EHOSTUNREACH
- set_syserr(EHOSTUNREACH, "EHOSTUNREACH");
-#endif
-#ifdef EALREADY
- set_syserr(EALREADY, "EALREADY");
-#endif
-#ifdef EINPROGRESS
- set_syserr(EINPROGRESS, "EINPROGRESS");
-#endif
-#ifdef ESTALE
- set_syserr(ESTALE, "ESTALE");
-#endif
-#ifdef EUCLEAN
- set_syserr(EUCLEAN, "EUCLEAN");
-#endif
-#ifdef ENOTNAM
- set_syserr(ENOTNAM, "ENOTNAM");
-#endif
-#ifdef ENAVAIL
- set_syserr(ENAVAIL, "ENAVAIL");
-#endif
-#ifdef EISNAM
- set_syserr(EISNAM, "EISNAM");
-#endif
-#ifdef EREMOTEIO
- set_syserr(EREMOTEIO, "EREMOTEIO");
-#endif
-#ifdef EDQUOT
- set_syserr(EDQUOT, "EDQUOT");
-#endif
- eNOERROR = set_syserr(0, "NOERROR");
-}
-
-static void
-err_append(s)
- const char *s;
-{
- extern VALUE ruby_errinfo;
-
- if (ruby_in_eval) {
- if (NIL_P(ruby_errinfo)) {
- ruby_errinfo = rb_exc_new2(rb_eSyntaxError, s);
- }
- else {
- VALUE str = rb_obj_as_string(ruby_errinfo);
-
- rb_str_cat2(str, "\n");
- rb_str_cat2(str, s);
- ruby_errinfo = rb_exc_new3(rb_eSyntaxError, str);
- }
- }
- else {
- rb_write_error(s);
- rb_write_error("\n");
- }
-}
-/**********************************************************************
- euc_jp.c - Oniguruma (regular expression library)
-**********************************************************************/
-/*-
- * Copyright (c) 2002-2005 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "regenc.h"
-
-#define eucjp_islead(c) ((UChar )((c) - 0xa1) > 0xfe - 0xa1)
-
-static int EncLen_EUCJP[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1
-};
-
-static int
-eucjp_mbc_enc_len(const UChar* p)
-{
- return EncLen_EUCJP[*p];
-}
-
-static OnigCodePoint
-eucjp_mbc_to_code(const UChar* p, const UChar* end)
-{
- int c, i, len;
- OnigCodePoint n;
-
- len = enc_len(ONIG_ENCODING_EUC_JP, p);
- n = (OnigCodePoint )*p++;
- if (len == 1) return n;
-
- for (i = 1; i < len; i++) {
- if (p >= end) break;
- c = *p++;
- n <<= 8; n += c;
- }
- return n;
-}
-
-static int
-eucjp_code_to_mbclen(OnigCodePoint code)
-{
- if (ONIGENC_IS_CODE_ASCII(code)) return 1;
- else if ((code & 0xff0000) != 0) return 3;
- else if ((code & 0xff00) != 0) return 2;
- else return 0;
-}
-
-#if 0
-static int
-eucjp_code_to_mbc_first(OnigCodePoint code)
-{
- int first;
-
- if ((code & 0xff0000) != 0) {
- first = (code >> 16) & 0xff;
- }
- else if ((code & 0xff00) != 0) {
- first = (code >> 8) & 0xff;
- }
- else {
- return (int )code;
- }
- return first;
-}
-#endif
-
-static int
-eucjp_code_to_mbc(OnigCodePoint code, UChar *buf)
-{
- UChar *p = buf;
-
- if ((code & 0xff0000) != 0) *p++ = (UChar )(((code >> 16) & 0xff));
- if ((code & 0xff00) != 0) *p++ = (UChar )(((code >> 8) & 0xff));
- *p++ = (UChar )(code & 0xff);
-
-#if 1
- if (enc_len(ONIG_ENCODING_EUC_JP, buf) != (p - buf))
- return ONIGENCERR_INVALID_WIDE_CHAR_VALUE;
-#endif
- return p - buf;
-}
-
-static int
-eucjp_mbc_to_normalize(OnigAmbigType flag,
- const UChar** pp, const UChar* end, UChar* lower)
-{
- int len;
- const UChar* p = *pp;
-
- if (ONIGENC_IS_MBC_ASCII(p)) {
- if ((flag & ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE) != 0) {
- *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p);
- }
- else {
- *lower = *p;
- }
-
- (*pp)++;
- return 1;
- }
- else {
- len = enc_len(ONIG_ENCODING_EUC_JP, p);
- if (lower != p) {
- int i;
- for (i = 0; i < len; i++) {
- *lower++ = *p++;
- }
- }
- (*pp) += len;
- return len; /* return byte length of converted char to lower */
- }
-}
-
-static int
-eucjp_is_mbc_ambiguous(OnigAmbigType flag, const UChar** pp, const UChar* end)
-{
- return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_EUC_JP, flag, pp, end);
-}
-
-static int
-eucjp_is_code_ctype(OnigCodePoint code, unsigned int ctype)
-{
- if ((ctype & ONIGENC_CTYPE_WORD) != 0) {
- if (code < 128)
- return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
- else
- return (eucjp_code_to_mbclen(code) > 1 ? TRUE : FALSE);
-
- ctype &= ~ONIGENC_CTYPE_WORD;
- if (ctype == 0) return FALSE;
- }
-
- if (code < 128)
- return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
- else
- return FALSE;
-}
-
-static UChar*
-eucjp_left_adjust_char_head(const UChar* start, const UChar* s)
-{
- /* In this encoding
- mb-trail bytes doesn't mix with single bytes.
- */
- const UChar *p;
- int len;
-
- if (s <= start) return (UChar* )s;
- p = s;
-
- while (!eucjp_islead(*p) && p > start) p--;
- len = enc_len(ONIG_ENCODING_EUC_JP, p);
- if (p + len > s) return (UChar* )p;
- p += len;
- return (UChar* )(p + ((s - p) & ~1));
-}
-
-static int
-eucjp_is_allowed_reverse_match(const UChar* s, const UChar* end)
-{
- const UChar c = *s;
- if (c <= 0x7e || c == 0x8e || c == 0x8f)
- return TRUE;
- else
- return FALSE;
-}
-
-OnigEncodingType OnigEncodingEUC_JP = {
- eucjp_mbc_enc_len,
- "EUC-JP", /* name */
- 3, /* max enc length */
- 1, /* min enc length */
- ONIGENC_AMBIGUOUS_MATCH_ASCII_CASE,
- {
- (OnigCodePoint )'\\' /* esc */
- , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */
- , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */
- , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */
- , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */
- , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */
- },
- onigenc_is_mbc_newline_0x0a,
- eucjp_mbc_to_code,
- eucjp_code_to_mbclen,
- eucjp_code_to_mbc,
- eucjp_mbc_to_normalize,
- eucjp_is_mbc_ambiguous,
- onigenc_ascii_get_all_pair_ambig_codes,
- onigenc_nothing_get_all_comp_ambig_codes,
- eucjp_is_code_ctype,
- onigenc_not_support_get_ctype_code_range,
- eucjp_left_adjust_char_head,
- eucjp_is_allowed_reverse_match
-};
-/**********************************************************************
-
- eval.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Thu Jun 10 14:22:17 JST 1993
-
- 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 "node.h"
-#include "env.h"
-#include "util.h"
-#include "rubysig.h"
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
-#include <stdio.h>
-#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
-#include <ucontext.h>
-#define USE_CONTEXT
-#else
-#include <setjmp.h>
-#endif
-
-#include "st.h"
-#include "dln.h"
-
-#ifdef __APPLE__
-#include <crt_externs.h>
-#endif
-
-/* Make alloca work the best possible way. */
-#ifdef __GNUC__
-# ifndef atarist
-# ifndef alloca
-# define alloca __builtin_alloca
-# endif
-# endif /* atarist */
-#else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-void *alloca ();
-# endif
-# endif /* AIX */
-# endif /* HAVE_ALLOCA_H */
-#endif /* __GNUC__ */
-
-#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
-
-#ifndef HAVE_STRING_H
-char *strrchr _((const char*,const char));
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef __BEOS__
-#include <net/socket.h>
-#endif
-
-#ifdef __MACOS__
-#include "macruby_private.h"
-#endif
-
-#ifdef USE_CONTEXT
-typedef struct {
- ucontext_t context;
- volatile int status;
-} rb_jmpbuf_t[1];
-
-#undef longjmp
-#undef setjmp
-NORETURN(static void rb_jump_context(rb_jmpbuf_t, int));
-static inline void
-rb_jump_context(env, val)
- rb_jmpbuf_t env;
- int val;
-{
- env->status = val;
- setcontext(&env->context);
- abort(); /* ensure noreturn */
-}
-#define longjmp(env, val) rb_jump_context(env, val)
-#define setjmp(j) ((j)->status = 0, getcontext(&(j)->context), (j)->status)
-#else
-typedef jmp_buf rb_jmpbuf_t;
-#ifndef setjmp
-#ifdef HAVE__SETJMP
-#define setjmp(env) _setjmp(env)
-#define longjmp(env,val) _longjmp(env,val)
-#endif
-#endif
-#endif
-
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-
-#if defined(__VMS)
-#pragma nostandard
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#include <sys/stat.h>
-
-VALUE rb_cProc;
-static VALUE rb_cBinding;
-static VALUE proc_invoke _((VALUE,VALUE,VALUE,VALUE));
-static VALUE rb_f_binding _((VALUE));
-static void rb_f_END _((void));
-static VALUE rb_f_block_given_p _((void));
-static VALUE block_pass _((VALUE,NODE*));
-static VALUE rb_cMethod;
-static VALUE method_call _((int, VALUE*, VALUE));
-static VALUE rb_cUnboundMethod;
-static VALUE umethod_bind _((VALUE, VALUE));
-static VALUE rb_mod_define_method _((int, VALUE*, VALUE));
-NORETURN(static void rb_raise_jump _((VALUE)));
-static VALUE rb_make_exception _((int argc, VALUE *argv));
-
-static int scope_vmode;
-#define SCOPE_PUBLIC 0
-#define SCOPE_PRIVATE 1
-#define SCOPE_PROTECTED 2
-#define SCOPE_MODFUNC 5
-#define SCOPE_MASK 7
-#define SCOPE_SET(f) (scope_vmode=(f))
-#define SCOPE_TEST(f) (scope_vmode&(f))
-
-NODE* ruby_current_node;
-int ruby_safe_level = 0;
-/* safe-level:
- 0 - strings from streams/environment/ARGV are tainted (default)
- 1 - no dangerous operation by tainted value
- 2 - process/file operations prohibited
- 3 - all generated objects are tainted
- 4 - no global (non-tainted) variable modification/no direct output
-*/
-
-static VALUE safe_getter _((void));
-static void safe_setter _((VALUE val));
-
-void
-rb_secure(level)
- int level;
-{
- if (level <= ruby_safe_level) {
- if (ruby_frame->callee) {
- rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
- rb_id2name(ruby_frame->callee), ruby_safe_level);
- }
- else {
- rb_raise(rb_eSecurityError, "Insecure operation at level %d", ruby_safe_level);
- }
- }
-}
-
-void
-rb_secure_update(obj)
- VALUE obj;
-{
- if (!OBJ_TAINTED(obj)) rb_secure(4);
-}
-
-void
-rb_check_safe_obj(x)
- VALUE x;
-{
- if (ruby_safe_level > 0 && OBJ_TAINTED(x)){
- if (ruby_frame->callee) {
- rb_raise(rb_eSecurityError, "Insecure operation - %s",
- rb_id2name(ruby_frame->callee));
- }
- else {
- rb_raise(rb_eSecurityError, "Insecure operation: -r");
- }
- }
- rb_secure(4);
-}
-
-void
-rb_check_safe_str(x)
- VALUE x;
-{
- rb_check_safe_obj(x);
- if (TYPE(x)!= T_STRING) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
- rb_obj_classname(x));
- }
-}
-
-NORETURN(static void print_undef _((VALUE, ID)));
-static void
-print_undef(klass, id)
- VALUE klass;
- ID id;
-{
- rb_name_error(id, "undefined method `%s' for %s `%s'",
- rb_id2name(id),
- (TYPE(klass) == T_MODULE) ? "module" : "class",
- rb_class2name(klass));
-}
-
-static ID removed, singleton_removed, undefined, singleton_undefined;
-
-#define CACHE_SIZE 0x800
-#define CACHE_MASK 0x7ff
-#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
-
-struct cache_entry { /* method hash table. */
- ID mid; /* method's id */
- ID mid0; /* method's original id */
- VALUE klass; /* receiver's class */
- VALUE origin; /* where method defined */
- NODE *method;
- int noex;
-};
-
-static struct cache_entry cache[CACHE_SIZE];
-static int ruby_running = 0;
-
-void
-rb_clear_cache()
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- ent->mid = 0;
- ent++;
- }
-}
-
-static void
-rb_clear_cache_for_undef(klass, id)
- VALUE klass;
- ID id;
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->origin == klass && ent->mid == id) {
- ent->mid = 0;
- }
- ent++;
- }
-}
-
-static void
-rb_clear_cache_by_id(id)
- ID id;
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->mid == id) {
- ent->mid = 0;
- }
- ent++;
- }
-}
-
-void
-rb_clear_cache_by_class(klass)
- VALUE klass;
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->klass == klass || ent->origin == klass) {
- ent->mid = 0;
- }
- ent++;
- }
-}
-
-static ID init, eqq, each, aref, aset, match, missing;
-static ID added, singleton_added;
-static ID __id__, __send__, respond_to;
-
-void
-rb_add_method(klass, mid, node, noex)
- VALUE klass;
- ID mid;
- NODE *node;
- int noex;
-{
- NODE *body;
-
- if (NIL_P(klass)) klass = rb_cObject;
- if (ruby_safe_level >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
- rb_raise(rb_eSecurityError, "Insecure: can't define method");
- }
- if (!FL_TEST(klass, FL_SINGLETON) &&
- node && nd_type(node) != NODE_ZSUPER &&
- (mid == rb_intern("initialize" )|| mid == rb_intern("initialize_copy"))) {
- noex = NOEX_PRIVATE | noex;
- }
- else if (FL_TEST(klass, FL_SINGLETON) && node && nd_type(node) == NODE_CFUNC &&
- mid == rb_intern("allocate")) {
- rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()",
- rb_class2name(rb_iv_get(klass, "__attached__")));
- mid = ID_ALLOCATOR;
- }
- if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
- rb_clear_cache_by_id(mid);
- body = NEW_METHOD(node, noex);
- st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body);
- if (node && mid != ID_ALLOCATOR && ruby_running) {
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid));
- }
- else {
- rb_funcall(klass, added, 1, ID2SYM(mid));
- }
- }
-}
-
-void
-rb_define_alloc_func(klass, func)
- VALUE klass;
- VALUE (*func) _((VALUE));
-{
- Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE);
-}
-
-void
-rb_undef_alloc_func(klass)
- VALUE klass;
-{
- Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
-}
-
-static NODE*
-search_method(klass, id, origin)
- VALUE klass, *origin;
- ID id;
-{
- NODE *body;
-
- if (!klass) return 0;
- while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body)) {
- klass = RCLASS(klass)->super;
- if (!klass) return 0;
- }
-
- if (origin) *origin = klass;
- return body;
-}
-
-static NODE*
-rb_get_method_body(klassp, idp, noexp)
- VALUE *klassp;
- ID *idp;
- int *noexp;
-{
- ID id = *idp;
- VALUE klass = *klassp;
- VALUE origin;
- NODE * volatile body;
- struct cache_entry *ent;
-
- if ((body = search_method(klass, id, &origin)) == 0 || !body->nd_body) {
- /* store empty info in cache */
- ent = cache + EXPR1(klass, id);
- ent->klass = klass;
- ent->origin = klass;
- ent->mid = ent->mid0 = id;
- ent->noex = 0;
- ent->method = 0;
-
- return 0;
- }
-
- if (ruby_running) {
- /* store in cache */
- ent = cache + EXPR1(klass, id);
- ent->klass = klass;
- ent->noex = body->nd_noex;
- if (noexp) *noexp = body->nd_noex;
- body = body->nd_body;
- if (nd_type(body) == NODE_FBODY) {
- ent->mid = id;
- *klassp = body->nd_orig;
- ent->origin = body->nd_orig;
- *idp = ent->mid0 = body->nd_mid;
- body = ent->method = body->nd_head;
- }
- else {
- *klassp = origin;
- ent->origin = origin;
- ent->mid = ent->mid0 = id;
- ent->method = body;
- }
- }
- else {
- if (noexp) *noexp = body->nd_noex;
- body = body->nd_body;
- if (nd_type(body) == NODE_FBODY) {
- *klassp = body->nd_orig;
- *idp = body->nd_mid;
- body = body->nd_head;
- }
- else {
- *klassp = origin;
- }
- }
-
- return body;
-}
-
-NODE*
-rb_method_node(klass, id)
- VALUE klass;
- ID id;
-{
- int noex;
- struct cache_entry *ent;
-
- ent = cache + EXPR1(klass, id);
- if (ent->mid == id && ent->klass == klass && ent->method){
- return ent->method;
- }
-
- return rb_get_method_body(&klass, &id, &noex);
-}
-
-static void
-remove_method(klass, mid)
- VALUE klass;
- ID mid;
-{
- NODE *body;
-
- if (klass == rb_cObject) {
- rb_secure(4);
- }
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
- rb_raise(rb_eSecurityError, "Insecure: can't remove method");
- }
- if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
- if (mid == __id__ || mid == __send__ || mid == init) {
- rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
- }
- if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) ||
- !body->nd_body) {
- rb_name_error(mid, "method `%s' not defined in %s",
- rb_id2name(mid), rb_class2name(klass));
- }
- rb_clear_cache_for_undef(klass, mid);
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid));
- }
- else {
- rb_funcall(klass, removed, 1, ID2SYM(mid));
- }
-}
-
-void
-rb_remove_method(klass, name)
- VALUE klass;
- const char *name;
-{
- remove_method(klass, rb_intern(name));
-}
-
-/*
- * call-seq:
- * remove_method(symbol) => self
- *
- * Removes the method identified by _symbol_ from the current
- * class. For an example, see <code>Module.undef_method</code>.
- */
-
-static VALUE
-rb_mod_remove_method(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- int i;
-
- for (i=0; i<argc; i++) {
- remove_method(mod, rb_to_id(argv[i]));
- }
- return mod;
-}
-
-#undef rb_disable_super
-#undef rb_enable_super
-
-void
-rb_disable_super(klass, name)
- VALUE klass;
- const char *name;
-{
- /* obsolete - no use */
-}
-
-void
-rb_enable_super(klass, name)
- VALUE klass;
- const char *name;
-{
- rb_warning("rb_enable_super() is obsolete");
-}
-
-static void
-rb_export_method(klass, name, noex)
- VALUE klass;
- ID name;
- ID noex;
-{
- NODE *body;
- VALUE origin;
-
- if (klass == rb_cObject) {
- rb_secure(4);
- }
- body = search_method(klass, name, &origin);
- if (!body && TYPE(klass) == T_MODULE) {
- body = search_method(rb_cObject, name, &origin);
- }
- if (!body || !body->nd_body) {
- print_undef(klass, name);
- }
- if (body->nd_noex != noex) {
- if (klass == origin) {
- body->nd_noex = noex;
- }
- else {
- rb_add_method(klass, name, NEW_ZSUPER(), noex);
- }
- }
-}
-
-int
-rb_method_boundp(klass, id, ex)
- VALUE klass;
- ID id;
- int ex;
-{
- struct cache_entry *ent;
- int noex;
-
- /* is it in the method cache? */
- ent = cache + EXPR1(klass, id);
- if (ent->mid == id && ent->klass == klass) {
- if (ex && (ent->noex & NOEX_PRIVATE))
- return Qfalse;
- if (!ent->method) return Qfalse;
- return Qtrue;
- }
- if (rb_get_method_body(&klass, &id, &noex)) {
- if (ex && (noex & NOEX_PRIVATE))
- return Qfalse;
- return Qtrue;
- }
- return Qfalse;
-}
-
-void
-rb_attr(klass, id, read, write, ex)
- VALUE klass;
- ID id;
- int read, write, ex;
-{
- const char *name;
- char *buf;
- ID attriv;
- int noex;
-
- if (!ex) noex = NOEX_PUBLIC;
- else {
- if (SCOPE_TEST(SCOPE_PRIVATE)) {
- noex = NOEX_PRIVATE;
- rb_warning((scope_vmode == SCOPE_MODFUNC) ?
- "attribute accessor as module_function" :
- "private attribute?");
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
- }
- }
-
- if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
- rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
- }
- name = rb_id2name(id);
- if (!name) {
- rb_raise(rb_eArgError, "argument needs to be symbol or string");
- }
- buf = ALLOCA_N(char,strlen(name)+2);
- sprintf(buf, "@%s", name);
- attriv = rb_intern(buf);
- if (read) {
- rb_add_method(klass, id, NEW_IVAR(attriv), noex);
- }
- if (write) {
- rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
- }
-}
-
-VALUE ruby_errinfo = Qnil;
-extern int ruby_nerrs;
-
-static VALUE rb_eLocalJumpError;
-static VALUE rb_eSysStackError;
-
-extern VALUE ruby_top_self;
-
-struct FRAME *ruby_frame;
-struct SCOPE *ruby_scope;
-static struct FRAME *top_frame;
-static struct SCOPE *top_scope;
-
-static unsigned long frame_unique = 0;
-
-#define PUSH_FRAME() do { \
- struct FRAME _frame; \
- _frame.prev = ruby_frame; \
- _frame.tmp = 0; \
- _frame.node = ruby_current_node; \
- _frame.iter = ruby_iter->iter; \
- _frame.argc = 0; \
- _frame.flags = 0; \
- _frame.uniq = frame_unique++; \
- ruby_frame = &_frame
-
-#define POP_FRAME() \
- ruby_current_node = _frame.node; \
- ruby_frame = _frame.prev; \
-} while (0)
-
-struct BLOCK {
- NODE *var;
- NODE *body;
- VALUE self;
- struct FRAME frame;
- struct SCOPE *scope;
- VALUE klass;
- NODE *cref;
- int iter;
- int vmode;
- int flags;
- int uniq;
- struct RVarmap *dyna_vars;
- VALUE orig_thread;
- VALUE wrapper;
- VALUE block_obj;
- struct BLOCK *outer;
- struct BLOCK *prev;
-};
-
-#define BLOCK_D_SCOPE 1
-#define BLOCK_LAMBDA 2
-#define BLOCK_FROM_METHOD 4
-
-static struct BLOCK *ruby_block;
-static unsigned long block_unique = 0;
-
-#define PUSH_BLOCK(v,b) do { \
- struct BLOCK _block; \
- _block.var = (v); \
- _block.body = (b); \
- _block.self = self; \
- _block.frame = *ruby_frame; \
- _block.klass = ruby_class; \
- _block.cref = ruby_cref; \
- _block.frame.node = ruby_current_node;\
- _block.scope = ruby_scope; \
- _block.prev = ruby_block; \
- _block.outer = ruby_block; \
- _block.iter = ruby_iter->iter; \
- _block.vmode = scope_vmode; \
- _block.flags = BLOCK_D_SCOPE; \
- _block.dyna_vars = ruby_dyna_vars; \
- _block.wrapper = ruby_wrapper; \
- _block.block_obj = 0; \
- _block.uniq = (b)?block_unique++:0; \
- if (b) { \
- prot_tag->blkid = _block.uniq; \
- } \
- ruby_block = &_block
-
-#define POP_BLOCK() \
- ruby_block = _block.prev; \
-} while (0)
-
-struct RVarmap *ruby_dyna_vars;
-#define PUSH_VARS() do { \
- struct RVarmap * volatile _old; \
- _old = ruby_dyna_vars; \
- ruby_dyna_vars = 0
-
-#define POP_VARS() \
- if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {\
- if (RBASIC(_old)->flags) /* unless it's already recycled */ \
- FL_SET(_old, DVAR_DONT_RECYCLE); \
- }\
- ruby_dyna_vars = _old; \
-} while (0)
-
-#define DVAR_DONT_RECYCLE FL_USER2
-
-static struct RVarmap*
-new_dvar(id, value, prev)
- ID id;
- VALUE value;
- struct RVarmap *prev;
-{
- NEWOBJ(vars, struct RVarmap);
- OBJSETUP(vars, 0, T_VARMAP);
- vars->id = id;
- vars->val = value;
- vars->next = prev;
-
- return vars;
-}
-
-VALUE
-rb_dvar_defined(id)
- ID id;
-{
- struct RVarmap *vars = ruby_dyna_vars;
-
- while (vars) {
- if (vars->id == id) return Qtrue;
- vars = vars->next;
- }
- return Qfalse;
-}
-
-VALUE
-rb_dvar_curr(id)
- ID id;
-{
- struct RVarmap *vars = ruby_dyna_vars;
-
- while (vars) {
- if (vars->id == 0) break;
- if (vars->id == id) return Qtrue;
- vars = vars->next;
- }
- return Qfalse;
-}
-
-VALUE
-rb_dvar_ref(id)
- ID id;
-{
- struct RVarmap *vars = ruby_dyna_vars;
-
- while (vars) {
- if (vars->id == id) {
- return vars->val;
- }
- vars = vars->next;
- }
- return Qnil;
-}
-
-void
-rb_dvar_push(id, value)
- ID id;
- VALUE value;
-{
- ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars);
-}
-
-static void
-dvar_asgn_internal(id, value, curr)
- ID id;
- VALUE value;
- int curr;
-{
- int n = 0;
- struct RVarmap *vars = ruby_dyna_vars;
-
- while (vars) {
- if (curr && vars->id == 0) {
- /* first null is a dvar header */
- n++;
- if (n == 2) break;
- }
- if (vars->id == id) {
- vars->val = value;
- return;
- }
- vars = vars->next;
- }
- if (!ruby_dyna_vars) {
- ruby_dyna_vars = new_dvar(id, value, 0);
- }
- else {
- vars = new_dvar(id, value, ruby_dyna_vars->next);
- ruby_dyna_vars->next = vars;
- }
-}
-
-static inline void
-dvar_asgn(id, value)
- ID id;
- VALUE value;
-{
- dvar_asgn_internal(id, value, 0);
-}
-
-static inline void
-dvar_asgn_curr(id, value)
- ID id;
- VALUE value;
-{
- dvar_asgn_internal(id, value, 1);
-}
-
-VALUE *
-rb_svar(cnt)
- int cnt;
-{
- struct RVarmap *vars = ruby_dyna_vars;
- ID id;
-
- if (!ruby_scope->local_tbl) return NULL;
- if (cnt >= ruby_scope->local_tbl[0]) return NULL;
- id = ruby_scope->local_tbl[cnt+1];
- while (vars) {
- if (vars->id == id) return &vars->val;
- vars = vars->next;
- }
- if (ruby_scope->local_vars == 0) return NULL;
- return &ruby_scope->local_vars[cnt];
-}
-
-struct iter {
- int iter;
- struct iter *prev;
-};
-static struct iter *ruby_iter;
-
-#define ITER_NOT 0
-#define ITER_PRE 1
-#define ITER_CUR 2
-
-#define PUSH_ITER(i) do { \
- struct iter _iter; \
- _iter.prev = ruby_iter; \
- _iter.iter = (i); \
- ruby_iter = &_iter
-
-#define POP_ITER() \
- ruby_iter = _iter.prev; \
-} while (0)
-
-struct tag {
- rb_jmpbuf_t buf;
- struct FRAME *frame;
- struct iter *iter;
- VALUE tag;
- VALUE retval;
- struct SCOPE *scope;
- VALUE dst;
- struct tag *prev;
- int blkid;
-};
-static struct tag *prot_tag;
-
-#define PUSH_TAG(ptag) do { \
- struct tag _tag; \
- _tag.retval = Qnil; \
- _tag.frame = ruby_frame; \
- _tag.iter = ruby_iter; \
- _tag.prev = prot_tag; \
- _tag.scope = ruby_scope; \
- _tag.tag = ptag; \
- _tag.dst = 0; \
- _tag.blkid = 0; \
- prot_tag = &_tag
-
-#define PROT_NONE Qfalse /* 0 */
-#define PROT_THREAD Qtrue /* 2 */
-#define PROT_FUNC INT2FIX(0) /* 1 */
-#define PROT_LOOP INT2FIX(1) /* 3 */
-#define PROT_LAMBDA INT2FIX(2) /* 5 */
-#define PROT_YIELD INT2FIX(3) /* 7 */
-#define PROT_TOP INT2FIX(4) /* 9 */
-
-#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf))
-
-#define JUMP_TAG(st) do { \
- ruby_frame = prot_tag->frame; \
- ruby_iter = prot_tag->iter; \
- longjmp(prot_tag->buf,(st)); \
-} while (0)
-
-#define POP_TAG() \
- prot_tag = _tag.prev; \
-} while (0)
-
-#define TAG_DST() (_tag.dst == (VALUE)ruby_frame->uniq)
-
-#define TAG_RETURN 0x1
-#define TAG_BREAK 0x2
-#define TAG_NEXT 0x3
-#define TAG_RETRY 0x4
-#define TAG_REDO 0x5
-#define TAG_RAISE 0x6
-#define TAG_THROW 0x7
-#define TAG_FATAL 0x8
-#define TAG_CONTCALL 0x9
-#define TAG_THREAD 0xa
-#define TAG_MASK 0xf
-
-VALUE ruby_class;
-static VALUE ruby_wrapper; /* security wrapper */
-
-#define PUSH_CLASS(c) do { \
- VALUE _class = ruby_class; \
- ruby_class = (c)
-
-#define POP_CLASS() ruby_class = _class; \
-} while (0)
-
-static NODE *ruby_cref = 0;
-static NODE *top_cref;
-#define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref)
-#define POP_CREF() ruby_cref = ruby_cref->nd_next
-
-#define PUSH_SCOPE() do { \
- volatile int _vmode = scope_vmode; \
- struct SCOPE * volatile _old; \
- NEWOBJ(_scope, struct SCOPE); \
- OBJSETUP(_scope, 0, T_SCOPE); \
- _scope->local_tbl = 0; \
- _scope->local_vars = 0; \
- _scope->flags = 0; \
- _old = ruby_scope; \
- ruby_scope = _scope; \
- scope_vmode = SCOPE_PUBLIC
-
-typedef struct thread * rb_thread_t;
-static rb_thread_t curr_thread = 0;
-static rb_thread_t main_thread;
-static void scope_dup _((struct SCOPE *));
-
-#define POP_SCOPE() \
- if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {\
- if (_old) scope_dup(_old); \
- } \
- if (!(ruby_scope->flags & SCOPE_MALLOC)) {\
- ruby_scope->local_vars = 0; \
- ruby_scope->local_tbl = 0; \
- if (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) && \
- ruby_scope != top_scope) { \
- rb_gc_force_recycle((VALUE)ruby_scope);\
- } \
- } \
- ruby_scope->flags |= SCOPE_NOSTACK; \
- ruby_scope = _old; \
- scope_vmode = _vmode; \
-} while (0)
-
-struct ruby_env {
- struct ruby_env *prev;
- struct FRAME *frame;
- struct SCOPE *scope;
- struct BLOCK *block;
- struct iter *iter;
- struct tag *tag;
- NODE *cref;
-};
-
-static void push_thread_anchor _((struct ruby_env *));
-static void pop_thread_anchor _((struct ruby_env *));
-
-#define PUSH_THREAD_TAG() PUSH_TAG(PROT_THREAD); \
- do { \
- struct ruby_env _interp; \
- push_thread_anchor(&_interp);
-#define POP_THREAD_TAG() \
- pop_thread_anchor(&_interp); \
- } while (0); \
- POP_TAG()
-
-static VALUE rb_eval _((VALUE,NODE*));
-static VALUE eval _((VALUE,VALUE,VALUE,char*,int));
-static NODE *compile _((VALUE, char*, int));
-
-static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
-
-#define YIELD_LAMBDA_CALL 1
-#define YIELD_PROC_CALL 2
-#define YIELD_PUBLIC_DEF 4
-#define YIELD_FUNC_AVALUE 1
-#define YIELD_FUNC_SVALUE 2
-
-static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int));
-static VALUE module_setup _((VALUE,NODE*));
-
-static VALUE massign _((VALUE,NODE*,VALUE,int));
-static void assign _((VALUE,NODE*,VALUE,int));
-
-typedef struct event_hook {
- rb_event_hook_func_t func;
- rb_event_t events;
- struct event_hook *next;
-} rb_event_hook_t;
-
-static rb_event_hook_t *event_hooks;
-
-#define EXEC_EVENT_HOOK(event, node, self, id, klass) \
- do { \
- rb_event_hook_t *hook; \
- \
- for (hook = event_hooks; hook; hook = hook->next) { \
- if (hook->events & event) \
- (*hook->func)(event, node, self, id, klass); \
- } \
- } while (0)
-
-static VALUE trace_func = 0;
-static int tracing = 0;
-static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE));
-
-#if 0
-#define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
- ruby_sourceline = nd_line(ruby_current_node))
-#else
-#define SET_CURRENT_SOURCE() ((void)0)
-#endif
-
-void
-ruby_set_current_source()
-{
- if (ruby_current_node) {
- ruby_sourcefile = ruby_current_node->nd_file;
- ruby_sourceline = nd_line(ruby_current_node);
- }
-}
-
-static void
-#ifdef HAVE_STDARG_PROTOTYPES
-warn_printf(const char *fmt, ...)
-#else
-warn_printf(fmt, va_alist)
- const char *fmt;
- va_dcl
-#endif
-{
- char buf[BUFSIZ];
- va_list args;
-
- va_init_list(args, fmt);
- vsnprintf(buf, BUFSIZ, fmt, args);
- va_end(args);
- rb_write_error(buf);
-}
-
-#define warn_print(x) rb_write_error(x)
-#define warn_print2(x,l) rb_write_error2(x,l)
-
-static void
-error_pos()
-{
- ruby_set_current_source();
- if (ruby_sourcefile) {
- if (ruby_frame->callee) {
- warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
- rb_id2name(ruby_frame->callee));
- }
- else if (ruby_sourceline == 0) {
- warn_printf("%s", ruby_sourcefile);
- }
- else {
- warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline);
- }
- }
-}
-
-static VALUE
-get_backtrace(info)
- VALUE info;
-{
- if (NIL_P(info)) return Qnil;
- info = rb_funcall(info, rb_intern("backtrace"), 0);
- if (NIL_P(info)) return Qnil;
- return rb_check_array_type(info);
-}
-
-static void
-set_backtrace(info, bt)
- VALUE info, bt;
-{
- rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
-}
-
-static void
-error_print()
-{
- VALUE errat = Qnil; /* OK */
- volatile VALUE eclass, e;
- char *einfo;
- long elen;
-
- if (NIL_P(ruby_errinfo)) return;
-
- PUSH_TAG(PROT_NONE);
- if (EXEC_TAG() == 0) {
- errat = get_backtrace(ruby_errinfo);
- }
- else {
- errat = Qnil;
- }
- if (EXEC_TAG()) goto error;
- if (NIL_P(errat)){
- ruby_set_current_source();
- if (ruby_sourcefile)
- warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline);
- else
- warn_printf("%d", ruby_sourceline);
- }
- else if (RARRAY(errat)->len == 0) {
- error_pos();
- }
- else {
- VALUE mesg = RARRAY(errat)->ptr[0];
-
- if (NIL_P(mesg)) error_pos();
- else {
- warn_print2(RSTRING(mesg)->ptr, RSTRING(mesg)->len);
- }
- }
-
- eclass = CLASS_OF(ruby_errinfo);
- if (EXEC_TAG() == 0) {
- e = rb_funcall(ruby_errinfo, rb_intern("message"), 0, 0);
- StringValue(e);
- einfo = RSTRING(e)->ptr;
- elen = RSTRING(e)->len;
- }
- else {
- einfo = "";
- elen = 0;
- }
- if (EXEC_TAG()) goto error;
- if (eclass == rb_eRuntimeError && elen == 0) {
- warn_print(": unhandled exception\n");
- }
- else {
- VALUE epath;
-
- epath = rb_class_name(eclass);
- if (elen == 0) {
- warn_print(": ");
- warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
- warn_print("\n");
- }
- else {
- char *tail = 0;
- long len = elen;
-
- if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = memchr(einfo, '\n', elen)) {
- len = tail - einfo;
- tail++; /* skip newline */
- }
- warn_print(": ");
- warn_print2(einfo, len);
- if (epath) {
- warn_print(" (");
- warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
- warn_print(")\n");
- }
- if (tail) {
- warn_print2(tail, elen-len-1);
- }
- }
- }
-
- if (!NIL_P(errat)) {
- long i;
- struct RArray *ep = RARRAY(errat);
-
-#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
-#define TRACE_HEAD 8
-#define TRACE_TAIL 5
-
- ep = RARRAY(errat);
- for (i=1; i<ep->len; i++) {
- if (TYPE(ep->ptr[i]) == T_STRING) {
- warn_printf("\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
- }
- if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
- warn_printf("\t ... %ld levels...\n",
- ep->len - TRACE_HEAD - TRACE_TAIL);
- i = ep->len - TRACE_TAIL;
- }
- }
- }
- error:
- POP_TAG();
-}
-
-#if defined(__APPLE__)
-#define environ (*_NSGetEnviron())
-#elif !defined(_WIN32) && !defined(__MACOS__) || defined(_WIN32_WCE)
-extern char **environ;
-#endif
-char **rb_origenviron;
-
-void rb_call_inits _((void));
-void Init_stack _((VALUE*));
-void Init_heap _((void));
-void Init_ext _((void));
-
-#ifdef HAVE_NATIVETHREAD
-static rb_nativethread_t ruby_thid;
-int
-is_ruby_native_thread()
-{
- return NATIVETHREAD_EQUAL(ruby_thid, NATIVETHREAD_CURRENT());
-}
-
-# ifdef HAVE_NATIVETHREAD_KILL
-void
-ruby_native_thread_kill(sig)
- int sig;
-{
- NATIVETHREAD_KILL(ruby_thid, sig);
-}
-# endif
-#endif
-
-NORETURN(static void rb_thread_start_1 _((void)));
-
-void
-ruby_init()
-{
- static int initialized = 0;
- static struct FRAME frame;
- static struct iter iter;
- int state;
-
- if (initialized)
- return;
- initialized = 1;
-#ifdef HAVE_NATIVETHREAD
- ruby_thid = NATIVETHREAD_CURRENT();
-#endif
-
- ruby_frame = top_frame = &frame;
- ruby_iter = &iter;
-
-#ifdef __MACOS__
- rb_origenviron = 0;
-#else
- rb_origenviron = environ;
-#endif
-
- Init_stack((void*)&state);
- Init_heap();
- PUSH_SCOPE();
- top_scope = ruby_scope;
- /* default visibility is private at toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- rb_call_inits();
- ruby_class = rb_cObject;
- ruby_frame->self = ruby_top_self;
- top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
- ruby_cref = top_cref;
- rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
-#ifdef __MACOS__
- _macruby_init();
-#endif
- ruby_prog_init();
- ALLOW_INTS;
- }
- POP_TAG();
- if (state) {
- error_print();
- exit(EXIT_FAILURE);
- }
- POP_SCOPE();
- ruby_scope = top_scope;
- top_scope->flags &= ~SCOPE_NOSTACK;
- ruby_running = 1;
-}
-
-static VALUE
-eval_node(self, node)
- VALUE self;
- NODE *node;
-{
- if (!node) return Qnil;
- if (nd_type(node) == NODE_PRELUDE) {
- rb_eval(self, node->nd_head);
- node = node->nd_body;
- }
- if (!node) return Qnil;
- return rb_eval(self, node);
-}
-
-int ruby_in_eval;
-
-static void rb_thread_cleanup _((void));
-static void rb_thread_wait_other_threads _((void));
-
-static int thread_set_raised();
-static int thread_reset_raised();
-
-static VALUE exception_error;
-static VALUE sysstack_error;
-
-static int
-error_handle(ex)
- int ex;
-{
- int status = EXIT_FAILURE;
-
- if (thread_set_raised()) return EXIT_FAILURE;
- switch (ex & TAG_MASK) {
- case 0:
- status = EXIT_SUCCESS;
- break;
-
- case TAG_RETURN:
- error_pos();
- warn_print(": unexpected return\n");
- break;
- case TAG_NEXT:
- error_pos();
- warn_print(": unexpected next\n");
- break;
- case TAG_BREAK:
- error_pos();
- warn_print(": unexpected break\n");
- break;
- case TAG_REDO:
- error_pos();
- warn_print(": unexpected redo\n");
- break;
- case TAG_RETRY:
- error_pos();
- warn_print(": retry outside of rescue clause\n");
- break;
- case TAG_THROW:
- if (prot_tag && prot_tag->frame && prot_tag->frame->node) {
- NODE *tag = prot_tag->frame->node;
- warn_printf("%s:%d: uncaught throw\n",
- tag->nd_file, nd_line(tag));
- }
- else {
- error_pos();
- warn_printf(": unexpected throw\n");
- }
- break;
- case TAG_RAISE:
- case TAG_FATAL:
- if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
- VALUE st = rb_iv_get(ruby_errinfo, "status");
- status = NUM2INT(st);
- }
- else {
- error_print();
- }
- break;
- default:
- rb_bug("Unknown longjmp status %d", ex);
- break;
- }
- thread_reset_raised();
- return status;
-}
-
-void
-ruby_options(argc, argv)
- int argc;
- char **argv;
-{
- int state;
-
-#ifdef _WIN32
- argc = rb_w32_cmdvector(GetCommandLine(), &argv);
-#endif
-
- Init_stack((void*)&state);
- PUSH_THREAD_TAG();
- if ((state = EXEC_TAG()) == 0) {
- ruby_process_options(argc, argv);
- }
- else {
- if (state == TAG_THREAD) {
- rb_thread_start_1();
- }
- trace_func = 0;
- tracing = 0;
- exit(error_handle(state));
- }
- POP_THREAD_TAG();
-
-#ifdef _WIN32_WCE
- wce_FreeCommandLine();
-#endif
-}
-
-void rb_exec_end_proc _((void));
-
-static void
-ruby_finalize_0()
-{
- PUSH_TAG(PROT_NONE);
- if (EXEC_TAG() == 0) {
- rb_trap_exit();
- }
- POP_TAG();
- rb_exec_end_proc();
-}
-
-static void
-ruby_finalize_1()
-{
- signal(SIGINT, SIG_DFL);
- ruby_errinfo = 0;
- rb_gc_call_finalizer_at_exit();
- trace_func = 0;
- tracing = 0;
-}
-
-void
-ruby_finalize()
-{
- ruby_finalize_0();
- ruby_finalize_1();
-}
-
-int
-ruby_cleanup(ex)
- int ex;
-{
- int state;
- volatile VALUE err = ruby_errinfo;
-
- ruby_safe_level = 0;
- Init_stack((void*)&state);
- PUSH_THREAD_TAG();
- PUSH_ITER(ITER_NOT);
- if ((state = EXEC_TAG()) == 0) {
- ruby_finalize_0();
- if (ruby_errinfo) err = ruby_errinfo;
- rb_thread_cleanup();
- rb_thread_wait_other_threads();
- }
- else if (state == TAG_THREAD) {
- rb_thread_start_1();
- }
- else if (ex == 0) {
- ex = state;
- }
- POP_ITER();
- ruby_errinfo = err;
- ex = error_handle(ex);
- ruby_finalize_1();
- POP_THREAD_TAG();
-
- if (err && rb_obj_is_kind_of(err, rb_eSystemExit)) {
- VALUE st = rb_iv_get(err, "status");
- return NUM2INT(st);
- }
- return ex;
-}
-
-extern NODE *ruby_eval_tree;
-
-static void cont_call _((VALUE));
-
-static int
-ruby_exec_internal()
-{
- int state;
-
- PUSH_THREAD_TAG();
- PUSH_ITER(ITER_NOT);
- /* default visibility is private at toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
- if ((state = EXEC_TAG()) == 0) {
- eval_node(ruby_top_self, ruby_eval_tree);
- }
-#if 0
- else if (state == TAG_CONTCALL) {
- cont_call(prot_tag->retval);
- }
-#endif
- else if (state == TAG_THREAD) {
- rb_thread_start_1();
- }
- POP_ITER();
- POP_THREAD_TAG();
- return state;
-}
-
-int
-ruby_exec()
-{
- volatile NODE *tmp;
-
- Init_stack((void*)&tmp);
- return ruby_exec_internal();
-}
-
-void
-ruby_stop(ex)
- int ex;
-{
- exit(ruby_cleanup(ex));
-}
-
-void
-ruby_run()
-{
- int state;
- static int ex;
-
- if (ruby_nerrs > 0) exit(EXIT_FAILURE);
- state = ruby_exec();
- if (state && !ex) ex = state;
- ruby_stop(ex);
-}
-
-static void
-compile_error(at)
- const char *at;
-{
- VALUE str;
-
- ruby_nerrs = 0;
- str = rb_str_buf_new2("compile error");
- if (at) {
- rb_str_buf_cat2(str, " in ");
- rb_str_buf_cat2(str, at);
- }
- rb_str_buf_cat(str, "\n", 1);
- if (!NIL_P(ruby_errinfo)) {
- rb_str_append(str, rb_obj_as_string(ruby_errinfo));
- }
- rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str));
-}
-
-VALUE
-rb_eval_string(str)
- const char *str;
-{
- VALUE v;
- NODE *oldsrc = ruby_current_node;
-
- ruby_current_node = 0;
- ruby_sourcefile = rb_source_filename("(eval)");
- v = eval(ruby_top_self, rb_str_new2(str), Qnil, 0, 0);
- ruby_current_node = oldsrc;
-
- return v;
-}
-
-VALUE
-rb_eval_string_protect(str, state)
- const char *str;
- int *state;
-{
- return rb_protect((VALUE (*)_((VALUE)))rb_eval_string, (VALUE)str, state);
-}
-
-VALUE
-rb_eval_string_wrap(str, state)
- const char *str;
- int *state;
-{
- int status;
- VALUE self = ruby_top_self;
- VALUE wrapper = ruby_wrapper;
- VALUE val;
-
- PUSH_CLASS(ruby_wrapper = rb_module_new());
- ruby_top_self = rb_obj_clone(ruby_top_self);
- rb_extend_object(ruby_top_self, ruby_wrapper);
- PUSH_FRAME();
- ruby_frame->callee = 0;
- ruby_frame->this_func = 0;
- ruby_frame->this_class = 0;
- ruby_frame->self = self;
- PUSH_CREF(ruby_wrapper);
- PUSH_SCOPE();
-
- val = rb_eval_string_protect(str, &status);
- ruby_top_self = self;
-
- POP_SCOPE();
- POP_FRAME();
- POP_CLASS();
- ruby_wrapper = wrapper;
- if (state) {
- *state = status;
- }
- else if (status) {
- JUMP_TAG(status);
- }
- return val;
-}
-
-NORETURN(static void localjump_error(const char*, VALUE, int));
-static void
-localjump_error(mesg, value, reason)
- const char *mesg;
- VALUE value;
- int reason;
-{
- VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg);
- ID id;
-
- rb_iv_set(exc, "@exit_value", value);
- switch (reason) {
- case TAG_BREAK:
- id = rb_intern("break"); break;
- case TAG_REDO:
- id = rb_intern("redo"); break;
- case TAG_RETRY:
- id = rb_intern("retry"); break;
- case TAG_NEXT:
- id = rb_intern("next"); break;
- case TAG_RETURN:
- id = rb_intern("return"); break;
- default:
- id = rb_intern("noreason"); break;
- }
- rb_iv_set(exc, "@reason", ID2SYM(id));
- rb_exc_raise(exc);
-}
-
-/*
- * call_seq:
- * local_jump_error.exit_value => obj
- *
- * Returns the exit value associated with this +LocalJumpError+.
- */
-static VALUE
-localjump_xvalue(exc)
- VALUE exc;
-{
- return rb_iv_get(exc, "@exit_value");
-}
-
-/*
- * call-seq:
- * local_jump_error.reason => symbol
- *
- * The reason this block was terminated:
- * :break, :redo, :retry, :next, :return, or :noreason.
- */
-
-static VALUE
-localjump_reason(exc)
- VALUE exc;
-{
- return rb_iv_get(exc, "@reason");
-}
-
-NORETURN(static void jump_tag_but_local_jump _((int,VALUE)));
-static void
-jump_tag_but_local_jump(state, val)
- int state;
- VALUE val;
-{
-
- if (val == Qundef) val = prot_tag->retval;
- switch (state) {
- case 0:
- break;
- case TAG_RETURN:
- localjump_error("unexpected return", val, state);
- break;
- case TAG_BREAK:
- localjump_error("unexpected break", val, state);
- break;
- case TAG_NEXT:
- localjump_error("unexpected next", val, state);
- break;
- case TAG_REDO:
- localjump_error("unexpected redo", Qnil, state);
- break;
- case TAG_RETRY:
- localjump_error("retry outside of rescue clause", Qnil, state);
- break;
- default:
- break;
- }
- JUMP_TAG(state);
-}
-
-VALUE
-rb_eval_cmd(cmd, arg, level)
- VALUE cmd, arg;
- int level;
-{
- int state;
- VALUE val = Qnil; /* OK */
- struct SCOPE *saved_scope;
- volatile int safe = ruby_safe_level;
-
- if (OBJ_TAINTED(cmd)) {
- level = 4;
- }
- if (TYPE(cmd) != T_STRING) {
- PUSH_ITER(ITER_NOT);
- PUSH_TAG(PROT_NONE);
- ruby_safe_level = level;
- if ((state = EXEC_TAG()) == 0) {
- val = rb_funcall2(cmd, rb_intern("call"), RARRAY(arg)->len, RARRAY(arg)->ptr);
- }
- ruby_safe_level = safe;
- POP_TAG();
- POP_ITER();
- if (state) JUMP_TAG(state);
- return val;
- }
-
- saved_scope = ruby_scope;
- ruby_scope = top_scope;
- PUSH_FRAME();
- ruby_frame->callee = 0;
- ruby_frame->this_func = 0;
- ruby_frame->this_class = 0;
- ruby_frame->self = ruby_top_self;
- PUSH_CREF(ruby_wrapper ? ruby_wrapper : rb_cObject);
-
- ruby_safe_level = level;
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- val = eval(ruby_top_self, cmd, Qnil, 0, 0);
- }
- if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
- scope_dup(saved_scope);
- ruby_scope = saved_scope;
- ruby_safe_level = safe;
- POP_TAG();
- POP_FRAME();
-
- jump_tag_but_local_jump(state, val);
- return val;
-}
-
-#define ruby_cbase (ruby_cref->nd_clss)
-
-static VALUE
-ev_const_defined(cref, id, self)
- NODE *cref;
- ID id;
- VALUE self;
-{
- NODE *cbase = cref;
- VALUE result;
-
- while (cbase && cbase->nd_next) {
- struct RClass *klass = RCLASS(cbase->nd_clss);
-
- if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id);
- if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
- if (result == Qundef && NIL_P(rb_autoload_p((VALUE)klass, id))) {
- return Qfalse;
- }
- return Qtrue;
- }
- cbase = cbase->nd_next;
- }
- return rb_const_defined(cref->nd_clss, id);
-}
-
-static VALUE
-ev_const_get(cref, id, self)
- NODE *cref;
- ID id;
- VALUE self;
-{
- NODE *cbase = cref;
- VALUE result;
-
- while (cbase && cbase->nd_next) {
- VALUE klass = cbase->nd_clss;
-
- if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
- while (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
- if (result == Qundef) {
- rb_autoload_load(klass, id);
- continue;
- }
- return result;
- }
- cbase = cbase->nd_next;
- }
- return rb_const_get(cref->nd_clss, id);
-}
-
-static VALUE
-cvar_cbase()
-{
- NODE *cref = ruby_cref;
-
- while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
- cref = cref->nd_next;
- if (!cref->nd_next) {
- rb_warn("class variable access from toplevel singleton method");
- }
- }
- if (NIL_P(cref->nd_clss)) {
- rb_raise(rb_eTypeError, "no class variables available");
- }
- return cref->nd_clss;
-}
-
-/*
- * call-seq:
- * Module.nesting => array
- *
- * Returns the list of +Modules+ nested at the point of call.
- *
- * module M1
- * module M2
- * $a = Module.nesting
- * end
- * end
- * $a #=> [M1::M2, M1]
- * $a[0].name #=> "M1::M2"
- */
-
-static VALUE
-rb_mod_nesting()
-{
- NODE *cbase = ruby_cref;
- VALUE ary = rb_ary_new();
-
- while (cbase && cbase->nd_next) {
- if (!NIL_P(cbase->nd_clss)) rb_ary_push(ary, cbase->nd_clss);
- cbase = cbase->nd_next;
- }
- if (ruby_wrapper && RARRAY(ary)->len == 0) {
- rb_ary_push(ary, ruby_wrapper);
- }
- return ary;
-}
-
-/*
- * call-seq:
- * Module.constants => array
- *
- * Returns an array of the names of all constants defined in the
- * system. This list includes the names of all modules and classes.
- *
- * p Module.constants.sort[1..5]
- *
- * <em>produces:</em>
- *
- * ["ARGV", "ArgumentError", "Array", "Bignum", "Binding"]
- */
-
-static VALUE
-rb_mod_s_constants()
-{
- NODE *cbase = ruby_cref;
- void *data = 0;
-
- while (cbase) {
- if (!NIL_P(cbase->nd_clss)) {
- data = rb_mod_const_at(cbase->nd_clss, data);
- }
- cbase = cbase->nd_next;
- }
-
- if (!NIL_P(ruby_cbase)) {
- data = rb_mod_const_of(ruby_cbase, data);
- }
- return rb_const_list(data);
-}
-
-void
-rb_frozen_class_p(klass)
- VALUE klass;
-{
- char *desc = "something(?!)";
-
- if (OBJ_FROZEN(klass)) {
- if (FL_TEST(klass, FL_SINGLETON))
- desc = "object";
- else {
- switch (TYPE(klass)) {
- case T_MODULE:
- case T_ICLASS:
- desc = "module"; break;
- case T_CLASS:
- desc = "class"; break;
- }
- }
- rb_error_frozen(desc);
- }
-}
-
-void
-rb_undef(klass, id)
- VALUE klass;
- ID id;
-{
- VALUE origin;
- NODE *body;
-
- if (ruby_cbase == rb_cObject && klass == rb_cObject) {
- rb_secure(4);
- }
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) {
- rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id));
- }
- rb_frozen_class_p(klass);
- if (id == __id__ || id == __send__ || id == init) {
- rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
- }
- body = search_method(klass, id, &origin);
- if (!body || !body->nd_body) {
- char *s0 = " class";
- VALUE c = klass;
-
- if (FL_TEST(c, FL_SINGLETON)) {
- VALUE obj = rb_iv_get(klass, "__attached__");
-
- switch (TYPE(obj)) {
- case T_MODULE:
- case T_CLASS:
- c = obj;
- s0 = "";
- }
- }
- else if (TYPE(c) == T_MODULE) {
- s0 = " module";
- }
- rb_name_error(id, "undefined method `%s' for%s `%s'",
- rb_id2name(id),s0,rb_class2name(c));
- }
- rb_add_method(klass, id, 0, NOEX_PUBLIC);
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(klass, "__attached__"),
- singleton_undefined, 1, ID2SYM(id));
- }
- else {
- rb_funcall(klass, undefined, 1, ID2SYM(id));
- }
-}
-
-/*
- * call-seq:
- * undef_method(symbol) => self
- *
- * Prevents the current class from responding to calls to the named
- * method. Contrast this with <code>remove_method</code>, which deletes
- * the method from the particular class; Ruby will still search
- * superclasses and mixed-in modules for a possible receiver.
- *
- * class Parent
- * def hello
- * puts "In parent"
- * end
- * end
- * class Child < Parent
- * def hello
- * puts "In child"
- * end
- * end
- *
- *
- * c = Child.new
- * c.hello
- *
- *
- * class Child
- * remove_method :hello # remove from child, still in parent
- * end
- * c.hello
- *
- *
- * class Child
- * undef_method :hello # prevent any calls to 'hello'
- * end
- * c.hello
- *
- * <em>produces:</em>
- *
- * In child
- * In parent
- * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
- */
-
-static VALUE
-rb_mod_undef_method(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- int i;
-
- for (i=0; i<argc; i++) {
- rb_undef(mod, rb_to_id(argv[i]));
- }
- return mod;
-}
-
-void
-rb_alias(klass, name, def)
- VALUE klass;
- ID name, def;
-{
- VALUE origin;
- NODE *orig, *body, *node;
- VALUE singleton = 0;
-
- rb_frozen_class_p(klass);
- if (name == def) return;
- if (klass == rb_cObject) {
- rb_secure(4);
- }
- orig = search_method(klass, def, &origin);
- if (!orig || !orig->nd_body) {
- if (TYPE(klass) == T_MODULE) {
- orig = search_method(rb_cObject, def, &origin);
- }
- }
- if (!orig || !orig->nd_body) {
- print_undef(klass, def);
- }
- if (FL_TEST(klass, FL_SINGLETON)) {
- singleton = rb_iv_get(klass, "__attached__");
- }
- body = orig->nd_body;
- orig->nd_cnt++;
- if (nd_type(body) == NODE_FBODY) { /* was alias */
- def = body->nd_mid;
- origin = body->nd_orig;
- body = body->nd_head;
- }
-
- rb_clear_cache_by_id(name);
- if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *)&node)) {
- if (node->nd_cnt == 0 && node->nd_body) {
- rb_warning("discarding old %s", rb_id2name(name));
- }
- }
- st_insert(RCLASS(klass)->m_tbl, name,
- (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
- if (singleton) {
- rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
- }
- else {
- rb_funcall(klass, added, 1, ID2SYM(name));
- }
-}
-
-/*
- * call-seq:
- * alias_method(new_name, old_name) => self
- *
- * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
- * be used to retain access to methods that are overridden.
- *
- * module Mod
- * alias_method :orig_exit, :exit
- * def exit(code=0)
- * puts "Exiting with code #{code}"
- * orig_exit(code)
- * end
- * end
- * include Mod
- * exit(99)
- *
- * <em>produces:</em>
- *
- * Exiting with code 99
- */
-
-static VALUE
-rb_mod_alias_method(mod, newname, oldname)
- VALUE mod, newname, oldname;
-{
- rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
- return mod;
-}
-
-static NODE*
-copy_node_scope(node, rval)
- NODE *node;
- NODE *rval;
-{
- NODE *copy = NEW_NODE(NODE_SCOPE,0,rval,node->nd_next);
-
- if (node->nd_tbl) {
- copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1);
- MEMCPY(copy->nd_tbl, node->nd_tbl, ID, node->nd_tbl[0]+1);
- }
- else {
- copy->nd_tbl = 0;
- }
- return copy;
-}
-
-#ifdef C_ALLOCA
-# define TMP_PROTECT NODE * volatile tmp__protect_tmp=0
-# define TMP_ALLOC(n) \
- (tmp__protect_tmp = rb_node_newnode(NODE_ALLOCA, \
- ALLOC_N(VALUE,n),tmp__protect_tmp,n), \
- (void*)tmp__protect_tmp->nd_head)
-#else
-# define TMP_PROTECT typedef int foobazzz
-# define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
-#endif
-
-#define SETUP_ARGS0(anode,alen) do {\
- NODE *n = anode;\
- if (!n) {\
- argc = 0;\
- argv = 0;\
- }\
- else if (nd_type(n) == NODE_ARRAY) {\
- argc=alen;\
- if (argc > 0) {\
- int i;\
- n = anode;\
- argv = TMP_ALLOC(argc);\
- for (i=0;i<argc;i++) {\
- argv[i] = rb_eval(self,n->nd_head);\
- n=n->nd_next;\
- }\
- }\
- else {\
- argc = 0;\
- argv = 0;\
- }\
- }\
- else {\
- VALUE args = rb_eval(self,n);\
- if (TYPE(args) != T_ARRAY)\
- args = rb_ary_to_ary(args);\
- argc = RARRAY(args)->len;\
- argv = ALLOCA_N(VALUE, argc);\
- MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
- }\
-} while (0)
-
-#define SETUP_ARGS(anode) SETUP_ARGS0(anode, anode->nd_alen)
-
-#define BEGIN_CALLARGS do {\
- struct BLOCK *tmp_block = ruby_block;\
- int tmp_iter = ruby_iter->iter;\
- if (tmp_iter == ITER_PRE) {\
- ruby_block = ruby_block->outer;\
- tmp_iter = ITER_NOT;\
- }\
- PUSH_ITER(tmp_iter)
-
-#define END_CALLARGS \
- ruby_block = tmp_block;\
- POP_ITER();\
-} while (0)
-
-#define MATCH_DATA *rb_svar(node->nd_cnt)
-
-static const char* is_defined _((VALUE, NODE*, char*, int));
-
-static char*
-arg_defined(self, node, buf, type)
- VALUE self;
- NODE *node;
- char *buf;
- char *type;
-{
- int argc;
- int i;
-
- if (!node) return type; /* no args */
- if (nd_type(node) == NODE_ARRAY) {
- argc=node->nd_alen;
- if (argc > 0) {
- for (i=0;i<argc;i++) {
- if (!is_defined(self, node->nd_head, buf, 0))
- return 0;
- node = node->nd_next;
- }
- }
- }
- else if (!is_defined(self, node, buf, 0)) {
- return 0;
- }
- return type;
-}
-
-static const char*
-is_defined(self, node, buf, noeval)
- VALUE self;
- NODE *node; /* OK */
- char *buf;
- int noeval;
-{
- VALUE val; /* OK */
- int state;
- static const char *ex = "expression";
-
- if (!node) return ex;
- switch (nd_type(node)) {
- case NODE_SUPER:
- case NODE_ZSUPER:
- if (ruby_frame->this_func == 0) return 0;
- else if (ruby_frame->this_class == 0) return 0;
- val = ruby_frame->this_class;
- if (rb_method_boundp(RCLASS(val)->super, ruby_frame->this_func, 0)) {
- if (nd_type(node) == NODE_SUPER) {
- return arg_defined(self, node->nd_args, buf, "super");
- }
- return "super";
- }
- break;
-
- case NODE_VCALL:
- case NODE_FCALL:
- val = self;
- goto check_bound;
-
- case NODE_ATTRASGN:
- val = self;
- if (node->nd_recv == (NODE *)1) goto check_bound;
- case NODE_CALL:
- if (!is_defined(self, node->nd_recv, buf, Qtrue)) return 0;
- if (noeval) return ex;
- val = rb_eval(self, node->nd_recv);
- check_bound:
- {
- int call = nd_type(node)==NODE_CALL;
-
- val = CLASS_OF(val);
- if (call) {
- int noex;
- ID id = node->nd_mid;
-
- if (!rb_get_method_body(&val, &id, &noex))
- break;
- if ((noex & NOEX_PRIVATE))
- break;
- if ((noex & NOEX_PROTECTED) &&
- !rb_obj_is_kind_of(self, rb_class_real(val)))
- break;
- }
- else if (!rb_method_boundp(val, node->nd_mid, call))
- break;
- return arg_defined(self, node->nd_args, buf,
- nd_type(node) == NODE_ATTRASGN ?
- "assignment" : "method");
- }
- break;
-
- case NODE_MATCH2:
- case NODE_MATCH3:
- return "method";
-
- case NODE_YIELD:
- if (rb_block_given_p()) {
- return "yield";
- }
- break;
-
- case NODE_SELF:
- return "self";
-
- case NODE_NIL:
- return "nil";
-
- case NODE_TRUE:
- return "true";
-
- case NODE_FALSE:
- return "false";
-
- case NODE_ATTRSET:
- case NODE_OP_ASGN1:
- case NODE_OP_ASGN2:
- case NODE_MASGN:
- case NODE_LASGN:
- case NODE_DASGN:
- case NODE_DASGN_CURR:
- case NODE_GASGN:
- case NODE_IASGN:
- case NODE_CDECL:
- case NODE_CVDECL:
- case NODE_CVASGN:
- return "assignment";
-
- case NODE_LVAR:
- return "local-variable";
- case NODE_DVAR:
- return "local-variable(in-block)";
-
- case NODE_GVAR:
- if (rb_gvar_defined(node->nd_entry)) {
- return "global-variable";
- }
- break;
-
- case NODE_IVAR:
- if (rb_ivar_defined(self, node->nd_vid)) {
- return "instance-variable";
- }
- break;
-
- case NODE_CONST:
- if (ev_const_defined(ruby_cref, node->nd_vid, self)) {
- return "constant";
- }
- break;
-
- case NODE_CVAR:
- if (rb_cvar_defined(cvar_cbase(), node->nd_vid)) {
- return "class variable";
- }
- break;
-
- case NODE_COLON2:
- if (!is_defined(self, node->nd_recv, buf, Qtrue)) return 0;
- if (noeval) return ex;
- val = rb_eval(self, node->nd_recv);
- switch (TYPE(val)) {
- case T_CLASS:
- case T_MODULE:
- if (rb_const_defined_from(val, node->nd_mid))
- return "constant";
- break;
- default:
- if (rb_method_boundp(CLASS_OF(val), node->nd_mid, 1)) {
- return "method";
- }
- }
- break;
-
- case NODE_COLON3:
- if (rb_const_defined_from(rb_cObject, node->nd_mid)) {
- return "constant";
- }
- break;
-
- case NODE_NTH_REF:
- if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) {
- if (!buf) return ex;
- sprintf(buf, "$%d", (int)node->nd_nth);
- return buf;
- }
- break;
-
- case NODE_BACK_REF:
- if (RTEST(rb_reg_nth_defined(0, MATCH_DATA))) {
- if (!buf) return ex;
- sprintf(buf, "$%c", (char)node->nd_nth);
- return buf;
- }
- break;
-
- default:
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- rb_eval(self, node);
- }
- POP_TAG();
- if (!state) {
- return ex;
- }
- ruby_errinfo = Qnil;
- break;
- }
- return 0;
-}
-
-static int handle_rescue _((VALUE,NODE*));
-
-static void blk_free();
-
-static VALUE
-rb_obj_is_proc(proc)
- VALUE proc;
-{
- if (TYPE(proc) == T_DATA && RDATA(proc)->dfree == (RUBY_DATA_FUNC)blk_free) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-void
-rb_add_event_hook(func, events)
- rb_event_hook_func_t func;
- rb_event_t events;
-{
- rb_event_hook_t *hook;
-
- hook = ALLOC(rb_event_hook_t);
- hook->func = func;
- hook->events = events;
- hook->next = event_hooks;
- event_hooks = hook;
-}
-
-int
-rb_remove_event_hook(func)
- rb_event_hook_func_t func;
-{
- rb_event_hook_t *prev, *hook;
-
- prev = NULL;
- hook = event_hooks;
- while (hook) {
- if (hook->func == func) {
- if (prev) {
- prev->next = hook->next;
- }
- else {
- event_hooks = hook->next;
- }
- xfree(hook);
- return 0;
- }
- prev = hook;
- hook = hook->next;
- }
- return -1;
-}
-
-/*
- * call-seq:
- * set_trace_func(proc) => proc
- * set_trace_func(nil) => nil
- *
- * Establishes _proc_ as the handler for tracing, or disables
- * tracing if the parameter is +nil+. _proc_ takes up
- * to six parameters: an event name, a filename, a line number, an
- * object id, a binding, and the name of a class. _proc_ is
- * invoked whenever an event occurs. Events are: <code>c-call</code>
- * (call a C-language routine), <code>c-return</code> (return from a
- * C-language routine), <code>call</code> (call a Ruby method),
- * <code>class</code> (start a class or module definition),
- * <code>end</code> (finish a class or module definition),
- * <code>line</code> (execute code on a new line), <code>raise</code>
- * (raise an exception), and <code>return</code> (return from a Ruby
- * method). Tracing is disabled within the context of _proc_.
- *
- * class Test
- * def test
- * a = 1
- * b = 2
- * end
- * end
- *
- * set_trace_func proc { |event, file, line, id, binding, classname|
- * printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
- * }
- * t = Test.new
- * t.test
- *
- * line prog.rb:11 false
- * c-call prog.rb:11 new Class
- * c-call prog.rb:11 initialize Object
- * c-return prog.rb:11 initialize Object
- * c-return prog.rb:11 new Class
- * line prog.rb:12 false
- * call prog.rb:2 test Test
- * line prog.rb:3 test Test
- * line prog.rb:4 test Test
- * return prog.rb:4 test Test
- */
-
-
-static VALUE
-set_trace_func(obj, trace)
- VALUE obj, trace;
-{
- rb_event_hook_t *hook;
-
- if (NIL_P(trace)) {
- trace_func = 0;
- rb_remove_event_hook(call_trace_func);
- return Qnil;
- }
- if (!rb_obj_is_proc(trace)) {
- rb_raise(rb_eTypeError, "trace_func needs to be Proc");
- }
- trace_func = trace;
- for (hook = event_hooks; hook; hook = hook->next) {
- if (hook->func == call_trace_func)
- return trace;
- }
- rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL);
- return trace;
-}
-
-static char *
-get_event_name(rb_event_t event)
-{
- switch (event) {
- case RUBY_EVENT_LINE:
- return "line";
- case RUBY_EVENT_CLASS:
- return "class";
- case RUBY_EVENT_END:
- return "end";
- case RUBY_EVENT_CALL:
- return "call";
- case RUBY_EVENT_RETURN:
- return "return";
- case RUBY_EVENT_C_CALL:
- return "c-call";
- case RUBY_EVENT_C_RETURN:
- return "c-return";
- case RUBY_EVENT_RAISE:
- return "raise";
- default:
- return "unknown";
- }
-}
-
-static void
-call_trace_func(event, node, self, id, klass)
- rb_event_t event;
- NODE *node;
- VALUE self;
- ID id;
- VALUE klass; /* OK */
-{
- int state, raised;
- struct FRAME *prev;
- NODE *node_save;
- VALUE srcfile;
- char *event_name;
-
- if (!trace_func) return;
- if (tracing) return;
- if (id == ID_ALLOCATOR) return;
- if (!node && ruby_sourceline == 0) return;
-
- if (!(node_save = ruby_current_node)) {
- node_save = NEW_BEGIN(0);
- }
- tracing = 1;
- prev = ruby_frame;
- PUSH_FRAME();
- *ruby_frame = *prev;
- ruby_frame->prev = prev;
- ruby_frame->iter = 0; /* blocks not available anyway */
-
- if (node) {
- ruby_current_node = node;
- ruby_frame->node = node;
- ruby_sourcefile = node->nd_file;
- ruby_sourceline = nd_line(node);
- }
- if (klass) {
- if (TYPE(klass) == T_ICLASS) {
- klass = RBASIC(klass)->klass;
- }
- else if (FL_TEST(klass, FL_SINGLETON)) {
- klass = self;
- }
- }
- PUSH_TAG(PROT_NONE);
- raised = thread_reset_raised();
- if ((state = EXEC_TAG()) == 0) {
- srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
- event_name = get_event_name(event);
- proc_invoke(trace_func, rb_ary_new3(6, rb_str_new2(event_name),
- srcfile,
- INT2FIX(ruby_sourceline),
- id?ID2SYM(id):Qnil,
- self ? rb_f_binding(self) : Qnil,
- klass?klass:Qnil),
- Qundef, 0);
- }
- if (raised) thread_set_raised();
- POP_TAG();
- POP_FRAME();
-
- tracing = 0;
- ruby_current_node = node_save;
- SET_CURRENT_SOURCE();
- if (state) JUMP_TAG(state);
-}
-
-static VALUE
-avalue_to_svalue(v)
- VALUE v;
-{
- VALUE tmp, top;
-
- tmp = rb_check_array_type(v);
- if (NIL_P(tmp)) {
- return v;
- }
- if (RARRAY(tmp)->len == 0) {
- return Qundef;
- }
- if (RARRAY(tmp)->len == 1) {
- top = rb_check_array_type(RARRAY(tmp)->ptr[0]);
- if (NIL_P(top)) {
- return RARRAY(tmp)->ptr[0];
- }
- if (RARRAY(top)->len > 1) {
- return v;
- }
- return top;
- }
- return tmp;
-}
-
-static VALUE
-svalue_to_avalue(v)
- VALUE v;
-{
- VALUE tmp, top;
-
- if (v == Qundef) return rb_ary_new2(0);
- tmp = rb_check_array_type(v);
- if (NIL_P(tmp)) {
- return rb_ary_new3(1, v);
- }
- if (RARRAY(tmp)->len == 1) {
- top = rb_check_array_type(RARRAY(tmp)->ptr[0]);
- if (!NIL_P(top) && RARRAY(top)->len > 1) {
- return tmp;
- }
- return rb_ary_new3(1, v);
- }
- return tmp;
-}
-
-static VALUE
-svalue_to_mrhs(v, lhs)
- VALUE v;
- NODE *lhs;
-{
- VALUE tmp;
-
- if (v == Qundef) return rb_values_new2(0, 0);
- tmp = rb_check_array_type(v);
- if (NIL_P(tmp)) {
- return rb_values_new(1, v);
- }
- /* no lhs means splat lhs only */
- if (!lhs) {
- return rb_values_new(1, v);
- }
- return tmp;
-}
-
-static VALUE
-avalue_splat(v)
- VALUE v;
-{
- if (RARRAY(v)->len == 0) {
- return Qundef;
- }
- if (RARRAY(v)->len == 1) {
- return RARRAY(v)->ptr[0];
- }
- return v;
-}
-
-static VALUE
-splat_value(v)
- VALUE v;
-{
- VALUE val;
-
- if (NIL_P(v)) val = rb_ary_new3(1, Qnil);
- else val = rb_Array(v);
- return rb_values_from_ary(val);
-}
-
-static VALUE
-class_prefix(self, cpath)
- VALUE self;
- NODE *cpath;
-{
- if (!cpath) {
- rb_bug("class path missing");
- }
- if (cpath->nd_head) {
- VALUE c = rb_eval(self, cpath->nd_head);
- switch (TYPE(c)) {
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- rb_raise(rb_eTypeError, "%s is not a class/module",
- RSTRING(rb_obj_as_string(c))->ptr);
- }
- return c;
- }
- else if (nd_type(cpath) == NODE_COLON2) {
- return ruby_cbase;
- }
- else if (ruby_wrapper) {
- return ruby_wrapper;
- }
- else {
- return rb_cObject;
- }
-}
-
-#define return_value(v) do {\
- if ((prot_tag->retval = (v)) == Qundef) {\
- prot_tag->retval = Qnil;\
- }\
-} while (0)
-
-NORETURN(static void return_jump _((VALUE)));
-NORETURN(static void break_jump _((VALUE)));
-
-static VALUE
-rb_eval(self, n)
- VALUE self;
- NODE *n;
-{
- NODE * volatile contnode = 0;
- NODE * volatile node = n;
- int state;
- volatile VALUE result = Qnil;
-
-#define RETURN(v) do { \
- result = (v); \
- goto finish; \
-} while (0)
-
- again:
- if (!node) RETURN(Qnil);
-
- ruby_current_node = node;
- if (node->flags & NODE_NEWLINE) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- }
- switch (nd_type(node)) {
- case NODE_BLOCK:
- if (contnode) {
- result = rb_eval(self, node);
- break;
- }
- contnode = node->nd_next;
- node = node->nd_head;
- goto again;
-
- case NODE_POSTEXE:
- rb_f_END();
- nd_set_type(node, NODE_NIL); /* exec just once */
- result = Qnil;
- break;
-
- /* begin .. end without clauses */
- case NODE_BEGIN:
- node = node->nd_body;
- goto again;
-
- /* nodes for speed-up(default match) */
- case NODE_MATCH:
- result = rb_reg_match2(node->nd_lit);
- break;
-
- /* nodes for speed-up(literal match) */
- case NODE_MATCH2:
- {
- VALUE l = rb_eval(self,node->nd_recv);
- VALUE r = rb_eval(self,node->nd_value);
- result = rb_reg_match(l, r);
- }
- break;
-
- /* nodes for speed-up(literal match) */
- case NODE_MATCH3:
- {
- VALUE r = rb_eval(self,node->nd_recv);
- VALUE l = rb_eval(self,node->nd_value);
- if (TYPE(l) == T_STRING) {
- result = rb_reg_match(r, l);
- }
- else {
- result = rb_funcall(l, match, 1, r);
- }
- }
- break;
-
- /* node for speed-up(top-level loop for -n/-p) */
- case NODE_OPT_N:
- PUSH_TAG(PROT_LOOP);
- switch (state = EXEC_TAG()) {
- case 0:
- opt_n_next:
- while (!NIL_P(rb_gets())) {
- opt_n_redo:
- rb_eval(self, node->nd_body);
- }
- break;
-
- case TAG_REDO:
- state = 0;
- goto opt_n_redo;
- case TAG_NEXT:
- state = 0;
- goto opt_n_next;
- case TAG_BREAK:
- state = 0;
- default:
- break;
- }
- POP_TAG();
- if (state) JUMP_TAG(state);
- RETURN(Qnil);
-
- case NODE_SELF:
- RETURN(self);
-
- case NODE_NIL:
- RETURN(Qnil);
-
- case NODE_TRUE:
- RETURN(Qtrue);
-
- case NODE_FALSE:
- RETURN(Qfalse);
-
- case NODE_ERRINFO:
- RETURN(ruby_errinfo);
-
- case NODE_IF:
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- if (RTEST(rb_eval(self, node->nd_cond))) {
- node = node->nd_body;
- }
- else {
- node = node->nd_else;
- }
- goto again;
-
- case NODE_WHEN:
- while (node) {
- NODE *tag;
-
- if (nd_type(node) != NODE_WHEN) goto again;
- tag = node->nd_head;
- while (tag) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- VALUE v = rb_eval(self, tag->nd_head->nd_head);
- long i;
-
- if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- for (i=0; i<RARRAY(v)->len; i++) {
- if (RTEST(RARRAY(v)->ptr[i])) {
- node = node->nd_body;
- goto again;
- }
- }
- tag = tag->nd_next;
- continue;
- }
- if (RTEST(rb_eval(self, tag->nd_head))) {
- node = node->nd_body;
- goto again;
- }
- tag = tag->nd_next;
- }
- node = node->nd_next;
- }
- RETURN(Qnil);
-
- case NODE_CASE:
- {
- VALUE val;
-
- val = rb_eval(self, node->nd_head);
- node = node->nd_body;
- while (node) {
- NODE *tag;
-
- if (nd_type(node) != NODE_WHEN) {
- goto again;
- }
- tag = node->nd_head;
- while (tag) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- VALUE v = rb_eval(self, tag->nd_head->nd_head);
- long i;
-
- if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- for (i=0; i<RARRAY(v)->len; i++) {
- if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
- node = node->nd_body;
- goto again;
- }
- }
- tag = tag->nd_next;
- continue;
- }
- if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val))) {
- node = node->nd_body;
- goto again;
- }
- tag = tag->nd_next;
- }
- node = node->nd_next;
- }
- }
- RETURN(Qnil);
-
- case NODE_WHILE:
- PUSH_TAG(PROT_LOOP);
- result = Qnil;
- switch (state = EXEC_TAG()) {
- case 0:
- if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
- goto while_out;
- do {
- while_redo:
- rb_eval(self, node->nd_body);
- while_next:
- ;
- } while (RTEST(rb_eval(self, node->nd_cond)));
- break;
-
- case TAG_REDO:
- state = 0;
- goto while_redo;
- case TAG_NEXT:
- state = 0;
- goto while_next;
- case TAG_BREAK:
- if (TAG_DST()) {
- state = 0;
- result = prot_tag->retval;
- }
- /* fall through */
- default:
- break;
- }
- while_out:
- POP_TAG();
- if (state) JUMP_TAG(state);
- RETURN(result);
-
- case NODE_UNTIL:
- PUSH_TAG(PROT_LOOP);
- result = Qnil;
- switch (state = EXEC_TAG()) {
- case 0:
- if (node->nd_state && RTEST(rb_eval(self, node->nd_cond)))
- goto until_out;
- do {
- until_redo:
- rb_eval(self, node->nd_body);
- until_next:
- ;
- } while (!RTEST(rb_eval(self, node->nd_cond)));
- break;
-
- case TAG_REDO:
- state = 0;
- goto until_redo;
- case TAG_NEXT:
- state = 0;
- goto until_next;
- case TAG_BREAK:
- if (TAG_DST()) {
- state = 0;
- result = prot_tag->retval;
- }
- /* fall through */
- default:
- break;
- }
- until_out:
- POP_TAG();
- if (state) JUMP_TAG(state);
- RETURN(result);
-
- case NODE_BLOCK_PASS:
- result = block_pass(self, node);
- break;
-
- case NODE_ITER:
- case NODE_FOR:
- case NODE_LAMBDA:
- {
- PUSH_TAG(PROT_LOOP);
- PUSH_BLOCK(node->nd_var, node->nd_body);
-
- state = EXEC_TAG();
- if (state == 0) {
- iter_retry:
- PUSH_ITER(ITER_PRE);
- if (nd_type(node) == NODE_ITER) {
- result = rb_eval(self, node->nd_iter);
- }
- else if (nd_type(node) == NODE_LAMBDA) {
- ruby_iter->iter = ruby_frame->iter = ITER_CUR;
- result = rb_block_proc();
- }
- else {
- VALUE recv;
-
- _block.flags &= ~BLOCK_D_SCOPE;
- BEGIN_CALLARGS;
- recv = rb_eval(self, node->nd_iter);
- END_CALLARGS;
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
- }
- POP_ITER();
- }
- else if (state == TAG_BREAK && TAG_DST()) {
- result = prot_tag->retval;
- state = 0;
- }
- else if (state == TAG_RETRY && ruby_block == &_block) {
- state = 0;
- goto iter_retry;
- }
- POP_BLOCK();
- POP_TAG();
- switch (state) {
- case 0:
- break;
- default:
- JUMP_TAG(state);
- }
- }
- break;
-
- case NODE_BREAK:
- break_jump(rb_eval(self, node->nd_stts));
- break;
-
- case NODE_NEXT:
- CHECK_INTS;
- return_value(rb_eval(self, node->nd_stts));
- JUMP_TAG(TAG_NEXT);
- break;
-
- case NODE_REDO:
- CHECK_INTS;
- JUMP_TAG(TAG_REDO);
- break;
-
- case NODE_RETRY:
- CHECK_INTS;
- JUMP_TAG(TAG_RETRY);
- break;
-
- case NODE_SPLAT:
- result = splat_value(rb_eval(self, node->nd_head));
- break;
-
- case NODE_TO_ARY:
- result = rb_ary_to_ary(rb_eval(self, node->nd_head));
- break;
-
- case NODE_SVALUE:
- result = avalue_splat(rb_eval(self, node->nd_head));
- if (result == Qundef) result = Qnil;
- break;
-
- case NODE_YIELD:
- if (node->nd_head) {
- result = rb_eval(self, node->nd_head);
- ruby_current_node = node;
- }
- else {
- result = Qundef; /* no arg */
- }
- SET_CURRENT_SOURCE();
- result = rb_yield_0(result, 0, 0, 0, node->nd_state);
- break;
-
- case NODE_RESCUE:
- {
- volatile VALUE e_info = ruby_errinfo;
- volatile int rescuing = 0;
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- retry_entry:
- result = rb_eval(self, node->nd_head);
- }
- else if (rescuing) {
- if (rescuing < 0) {
- /* in rescue argument, just reraise */
- }
- else if (state == TAG_RETRY) {
- rescuing = state = 0;
- ruby_errinfo = e_info;
- goto retry_entry;
- }
- else if (state != TAG_RAISE) {
- result = prot_tag->retval;
- }
- }
- else if (state == TAG_RAISE) {
- NODE *resq = node->nd_resq;
-
- rescuing = -1;
- while (resq) {
- ruby_current_node = resq;
- if (handle_rescue(self, resq)) {
- state = 0;
- rescuing = 1;
- result = rb_eval(self, resq->nd_body);
- break;
- }
- resq = resq->nd_head; /* next rescue */
- }
- }
- else {
- result = prot_tag->retval;
- }
- POP_TAG();
- if (state != TAG_RAISE) ruby_errinfo = e_info;
- if (state) {
- if (state == TAG_NEXT) prot_tag->retval = result;
- JUMP_TAG(state);
- }
- /* no exception raised */
- if (!rescuing && (node = node->nd_else)) { /* else clause given */
- goto again;
- }
- }
- break;
-
- case NODE_ENSURE:
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_head);
- }
- POP_TAG();
- if (node->nd_ensr) {
- VALUE retval = prot_tag->retval; /* save retval */
- VALUE errinfo = ruby_errinfo;
-
- rb_eval(self, node->nd_ensr);
- return_value(retval);
- ruby_errinfo = errinfo;
- }
- if (state) JUMP_TAG(state);
- break;
-
- case NODE_AND:
- result = rb_eval(self, node->nd_1st);
- if (!RTEST(result)) break;
- node = node->nd_2nd;
- goto again;
-
- case NODE_OR:
- result = rb_eval(self, node->nd_1st);
- if (RTEST(result)) break;
- node = node->nd_2nd;
- goto again;
-
- case NODE_NOT:
- if (RTEST(rb_eval(self, node->nd_body))) result = Qfalse;
- else result = Qtrue;
- break;
-
- case NODE_DOT2:
- case NODE_DOT3:
- result = rb_range_new(rb_eval(self, node->nd_beg),
- rb_eval(self, node->nd_end),
- nd_type(node) == NODE_DOT3);
- break;
-
- case NODE_FLIP2: /* like AWK */
- {
- VALUE *flip = rb_svar(node->nd_cnt);
- if (!flip) rb_bug("unexpected local variable");
- if (!RTEST(*flip)) {
- if (RTEST(rb_eval(self, node->nd_beg))) {
- *flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
- result = Qtrue;
- }
- else {
- result = Qfalse;
- }
- }
- else {
- if (RTEST(rb_eval(self, node->nd_end))) {
- *flip = Qfalse;
- }
- result = Qtrue;
- }
- }
- break;
-
- case NODE_FLIP3: /* like SED */
- {
- VALUE *flip = rb_svar(node->nd_cnt);
- if (!flip) rb_bug("unexpected local variable");
- if (!RTEST(*flip)) {
- result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse;
- *flip = result;
- }
- else {
- if (RTEST(rb_eval(self, node->nd_end))) {
- *flip = Qfalse;
- }
- result = Qtrue;
- }
- }
- break;
-
- case NODE_RETURN:
- return_jump(rb_eval(self, node->nd_stts));
- break;
-
- case NODE_ARGSCAT:
- {
- VALUE args = rb_eval(self, node->nd_head);
- result = rb_ary_concat(args, splat_value(rb_eval(self, node->nd_body)));
- }
- break;
-
- case NODE_ARGSPUSH:
- {
- VALUE args = rb_ary_dup(rb_eval(self, node->nd_head));
- result = rb_ary_push(args, rb_eval(self, node->nd_body));
- }
- break;
-
- case NODE_ATTRASGN:
- {
- VALUE recv;
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- int scope;
- TMP_PROTECT;
-
- BEGIN_CALLARGS;
- if (node->nd_recv == (NODE *)1) {
- recv = self;
- scope = 1;
- }
- else {
- recv = rb_eval(self, node->nd_recv);
- scope = 0;
- }
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope);
- result = argv[argc-1];
- }
- break;
-
- case NODE_CALL:
- {
- VALUE recv;
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- BEGIN_CALLARGS;
- recv = rb_eval(self, node->nd_recv);
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
- }
- break;
-
- case NODE_FCALL:
- {
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- BEGIN_CALLARGS;
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
- }
- break;
-
- case NODE_VCALL:
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2);
- break;
-
- case NODE_SUPER:
- case NODE_ZSUPER:
- {
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- if (ruby_frame->this_class == 0) {
- if (ruby_frame->this_func) {
- rb_name_error(ruby_frame->callee,
- "superclass method `%s' disabled",
- rb_id2name(ruby_frame->this_func));
- }
- else {
- rb_raise(rb_eNoMethodError, "super called outside of method");
- }
- }
- if (nd_type(node) == NODE_ZSUPER) {
- argc = ruby_frame->argc;
- if (argc && ruby_frame->prev &&
- (ruby_frame->prev->flags & FRAME_DMETH)) {
- if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||
- RARRAY(RBASIC(ruby_scope)->klass)->len != argc) {
- rb_raise(rb_eRuntimeError,
- "super: specify arguments explicitly");
- }
- argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
- }
- else {
- argv = ruby_scope->local_vars + 2;
- }
- }
- else {
- BEGIN_CALLARGS;
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
- ruby_current_node = node;
- }
-
- SET_CURRENT_SOURCE();
- result = rb_call_super(argc, argv);
- }
- break;
-
- case NODE_SCOPE:
- {
- struct FRAME frame;
- NODE *saved_cref = 0;
-
- frame = *ruby_frame;
- frame.tmp = ruby_frame;
- ruby_frame = &frame;
-
- PUSH_SCOPE();
- PUSH_TAG(PROT_NONE);
- if (node->nd_rval) {
- saved_cref = ruby_cref;
- ruby_cref = (NODE*)node->nd_rval;
- }
- if (node->nd_tbl) {
- VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
- *vars++ = (VALUE)node;
- ruby_scope->local_vars = vars;
- rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
- ruby_scope->local_tbl = node->nd_tbl;
- }
- else {
- ruby_scope->local_vars = 0;
- ruby_scope->local_tbl = 0;
- }
- if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_next);
- }
- POP_TAG();
- POP_SCOPE();
- ruby_frame = frame.tmp;
- if (saved_cref)
- ruby_cref = saved_cref;
- if (state) JUMP_TAG(state);
- }
- break;
-
- case NODE_OP_ASGN1:
- {
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- VALUE recv, val;
- NODE *rval;
- TMP_PROTECT;
-
- recv = rb_eval(self, node->nd_recv);
- rval = node->nd_args->nd_head;
- SETUP_ARGS0(node->nd_args->nd_next, node->nd_args->nd_alen - 1);
- val = rb_funcall2(recv, aref, argc-1, argv);
- switch (node->nd_mid) {
- case 0: /* OR */
- if (RTEST(val)) RETURN(val);
- val = rb_eval(self, rval);
- break;
- case 1: /* AND */
- if (!RTEST(val)) RETURN(val);
- val = rb_eval(self, rval);
- break;
- default:
- val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
- }
- argv[argc-1] = val;
- rb_funcall2(recv, aset, argc, argv);
- result = val;
- }
- break;
-
- case NODE_OP_ASGN2:
- {
- ID id = node->nd_next->nd_vid;
- VALUE recv, val;
-
- recv = rb_eval(self, node->nd_recv);
- val = rb_funcall(recv, id, 0);
- switch (node->nd_next->nd_mid) {
- case 0: /* OR */
- if (RTEST(val)) RETURN(val);
- val = rb_eval(self, node->nd_value);
- break;
- case 1: /* AND */
- if (!RTEST(val)) RETURN(val);
- val = rb_eval(self, node->nd_value);
- break;
- default:
- val = rb_funcall(val, node->nd_next->nd_mid, 1,
- rb_eval(self, node->nd_value));
- }
-
- rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
- result = val;
- }
- break;
-
- case NODE_OP_ASGN_AND:
- result = rb_eval(self, node->nd_head);
- if (!RTEST(result)) break;
- node = node->nd_value;
- goto again;
-
- case NODE_OP_ASGN_OR:
- if ((node->nd_aid && !is_defined(self, node->nd_head, 0, 0)) ||
- !RTEST(result = rb_eval(self, node->nd_head))) {
- node = node->nd_value;
- goto again;
- }
- break;
-
- case NODE_MASGN:
- result = massign(self, node, rb_eval(self, node->nd_value), 0);
- break;
-
- case NODE_LASGN:
- if (ruby_scope->local_vars == 0)
- rb_bug("unexpected local variable assignment");
- result = rb_eval(self, node->nd_value);
- ruby_scope->local_vars[node->nd_cnt] = result;
- break;
-
- case NODE_DASGN:
- result = rb_eval(self, node->nd_value);
- dvar_asgn(node->nd_vid, result);
- break;
-
- case NODE_DASGN_CURR:
- result = rb_eval(self, node->nd_value);
- dvar_asgn_curr(node->nd_vid, result);
- break;
-
- case NODE_GASGN:
- result = rb_eval(self, node->nd_value);
- rb_gvar_set(node->nd_entry, result);
- break;
-
- case NODE_IASGN:
- result = rb_eval(self, node->nd_value);
- rb_ivar_set(self, node->nd_vid, result);
- break;
-
- case NODE_CDECL:
- result = rb_eval(self, node->nd_value);
- if (node->nd_vid == 0) {
- rb_const_set(class_prefix(self, node->nd_else), node->nd_else->nd_mid, result);
- }
- else {
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no class/module to define constant");
- }
- rb_const_set(ruby_cbase, node->nd_vid, result);
- }
- break;
-
- case NODE_CVDECL:
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no class/module to define class variable");
- }
- result = rb_eval(self, node->nd_value);
- rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qtrue);
- break;
-
- case NODE_CVASGN:
- result = rb_eval(self, node->nd_value);
- rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qfalse);
- break;
-
- case NODE_LVAR:
- if (ruby_scope->local_vars == 0) {
- rb_bug("unexpected local variable");
- }
- result = ruby_scope->local_vars[node->nd_cnt];
- break;
-
- case NODE_DVAR:
- result = rb_dvar_ref(node->nd_vid);
- break;
-
- case NODE_GVAR:
- result = rb_gvar_get(node->nd_entry);
- break;
-
- case NODE_IVAR:
- result = rb_ivar_get(self, node->nd_vid);
- break;
-
- case NODE_CONST:
- result = ev_const_get(ruby_cref, node->nd_vid, self);
- break;
-
- case NODE_CVAR:
- result = rb_cvar_get(cvar_cbase(), node->nd_vid);
- break;
-
- case NODE_BLOCK_ARG:
- if (ruby_scope->local_vars == 0)
- rb_bug("unexpected block argument");
- if (rb_block_given_p()) {
- result = rb_block_proc();
- ruby_scope->local_vars[node->nd_cnt] = result;
- }
- else {
- result = Qnil;
- }
- break;
-
- case NODE_COLON2:
- {
- VALUE klass;
-
- klass = rb_eval(self, node->nd_head);
- if (rb_is_const_id(node->nd_mid)) {
- switch (TYPE(klass)) {
- case T_CLASS:
- case T_MODULE:
- result = rb_const_get_from(klass, node->nd_mid);
- break;
- default:
- rb_raise(rb_eTypeError, "%s is not a class/module",
- RSTRING(rb_obj_as_string(klass))->ptr);
- break;
- }
- }
- else {
- result = rb_funcall(klass, node->nd_mid, 0, 0);
- }
- }
- break;
-
- case NODE_COLON3:
- result = rb_const_get_from(rb_cObject, node->nd_mid);
- break;
-
- case NODE_NTH_REF:
- result = rb_reg_nth_match(node->nd_nth, MATCH_DATA);
- break;
-
- case NODE_BACK_REF:
- switch (node->nd_nth) {
- case '&':
- result = rb_reg_last_match(MATCH_DATA);
- break;
- case '`':
- result = rb_reg_match_pre(MATCH_DATA);
- break;
- case '\'':
- result = rb_reg_match_post(MATCH_DATA);
- break;
- case '+':
- result = rb_reg_match_last(MATCH_DATA);
- break;
- default:
- rb_bug("unexpected back-ref");
- }
- break;
-
- case NODE_HASH:
- {
- NODE *list;
- VALUE hash = rb_hash_new();
- VALUE key, val;
-
- list = node->nd_head;
- while (list) {
- key = rb_eval(self, list->nd_head);
- list = list->nd_next;
- if (list == 0)
- rb_bug("odd number list for Hash");
- val = rb_eval(self, list->nd_head);
- list = list->nd_next;
- rb_hash_aset(hash, key, val);
- }
- result = hash;
- }
- break;
-
- case NODE_ZARRAY: /* zero length list */
- result = rb_ary_new();
- break;
-
- case NODE_ARRAY:
- {
- VALUE ary;
- long i;
-
- i = node->nd_alen;
- ary = rb_ary_new2(i);
- for (i=0;node;node=node->nd_next) {
- RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
- RARRAY(ary)->len = i;
- }
-
- result = ary;
- }
- break;
-
- case NODE_VALUES:
- {
- VALUE val;
- long i;
-
- i = node->nd_alen;
- val = rb_values_new2(i, 0);
- for (i=0;node;node=node->nd_next) {
- RARRAY(val)->ptr[i++] = rb_eval(self, node->nd_head);
- RARRAY(val)->len = i;
- }
-
- result = val;
- }
- break;
-
- case NODE_STR:
- result = rb_str_new3(node->nd_lit);
- break;
-
- case NODE_EVSTR:
- result = rb_obj_as_string(rb_eval(self, node->nd_body));
- break;
-
- case NODE_DSTR:
- case NODE_DXSTR:
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- case NODE_DSYM:
- {
- VALUE str, str2;
- NODE *list = node->nd_next;
-
- str = rb_str_new3(node->nd_lit);
- while (list) {
- if (list->nd_head) {
- switch (nd_type(list->nd_head)) {
- case NODE_STR:
- str2 = list->nd_head->nd_lit;
- break;
- default:
- str2 = rb_eval(self, list->nd_head);
- break;
- }
- rb_str_append(str, str2);
- OBJ_INFECT(str, str2);
- }
- list = list->nd_next;
- }
- switch (nd_type(node)) {
- case NODE_DREGX:
- result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- node->nd_cflag);
- break;
- case NODE_DREGX_ONCE: /* regexp expand once */
- result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- node->nd_cflag);
- nd_set_type(node, NODE_LIT);
- node->nd_lit = result;
- break;
- case NODE_LIT:
- /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */
- goto again;
- case NODE_DXSTR:
- result = rb_funcall(self, '`', 1, str);
- break;
- case NODE_DSYM:
- result = rb_str_intern(str);
- break;
- default:
- result = str;
- break;
- }
- }
- break;
-
- case NODE_XSTR:
- result = rb_funcall(self, '`', 1, rb_str_new3(node->nd_lit));
- break;
-
- case NODE_LIT:
- result = node->nd_lit;
- break;
-
- case NODE_DEFN:
- if (node->nd_defn) {
- NODE *body, *defn;
- VALUE origin;
- int noex;
-
- if (NIL_P(ruby_class)) {
- rb_raise(rb_eTypeError, "no class/module to add method");
- }
- if (ruby_class == rb_cObject && node->nd_mid == init) {
- rb_warn("redefining Object#initialize may cause infinite loop");
- }
- if (node->nd_mid == __id__ || node->nd_mid == __send__) {
- rb_warn("redefining `%s' may cause serious problem",
- rb_id2name(node->nd_mid));
- }
- rb_frozen_class_p(ruby_class);
- body = search_method(ruby_class, node->nd_mid, &origin);
- if (body){
- if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0 && body->nd_body) {
- rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid));
- }
- }
-
- if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
- noex = NOEX_PRIVATE;
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
- }
- if (body && origin == ruby_class && body->nd_body == 0) {
- noex |= NOEX_NOSUPER;
- }
-
- defn = copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(ruby_class, node->nd_mid, defn, noex);
- if (scope_vmode == SCOPE_MODFUNC) {
- rb_add_method(rb_singleton_class(ruby_class),
- node->nd_mid, defn, NOEX_PUBLIC);
- }
- result = Qnil;
- }
- break;
-
- case NODE_DEFS:
- if (node->nd_defn) {
- VALUE recv = rb_eval(self, node->nd_recv);
- VALUE klass;
- NODE *body = 0, *defn;
-
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(recv)) {
- rb_raise(rb_eSecurityError, "Insecure: can't define singleton method");
- }
- if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
- rb_raise(rb_eTypeError,
- "can't define singleton method \"%s\" for %s",
- rb_id2name(node->nd_mid),
- rb_obj_classname(recv));
- }
-
- if (OBJ_FROZEN(recv)) rb_error_frozen("object");
- klass = rb_singleton_class(recv);
- if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, (st_data_t *)&body)) {
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "redefining method prohibited");
- }
- if (RTEST(ruby_verbose)) {
- rb_warning("redefine %s", rb_id2name(node->nd_mid));
- }
- }
- defn = copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(klass, node->nd_mid, defn,
- NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
- result = Qnil;
- }
- break;
-
- case NODE_UNDEF:
- if (NIL_P(ruby_class)) {
- rb_raise(rb_eTypeError, "no class to undef method");
- }
- rb_undef(ruby_class, rb_to_id(rb_eval(self, node->u2.node)));
- result = Qnil;
- break;
-
- case NODE_ALIAS:
- if (NIL_P(ruby_class)) {
- rb_raise(rb_eTypeError, "no class to make alias");
- }
- rb_alias(ruby_class, rb_to_id(rb_eval(self, node->u1.node)),
- rb_to_id(rb_eval(self, node->u2.node)));
- result = Qnil;
- break;
-
- case NODE_VALIAS:
- rb_alias_variable(node->u1.id, node->u2.id);
- result = Qnil;
- break;
-
- case NODE_CLASS:
- {
- VALUE super, klass, tmp, cbase;
- ID cname;
- int gen = Qfalse;
-
- cbase = class_prefix(self, node->nd_cpath);
- cname = node->nd_cpath->nd_mid;
-
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no outer class/module");
- }
- if (node->nd_super) {
- super = rb_eval(self, node->nd_super);
- rb_check_inheritable(super);
- }
- else {
- super = 0;
- }
-
- if (rb_const_defined_at(cbase, cname)) {
- klass = rb_const_get_at(cbase, cname);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class",
- rb_id2name(cname));
- }
- if (super) {
- tmp = rb_class_real(RCLASS(klass)->super);
- if (tmp != super) {
- rb_raise(rb_eTypeError, "superclass mismatch for class %s",
- rb_id2name(cname));
- }
- super = 0;
- }
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "extending class prohibited");
- }
- }
- else {
- if (!super) super = rb_cObject;
- klass = rb_define_class_id(cname, super);
- rb_set_class_path(klass, cbase, rb_id2name(cname));
- rb_const_set(cbase, cname, klass);
- gen = Qtrue;
- }
- if (ruby_wrapper) {
- rb_extend_object(klass, ruby_wrapper);
- rb_include_module(klass, ruby_wrapper);
- }
- if (super && gen) {
- rb_class_inherited(super, klass);
- }
- result = module_setup(klass, node);
- }
- break;
-
- case NODE_MODULE:
- {
- VALUE module, cbase;
- ID cname;
-
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no outer class/module");
- }
- cbase = class_prefix(self, node->nd_cpath);
- cname = node->nd_cpath->nd_mid;
- if (rb_const_defined_at(cbase, cname)) {
- module = rb_const_get_at(cbase, cname);
- if (TYPE(module) != T_MODULE) {
- rb_raise(rb_eTypeError, "%s is not a module",
- rb_id2name(cname));
- }
- if (ruby_safe_level >= 4) {
- rb_raise(rb_eSecurityError, "extending module prohibited");
- }
- }
- else {
- module = rb_define_module_id(cname);
- rb_set_class_path(module, cbase, rb_id2name(cname));
- rb_const_set(cbase, cname, module);
- }
- if (ruby_wrapper) {
- rb_extend_object(module, ruby_wrapper);
- rb_include_module(module, ruby_wrapper);
- }
-
- result = module_setup(module, node);
- }
- break;
-
- case NODE_SCLASS:
- {
- VALUE klass;
-
- result = rb_eval(self, node->nd_recv);
- if (FIXNUM_P(result) || SYMBOL_P(result)) {
- rb_raise(rb_eTypeError, "no singleton class for %s",
- rb_obj_classname(result));
- }
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(result))
- rb_raise(rb_eSecurityError, "Insecure: can't extend object");
- klass = rb_singleton_class(result);
-
- if (ruby_wrapper) {
- rb_extend_object(klass, ruby_wrapper);
- rb_include_module(klass, ruby_wrapper);
- }
-
- result = module_setup(klass, node);
- }
- break;
-
- case NODE_DEFINED:
- {
- char buf[20];
- const char *desc = is_defined(self, node->nd_head, buf, 0);
-
- if (desc) result = rb_str_new2(desc);
- else result = Qnil;
- }
- break;
-
- default:
- rb_bug("unknown node type %d", nd_type(node));
- }
- finish:
- CHECK_INTS;
- if (contnode) {
- node = contnode;
- contnode = 0;
- goto again;
- }
- return result;
-}
-
-static VALUE
-module_setup(module, n)
- VALUE module;
- NODE *n;
-{
- NODE * volatile node = n->nd_body;
- int state;
- struct FRAME frame;
- VALUE result = Qnil; /* OK */
- TMP_PROTECT;
-
- frame = *ruby_frame;
- frame.tmp = ruby_frame;
- ruby_frame = &frame;
-
- PUSH_CLASS(module);
- PUSH_SCOPE();
- PUSH_VARS();
-
- if (node->nd_tbl) {
- VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
- *vars++ = (VALUE)node;
- ruby_scope->local_vars = vars;
- rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
- ruby_scope->local_tbl = node->nd_tbl;
- }
- else {
- ruby_scope->local_vars = 0;
- ruby_scope->local_tbl = 0;
- }
-
- PUSH_CREF(module);
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- EXEC_EVENT_HOOK(RUBY_EVENT_CLASS, n, ruby_cbase,
- ruby_frame->this_func, ruby_frame->this_class);
- result = rb_eval(ruby_cbase, node->nd_next);
- }
- POP_TAG();
- POP_CREF();
- POP_VARS();
- POP_SCOPE();
- POP_CLASS();
-
- ruby_frame = frame.tmp;
- EXEC_EVENT_HOOK(RUBY_EVENT_END, n, 0, ruby_frame->this_func,
- ruby_frame->this_class);
- if (state) JUMP_TAG(state);
-
- return result;
-}
-
-static NODE *basic_respond_to = 0;
-
-int
-rb_respond_to(obj, id)
- VALUE obj;
- ID id;
-{
- VALUE klass = CLASS_OF(obj);
- if (rb_method_node(klass, respond_to) == basic_respond_to &&
- rb_method_boundp(klass, id, 0)) {
- return Qtrue;
- }
- else{
- return rb_funcall(obj, respond_to, 1, ID2SYM(id));
- }
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * obj.respond_to?(symbol, include_private=false) => true or false
- *
- * Returns +true+> if _obj_ responds to the given
- * method. Private methods are included in the search only if the
- * optional second parameter evaluates to +true+.
- */
-
-static VALUE
-rb_obj_respond_to(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE mid, priv;
- ID id;
-
- rb_scan_args(argc, argv, "11", &mid, &priv);
- id = rb_to_id(mid);
- if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * mod.method_defined?(symbol) => true or false
- *
- * Returns +true+ if the named method is defined by
- * _mod_ (or its included modules and, if _mod_ is a class,
- * its ancestors). Public and protected methods are matched.
- *
- * module A
- * def method1() end
- * end
- * class B
- * def method2() end
- * end
- * class C < B
- * include A
- * def method3() end
- * end
- *
- * A.method_defined? :method1 #=> true
- * C.method_defined? "method1" #=> true
- * C.method_defined? "method2" #=> true
- * C.method_defined? "method3" #=> true
- * C.method_defined? "method4" #=> false
- */
-
-static VALUE
-rb_mod_method_defined(mod, mid)
- VALUE mod, mid;
-{
- return rb_method_boundp(mod, rb_to_id(mid), 1);
-}
-
-#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
-
-/*
- * call-seq:
- * mod.public_method_defined?(symbol) => true or false
- *
- * Returns +true+ if the named public method is defined by
- * _mod_ (or its included modules and, if _mod_ is a class,
- * its ancestors).
- *
- * module A
- * def method1() end
- * end
- * class B
- * protected
- * def method2() end
- * end
- * class C < B
- * include A
- * def method3() end
- * end
- *
- * A.method_defined? :method1 #=> true
- * C.public_method_defined? "method1" #=> true
- * C.public_method_defined? "method2" #=> false
- * C.method_defined? "method2" #=> true
- */
-
-static VALUE
-rb_mod_public_method_defined(mod, mid)
- VALUE mod, mid;
-{
- ID id = rb_to_id(mid);
- int noex;
-
- if (rb_get_method_body(&mod, &id, &noex)) {
- if (VISI_CHECK(noex, NOEX_PUBLIC))
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * mod.private_method_defined?(symbol) => true or false
- *
- * Returns +true+ if the named private method is defined by
- * _ mod_ (or its included modules and, if _mod_ is a class,
- * its ancestors).
- *
- * module A
- * def method1() end
- * end
- * class B
- * private
- * def method2() end
- * end
- * class C < B
- * include A
- * def method3() end
- * end
- *
- * A.method_defined? :method1 #=> true
- * C.private_method_defined? "method1" #=> false
- * C.private_method_defined? "method2" #=> true
- * C.method_defined? "method2" #=> false
- */
-
-static VALUE
-rb_mod_private_method_defined(mod, mid)
- VALUE mod, mid;
-{
- ID id = rb_to_id(mid);
- int noex;
-
- if (rb_get_method_body(&mod, &id, &noex)) {
- if (VISI_CHECK(noex, NOEX_PRIVATE))
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * mod.protected_method_defined?(symbol) => true or false
- *
- * Returns +true+ if the named protected method is defined
- * by _mod_ (or its included modules and, if _mod_ is a
- * class, its ancestors).
- *
- * module A
- * def method1() end
- * end
- * class B
- * protected
- * def method2() end
- * end
- * class C < B
- * include A
- * def method3() end
- * end
- *
- * A.method_defined? :method1 #=> true
- * C.protected_method_defined? "method1" #=> false
- * C.protected_method_defined? "method2" #=> true
- * C.method_defined? "method2" #=> true
- */
-
-static VALUE
-rb_mod_protected_method_defined(mod, mid)
- VALUE mod, mid;
-{
- ID id = rb_to_id(mid);
- int noex;
-
- if (rb_get_method_body(&mod, &id, &noex)) {
- if (VISI_CHECK(noex, NOEX_PROTECTED))
- return Qtrue;
- }
- return Qfalse;
-}
-
-NORETURN(static VALUE terminate_process _((int, const char *, long)));
-static VALUE
-terminate_process(status, mesg, mlen)
- int status;
- const char *mesg;
- long mlen;
-{
- VALUE args[2];
- args[0] = INT2NUM(status);
- args[1] = rb_str_new(mesg, mlen);
-
- rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
-}
-
-void
-rb_exit(status)
- int status;
-{
- if (prot_tag) {
- terminate_process(status, "exit", 4);
- }
- ruby_finalize();
- exit(status);
-}
-
-
-/*
- * call-seq:
- * exit(integer=0)
- * Kernel::exit(integer=0)
- * Process::exit(integer=0)
- *
- * Initiates the termination of the Ruby script by raising the
- * <code>SystemExit</code> exception. This exception may be caught. The
- * optional parameter is used to return a status code to the invoking
- * environment.
- *
- * begin
- * exit
- * puts "never get here"
- * rescue SystemExit
- * puts "rescued a SystemExit exception"
- * end
- * puts "after begin block"
- *
- * <em>produces:</em>
- *
- * rescued a SystemExit exception
- * after begin block
- *
- * Just prior to termination, Ruby executes any <code>at_exit</code> functions
- * (see Kernel::at_exit) and runs any object finalizers (see
- * ObjectSpace::define_finalizer).
- *
- * at_exit { puts "at_exit function" }
- * ObjectSpace.define_finalizer("string", proc { puts "in finalizer" })
- * exit
- *
- * <em>produces:</em>
- *
- * at_exit function
- * in finalizer
- */
-
-VALUE
-rb_f_exit(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE status;
- int istatus;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "01", &status) == 1) {
- switch (status) {
- case Qtrue:
- istatus = EXIT_SUCCESS;
- break;
- case Qfalse:
- istatus = EXIT_FAILURE;
- break;
- default:
- istatus = NUM2INT(status);
- break;
- }
- }
- else {
- istatus = EXIT_SUCCESS;
- }
- rb_exit(istatus);
- return Qnil; /* not reached */
-}
-
-
-/*
- * call-seq:
- * abort
- * Kernel::abort
- * Process::abort
- *
- * Terminate execution immediately, effectively by calling
- * <code>Kernel.exit(1)</code>. If _msg_ is given, it is written
- * to STDERR prior to terminating.
- */
-
-VALUE
-rb_f_abort(argc, argv)
- int argc;
- VALUE *argv;
-{
- rb_secure(4);
- if (argc == 0) {
- if (!NIL_P(ruby_errinfo)) {
- error_print();
- }
- rb_exit(EXIT_FAILURE);
- }
- else {
- VALUE mesg;
-
- rb_scan_args(argc, argv, "1", &mesg);
- StringValue(argv[0]);
- rb_io_puts(argc, argv, rb_stderr);
- terminate_process(EXIT_FAILURE, RSTRING(argv[0])->ptr, RSTRING(argv[0])->len);
- }
- return Qnil; /* not reached */
-}
-
-void
-rb_iter_break()
-{
- break_jump(Qnil);
-}
-
-NORETURN(static void rb_longjmp _((int, VALUE)));
-static VALUE make_backtrace _((void));
-
-static void
-rb_longjmp(tag, mesg)
- int tag;
- VALUE mesg;
-{
- VALUE at;
-
- if (thread_set_raised()) {
- ruby_errinfo = exception_error;
- JUMP_TAG(TAG_FATAL);
- }
- if (NIL_P(mesg)) mesg = ruby_errinfo;
- if (NIL_P(mesg)) {
- mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
- }
-
- ruby_set_current_source();
- if (ruby_sourcefile && !NIL_P(mesg)) {
- at = get_backtrace(mesg);
- if (NIL_P(at)) {
- at = make_backtrace();
- set_backtrace(mesg, at);
- }
- }
- if (!NIL_P(mesg)) {
- ruby_errinfo = mesg;
- }
-
- if (RTEST(ruby_debug) && !NIL_P(ruby_errinfo)
- && !rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
- VALUE e = ruby_errinfo;
- int status;
-
- PUSH_TAG(PROT_NONE);
- if ((status = EXEC_TAG()) == 0) {
- e = rb_obj_as_string(e);
- warn_printf("Exception `%s' at %s:%d - %s\n",
- rb_obj_classname(ruby_errinfo),
- ruby_sourcefile, ruby_sourceline,
- RSTRING(e)->ptr);
- }
- POP_TAG();
- if (status == TAG_FATAL && ruby_errinfo == exception_error) {
- ruby_errinfo = mesg;
- }
- else if (status) {
- thread_reset_raised();
- JUMP_TAG(status);
- }
- }
-
- rb_trap_restore_mask();
- if (tag != TAG_FATAL) {
- EXEC_EVENT_HOOK(RUBY_EVENT_RAISE, ruby_current_node,
- ruby_frame->self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- }
- if (!prot_tag) {
- error_print();
- }
- thread_reset_raised();
- JUMP_TAG(tag);
-}
-
-void
-rb_exc_raise(mesg)
- VALUE mesg;
-{
- rb_longjmp(TAG_RAISE, mesg);
-}
-
-void
-rb_exc_fatal(mesg)
- VALUE mesg;
-{
- rb_longjmp(TAG_FATAL, mesg);
-}
-
-void
-rb_interrupt()
-{
- rb_raise(rb_eInterrupt, "");
-}
-
-/*
- * call-seq:
- * raise
- * raise(string)
- * raise(exception [, string [, array]])
- * fail
- * fail(string)
- * fail(exception [, string [, array]])
- *
- * With no arguments, raises the exception in <code>$!</code> or raises
- * a <code>RuntimeError</code> if <code>$!</code> is +nil+.
- * With a single +String+ argument, raises a
- * +RuntimeError+ with the string as a message. Otherwise,
- * the first parameter should be the name of an +Exception+
- * class (or an object that returns an +Exception+ object when sent
- * an +exception+ message). The optional second parameter sets the
- * message associated with the exception, and the third parameter is an
- * array of callback information. Exceptions are caught by the
- * +rescue+ clause of <code>begin...end</code> blocks.
- *
- * raise "Failed to create socket"
- * raise ArgumentError, "No parameters", caller
- */
-
-static VALUE
-rb_f_raise(argc, argv)
- int argc;
- VALUE *argv;
-{
- rb_raise_jump(rb_make_exception(argc, argv));
- return Qnil; /* not reached */
-}
-
-static VALUE
-rb_make_exception(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE mesg;
- ID exception;
- int n;
-
- mesg = Qnil;
- switch (argc) {
- case 0:
- mesg = Qnil;
- break;
- case 1:
- if (NIL_P(argv[0])) break;
- if (TYPE(argv[0]) == T_STRING) {
- mesg = rb_exc_new3(rb_eRuntimeError, argv[0]);
- break;
- }
- n = 0;
- goto exception_call;
-
- case 2:
- case 3:
- n = 1;
- exception_call:
- exception = rb_intern("exception");
- if (!rb_respond_to(argv[0], exception)) {
- rb_raise(rb_eTypeError, "exception class/object expected");
- }
- mesg = rb_funcall(argv[0], exception, n, argv[1]);
- break;
- default:
- rb_raise(rb_eArgError, "wrong number of arguments");
- break;
- }
- if (argc > 0) {
- if (!rb_obj_is_kind_of(mesg, rb_eException))
- rb_raise(rb_eTypeError, "exception object expected");
- if (argc>2)
- set_backtrace(mesg, argv[2]);
- }
-
- return mesg;
-}
-
-static void
-rb_raise_jump(mesg)
- VALUE mesg;
-{
- if (ruby_frame != top_frame) {
- PUSH_FRAME(); /* fake frame */
- *ruby_frame = *_frame.prev->prev;
- rb_longjmp(TAG_RAISE, mesg);
- POP_FRAME();
- }
- rb_longjmp(TAG_RAISE, mesg);
-}
-
-void
-rb_jump_tag(tag)
- int tag;
-{
- JUMP_TAG(tag);
-}
-
-int
-rb_block_given_p()
-{
- if (ruby_frame->iter == ITER_CUR && ruby_block)
- return Qtrue;
- return Qfalse;
-}
-
-int
-rb_iterator_p()
-{
- return rb_block_given_p();
-}
-
-/*
- * call-seq:
- * block_given? => true or false
- * iterator? => true or false
- *
- * Returns <code>true</code> if <code>yield</code> would execute a
- * block in the current context. The <code>iterator?</code> form
- * is mildly deprecated.
- *
- * def try
- * if block_given?
- * yield
- * else
- * "no block"
- * end
- * end
- * try #=> "no block"
- * try { "hello" } #=> "hello"
- * try do "hello" end #=> "hello"
- */
-
-
-static VALUE
-rb_f_block_given_p()
-{
- if (ruby_frame->prev && ruby_frame->prev->iter == ITER_CUR && ruby_block)
- return Qtrue;
- return Qfalse;
-}
-
-static VALUE rb_eThreadError;
-
-NORETURN(static void proc_jump_error(int, VALUE));
-static void
-proc_jump_error(state, result)
- int state;
- VALUE result;
-{
- char mesg[32];
- char *statement;
-
- switch (state) {
- case TAG_BREAK:
- statement = "break"; break;
- case TAG_RETURN:
- statement = "return"; break;
- case TAG_RETRY:
- statement = "retry"; break;
- default:
- statement = "local-jump"; break; /* should not happen */
- }
- snprintf(mesg, sizeof mesg, "%s from proc-closure", statement);
- localjump_error(mesg, result, state);
-}
-
-NORETURN(static void return_jump(VALUE));
-static void
-return_jump(retval)
- VALUE retval;
-{
- struct tag *tt = prot_tag;
- int yield = Qfalse;
-
- if (retval == Qundef) retval = Qnil;
- while (tt) {
- if (tt->tag == PROT_YIELD) {
- yield = Qtrue;
- tt = tt->prev;
- }
- if ((tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) ||
- (tt->tag == PROT_LAMBDA && !yield))
- {
- tt->dst = (VALUE)tt->frame->uniq;
- tt->retval = retval;
- JUMP_TAG(TAG_RETURN);
- }
- if (tt->tag == PROT_THREAD) {
- rb_raise(rb_eThreadError, "return can't jump across threads");
- }
- tt = tt->prev;
- }
- localjump_error("unexpected return", retval, TAG_RETURN);
-}
-
-static void
-break_jump(retval)
- VALUE retval;
-{
- struct tag *tt = prot_tag;
-
- if (retval == Qundef) retval = Qnil;
- while (tt) {
- switch (tt->tag) {
- case PROT_THREAD:
- case PROT_YIELD:
- case PROT_LOOP:
- case PROT_LAMBDA:
- tt->dst = (VALUE)tt->frame->uniq;
- tt->retval = retval;
- JUMP_TAG(TAG_BREAK);
- break;
- default:
- break;
- }
- tt = tt->prev;
- }
- localjump_error("unexpected break", retval, TAG_BREAK);
-}
-
-static VALUE bmcall _((VALUE, VALUE));
-static int method_arity _((VALUE));
-
-static VALUE
-rb_yield_0(val, self, klass, flags, avalue)
- VALUE val, self, klass; /* OK */
- int flags, avalue;
-{
- NODE *node, *var;
- volatile VALUE result = Qnil;
- volatile VALUE old_cref;
- volatile VALUE old_wrapper;
- struct BLOCK * volatile block;
- struct SCOPE * volatile old_scope;
- int old_vmode;
- struct FRAME frame;
- NODE *cnode = ruby_current_node;
- int lambda = flags & YIELD_LAMBDA_CALL;
- int state;
-
- if (!rb_block_given_p()) {
- localjump_error("no block given", Qnil, 0);
- }
-
- PUSH_VARS();
- block = ruby_block;
- frame = block->frame;
- frame.prev = ruby_frame;
- ruby_frame = &(frame);
- old_cref = (VALUE)ruby_cref;
- ruby_cref = block->cref;
- old_wrapper = ruby_wrapper;
- ruby_wrapper = block->wrapper;
- old_scope = ruby_scope;
- ruby_scope = block->scope;
- old_vmode = scope_vmode;
- scope_vmode = (flags & YIELD_PUBLIC_DEF) ? SCOPE_PUBLIC : block->vmode;
- ruby_block = block->prev;
- if (block->flags & BLOCK_D_SCOPE) {
- /* put place holder for dynamic (in-block) local variables */
- ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
- }
- else {
- /* FOR does not introduce new scope */
- ruby_dyna_vars = block->dyna_vars;
- }
- PUSH_CLASS(klass ? klass : block->klass);
- if (!klass) {
- self = block->self;
- }
- node = block->body;
- var = block->var;
-
- if (var) {
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- NODE *bvar = NULL;
- block_var:
- if (var == (NODE*)1) { /* no parameter || */
- if (lambda && RARRAY(val)->len != 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
- RARRAY(val)->len);
- }
- }
- else if (var == (NODE*)2) {
- if (TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
- RARRAY(val)->len);
- }
- }
- else if (!bvar && nd_type(var) == NODE_BLOCK_PASS) {
- bvar = var->nd_body;
- var = var->nd_args;
- goto block_var;
- }
- else if (nd_type(var) == NODE_MASGN) {
- if (!avalue) {
- val = svalue_to_mrhs(val, var->nd_head);
- }
- massign(self, var, val, lambda);
- }
- else {
- int len = 0;
- if (avalue) {
- len = RARRAY(val)->len;
- if (len == 0) {
- goto zero_arg;
- }
- if (len == 1) {
- val = RARRAY(val)->ptr[0];
- }
- else {
- goto multi_values;
- }
- }
- else if (val == Qundef) {
- zero_arg:
- val = Qnil;
- multi_values:
- {
- ruby_current_node = var;
- rb_warn("multiple values for a block parameter (%d for 1)\n\tfrom %s:%d",
- len, cnode->nd_file, nd_line(cnode));
- ruby_current_node = cnode;
- }
- }
- assign(self, var, val, lambda);
- }
- if (bvar) {
- VALUE blk;
- if (flags & YIELD_PROC_CALL)
- blk = block->block_obj;
- else
- blk = rb_block_proc();
- assign(self, bvar, blk, 0);
- }
- }
- POP_TAG();
- if (state) goto pop_state;
- }
- else if (lambda && RARRAY(val)->len != 0 &&
- (!node || nd_type(node) != NODE_IFUNC ||
- node->nd_cfnc != bmcall)) {
- rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
- RARRAY(val)->len);
- }
- if (!node) {
- state = 0;
- goto pop_state;
- }
- ruby_current_node = node;
-
- PUSH_ITER(block->iter);
- PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
- if ((state = EXEC_TAG()) == 0) {
- redo:
- if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
- if (node->nd_state == YIELD_FUNC_AVALUE) {
- if (!avalue) {
- val = svalue_to_avalue(val);
- }
- }
- else {
- if (avalue) {
- val = avalue_to_svalue(val);
- }
- if (val == Qundef && node->nd_state != YIELD_FUNC_SVALUE)
- val = Qnil;
- }
- if ((block->flags&BLOCK_FROM_METHOD) && RTEST(block->block_obj)) {
- struct BLOCK *data, _block;
- Data_Get_Struct(block->block_obj, struct BLOCK, data);
- _block = *data;
- _block.outer = ruby_block;
- _block.uniq = block_unique++;
- ruby_block = &_block;
- PUSH_ITER(ITER_PRE);
- ruby_frame->iter = ITER_CUR;
- result = (*node->nd_cfnc)(val, node->nd_tval, self);
- POP_ITER();
- }
- else {
- result = (*node->nd_cfnc)(val, node->nd_tval, self);
- }
- }
- else {
- result = rb_eval(self, node);
- }
- }
- else {
- switch (state) {
- case TAG_REDO:
- state = 0;
- CHECK_INTS;
- goto redo;
- case TAG_NEXT:
- state = 0;
- result = prot_tag->retval;
- break;
- case TAG_BREAK:
- if (TAG_DST()) {
- result = prot_tag->retval;
- }
- else {
- lambda = Qtrue; /* just pass TAG_BREAK */
- }
- break;
- default:
- break;
- }
- }
- POP_TAG();
- POP_ITER();
- pop_state:
- POP_CLASS();
- if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
- !FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) {
- struct RVarmap *vars = ruby_dyna_vars;
-
- if (ruby_dyna_vars->id == 0) {
- vars = ruby_dyna_vars->next;
- rb_gc_force_recycle((VALUE)ruby_dyna_vars);
- while (vars && vars->id != 0 && vars != block->dyna_vars) {
- struct RVarmap *tmp = vars->next;
- rb_gc_force_recycle((VALUE)vars);
- vars = tmp;
- }
- }
- }
- POP_VARS();
- ruby_block = block;
- ruby_frame = ruby_frame->prev;
- ruby_cref = (NODE*)old_cref;
- ruby_wrapper = old_wrapper;
- if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
- scope_dup(old_scope);
- ruby_scope = old_scope;
- scope_vmode = old_vmode;
- switch (state) {
- case 0:
- break;
- case TAG_BREAK:
- if (!lambda) {
- struct tag *tt = prot_tag;
-
- while (tt) {
- if (tt->tag == PROT_LOOP && tt->blkid == ruby_block->uniq) {
- tt->dst = (VALUE)tt->frame->uniq;
- tt->retval = result;
- JUMP_TAG(TAG_BREAK);
- }
- tt = tt->prev;
- }
- proc_jump_error(TAG_BREAK, result);
- }
- /* fall through */
- default:
- JUMP_TAG(state);
- break;
- }
- ruby_current_node = cnode;
- return result;
-}
-
-VALUE
-rb_yield(val)
- VALUE val;
-{
- return rb_yield_0(val, 0, 0, 0, Qfalse);
-}
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_yield_values(int n, ...)
-#else
-rb_yield_values(n, va_alist)
- int n;
- va_dcl
-#endif
-{
- int i;
- va_list args;
- VALUE val;
-
- if (n == 0) {
- return rb_yield_0(Qundef, 0, 0, 0, Qfalse);
- }
- val = rb_values_new2(n, 0);
- va_init_list(args, n);
- for (i=0; i<n; i++) {
- RARRAY(val)->ptr[i] = va_arg(args, VALUE);
- }
- RARRAY(val)->len = n;
- va_end(args);
- return rb_yield_0(val, 0, 0, 0, Qtrue);
-}
-
-VALUE
-rb_yield_splat(values)
- VALUE values;
-{
- int avalue = Qfalse;
-
- if (TYPE(values) == T_ARRAY) {
- if (RARRAY(values)->len == 0) {
- values = Qundef;
- }
- else {
- avalue = Qtrue;
- }
- }
- return rb_yield_0(values, 0, 0, 0, avalue);
-}
-
-/*
- * call-seq:
- * loop {|| block }
- *
- * Repeatedly executes the block.
- *
- * loop do
- * print "Input: "
- * line = gets
- * break if !line or line =~ /^qQ/
- * # ...
- * end
- */
-
-static VALUE
-rb_f_loop()
-{
- for (;;) {
- rb_yield_0(Qundef, 0, 0, 0, Qfalse);
- CHECK_INTS;
- }
- return Qnil; /* dummy */
-}
-
-static VALUE
-massign(self, node, val, pcall)
- VALUE self;
- NODE *node;
- VALUE val;
- int pcall;
-{
- NODE *list;
- long i = 0, len;
-
- len = RARRAY(val)->len;
- list = node->nd_head;
- for (; list && i<len; i++) {
- assign(self, list->nd_head, RARRAY(val)->ptr[i], pcall);
- list = list->nd_next;
- }
- if (pcall && list) goto arg_error;
- if (node->nd_args) {
- if ((long)(node->nd_args) == -1) {
- /* no check for mere `*' */
- }
- else if (!list && i<len) {
- assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i), pcall);
- }
- else {
- assign(self, node->nd_args, rb_ary_new2(0), pcall);
- }
- }
- else if (pcall && i < len) {
- goto arg_error;
- }
-
- while (list) {
- i++;
- assign(self, list->nd_head, Qnil, pcall);
- list = list->nd_next;
- }
- return val;
-
- arg_error:
- while (list) {
- i++;
- list = list->nd_next;
- }
- rb_raise(rb_eArgError, "wrong number of arguments (%ld for %ld)", len, i);
-}
-
-static void
-assign(self, lhs, val, pcall)
- VALUE self;
- NODE *lhs;
- VALUE val;
- int pcall;
-{
- ruby_current_node = lhs;
- if (val == Qundef) {
- rb_warning("assigning void value");
- val = Qnil;
- }
- switch (nd_type(lhs)) {
- case NODE_GASGN:
- rb_gvar_set(lhs->nd_entry, val);
- break;
-
- case NODE_IASGN:
- rb_ivar_set(self, lhs->nd_vid, val);
- break;
-
- case NODE_LASGN:
- if (ruby_scope->local_vars == 0)
- rb_bug("unexpected local variable assignment");
- ruby_scope->local_vars[lhs->nd_cnt] = val;
- break;
-
- case NODE_DASGN:
- dvar_asgn(lhs->nd_vid, val);
- break;
-
- case NODE_DASGN_CURR:
- dvar_asgn_curr(lhs->nd_vid, val);
- break;
-
- case NODE_CDECL:
- if (lhs->nd_vid == 0) {
- rb_const_set(class_prefix(self, lhs->nd_else), lhs->nd_else->nd_mid, val);
- }
- else {
- rb_const_set(ruby_cbase, lhs->nd_vid, val);
- }
- break;
-
- case NODE_CVDECL:
- if (RTEST(ruby_verbose) && FL_TEST(ruby_cbase, FL_SINGLETON)) {
- rb_warn("declaring singleton class variable");
- }
- rb_cvar_set(cvar_cbase(), lhs->nd_vid, val, Qtrue);
- break;
-
- case NODE_CVASGN:
- rb_cvar_set(cvar_cbase(), lhs->nd_vid, val, Qfalse);
- break;
-
- case NODE_MASGN:
- massign(self, lhs, svalue_to_mrhs(val, lhs->nd_head), pcall);
- break;
-
- case NODE_CALL:
- case NODE_ATTRASGN:
- {
- VALUE recv;
- int scope;
- if (lhs->nd_recv == (NODE *)1) {
- recv = self;
- scope = 1;
- }
- else {
- recv = rb_eval(self, lhs->nd_recv);
- scope = 0;
- }
- if (!lhs->nd_args) {
- /* attr set */
- ruby_current_node = lhs;
- SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope);
- }
- else {
- /* array set */
- VALUE args;
-
- args = rb_eval(self, lhs->nd_args);
- rb_ary_push(args, val);
- ruby_current_node = lhs;
- SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
- RARRAY(args)->len, RARRAY(args)->ptr, scope);
- }
- }
- break;
-
- default:
- rb_bug("bug in variable assignment");
- break;
- }
-}
-
-VALUE
-rb_iterate(it_proc, data1, bl_proc, data2)
- VALUE (*it_proc) _((VALUE)), (*bl_proc)(ANYARGS);
- VALUE data1, data2;
-{
- int state;
- volatile VALUE retval = Qnil;
- NODE *node = NEW_IFUNC(bl_proc, data2);
- VALUE self = ruby_top_self;
-
- PUSH_ITER(ITER_PRE);
- PUSH_TAG(PROT_LOOP);
- PUSH_BLOCK(0, node);
- state = EXEC_TAG();
- if (state == 0) {
- iter_retry:
- retval = (*it_proc)(data1);
- }
- else if (state == TAG_BREAK && TAG_DST()) {
- retval = prot_tag->retval;
- state = 0;
- }
- else if (state == TAG_RETRY) {
- state = 0;
- goto iter_retry;
- }
- POP_BLOCK();
- POP_TAG();
- POP_ITER();
-
- switch (state) {
- case 0:
- break;
- default:
- JUMP_TAG(state);
- }
- return retval;
-}
-
-static int
-handle_rescue(self, node)
- VALUE self;
- NODE *node;
-{
- int argc; VALUE *argv; /* used in SETUP_ARGS */
- TMP_PROTECT;
-
- if (!node->nd_args) {
- return rb_obj_is_kind_of(ruby_errinfo, rb_eStandardError);
- }
-
- BEGIN_CALLARGS;
- SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
- while (argc--) {
- if (!rb_obj_is_kind_of(argv[0], rb_cModule)) {
- rb_raise(rb_eTypeError, "class or module required for rescue clause");
- }
- if (RTEST(rb_funcall(*argv, eqq, 1, ruby_errinfo))) return 1;
- argv++;
- }
- return 0;
-}
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_rescue2(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*r_proc)(ANYARGS), VALUE data2, ...)
-#else
-rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
- VALUE (*b_proc)(ANYARGS), (*r_proc)(ANYARGS);
- VALUE data1, data2;
- va_dcl
-#endif
-{
- int state;
- volatile VALUE result;
- volatile VALUE e_info = ruby_errinfo;
- va_list args;
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- retry_entry:
- result = (*b_proc)(data1);
- }
- else if (state == TAG_RAISE) {
- int handle = Qfalse;
- VALUE eclass;
-
- va_init_list(args, data2);
- while (eclass = va_arg(args, VALUE)) {
- if (rb_obj_is_kind_of(ruby_errinfo, eclass)) {
- handle = Qtrue;
- break;
- }
- }
- va_end(args);
-
- if (handle) {
- if (r_proc) {
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = (*r_proc)(data2, ruby_errinfo);
- }
- POP_TAG();
- if (state == TAG_RETRY) {
- state = 0;
- ruby_errinfo = Qnil;
- goto retry_entry;
- }
- }
- else {
- result = Qnil;
- state = 0;
- }
- if (state == 0) {
- ruby_errinfo = e_info;
- }
- }
- }
- POP_TAG();
- if (state) JUMP_TAG(state);
-
- return result;
-}
-
-VALUE
-rb_rescue(b_proc, data1, r_proc, data2)
- VALUE (*b_proc)(), (*r_proc)();
- VALUE data1, data2;
-{
- return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0);
-}
-
-static VALUE cont_protect;
-
-VALUE
-rb_protect(proc, data, state)
- VALUE (*proc) _((VALUE));
- VALUE data;
- int *state;
-{
- VALUE result = Qnil; /* OK */
- int status;
-
- PUSH_THREAD_TAG();
- cont_protect = (VALUE)rb_node_newnode(NODE_MEMO, cont_protect, 0, 0);
- if ((status = EXEC_TAG()) == 0) {
- result = (*proc)(data);
- }
- else if (status == TAG_THREAD) {
- rb_thread_start_1();
- }
- cont_protect = ((NODE *)cont_protect)->u1.value;
- POP_THREAD_TAG();
- if (state) {
- *state = status;
- }
- if (status != 0) {
- return Qnil;
- }
-
- return result;
-}
-
-VALUE
-rb_ensure(b_proc, data1, e_proc, data2)
- VALUE (*b_proc)();
- VALUE data1;
- VALUE (*e_proc)();
- VALUE data2;
-{
- int state;
- volatile VALUE result = Qnil;
- VALUE retval;
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = (*b_proc)(data1);
- }
- POP_TAG();
- retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
- (*e_proc)(data2);
- if (prot_tag) return_value(retval);
- if (state) JUMP_TAG(state);
- return result;
-}
-
-VALUE
-rb_with_disable_interrupt(proc, data)
- VALUE (*proc)();
- VALUE data;
-{
- VALUE result = Qnil; /* OK */
- int status;
-
- DEFER_INTS;
- {
- int thr_critical = rb_thread_critical;
-
- rb_thread_critical = Qtrue;
- PUSH_TAG(PROT_NONE);
- if ((status = EXEC_TAG()) == 0) {
- result = (*proc)(data);
- }
- POP_TAG();
- rb_thread_critical = thr_critical;
- }
- ENABLE_INTS;
- if (status) JUMP_TAG(status);
-
- return result;
-}
-
-static inline void
-stack_check()
-{
- static int overflowing = 0;
-
- if (!overflowing && ruby_stack_check()) {
- int state;
- overflowing = 1;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- rb_exc_raise(sysstack_error);
- }
- POP_TAG();
- overflowing = 0;
- JUMP_TAG(state);
- }
-}
-
-static int last_call_status;
-
-#define CSTAT_PRIV 1
-#define CSTAT_PROT 2
-#define CSTAT_VCALL 4
-#define CSTAT_SUPER 8
-
-/*
- * call-seq:
- * obj.method_missing(symbol [, *args] ) => result
- *
- * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
- * <i>symbol</i> is the symbol for the method called, and <i>args</i>
- * are any arguments that were passed to it. By default, the interpreter
- * raises an error when this method is called. However, it is possible
- * to override the method to provide more dynamic behavior.
- * The example below creates
- * a class <code>Roman</code>, which responds to methods with names
- * consisting of roman numerals, returning the corresponding integer
- * values.
- *
- * class Roman
- * def romanToInt(str)
- * # ...
- * end
- * def method_missing(methId)
- * str = methId.id2name
- * romanToInt(str)
- * end
- * end
- *
- * r = Roman.new
- * r.iv #=> 4
- * r.xxiii #=> 23
- * r.mm #=> 2000
- */
-
-static VALUE
-rb_method_missing(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- ID id;
- VALUE exc = rb_eNoMethodError;
- char *format = 0;
- NODE *cnode = ruby_current_node;
-
- if (argc == 0 || !SYMBOL_P(argv[0])) {
- rb_raise(rb_eArgError, "no id given");
- }
-
- stack_check();
-
- id = SYM2ID(argv[0]);
-
- if (last_call_status & CSTAT_PRIV) {
- format = "private method `%s' called for %s";
- }
- else if (last_call_status & CSTAT_PROT) {
- format = "protected method `%s' called for %s";
- }
- else if (last_call_status & CSTAT_VCALL) {
- format = "undefined local variable or method `%s' for %s";
- exc = rb_eNameError;
- }
- else if (last_call_status & CSTAT_SUPER) {
- format = "super: no superclass method `%s'";
- }
- if (!format) {
- format = "undefined method `%s' for %s";
- }
-
- ruby_current_node = cnode;
- {
- int n = 0;
- VALUE args[3];
-
- args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
- 3, rb_str_new2(format), obj, argv[0]);
- args[n++] = argv[0];
- if (exc == rb_eNoMethodError) {
- args[n++] = rb_ary_new4(argc-1, argv+1);
- }
- exc = rb_class_new_instance(n, args, exc);
- ruby_frame = ruby_frame->prev; /* pop frame for "method_missing" */
- rb_exc_raise(exc);
- }
-
- return Qnil; /* not reached */
-}
-
-static VALUE
-method_missing(obj, id, argc, argv, call_status)
- VALUE obj;
- ID id;
- int argc;
- const VALUE *argv;
- int call_status;
-{
- VALUE *nargv;
-
- last_call_status = call_status;
-
- if (id == missing) {
- PUSH_FRAME();
- rb_method_missing(argc, argv, obj);
- POP_FRAME();
- }
- else if (id == ID_ALLOCATOR) {
- rb_raise(rb_eTypeError, "allocator undefined for %s", rb_class2name(obj));
- }
-
- nargv = ALLOCA_N(VALUE, argc+1);
- nargv[0] = ID2SYM(id);
- MEMCPY(nargv+1, argv, VALUE, argc);
-
- return rb_funcall2(obj, missing, argc+1, nargv);
-}
-
-static inline VALUE
-call_cfunc(func, recv, len, argc, argv)
- VALUE (*func)();
- VALUE recv;
- int len, argc;
- VALUE *argv;
-{
- if (len >= 0 && argc != len) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, len);
- }
-
- switch (len) {
- case -2:
- return (*func)(recv, rb_ary_new4(argc, argv));
- break;
- case -1:
- return (*func)(argc, argv, recv);
- break;
- case 0:
- return (*func)(recv);
- break;
- case 1:
- return (*func)(recv, argv[0]);
- break;
- case 2:
- return (*func)(recv, argv[0], argv[1]);
- break;
- case 3:
- return (*func)(recv, argv[0], argv[1], argv[2]);
- break;
- case 4:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3]);
- break;
- case 5:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
- break;
- case 6:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5]);
- break;
- case 7:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6]);
- break;
- case 8:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7]);
- break;
- case 9:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8]);
- break;
- case 10:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8], argv[9]);
- break;
- case 11:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
- break;
- case 12:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8], argv[9],
- argv[10], argv[11]);
- break;
- case 13:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
- argv[11], argv[12]);
- break;
- case 14:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
- argv[11], argv[12], argv[13]);
- break;
- case 15:
- return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
- argv[11], argv[12], argv[13], argv[14]);
- break;
- default:
- rb_raise(rb_eArgError, "too many arguments (%d)", len);
- break;
- }
- return Qnil; /* not reached */
-}
-
-static VALUE
-rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
- VALUE klass, recv;
- ID id;
- ID oid;
- int argc; /* OK */
- VALUE *argv; /* OK */
- NODE *body; /* OK */
- int nosuper;
-{
- NODE *b2; /* OK */
- volatile VALUE result = Qnil;
- int itr;
- static int tick;
- volatile VALUE args;
- TMP_PROTECT;
-
- switch (ruby_iter->iter) {
- case ITER_PRE:
- itr = ITER_CUR;
- break;
- case ITER_CUR:
- default:
- itr = ITER_NOT;
- break;
- }
-
- if ((++tick & 0xff) == 0) {
- CHECK_INTS; /* better than nothing */
- stack_check();
- rb_gc_finalize_deferred();
- }
- if (argc < 0) {
- argc = -argc-1;
- args = rb_ary_concat(rb_ary_new4(argc, argv), splat_value(argv[argc]));
- argc = RARRAY(args)->len;
- argv = RARRAY(args)->ptr;
- }
- PUSH_ITER(itr);
- PUSH_FRAME();
- ruby_frame->callee = id;
- ruby_frame->this_func = oid;
- ruby_frame->this_class = nosuper?0:klass;
- ruby_frame->self = recv;
- ruby_frame->argc = argc;
-
- switch (nd_type(body)) {
- case NODE_CFUNC:
- {
- int len = body->nd_argc;
-
- if (len < -2) {
- rb_bug("bad argc (%d) specified for `%s(%s)'",
- len, rb_class2name(klass), rb_id2name(id));
- }
- if (event_hooks) {
- int state;
-
- EXEC_EVENT_HOOK(RUBY_EVENT_C_CALL, ruby_current_node,
- recv, id, klass);
- PUSH_TAG(PROT_FUNC);
- if ((state = EXEC_TAG()) == 0) {
- result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
- }
- POP_TAG();
- ruby_current_node = ruby_frame->node;
- EXEC_EVENT_HOOK(RUBY_EVENT_C_RETURN, ruby_current_node,
- recv, id, klass);
- if (state) JUMP_TAG(state);
- }
- else {
- result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
- }
- }
- break;
-
- /* for attr get/set */
- case NODE_IVAR:
- if (argc != 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
- }
- result = rb_attr_get(recv, body->nd_vid);
- break;
-
- case NODE_ATTRSET:
- if (argc != 1)
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
- result = rb_ivar_set(recv, body->nd_vid, argv[0]);
- break;
-
- case NODE_ZSUPER: /* visibility override */
- result = rb_call_super(argc, argv);
- break;
-
- case NODE_BMETHOD:
- ruby_frame->flags |= FRAME_DMETH;
- result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
- break;
-
- case NODE_SCOPE:
- {
- int state;
- VALUE *local_vars; /* OK */
- NODE *saved_cref = 0;
-
- PUSH_SCOPE();
-
- if (body->nd_rval) {
- saved_cref = ruby_cref;
- ruby_cref = (NODE*)body->nd_rval;
- }
- PUSH_CLASS(ruby_cbase);
- if (body->nd_tbl) {
- local_vars = TMP_ALLOC(body->nd_tbl[0]+1);
- *local_vars++ = (VALUE)body;
- rb_mem_clear(local_vars, body->nd_tbl[0]);
- ruby_scope->local_tbl = body->nd_tbl;
- ruby_scope->local_vars = local_vars;
- }
- else {
- local_vars = ruby_scope->local_vars = 0;
- ruby_scope->local_tbl = 0;
- }
- b2 = body = body->nd_next;
-
- PUSH_VARS();
- PUSH_TAG(PROT_FUNC);
-
- if ((state = EXEC_TAG()) == 0) {
- NODE *node = 0;
- int i;
-
- if (nd_type(body) == NODE_ARGS) {
- node = body;
- body = 0;
- }
- else if (nd_type(body) == NODE_BLOCK) {
- node = body->nd_head;
- body = body->nd_next;
- }
- if (node) {
- if (nd_type(node) != NODE_ARGS) {
- rb_bug("no argument-node");
- }
-
- i = node->nd_cnt;
- if (i > argc) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
- }
- if ((long)node->nd_rest == -1) {
- int opt = i;
- NODE *optnode = node->nd_opt;
-
- while (optnode) {
- opt++;
- optnode = optnode->nd_next;
- }
- if (opt < argc) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, opt);
- }
- ruby_frame->argc = opt;
- }
-
- if (local_vars) {
- if (i > 0) {
- /* +2 for $_ and $~ */
- MEMCPY(local_vars+2, argv, VALUE, i);
- }
- argv += i; argc -= i;
- if (node->nd_opt) {
- NODE *opt = node->nd_opt;
-
- while (opt && argc) {
- assign(recv, opt->nd_head, *argv, 1);
- argv++; argc--;
- opt = opt->nd_next;
- }
- if (opt) {
- rb_eval(recv, opt);
- }
- }
- if ((long)node->nd_rest >= 0) {
- VALUE v;
-
- if (argc > 0)
- v = rb_ary_new4(argc,argv);
- else
- v = rb_ary_new2(0);
- ruby_scope->local_vars[node->nd_rest] = v;
- }
- }
- }
- if ((long)node->nd_rest >= 0) {
- ruby_frame->argc = -(ruby_frame->argc - argc)-1;
- }
-
- if (event_hooks) {
- EXEC_EVENT_HOOK(RUBY_EVENT_CALL, b2, recv, id, klass);
- }
- result = rb_eval(recv, body);
- }
- else if (state == TAG_RETURN && TAG_DST()) {
- result = prot_tag->retval;
- state = 0;
- }
- POP_TAG();
- POP_VARS();
- POP_CLASS();
- POP_SCOPE();
- ruby_cref = saved_cref;
- if (event_hooks) {
- EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
- }
- switch (state) {
- case 0:
- break;
-
- case TAG_BREAK:
- case TAG_RETURN:
- JUMP_TAG(state);
- break;
-
- case TAG_RETRY:
- if (rb_block_given_p()) JUMP_TAG(state);
- /* fall through */
- default:
- jump_tag_but_local_jump(state, result);
- break;
- }
- }
- break;
-
- default:
- rb_bug("unknown node type %d", nd_type(body));
- break;
- }
- POP_FRAME();
- POP_ITER();
- return result;
-}
-
-static VALUE
-rb_call(klass, recv, mid, argc, argv, scope)
- VALUE klass, recv;
- ID mid;
- int argc; /* OK */
- const VALUE *argv; /* OK */
- int scope;
-{
- NODE *body; /* OK */
- int noex;
- ID id = mid;
- struct cache_entry *ent;
-
- if (!klass) {
- rb_raise(rb_eNotImpError, "method `%s' called on terminated object (0x%lx)",
- rb_id2name(mid), recv);
- }
- /* is it in the method cache? */
- ent = cache + EXPR1(klass, mid);
- if (ent->mid == mid && ent->klass == klass) {
- if (!ent->method)
- return method_missing(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
- klass = ent->origin;
- id = ent->mid0;
- noex = ent->noex;
- body = ent->method;
- }
- else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
- if (scope == 3) {
- return method_missing(recv, mid, argc, argv, CSTAT_SUPER);
- }
- return method_missing(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
- }
-
- if (mid != missing) {
- /* receiver specified form for private method */
- if ((noex & NOEX_PRIVATE) && scope == 0)
- return method_missing(recv, mid, argc, argv, CSTAT_PRIV);
-
- /* self must be kind of a specified form for protected method */
- if ((noex & NOEX_PROTECTED)) {
- VALUE defined_class = klass;
-
- if (TYPE(defined_class) == T_ICLASS) {
- defined_class = RBASIC(defined_class)->klass;
- }
- if (!rb_obj_is_kind_of(ruby_frame->self, rb_class_real(defined_class)))
- return method_missing(recv, mid, argc, argv, CSTAT_PROT);
- }
- }
-
- return rb_call0(klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER);
-}
-
-VALUE
-rb_apply(recv, mid, args)
- VALUE recv;
- ID mid;
- VALUE args;
-{
- int argc;
- VALUE *argv;
-
- argc = RARRAY(args)->len; /* Assigns LONG, but argc is INT */
- argv = ALLOCA_N(VALUE, argc);
- MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
-}
-
-/*
- * call-seq:
- * obj.send(symbol [, args...]) => obj
- * obj.__send__(symbol [, args...]) => obj
- *
- * Invokes the method identified by _symbol_, passing it any
- * arguments specified. You can use <code>__send__</code> if the name
- * +send+ clashes with an existing method in _obj_.
- *
- * class Klass
- * def hello(*args)
- * "Hello " + args.join(' ')
- * end
- * end
- * k = Klass.new
- * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
- */
-
-static VALUE
-rb_f_send(argc, argv, recv)
- int argc;
- VALUE *argv;
- VALUE recv;
-{
- VALUE vid;
-
- if (argc == 0) rb_raise(rb_eArgError, "no method name given");
-
- vid = *argv++; argc--;
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1);
- POP_ITER();
-
- return vid;
-}
-
-VALUE
-#ifdef HAVE_STDARG_PROTOTYPES
-rb_funcall(VALUE recv, ID mid, int n, ...)
-#else
-rb_funcall(recv, mid, n, va_alist)
- VALUE recv;
- ID mid;
- int n;
- va_dcl
-#endif
-{
- VALUE *argv;
- va_list ar;
- va_init_list(ar, n);
-
- if (n > 0) {
- long i;
-
- argv = ALLOCA_N(VALUE, n);
-
- for (i=0;i<n;i++) {
- argv[i] = va_arg(ar, VALUE);
- }
- va_end(ar);
- }
- else {
- argv = 0;
- }
-
- return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1);
-}
-
-VALUE
-rb_funcall2(recv, mid, argc, argv)
- VALUE recv;
- ID mid;
- int argc;
- const VALUE *argv;
-{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
-}
-
-VALUE
-rb_funcall3(recv, mid, argc, argv)
- VALUE recv;
- ID mid;
- int argc;
- const VALUE *argv;
-{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0);
-}
-
-VALUE
-rb_call_super(argc, argv)
- int argc;
- const VALUE *argv;
-{
- VALUE result, self, klass, k;
-
- if (ruby_frame->this_class == 0) {
- rb_name_error(ruby_frame->callee, "calling `super' from `%s' is prohibited",
- rb_id2name(ruby_frame->this_func));
- }
-
- self = ruby_frame->self;
- klass = ruby_frame->this_class;
-
- PUSH_ITER(ruby_iter->iter ? ITER_PRE : ITER_NOT);
- result = rb_call(RCLASS(klass)->super, self, ruby_frame->this_func, argc, argv, 3);
- POP_ITER();
-
- return result;
-}
-
-static VALUE
-backtrace(lev)
- int lev;
-{
- struct FRAME *frame = ruby_frame;
- char buf[BUFSIZ];
- volatile VALUE ary;
- NODE *n;
-
- ary = rb_ary_new();
- if (frame->this_func == ID_ALLOCATOR) {
- frame = frame->prev;
- }
- if (lev < 0) {
- ruby_set_current_source();
- if (frame->this_func) {
- snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
- ruby_sourcefile, ruby_sourceline,
- rb_id2name(frame->this_func));
- }
- else if (ruby_sourceline == 0) {
- snprintf(buf, BUFSIZ, "%s", ruby_sourcefile);
- }
- else {
- snprintf(buf, BUFSIZ, "%s:%d", ruby_sourcefile, ruby_sourceline);
- }
- rb_ary_push(ary, rb_str_new2(buf));
- if (lev < -1) return ary;
- }
- else {
- while (lev-- > 0) {
- frame = frame->prev;
- if (!frame) {
- ary = Qnil;
- break;
- }
- }
- }
- while (frame && (n = frame->node)) {
- if (frame->prev && frame->prev->this_func) {
- snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
- n->nd_file, nd_line(n),
- rb_id2name(frame->prev->this_func));
- }
- else {
- snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
- }
- rb_ary_push(ary, rb_str_new2(buf));
- frame = frame->prev;
- }
-
- return ary;
-}
-
-/*
- * call-seq:
- * caller(start=1) => array
- *
- * Returns the current execution stack---an array containing strings in
- * the form ``<em>file:line</em>'' or ``<em>file:line: in
- * `method'</em>''. The optional _start_ parameter
- * determines the number of initial stack entries to omit from the
- * result.
- *
- * def a(skip)
- * caller(skip)
- * end
- * def b(skip)
- * a(skip)
- * end
- * def c(skip)
- * b(skip)
- * end
- * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
- * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
- * c(2) #=> ["prog:8:in `c'", "prog:12"]
- * c(3) #=> ["prog:13"]
- */
-
-static VALUE
-rb_f_caller(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE level;
- int lev;
-
- rb_scan_args(argc, argv, "01", &level);
-
- if (NIL_P(level)) lev = 1;
- else lev = NUM2INT(level);
- if (lev < 0) rb_raise(rb_eArgError, "negative level (%d)", lev);
-
- return backtrace(lev);
-}
-
-void
-rb_backtrace()
-{
- long i;
- VALUE ary;
-
- ary = backtrace(-1);
- for (i=0; i<RARRAY(ary)->len; i++) {
- printf("\tfrom %s\n", RSTRING(RARRAY(ary)->ptr[i])->ptr);
- }
-}
-
-static VALUE
-make_backtrace()
-{
- return backtrace(-1);
-}
-
-ID
-rb_frame_this_func()
-{
- return ruby_frame->this_func;
-}
-
-static NODE*
-compile(src, file, line)
- VALUE src;
- char *file;
- int line;
-{
- NODE *node;
- int critical;
-
- ruby_nerrs = 0;
- StringValue(src);
- critical = rb_thread_critical;
- rb_thread_critical = Qtrue;
- node = rb_compile_string(file, src, line);
- rb_thread_critical = critical;
-
- if (ruby_nerrs == 0) return node;
- return 0;
-}
-
-static VALUE
-eval(self, src, scope, file, line)
- VALUE self, src, scope;
- char *file;
- int line;
-{
- struct BLOCK *data = NULL;
- volatile VALUE result = Qnil;
- struct SCOPE * volatile old_scope;
- struct BLOCK * volatile old_block;
- struct RVarmap * volatile old_dyna_vars;
- VALUE volatile old_cref;
- int volatile old_vmode;
- volatile VALUE old_wrapper;
- struct FRAME frame;
- NODE *nodesave = ruby_current_node;
- volatile int iter = ruby_frame->iter;
- volatile int safe = ruby_safe_level;
- int state;
-
- if (!NIL_P(scope)) {
- if (!rb_obj_is_proc(scope)) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Binding)",
- rb_obj_classname(scope));
- }
-
- Data_Get_Struct(scope, struct BLOCK, data);
- /* PUSH BLOCK from data */
- frame = data->frame;
- frame.tmp = ruby_frame; /* gc protection */
- ruby_frame = &(frame);
- old_scope = ruby_scope;
- ruby_scope = data->scope;
- old_block = ruby_block;
- ruby_block = data->prev;
- old_dyna_vars = ruby_dyna_vars;
- ruby_dyna_vars = data->dyna_vars;
- old_vmode = scope_vmode;
- scope_vmode = data->vmode;
- old_cref = (VALUE)ruby_cref;
- ruby_cref = data->cref;
- old_wrapper = ruby_wrapper;
- ruby_wrapper = data->wrapper;
- if ((file == 0 || (line == 1 && strcmp(file, "(eval)") == 0)) && data->frame.node) {
- file = data->frame.node->nd_file;
- if (!file) file = "__builtin__";
- line = nd_line(data->frame.node);
- }
-
- self = data->self;
- ruby_frame->iter = data->iter;
- }
- else {
- if (ruby_frame->prev) {
- ruby_frame->iter = ruby_frame->prev->iter;
- }
- }
- if (file == 0) {
- ruby_set_current_source();
- file = ruby_sourcefile;
- line = ruby_sourceline;
- }
- PUSH_CLASS(ruby_cbase);
- ruby_in_eval++;
- if (TYPE(ruby_class) == T_ICLASS) {
- ruby_class = RBASIC(ruby_class)->klass;
- }
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- NODE *node;
-
- ruby_safe_level = 0;
- result = ruby_errinfo;
- ruby_errinfo = Qnil;
- node = compile(src, file, line);
- ruby_safe_level = safe;
- if (ruby_nerrs > 0) {
- compile_error(0);
- }
- if (!NIL_P(result)) ruby_errinfo = result;
- result = eval_node(self, node);
- }
- POP_TAG();
- POP_CLASS();
- ruby_in_eval--;
- ruby_safe_level = safe;
- if (!NIL_P(scope)) {
- int dont_recycle = ruby_scope->flags & SCOPE_DONT_RECYCLE;
-
- ruby_wrapper = old_wrapper;
- ruby_cref = (NODE*)old_cref;
- ruby_frame = frame.tmp;
- ruby_scope = old_scope;
- ruby_block = old_block;
- ruby_dyna_vars = old_dyna_vars;
- data->vmode = scope_vmode; /* write back visibility mode */
- scope_vmode = old_vmode;
- if (dont_recycle) {
- struct tag *tag;
- struct RVarmap *vars;
-
- scope_dup(ruby_scope);
- for (tag=prot_tag; tag; tag=tag->prev) {
- scope_dup(tag->scope);
- }
- for (vars = ruby_dyna_vars; vars; vars = vars->next) {
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- }
- }
- else {
- ruby_frame->iter = iter;
- }
- ruby_current_node = nodesave;
- ruby_set_current_source();
- if (state) {
- if (state == TAG_RAISE) {
- if (strcmp(file, "(eval)") == 0) {
- VALUE mesg, errat;
-
- errat = get_backtrace(ruby_errinfo);
- mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
- if (!NIL_P(errat) && TYPE(errat) == T_ARRAY) {
- if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) {
- rb_str_update(mesg, 0, 0, rb_str_new2(": "));
- rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]);
- }
- RARRAY(errat)->ptr[0] = RARRAY(backtrace(-2))->ptr[0];
- }
- }
- rb_exc_raise(ruby_errinfo);
- }
- JUMP_TAG(state);
- }
-
- return result;
-}
-
-/*
- * call-seq:
- * eval(string [, binding [, filename [,lineno]]]) => obj
- *
- * Evaluates the Ruby expression(s) in <em>string</em>. If
- * <em>binding</em> is given, the evaluation is performed in its
- * context. The binding may be a <code>Binding</code> object or a
- * <code>Proc</code> object. If the optional <em>filename</em> and
- * <em>lineno</em> parameters are present, they will be used when
- * reporting syntax errors.
- *
- * def getBinding(str)
- * return binding
- * end
- * str = "hello"
- * eval "str + ' Fred'" #=> "hello Fred"
- * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
- */
-
-static VALUE
-rb_f_eval(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE src, scope, vfile, vline;
- char *file = "(eval)";
- int line = 1;
-
- rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
- if (ruby_safe_level >= 4) {
- StringValue(src);
- if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
- rb_raise(rb_eSecurityError, "Insecure: can't modify trusted binding");
- }
- }
- else {
- SafeStringValue(src);
- }
- if (argc >= 3) {
- StringValue(vfile);
- }
- if (argc >= 4) {
- line = NUM2INT(vline);
- }
-
- if (!NIL_P(vfile)) file = RSTRING(vfile)->ptr;
- if (NIL_P(scope) && ruby_frame->prev) {
- struct FRAME *prev;
- VALUE val;
-
- prev = ruby_frame;
- PUSH_FRAME();
- *ruby_frame = *prev->prev;
- ruby_frame->prev = prev;
- val = eval(self, src, scope, file, line);
- POP_FRAME();
-
- return val;
- }
- return eval(self, src, scope, file, line);
-}
-
-/* function to call func under the specified class/module context */
-static VALUE
-exec_under(func, under, cbase, args)
- VALUE (*func)();
- VALUE under, cbase;
- void *args;
-{
- VALUE val = Qnil; /* OK */
- int state;
- int mode;
-
- PUSH_CLASS(under);
- PUSH_FRAME();
- ruby_frame->self = _frame.prev->self;
- ruby_frame->callee = _frame.prev->callee;
- ruby_frame->this_func = _frame.prev->this_func;
- ruby_frame->this_class = _frame.prev->this_class;
- ruby_frame->argc = _frame.prev->argc;
- if (cbase) {
- PUSH_CREF(cbase);
- }
-
- mode = scope_vmode;
- SCOPE_SET(SCOPE_PUBLIC);
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- val = (*func)(args);
- }
- POP_TAG();
- if (cbase) POP_CREF();
- SCOPE_SET(mode);
- POP_FRAME();
- POP_CLASS();
- if (state) JUMP_TAG(state);
-
- return val;
-}
-
-static VALUE
-eval_under_i(args)
- VALUE *args;
-{
- return eval(args[0], args[1], Qnil, (char*)args[2], (int)args[3]);
-}
-
-/* string eval under the class/module context */
-static VALUE
-eval_under(under, self, src, file, line)
- VALUE under, self, src;
- const char *file;
- int line;
-{
- VALUE args[4];
-
- if (ruby_safe_level >= 4) {
- StringValue(src);
- }
- else {
- SafeStringValue(src);
- }
- args[0] = self;
- args[1] = src;
- args[2] = (VALUE)file;
- args[3] = (VALUE)line;
- return exec_under(eval_under_i, under, under, args);
-}
-
-static VALUE
-yield_under_i(self)
- VALUE self;
-{
- return rb_yield_0(self, self, ruby_class, YIELD_PUBLIC_DEF, Qfalse);
-}
-
-/* block eval under the class/module context */
-static VALUE
-yield_under(under, self)
- VALUE under, self;
-{
- return exec_under(yield_under_i, under, 0, self);
-}
-
-static VALUE
-specific_eval(argc, argv, klass, self)
- int argc;
- VALUE *argv;
- VALUE klass, self;
-{
- if (rb_block_given_p()) {
- if (argc > 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
- }
- return yield_under(klass, self);
- }
- else {
- char *file = "(eval)";
- int line = 1;
-
- if (argc == 0) {
- rb_raise(rb_eArgError, "block not supplied");
- }
- else {
- if (ruby_safe_level >= 4) {
- StringValue(argv[0]);
- }
- else {
- SafeStringValue(argv[0]);
- }
- if (argc > 3) {
- rb_raise(rb_eArgError, "wrong number of arguments: %s(src) or %s{..}",
- rb_id2name(ruby_frame->callee),
- rb_id2name(ruby_frame->callee));
- }
- if (argc > 2) line = NUM2INT(argv[2]);
- if (argc > 1) {
- file = StringValuePtr(argv[1]);
- }
- }
- return eval_under(klass, self, argv[0], file, line);
- }
-}
-
-/*
- * call-seq:
- * obj.instance_eval(string [, filename [, lineno]] ) => obj
- * obj.instance_eval {| | block } => obj
- *
- * Evaluates a string containing Ruby source code, or the given block,
- * within the context of the receiver (_obj_). In order to set the
- * context, the variable +self+ is set to _obj_ while
- * the code is executing, giving the code access to _obj_'s
- * instance variables. In the version of <code>instance_eval</code>
- * that takes a +String+, the optional second and third
- * parameters supply a filename and starting line number that are used
- * when reporting compilation errors.
- *
- * class Klass
- * def initialize
- * @secret = 99
- * end
- * end
- * k = Klass.new
- * k.instance_eval { @secret } #=> 99
- */
-
-VALUE
-rb_obj_instance_eval(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- VALUE klass;
-
- if (FIXNUM_P(self) || SYMBOL_P(self)) {
- klass = Qnil;
- }
- else {
- klass = rb_singleton_class(self);
- }
- return specific_eval(argc, argv, klass, self);
-}
-
-/*
- * call-seq:
- * mod.class_eval(string [, filename [, lineno]]) => obj
- * mod.module_eval {|| block } => obj
- *
- * Evaluates the string or block in the context of _mod_. This can
- * be used to add methods to a class. <code>module_eval</code> returns
- * the result of evaluating its argument. The optional _filename_
- * and _lineno_ parameters set the text for error messages.
- *
- * class Thing
- * end
- * a = %q{def hello() "Hello there!" end}
- * Thing.module_eval(a)
- * puts Thing.new.hello()
- * Thing.module_eval("invalid code", "dummy", 123)
- *
- * <em>produces:</em>
- *
- * Hello there!
- * dummy:123:in `module_eval': undefined local variable
- * or method `code' for Thing:Class
- */
-
-VALUE
-rb_mod_module_eval(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- return specific_eval(argc, argv, mod, mod);
-}
-
-VALUE rb_load_path;
-
-NORETURN(static void load_failed _((VALUE)));
-
-void
-rb_load(fname, wrap)
- VALUE fname;
- int wrap;
-{
- VALUE tmp;
- int state;
- volatile int prohibit_int = rb_prohibit_interrupt;
- volatile ID callee, this_func;
- volatile VALUE wrapper = ruby_wrapper;
- volatile VALUE self = ruby_top_self;
- NODE * volatile last_node;
- NODE *saved_cref = ruby_cref;
- TMP_PROTECT;
-
- if (!wrap) rb_secure(4);
- FilePathValue(fname);
- fname = rb_str_new4(fname);
- tmp = rb_find_file(fname);
- if (!tmp) {
- load_failed(fname);
- }
- fname = tmp;
-
- ruby_errinfo = Qnil; /* ensure */
- PUSH_VARS();
- PUSH_CLASS(ruby_wrapper);
- ruby_cref = top_cref;
- if (!wrap) {
- rb_secure(4); /* should alter global state */
- ruby_class = rb_cObject;
- ruby_wrapper = 0;
- }
- else {
- /* load in anonymous module as toplevel */
- ruby_class = ruby_wrapper = rb_module_new();
- self = rb_obj_clone(ruby_top_self);
- rb_extend_object(self, ruby_wrapper);
- PUSH_CREF(ruby_wrapper);
- }
- PUSH_ITER(ITER_NOT);
- PUSH_FRAME();
- ruby_frame->callee = 0;
- ruby_frame->this_func = 0;
- ruby_frame->this_class = 0;
- ruby_frame->self = self;
- PUSH_SCOPE();
- /* default visibility is private at loading toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
- PUSH_TAG(PROT_NONE);
- state = EXEC_TAG();
- callee = ruby_frame->callee;
- this_func = ruby_frame->this_func;
- last_node = ruby_current_node;
- if (!ruby_current_node && ruby_sourcefile) {
- last_node = NEW_BEGIN(0);
- }
- ruby_current_node = 0;
- if (state == 0) {
- NODE * volatile node;
- volatile int critical;
-
- DEFER_INTS;
- ruby_in_eval++;
- critical = rb_thread_critical;
- rb_thread_critical = Qtrue;
- rb_load_file(RSTRING(fname)->ptr);
- ruby_in_eval--;
- node = ruby_eval_tree;
- rb_thread_critical = critical;
- ALLOW_INTS;
- if (ruby_nerrs == 0) {
- eval_node(self, node);
- }
- }
- ruby_frame->callee = callee;
- ruby_frame->this_func = this_func;
- ruby_current_node = last_node;
- ruby_sourcefile = 0;
- ruby_set_current_source();
- if (ruby_scope->flags == SCOPE_ALLOCA && ruby_class == rb_cObject) {
- if (ruby_scope->local_tbl) /* toplevel was empty */
- free(ruby_scope->local_tbl);
- }
- POP_TAG();
- rb_prohibit_interrupt = prohibit_int;
- ruby_cref = saved_cref;
- POP_SCOPE();
- POP_FRAME();
- POP_ITER();
- POP_CLASS();
- POP_VARS();
- ruby_wrapper = wrapper;
- if (ruby_nerrs > 0) {
- ruby_nerrs = 0;
- rb_exc_raise(ruby_errinfo);
- }
- if (state) jump_tag_but_local_jump(state, Qundef);
- if (!NIL_P(ruby_errinfo)) /* exception during load */
- rb_exc_raise(ruby_errinfo);
-}
-
-void
-rb_load_protect(fname, wrap, state)
- VALUE fname;
- int wrap;
- int *state;
-{
- int status;
-
- PUSH_THREAD_TAG();
- if ((status = EXEC_TAG()) == 0) {
- rb_load(fname, wrap);
- }
- else if (status == TAG_THREAD) {
- rb_thread_start_1();
- }
- POP_THREAD_TAG();
- if (state) *state = status;
-}
-
-/*
- * call-seq:
- * load(filename, wrap=false) => true
- *
- * Loads and executes the Ruby
- * program in the file _filename_. If the filename does not
- * resolve to an absolute path, the file is searched for in the library
- * directories listed in <code>$:</code>. If the optional _wrap_
- * parameter is +true+, the loaded script will be executed
- * under an anonymous module, protecting the calling program's global
- * namespace. In no circumstance will any local variables in the loaded
- * file be propagated to the loading environment.
- */
-
-
-static VALUE
-rb_f_load(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fname, wrap;
-
- rb_scan_args(argc, argv, "11", &fname, &wrap);
- rb_load(fname, RTEST(wrap));
- return Qtrue;
-}
-
-VALUE ruby_dln_librefs;
-static VALUE rb_features;
-static st_table *loading_tbl;
-
-#define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0)
-#ifdef DLEXT2
-#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0)
-#else
-#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
-#endif
-
-static char *
-rb_feature_p(feature, ext, rb)
- const char *feature, *ext;
- int rb;
-{
- VALUE v;
- char *f, *e;
- long i, len, elen;
-
- if (ext) {
- len = ext - feature;
- elen = strlen(ext);
- }
- else {
- len = strlen(feature);
- elen = 0;
- }
- for (i = 0; i < RARRAY(rb_features)->len; ++i) {
- v = RARRAY(rb_features)->ptr[i];
- f = StringValuePtr(v);
- if (strncmp(f, feature, len) != 0) continue;
- if (!*(e = f + len)) {
- if (ext) continue;
- return e;
- }
- if (*e != '.') continue;
- if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
- return e;
- }
- if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
- return e;
- }
- }
- return 0;
-}
-
-static const char *const loadable_ext[] = {
- ".rb", DLEXT,
-#ifdef DLEXT2
- DLEXT2,
-#endif
- 0
-};
-
-static int search_required _((VALUE, VALUE *));
-
-int
-rb_provided(feature)
- const char *feature;
-{
- int i;
- char *buf;
- VALUE fname;
-
- if (rb_feature_p(feature, 0, Qfalse))
- return Qtrue;
- if (loading_tbl) {
- if (st_lookup(loading_tbl, (st_data_t)feature, 0)) return Qtrue;
- buf = ALLOCA_N(char, strlen(feature)+8);
- strcpy(buf, feature);
- for (i=0; loadable_ext[i]; i++) {
- strcpy(buf+strlen(feature), loadable_ext[i]);
- if (st_lookup(loading_tbl, (st_data_t)buf, 0)) return Qtrue;
- }
- }
- if (search_required(rb_str_new2(feature), &fname)) {
- feature = RSTRING(fname)->ptr;
- if (rb_feature_p(feature, 0, Qfalse))
- return Qtrue;
- if (loading_tbl && st_lookup(loading_tbl, (st_data_t)feature, 0))
- return Qtrue;
- }
- return Qfalse;
-}
-
-static void
-rb_provide_feature(feature)
- VALUE feature;
-{
- rb_ary_push(rb_features, feature);
-}
-
-void
-rb_provide(feature)
- const char *feature;
-{
- rb_provide_feature(rb_str_new2(feature));
-}
-
-static int
-load_wait(ftptr)
- char *ftptr;
-{
- st_data_t th;
-
- if (!loading_tbl) return Qfalse;
- if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse;
- if ((rb_thread_t)th == curr_thread) return Qtrue;
- do {
- CHECK_INTS;
- rb_thread_schedule();
- } while (st_lookup(loading_tbl, (st_data_t)ftptr, &th));
- return Qtrue;
-}
-
-/*
- * call-seq:
- * require(string) => true or false
- *
- * Ruby tries to load the library named _string_, returning
- * +true+ if successful. If the filename does not resolve to
- * an absolute path, it will be searched for in the directories listed
- * in <code>$:</code>. If the file has the extension ``.rb'', it is
- * loaded as a source file; if the extension is ``.so'', ``.o'', or
- * ``.dll'', or whatever the default shared library extension is on
- * the current platform, Ruby loads the shared library as a Ruby
- * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
- * to the name. The name of the loaded feature is added to the array in
- * <code>$"</code>. A feature will not be loaded if it's name already
- * appears in <code>$"</code>. However, the file name is not converted
- * to an absolute path, so that ``<code>require 'a';require
- * './a'</code>'' will load <code>a.rb</code> twice.
- *
- * require "my-library.rb"
- * require "db-driver"
- */
-
-VALUE
-rb_f_require(obj, fname)
- VALUE obj, fname;
-{
- return rb_require_safe(fname, ruby_safe_level);
-}
-
-static int
-search_required(fname, path)
- VALUE fname, *path;
-{
- VALUE tmp;
- char *ext, *ftptr;
- int type;
-
- *path = 0;
- ext = strrchr(ftptr = RSTRING(fname)->ptr, '.');
- if (ext && !strchr(ext, '/')) {
- if (strcmp(".rb", ext) == 0) {
- if (rb_feature_p(ftptr, ext, Qtrue)) return 'r';
- if (tmp = rb_find_file(fname)) {
- tmp = rb_file_expand_path(tmp, Qnil);
- ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
- if (!rb_feature_p(ftptr, ext, Qtrue))
- *path = tmp;
- return 'r';
- }
- return 0;
- }
- else if (IS_SOEXT(ext)) {
- if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr);
-#ifdef DLEXT2
- OBJ_FREEZE(tmp);
- if (rb_find_file_ext(&tmp, loadable_ext+1)) {
- tmp = rb_file_expand_path(tmp, Qnil);
- ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
- if (!rb_feature_p(ftptr, ext, Qfalse))
- *path = tmp;
- return 's';
- }
-#else
- rb_str_cat2(tmp, DLEXT);
- OBJ_FREEZE(tmp);
- if (tmp = rb_find_file(tmp)) {
- tmp = rb_file_expand_path(tmp, Qnil);
- ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
- if (!rb_feature_p(ftptr, ext, Qfalse))
- *path = tmp;
- return 's';
- }
-#endif
- }
- else if (IS_DLEXT(ext)) {
- if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- if (tmp = rb_find_file(fname)) {
- tmp = rb_file_expand_path(tmp, Qnil);
- ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
- if (!rb_feature_p(ftptr, ext, Qfalse))
- *path = tmp;
- return 's';
- }
- }
- }
- else if (ext = rb_feature_p(ftptr, 0, Qfalse)) {
- return (*ext && (IS_SOEXT(ext) || IS_DLEXT(ext))) ? 's' : 'r';
- }
- tmp = fname;
- type = rb_find_file_ext(&tmp, loadable_ext);
- tmp = rb_file_expand_path(tmp, Qnil);
- switch (type) {
- case 0:
- ftptr = RSTRING(tmp)->ptr;
- if ((ext = rb_feature_p(ftptr, 0, Qfalse))) {
- type = strcmp(".rb", ext);
- break;
- }
- return 0;
-
- default:
- ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
- if (rb_feature_p(ftptr, ext, !--type)) break;
- *path = tmp;
- }
- return type ? 's' : 'r';
-}
-
-static void
-load_failed(fname)
- VALUE fname;
-{
- rb_raise(rb_eLoadError, "no such file to load -- %s", RSTRING(fname)->ptr);
-}
-
-VALUE
-rb_require_safe(fname, safe)
- VALUE fname;
- int safe;
-{
- VALUE result = Qnil;
- volatile VALUE errinfo = ruby_errinfo;
- int state;
- struct {
- NODE *node;
- ID this_func, callee;
- int vmode, safe;
- } volatile saved;
- char *volatile ftptr = 0;
-
- saved.vmode = scope_vmode;
- saved.node = ruby_current_node;
- saved.callee = ruby_frame->callee;
- saved.this_func = ruby_frame->this_func;
- saved.safe = ruby_safe_level;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- VALUE path;
- long handle;
- int found;
-
- ruby_safe_level = safe;
- FilePathValue(fname);
- *(volatile VALUE *)&fname = rb_str_new4(fname);
- found = search_required(fname, &path);
- if (found) {
- if (!path || load_wait(RSTRING(path)->ptr)) {
- result = Qfalse;
- }
- else {
- ruby_safe_level = 0;
- switch (found) {
- case 'r':
- /* loading ruby library should be serialized. */
- if (!loading_tbl) {
- loading_tbl = st_init_strtable();
- }
- /* partial state */
- ftptr = ruby_strdup(RSTRING(path)->ptr);
- st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
- rb_load(path, 0);
- break;
-
- case 's':
- ruby_current_node = 0;
- ruby_sourcefile = rb_source_filename(RSTRING(path)->ptr);
- ruby_sourceline = 0;
- ruby_frame->callee = 0;
- ruby_frame->this_func = 0;
- SCOPE_SET(SCOPE_PUBLIC);
- handle = (long)dln_load(RSTRING(path)->ptr);
- rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
- break;
- }
- rb_provide_feature(path);
- result = Qtrue;
- }
- }
- }
- POP_TAG();
- ruby_current_node = saved.node;
- ruby_set_current_source();
- ruby_frame->this_func = saved.this_func;
- ruby_frame->callee = saved.callee;
- SCOPE_SET(saved.vmode);
- ruby_safe_level = saved.safe;
- if (ftptr) {
- if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
- free(ftptr);
- }
- }
- if (state) JUMP_TAG(state);
- if (NIL_P(result)) {
- load_failed(fname);
- }
- ruby_errinfo = errinfo;
-
- return result;
-}
-
-VALUE
-rb_require(fname)
- const char *fname;
-{
- VALUE fn = rb_str_new2(fname);
- OBJ_FREEZE(fn);
- return rb_require_safe(fn, ruby_safe_level);
-}
-
-static void
-secure_visibility(self)
- VALUE self;
-{
- if (ruby_safe_level >= 4 && !OBJ_TAINTED(self)) {
- rb_raise(rb_eSecurityError, "Insecure: can't change method visibility");
- }
-}
-
-static void
-set_method_visibility(self, argc, argv, ex)
- VALUE self;
- int argc;
- VALUE *argv;
- ID ex;
-{
- int i;
-
- secure_visibility(self);
- for (i=0; i<argc; i++) {
- rb_export_method(self, rb_to_id(argv[i]), ex);
- }
- rb_clear_cache_by_class(self);
-}
-
-/*
- * call-seq:
- * public => self
- * public(symbol, ...) => self
- *
- * With no arguments, sets the default visibility for subsequently
- * defined methods to public. With arguments, sets the named methods to
- * have public visibility.
- */
-
-static VALUE
-rb_mod_public(argc, argv, module)
- int argc;
- VALUE *argv;
- VALUE module;
-{
- secure_visibility(module);
- if (argc == 0) {
- SCOPE_SET(SCOPE_PUBLIC);
- }
- else {
- set_method_visibility(module, argc, argv, NOEX_PUBLIC);
- }
- return module;
-}
-
-/*
- * call-seq:
- * protected => self
- * protected(symbol, ...) => self
- *
- * With no arguments, sets the default visibility for subsequently
- * defined methods to protected. With arguments, sets the named methods
- * to have protected visibility.
- */
-
-static VALUE
-rb_mod_protected(argc, argv, module)
- int argc;
- VALUE *argv;
- VALUE module;
-{
- secure_visibility(module);
- if (argc == 0) {
- SCOPE_SET(SCOPE_PROTECTED);
- }
- else {
- set_method_visibility(module, argc, argv, NOEX_PROTECTED);
- }
- return module;
-}
-
-/*
- * call-seq:
- * private => self
- * private(symbol, ...) => self
- *
- * With no arguments, sets the default visibility for subsequently
- * defined methods to private. With arguments, sets the named methods
- * to have private visibility.
- *
- * module Mod
- * def a() end
- * def b() end
- * private
- * def c() end
- * private :a
- * end
- * Mod.private_instance_methods #=> ["a", "c"]
- */
-
-static VALUE
-rb_mod_private(argc, argv, module)
- int argc;
- VALUE *argv;
- VALUE module;
-{
- secure_visibility(module);
- if (argc == 0) {
- SCOPE_SET(SCOPE_PRIVATE);
- }
- else {
- set_method_visibility(module, argc, argv, NOEX_PRIVATE);
- }
- return module;
-}
-
-/*
- * call-seq:
- * mod.public_class_method(symbol, ...) => mod
- *
- * Makes a list of existing class methods public.
- */
-
-static VALUE
-rb_mod_public_method(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
- return obj;
-}
-
-/*
- * call-seq:
- * mod.private_class_method(symbol, ...) => mod
- *
- * Makes existing class methods private. Often used to hide the default
- * constructor <code>new</code>.
- *
- * class SimpleSingleton # Not thread safe
- * private_class_method :new
- * def SimpleSingleton.create(*args, &block)
- * @me = new(*args, &block) if ! @me
- * @me
- * end
- * end
- */
-
-static VALUE
-rb_mod_private_method(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
- return obj;
-}
-
-/*
- * call-seq:
- * public
- * public(symbol, ...)
- *
- * With no arguments, sets the default visibility for subsequently
- * defined methods to public. With arguments, sets the named methods to
- * have public visibility.
- */
-
-static VALUE
-top_public(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_mod_public(argc, argv, rb_cObject);
-}
-
-static VALUE
-top_private(argc, argv)
- int argc;
- VALUE *argv;
-{
- return rb_mod_private(argc, argv, rb_cObject);
-}
-
-/*
- * call-seq:
- * module_function(symbol, ...) => self
- *
- * Creates module functions for the named methods. These functions may
- * be called with the module as a receiver, and also become available
- * as instance methods to classes that mix in the module. Module
- * functions are copies of the original, and so may be changed
- * independently. The instance-method versions are made private. If
- * used with no arguments, subsequently defined methods become module
- * functions.
- *
- * module Mod
- * def one
- * "This is one"
- * end
- * module_function :one
- * end
- * class Cls
- * include Mod
- * def callOne
- * one
- * end
- * end
- * Mod.one #=> "This is one"
- * c = Cls.new
- * c.callOne #=> "This is one"
- * module Mod
- * def one
- * "This is the new one"
- * end
- * end
- * Mod.one #=> "This is one"
- * c.callOne #=> "This is the new one"
- */
-
-static VALUE
-rb_mod_modfunc(argc, argv, module)
- int argc;
- VALUE *argv;
- VALUE module;
-{
- int i;
- ID id;
- NODE *body;
-
- if (TYPE(module) != T_MODULE) {
- rb_raise(rb_eTypeError, "module_function must be called for modules");
- }
-
- secure_visibility(module);
- if (argc == 0) {
- SCOPE_SET(SCOPE_MODFUNC);
- return module;
- }
-
- set_method_visibility(module, argc, argv, NOEX_PRIVATE);
- for (i=0; i<argc; i++) {
- VALUE m = module;
-
- id = rb_to_id(argv[i]);
- for (;;) {
- body = search_method(m, id, &m);
- if (body == 0) {
- body = search_method(rb_cObject, id, &m);
- }
- if (body == 0 || body->nd_body == 0) {
- rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
- }
- if (nd_type(body->nd_body) != NODE_ZSUPER) {
- break; /* normal case: need not to follow 'super' link */
- }
- m = RCLASS(m)->super;
- if (!m) break;
- }
- rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
- }
- return module;
-}
-
-/*
- * call-seq:
- * append_features(mod) => mod
- *
- * When this module is included in another, Ruby calls
- * <code>append_features</code> in this module, passing it the
- * receiving module in _mod_. Ruby's default implementation is
- * to add the constants, methods, and module variables of this module
- * to _mod_ if this module has not already been added to
- * _mod_ or one of its ancestors. See also <code>Module#include</code>.
- */
-
-static VALUE
-rb_mod_append_features(module, include)
- VALUE module, include;
-{
- switch (TYPE(include)) {
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- Check_Type(include, T_CLASS);
- break;
- }
- rb_include_module(include, module);
-
- return module;
-}
-
-/*
- * call-seq:
- * include(module, ...) => self
- *
- * Invokes <code>Module.append_features</code> on each parameter in turn.
- */
-
-static VALUE
-rb_mod_include(argc, argv, module)
- int argc;
- VALUE *argv;
- VALUE module;
-{
- int i;
-
- for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
- while (argc--) {
- rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
- rb_funcall(argv[argc], rb_intern("included"), 1, module);
- }
- return module;
-}
-
-void
-rb_obj_call_init(obj, argc, argv)
- VALUE obj;
- int argc;
- VALUE *argv;
-{
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- rb_funcall2(obj, init, argc, argv);
- POP_ITER();
-}
-
-void
-rb_extend_object(obj, module)
- VALUE obj, module;
-{
- rb_include_module(rb_singleton_class(obj), module);
-}
-
-/*
- * call-seq:
- * extend_object(obj) => obj
- *
- * Extends the specified object by adding this module's constants and
- * methods (which are added as singleton methods). This is the callback
- * method used by <code>Object#extend</code>.
- *
- * module Picky
- * def Picky.extend_object(o)
- * if String === o
- * puts "Can't add Picky to a String"
- * else
- * puts "Picky added to #{o.class}"
- * super
- * end
- * end
- * end
- * (s = Array.new).extend Picky # Call Object.extend
- * (s = "quick brown fox").extend Picky
- *
- * <em>produces:</em>
- *
- * Picky added to Array
- * Can't add Picky to a String
- */
-
-static VALUE
-rb_mod_extend_object(mod, obj)
- VALUE mod, obj;
-{
- rb_extend_object(obj, mod);
- return obj;
-}
-
-/*
- * call-seq:
- * obj.extend(module, ...) => obj
- *
- * Adds to _obj_ the instance methods from each module given as a
- * parameter.
- *
- * module Mod
- * def hello
- * "Hello from Mod.\n"
- * end
- * end
- *
- * class Klass
- * def hello
- * "Hello from Klass.\n"
- * end
- * end
- *
- * k = Klass.new
- * k.hello #=> "Hello from Klass.\n"
- * k.extend(Mod) #=> #<Klass:0x401b3bc8>
- * k.hello #=> "Hello from Mod.\n"
- */
-
-static VALUE
-rb_obj_extend(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- int i;
-
- if (argc == 0) {
- rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
- }
- for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
- while (argc--) {
- rb_funcall(argv[argc], rb_intern("extend_object"), 1, obj);
- rb_funcall(argv[argc], rb_intern("extended"), 1, obj);
- }
- return obj;
-}
-
-/*
- * call-seq:
- * include(module, ...) => self
- *
- * Invokes <code>Module.append_features</code>
- * on each parameter in turn. Effectively adds the methods and constants
- * in each module to the receiver.
- */
-
-static VALUE
-top_include(argc, argv, self)
- int argc;
- VALUE *argv;
- VALUE self;
-{
- rb_secure(4);
- if (ruby_wrapper) {
- rb_warning("main#include in the wrapped load is effective only in wrapper module");
- return rb_mod_include(argc, argv, ruby_wrapper);
- }
- return rb_mod_include(argc, argv, rb_cObject);
-}
-
-VALUE rb_f_trace_var();
-VALUE rb_f_untrace_var();
-
-static void
-errinfo_setter(val, id, var)
- VALUE val;
- ID id;
- VALUE *var;
-{
- if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
- rb_raise(rb_eTypeError, "assigning non-exception to $!");
- }
- *var = val;
-}
-
-static VALUE
-errat_getter(id)
- ID id;
-{
- return get_backtrace(ruby_errinfo);
-}
-
-static void
-errat_setter(val, id, var)
- VALUE val;
- ID id;
- VALUE *var;
-{
- if (NIL_P(ruby_errinfo)) {
- rb_raise(rb_eArgError, "$! not set");
- }
- set_backtrace(ruby_errinfo, val);
-}
-
-/*
- * call-seq:
- * local_variables => array
- *
- * Returns the names of the current local variables.
- *
- * fred = 1
- * for i in 1..10
- * # ...
- * end
- * local_variables #=> ["fred", "i"]
- */
-
-static VALUE
-rb_f_local_variables()
-{
- ID *tbl;
- int n, i;
- VALUE ary = rb_ary_new();
- struct RVarmap *vars;
-
- tbl = ruby_scope->local_tbl;
- if (tbl) {
- n = *tbl++;
- for (i=2; i<n; i++) { /* skip first 2 ($_ and $~) */
- if (!rb_is_local_id(tbl[i])) continue; /* skip flip states */
- rb_ary_push(ary, rb_str_new2(rb_id2name(tbl[i])));
- }
- }
-
- vars = ruby_dyna_vars;
- while (vars) {
- if (vars->id && rb_is_local_id(vars->id)) { /* skip $_, $~ and flip states */
- rb_ary_push(ary, rb_str_new2(rb_id2name(vars->id)));
- }
- vars = vars->next;
- }
-
- return ary;
-}
-
-static VALUE rb_f_catch _((VALUE,VALUE));
-NORETURN(static VALUE rb_f_throw _((int,VALUE*)));
-
-struct end_proc_data {
- void (*func)();
- VALUE data;
- int safe;
- struct end_proc_data *next;
-};
-
-static struct end_proc_data *end_procs, *ephemeral_end_procs, *tmp_end_procs;
-
-void
-rb_set_end_proc(func, data)
- void (*func) _((VALUE));
- VALUE data;
-{
- struct end_proc_data *link = ALLOC(struct end_proc_data);
- struct end_proc_data **list;
-
- if (ruby_wrapper) list = &ephemeral_end_procs;
- else list = &end_procs;
- link->next = *list;
- link->func = func;
- link->data = data;
- link->safe = ruby_safe_level;
- *list = link;
-}
-
-void
-rb_mark_end_proc()
-{
- struct end_proc_data *link;
-
- link = end_procs;
- while (link) {
- rb_gc_mark(link->data);
- link = link->next;
- }
- link = ephemeral_end_procs;
- while (link) {
- rb_gc_mark(link->data);
- link = link->next;
- }
- link = tmp_end_procs;
- while (link) {
- rb_gc_mark(link->data);
- link = link->next;
- }
-}
-
-static void call_end_proc _((VALUE data));
-
-static void
-call_end_proc(data)
- VALUE data;
-{
- PUSH_ITER(ITER_NOT);
- PUSH_FRAME();
- ruby_frame->self = ruby_frame->prev->self;
- ruby_frame->node = 0;
- ruby_frame->callee = 0;
- ruby_frame->this_func = 0;
- ruby_frame->this_class = 0;
- proc_invoke(data, rb_ary_new2(0), Qundef, 0);
- POP_FRAME();
- POP_ITER();
-}
-
-static void
-rb_f_END()
-{
- PUSH_FRAME();
- ruby_frame->argc = 0;
- ruby_frame->iter = ITER_CUR;
- rb_set_end_proc(call_end_proc, rb_block_proc());
- POP_FRAME();
-}
-
-/*
- * call-seq:
- * at_exit { block } -> proc
- *
- * Converts _block_ to a +Proc+ object (and therefore
- * binds it at the point of call) and registers it for execution when
- * the program exits. If multiple handlers are registered, they are
- * executed in reverse order of registration.
- *
- * def do_at_exit(str1)
- * at_exit { print str1 }
- * end
- * at_exit { puts "cruel world" }
- * do_at_exit("goodbye ")
- * exit
- *
- * <em>produces:</em>
- *
- * goodbye cruel world
- */
-
-static VALUE
-rb_f_at_exit()
-{
- VALUE proc;
-
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "called without a block");
- }
- proc = rb_block_proc();
- rb_set_end_proc(call_end_proc, proc);
- return proc;
-}
-
-void
-rb_exec_end_proc()
-{
- struct end_proc_data *link, *tmp;
- int status;
- volatile int safe = ruby_safe_level;
-
- while (ephemeral_end_procs) {
- tmp_end_procs = link = ephemeral_end_procs;
- ephemeral_end_procs = 0;
- while (link) {
- PUSH_TAG(PROT_NONE);
- if ((status = EXEC_TAG()) == 0) {
- ruby_safe_level = link->safe;
- (*link->func)(link->data);
- }
- POP_TAG();
- if (status) {
- error_handle(status);
- }
- tmp = link;
- tmp_end_procs = link = link->next;
- free(tmp);
- }
- }
- while (end_procs) {
- tmp_end_procs = link = end_procs;
- end_procs = 0;
- while (link) {
- PUSH_TAG(PROT_NONE);
- if ((status = EXEC_TAG()) == 0) {
- ruby_safe_level = link->safe;
- (*link->func)(link->data);
- }
- POP_TAG();
- if (status) {
- error_handle(status);
- }
- tmp = link;
- tmp_end_procs = link = link->next;
- free(tmp);
- }
- }
- ruby_safe_level = safe;
-}
-
-void
-Init_eval()
-{
- init = rb_intern("initialize");
- eqq = rb_intern("===");
- each = rb_intern("each");
-
- aref = rb_intern("[]");
- aset = rb_intern("[]=");
- match = rb_intern("=~");
- missing = rb_intern("method_missing");
- added = rb_intern("method_added");
- singleton_added = rb_intern("singleton_method_added");
- removed = rb_intern("method_removed");
- singleton_removed = rb_intern("singleton_method_removed");
- undefined = rb_intern("method_undefined");
- singleton_undefined = rb_intern("singleton_method_undefined");
-
- __id__ = rb_intern("__id__");
- __send__ = rb_intern("__send__");
-
- rb_global_variable((VALUE*)&top_scope);
- rb_global_variable((VALUE*)&ruby_eval_tree);
- rb_global_variable((VALUE*)&ruby_dyna_vars);
-
- rb_define_virtual_variable("$@", errat_getter, errat_setter);
- rb_define_hooked_variable("$!", &ruby_errinfo, 0, errinfo_setter);
-
- rb_define_global_function("eval", rb_f_eval, -1);
- rb_define_global_function("iterator?", rb_f_block_given_p, 0);
- rb_define_global_function("block_given?", rb_f_block_given_p, 0);
- rb_define_global_function("method_missing", rb_method_missing, -1);
- rb_define_global_function("loop", rb_f_loop, 0);
-
- rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
- respond_to = rb_intern("respond_to?");
- basic_respond_to = rb_method_node(rb_cObject, respond_to);
- rb_global_variable((VALUE*)&basic_respond_to);
-
- rb_define_global_function("raise", rb_f_raise, -1);
- rb_define_global_function("fail", rb_f_raise, -1);
-
- rb_define_global_function("caller", rb_f_caller, -1);
-
- rb_define_global_function("exit", rb_f_exit, -1);
- rb_define_global_function("abort", rb_f_abort, -1);
-
- rb_define_global_function("at_exit", rb_f_at_exit, 0);
-
- rb_define_global_function("catch", rb_f_catch, 1);
- rb_define_global_function("throw", rb_f_throw, -1);
- rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */
- rb_define_global_function("local_variables", rb_f_local_variables, 0);
-
- rb_define_method(rb_mKernel, "send", rb_f_send, -1);
- rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
- rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
-
- rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
- rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
- rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
- rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
- rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
- rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
- rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
- rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
- rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
- rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
- rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
- rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
- rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
- rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
- rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
-
- rb_undef_method(rb_cClass, "module_function");
-
- rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
- rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
- rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
- rb_define_private_method(rb_cModule, "define_method", rb_mod_define_method, -1);
-
- rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
- rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0);
-
- rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
- rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
- rb_define_singleton_method(ruby_top_self, "private", top_private, -1);
-
- rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
-
- rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
- rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */
-
- rb_define_global_function("set_trace_func", set_trace_func, 1);
- rb_global_variable(&trace_func);
-
- rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
-}
-
-/*
- * call-seq:
- * mod.autoload(name, filename) => nil
- *
- * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
- * the first time that _module_ (which may be a <code>String</code> or
- * a symbol) is accessed in the namespace of _mod_.
- *
- * module A
- * end
- * A.autoload(:B, "b")
- * A::B.doit # autoloads "b"
- */
-
-static VALUE
-rb_mod_autoload(mod, sym, file)
- VALUE mod;
- VALUE sym;
- VALUE file;
-{
- ID id = rb_to_id(sym);
-
- Check_SafeStr(file);
- rb_autoload(mod, id, RSTRING(file)->ptr);
- return Qnil;
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_mod_autoload_p(mod, sym)
- VALUE mod, sym;
-{
- return rb_autoload_p(mod, rb_to_id(sym));
-}
-
-/*
- * call-seq:
- * autoload(module, filename) => nil
- *
- * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
- * the first time that _module_ (which may be a <code>String</code> or
- * a symbol) is accessed.
- *
- * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
- */
-
-static VALUE
-rb_f_autoload(obj, sym, file)
- VALUE obj;
- VALUE sym;
- VALUE file;
-{
- return rb_mod_autoload(ruby_cbase, sym, file);
-}
-
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-rb_f_autoload_p(obj, sym)
- VALUE obj;
- VALUE sym;
-{
- /* use ruby_cbase as same as rb_f_autoload. */
- return rb_mod_autoload_p(ruby_cbase, sym);
-}
-
-void
-Init_load()
-{
- rb_load_path = rb_ary_new();
- rb_define_readonly_variable("$:", &rb_load_path);
- rb_define_readonly_variable("$-I", &rb_load_path);
- rb_define_readonly_variable("$LOAD_PATH", &rb_load_path);
-
- rb_features = rb_ary_new();
- rb_define_readonly_variable("$\"", &rb_features);
- rb_define_readonly_variable("$LOADED_FEATURES", &rb_features);
-
- rb_define_global_function("load", rb_f_load, -1);
- rb_define_global_function("require", rb_f_require, 1);
- rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
- rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
- rb_define_global_function("autoload", rb_f_autoload, 2);
- rb_define_global_function("autoload?", rb_f_autoload_p, 1);
- rb_global_variable(&ruby_wrapper);
-
- ruby_dln_librefs = rb_ary_new();
- rb_global_variable(&ruby_dln_librefs);
-}
-
-static void
-scope_dup(scope)
- struct SCOPE *scope;
-{
- volatile ID *tbl;
- VALUE *vars;
-
- scope->flags |= SCOPE_DONT_RECYCLE;
- if (scope->flags & SCOPE_MALLOC) return;
-
- if (scope->local_tbl) {
- tbl = scope->local_tbl;
- vars = ALLOC_N(VALUE, tbl[0]+1);
- *vars++ = scope->local_vars[-1];
- MEMCPY(vars, scope->local_vars, VALUE, tbl[0]);
- scope->local_vars = vars;
- scope->flags |= SCOPE_MALLOC;
- }
-}
-
-static void
-blk_mark(data)
- struct BLOCK *data;
-{
- while (data) {
- rb_gc_mark_frame(&data->frame);
- rb_gc_mark((VALUE)data->scope);
- rb_gc_mark((VALUE)data->var);
- rb_gc_mark((VALUE)data->body);
- rb_gc_mark((VALUE)data->self);
- rb_gc_mark((VALUE)data->dyna_vars);
- rb_gc_mark((VALUE)data->cref);
- rb_gc_mark(data->wrapper);
- rb_gc_mark(data->block_obj);
- data = data->prev;
- }
-}
-
-static void
-frame_free(frame)
- struct FRAME *frame;
-{
- struct FRAME *tmp;
-
- frame = frame->prev;
- while (frame) {
- tmp = frame;
- frame = frame->prev;
- free(tmp);
- }
-}
-
-static void
-blk_free(data)
- struct BLOCK *data;
-{
- void *tmp;
-
- while (data) {
- frame_free(&data->frame);
- tmp = data;
- data = data->prev;
- free(tmp);
- }
-}
-
-static void
-frame_dup(frame)
- struct FRAME *frame;
-{
- struct FRAME *tmp;
-
- for (;;) {
- frame->tmp = 0; /* should not preserve tmp */
- if (!frame->prev) break;
- tmp = ALLOC(struct FRAME);
- *tmp = *frame->prev;
- frame->prev = tmp;
- frame = tmp;
- }
-}
-
-static void
-blk_copy_prev(block)
- struct BLOCK *block;
-{
- struct BLOCK *tmp;
- struct RVarmap* vars;
-
- while (block->prev) {
- tmp = ALLOC_N(struct BLOCK, 1);
- MEMCPY(tmp, block->prev, struct BLOCK, 1);
- scope_dup(tmp->scope);
- frame_dup(&tmp->frame);
-
- for (vars = tmp->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
-
- block->prev = tmp;
- block = tmp;
- }
-}
-
-
-static void
-blk_dup(dup, orig)
- struct BLOCK *dup, *orig;
-{
- MEMCPY(dup, orig, struct BLOCK, 1);
- frame_dup(&dup->frame);
-
- if (dup->iter) {
- blk_copy_prev(dup);
- }
- else {
- dup->prev = 0;
- }
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-proc_clone(self)
- VALUE self;
-{
- struct BLOCK *orig, *data;
- VALUE bind;
-
- Data_Get_Struct(self, struct BLOCK, orig);
- bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
- CLONESETUP(bind, self);
- blk_dup(data, orig);
-
- return bind;
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-proc_dup(self)
- VALUE self;
-{
- struct BLOCK *orig, *data;
- VALUE bind;
-
- Data_Get_Struct(self, struct BLOCK, orig);
- bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
- blk_dup(data, orig);
-
- return bind;
-}
-
-/*
- * call-seq:
- * binding -> a_binding
- *
- * Returns a +Binding+ object, describing the variable and
- * method bindings at the point of call. This object can be used when
- * calling +eval+ to execute the evaluated command in this
- * environment. Also see the description of class +Binding+.
- *
- * def getBinding(param)
- * return binding
- * end
- * b = getBinding("hello")
- * eval("param", b) #=> "hello"
- */
-
-static VALUE
-rb_f_binding(self)
- VALUE self;
-{
- struct BLOCK *data, *p;
- struct RVarmap *vars;
- VALUE bind;
-
- PUSH_BLOCK(0,0);
- bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
- *data = *ruby_block;
-
- data->orig_thread = rb_thread_current();
- data->wrapper = ruby_wrapper;
- data->iter = rb_f_block_given_p();
- frame_dup(&data->frame);
- if (ruby_frame->prev) {
- data->frame.callee = ruby_frame->prev->callee;
- data->frame.this_func = ruby_frame->prev->this_func;
- data->frame.this_class = ruby_frame->prev->this_class;
- }
-
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
-
- for (p = data; p; p = p->prev) {
- for (vars = p->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- }
- scope_dup(data->scope);
- POP_BLOCK();
-
- return bind;
-}
-
-/*
- * call-seq:
- * binding.eval(string [, filename [,lineno]]) => obj
- *
- * Evaluates the Ruby expression(s) in <em>string</em>, in the
- * <em>binding</em>'s context. If the optional <em>filename</em> and
- * <em>lineno</em> parameters are present, they will be used when
- * reporting syntax errors.
- *
- * def getBinding(param)
- * return binding
- * end
- * b = getBinding("hello")
- * b.eval("param") #=> "hello"
- */
-
-static VALUE
-bind_eval(argc, argv, bind)
- int argc;
- VALUE *argv;
- VALUE bind;
-{
- struct BLOCK *data;
- VALUE args[4];
-
- rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
- args[1] = bind;
- Data_Get_Struct(bind, struct BLOCK, data);
-
- return rb_f_eval(argc+1, args, data->self);
-}
-
-#define PROC_TSHIFT (FL_USHIFT+1)
-#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
-#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
-#define PROC_NOSAFE FL_USER4
-
-#define SAFE_LEVEL_MAX PROC_TMASK
-
-#define proc_safe_level_p(data) (!(RBASIC(data)->flags & PROC_NOSAFE))
-
-static void
-proc_save_safe_level(data)
- VALUE data;
-{
- int safe = ruby_safe_level;
- if (safe > PROC_TMAX) safe = PROC_TMAX;
- FL_SET(data, (safe << PROC_TSHIFT) & PROC_TMASK);
-}
-
-static int
-proc_get_safe_level(data)
- VALUE data;
-{
- return (RBASIC(data)->flags & PROC_TMASK) >> PROC_TSHIFT;
-}
-
-static void
-proc_set_safe_level(data)
- VALUE data;
-{
- if (!proc_safe_level_p(data)) return;
- ruby_safe_level = proc_get_safe_level(data);
-}
-
-static VALUE
-proc_alloc(klass, proc)
- VALUE klass;
- int proc;
-{
- volatile VALUE block;
- struct BLOCK *data, *p;
- struct RVarmap *vars;
-
- if (!rb_block_given_p() && !rb_f_block_given_p()) {
- rb_raise(rb_eArgError, "tried to create Proc object without a block");
- }
- if (proc && !rb_block_given_p()) {
- rb_warn("tried to create Proc object without a block");
- }
-
- if (!proc && ruby_block->block_obj) {
- VALUE obj = ruby_block->block_obj;
- if (CLASS_OF(obj) != klass) {
- obj = proc_clone(obj);
- RBASIC(obj)->klass = klass;
- }
- return obj;
- }
- block = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
- *data = *ruby_block;
-
- data->orig_thread = rb_thread_current();
- data->wrapper = ruby_wrapper;
- data->iter = data->prev?Qtrue:Qfalse;
- data->block_obj = block;
- frame_dup(&data->frame);
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
-
- for (p = data; p; p = p->prev) {
- for (vars = p->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- }
- scope_dup(data->scope);
- proc_save_safe_level(block);
- if (proc) {
- data->flags |= BLOCK_LAMBDA;
- }
- else {
- ruby_block->block_obj = block;
- }
-
- return block;
-}
-
-/*
- * call-seq:
- * Proc.new {|...| block } => a_proc
- * Proc.new => a_proc
- *
- * Creates a new <code>Proc</code> object, bound to the current
- * context. <code>Proc::new</code> may be called without a block only
- * within a method with an attached block, in which case that block is
- * converted to the <code>Proc</code> object.
- *
- * def proc_from
- * Proc.new
- * end
- * proc = proc_from { "hello" }
- * proc.call #=> "hello"
- */
-
-static VALUE
-proc_s_new(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE block = proc_alloc(klass, Qfalse);
-
- rb_obj_call_init(block, argc, argv);
- return block;
-}
-
-/*
- * call-seq:
- * proc { |...| block } => a_proc
- *
- * Equivalent to <code>Proc.new</code>.
- */
-
-VALUE
-rb_block_proc()
-{
- return proc_alloc(rb_cProc, Qfalse);
-}
-
-VALUE
-rb_f_lambda()
-{
- rb_warn("rb_f_lambda() is deprecated; use rb_block_proc() instead");
- return proc_alloc(rb_cProc, Qtrue);
-}
-
-/*
- * call-seq:
- * lambda { |...| block } => a_proc
- *
- * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
- * check the number of parameters passed when called.
- */
-
-static VALUE
-proc_lambda()
-{
- return proc_alloc(rb_cProc, Qtrue);
-}
-
-static int
-block_orphan(data)
- struct BLOCK *data;
-{
- if (data->scope->flags & SCOPE_NOSTACK) {
- return 1;
- }
- if (data->orig_thread != rb_thread_current()) {
- return 1;
- }
- return 0;
-}
-
-static VALUE
-proc_invoke(proc, args, self, klass)
- VALUE proc, args; /* OK */
- VALUE self, klass;
-{
- struct BLOCK * volatile old_block;
- struct BLOCK _block;
- struct BLOCK *data;
- volatile VALUE result = Qundef;
- int state;
- volatile int safe = ruby_safe_level;
- volatile VALUE old_wrapper = ruby_wrapper;
- volatile int pcall, avalue = Qtrue;
- VALUE bvar = Qnil, tmp = args;
-
- Data_Get_Struct(proc, struct BLOCK, data);
- pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
- if (!pcall && RARRAY(args)->len == 1) {
- avalue = Qfalse;
- args = RARRAY(args)->ptr[0];
- }
- if (rb_block_given_p() && ruby_frame->callee) {
- if (klass != ruby_frame->this_class)
- klass = rb_obj_class(proc);
- bvar = rb_block_proc();
- }
-
- PUSH_VARS();
- ruby_wrapper = data->wrapper;
- ruby_dyna_vars = data->dyna_vars;
- /* PUSH BLOCK from data */
- old_block = ruby_block;
- _block = *data;
- _block.block_obj = bvar;
- if (self != Qundef) _block.frame.self = self;
- if (klass) _block.frame.this_class = klass;
- _block.frame.argc = RARRAY(tmp)->len;
- if (_block.frame.argc && (ruby_frame->flags & FRAME_DMETH)) {
- NEWOBJ(scope, struct SCOPE);
- OBJSETUP(scope, tmp, T_SCOPE);
- scope->local_tbl = _block.scope->local_tbl;
- scope->local_vars = _block.scope->local_vars;
- _block.scope = scope;
- }
- ruby_block = &_block;
-
- PUSH_ITER(ITER_CUR);
- ruby_frame->iter = ITER_CUR;
- PUSH_TAG((pcall&YIELD_LAMBDA_CALL) ? PROT_LAMBDA : PROT_NONE);
- state = EXEC_TAG();
- if (state == 0) {
- proc_set_safe_level(proc);
- result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0,
- pcall | YIELD_PROC_CALL, avalue);
- }
- else if (TAG_DST()) {
- result = prot_tag->retval;
- }
- POP_TAG();
- POP_ITER();
- ruby_block = old_block;
- ruby_wrapper = old_wrapper;
- POP_VARS();
- if (proc_safe_level_p(proc)) ruby_safe_level = safe;
-
- switch (state) {
- case 0:
- break;
- case TAG_RETRY:
- proc_jump_error(TAG_RETRY, Qnil); /* xxx */
- JUMP_TAG(state);
- break;
- case TAG_BREAK:
- if (!pcall && result != Qundef) {
- proc_jump_error(state, result);
- }
- case TAG_RETURN:
- if (result != Qundef) {
- if (pcall) break;
- return_jump(result);
- }
- default:
- JUMP_TAG(state);
- }
- return result;
-}
-
-/* CHECKME: are the argument checking semantics correct? */
-
-/*
- * call-seq:
- * prc.call(params,...) => obj
- * prc[params,...] => obj
- *
- * Invokes the block, setting the block's parameters to the values in
- * <i>params</i> using something close to method calling semantics.
- * Generates a warning if multiple values are passed to a proc that
- * expects just one (previously this silently converted the parameters
- * to an array).
- *
- * For procs created using <code>Kernel.proc</code>, generates an
- * error if the wrong number of parameters
- * are passed to a proc with multiple parameters. For procs created using
- * <code>Proc.new</code>, extra parameters are silently discarded.
- *
- * Returns the value of the last expression evaluated in the block. See
- * also <code>Proc#yield</code>.
- *
- * a_proc = Proc.new {|a, *b| b.collect {|i| i*a }}
- * a_proc.call(9, 1, 2, 3) #=> [9, 18, 27]
- * a_proc[9, 1, 2, 3] #=> [9, 18, 27]
- * a_proc = Proc.new {|a,b| a}
- * a_proc.call(1,2,3)
- *
- * <em>produces:</em>
- *
- * prog.rb:5: wrong number of arguments (3 for 2) (ArgumentError)
- * from prog.rb:4:in `call'
- * from prog.rb:5
- */
-
-static VALUE
-proc_call(proc, args)
- VALUE proc, args; /* OK */
-{
- return proc_invoke(proc, args, Qundef, 0);
-}
-
-int
-rb_proc_arity(proc)
- VALUE proc;
-{
- struct BLOCK *data;
- NODE *var, *list;
- int n;
-
- Data_Get_Struct(proc, struct BLOCK, data);
- var = data->var;
- if (var == 0) {
- if (data->body && nd_type(data->body) == NODE_IFUNC &&
- data->body->nd_cfnc == bmcall) {
- return method_arity(data->body->nd_tval);
- }
- return 0;
- }
- if (var == (NODE*)1) return 0;
- if (var == (NODE*)2) return 0;
- if (nd_type(var) == NODE_BLOCK_ARG) {
- var = var->nd_args;
- if (var == (NODE*)1) return 0;
- if (var == (NODE*)2) return 0;
- }
- switch (nd_type(var)) {
- default:
- return 1;
- case NODE_MASGN:
- list = var->nd_head;
- n = 0;
- while (list) {
- n++;
- list = list->nd_next;
- }
- if (var->nd_args) return -n-1;
- return n;
- }
-}
-
-/*
- * call-seq:
- * prc.arity -> fixnum
- *
- * Returns the number of arguments that would not be ignored. If the block
- * is declared to take no arguments, returns 0. If the block is known
- * to take exactly n arguments, returns n. If the block has optional
- * arguments, return -n-1, where n is the number of mandatory
- * arguments. A <code>proc</code> with no argument declarations
- * is the same a block declaring <code>||</code> as its arguments.
- *
- * Proc.new {}.arity #=> 0
- * Proc.new {||}.arity #=> 0
- * Proc.new {|a|}.arity #=> 1
- * Proc.new {|a,b|}.arity #=> 2
- * Proc.new {|a,b,c|}.arity #=> 3
- * Proc.new {|*a|}.arity #=> -1
- * Proc.new {|a,*b|}.arity #=> -2
- */
-
-static VALUE
-proc_arity(proc)
- VALUE proc;
-{
- int arity = rb_proc_arity(proc);
- return INT2FIX(arity);
-}
-
-/*
- * call-seq:
- * prc == other_proc => true or false
- *
- * Return <code>true</code> if <i>prc</i> is the same object as
- * <i>other_proc</i>, or if they are both procs with the same body.
- */
-
-static VALUE
-proc_eq(self, other)
- VALUE self, other;
-{
- struct BLOCK *data, *data2;
-
- if (self == other) return Qtrue;
- if (TYPE(other) != T_DATA) return Qfalse;
- if (RDATA(other)->dmark != (RUBY_DATA_FUNC)blk_mark) return Qfalse;
- if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse;
- Data_Get_Struct(self, struct BLOCK, data);
- Data_Get_Struct(other, struct BLOCK, data2);
- if (data->body != data2->body) return Qfalse;
- if (data->var != data2->var) return Qfalse;
- if (data->scope != data2->scope) return Qfalse;
- if (data->dyna_vars != data2->dyna_vars) return Qfalse;
- if (data->flags != data2->flags) return Qfalse;
-
- return Qtrue;
-}
-
-/*
- * call-seq:
- * prc.hash => integer
- *
- * Return hash value corresponding to proc body.
- */
-
-static VALUE
-proc_hash(self)
- VALUE self;
-{
- struct BLOCK *data;
- long hash;
-
- Data_Get_Struct(self, struct BLOCK, data);
- hash = (long)data->body;
- hash ^= (long)data->var;
- hash ^= data->frame.uniq << 16;
- hash ^= data->flags;
-
- return INT2FIX(hash);
-}
-
-/*
- * call-seq:
- * prc.to_s => string
- *
- * Shows the unique identifier for this proc, along with
- * an indication of where the proc was defined.
- */
-
-static VALUE
-proc_to_s(self)
- VALUE self;
-{
- struct BLOCK *data;
- NODE *node;
- char *cname = rb_obj_classname(self);
- const int w = (SIZEOF_LONG * CHAR_BIT) / 4;
- long len = strlen(cname)+6+w; /* 6:tags 16:addr */
- VALUE str;
-
- Data_Get_Struct(self, struct BLOCK, data);
- if ((node = data->frame.node) || (node = data->body)) {
- len += strlen(node->nd_file) + 2 + (SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3;
- str = rb_str_new(0, len);
- sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx@%s:%d>", cname, w, (VALUE)data->body,
- node->nd_file, nd_line(node));
- }
- else {
- str = rb_str_new(0, len);
- sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx>", cname, w, (VALUE)data->body);
- }
- RSTRING(str)->len = strlen(RSTRING(str)->ptr);
- if (OBJ_TAINTED(self)) OBJ_TAINT(str);
-
- return str;
-}
-
-/*
- * call-seq:
- * prc.to_proc -> prc
- *
- * Part of the protocol for converting objects to <code>Proc</code>
- * objects. Instances of class <code>Proc</code> simply return
- * themselves.
- */
-
-static VALUE
-proc_to_self(self)
- VALUE self;
-{
- return self;
-}
-
-/*
- * call-seq:
- * prc.binding => binding
- *
- * Returns the binding associated with <i>prc</i>. Note that
- * <code>Kernel#eval</code> accepts either a <code>Proc</code> or a
- * <code>Binding</code> object as its second parameter.
- *
- * def fred(param)
- * proc {}
- * end
- *
- * b = fred(99)
- * eval("param", b.binding) #=> 99
- * eval("param", b) #=> 99
- */
-
-static VALUE
-proc_binding(proc)
- VALUE proc;
-{
- struct BLOCK *orig, *data;
- VALUE bind;
-
- Data_Get_Struct(proc, struct BLOCK, orig);
- bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
- MEMCPY(data, orig, struct BLOCK, 1);
- frame_dup(&data->frame);
-
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
-
- return bind;
-}
-
-static VALUE
-rb_block_pass(func, arg, proc)
- VALUE (*func) _((VALUE));
- VALUE arg;
- VALUE proc;
-{
- VALUE b;
- struct BLOCK * volatile old_block;
- struct BLOCK _block;
- struct BLOCK *data;
- volatile VALUE result = Qnil;
- int state;
- volatile int orphan;
- volatile int safe = ruby_safe_level;
-
- if (NIL_P(proc)) {
- PUSH_ITER(ITER_NOT);
- result = (*func)(arg);
- POP_ITER();
- return result;
- }
- if (!rb_obj_is_proc(proc)) {
- b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
- if (!rb_obj_is_proc(b)) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)",
- rb_obj_classname(proc));
- }
- proc = b;
- }
-
- if (ruby_safe_level >= 1 && OBJ_TAINTED(proc)) {
- if (ruby_safe_level > proc_get_safe_level(proc)) {
- rb_raise(rb_eSecurityError, "Insecure: tainted block value");
- }
- }
-
- if (ruby_block && ruby_block->block_obj == proc) {
- PUSH_ITER(ITER_PRE);
- result = (*func)(arg);
- POP_ITER();
- return result;
- }
-
- Data_Get_Struct(proc, struct BLOCK, data);
- orphan = block_orphan(data);
-
- /* PUSH BLOCK from data */
- _block = *data;
- _block.outer = ruby_block;
- if (orphan) _block.uniq = block_unique++;
- ruby_block = &_block;
- PUSH_ITER(ITER_PRE);
- if (ruby_frame->iter == ITER_NOT)
- ruby_frame->iter = ITER_PRE;
-
- PUSH_TAG(PROT_LOOP);
- state = EXEC_TAG();
- if (state == 0) {
- retry:
- proc_set_safe_level(proc);
- if (safe > ruby_safe_level)
- ruby_safe_level = safe;
- result = (*func)(arg);
- }
- else if (state == TAG_BREAK && TAG_DST()) {
- result = prot_tag->retval;
- state = 0;
- }
- else if (state == TAG_RETRY) {
- state = 0;
- goto retry;
- }
- POP_TAG();
- POP_ITER();
- ruby_block = _block.outer;
- if (proc_safe_level_p(proc)) ruby_safe_level = safe;
-
- switch (state) {/* escape from orphan block */
- case 0:
- break;
- case TAG_RETURN:
- if (orphan) {
- proc_jump_error(state, prot_tag->retval);
- }
- default:
- JUMP_TAG(state);
- }
-
- return result;
-}
-
-struct block_arg {
- VALUE self;
- NODE *iter;
-};
-
-static VALUE
-call_block(arg)
- struct block_arg *arg;
-{
- return rb_eval(arg->self, arg->iter);
-}
-
-static VALUE
-block_pass(self, node)
- VALUE self;
- NODE *node;
-{
- struct block_arg arg;
- arg.self = self;
- arg.iter = node->nd_iter;
- return rb_block_pass((VALUE (*)_((VALUE)))call_block,
- (VALUE)&arg, rb_eval(self, node->nd_body));
-}
-
-struct METHOD {
- VALUE klass, rklass;
- VALUE recv;
- ID id, oid;
- NODE *body;
-};
-
-static void
-bm_mark(data)
- struct METHOD *data;
-{
- rb_gc_mark(data->rklass);
- rb_gc_mark(data->klass);
- rb_gc_mark(data->recv);
- rb_gc_mark((VALUE)data->body);
-}
-
-static VALUE
-mnew(klass, obj, id, mklass)
- VALUE klass, obj, mklass;
- ID id;
-{
- VALUE method;
- NODE *body;
- int noex;
- struct METHOD *data;
- VALUE rklass = klass;
- ID oid = id;
-
- again:
- if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
- print_undef(rklass, oid);
- }
-
- if (nd_type(body) == NODE_ZSUPER) {
- klass = RCLASS(klass)->super;
- goto again;
- }
-
- while (rklass != klass &&
- (FL_TEST(rklass, FL_SINGLETON) || TYPE(rklass) == T_ICLASS)) {
- rklass = RCLASS(rklass)->super;
- }
- if (TYPE(klass) == T_ICLASS) klass = RBASIC(klass)->klass;
- method = Data_Make_Struct(mklass, struct METHOD, bm_mark, -1, data);
- data->klass = klass;
- data->recv = obj;
- data->id = id;
- data->body = body;
- data->rklass = rklass;
- data->oid = oid;
- OBJ_INFECT(method, klass);
-
- return method;
-}
-
-
-/**********************************************************************
- *
- * Document-class : Method
- *
- * Method objects are created by <code>Object#method</code>, and are
- * associated with a particular object (not just with a class). They
- * may be used to invoke the method within the object, and as a block
- * associated with an iterator. They may also be unbound from one
- * object (creating an <code>UnboundMethod</code>) and bound to
- * another.
- *
- * class Thing
- * def square(n)
- * n*n
- * end
- * end
- * thing = Thing.new
- * meth = thing.method(:square)
- *
- * meth.call(9) #=> 81
- * [ 1, 2, 3 ].collect(&meth) #=> [1, 4, 9]
- *
- */
-
-/*
- * call-seq:
- * meth == other_meth => true or false
- *
- * Two method objects are equal if that are bound to the same
- * object and contain the same body.
- */
-
-
-static VALUE
-method_eq(method, other)
- VALUE method, other;
-{
- struct METHOD *m1, *m2;
-
- if (TYPE(other) != T_DATA || RDATA(other)->dmark != (RUBY_DATA_FUNC)bm_mark)
- return Qfalse;
- if (CLASS_OF(method) != CLASS_OF(other))
- return Qfalse;
-
- Data_Get_Struct(method, struct METHOD, m1);
- Data_Get_Struct(other, struct METHOD, m2);
-
- if (m1->klass != m2->klass || m1->rklass != m2->rklass ||
- m1->recv != m2->recv || m1->body != m2->body)
- return Qfalse;
-
- return Qtrue;
-}
-
-/*
- * call-seq:
- * meth.hash => integer
- *
- * Return a hash value corresponding to the method object.
- */
-
-static VALUE
-method_hash(method)
- VALUE method;
-{
- struct METHOD *m;
- long hash;
-
- Data_Get_Struct(method, struct METHOD, m);
- hash = (long)m->klass;
- hash ^= (long)m->rklass;
- hash ^= (long)m->recv;
- hash ^= (long)m->body;
-
- return INT2FIX(hash);
-}
-
-/*
- * call-seq:
- * meth.unbind => unbound_method
- *
- * Dissociates <i>meth</i> from it's current receiver. The resulting
- * <code>UnboundMethod</code> can subsequently be bound to a new object
- * of the same class (see <code>UnboundMethod</code>).
- */
-
-static VALUE
-method_unbind(obj)
- VALUE obj;
-{
- VALUE method;
- struct METHOD *orig, *data;
-
- Data_Get_Struct(obj, struct METHOD, orig);
- method = Data_Make_Struct(rb_cUnboundMethod, struct METHOD, bm_mark, free, data);
- data->klass = orig->klass;
- data->recv = Qundef;
- data->id = orig->id;
- data->body = orig->body;
- data->rklass = orig->rklass;
- data->oid = orig->oid;
- OBJ_INFECT(method, obj);
-
- return method;
-}
-
-/*
- * call-seq:
- * obj.method(sym) => method
- *
- * Looks up the named method as a receiver in <i>obj</i>, returning a
- * <code>Method</code> object (or raising <code>NameError</code>). The
- * <code>Method</code> object acts as a closure in <i>obj</i>'s object
- * instance, so instance variables and the value of <code>self</code>
- * remain available.
- *
- * class Demo
- * def initialize(n)
- * @iv = n
- * end
- * def hello()
- * "Hello, @iv = #{@iv}"
- * end
- * end
- *
- * k = Demo.new(99)
- * m = k.method(:hello)
- * m.call #=> "Hello, @iv = 99"
- *
- * l = Demo.new('Fred')
- * m = l.method("hello")
- * m.call #=> "Hello, @iv = Fred"
- */
-
-static VALUE
-rb_obj_method(obj, vid)
- VALUE obj;
- VALUE vid;
-{
- return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod);
-}
-
-/*
- * call-seq:
- * mod.instance_method(symbol) => unbound_method
- *
- * Returns an +UnboundMethod+ representing the given
- * instance method in _mod_.
- *
- * class Interpreter
- * def do_a() print "there, "; end
- * def do_d() print "Hello "; end
- * def do_e() print "!\n"; end
- * def do_v() print "Dave"; end
- * Dispatcher = {
- * ?a => instance_method(:do_a),
- * ?d => instance_method(:do_d),
- * ?e => instance_method(:do_e),
- * ?v => instance_method(:do_v)
- * }
- * def interpret(string)
- * string.each_byte {|b| Dispatcher[b].bind(self).call }
- * end
- * end
- *
- *
- * interpreter = Interpreter.new
- * interpreter.interpret('dave')
- *
- * <em>produces:</em>
- *
- * Hello there, Dave!
- */
-
-static VALUE
-rb_mod_method(mod, vid)
- VALUE mod;
- VALUE vid;
-{
- return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod);
-}
-
-/*
- * MISSING: documentation
- */
-
-static VALUE
-method_clone(self)
- VALUE self;
-{
- VALUE clone;
- struct METHOD *orig, *data;
-
- Data_Get_Struct(self, struct METHOD, orig);
- clone = Data_Make_Struct(CLASS_OF(self),struct METHOD, bm_mark, free, data);
- CLONESETUP(clone, self);
- *data = *orig;
-
- return clone;
-}
-
-/*
- * call-seq:
- * meth.call(args, ...) => obj
- * meth[args, ...] => obj
- *
- * Invokes the <i>meth</i> with the specified arguments, returning the
- * method's return value.
- *
- * m = 12.method("+")
- * m.call(3) #=> 15
- * m.call(20) #=> 32
- */
-
-static VALUE
-method_call(argc, argv, method)
- int argc;
- VALUE *argv;
- VALUE method;
-{
- VALUE result = Qnil; /* OK */
- struct METHOD *data;
- int state;
- volatile int safe = -1;
-
- Data_Get_Struct(method, struct METHOD, data);
- if (data->recv == Qundef) {
- rb_raise(rb_eTypeError, "can't call unbound method; bind first");
- }
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- PUSH_TAG(PROT_NONE);
- if (OBJ_TAINTED(method)) {
- safe = ruby_safe_level;
- if (ruby_safe_level < 4) ruby_safe_level = 4;
- }
- if ((state = EXEC_TAG()) == 0) {
- result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,0);
- }
- POP_TAG();
- POP_ITER();
- if (safe >= 0) ruby_safe_level = safe;
- if (state) JUMP_TAG(state);
- return result;
-}
-
-/**********************************************************************
- *
- * Document-class: UnboundMethod
- *
- * Ruby supports two forms of objectified methods. Class
- * <code>Method</code> is used to represent methods that are associated
- * with a particular object: these method objects are bound to that
- * object. Bound method objects for an object can be created using
- * <code>Object#method</code>.
- *
- * Ruby also supports unbound methods; methods objects that are not
- * associated with a particular object. These can be created either by
- * calling <code>Module#instance_method</code> or by calling
- * <code>unbind</code> on a bound method object. The result of both of
- * these is an <code>UnboundMethod</code> object.
- *
- * Unbound methods can only be called after they are bound to an
- * object. That object must be be a kind_of? the method's original
- * class.
- *
- * class Square
- * def area
- * @side * @side
- * end
- * def initialize(side)
- * @side = side
- * end
- * end
- *
- * area_un = Square.instance_method(:area)
- *
- * s = Square.new(12)
- * area = area_un.bind(s)
- * area.call #=> 144
- *
- * Unbound methods are a reference to the method at the time it was
- * objectified: subsequent changes to the underlying class will not
- * affect the unbound method.
- *
- * class Test
- * def test
- * :original
- * end
- * end
- * um = Test.instance_method(:test)
- * class Test
- * def test
- * :modified
- * end
- * end
- * t = Test.new
- * t.test #=> :modified
- * um.bind(t).call #=> :original
- *
- */
-
-/*
- * call-seq:
- * umeth.bind(obj) -> method
- *
- * Bind <i>umeth</i> to <i>obj</i>. If <code>Klass</code> was the class
- * from which <i>umeth</i> was obtained,
- * <code>obj.kind_of?(Klass)</code> must be true.
- *
- * class A
- * def test
- * puts "In test, class = #{self.class}"
- * end
- * end
- * class B < A
- * end
- * class C < B
- * end
- *
- *
- * um = B.instance_method(:test)
- * bm = um.bind(C.new)
- * bm.call
- * bm = um.bind(B.new)
- * bm.call
- * bm = um.bind(A.new)
- * bm.call
- *
- * <em>produces:</em>
- *
- * In test, class = C
- * In test, class = B
- * prog.rb:16:in `bind': bind argument must be an instance of B (TypeError)
- * from prog.rb:16
- */
-
-static VALUE
-umethod_bind(method, recv)
- VALUE method, recv;
-{
- struct METHOD *data, *bound;
-
- Data_Get_Struct(method, struct METHOD, data);
- if (data->rklass != CLASS_OF(recv)) {
- if (FL_TEST(data->rklass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "singleton method called for a different object");
- }
- if(!rb_obj_is_kind_of(recv, data->rklass)) {
- rb_raise(rb_eTypeError, "bind argument must be an instance of %s",
- rb_class2name(data->rklass));
- }
- }
-
- method = Data_Make_Struct(rb_cMethod,struct METHOD,bm_mark,free,bound);
- *bound = *data;
- bound->recv = recv;
- bound->rklass = CLASS_OF(recv);
-
- return method;
-}
-
-int
-rb_node_arity(body)
- NODE *body;
-{
- int n;
-
- switch (nd_type(body)) {
- case NODE_CFUNC:
- if (body->nd_argc < 0) return -1;
- return body->nd_argc;
- case NODE_ZSUPER:
- return -1;
- case NODE_ATTRSET:
- return 1;
- case NODE_IVAR:
- return 0;
- case NODE_BMETHOD:
- return rb_proc_arity(body->nd_cval);
- case NODE_SCOPE:
- body = body->nd_next; /* skip NODE_SCOPE */
- if (nd_type(body) == NODE_BLOCK)
- body = body->nd_head;
- if (!body) return 0;
- n = body->nd_cnt;
- if (body->nd_opt || body->nd_rest != -1)
- n = -n-1;
- return n;
- default:
- rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
- }
-}
-
-/*
- * call-seq:
- * meth.arity => fixnum
- *
- * Returns an indication of the number of arguments accepted by a
- * method. Returns a nonnegative integer for methods that take a fixed
- * number of arguments. For Ruby methods that take a variable number of
- * arguments, returns -n-1, where n is the number of required
- * arguments. For methods written in C, returns -1 if the call takes a
- * variable number of arguments.
- *
- * class C
- * def one; end
- * def two(a); end
- * def three(*a); end
- * def four(a, b); end
- * def five(a, b, *c); end
- * def six(a, b, *c, &d); end
- * end
- * c = C.new
- * c.method(:one).arity #=> 0
- * c.method(:two).arity #=> 1
- * c.method(:three).arity #=> -1
- * c.method(:four).arity #=> 2
- * c.method(:five).arity #=> -3
- * c.method(:six).arity #=> -3
- *
- * "cat".method(:size).arity #=> 0
- * "cat".method(:replace).arity #=> 1
- * "cat".method(:squeeze).arity #=> -1
- * "cat".method(:count).arity #=> -1
- */
-
-static VALUE
-method_arity_m(method)
- VALUE method;
-{
- int n = method_arity(method);
- return INT2FIX(n);
-}
-
-static int
-method_arity(method)
- VALUE method;
-{
- struct METHOD *data;
-
- Data_Get_Struct(method, struct METHOD, data);
- return rb_node_arity(data->body);
-}
-
-int
-rb_mod_method_arity(mod, id)
- VALUE mod;
- ID id;
-{
- NODE *node = rb_method_node(mod, id);
- return rb_node_arity(node);
-}
-
-int
-rb_obj_method_arity(obj, id)
- VALUE obj;
- ID id;
-{
- return rb_mod_method_arity(CLASS_OF(obj), id);
-}
-
-/*
- * call-seq:
- * meth.to_s => string
- * meth.inspect => string
- *
- * Show the name of the underlying method.
- *
- * "cat".method(:count).inspect #=> "#<Method: String#count>"
- */
-
-static VALUE
-method_inspect(method)
- VALUE method;
-{
- struct METHOD *data;
- VALUE str;
- const char *s;
- char *sharp = "#";
-
- Data_Get_Struct(method, struct METHOD, data);
- str = rb_str_buf_new2("#<");
- s = rb_obj_classname(method);
- rb_str_buf_cat2(str, s);
- rb_str_buf_cat2(str, ": ");
-
- if (FL_TEST(data->klass, FL_SINGLETON)) {
- VALUE v = rb_iv_get(data->klass, "__attached__");
-
- if (data->recv == Qundef) {
- rb_str_buf_append(str, rb_inspect(data->klass));
- }
- else if (data->recv == v) {
- rb_str_buf_append(str, rb_inspect(v));
- sharp = ".";
- }
- else {
- rb_str_buf_append(str, rb_inspect(data->recv));
- rb_str_buf_cat2(str, "(");
- rb_str_buf_append(str, rb_inspect(v));
- rb_str_buf_cat2(str, ")");
- sharp = ".";
- }
- }
- else {
- rb_str_buf_cat2(str, rb_class2name(data->rklass));
- if (data->rklass != data->klass) {
- rb_str_buf_cat2(str, "(");
- rb_str_buf_cat2(str, rb_class2name(data->klass));
- rb_str_buf_cat2(str, ")");
- }
- }
- rb_str_buf_cat2(str, sharp);
- rb_str_buf_cat2(str, rb_id2name(data->oid));
- rb_str_buf_cat2(str, ">");
-
- return str;
-}
-
-static VALUE
-mproc(method)
- VALUE method;
-{
- VALUE proc;
-
- /* emulate ruby's method call */
- PUSH_ITER(ITER_CUR);
- PUSH_FRAME();
- proc = rb_block_proc();
- POP_FRAME();
- POP_ITER();
-
- return proc;
-}
-
-static VALUE
-bmcall(args, method)
- VALUE args, method;
-{
- volatile VALUE a;
-
- a = svalue_to_avalue(args);
- return method_call(RARRAY(a)->len, RARRAY(a)->ptr, method);
-}
-
-VALUE
-rb_proc_new(func, val)
- VALUE (*func)(ANYARGS); /* VALUE yieldarg[, VALUE procarg] */
- VALUE val;
-{
- struct BLOCK *data;
- VALUE proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, func, val);
-
- Data_Get_Struct(proc, struct BLOCK, data);
- data->body->nd_state = YIELD_FUNC_AVALUE;
- return proc;
-}
-
-/*
- * call-seq:
- * meth.to_proc => prc
- *
- * Returns a <code>Proc</code> object corresponding to this method.
- */
-
-static VALUE
-method_proc(method)
- VALUE method;
-{
- VALUE proc;
- struct METHOD *mdata;
- struct BLOCK *bdata;
-
- Data_Get_Struct(method, struct METHOD, mdata);
- if (nd_type(mdata->body) == NODE_BMETHOD) {
- return mdata->body->nd_cval;
- }
- proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, bmcall, method);
- Data_Get_Struct(proc, struct BLOCK, bdata);
- bdata->body->nd_file = mdata->body->nd_file;
- nd_set_line(bdata->body, nd_line(mdata->body));
- bdata->body->nd_state = YIELD_FUNC_SVALUE;
- bdata->flags |= BLOCK_FROM_METHOD;
-
- return proc;
-}
-
-static VALUE
-rb_obj_is_method(m)
- VALUE m;
-{
- if (TYPE(m) == T_DATA && RDATA(m)->dmark == (RUBY_DATA_FUNC)bm_mark) {
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * define_method(symbol, method) => new_method
- * define_method(symbol) { block } => proc
- *
- * Defines an instance method in the receiver. The _method_
- * parameter can be a +Proc+ or +Method+ object.
- * If a block is specified, it is used as the method body. This block
- * is evaluated using <code>instance_eval</code>, a point that is
- * tricky to demonstrate because <code>define_method</code> is private.
- * (This is why we resort to the +send+ hack in this example.)
- *
- * class A
- * def fred
- * puts "In Fred"
- * end
- * def create_method(name, &block)
- * self.class.send(:define_method, name, &block)
- * end
- * define_method(:wilma) { puts "Charge it!" }
- * end
- * class B < A
- * define_method(:barney, instance_method(:fred))
- * end
- * a = B.new
- * a.barney
- * a.wilma
- * a.create_method(:betty) { p self }
- * a.betty
- *
- * <em>produces:</em>
- *
- * In Fred
- * Charge it!
- * #<B:0x401b39e8>
- */
-
-static VALUE
-rb_mod_define_method(argc, argv, mod)
- int argc;
- VALUE *argv;
- VALUE mod;
-{
- ID id;
- VALUE body;
- NODE *node;
- int noex;
-
- if (argc == 1) {
- id = rb_to_id(argv[0]);
- body = proc_lambda();
- }
- else if (argc == 2) {
- id = rb_to_id(argv[0]);
- body = argv[1];
- if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Method)",
- rb_obj_classname(body));
- }
- }
- else {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
- }
- if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) {
- struct METHOD *method = (struct METHOD *)DATA_PTR(body);
- VALUE rklass = method->rklass;
- if (rklass != mod) {
- if (FL_TEST(rklass, FL_SINGLETON)) {
- rb_raise(rb_eTypeError, "can't bind singleton method to a different class");
- }
- if (!RTEST(rb_class_inherited_p(mod, rklass))) {
- rb_raise(rb_eTypeError, "bind argument must be a subclass of %s",
- rb_class2name(rklass));
- }
- }
- node = method->body;
- }
- else if (RDATA(body)->dmark == (RUBY_DATA_FUNC)blk_mark) {
- struct BLOCK *block;
-
- body = proc_clone(body);
- RBASIC(body)->flags |= PROC_NOSAFE;
- Data_Get_Struct(body, struct BLOCK, block);
- block->frame.callee = id;
- block->frame.this_func = id;
- block->frame.this_class = mod;
- node = NEW_BMETHOD(body);
- }
- else {
- /* type error */
- rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
- }
-
- if (SCOPE_TEST(SCOPE_PRIVATE)) {
- noex = NOEX_PRIVATE;
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
- }
- rb_add_method(mod, id, node, noex);
- return body;
-}
-
-/*
- * <code>Proc</code> objects are blocks of code that have been bound to
- * a set of local variables. Once bound, the code may be called in
- * different contexts and still access those variables.
- *
- * def gen_times(factor)
- * return Proc.new {|n| n*factor }
- * end
- *
- * times3 = gen_times(3)
- * times5 = gen_times(5)
- *
- * times3.call(12) #=> 36
- * times5.call(5) #=> 25
- * times3.call(times5.call(4)) #=> 60
- *
- */
-
-void
-Init_Proc()
-{
- rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
- rb_define_method(rb_eLocalJumpError, "exit_value", localjump_xvalue, 0);
- rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0);
-
- exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
- rb_global_variable(&exception_error);
-
- rb_eSysStackError = rb_define_class("SystemStackError", rb_eException);
- sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep");
- OBJ_TAINT(sysstack_error);
- rb_global_variable(&sysstack_error);
-
- rb_cProc = rb_define_class("Proc", rb_cObject);
- rb_undef_alloc_func(rb_cProc);
- rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1);
-
- rb_define_method(rb_cProc, "clone", proc_clone, 0);
- rb_define_method(rb_cProc, "dup", proc_dup, 0);
- rb_define_method(rb_cProc, "call", proc_call, -2);
- rb_define_method(rb_cProc, "arity", proc_arity, 0);
- rb_define_method(rb_cProc, "[]", proc_call, -2);
- rb_define_method(rb_cProc, "==", proc_eq, 1);
- rb_define_method(rb_cProc, "eql?", proc_eq, 1);
- rb_define_method(rb_cProc, "hash", proc_hash, 0);
- rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
- rb_define_method(rb_cProc, "to_proc", proc_to_self, 0);
- rb_define_method(rb_cProc, "binding", proc_binding, 0);
-
- rb_define_global_function("proc", rb_block_proc, 0);
- rb_define_global_function("lambda", proc_lambda, 0);
-
- rb_cMethod = rb_define_class("Method", rb_cObject);
- rb_undef_alloc_func(rb_cMethod);
- rb_undef_method(CLASS_OF(rb_cMethod), "new");
- rb_define_method(rb_cMethod, "==", method_eq, 1);
- rb_define_method(rb_cMethod, "eql?", method_eq, 1);
- rb_define_method(rb_cMethod, "hash", method_hash, 0);
- rb_define_method(rb_cMethod, "clone", method_clone, 0);
- rb_define_method(rb_cMethod, "call", method_call, -1);
- rb_define_method(rb_cMethod, "[]", method_call, -1);
- rb_define_method(rb_cMethod, "arity", method_arity_m, 0);
- rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
- rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
- rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
- rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
- rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
-
- rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject);
- rb_undef_alloc_func(rb_cUnboundMethod);
- rb_undef_method(CLASS_OF(rb_cUnboundMethod), "new");
- rb_define_method(rb_cUnboundMethod, "==", method_eq, 1);
- rb_define_method(rb_cUnboundMethod, "eql?", method_eq, 1);
- rb_define_method(rb_cUnboundMethod, "hash", method_hash, 0);
- rb_define_method(rb_cUnboundMethod, "clone", method_clone, 0);
- rb_define_method(rb_cUnboundMethod, "arity", method_arity_m, 0);
- rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
- rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
- rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
- rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1);
-}
-
-/*
- * Objects of class <code>Binding</code> encapsulate the execution
- * context at some particular place in the code and retain this context
- * for future use. The variables, methods, value of <code>self</code>,
- * and possibly an iterator block that can be accessed in this context
- * are all retained. Binding objects can be created using
- * <code>Kernel#binding</code>, and are made available to the callback
- * of <code>Kernel#set_trace_func</code>.
- *
- * These binding objects can be passed as the second argument of the
- * <code>Kernel#eval</code> method, establishing an environment for the
- * evaluation.
- *
- * class Demo
- * def initialize(n)
- * @secret = n
- * end
- * def getBinding
- * return binding()
- * end
- * end
- *
- * k1 = Demo.new(99)
- * b1 = k1.getBinding
- * k2 = Demo.new(-3)
- * b2 = k2.getBinding
- *
- * eval("@secret", b1) #=> 99
- * eval("@secret", b2) #=> -3
- * eval("@secret") #=> nil
- *
- * Binding objects have no class-specific methods.
- *
- */
-
-void
-Init_Binding()
-{
- rb_cBinding = rb_define_class("Binding", rb_cObject);
- rb_undef_alloc_func(rb_cBinding);
- rb_undef_method(CLASS_OF(rb_cBinding), "new");
- rb_define_method(rb_cBinding, "clone", proc_clone, 0);
- rb_define_method(rb_cBinding, "eval", bind_eval, -1);
- rb_define_global_function("binding", rb_f_binding, 0);
-}
-
-#ifdef __ia64__
-#if defined(__FreeBSD__)
-/*
- * FreeBSD/ia64 currently does not have a way for a process to get the
- * base address for the RSE backing store, so hardcode it.
- */
-#define __libc_ia64_register_backing_store_base (4ULL<<61)
-#else
-#ifdef HAVE_UNWIND_H
-#include <unwind.h>
-#else
-#pragma weak __libc_ia64_register_backing_store_base
-extern unsigned long __libc_ia64_register_backing_store_base;
-#endif
-#endif
-#endif
-
-/* Windows SEH refers data on the stack. */
-#undef SAVE_WIN32_EXCEPTION_LIST
-#if defined _WIN32 || defined __CYGWIN__
-#if defined __CYGWIN__
-typedef unsigned long DWORD;
-#endif
-
-static inline DWORD
-win32_get_exception_list()
-{
- DWORD p;
-# if defined _MSC_VER
-# ifdef _M_IX86
-# define SAVE_WIN32_EXCEPTION_LIST
-# if _MSC_VER >= 1310
- /* warning: unsafe assignment to fs:0 ... this is ok */
-# pragma warning(disable: 4733)
-# endif
- __asm mov eax, fs:[0];
- __asm mov p, eax;
-# endif
-# elif defined __GNUC__
-# ifdef __i386__
-# define SAVE_WIN32_EXCEPTION_LIST
- __asm__("movl %%fs:0,%0" : "=r"(p));
-# endif
-# elif defined __BORLANDC__
-# define SAVE_WIN32_EXCEPTION_LIST
- __emit__(0x64, 0xA1, 0, 0, 0, 0); /* mov eax, fs:[0] */
- p = _EAX;
-# endif
- return p;
-}
-
-static inline void
-win32_set_exception_list(p)
- DWORD p;
-{
-# if defined _MSC_VER
-# ifdef _M_IX86
- __asm mov eax, p;
- __asm mov fs:[0], eax;
-# endif
-# elif defined __GNUC__
-# ifdef __i386__
- __asm__("movl %0,%%fs:0" :: "r"(p));
-# endif
-# elif defined __BORLANDC__
- _EAX = p;
- __emit__(0x64, 0xA3, 0, 0, 0, 0); /* mov fs:[0], eax */
-# endif
-}
-
-#if !defined SAVE_WIN32_EXCEPTION_LIST && !defined _WIN32_WCE
-# error unsupported platform
-#endif
-#endif
-
-int rb_thread_pending = 0;
-
-VALUE rb_cThread;
-
-extern VALUE rb_last_status;
-
-enum thread_status {
- THREAD_TO_KILL,
- THREAD_RUNNABLE,
- THREAD_STOPPED,
- THREAD_KILLED,
-};
-
-#define WAIT_FD (1<<0)
-#define WAIT_SELECT (1<<1)
-#define WAIT_TIME (1<<2)
-#define WAIT_JOIN (1<<3)
-#define WAIT_PID (1<<4)
-
-/* +infty, for this purpose */
-#define DELAY_INFTY 1E30
-
-#if !defined HAVE_PAUSE
-# if defined _WIN32 && !defined __CYGWIN__
-# define pause() Sleep(INFINITE)
-# else
-# define pause() sleep(0x7fffffff)
-# endif
-#endif
-
-/* typedef struct thread * rb_thread_t; */
-
-struct thread {
- struct thread *next, *prev;
- rb_jmpbuf_t context;
-#ifdef SAVE_WIN32_EXCEPTION_LIST
- DWORD win32_exception_list;
-#endif
-
- VALUE result;
-
- long stk_len;
- long stk_max;
- VALUE *stk_ptr;
- VALUE *stk_pos;
-#ifdef __ia64__
- VALUE *bstr_ptr;
- long bstr_len;
-#endif
-
- struct FRAME *frame;
- struct SCOPE *scope;
- struct RVarmap *dyna_vars;
- struct BLOCK *block;
- struct iter *iter;
- struct tag *tag;
- VALUE klass;
- VALUE wrapper;
- NODE *cref;
- struct ruby_env *anchor;
-
- int flags; /* misc. states (vmode/rb_trap_immediate/raised) */
-
- NODE *node;
-
- int tracing;
- VALUE errinfo;
- VALUE last_status;
- VALUE last_line;
- VALUE last_match;
-
- int safe;
-
- enum thread_status status;
- int wait_for;
- int fd;
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
- int select_value;
- double delay;
- rb_thread_t join;
-
- int abort;
- int priority;
- VALUE thgroup;
-
- st_table *locals;
-
- VALUE thread;
-};
-
-#define THREAD_RAISED 0x200 /* temporary flag */
-#define THREAD_TERMINATING 0x400 /* persistent flag */
-#define THREAD_FLAGS_MASK 0x400 /* mask for persistent flags */
-
-#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
-#define END_FOREACH_FROM(f,x) } while (x != f)
-
-#define FOREACH_THREAD(x) FOREACH_THREAD_FROM(curr_thread,x)
-#define END_FOREACH(x) END_FOREACH_FROM(curr_thread,x)
-
-struct thread_status_t {
- NODE *node;
-
- int tracing;
- VALUE errinfo;
- VALUE last_status;
- VALUE last_line;
- VALUE last_match;
-
- int safe;
-
- enum thread_status status;
- int wait_for;
- int fd;
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
- int select_value;
- double delay;
- rb_thread_t join;
-};
-
-#define THREAD_COPY_STATUS(src, dst) (void)( \
- (dst)->node = (src)->node, \
- \
- (dst)->tracing = (src)->tracing, \
- (dst)->errinfo = (src)->errinfo, \
- (dst)->last_status = (src)->last_status, \
- (dst)->last_line = (src)->last_line, \
- (dst)->last_match = (src)->last_match, \
- \
- (dst)->safe = (src)->safe, \
- \
- (dst)->status = (src)->status, \
- (dst)->wait_for = (src)->wait_for, \
- (dst)->fd = (src)->fd, \
- (dst)->readfds = (src)->readfds, \
- (dst)->writefds = (src)->writefds, \
- (dst)->exceptfds = (src)->exceptfds, \
- (dst)->select_value = (src)->select_value, \
- (dst)->delay = (src)->delay, \
- (dst)->join = (src)->join, \
- 0)
-
-static int
-thread_set_raised()
-{
- if (curr_thread->flags & THREAD_RAISED) return 1;
- curr_thread->flags |= THREAD_RAISED;
- return 0;
-}
-
-static int
-thread_reset_raised()
-{
- if (!(curr_thread->flags & THREAD_RAISED)) return 0;
- curr_thread->flags &= ~THREAD_RAISED;
- return 1;
-}
-
-static void rb_thread_ready _((rb_thread_t));
-
-static VALUE run_trap_eval _((VALUE));
-static VALUE
-run_trap_eval(arg)
- VALUE arg;
-{
- VALUE *p = (VALUE *)arg;
- return rb_eval_cmd(p[0], p[1], (int)p[2]);
-}
-
-static VALUE
-rb_trap_eval(cmd, sig, safe)
- VALUE cmd;
- int sig, safe;
-{
- int state;
- VALUE val = Qnil; /* OK */
- volatile struct thread_status_t save;
- VALUE arg[3];
-
- arg[0] = cmd;
- arg[1] = rb_ary_new3(1, INT2FIX(sig));
- arg[2] = (VALUE)safe;
- THREAD_COPY_STATUS(curr_thread, &save);
- rb_thread_ready(curr_thread);
- PUSH_ITER(ITER_NOT);
- val = rb_protect(run_trap_eval, (VALUE)&arg, &state);
- POP_ITER();
- THREAD_COPY_STATUS(&save, curr_thread);
-
- if (state) {
- rb_trap_immediate = 0;
- JUMP_TAG(state);
- }
-
- if (curr_thread->status == THREAD_STOPPED) {
- rb_thread_schedule();
- }
- errno = EINTR;
-
- return val;
-}
-
-static const char *
-thread_status_name(status)
- enum thread_status status;
-{
- switch (status) {
- case THREAD_RUNNABLE:
- return "run";
- case THREAD_STOPPED:
- return "sleep";
- case THREAD_TO_KILL:
- return "aborting";
- case THREAD_KILLED:
- return "dead";
- default:
- return "unknown";
- }
-}
-
-/* $SAFE accessor */
-void
-rb_set_safe_level(level)
- int level;
-{
- if (level > ruby_safe_level) {
- if (level > SAFE_LEVEL_MAX) level = SAFE_LEVEL_MAX;
- ruby_safe_level = level;
- curr_thread->safe = level;
- }
-}
-
-static VALUE
-safe_getter()
-{
- return INT2NUM(ruby_safe_level);
-}
-
-static void
-safe_setter(val)
- VALUE val;
-{
- int level = NUM2INT(val);
-
- if (level < ruby_safe_level) {
- rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
- ruby_safe_level, level);
- }
- if (level > SAFE_LEVEL_MAX) level = SAFE_LEVEL_MAX;
- ruby_safe_level = level;
- curr_thread->safe = level;
-}
-
-/* Return the current time as a floating-point number */
-static double
-timeofday()
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
-}
-
-#define STACK(addr) (th->stk_pos<(VALUE*)(addr) && (VALUE*)(addr)<th->stk_pos+th->stk_len)
-#define ADJ(addr) (void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr))
-
-static void
-thread_mark(th)
- rb_thread_t th;
-{
- struct FRAME *frame;
- struct BLOCK *block;
-
- rb_gc_mark(th->result);
- rb_gc_mark(th->thread);
- if (th->join) rb_gc_mark(th->join->thread);
-
- rb_gc_mark(th->klass);
- rb_gc_mark(th->wrapper);
- rb_gc_mark((VALUE)th->cref);
-
- rb_gc_mark((VALUE)th->scope);
- rb_gc_mark((VALUE)th->dyna_vars);
- rb_gc_mark(th->errinfo);
- rb_gc_mark(th->last_line);
- rb_gc_mark(th->last_match);
- rb_mark_tbl(th->locals);
- rb_gc_mark(th->thgroup);
-
- /* mark data in copied stack */
- if (th == curr_thread) return;
- if (th->status == THREAD_KILLED) return;
- if (th->stk_len == 0) return; /* stack not active, no need to mark. */
- if (th->stk_ptr) {
- rb_gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
-#if defined(THINK_C) || defined(__human68k__)
- rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
-#endif
-#ifdef __ia64__
- if (th->bstr_ptr) {
- rb_gc_mark_locations(th->bstr_ptr, th->bstr_ptr+th->bstr_len);
- }
-#endif
- }
- frame = th->frame;
- while (frame && frame != top_frame) {
- frame = ADJ(frame);
- rb_gc_mark_frame(frame);
- if (frame->tmp) {
- struct FRAME *tmp = frame->tmp;
-
- while (tmp && tmp != top_frame) {
- tmp = ADJ(tmp);
- rb_gc_mark_frame(tmp);
- tmp = tmp->prev;
- }
- }
- frame = frame->prev;
- }
- block = th->block;
- while (block) {
- block = ADJ(block);
- rb_gc_mark_frame(&block->frame);
- block = block->prev;
- }
-}
-
-static struct {
- rb_thread_t thread;
- VALUE proc, arg;
-} new_thread;
-
-void
-rb_gc_mark_threads()
-{
- rb_thread_t th;
-
- /* static global mark */
- rb_gc_mark((VALUE)ruby_cref);
-
- if (!curr_thread) return;
- FOREACH_THREAD(th) {
- rb_gc_mark(th->thread);
- } END_FOREACH(th);
- if (new_thread.thread) {
- rb_gc_mark(new_thread.thread->thread);
- rb_gc_mark(new_thread.proc);
- rb_gc_mark(new_thread.arg);
- }
-}
-
-static void
-thread_free(th)
- rb_thread_t th;
-{
- if (th->stk_ptr) free(th->stk_ptr);
- th->stk_ptr = 0;
-#ifdef __ia64__
- if (th->bstr_ptr) free(th->bstr_ptr);
- th->bstr_ptr = 0;
-#endif
- if (th->locals) st_free_table(th->locals);
- if (th->status != THREAD_KILLED) {
- if (th->prev) th->prev->next = th->next;
- if (th->next) th->next->prev = th->prev;
- }
- if (th != main_thread) free(th);
-}
-
-static rb_thread_t
-rb_thread_check(data)
- VALUE data;
-{
- if (TYPE(data) != T_DATA || RDATA(data)->dmark != (RUBY_DATA_FUNC)thread_mark) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
- rb_obj_classname(data));
- }
- return (rb_thread_t)RDATA(data)->data;
-}
-
-static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));
-
-static VALUE th_raise_exception;
-static NODE *th_raise_node;
-static VALUE th_cmd;
-static int th_sig, th_safe;
-static char *th_signm;
-
-#define RESTORE_NORMAL 1
-#define RESTORE_FATAL 2
-#define RESTORE_INTERRUPT 3
-#define RESTORE_TRAP 4
-#define RESTORE_RAISE 5
-#define RESTORE_SIGNAL 6
-#define RESTORE_EXIT 7
-
-extern VALUE *rb_gc_stack_start;
-
-static void
-rb_thread_save_context(th)
- rb_thread_t th;
-{
- VALUE *pos;
- int len;
- static VALUE tval;
-
- len = ruby_stack_length(&pos);
- th->stk_len = 0;
- th->stk_pos = pos;
- if (len > th->stk_max) {
- REALLOC_N(th->stk_ptr, VALUE, len);
- th->stk_max = len;
- }
- th->stk_len = len;
- FLUSH_REGISTER_WINDOWS;
- MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
-#ifdef __ia64__
- {
- VALUE *top, *bot;
-#ifdef HAVE_UNWIND_H
- _Unwind_Context *unwctx = _UNW_createContextForSelf();
-
- _UNW_currentContext(unwctx);
- bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
- top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
- _UNW_destroyContext(unwctx);
-#else
- ucontext_t ctx;
-
- getcontext(&ctx);
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
- top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
-#endif
- th->bstr_len = top - bot;
- REALLOC_N(th->bstr_ptr, VALUE, th->bstr_len);
- MEMCPY(th->bstr_ptr, bot, VALUE, th->bstr_len);
- }
-#endif
-#ifdef SAVE_WIN32_EXCEPTION_LIST
- th->win32_exception_list = win32_get_exception_list();
-#endif
-
- th->frame = ruby_frame;
- th->scope = ruby_scope;
- th->klass = ruby_class;
- th->wrapper = ruby_wrapper;
- th->cref = ruby_cref;
- th->dyna_vars = ruby_dyna_vars;
- th->block = ruby_block;
- th->flags &= THREAD_FLAGS_MASK;
- th->flags |= (rb_trap_immediate<<8) | scope_vmode;
- th->iter = ruby_iter;
- th->tag = prot_tag;
- th->tracing = tracing;
- th->errinfo = ruby_errinfo;
- th->last_status = rb_last_status;
- tval = rb_lastline_get();
- rb_lastline_set(th->last_line);
- th->last_line = tval;
- tval = rb_backref_get();
- rb_backref_set(th->last_match);
- th->last_match = tval;
- th->safe = ruby_safe_level;
-
- th->node = ruby_current_node;
-}
-
-static int
-rb_thread_switch(n)
- int n;
-{
- rb_trap_immediate = (curr_thread->flags&(1<<8))?1:0;
- switch (n) {
- case 0:
- return 0;
- case RESTORE_FATAL:
- JUMP_TAG(TAG_FATAL);
- break;
- case RESTORE_INTERRUPT:
- rb_interrupt();
- break;
- case RESTORE_TRAP:
- rb_trap_eval(th_cmd, th_sig, th_safe);
- break;
- case RESTORE_RAISE:
- ruby_frame->callee = 0;
- ruby_frame->this_func = 0;
- ruby_current_node = th_raise_node;
- rb_raise_jump(th_raise_exception);
- break;
- case RESTORE_SIGNAL:
- rb_raise(rb_eSignal, "SIG%s", th_signm);
- break;
- case RESTORE_EXIT:
- ruby_errinfo = th_raise_exception;
- ruby_current_node = th_raise_node;
- error_print();
- terminate_process(EXIT_FAILURE, 0, 0);
- break;
- case RESTORE_NORMAL:
- default:
- break;
- }
- return 1;
-}
-
-#define THREAD_SAVE_CONTEXT(th) \
- (rb_thread_save_context(th),\
- rb_thread_switch((FLUSH_REGISTER_WINDOWS, setjmp((th)->context))))
-
-NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
-NOINLINE(static void stack_extend _((rb_thread_t, int)));
-
-static void
-stack_extend(th, exit)
- rb_thread_t th;
- int exit;
-{
- VALUE space[1024];
-
- memset(space, 0, 1); /* prevent array from optimization */
- rb_thread_restore_context(th, exit);
-}
-
-static void
-rb_thread_restore_context(th, exit)
- rb_thread_t th;
- int exit;
-{
- VALUE v;
- static rb_thread_t tmp;
- static int ex;
- static VALUE tval;
-
- if (!th->stk_ptr) rb_bug("unsaved context");
-
-#if STACK_GROW_DIRECTION < 0
- if (&v > th->stk_pos) stack_extend(th, exit);
-#elif STACK_GROW_DIRECTION > 0
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
-#else
- if (&v < rb_gc_stack_start) {
- /* Stack grows downward */
- if (&v > th->stk_pos) stack_extend(th, exit);
- }
- else {
- /* Stack grows upward */
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
- }
-#endif
-
- rb_trap_immediate = 0; /* inhibit interrupts from here */
- ruby_frame = th->frame;
- ruby_scope = th->scope;
- ruby_class = th->klass;
- ruby_wrapper = th->wrapper;
- ruby_cref = th->cref;
- ruby_dyna_vars = th->dyna_vars;
- ruby_block = th->block;
- scope_vmode = th->flags&SCOPE_MASK;
- ruby_iter = th->iter;
- prot_tag = th->tag;
- tracing = th->tracing;
- ruby_errinfo = th->errinfo;
- rb_last_status = th->last_status;
- ruby_safe_level = th->safe;
-
- ruby_current_node = th->node;
-
-#ifdef SAVE_WIN32_EXCEPTION_LIST
- win32_set_exception_list(th->win32_exception_list);
-#endif
- tmp = th;
- ex = exit;
- FLUSH_REGISTER_WINDOWS;
- MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
-#ifdef __ia64__
- {
- VALUE *base;
-#ifdef HAVE_UNWIND_H
- _Unwind_Context *unwctx = _UNW_createContextForSelf();
-
- _UNW_currentContext(unwctx);
- base = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
- _UNW_destroyContext(unwctx);
-#else
- base = (VALUE*)__libc_ia64_register_backing_store_base;
-#endif
- MEMCPY(base, tmp->bstr_ptr, VALUE, tmp->bstr_len);
- }
-#endif
-
- tval = rb_lastline_get();
- rb_lastline_set(tmp->last_line);
- tmp->last_line = tval;
- tval = rb_backref_get();
- rb_backref_set(tmp->last_match);
- tmp->last_match = tval;
-
- longjmp(tmp->context, ex);
-}
-
-static void
-rb_thread_ready(th)
- rb_thread_t th;
-{
- th->wait_for = 0;
- if (th->status != THREAD_TO_KILL) {
- th->status = THREAD_RUNNABLE;
- }
-}
-
-static void
-rb_thread_die(th)
- rb_thread_t th;
-{
- th->thgroup = 0;
- th->status = THREAD_KILLED;
- if (th->stk_ptr) free(th->stk_ptr);
- th->stk_ptr = 0;
-}
-
-static void
-rb_thread_remove(th)
- rb_thread_t th;
-{
- if (th->status == THREAD_KILLED) return;
-
- rb_thread_ready(th);
- rb_thread_die(th);
- th->prev->next = th->next;
- th->next->prev = th->prev;
-}
-
-static int
-rb_thread_dead(th)
- rb_thread_t th;
-{
- return th->status == THREAD_KILLED;
-}
-
-void
-rb_thread_fd_close(fd)
- int fd;
-{
- rb_thread_t th;
-
- FOREACH_THREAD(th) {
- if (((th->wait_for & WAIT_FD) && fd == th->fd) ||
- ((th->wait_for & WAIT_SELECT) && (fd < th->fd) &&
- (FD_ISSET(fd, &th->readfds) ||
- FD_ISSET(fd, &th->writefds) ||
- FD_ISSET(fd, &th->exceptfds)))) {
- VALUE exc = rb_exc_new2(rb_eIOError, "stream closed");
- rb_thread_raise(1, &exc, th);
- }
- }
- END_FOREACH(th);
-}
-
-NORETURN(static void rb_thread_main_jump _((VALUE, int)));
-static void
-rb_thread_main_jump(err, tag)
- VALUE err;
- int tag;
-{
- curr_thread = main_thread;
- th_raise_exception = err;
- th_raise_node = ruby_current_node;
- rb_thread_restore_context(main_thread, tag);
-}
-
-NORETURN(static void rb_thread_deadlock _((void)));
-static void
-rb_thread_deadlock()
-{
- char msg[21+SIZEOF_LONG*2];
- VALUE e;
-
- sprintf(msg, "Thread(0x%lx): deadlock", curr_thread->thread);
- e = rb_exc_new2(rb_eFatal, msg);
- if (curr_thread == main_thread) {
- rb_exc_raise(e);
- }
- rb_thread_main_jump(e, RESTORE_RAISE);
-}
-
-static void
-copy_fds(dst, src, max)
- fd_set *dst, *src;
- int max;
-{
- int n = 0;
- int i;
-
- for (i=0; i<=max; i++) {
- if (FD_ISSET(i, src)) {
- n = i;
- FD_SET(i, dst);
- }
- }
-}
-
-static int
-match_fds(dst, src, max)
- fd_set *dst, *src;
- int max;
-{
- int i;
-
- for (i=0; i<=max; i++) {
- if (FD_ISSET(i, src) && FD_ISSET(i, dst)) {
- return Qtrue;
- }
- }
- return Qfalse;
-}
-
-static int
-intersect_fds(src, dst, max)
- fd_set *src, *dst;
- int max;
-{
- int i, n = 0;
-
- for (i=0; i<=max; i++) {
- if (FD_ISSET(i, dst)) {
- if (FD_ISSET(i, src)) {
- /* Wake up only one thread per fd. */
- FD_CLR(i, src);
- n++;
- }
- else {
- FD_CLR(i, dst);
- }
- }
- }
- return n;
-}
-
-static int
-find_bad_fds(dst, src, max)
- fd_set *dst, *src;
- int max;
-{
- int i, test = Qfalse;
-
- for (i=0; i<=max; i++) {
- if (FD_ISSET(i, src) && !FD_ISSET(i, dst)) {
- FD_CLR(i, src);
- test = Qtrue;
- }
- }
- return test;
-}
-
-void
-rb_thread_schedule()
-{
- rb_thread_t next; /* OK */
- rb_thread_t th;
- rb_thread_t curr;
- int found = 0;
-
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
- struct timeval delay_tv, *delay_ptr;
- double delay, now; /* OK */
- int n, max;
- int need_select = 0;
- int select_timeout = 0;
-
-#ifdef HAVE_NATIVETHREAD
- if (!is_ruby_native_thread()) {
- rb_bug("cross-thread violation on rb_thread_schedule()");
- }
-#endif
- rb_thread_pending = 0;
- if (curr_thread == curr_thread->next
- && curr_thread->status == THREAD_RUNNABLE)
- return;
-
- next = 0;
- curr = curr_thread; /* starting thread */
-
- while (curr->status == THREAD_KILLED) {
- curr = curr->prev;
- }
-
- again:
- max = -1;
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
- delay = DELAY_INFTY;
- now = -1.0;
-
- FOREACH_THREAD_FROM(curr, th) {
- if (!found && th->status <= THREAD_RUNNABLE) {
- found = 1;
- }
- if (th->status != THREAD_STOPPED) continue;
- if (th->wait_for & WAIT_JOIN) {
- if (rb_thread_dead(th->join)) {
- th->status = THREAD_RUNNABLE;
- found = 1;
- }
- }
- if (th->wait_for & WAIT_FD) {
- FD_SET(th->fd, &readfds);
- if (max < th->fd) max = th->fd;
- need_select = 1;
- }
- if (th->wait_for & WAIT_SELECT) {
- copy_fds(&readfds, &th->readfds, th->fd);
- copy_fds(&writefds, &th->writefds, th->fd);
- copy_fds(&exceptfds, &th->exceptfds, th->fd);
- if (max < th->fd) max = th->fd;
- need_select = 1;
- if (th->wait_for & WAIT_TIME) {
- select_timeout = 1;
- }
- th->select_value = 0;
- }
- if (th->wait_for & WAIT_TIME) {
- double th_delay;
-
- if (now < 0.0) now = timeofday();
- th_delay = th->delay - now;
- if (th_delay <= 0.0) {
- th->status = THREAD_RUNNABLE;
- found = 1;
- }
- else if (th_delay < delay) {
- delay = th_delay;
- need_select = 1;
- }
- else if (th->delay == DELAY_INFTY) {
- need_select = 1;
- }
- }
- }
- END_FOREACH_FROM(curr, th);
-
- /* Do the select if needed */
- if (need_select) {
- /* Convert delay to a timeval */
- /* If a thread is runnable, just poll */
- if (found) {
- delay_tv.tv_sec = 0;
- delay_tv.tv_usec = 0;
- delay_ptr = &delay_tv;
- }
- else if (delay == DELAY_INFTY) {
- delay_ptr = 0;
- }
- else {
- delay_tv.tv_sec = delay;
- delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec)*1e6;
- delay_ptr = &delay_tv;
- }
-
- n = select(max+1, &readfds, &writefds, &exceptfds, delay_ptr);
- if (n < 0) {
- int e = errno;
-
- if (rb_trap_pending) rb_trap_exec();
- if (e == EINTR) goto again;
-#ifdef ERESTART
- if (e == ERESTART) goto again;
-#endif
- FOREACH_THREAD_FROM(curr, th) {
- if (th->wait_for & WAIT_SELECT) {
- int v = 0;
-
- v |= find_bad_fds(&readfds, &th->readfds, th->fd);
- v |= find_bad_fds(&writefds, &th->writefds, th->fd);
- v |= find_bad_fds(&exceptfds, &th->exceptfds, th->fd);
- if (v) {
- th->select_value = n;
- n = max;
- }
- }
- }
- END_FOREACH_FROM(curr, th);
- }
- if (select_timeout && n == 0) {
- if (now < 0.0) now = timeofday();
- FOREACH_THREAD_FROM(curr, th) {
- if (((th->wait_for&(WAIT_SELECT|WAIT_TIME)) == (WAIT_SELECT|WAIT_TIME)) &&
- th->delay <= now) {
- th->status = THREAD_RUNNABLE;
- th->wait_for = 0;
- th->select_value = 0;
- found = 1;
- intersect_fds(&readfds, &th->readfds, max);
- intersect_fds(&writefds, &th->writefds, max);
- intersect_fds(&exceptfds, &th->exceptfds, max);
- }
- }
- END_FOREACH_FROM(curr, th);
- }
- if (n > 0) {
- now = -1.0;
- /* Some descriptors are ready.
- Make the corresponding threads runnable. */
- FOREACH_THREAD_FROM(curr, th) {
- if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) {
- /* Wake up only one thread per fd. */
- FD_CLR(th->fd, &readfds);
- th->status = THREAD_RUNNABLE;
- th->fd = 0;
- th->wait_for = 0;
- found = 1;
- }
- if ((th->wait_for&WAIT_SELECT) &&
- (match_fds(&readfds, &th->readfds, max) ||
- match_fds(&writefds, &th->writefds, max) ||
- match_fds(&exceptfds, &th->exceptfds, max))) {
- /* Wake up only one thread per fd. */
- th->status = THREAD_RUNNABLE;
- th->wait_for = 0;
- n = intersect_fds(&readfds, &th->readfds, max) +
- intersect_fds(&writefds, &th->writefds, max) +
- intersect_fds(&exceptfds, &th->exceptfds, max);
- th->select_value = n;
- found = 1;
- }
- }
- END_FOREACH_FROM(curr, th);
- }
- /* The delays for some of the threads should have expired.
- Go through the loop once more, to check the delays. */
- if (!found && delay != DELAY_INFTY)
- goto again;
- }
-
- FOREACH_THREAD_FROM(curr, th) {
- if (th->status == THREAD_TO_KILL) {
- next = th;
- break;
- }
- if (th->status == THREAD_RUNNABLE && th->stk_ptr) {
- if (!next || next->priority < th->priority)
- next = th;
- }
- }
- END_FOREACH_FROM(curr, th);
-
- if (!next) {
- /* raise fatal error to main thread */
- curr_thread->node = ruby_current_node;
- if (curr->next == curr) {
- TRAP_BEG;
- pause();
- TRAP_END;
- }
- FOREACH_THREAD_FROM(curr, th) {
- warn_printf("deadlock 0x%lx: %s:",
- th->thread, thread_status_name(th->status));
- if (th->wait_for & WAIT_FD) warn_printf("F(%d)", th->fd);
- if (th->wait_for & WAIT_SELECT) warn_printf("S");
- if (th->wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay);
- if (th->wait_for & WAIT_JOIN)
- warn_printf("J(0x%lx)", th->join ? th->join->thread : 0);
- if (th->wait_for & WAIT_PID) warn_printf("P");
- if (!th->wait_for) warn_printf("-");
- warn_printf(" %s - %s:%d\n",
- th==main_thread ? "(main)" : "",
- th->node->nd_file, nd_line(th->node));
- }
- END_FOREACH_FROM(curr, th);
- next = main_thread;
- rb_thread_ready(next);
- next->status = THREAD_TO_KILL;
- if (!rb_thread_dead(curr_thread)) {
- rb_thread_save_context(curr_thread);
- }
- rb_thread_deadlock();
- }
- next->wait_for = 0;
- if (next->status == THREAD_RUNNABLE && next == curr_thread) {
- return;
- }
-
- /* context switch */
- if (curr == curr_thread) {
- if (THREAD_SAVE_CONTEXT(curr)) {
- return;
- }
- }
-
- curr_thread = next;
- if (next->status == THREAD_TO_KILL) {
- if (!(next->flags & THREAD_TERMINATING)) {
- next->flags |= THREAD_TERMINATING;
- /* terminate; execute ensure-clause if any */
- rb_thread_restore_context(next, RESTORE_FATAL);
- }
- }
- rb_thread_restore_context(next, RESTORE_NORMAL);
-}
-
-void
-rb_thread_wait_fd(fd)
- int fd;
-{
- if (rb_thread_critical) return;
- if (curr_thread == curr_thread->next) return;
- if (curr_thread->status == THREAD_TO_KILL) return;
-
- curr_thread->status = THREAD_STOPPED;
- curr_thread->fd = fd;
- curr_thread->wait_for = WAIT_FD;
- rb_thread_schedule();
-}
-
-int
-rb_thread_fd_writable(fd)
- int fd;
-{
- if (rb_thread_critical) return Qtrue;
- if (curr_thread == curr_thread->next) return Qtrue;
- if (curr_thread->status == THREAD_TO_KILL) return Qtrue;
-
- curr_thread->status = THREAD_STOPPED;
- FD_ZERO(&curr_thread->readfds);
- FD_ZERO(&curr_thread->writefds);
- FD_SET(fd, &curr_thread->writefds);
- FD_ZERO(&curr_thread->exceptfds);
- curr_thread->fd = fd+1;
- curr_thread->wait_for = WAIT_SELECT;
- rb_thread_schedule();
- return Qfalse;
-}
-
-void
-rb_thread_wait_for(time)
- struct timeval time;
-{
- double date;
-
- if (rb_thread_critical ||
- curr_thread == curr_thread->next ||
- curr_thread->status == THREAD_TO_KILL) {
- int n;
- int thr_critical = rb_thread_critical;
-#ifndef linux
- double d, limit;
- limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6;
-#endif
- for (;;) {
- rb_thread_critical = Qtrue;
- TRAP_BEG;
- n = select(0, 0, 0, 0, &time);
- rb_thread_critical = thr_critical;
- TRAP_END;
- if (n == 0) return;
- if (n < 0) {
- switch (errno) {
- case EINTR:
-#ifdef ERESTART
- case ERESTART:
-#endif
- return;
- default:
- rb_sys_fail("sleep");
- }
- }
-#ifndef linux
- d = limit - timeofday();
-
- time.tv_sec = (int)d;
- time.tv_usec = (int)((d - (int)d)*1e6);
- if (time.tv_usec < 0) {
- time.tv_usec += (long)1e6;
- time.tv_sec -= 1;
- }
- if (time.tv_sec < 0) return;
-#endif
- }
- }
-
- date = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6;
- curr_thread->status = THREAD_STOPPED;
- curr_thread->delay = date;
- curr_thread->wait_for = WAIT_TIME;
- rb_thread_schedule();
-}
-
-void rb_thread_sleep_forever _((void));
-
-int
-rb_thread_alone()
-{
- return curr_thread == curr_thread->next;
-}
-
-int
-rb_thread_select(max, read, write, except, timeout)
- int max;
- fd_set *read, *write, *except;
- struct timeval *timeout;
-{
- double limit;
- int n;
-
- if (!read && !write && !except) {
- if (!timeout) {
- rb_thread_sleep_forever();
- return 0;
- }
- rb_thread_wait_for(*timeout);
- return 0;
- }
-
- if (timeout) {
- limit = timeofday()+
- (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
- }
-
- if (rb_thread_critical ||
- curr_thread == curr_thread->next ||
- curr_thread->status == THREAD_TO_KILL) {
-#ifndef linux
- struct timeval tv, *tvp = timeout;
-
- if (timeout) {
- tv = *timeout;
- tvp = &tv;
- }
-#else
- struct timeval *const tvp = timeout;
-#endif
- for (;;) {
- TRAP_BEG;
- n = select(max, read, write, except, tvp);
- TRAP_END;
- if (n < 0) {
- switch (errno) {
- case EINTR:
-#ifdef ERESTART
- case ERESTART:
-#endif
-#ifndef linux
- if (timeout) {
- double d = limit - timeofday();
-
- tv.tv_sec = (unsigned int)d;
- tv.tv_usec = (long)((d-(double)tv.tv_sec)*1e6);
- if (tv.tv_sec < 0) tv.tv_sec = 0;
- if (tv.tv_usec < 0) tv.tv_usec = 0;
- }
-#endif
- continue;
- default:
- break;
- }
- }
- return n;
- }
- }
-
- curr_thread->status = THREAD_STOPPED;
- if (read) curr_thread->readfds = *read;
- else FD_ZERO(&curr_thread->readfds);
- if (write) curr_thread->writefds = *write;
- else FD_ZERO(&curr_thread->writefds);
- if (except) curr_thread->exceptfds = *except;
- else FD_ZERO(&curr_thread->exceptfds);
- curr_thread->fd = max;
- curr_thread->wait_for = WAIT_SELECT;
- if (timeout) {
- curr_thread->delay = timeofday() +
- (double)timeout->tv_sec + (double)timeout->tv_usec*1e-6;
- curr_thread->wait_for |= WAIT_TIME;
- }
- rb_thread_schedule();
- if (read) *read = curr_thread->readfds;
- if (write) *write = curr_thread->writefds;
- if (except) *except = curr_thread->exceptfds;
- return curr_thread->select_value;
-}
-
-static int rb_thread_join _((rb_thread_t, double));
-
-static int
-rb_thread_join(th, limit)
- rb_thread_t th;
- double limit;
-{
- enum thread_status last_status = THREAD_RUNNABLE;
-
- if (rb_thread_critical) rb_thread_deadlock();
- if (!rb_thread_dead(th)) {
- if (th == curr_thread)
- rb_raise(rb_eThreadError, "thread 0x%lx tried to join itself",
- th->thread);
- if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
- rb_raise(rb_eThreadError, "Thread#join: deadlock 0x%lx - mutual join(0x%lx)",
- curr_thread->thread, th->thread);
- if (curr_thread->status == THREAD_TO_KILL)
- last_status = THREAD_TO_KILL;
- if (limit == 0) return Qfalse;
- curr_thread->status = THREAD_STOPPED;
- curr_thread->join = th;
- curr_thread->wait_for = WAIT_JOIN;
- curr_thread->delay = timeofday() + limit;
- if (limit < DELAY_INFTY) curr_thread->wait_for |= WAIT_TIME;
- rb_thread_schedule();
- curr_thread->status = last_status;
- if (!rb_thread_dead(th)) return Qfalse;
- }
-
- if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) {
- VALUE oldbt = get_backtrace(th->errinfo);
- VALUE errat = make_backtrace();
- VALUE errinfo = rb_obj_dup(th->errinfo);
-
- if (TYPE(oldbt) == T_ARRAY && RARRAY(oldbt)->len > 0) {
- rb_ary_unshift(errat, rb_ary_entry(oldbt, 0));
- }
- set_backtrace(errinfo, errat);
- rb_exc_raise(errinfo);
- }
-
- return Qtrue;
-}
-
-
-/*
- * call-seq:
- * thr.join => thr
- * thr.join(limit) => thr
- *
- * The calling thread will suspend execution and run <i>thr</i>. Does not
- * return until <i>thr</i> exits or until <i>limit</i> seconds have passed. If
- * the time limit expires, <code>nil</code> will be returned, otherwise
- * <i>thr</i> is returned.
- *
- * Any threads not joined will be killed when the main program exits. If
- * <i>thr</i> had previously raised an exception and the
- * <code>abort_on_exception</code> and <code>$DEBUG</code> flags are not set
- * (so the exception has not yet been processed) it will be processed at this
- * time.
- *
- * a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
- * x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
- * x.join # Let x thread finish, a will be killed on exit.
- *
- * <em>produces:</em>
- *
- * axyz
- *
- * The following example illustrates the <i>limit</i> parameter.
- *
- * y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
- * puts "Waiting" until y.join(0.15)
- *
- * <em>produces:</em>
- *
- * tick...
- * Waiting
- * tick...
- * Waitingtick...
- *
- *
- * tick...
- */
-
-static VALUE
-rb_thread_join_m(argc, argv, thread)
- int argc;
- VALUE *argv;
- VALUE thread;
-{
- VALUE limit;
- double delay = DELAY_INFTY;
- rb_thread_t th = rb_thread_check(thread);
-
- rb_scan_args(argc, argv, "01", &limit);
- if (!NIL_P(limit)) delay = rb_num2dbl(limit);
- if (!rb_thread_join(th, delay))
- return Qnil;
- return thread;
-}
-
-
-/*
- * call-seq:
- * Thread.current => thread
- *
- * Returns the currently executing thread.
- *
- * Thread.current #=> #<Thread:0x401bdf4c run>
- */
-
-VALUE
-rb_thread_current()
-{
- return curr_thread->thread;
-}
-
-
-/*
- * call-seq:
- * Thread.main => thread
- *
- * Returns the main thread for the process.
- *
- * Thread.main #=> #<Thread:0x401bdf4c run>
- */
-
-VALUE
-rb_thread_main()
-{
- return main_thread->thread;
-}
-
-
-/*
- * call-seq:
- * Thread.list => array
- *
- * Returns an array of <code>Thread</code> objects for all threads that are
- * either runnable or stopped.
- *
- * Thread.new { sleep(200) }
- * Thread.new { 1000000.times {|i| i*i } }
- * Thread.new { Thread.stop }
- * Thread.list.each {|t| p t}
- *
- * <em>produces:</em>
- *
- * #<Thread:0x401b3e84 sleep>
- * #<Thread:0x401b3f38 run>
- * #<Thread:0x401b3fb0 sleep>
- * #<Thread:0x401bdf4c run>
- */
-
-VALUE
-rb_thread_list()
-{
- rb_thread_t th;
- VALUE ary = rb_ary_new();
-
- FOREACH_THREAD(th) {
- switch (th->status) {
- case THREAD_RUNNABLE:
- case THREAD_STOPPED:
- case THREAD_TO_KILL:
- rb_ary_push(ary, th->thread);
- default:
- break;
- }
- }
- END_FOREACH(th);
-
- return ary;
-}
-
-
-/*
- * call-seq:
- * thr.wakeup => thr
- *
- * Marks <i>thr</i> as eligible for scheduling (it may still remain blocked on
- * I/O, however). Does not invoke the scheduler (see <code>Thread#run</code>).
- *
- * c = Thread.new { Thread.stop; puts "hey!" }
- * c.wakeup
- *
- * <em>produces:</em>
- *
- * hey!
- */
-
-VALUE
-rb_thread_wakeup(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (th->status == THREAD_KILLED)
- rb_raise(rb_eThreadError, "killed thread");
- rb_thread_ready(th);
-
- return thread;
-}
-
-
-/*
- * call-seq:
- * thr.run => thr
- *
- * Wakes up <i>thr</i>, making it eligible for scheduling. If not in a critical
- * section, then invokes the scheduler.
- *
- * a = Thread.new { puts "a"; Thread.stop; puts "c" }
- * Thread.pass
- * puts "Got here"
- * a.run
- * a.join
- *
- * <em>produces:</em>
- *
- * a
- * Got here
- * c
- */
-
-VALUE
-rb_thread_run(thread)
- VALUE thread;
-{
- rb_thread_wakeup(thread);
- if (!rb_thread_critical) rb_thread_schedule();
-
- return thread;
-}
-
-
-/*
- * call-seq:
- * thr.exit => thr or nil
- * thr.kill => thr or nil
- * thr.terminate => thr or nil
- *
- * Terminates <i>thr</i> and schedules another thread to be run. If this thread
- * is already marked to be killed, <code>exit</code> returns the
- * <code>Thread</code>. If this is the main thread, or the last thread, exits
- * the process.
- */
-
-VALUE
-rb_thread_kill(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (th != curr_thread && th->safe < 4) {
- rb_secure(4);
- }
- if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
- return thread;
- if (th == th->next || th == main_thread) rb_exit(EXIT_SUCCESS);
-
- rb_thread_ready(th);
- th->status = THREAD_TO_KILL;
- if (!rb_thread_critical) rb_thread_schedule();
- return thread;
-}
-
-
-/*
- * call-seq:
- * Thread.kill(thread) => thread
- *
- * Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
- *
- * count = 0
- * a = Thread.new { loop { count += 1 } }
- * sleep(0.1) #=> 0
- * Thread.kill(a) #=> #<Thread:0x401b3d30 dead>
- * count #=> 93947
- * a.alive? #=> false
- */
-
-static VALUE
-rb_thread_s_kill(obj, th)
- VALUE obj, th;
-{
- return rb_thread_kill(th);
-}
-
-
-/*
- * call-seq:
- * Thread.exit => thread
- *
- * Terminates the currently running thread and schedules another thread to be
- * run. If this thread is already marked to be killed, <code>exit</code>
- * returns the <code>Thread</code>. If this is the main thread, or the last
- * thread, exit the process.
- */
-
-static VALUE
-rb_thread_exit()
-{
- return rb_thread_kill(curr_thread->thread);
-}
-
-
-/*
- * call-seq:
- * Thread.pass => nil
- *
- * Invokes the thread scheduler to pass execution to another thread.
- *
- * a = Thread.new { print "a"; Thread.pass;
- * print "b"; Thread.pass;
- * print "c" }
- * b = Thread.new { print "x"; Thread.pass;
- * print "y"; Thread.pass;
- * print "z" }
- * a.join
- * b.join
- *
- * <em>produces:</em>
- *
- * axbycz
- */
-
-static VALUE
-rb_thread_pass()
-{
- rb_thread_schedule();
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * Thread.stop => nil
- *
- * Stops execution of the current thread, putting it into a ``sleep'' state,
- * and schedules execution of another thread. Resets the ``critical'' condition
- * to <code>false</code>.
- *
- * a = Thread.new { print "a"; Thread.stop; print "c" }
- * Thread.pass
- * print "b"
- * a.run
- * a.join
- *
- * <em>produces:</em>
- *
- * abc
- */
-
-VALUE
-rb_thread_stop()
-{
- enum thread_status last_status = THREAD_RUNNABLE;
-
- rb_thread_critical = 0;
- if (curr_thread == curr_thread->next) {
- rb_raise(rb_eThreadError, "stopping only thread\n\tnote: use sleep to stop forever");
- }
- if (curr_thread->status == THREAD_TO_KILL)
- last_status = THREAD_TO_KILL;
- curr_thread->status = THREAD_STOPPED;
- rb_thread_schedule();
- curr_thread->status = last_status;
-
- return Qnil;
-}
-
-struct timeval rb_time_timeval();
-
-void
-rb_thread_polling()
-{
- if (curr_thread != curr_thread->next) {
- curr_thread->status = THREAD_STOPPED;
- curr_thread->delay = timeofday() + (double)0.06;
- curr_thread->wait_for = WAIT_TIME;
- rb_thread_schedule();
- }
-}
-
-void
-rb_thread_sleep(sec)
- int sec;
-{
- if (curr_thread == curr_thread->next) {
- TRAP_BEG;
- sleep(sec);
- TRAP_END;
- return;
- }
- rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
-}
-
-void
-rb_thread_sleep_forever()
-{
- int thr_critical = rb_thread_critical;
- if (curr_thread == curr_thread->next ||
- curr_thread->status == THREAD_TO_KILL) {
- rb_thread_critical = Qtrue;
- TRAP_BEG;
- pause();
- rb_thread_critical = thr_critical;
- TRAP_END;
- return;
- }
-
- curr_thread->delay = DELAY_INFTY;
- curr_thread->wait_for = WAIT_TIME;
- curr_thread->status = THREAD_STOPPED;
- rb_thread_schedule();
-}
-
-
-/*
- * call-seq:
- * thr.priority => integer
- *
- * Returns the priority of <i>thr</i>. Default is zero; higher-priority threads
- * will run before lower-priority threads.
- *
- * Thread.current.priority #=> 0
- */
-
-static VALUE
-rb_thread_priority(thread)
- VALUE thread;
-{
- return INT2NUM(rb_thread_check(thread)->priority);
-}
-
-
-/*
- * call-seq:
- * thr.priority= integer => thr
- *
- * Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
- * will run before lower-priority threads.
- *
- * count1 = count2 = 0
- * a = Thread.new do
- * loop { count1 += 1 }
- * end
- * a.priority = -1
- *
- * b = Thread.new do
- * loop { count2 += 1 }
- * end
- * b.priority = -2
- * sleep 1 #=> 1
- * Thread.critical = 1
- * count1 #=> 622504
- * count2 #=> 5832
- */
-
-static VALUE
-rb_thread_priority_set(thread, prio)
- VALUE thread, prio;
-{
- rb_thread_t th;
-
- rb_secure(4);
- th = rb_thread_check(thread);
-
- th->priority = NUM2INT(prio);
- rb_thread_schedule();
- return prio;
-}
-
-
-/*
- * call-seq:
- * thr.safe_level => integer
- *
- * Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
- * levels can help when implementing sandboxes which run insecure code.
- *
- * thr = Thread.new { $SAFE = 3; sleep }
- * Thread.current.safe_level #=> 0
- * thr.safe_level #=> 3
- */
-
-static VALUE
-rb_thread_safe_level(thread)
- VALUE thread;
-{
- rb_thread_t th;
-
- th = rb_thread_check(thread);
- if (th == curr_thread) {
- return INT2NUM(ruby_safe_level);
- }
- return INT2NUM(th->safe);
-}
-
-static int ruby_thread_abort;
-static VALUE thgroup_default;
-
-
-/*
- * call-seq:
- * Thread.abort_on_exception => true or false
- *
- * Returns the status of the global ``abort on exception'' condition. The
- * default is <code>false</code>. When set to <code>true</code>, or if the
- * global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
- * command line option <code>-d</code> was specified) all threads will abort
- * (the process will <code>exit(0)</code>) if an exception is raised in any
- * thread. See also <code>Thread::abort_on_exception=</code>.
- */
-
-static VALUE
-rb_thread_s_abort_exc()
-{
- return ruby_thread_abort?Qtrue:Qfalse;
-}
-
-
-/*
- * call-seq:
- * Thread.abort_on_exception= boolean => true or false
- *
- * When set to <code>true</code>, all threads will abort if an exception is
- * raised. Returns the new state.
- *
- * Thread.abort_on_exception = true
- * t1 = Thread.new do
- * puts "In new thread"
- * raise "Exception from thread"
- * end
- * sleep(1)
- * puts "not reached"
- *
- * <em>produces:</em>
- *
- * In new thread
- * prog.rb:4: Exception from thread (RuntimeError)
- * from prog.rb:2:in `initialize'
- * from prog.rb:2:in `new'
- * from prog.rb:2
- */
-
-static VALUE
-rb_thread_s_abort_exc_set(self, val)
- VALUE self, val;
-{
- rb_secure(4);
- ruby_thread_abort = RTEST(val);
- return val;
-}
-
-
-/*
- * call-seq:
- * thr.abort_on_exception => true or false
- *
- * Returns the status of the thread-local ``abort on exception'' condition for
- * <i>thr</i>. The default is <code>false</code>. See also
- * <code>Thread::abort_on_exception=</code>.
- */
-
-static VALUE
-rb_thread_abort_exc(thread)
- VALUE thread;
-{
- return rb_thread_check(thread)->abort?Qtrue:Qfalse;
-}
-
-
-/*
- * call-seq:
- * thr.abort_on_exception= boolean => true or false
- *
- * When set to <code>true</code>, causes all threads (including the main
- * program) to abort if an exception is raised in <i>thr</i>. The process will
- * effectively <code>exit(0)</code>.
- */
-
-static VALUE
-rb_thread_abort_exc_set(thread, val)
- VALUE thread, val;
-{
- rb_secure(4);
- rb_thread_check(thread)->abort = RTEST(val);
- return val;
-}
-
-
-/*
- * call-seq:
- * thr.group => thgrp or nil
- *
- * Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
- * the thread is not a member of any group.
- *
- * Thread.main.group #=> #<ThreadGroup:0x4029d914>
- */
-
-VALUE
-rb_thread_group(thread)
- VALUE thread;
-{
- VALUE group = rb_thread_check(thread)->thgroup;
- if (!group) {
- group = Qnil;
- }
- return group;
-}
-
-#ifdef __ia64__
-# define IA64_INIT(x) x
-#else
-# define IA64_INIT(x)
-#endif
-
-#define THREAD_ALLOC(th) do {\
- th = ALLOC(struct thread);\
-\
- th->next = 0;\
- th->prev = 0;\
-\
- th->status = THREAD_RUNNABLE;\
- th->result = 0;\
- th->flags = 0;\
-\
- th->stk_ptr = 0;\
- th->stk_len = 0;\
- th->stk_max = 0;\
- th->wait_for = 0;\
- IA64_INIT(th->bstr_ptr = 0);\
- IA64_INIT(th->bstr_len = 0);\
- FD_ZERO(&th->readfds);\
- FD_ZERO(&th->writefds);\
- FD_ZERO(&th->exceptfds);\
- th->delay = 0.0;\
- th->join = 0;\
-\
- th->frame = 0;\
- th->scope = 0;\
- th->klass = 0;\
- th->wrapper = 0;\
- th->cref = ruby_cref;\
- th->dyna_vars = ruby_dyna_vars;\
- th->block = 0;\
- th->iter = 0;\
- th->tag = 0;\
- th->tracing = 0;\
- th->errinfo = Qnil;\
- th->last_status = 0;\
- th->last_line = 0;\
- th->last_match = Qnil;\
- th->abort = 0;\
- th->priority = 0;\
- th->thgroup = thgroup_default;\
- th->locals = 0;\
- th->thread = 0;\
- th->anchor = 0;\
-} while (0)
-
-static rb_thread_t
-rb_thread_alloc(klass)
- VALUE klass;
-{
- rb_thread_t th;
- struct RVarmap *vars;
-
- THREAD_ALLOC(th);
- th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th);
-
- for (vars = th->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- return th;
-}
-
-static int thread_init = 0;
-
-#if defined(_THREAD_SAFE)
-static void
-catch_timer(sig)
- int sig;
-{
-#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
- signal(sig, catch_timer);
-#endif
- /* cause EINTR */
-}
-
-static pthread_t time_thread;
-
-static void*
-thread_timer(dummy)
- void *dummy;
-{
- for (;;) {
-#ifdef HAVE_NANOSLEEP
- struct timespec req, rem;
-
- req.tv_sec = 0;
- req.tv_nsec = 10000000;
- nanosleep(&req, &rem);
-#else
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 10000;
- select(0, NULL, NULL, NULL, &tv);
-#endif
- if (!rb_thread_critical) {
- rb_thread_pending = 1;
- if (rb_trap_immediate) {
- pthread_kill(ruby_thid, SIGVTALRM);
- }
- }
- }
-}
-
-void
-rb_thread_start_timer()
-{
-}
-
-void
-rb_thread_stop_timer()
-{
-}
-#elif defined(HAVE_SETITIMER)
-static void
-catch_timer(sig)
- int sig;
-{
-#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
- signal(sig, catch_timer);
-#endif
- if (!rb_thread_critical) {
- rb_thread_pending = 1;
- }
- /* cause EINTR */
-}
-
-void
-rb_thread_start_timer()
-{
- struct itimerval tval;
-
- if (!thread_init) return;
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = 10000;
- tval.it_value = tval.it_interval;
- setitimer(ITIMER_VIRTUAL, &tval, NULL);
-}
-
-void
-rb_thread_stop_timer()
-{
- struct itimerval tval;
-
- if (!thread_init) return;
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = 0;
- tval.it_value = tval.it_interval;
- setitimer(ITIMER_VIRTUAL, &tval, NULL);
-}
-#else /* !(_THREAD_SAFE || HAVE_SETITIMER) */
-int rb_thread_tick = THREAD_TICK;
-#endif
-
-NORETURN(static void rb_thread_terminated _((rb_thread_t, int, enum thread_status)));
-static VALUE rb_thread_yield _((VALUE, rb_thread_t));
-
-static void
-push_thread_anchor(ip)
- struct ruby_env *ip;
-{
- ip->tag = prot_tag;
- ip->frame = ruby_frame;
- ip->block = ruby_block;
- ip->scope = ruby_scope;
- ip->iter = ruby_iter;
- ip->cref = ruby_cref;
- ip->prev = curr_thread->anchor;
- curr_thread->anchor = ip;
-}
-
-static void
-pop_thread_anchor(ip)
- struct ruby_env *ip;
-{
- curr_thread->anchor = ip->prev;
-}
-
-static void
-thread_insert(th)
- rb_thread_t th;
-{
- if (!th->next) {
- /* merge in thread list */
- th->prev = curr_thread;
- curr_thread->next->prev = th;
- th->next = curr_thread->next;
- curr_thread->next = th;
- th->priority = curr_thread->priority;
- th->thgroup = curr_thread->thgroup;
- }
-}
-
-static VALUE
-rb_thread_start_0(fn, arg, th)
- VALUE (*fn)();
- void *arg;
- rb_thread_t th;
-{
- volatile rb_thread_t th_save = th;
- volatile VALUE thread = th->thread;
- struct BLOCK *volatile saved_block = 0;
- enum thread_status status;
- int state;
-
- if (OBJ_FROZEN(curr_thread->thgroup)) {
- rb_raise(rb_eThreadError,
- "can't start a new thread (frozen ThreadGroup)");
- }
-
- if (!thread_init) {
- thread_init = 1;
-#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
-#if defined(POSIX_SIGNAL)
- posix_signal(SIGVTALRM, catch_timer);
-#else
- signal(SIGVTALRM, catch_timer);
-#endif
-
-#ifdef _THREAD_SAFE
- pthread_create(&time_thread, 0, thread_timer, 0);
-#else
- rb_thread_start_timer();
-#endif
-#endif
- }
-
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return thread;
- }
-
- if (fn == rb_thread_yield && curr_thread->anchor) {
- struct ruby_env *ip = curr_thread->anchor;
- new_thread.thread = th;
- new_thread.proc = rb_block_proc();
- new_thread.arg = (VALUE)arg;
- th->anchor = ip;
- thread_insert(th);
- curr_thread = th;
- longjmp((prot_tag = ip->tag)->buf, TAG_THREAD);
- }
-
- if (ruby_block) { /* should nail down higher blocks */
- struct BLOCK dummy;
-
- dummy.prev = ruby_block;
- blk_copy_prev(&dummy);
- saved_block = ruby_block = dummy.prev;
- }
- scope_dup(ruby_scope);
-
- thread_insert(th);
-
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- if (THREAD_SAVE_CONTEXT(th) == 0) {
- curr_thread = th;
- th->result = (*fn)(arg, th);
- }
- th = th_save;
- }
- else if (TAG_DST()) {
- th = th_save;
- th->result = prot_tag->retval;
- }
- POP_TAG();
- status = th->status;
-
- if (th == main_thread) ruby_stop(state);
- rb_thread_remove(th);
-
- if (saved_block) {
- blk_free(saved_block);
- }
-
- rb_thread_terminated(th, state, status);
- return 0; /* not reached */
-}
-
-static void
-rb_thread_terminated(th, state, status)
- rb_thread_t th;
- int state;
- enum thread_status status;
-{
- if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
- th->flags |= THREAD_RAISED;
- if (state == TAG_FATAL) {
- /* fatal error within this thread, need to stop whole script */
- main_thread->errinfo = ruby_errinfo;
- rb_thread_cleanup();
- }
- else if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
- if (th->safe >= 4) {
- char buf[32];
-
- sprintf(buf, "Insecure exit at level %d", th->safe);
- th->errinfo = rb_exc_new2(rb_eSecurityError, buf);
- }
- else {
- /* delegate exception to main_thread */
- rb_thread_main_jump(ruby_errinfo, RESTORE_RAISE);
- }
- }
- else if (th->safe < 4 && (ruby_thread_abort || th->abort || RTEST(ruby_debug))) {
- /* exit on main_thread */
- rb_thread_main_jump(ruby_errinfo, RESTORE_EXIT);
- }
- else {
- th->errinfo = ruby_errinfo;
- }
- }
- rb_thread_schedule();
- ruby_stop(0); /* last thread termination */
-}
-
-static VALUE
-rb_thread_yield_0(arg)
- VALUE arg;
-{
- return rb_thread_yield(arg, curr_thread);
-}
-
-static void
-rb_thread_start_1()
-{
- rb_thread_t th = new_thread.thread;
- volatile rb_thread_t th_save = th;
- VALUE proc = new_thread.proc;
- VALUE arg = new_thread.arg;
- struct ruby_env *ip = th->anchor;
- enum thread_status status;
- int state;
-
- ruby_frame = ip->frame;
- ruby_block = ip->block;
- ruby_scope = ip->scope;
- ruby_iter = ip->iter;
- ruby_cref = ip->cref;
- ruby_dyna_vars = ((struct BLOCK *)DATA_PTR(proc))->dyna_vars;
- PUSH_FRAME();
- *ruby_frame = *ip->frame;
- ruby_frame->prev = ip->frame;
- ruby_frame->iter = ITER_CUR;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- if (THREAD_SAVE_CONTEXT(th) == 0) {
- new_thread.thread = 0;
- th->result = rb_block_pass(rb_thread_yield_0, arg, proc);
- }
- th = th_save;
- }
- else if (TAG_DST()) {
- th = th_save;
- th->result = prot_tag->retval;
- }
- POP_TAG();
- POP_FRAME();
- status = th->status;
-
- if (th == main_thread) ruby_stop(state);
- rb_thread_remove(th);
- rb_thread_terminated(th, state, status);
-}
-
-VALUE
-rb_thread_create(fn, arg)
- VALUE (*fn)();
- void *arg;
-{
- Init_stack((VALUE*)&arg);
- return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
-}
-
-static VALUE
-rb_thread_yield(arg, th)
- VALUE arg;
- rb_thread_t th;
-{
- const ID *tbl;
-
- scope_dup(ruby_block->scope);
-
- tbl = ruby_scope->local_tbl;
- if (tbl) {
- int n = *tbl++;
- for (tbl += 2, n -= 2; n > 0; --n) { /* skip first 2 ($_ and $~) */
- ID id = *tbl++;
- if (id != 0 && !rb_is_local_id(id)) /* push flip states */
- rb_dvar_push(id, Qfalse);
- }
- }
- rb_dvar_push('_', Qnil);
- rb_dvar_push('~', Qnil);
- ruby_block->dyna_vars = ruby_dyna_vars;
-
- return rb_yield_0(arg, 0, 0, YIELD_LAMBDA_CALL, Qtrue);
-}
-
-/*
- * call-seq:
- * Thread.new([arg]*) {|args| block } => thread
- *
- * Creates and runs a new thread to execute the instructions given in
- * <i>block</i>. Any arguments passed to <code>Thread::new</code> are passed
- * into the block.
- *
- * x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
- * a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
- * x.join # Let the threads finish before
- * a.join # main thread exits...
- *
- * <em>produces:</em>
- *
- * abxyzc
- */
-
-static VALUE
-rb_thread_s_new(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- rb_thread_t th = rb_thread_alloc(klass);
- volatile VALUE *pos;
-
- pos = th->stk_pos;
- rb_obj_call_init(th->thread, argc, argv);
- if (th->stk_pos == 0) {
- rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
- rb_class2name(klass));
- }
-
- return th->thread;
-}
-
-
-/*
- * call-seq:
- * Thread.new([arg]*) {|args| block } => thread
- *
- * Creates and runs a new thread to execute the instructions given in
- * <i>block</i>. Any arguments passed to <code>Thread::new</code> are passed
- * into the block.
- *
- * x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
- * a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
- * x.join # Let the threads finish before
- * a.join # main thread exits...
- *
- * <em>produces:</em>
- *
- * abxyzc
- */
-
-static VALUE
-rb_thread_initialize(thread, args)
- VALUE thread, args;
-{
- rb_thread_t th;
-
- if (!rb_block_given_p()) {
- rb_raise(rb_eThreadError, "must be called with a block");
- }
- th = rb_thread_check(thread);
- if (th->stk_max) {
- NODE *node = th->node;
- if (!node) {
- rb_raise(rb_eThreadError, "already initialized thread");
- }
- rb_raise(rb_eThreadError, "already initialized thread - %s:%d",
- node->nd_file, nd_line(node));
- }
- return rb_thread_start_0(rb_thread_yield, args, th);
-}
-
-
-/*
- * call-seq:
- * Thread.start([args]*) {|args| block } => thread
- * Thread.fork([args]*) {|args| block } => thread
- *
- * Basically the same as <code>Thread::new</code>. However, if class
- * <code>Thread</code> is subclassed, then calling <code>start</code> in that
- * subclass will not invoke the subclass's <code>initialize</code> method.
- */
-
-static VALUE
-rb_thread_start(klass, args)
- VALUE klass, args;
-{
- if (!rb_block_given_p()) {
- rb_raise(rb_eThreadError, "must be called with a block");
- }
- return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(klass));
-}
-
-
-/*
- * call-seq:
- * thr.value => obj
- *
- * Waits for <i>thr</i> to complete (via <code>Thread#join</code>) and returns
- * its value.
- *
- * a = Thread.new { 2 + 2 }
- * a.value #=> 4
- */
-
-static VALUE
-rb_thread_value(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- while (!rb_thread_join(th, DELAY_INFTY));
-
- return th->result;
-}
-
-
-/*
- * call-seq:
- * thr.status => string, false or nil
- *
- * Returns the status of <i>thr</i>: ``<code>sleep</code>'' if <i>thr</i> is
- * sleeping or waiting on I/O, ``<code>run</code>'' if <i>thr</i> is executing,
- * ``<code>aborting</code>'' if <i>thr</i> is aborting, <code>false</code> if
- * <i>thr</i> terminated normally, and <code>nil</code> if <i>thr</i>
- * terminated with an exception.
- *
- * a = Thread.new { raise("die now") }
- * b = Thread.new { Thread.stop }
- * c = Thread.new { Thread.exit }
- * d = Thread.new { sleep }
- * Thread.critical = true
- * d.kill #=> #<Thread:0x401b3678 aborting>
- * a.status #=> nil
- * b.status #=> "sleep"
- * c.status #=> false
- * d.status #=> "aborting"
- * Thread.current.status #=> "run"
- */
-
-static VALUE
-rb_thread_status(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (rb_thread_dead(th)) {
- if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED))
- return Qnil;
- return Qfalse;
- }
-
- return rb_str_new2(thread_status_name(th->status));
-}
-
-
-/*
- * call-seq:
- * thr.alive? => true or false
- *
- * Returns <code>true</code> if <i>thr</i> is running or sleeping.
- *
- * thr = Thread.new { }
- * thr.join #=> #<Thread:0x401b3fb0 dead>
- * Thread.current.alive? #=> true
- * thr.alive? #=> false
- */
-
-static VALUE
-rb_thread_alive_p(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (rb_thread_dead(th)) return Qfalse;
- return Qtrue;
-}
-
-
-/*
- * call-seq:
- * thr.stop? => true or false
- *
- * Returns <code>true</code> if <i>thr</i> is dead or sleeping.
- *
- * a = Thread.new { Thread.stop }
- * b = Thread.current
- * a.stop? #=> true
- * b.stop? #=> false
- */
-
-static VALUE
-rb_thread_stop_p(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (rb_thread_dead(th)) return Qtrue;
- if (th->status == THREAD_STOPPED) return Qtrue;
- return Qfalse;
-}
-
-static void
-rb_thread_wait_other_threads()
-{
- rb_thread_t th;
- int found;
-
- /* wait other threads to terminate */
- while (curr_thread != curr_thread->next) {
- found = 0;
- FOREACH_THREAD(th) {
- if (th != curr_thread && th->status != THREAD_STOPPED) {
- found = 1;
- break;
- }
- }
- END_FOREACH(th);
- if (!found) return;
- rb_thread_schedule();
- }
-}
-
-static void
-rb_thread_cleanup()
-{
- rb_thread_t curr, th;
-
- curr = curr_thread;
- while (curr->status == THREAD_KILLED) {
- curr = curr->prev;
- }
-
- FOREACH_THREAD_FROM(curr, th) {
- if (th->status != THREAD_KILLED) {
- rb_thread_ready(th);
- if (th != main_thread) {
- th->thgroup = 0;
- th->priority = 0;
- th->status = THREAD_TO_KILL;
- RDATA(th->thread)->dfree = NULL;
- }
- }
- }
- END_FOREACH_FROM(curr, th);
-}
-
-int rb_thread_critical;
-
-
-/*
- * call-seq:
- * Thread.critical => true or false
- *
- * Returns the status of the global ``thread critical'' condition.
- */
-
-static VALUE
-rb_thread_critical_get()
-{
- return rb_thread_critical?Qtrue:Qfalse;
-}
-
-
-/*
- * call-seq:
- * Thread.critical= boolean => true or false
- *
- * Sets the status of the global ``thread critical'' condition and returns
- * it. When set to <code>true</code>, prohibits scheduling of any existing
- * thread. Does not block new threads from being created and run. Certain
- * thread operations (such as stopping or killing a thread, sleeping in the
- * current thread, and raising an exception) may cause a thread to be scheduled
- * even when in a critical section. <code>Thread::critical</code> is not
- * intended for daily use: it is primarily there to support folks writing
- * threading libraries.
- */
-
-static VALUE
-rb_thread_critical_set(obj, val)
- VALUE obj, val;
-{
- rb_thread_critical = RTEST(val);
- return val;
-}
-
-void
-rb_thread_interrupt()
-{
- rb_thread_critical = 0;
- rb_thread_ready(main_thread);
- if (curr_thread == main_thread) {
- rb_interrupt();
- }
- if (!rb_thread_dead(curr_thread)) {
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return;
- }
- }
- curr_thread = main_thread;
- rb_thread_restore_context(curr_thread, RESTORE_INTERRUPT);
-}
-
-void
-rb_thread_signal_raise(sig)
- char *sig;
-{
- if (sig == 0) return; /* should not happen */
- rb_thread_critical = 0;
- if (curr_thread == main_thread) {
- rb_thread_ready(curr_thread);
- rb_raise(rb_eSignal, "SIG%s", sig);
- }
- rb_thread_ready(main_thread);
- if (!rb_thread_dead(curr_thread)) {
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return;
- }
- }
- th_signm = sig;
- curr_thread = main_thread;
- rb_thread_restore_context(curr_thread, RESTORE_SIGNAL);
-}
-
-void
-rb_thread_trap_eval(cmd, sig, safe)
- VALUE cmd;
- int sig, safe;
-{
- rb_thread_critical = 0;
- if (curr_thread == main_thread) {
- rb_trap_eval(cmd, sig, safe);
- return;
- }
- if (!rb_thread_dead(curr_thread)) {
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return;
- }
- }
- th_cmd = cmd;
- th_sig = sig;
- th_safe = safe;
- curr_thread = main_thread;
- rb_thread_restore_context(curr_thread, RESTORE_TRAP);
-}
-
-static VALUE
-rb_thread_raise(argc, argv, th)
- int argc;
- VALUE *argv;
- rb_thread_t th;
-{
- volatile rb_thread_t th_save = th;
- VALUE exc;
-
- if (!th->next) {
- rb_raise(rb_eArgError, "unstarted thread");
- }
- if (rb_thread_dead(th)) return Qnil;
- exc = rb_make_exception(argc, argv);
- if (curr_thread == th) {
- rb_raise_jump(exc);
- }
-
- if (!rb_thread_dead(curr_thread)) {
- if (THREAD_SAVE_CONTEXT(curr_thread)) {
- return th_save->thread;
- }
- }
-
- rb_thread_ready(th);
- curr_thread = th;
-
- th_raise_exception = exc;
- th_raise_node = ruby_current_node;
- rb_thread_restore_context(curr_thread, RESTORE_RAISE);
- return Qnil; /* not reached */
-}
-
-
-/*
- * call-seq:
- * thr.raise(exception)
- *
- * Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
- * caller does not have to be <i>thr</i>.
- *
- * Thread.abort_on_exception = true
- * a = Thread.new { sleep(200) }
- * a.raise("Gotcha")
- *
- * <em>produces:</em>
- *
- * prog.rb:3: Gotcha (RuntimeError)
- * from prog.rb:2:in `initialize'
- * from prog.rb:2:in `new'
- * from prog.rb:2
- */
-
-static VALUE
-rb_thread_raise_m(argc, argv, thread)
- int argc;
- VALUE *argv;
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (ruby_safe_level > th->safe) {
- rb_secure(4);
- }
- rb_thread_raise(argc, argv, th);
- return Qnil; /* not reached */
-}
-
-VALUE
-rb_thread_local_aref(thread, id)
- VALUE thread;
- ID id;
-{
- rb_thread_t th;
- VALUE val;
-
- th = rb_thread_check(thread);
- if (ruby_safe_level >= 4 && th != curr_thread) {
- rb_raise(rb_eSecurityError, "Insecure: thread locals");
- }
- if (!th->locals) return Qnil;
- if (st_lookup(th->locals, id, &val)) {
- return val;
- }
- return Qnil;
-}
-
-
-/*
- * call-seq:
- * thr[sym] => obj or nil
- *
- * Attribute Reference---Returns the value of a thread-local variable, using
- * either a symbol or a string name. If the specified variable does not exist,
- * returns <code>nil</code>.
- *
- * a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
- * b = Thread.new { Thread.current[:name] = "B"; Thread.stop }
- * c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
- * Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
- *
- * <em>produces:</em>
- *
- * #<Thread:0x401b3b3c sleep>: C
- * #<Thread:0x401b3bc8 sleep>: B
- * #<Thread:0x401b3c68 sleep>: A
- * #<Thread:0x401bdf4c run>:
- */
-
-static VALUE
-rb_thread_aref(thread, id)
- VALUE thread, id;
-{
- return rb_thread_local_aref(thread, rb_to_id(id));
-}
-
-VALUE
-rb_thread_local_aset(thread, id, val)
- VALUE thread;
- ID id;
- VALUE val;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (ruby_safe_level >= 4 && th != curr_thread) {
- rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
- }
- if (OBJ_FROZEN(thread)) rb_error_frozen("thread locals");
-
- if (!th->locals) {
- th->locals = st_init_numtable();
- }
- if (NIL_P(val)) {
- st_delete(th->locals, (st_data_t*)&id, 0);
- return Qnil;
- }
- st_insert(th->locals, id, val);
-
- return val;
-}
-
-
-/*
- * call-seq:
- * thr[sym] = obj => obj
- *
- * Attribute Assignment---Sets or creates the value of a thread-local variable,
- * using either a symbol or a string. See also <code>Thread#[]</code>.
- */
-
-static VALUE
-rb_thread_aset(thread, id, val)
- VALUE thread, id, val;
-{
- return rb_thread_local_aset(thread, rb_to_id(id), val);
-}
-
-
-/*
- * call-seq:
- * thr.key?(sym) => true or false
- *
- * Returns <code>true</code> if the given string (or symbol) exists as a
- * thread-local variable.
- *
- * me = Thread.current
- * me[:oliver] = "a"
- * me.key?(:oliver) #=> true
- * me.key?(:stanley) #=> false
- */
-
-static VALUE
-rb_thread_key_p(thread, id)
- VALUE thread, id;
-{
- rb_thread_t th = rb_thread_check(thread);
-
- if (!th->locals) return Qfalse;
- if (st_lookup(th->locals, rb_to_id(id), 0))
- return Qtrue;
- return Qfalse;
-}
-
-static int
-thread_keys_i(key, value, ary)
- ID key;
- VALUE value, ary;
-{
- rb_ary_push(ary, ID2SYM(key));
- return ST_CONTINUE;
-}
-
-
-/*
- * call-seq:
- * thr.keys => array
- *
- * Returns an an array of the names of the thread-local variables (as Symbols).
- *
- * thr = Thread.new do
- * Thread.current[:cat] = 'meow'
- * Thread.current["dog"] = 'woof'
- * end
- * thr.join #=> #<Thread:0x401b3f10 dead>
- * thr.keys #=> [:dog, :cat]
- */
-
-static VALUE
-rb_thread_keys(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
- VALUE ary = rb_ary_new();
-
- if (th->locals) {
- st_foreach(th->locals, thread_keys_i, ary);
- }
- return ary;
-}
-
-/*
- * call-seq:
- * thr.inspect => string
- *
- * Dump the name, id, and status of _thr_ to a string.
- */
-
-static VALUE
-rb_thread_inspect(thread)
- VALUE thread;
-{
- char *cname = rb_obj_classname(thread);
- rb_thread_t th = rb_thread_check(thread);
- const char *status = thread_status_name(th->status);
- VALUE str;
-
- str = rb_str_new(0, strlen(cname)+7+16+9+1); /* 7:tags 16:addr 9:status 1:nul */
- sprintf(RSTRING(str)->ptr, "#<%s:0x%lx %s>", cname, thread, status);
- RSTRING(str)->len = strlen(RSTRING(str)->ptr);
- OBJ_INFECT(str, thread);
-
- return str;
-}
-
-void
-rb_thread_atfork()
-{
- rb_thread_t th;
-
- if (rb_thread_alone()) return;
- FOREACH_THREAD(th) {
- if (th != curr_thread) {
- rb_thread_die(th);
- }
- }
- END_FOREACH(th);
- main_thread = curr_thread;
- curr_thread->next = curr_thread;
- curr_thread->prev = curr_thread;
-}
-
-
-/*
- * Document-class: Continuation
- *
- * Continuation objects are generated by
- * <code>Kernel#callcc</code>. They hold a return address and execution
- * context, allowing a nonlocal return to the end of the
- * <code>callcc</code> block from anywhere within a program.
- * Continuations are somewhat analogous to a structured version of C's
- * <code>setjmp/longjmp</code> (although they contain more state, so
- * you might consider them closer to threads).
- *
- * For instance:
- *
- * arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
- * callcc{|$cc|}
- * puts(message = arr.shift)
- * $cc.call unless message =~ /Max/
- *
- * <em>produces:</em>
- *
- * Freddie
- * Herbie
- * Ron
- * Max
- *
- * This (somewhat contrived) example allows the inner loop to abandon
- * processing early:
- *
- * callcc {|cont|
- * for i in 0..4
- * print "\n#{i}: "
- * for j in i*5...(i+1)*5
- * cont.call() if j == 17
- * printf "%3d", j
- * end
- * end
- * }
- * print "\n"
- *
- * <em>produces:</em>
- *
- * 0: 0 1 2 3 4
- * 1: 5 6 7 8 9
- * 2: 10 11 12 13 14
- * 3: 15 16
- */
-
-static VALUE rb_cCont;
-
-/*
- * call-seq:
- * callcc {|cont| block } => obj
- *
- * Generates a <code>Continuation</code> object, which it passes to the
- * associated block. Performing a <em>cont</em><code>.call</code> will
- * cause the <code>callcc</code> to return (as will falling through the
- * end of the block). The value returned by the <code>callcc</code> is
- * the value of the block, or the value passed to
- * <em>cont</em><code>.call</code>. See class <code>Continuation</code>
- * for more details. Also see <code>Kernel::throw</code> for
- * an alternative mechanism for unwinding a call stack.
- */
-
-static VALUE
-rb_callcc(self)
- VALUE self;
-{
- volatile VALUE cont;
- rb_thread_t th;
- volatile rb_thread_t th_save;
- struct tag *tag;
- struct RVarmap *vars;
-
- THREAD_ALLOC(th);
- cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
-
- scope_dup(ruby_scope);
- for (tag=prot_tag; tag; tag=tag->prev) {
- scope_dup(tag->scope);
- }
- th->thread = curr_thread->thread;
- th->thgroup = cont_protect;
-
- for (vars = ruby_dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- th_save = th;
- if (THREAD_SAVE_CONTEXT(th)) {
- return th_save->result;
- }
- else {
- return rb_yield(cont);
- }
-}
-
-/*
- * call-seq:
- * cont.call(args, ...)
- * cont[args, ...]
- *
- * Invokes the continuation. The program continues from the end of the
- * <code>callcc</code> block. If no arguments are given, the original
- * <code>callcc</code> returns <code>nil</code>. If one argument is
- * given, <code>callcc</code> returns it. Otherwise, an array
- * containing <i>args</i> is returned.
- *
- * callcc {|cont| cont.call } #=> nil
- * callcc {|cont| cont.call 1 } #=> 1
- * callcc {|cont| cont.call 1, 2, 3 } #=> [1, 2, 3]
- */
-
-static VALUE
-rb_cont_call(argc, argv, cont)
- int argc;
- VALUE *argv;
- VALUE cont;
-{
- rb_thread_t th = rb_thread_check(cont);
-
- if (th->thread != curr_thread->thread) {
- rb_raise(rb_eRuntimeError, "continuation called across threads");
- }
- if (th->thgroup != cont_protect) {
- rb_raise(rb_eRuntimeError, "continuation called across trap");
- }
- switch (argc) {
- case 0:
- th->result = Qnil;
- break;
- case 1:
- th->result = argv[0];
- break;
- default:
- th->result = rb_ary_new4(argc, argv);
- break;
- }
-
- rb_thread_restore_context(th, RESTORE_NORMAL);
- return Qnil;
-}
-
-struct thgroup {
- int enclosed;
- VALUE group;
-};
-
-
-/*
- * Document-class: ThreadGroup
- *
- * <code>ThreadGroup</code> provides a means of keeping track of a number of
- * threads as a group. A <code>Thread</code> can belong to only one
- * <code>ThreadGroup</code> at a time; adding a thread to a new group will
- * remove it from any previous group.
- *
- * Newly created threads belong to the same group as the thread from which they
- * were created.
- */
-
-static VALUE thgroup_s_alloc _((VALUE));
-static VALUE
-thgroup_s_alloc(klass)
- VALUE klass;
-{
- VALUE group;
- struct thgroup *data;
-
- group = Data_Make_Struct(klass, struct thgroup, 0, free, data);
- data->enclosed = 0;
- data->group = group;
-
- return group;
-}
-
-
-/*
- * call-seq:
- * thgrp.list => array
- *
- * Returns an array of all existing <code>Thread</code> objects that belong to
- * this group.
- *
- * ThreadGroup::Default.list #=> [#<Thread:0x401bdf4c run>]
- */
-
-static VALUE
-thgroup_list(group)
- VALUE group;
-{
- struct thgroup *data;
- rb_thread_t th;
- VALUE ary;
-
- Data_Get_Struct(group, struct thgroup, data);
- ary = rb_ary_new();
-
- FOREACH_THREAD(th) {
- if (th->thgroup == data->group) {
- rb_ary_push(ary, th->thread);
- }
- }
- END_FOREACH(th);
-
- return ary;
-}
-
-
-/*
- * call-seq:
- * thgrp.enclose => thgrp
- *
- * Prevents threads from being added to or removed from the receiving
- * <code>ThreadGroup</code>. New threads can still be started in an enclosed
- * <code>ThreadGroup</code>.
- *
- * ThreadGroup::Default.enclose #=> #<ThreadGroup:0x4029d914>
- * thr = Thread::new { Thread.stop } #=> #<Thread:0x402a7210 sleep>
- * tg = ThreadGroup::new #=> #<ThreadGroup:0x402752d4>
- * tg.add thr
- *
- * <em>produces:</em>
- *
- * ThreadError: can't move from the enclosed thread group
- */
-
-VALUE
-thgroup_enclose(group)
- VALUE group;
-{
- struct thgroup *data;
-
- Data_Get_Struct(group, struct thgroup, data);
- data->enclosed = 1;
-
- return group;
-}
-
-
-/*
- * call-seq:
- * thgrp.enclosed? => true or false
- *
- * Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
- * ThreadGroup#enclose.
- */
-
-static VALUE
-thgroup_enclosed_p(group)
- VALUE group;
-{
- struct thgroup *data;
-
- Data_Get_Struct(group, struct thgroup, data);
- if (data->enclosed) return Qtrue;
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * thgrp.add(thread) => thgrp
- *
- * Adds the given <em>thread</em> to this group, removing it from any other
- * group to which it may have previously belonged.
- *
- * puts "Initial group is #{ThreadGroup::Default.list}"
- * tg = ThreadGroup.new
- * t1 = Thread.new { sleep }
- * t2 = Thread.new { sleep }
- * puts "t1 is #{t1}"
- * puts "t2 is #{t2}"
- * tg.add(t1)
- * puts "Initial group now #{ThreadGroup::Default.list}"
- * puts "tg group now #{tg.list}"
- *
- * <em>produces:</em>
- *
- * Initial group is #<Thread:0x401bdf4c>
- * t1 is #<Thread:0x401b3c90>
- * t2 is #<Thread:0x401b3c18>
- * Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
- * tg group now #<Thread:0x401b3c90>
- */
-
-static VALUE
-thgroup_add(group, thread)
- VALUE group, thread;
-{
- rb_thread_t th;
- struct thgroup *data;
-
- rb_secure(4);
- th = rb_thread_check(thread);
- if (!th->next || !th->prev) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
- rb_obj_classname(thread));
- }
-
- if (OBJ_FROZEN(group)) {
- rb_raise(rb_eThreadError, "can't move to the frozen thread group");
- }
- Data_Get_Struct(group, struct thgroup, data);
- if (data->enclosed) {
- rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
- }
-
- if (!th->thgroup) {
- return Qnil;
- }
- if (OBJ_FROZEN(th->thgroup)) {
- rb_raise(rb_eThreadError, "can't move from the frozen thread group");
- }
- Data_Get_Struct(th->thgroup, struct thgroup, data);
- if (data->enclosed) {
- rb_raise(rb_eThreadError, "can't move from the enclosed thread group");
- }
-
- th->thgroup = group;
- return group;
-}
-
-/* variables for recursive traversals */
-static ID recursive_key;
-static VALUE recursive_tbl;
-
-
-/*
- * +Thread+ encapsulates the behavior of a thread of
- * execution, including the main thread of the Ruby script.
- *
- * In the descriptions of the methods in this class, the parameter _sym_
- * refers to a symbol, which is either a quoted string or a
- * +Symbol+ (such as <code>:name</code>).
- */
-
-void
-Init_Thread()
-{
- VALUE cThGroup;
-
- rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
- rb_cThread = rb_define_class("Thread", rb_cObject);
- rb_undef_alloc_func(rb_cThread);
-
- rb_define_singleton_method(rb_cThread, "new", rb_thread_s_new, -1);
- rb_define_method(rb_cThread, "initialize", rb_thread_initialize, -2);
- rb_define_singleton_method(rb_cThread, "start", rb_thread_start, -2);
- rb_define_singleton_method(rb_cThread, "fork", rb_thread_start, -2);
-
- rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
- rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
- rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
- rb_define_singleton_method(rb_cThread, "pass", rb_thread_pass, 0);
- rb_define_singleton_method(rb_cThread, "current", rb_thread_current, 0);
- rb_define_singleton_method(rb_cThread, "main", rb_thread_main, 0);
- rb_define_singleton_method(rb_cThread, "list", rb_thread_list, 0);
-
- rb_define_singleton_method(rb_cThread, "critical", rb_thread_critical_get, 0);
- rb_define_singleton_method(rb_cThread, "critical=", rb_thread_critical_set, 1);
-
- rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
- rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
-
- rb_define_method(rb_cThread, "run", rb_thread_run, 0);
- rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
- rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
- rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
- rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
- rb_define_method(rb_cThread, "value", rb_thread_value, 0);
- rb_define_method(rb_cThread, "status", rb_thread_status, 0);
- rb_define_method(rb_cThread, "join", rb_thread_join_m, -1);
- rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
- rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
- rb_define_method(rb_cThread, "raise", rb_thread_raise_m, -1);
-
- rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
- rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
-
- rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
- rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
- rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
- rb_define_method(rb_cThread, "group", rb_thread_group, 0);
-
- rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
- rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
- rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
- rb_define_method(rb_cThread, "keys", rb_thread_keys, 0);
-
- rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
-
- rb_cCont = rb_define_class("Continuation", rb_cObject);
- rb_undef_alloc_func(rb_cCont);
- rb_undef_method(CLASS_OF(rb_cCont), "new");
- rb_define_method(rb_cCont, "call", rb_cont_call, -1);
- rb_define_method(rb_cCont, "[]", rb_cont_call, -1);
- rb_define_global_function("callcc", rb_callcc, 0);
- rb_global_variable(&cont_protect);
-
- cThGroup = rb_define_class("ThreadGroup", rb_cObject);
- rb_define_alloc_func(cThGroup, thgroup_s_alloc);
- rb_define_method(cThGroup, "list", thgroup_list, 0);
- rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
- rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
- rb_define_method(cThGroup, "add", thgroup_add, 1);
- thgroup_default = rb_obj_alloc(cThGroup);
- rb_define_const(cThGroup, "Default", thgroup_default);
- rb_global_variable(&thgroup_default);
-
- /* allocate main thread */
- main_thread = rb_thread_alloc(rb_cThread);
- curr_thread = main_thread->prev = main_thread->next = main_thread;
- recursive_key = rb_intern("__recursive_key__");
-}
-
-/*
- * call-seq:
- * catch(symbol) {| | block } > obj
- *
- * +catch+ executes its block. If a +throw+ is
- * executed, Ruby searches up its stack for a +catch+ block
- * with a tag corresponding to the +throw+'s
- * _symbol_. If found, that block is terminated, and
- * +catch+ returns the value given to +throw+. If
- * +throw+ is not called, the block terminates normally, and
- * the value of +catch+ is the value of the last expression
- * evaluated. +catch+ expressions may be nested, and the
- * +throw+ call need not be in lexical scope.
- *
- * def routine(n)
- * puts n
- * throw :done if n <= 0
- * routine(n-1)
- * end
- *
- *
- * catch(:done) { routine(3) }
- *
- * <em>produces:</em>
- *
- * 3
- * 2
- * 1
- * 0
- */
-
-static VALUE
-rb_f_catch(dmy, tag)
- VALUE dmy, tag;
-{
- int state;
- VALUE val = Qnil; /* OK */
-
- tag = ID2SYM(rb_to_id(tag));
- PUSH_TAG(tag);
- if ((state = EXEC_TAG()) == 0) {
- val = rb_yield_0(tag, 0, 0, 0, Qfalse);
- }
- else if (state == TAG_THROW && tag == prot_tag->dst) {
- val = prot_tag->retval;
- state = 0;
- }
- POP_TAG();
- if (state) JUMP_TAG(state);
-
- return val;
-}
-
-static VALUE
-catch_i(tag)
- VALUE tag;
-{
- return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
-}
-
-VALUE
-rb_catch(tag, func, data)
- const char *tag;
- VALUE (*func)();
- VALUE data;
-{
- return rb_iterate((VALUE(*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)), func, data);
-}
-
-/*
- * call-seq:
- * throw(symbol [, obj])
- *
- * Transfers control to the end of the active +catch+ block
- * waiting for _symbol_. Raises +NameError+ if there
- * is no +catch+ block for the symbol. The optional second
- * parameter supplies a return value for the +catch+ block,
- * which otherwise defaults to +nil+. For examples, see
- * <code>Kernel::catch</code>.
- */
-
-static VALUE
-rb_f_throw(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE tag, value;
- struct tag *tt = prot_tag;
-
- rb_scan_args(argc, argv, "11", &tag, &value);
- tag = ID2SYM(rb_to_id(tag));
-
- while (tt) {
- if (tt->tag == tag) {
- tt->dst = tag;
- tt->retval = value;
- break;
- }
- if (tt->tag == PROT_THREAD) {
- rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%lx",
- rb_id2name(SYM2ID(tag)),
- curr_thread);
- }
- tt = tt->prev;
- }
- if (!tt) {
- rb_name_error(SYM2ID(tag), "uncaught throw `%s'", rb_id2name(SYM2ID(tag)));
- }
- rb_trap_restore_mask();
- JUMP_TAG(TAG_THROW);
-#ifndef __GNUC__
- return Qnil; /* not reached */
-#endif
-}
-
-void
-rb_throw(tag, val)
- const char *tag;
- VALUE val;
-{
- VALUE argv[2];
-
- argv[0] = ID2SYM(rb_intern(tag));
- argv[1] = val;
- rb_f_throw(2, argv);
-}
-
-static VALUE
-recursive_check(obj)
- VALUE obj;
-{
- VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
-
- if (NIL_P(hash) || TYPE(hash) != T_HASH) {
- return Qfalse;
- }
- else {
- VALUE list = rb_hash_aref(hash, ID2SYM(ruby_frame->this_func));
-
- if (NIL_P(list) || TYPE(list) != T_ARRAY) return Qfalse;
- return rb_ary_includes(list, rb_obj_id(obj));
- }
-}
-
-static void
-recursive_push(obj)
- VALUE obj;
-{
- VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
- VALUE list, sym;
-
- sym = ID2SYM(ruby_frame->this_func);
- if (NIL_P(hash) || TYPE(hash) != T_HASH) {
- hash = rb_hash_new();
- rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
- list = Qnil;
- }
- else {
- list = rb_hash_aref(hash, sym);
- }
- if (NIL_P(list) || TYPE(list) != T_ARRAY) {
- list = rb_ary_new();
- rb_hash_aset(hash, sym, list);
- }
- rb_ary_push(list, rb_obj_id(obj));
-}
-
-static void
-recursive_pop()
-{
- VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
- VALUE list, sym;
-
- sym = ID2SYM(ruby_frame->this_func);
- if (NIL_P(hash) || TYPE(hash) != T_HASH) {
- VALUE symname = rb_inspect(sym);
- VALUE thrname = rb_inspect(rb_thread_current());
- rb_raise(rb_eTypeError, "invalid inspect_tbl hash for %s in %s",
- StringValuePtr(symname), StringValuePtr(thrname));
- }
- list = rb_hash_aref(hash, sym);
- if (NIL_P(list) || TYPE(list) != T_ARRAY) {
- VALUE symname = rb_inspect(sym);
- VALUE thrname = rb_inspect(rb_thread_current());
- rb_raise(rb_eTypeError, "invalid inspect_tbl list for %s in %s",
- StringValuePtr(symname), StringValuePtr(thrname));
- }
- rb_ary_pop(list);
-}
-
-VALUE
-rb_exec_recursive(func, obj, arg)
- VALUE (*func)(ANYARGS); /* VALUE obj, VALUE arg, int flag */
- VALUE obj, arg;
-{
- if (recursive_check(obj)) {
- return (*func)(obj, arg, Qtrue);
- }
- else {
- VALUE result;
- int state;
-
- recursive_push(obj);
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = (*func)(obj, arg, Qfalse);
- }
- POP_TAG();
- recursive_pop();
- if (state) JUMP_TAG(state);
- return result;
- }
-}
-/**********************************************************************
-
- file.c -
-
- $Author: murphy $
- $Date: 2005-11-05 04:33:55 +0100 (Sa, 05 Nov 2005) $
- created at: Mon Nov 15 12:24:34 JST 1993
-
- Copyright (C) 1993-2003 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#ifdef _WIN32
-#include "missing/file.h"
-#endif
-
-#include "ruby.h"
-#include "rubyio.h"
-#include "rubysig.h"
-#include "util.h"
-#include "dln.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_FILE_H
-# include <sys/file.h>
-#else
-int flock _((int, int));
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
-#include <time.h>
-
-VALUE rb_time_new _((time_t, time_t));
-
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#elif defined HAVE_SYS_UTIME_H
-#include <sys/utime.h>
-#endif
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-#ifndef HAVE_STRING_H
-char *strrchr _((const char*,const char));
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
-#endif
-
-#if !defined HAVE_LSTAT && !defined lstat
-#define lstat stat
-#endif
-
-VALUE rb_cFile;
-VALUE rb_mFileTest;
-static VALUE rb_cStat;
-
-VALUE
-rb_get_path(obj)
- VALUE obj;
-{
- VALUE tmp;
- static ID to_path;
-
- rb_check_safe_obj(obj);
- tmp = rb_check_string_type(obj);
- if (!NIL_P(tmp)) goto exit;
-
- if (!to_path) {
- to_path = rb_intern("to_path");
- }
- if (rb_respond_to(obj, to_path)) {
- obj = rb_funcall(obj, to_path, 0, 0);
- }
- tmp = rb_str_to_str(obj);
- exit:
- if (obj != tmp) {
- rb_check_safe_obj(tmp);
- }
- return tmp;
-}
-
-static long
-apply2files(func, vargs, arg)
- void (*func)();
- VALUE vargs;
- void *arg;
-{
- long i;
- VALUE path;
- struct RArray *args = RARRAY(vargs);
-
- rb_secure(4);
- for (i=0; i<args->len; i++) {
- path = rb_get_path(args->ptr[i]);
- (*func)(StringValueCStr(path), arg);
- }
-
- return args->len;
-}
-
-/*
- * call-seq:
- * file.path -> filename
- *
- * Returns the pathname used to create <i>file</i> as a string. Does
- * not normalize the name.
- *
- * File.new("testfile").path #=> "testfile"
- * File.new("/tmp/../tmp/xxx", "w").path #=> "/tmp/../tmp/xxx"
- *
- */
-
-static VALUE
-rb_file_path(obj)
- VALUE obj;
-{
- OpenFile *fptr;
-
- fptr = RFILE(rb_io_taint_check(obj))->fptr;
- rb_io_check_initialized(fptr);
- if (!fptr->path) return Qnil;
- return rb_tainted_str_new2(fptr->path);
-}
-
-static VALUE
-stat_new_0(klass, st)
- VALUE klass;
- struct stat *st;
-{
- struct stat *nst = 0;
-
- if (st) {
- nst = ALLOC(struct stat);
- *nst = *st;
- }
- return Data_Wrap_Struct(klass, NULL, free, nst);
-}
-
-static VALUE
-stat_new(st)
- struct stat *st;
-{
- return stat_new_0(rb_cStat, st);
-}
-
-static struct stat*
-get_stat(self)
- VALUE self;
-{
- struct stat* st;
- Data_Get_Struct(self, struct stat, st);
- if (!st) rb_raise(rb_eTypeError, "uninitialized File::Stat");
- return st;
-}
-
-/*
- * call-seq:
- * stat <=> other_stat => -1, 0, 1
- *
- * Compares <code>File::Stat</code> objects by comparing their
- * respective modification times.
- *
- * f1 = File.new("f1", "w")
- * sleep 1
- * f2 = File.new("f2", "w")
- * f1.stat <=> f2.stat #=> -1
- */
-
-static VALUE
-rb_stat_cmp(self, other)
- VALUE self, other;
-{
- if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
- time_t t1 = get_stat(self)->st_mtime;
- time_t t2 = get_stat(other)->st_mtime;
- if (t1 == t2)
- return INT2FIX(0);
- else if (t1 < t2)
- return INT2FIX(-1);
- else
- return INT2FIX(1);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * stat.dev => fixnum
- *
- * Returns an integer representing the device on which <i>stat</i>
- * resides.
- *
- * File.stat("testfile").dev #=> 774
- */
-
-static VALUE
-rb_stat_dev(self)
- VALUE self;
-{
- return INT2NUM(get_stat(self)->st_dev);
-}
-
-/*
- * call-seq:
- * stat.dev_major => fixnum
- *
- * Returns the major part of <code>File_Stat#dev</code> or
- * <code>nil</code>.
- *
- * File.stat("/dev/fd1").dev_major #=> 2
- * File.stat("/dev/tty").dev_major #=> 5
- */
-
-static VALUE
-rb_stat_dev_major(self)
- VALUE self;
-{
-#if defined(major)
- long dev = get_stat(self)->st_dev;
- return ULONG2NUM(major(dev));
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * stat.dev_minor => fixnum
- *
- * Returns the minor part of <code>File_Stat#dev</code> or
- * <code>nil</code>.
- *
- * File.stat("/dev/fd1").dev_minor #=> 1
- * File.stat("/dev/tty").dev_minor #=> 0
- */
-
-static VALUE
-rb_stat_dev_minor(self)
- VALUE self;
-{
-#if defined(minor)
- long dev = get_stat(self)->st_dev;
- return ULONG2NUM(minor(dev));
-#else
- return Qnil;
-#endif
-}
-
-
-/*
- * call-seq:
- * stat.ino => fixnum
- *
- * Returns the inode number for <i>stat</i>.
- *
- * File.stat("testfile").ino #=> 1083669
- *
- */
-
-static VALUE
-rb_stat_ino(self)
- VALUE self;
-{
-#ifdef HUGE_ST_INO
- return ULL2NUM(get_stat(self)->st_ino);
-#else
- return ULONG2NUM(get_stat(self)->st_ino);
-#endif
-}
-
-/*
- * call-seq:
- * stat.mode => fixnum
- *
- * Returns an integer representing the permission bits of
- * <i>stat</i>. The meaning of the bits is platform dependent; on
- * Unix systems, see <code>stat(2)</code>.
- *
- * File.chmod(0644, "testfile") #=> 1
- * s = File.stat("testfile")
- * sprintf("%o", s.mode) #=> "100644"
- */
-
-static VALUE
-rb_stat_mode(self)
- VALUE self;
-{
-#ifdef __BORLANDC__
- return UINT2NUM((unsigned short)(get_stat(self)->st_mode));
-#else
- return UINT2NUM(get_stat(self)->st_mode);
-#endif
-}
-
-/*
- * call-seq:
- * stat.nlink => fixnum
- *
- * Returns the number of hard links to <i>stat</i>.
- *
- * File.stat("testfile").nlink #=> 1
- * File.link("testfile", "testfile.bak") #=> 0
- * File.stat("testfile").nlink #=> 2
- *
- */
-
-static VALUE
-rb_stat_nlink(self)
- VALUE self;
-{
- return UINT2NUM(get_stat(self)->st_nlink);
-}
-
-
-/*
- * call-seq:
- * stat.uid => fixnum
- *
- * Returns the numeric user id of the owner of <i>stat</i>.
- *
- * File.stat("testfile").uid #=> 501
- *
- */
-
-static VALUE
-rb_stat_uid(self)
- VALUE self;
-{
- return UINT2NUM(get_stat(self)->st_uid);
-}
-
-/*
- * call-seq:
- * stat.gid => fixnum
- *
- * Returns the numeric group id of the owner of <i>stat</i>.
- *
- * File.stat("testfile").gid #=> 500
- *
- */
-
-static VALUE
-rb_stat_gid(self)
- VALUE self;
-{
- return UINT2NUM(get_stat(self)->st_gid);
-}
-
-
-/*
- * call-seq:
- * stat.rdev => fixnum or nil
- *
- * Returns an integer representing the device type on which
- * <i>stat</i> resides. Returns <code>nil</code> if the operating
- * system doesn't support this feature.
- *
- * File.stat("/dev/fd1").rdev #=> 513
- * File.stat("/dev/tty").rdev #=> 1280
- */
-
-static VALUE
-rb_stat_rdev(self)
- VALUE self;
-{
-#ifdef HAVE_ST_RDEV
- return ULONG2NUM(get_stat(self)->st_rdev);
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * stat.rdev_major => fixnum
- *
- * Returns the major part of <code>File_Stat#rdev</code> or
- * <code>nil</code>.
- *
- * File.stat("/dev/fd1").rdev_major #=> 2
- * File.stat("/dev/tty").rdev_major #=> 5
- */
-
-static VALUE
-rb_stat_rdev_major(self)
- VALUE self;
-{
-#if defined(HAVE_ST_RDEV) && defined(major)
- long rdev = get_stat(self)->st_rdev;
- return ULONG2NUM(major(rdev));
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * stat.rdev_minor => fixnum
- *
- * Returns the minor part of <code>File_Stat#rdev</code> or
- * <code>nil</code>.
- *
- * File.stat("/dev/fd1").rdev_minor #=> 1
- * File.stat("/dev/tty").rdev_minor #=> 0
- */
-
-static VALUE
-rb_stat_rdev_minor(self)
- VALUE self;
-{
-#if defined(HAVE_ST_RDEV) && defined(minor)
- long rdev = get_stat(self)->st_rdev;
- return ULONG2NUM(minor(rdev));
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * stat.size => fixnum
- *
- * Returns the size of <i>stat</i> in bytes.
- *
- * File.stat("testfile").size #=> 66
- */
-
-static VALUE
-rb_stat_size(self)
- VALUE self;
-{
- return OFFT2NUM(get_stat(self)->st_size);
-}
-
-/*
- * call-seq:
- * stat.blksize => integer or nil
- *
- * Returns the native file system's block size. Will return <code>nil</code>
- * on platforms that don't support this information.
- *
- * File.stat("testfile").blksize #=> 4096
- *
- */
-
-static VALUE
-rb_stat_blksize(self)
- VALUE self;
-{
-#ifdef HAVE_ST_BLKSIZE
- return ULONG2NUM(get_stat(self)->st_blksize);
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * stat.blocks => integer or nil
- *
- * Returns the number of native file system blocks allocated for this
- * file, or <code>nil</code> if the operating system doesn't
- * support this feature.
- *
- * File.stat("testfile").blocks #=> 2
- */
-
-static VALUE
-rb_stat_blocks(self)
- VALUE self;
-{
-#ifdef HAVE_ST_BLOCKS
- return ULONG2NUM(get_stat(self)->st_blocks);
-#else
- return Qnil;
-#endif
-}
-
-
-/*
- * call-seq:
- * stat.atime => time
- *
- * Returns the last access time for this file as an object of class
- * <code>Time</code>.
- *
- * File.stat("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
- *
- */
-
-static VALUE
-rb_stat_atime(self)
- VALUE self;
-{
- return rb_time_new(get_stat(self)->st_atime, 0);
-}
-
-/*
- * call-seq:
- * stat.mtime -> aTime
- *
- * Returns the modification time of <i>stat</i>.
- *
- * File.stat("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
- *
- */
-
-static VALUE
-rb_stat_mtime(self)
- VALUE self;
-{
- return rb_time_new(get_stat(self)->st_mtime, 0);
-}
-
-/*
- * call-seq:
- * stat.ctime -> aTime
- *
- * Returns the change time for <i>stat</i> (that is, the time
- * directory information about the file was changed, not the file
- * itself).
- *
- * File.stat("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
- *
- */
-
-static VALUE
-rb_stat_ctime(self)
- VALUE self;
-{
- return rb_time_new(get_stat(self)->st_ctime, 0);
-}
-
-/*
- * call-seq:
- * stat.inspect => string
- *
- * Produce a nicely formatted description of <i>stat</i>.
- *
- * File.stat("/etc/passwd").inspect
- * #=> "#<File::Stat dev=0xe000005, ino=1078078, mode=0100644,
- * nlink=1, uid=0, gid=0, rdev=0x0, size=1374, blksize=4096,
- * blocks=8, atime=Wed Dec 10 10:16:12 CST 2003,
- * mtime=Fri Sep 12 15:41:41 CDT 2003,
- * ctime=Mon Oct 27 11:20:27 CST 2003>"
- */
-
-static VALUE
-rb_stat_inspect(self)
- VALUE self;
-{
- VALUE str;
- int i;
- static struct {
- char *name;
- VALUE (*func)();
- } member[] = {
- {"dev", rb_stat_dev},
- {"ino", rb_stat_ino},
- {"mode", rb_stat_mode},
- {"nlink", rb_stat_nlink},
- {"uid", rb_stat_uid},
- {"gid", rb_stat_gid},
- {"rdev", rb_stat_rdev},
- {"size", rb_stat_size},
- {"blksize", rb_stat_blksize},
- {"blocks", rb_stat_blocks},
- {"atime", rb_stat_atime},
- {"mtime", rb_stat_mtime},
- {"ctime", rb_stat_ctime},
- };
-
- str = rb_str_buf_new2("#<");
- rb_str_buf_cat2(str, rb_obj_classname(self));
- rb_str_buf_cat2(str, " ");
-
- for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
- VALUE v;
-
- if (i > 0) {
- rb_str_buf_cat2(str, ", ");
- }
- rb_str_buf_cat2(str, member[i].name);
- rb_str_buf_cat2(str, "=");
- v = (*member[i].func)(self);
- if (i == 2) { /* mode */
- char buf[32];
-
- sprintf(buf, "0%lo", NUM2ULONG(v));
- rb_str_buf_cat2(str, buf);
- }
- else if (i == 0 || i == 6) { /* dev/rdev */
- char buf[32];
-
- sprintf(buf, "0x%lx", NUM2ULONG(v));
- rb_str_buf_cat2(str, buf);
- }
- else {
- rb_str_append(str, rb_inspect(v));
- }
- }
- rb_str_buf_cat2(str, ">");
- OBJ_INFECT(str, self);
-
- return str;
-}
-
-static int
-rb_stat(file, st)
- VALUE file;
- struct stat *st;
-{
- VALUE tmp;
-
- rb_secure(2);
- tmp = rb_check_convert_type(file, T_FILE, "IO", "to_io");
- if (!NIL_P(tmp)) {
- OpenFile *fptr;
-
- GetOpenFile(tmp, fptr);
- return fstat(fptr->fd, st);
- }
- FilePathValue(file);
- return stat(StringValueCStr(file), st);
-}
-
-/*
- * call-seq:
- * File.stat(file_name) => stat
- *
- * Returns a <code>File::Stat</code> object for the named file (see
- * <code>File::Stat</code>).
- *
- * File.stat("testfile").mtime #=> Tue Apr 08 12:58:04 CDT 2003
- *
- */
-
-static VALUE
-rb_file_s_stat(klass, fname)
- VALUE klass, fname;
-{
- struct stat st;
-
- rb_secure(4);
- FilePathValue(fname);
- if (rb_stat(fname, &st) < 0) {
- rb_sys_fail(StringValueCStr(fname));
- }
- return stat_new(&st);
-}
-
-/*
- * call-seq:
- * ios.stat => stat
- *
- * Returns status information for <em>ios</em> as an object of type
- * <code>File::Stat</code>.
- *
- * f = File.new("testfile")
- * s = f.stat
- * "%o" % s.mode #=> "100644"
- * s.blksize #=> 4096
- * s.atime #=> Wed Apr 09 08:53:54 CDT 2003
- *
- */
-
-static VALUE
-rb_io_stat(obj)
- VALUE obj;
-{
- OpenFile *fptr;
- struct stat st;
-
- GetOpenFile(obj, fptr);
- if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail(fptr->path);
- }
- return stat_new(&st);
-}
-
-/*
- * call-seq:
- * File.lstat(file_name) => stat
- *
- * Same as <code>File::stat</code>, but does not follow the last symbolic
- * link. Instead, reports on the link itself.
- *
- * File.symlink("testfile", "link2test") #=> 0
- * File.stat("testfile").size #=> 66
- * File.lstat("link2test").size #=> 8
- * File.stat("link2test").size #=> 66
- *
- */
-
-static VALUE
-rb_file_s_lstat(klass, fname)
- VALUE klass, fname;
-{
-#ifdef HAVE_LSTAT
- struct stat st;
-
- rb_secure(2);
- FilePathValue(fname);
- if (lstat(StringValueCStr(fname), &st) == -1) {
- rb_sys_fail(RSTRING(fname)->ptr);
- }
- return stat_new(&st);
-#else
- return rb_file_s_stat(klass, fname);
-#endif
-}
-
-
-/*
- * call-seq:
- * file.lstat => stat
- *
- * Same as <code>IO#stat</code>, but does not follow the last symbolic
- * link. Instead, reports on the link itself.
- *
- * File.symlink("testfile", "link2test") #=> 0
- * File.stat("testfile").size #=> 66
- * f = File.new("link2test")
- * f.lstat.size #=> 8
- * f.stat.size #=> 66
- */
-
-static VALUE
-rb_file_lstat(obj)
- VALUE obj;
-{
-#ifdef HAVE_LSTAT
- OpenFile *fptr;
- struct stat st;
-
- rb_secure(2);
- GetOpenFile(obj, fptr);
- if (!fptr->path) return Qnil;
- if (lstat(fptr->path, &st) == -1) {
- rb_sys_fail(fptr->path);
- }
- return stat_new(&st);
-#else
- return rb_io_stat(obj);
-#endif
-}
-
-static int
-group_member(gid)
- GETGROUPS_T gid;
-{
-#ifndef _WIN32
- if (getgid() == gid)
- return Qtrue;
-
-# ifdef HAVE_GETGROUPS
-# ifndef NGROUPS
-# ifdef NGROUPS_MAX
-# define NGROUPS NGROUPS_MAX
-# else
-# define NGROUPS 32
-# endif
-# endif
- {
- GETGROUPS_T gary[NGROUPS];
- int anum;
-
- anum = getgroups(NGROUPS, gary);
- while (--anum >= 0)
- if (gary[anum] == gid)
- return Qtrue;
- }
-# endif
-#endif
- return Qfalse;
-}
-
-#ifndef S_IXUGO
-# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
-#endif
-
-int
-eaccess(path, mode)
- const char *path;
- int mode;
-{
-#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
- struct stat st;
- int euid;
-
- if (stat(path, &st) < 0) return -1;
-
- euid = geteuid();
-
- if (euid == 0) {
- /* Root can read or write any file. */
- if (!(mode & X_OK))
- return 0;
-
- /* Root can execute any file that has any one of the execute
- bits set. */
- if (st.st_mode & S_IXUGO)
- return 0;
-
- return -1;
- }
-
- if (st.st_uid == euid) /* owner */
- mode <<= 6;
- else if (getegid() == st.st_gid || group_member(st.st_gid))
- mode <<= 3;
-
- if ((st.st_mode & mode) == mode) return 0;
-
- return -1;
-#else
-# if _MSC_VER >= 1400
- mode &= 6;
-# endif
- return access(path, mode);
-#endif
-}
-
-
-/*
- * Document-class: FileTest
- *
- * <code>FileTest</code> implements file test operations similar to
- * those used in <code>File::Stat</code>. It exists as a standalone
- * module, and its methods are also insinuated into the <code>File</code>
- * class. (Note that this is not done by inclusion: the interpreter cheats).
- *
- */
-
-
-/*
- * call-seq:
- * File.directory?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a directory,
- * <code>false</code> otherwise.
- *
- * File.directory?(".")
- */
-
-static VALUE
-test_d(obj, fname)
- VALUE obj, fname;
-{
-#ifndef S_ISDIR
-# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
-#endif
-
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISDIR(st.st_mode)) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.pipe?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a pipe.
- */
-
-static VALUE
-test_p(obj, fname)
- VALUE obj, fname;
-{
-#ifdef S_IFIFO
-# ifndef S_ISFIFO
-# define S_ISFIFO(m) ((m & S_IFMT) == S_IFIFO)
-# endif
-
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISFIFO(st.st_mode)) return Qtrue;
-
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.symlink?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a symbolic link.
- */
-
-static VALUE
-test_l(obj, fname)
- VALUE obj, fname;
-{
-#ifndef S_ISLNK
-# ifdef _S_ISLNK
-# define S_ISLNK(m) _S_ISLNK(m)
-# else
-# ifdef _S_IFLNK
-# define S_ISLNK(m) ((m & S_IFMT) == _S_IFLNK)
-# else
-# ifdef S_IFLNK
-# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
-# endif
-# endif
-# endif
-#endif
-
-#ifdef S_ISLNK
- struct stat st;
-
- rb_secure(2);
- FilePathValue(fname);
- if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
- if (S_ISLNK(st.st_mode)) return Qtrue;
-#endif
-
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.socket?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a socket.
- */
-
-static VALUE
-test_S(obj, fname)
- VALUE obj, fname;
-{
-#ifndef S_ISSOCK
-# ifdef _S_ISSOCK
-# define S_ISSOCK(m) _S_ISSOCK(m)
-# else
-# ifdef _S_IFSOCK
-# define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
-# else
-# ifdef S_IFSOCK
-# define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
-# endif
-# endif
-# endif
-#endif
-
-#ifdef S_ISSOCK
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISSOCK(st.st_mode)) return Qtrue;
-
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.blockdev?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a block device.
- */
-
-static VALUE
-test_b(obj, fname)
- VALUE obj, fname;
-{
-#ifndef S_ISBLK
-# ifdef S_IFBLK
-# define S_ISBLK(m) ((m & S_IFMT) == S_IFBLK)
-# else
-# define S_ISBLK(m) (0) /* anytime false */
-# endif
-#endif
-
-#ifdef S_ISBLK
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISBLK(st.st_mode)) return Qtrue;
-
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.chardev?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a character device.
- */
-static VALUE
-test_c(obj, fname)
- VALUE obj, fname;
-{
-#ifndef S_ISCHR
-# define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR)
-#endif
-
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISCHR(st.st_mode)) return Qtrue;
-
- return Qfalse;
-}
-
-
-/*
- * call-seq:
- * File.exist?(file_name) => true or false
- * File.exists?(file_name) => true or false (obsolete)
- *
- * Return <code>true</code> if the named file exists.
- */
-
-static VALUE
-test_e(obj, fname)
- VALUE obj, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * File.readable?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is readable by the effective
- * user id of this process.
- */
-
-static VALUE
-test_r(obj, fname)
- VALUE obj, fname;
-{
- rb_secure(2);
- FilePathValue(fname);
- if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * File.readable_real?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is readable by the real
- * user id of this process.
- */
-
-static VALUE
-test_R(obj, fname)
- VALUE obj, fname;
-{
- rb_secure(2);
- FilePathValue(fname);
- if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
- return Qtrue;
-}
-
-#ifndef S_IRUGO
-# define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
-#endif
-
-#ifndef S_IWUGO
-# define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
-#endif
-
-/*
- * call-seq:
- * File.world_readable?(file_name) => fixnum or nil
- *
- * If <i>file_name</i> is readable by others, returns an integer
- * representing the file permission bits of <i>file_name</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *
- * File.world_readable?("/etc/passwd") # => 420
- * m = File.world_readable?("/etc/passwd")
- * sprintf("%o", m) # => "644"
- */
-
-static VALUE
-test_wr(obj, fname)
- VALUE obj, fname;
-{
-#ifdef S_IROTH
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qnil;
- if ((st.st_mode & (S_IROTH)) == S_IROTH) {
- return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
- }
-#endif
- return Qnil;
-}
-
-/*
- * call-seq:
- * File.writable?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is writable by the effective
- * user id of this process.
- */
-
-static VALUE
-test_w(obj, fname)
- VALUE obj, fname;
-{
- rb_secure(2);
- FilePathValue(fname);
- if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * File.writable_real?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is writable by the real
- * user id of this process.
- */
-
-static VALUE
-test_W(obj, fname)
- VALUE obj, fname;
-{
- rb_secure(2);
- FilePathValue(fname);
- if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * File.world_writable?(file_name) => fixnum or nil
- *
- * If <i>file_name</i> is writable by others, returns an integer
- * representing the file permission bits of <i>file_name</i>. Returns
- * <code>nil</code> otherwise. The meaning of the bits is platform
- * dependent; on Unix systems, see <code>stat(2)</code>.
- *
- * File.world_writable?("/tmp") #=> 511
- * m = File.world_writable?("/tmp")
- * sprintf("%o", m) #=> "777"
- */
-
-static VALUE
-test_ww(obj, fname)
- VALUE obj, fname;
-{
-#ifdef S_IWOTH
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if ((st.st_mode & (S_IWOTH)) == S_IWOTH) {
- return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
- }
-#endif
- return Qnil;
-}
-
-/*
- * call-seq:
- * File.executable?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is executable by the effective
- * user id of this process.
- */
-
-static VALUE
-test_x(obj, fname)
- VALUE obj, fname;
-{
- rb_secure(2);
- FilePathValue(fname);
- if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
- return Qtrue;
-}
-
-/*
- * call-seq:
- * File.executable_real?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is executable by the real
- * user id of this process.
- */
-
-static VALUE
-test_X(obj, fname)
- VALUE obj, fname;
-{
- rb_secure(2);
- FilePathValue(fname);
- if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
- return Qtrue;
-}
-
-#ifndef S_ISREG
-# define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
-#endif
-
-/*
- * call-seq:
- * File.file?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file exists and is a
- * regular file.
- */
-
-static VALUE
-test_f(obj, fname)
- VALUE obj, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (S_ISREG(st.st_mode)) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.zero?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file exists and has
- * a zero size.
- */
-
-static VALUE
-test_z(obj, fname)
- VALUE obj, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_size == 0) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.file?(file_name) => integer or nil
- *
- * Returns <code>nil</code> if <code>file_name</code> doesn't
- * exist or has zero size, the size of the file otherwise.
- */
-
-static VALUE
-test_s(obj, fname)
- VALUE obj, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qnil;
- if (st.st_size == 0) return Qnil;
- return OFFT2NUM(st.st_size);
-}
-
-/*
- * call-seq:
- * File.owned?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file exists and the
- * effective used id of the calling process is the owner of
- * the file.
- */
-
-static VALUE
-test_owned(obj, fname)
- VALUE obj, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_uid == geteuid()) return Qtrue;
- return Qfalse;
-}
-
-static VALUE
-test_rowned(obj, fname)
- VALUE obj, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_uid == getuid()) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * File.grpowned?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file exists and the
- * effective group id of the calling process is the owner of
- * the file. Returns <code>false</code> on Windows.
- */
-
-static VALUE
-test_grpowned(obj, fname)
- VALUE obj, fname;
-{
-#ifndef _WIN32
- struct stat st;
-
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_gid == getegid()) return Qtrue;
-#endif
- return Qfalse;
-}
-
-#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
-static VALUE
-check3rdbyte(fname, mode)
- VALUE fname;
- int mode;
-{
- struct stat st;
-
- rb_secure(2);
- FilePathValue(fname);
- if (stat(StringValueCStr(fname), &st) < 0) return Qfalse;
- if (st.st_mode & mode) return Qtrue;
- return Qfalse;
-}
-#endif
-
-/*
- * call-seq:
- * File.setuid?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a has the setuid bit set.
- */
-
-static VALUE
-test_suid(obj, fname)
- VALUE obj, fname;
-{
-#ifdef S_ISUID
- return check3rdbyte(fname, S_ISUID);
-#else
- return Qfalse;
-#endif
-}
-
-/*
- * call-seq:
- * File.setgid?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a has the setgid bit set.
- */
-
-static VALUE
-test_sgid(obj, fname)
- VALUE obj, fname;
-{
-#ifdef S_ISGID
- return check3rdbyte(fname, S_ISGID);
-#else
- return Qfalse;
-#endif
-}
-
-/*
- * call-seq:
- * File.sticky?(file_name) => true or false
- *
- * Returns <code>true</code> if the named file is a has the sticky bit set.
- */
-
-static VALUE
-test_sticky(obj, fname)
- VALUE obj, fname;
-{
-#ifdef S_ISVTX
- return check3rdbyte(fname, S_ISVTX);
-#else
- return Qnil;
-#endif
-}
-
-/*
- * call-seq:
- * File.size(file_name) => integer
- *
- * Returns the size of <code>file_name</code>.
- */
-
-static VALUE
-rb_file_s_size(klass, fname)
- VALUE klass, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0)
- rb_sys_fail(StringValueCStr(fname));
- return OFFT2NUM(st.st_size);
-}
-
-static VALUE
-rb_file_ftype(st)
- struct stat *st;
-{
- char *t;
-
- if (S_ISREG(st->st_mode)) {
- t = "file";
- }
- else if (S_ISDIR(st->st_mode)) {
- t = "directory";
- }
- else if (S_ISCHR(st->st_mode)) {
- t = "characterSpecial";
- }
-#ifdef S_ISBLK
- else if (S_ISBLK(st->st_mode)) {
- t = "blockSpecial";
- }
-#endif
-#ifdef S_ISFIFO
- else if (S_ISFIFO(st->st_mode)) {
- t = "fifo";
- }
-#endif
-#ifdef S_ISLNK
- else if (S_ISLNK(st->st_mode)) {
- t = "link";
- }
-#endif
-#ifdef S_ISSOCK
- else if (S_ISSOCK(st->st_mode)) {
- t = "socket";
- }
-#endif
- else {
- t = "unknown";
- }
-
- return rb_str_new2(t);
-}
-
-/*
- * call-seq:
- * File.ftype(file_name) => string
- *
- * Identifies the type of the named file; the return string is one of
- * ``<code>file</code>'', ``<code>directory</code>'',
- * ``<code>characterSpecial</code>'', ``<code>blockSpecial</code>'',
- * ``<code>fifo</code>'', ``<code>link</code>'',
- * ``<code>socket</code>'', or ``<code>unknown</code>''.
- *
- * File.ftype("testfile") #=> "file"
- * File.ftype("/dev/tty") #=> "characterSpecial"
- * File.ftype("/tmp/.X11-unix/X0") #=> "socket"
- */
-
-static VALUE
-rb_file_s_ftype(klass, fname)
- VALUE klass, fname;
-{
- struct stat st;
-
- rb_secure(2);
- FilePathValue(fname);
- if (lstat(StringValueCStr(fname), &st) == -1) {
- rb_sys_fail(RSTRING(fname)->ptr);
- }
-
- return rb_file_ftype(&st);
-}
-
-/*
- * call-seq:
- * File.atime(file_name) => time
- *
- * Returns the last access time for the named file as a Time object).
- *
- * File.atime("testfile") #=> Wed Apr 09 08:51:48 CDT 2003
- *
- */
-
-static VALUE
-rb_file_s_atime(klass, fname)
- VALUE klass, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0)
- rb_sys_fail(StringValueCStr(fname));
- return rb_time_new(st.st_atime, 0);
-}
-
-/*
- * call-seq:
- * file.atime => time
- *
- * Returns the last access time (a <code>Time</code> object)
- * for <i>file</i>, or epoch if <i>file</i> has not been accessed.
- *
- * File.new("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
- *
- */
-
-static VALUE
-rb_file_atime(obj)
- VALUE obj;
-{
- OpenFile *fptr;
- struct stat st;
-
- GetOpenFile(obj, fptr);
- if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail(fptr->path);
- }
- return rb_time_new(st.st_atime, 0);
-}
-
-/*
- * call-seq:
- * File.mtime(file_name) => time
- *
- * Returns the modification time for the named file as a Time object.
- *
- * File.mtime("testfile") #=> Tue Apr 08 12:58:04 CDT 2003
- *
- */
-
-static VALUE
-rb_file_s_mtime(klass, fname)
- VALUE klass, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0)
- rb_sys_fail(RSTRING(fname)->ptr);
- return rb_time_new(st.st_mtime, 0);
-}
-
-/*
- * call-seq:
- * file.mtime -> time
- *
- * Returns the modification time for <i>file</i>.
- *
- * File.new("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
- *
- */
-
-static VALUE
-rb_file_mtime(obj)
- VALUE obj;
-{
- OpenFile *fptr;
- struct stat st;
-
- GetOpenFile(obj, fptr);
- if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail(fptr->path);
- }
- return rb_time_new(st.st_mtime, 0);
-}
-
-/*
- * call-seq:
- * File.ctime(file_name) => time
- *
- * Returns the change time for the named file (the time at which
- * directory information about the file was changed, not the file
- * itself).
- *
- * File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
- *
- */
-
-static VALUE
-rb_file_s_ctime(klass, fname)
- VALUE klass, fname;
-{
- struct stat st;
-
- if (rb_stat(fname, &st) < 0)
- rb_sys_fail(RSTRING(fname)->ptr);
- return rb_time_new(st.st_ctime, 0);
-}
-
-/*
- * call-seq:
- * file.ctime -> time
- *
- * Returns the change time for <i>file</i> (that is, the time directory
- * information about the file was changed, not the file itself).
- *
- * File.new("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
- *
- */
-
-static VALUE
-rb_file_ctime(obj)
- VALUE obj;
-{
- OpenFile *fptr;
- struct stat st;
-
- GetOpenFile(obj, fptr);
- if (fstat(fptr->fd, &st) == -1) {
- rb_sys_fail(fptr->path);
- }
- return rb_time_new(st.st_ctime, 0);
-}
-
-static void
-chmod_internal(path, mode)
- const char *path;
- int mode;
-{
- if (chmod(path, mode) < 0)
- rb_sys_fail(path);
-}
-
-/*
- * call-seq:
- * File.chmod(mode_int, file_name, ... ) -> integer
- *
- * Changes permission bits on the named file(s) to the bit pattern
- * represented by <i>mode_int</i>. Actual effects are operating system
- * dependent (see the beginning of this section). On Unix systems, see
- * <code>chmod(2)</code> for details. Returns the number of files
- * processed.
- *
- * File.chmod(0644, "testfile", "out") #=> 2
- */
-
-static VALUE
-rb_file_s_chmod(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE vmode;
- VALUE rest;
- int mode;
- long n;
-
- rb_secure(2);
- rb_scan_args(argc, argv, "1*", &vmode, &rest);
- mode = NUM2INT(vmode);
-
- n = apply2files(chmod_internal, rest, (void *)(long)mode);
- return LONG2FIX(n);
-}
-
-/*
- * call-seq:
- * file.chmod(mode_int) => 0
- *
- * Changes permission bits on <i>file</i> to the bit pattern
- * represented by <i>mode_int</i>. Actual effects are platform
- * dependent; on Unix systems, see <code>chmod(2)</code> for details.
- * Follows symbolic links. Also see <code>File#lchmod</code>.
- *
- * f = File.new("out", "w");
- * f.chmod(0644) #=> 0
- */
-
-static VALUE
-rb_file_chmod(obj, vmode)
- VALUE obj, vmode;
-{
- OpenFile *fptr;
- int mode;
-
- rb_secure(2);
- mode = NUM2INT(vmode);
-
- GetOpenFile(obj, fptr);
-#ifdef HAVE_FCHMOD
- if (fchmod(fptr->fd, mode) == -1)
- rb_sys_fail(fptr->path);
-#else
- if (!fptr->path) return Qnil;
- if (chmod(fptr->path, mode) == -1)
- rb_sys_fail(fptr->path);
-#endif
-
- return INT2FIX(0);
-}
-
-#if defined(HAVE_LCHMOD)
-static void
-lchmod_internal(path, mode)
- const char *path;
- int mode;
-{
- if (lchmod(path, mode) < 0)
- rb_sys_fail(path);
-}
-
-/*
- * call-seq:
- * File.lchmod(mode_int, file_name, ...) => integer
- *
- * Equivalent to <code>File::chmod</code>, but does not follow symbolic
- * links (so it will change the permissions associated with the link,
- * not the file referenced by the link). Often not available.
- *
- */
-
-static VALUE
-rb_file_s_lchmod(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE vmode;
- VALUE rest;
- long mode, n;
-
- rb_secure(2);
- rb_scan_args(argc, argv, "1*", &vmode, &rest);
- mode = NUM2INT(vmode);
-
- n = apply2files(lchmod_internal, rest, (void *)(long)mode);
- return LONG2FIX(n);
-}
-#else
-static VALUE
-rb_file_s_lchmod(argc, argv)
- int argc;
- VALUE *argv;
-{
- rb_notimplement();
- return Qnil; /* not reached */
-}
-#endif
-
-struct chown_args {
- int owner, group;
-};
-
-static void
-chown_internal(path, args)
- const char *path;
- struct chown_args *args;
-{
- if (chown(path, args->owner, args->group) < 0)
- rb_sys_fail(path);
-}
-
-/*
- * call-seq:
- * File.chown(owner_int, group_int, file_name,... ) -> integer
- *
- * Changes the owner and group of the named file(s) to the given
- * numeric owner and group id's. Only a process with superuser
- * privileges may change the owner of a file. The current owner of a
- * file may change the file's group to any group to which the owner
- * belongs. A <code>nil</code> or -1 owner or group id is ignored.
- * Returns the number of files processed.
- *
- * File.chown(nil, 100, "testfile")
- *
- */
-
-static VALUE
-rb_file_s_chown(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE o, g, rest;
- struct chown_args arg;
- long n;
-
- rb_secure(2);
- rb_scan_args(argc, argv, "2*", &o, &g, &rest);
- if (NIL_P(o)) {
- arg.owner = -1;
- }
- else {
- arg.owner = NUM2INT(o);
- }
- if (NIL_P(g)) {
- arg.group = -1;
- }
- else {
- arg.group = NUM2INT(g);
- }
-
- n = apply2files(chown_internal, rest, &arg);
- return LONG2FIX(n);
-}
-
-/*
- * call-seq:
- * file.chown(owner_int, group_int ) => 0
- *
- * Changes the owner and group of <i>file</i> to the given numeric
- * owner and group id's. Only a process with superuser privileges may
- * change the owner of a file. The current owner of a file may change
- * the file's group to any group to which the owner belongs. A
- * <code>nil</code> or -1 owner or group id is ignored. Follows
- * symbolic links. See also <code>File#lchown</code>.
- *
- * File.new("testfile").chown(502, 1000)
- *
- */
-
-static VALUE
-rb_file_chown(obj, owner, group)
- VALUE obj, owner, group;
-{
- OpenFile *fptr;
- int o, g;
-
- rb_secure(2);
- o = NUM2INT(owner);
- g = NUM2INT(group);
- GetOpenFile(obj, fptr);
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32) || defined(__EMX__)
- if (!fptr->path) return Qnil;
- if (chown(fptr->path, o, g) == -1)
- rb_sys_fail(fptr->path);
-#else
- if (fchown(fptr->fd, o, g) == -1)
- rb_sys_fail(fptr->path);
-#endif
-
- return INT2FIX(0);
-}
-
-#if defined(HAVE_LCHOWN) && !defined(__CHECKER__)
-static void
-lchown_internal(path, args)
- const char *path;
- struct chown_args *args;
-{
- if (lchown(path, args->owner, args->group) < 0)
- rb_sys_fail(path);
-}
-
-
-/*
- * call-seq:
- * file.lchown(owner_int, group_int, file_name,..) => integer
- *
- * Equivalent to <code>File::chown</code>, but does not follow symbolic
- * links (so it will change the owner associated with the link, not the
- * file referenced by the link). Often not available. Returns number
- * of files in the argument list.
- *
- */
-
-static VALUE
-rb_file_s_lchown(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE o, g, rest;
- struct chown_args arg;
- long n;
-
- rb_secure(2);
- rb_scan_args(argc, argv, "2*", &o, &g, &rest);
- if (NIL_P(o)) {
- arg.owner = -1;
- }
- else {
- arg.owner = NUM2INT(o);
- }
- if (NIL_P(g)) {
- arg.group = -1;
- }
- else {
- arg.group = NUM2INT(g);
- }
-
- n = apply2files(lchown_internal, rest, &arg);
- return LONG2FIX(n);
-}
-#else
-static VALUE
-rb_file_s_lchown(argc, argv)
- int argc;
- VALUE *argv;
-{
- rb_notimplement();
-}
-#endif
-
-struct timeval rb_time_timeval();
-
-#if defined(HAVE_UTIMES) && !defined(__CHECKER__)
-
-static void
-utime_internal(path, tvp)
- char *path;
- struct timeval tvp[];
-{
- if (utimes(path, tvp) < 0)
- rb_sys_fail(path);
-}
-
-/*
- * call-seq:
- * File.utime(atime, mtime, file_name,...) => integer
- *
- * Sets the access and modification times of each
- * named file to the first two arguments. Returns
- * the number of file names in the argument list.
- */
-
-static VALUE
-rb_file_s_utime(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE atime, mtime, rest;
- struct timeval tvp[2];
- long n;
-
- rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
-
- tvp[0] = rb_time_timeval(atime);
- tvp[1] = rb_time_timeval(mtime);
-
- n = apply2files(utime_internal, rest, tvp);
- return LONG2FIX(n);
-}
-
-#else
-
-#if !defined HAVE_UTIME_H && !defined HAVE_SYS_UTIME_H
-struct utimbuf {
- long actime;
- long modtime;
-};
-#endif
-
-static void
-utime_internal(path, utp)
- const char *path;
- struct utimbuf *utp;
-{
- if (utime(path, utp) < 0)
- rb_sys_fail(path);
-}
-
-static VALUE
-rb_file_s_utime(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE atime, mtime, rest;
- long n;
- struct timeval tv;
- struct utimbuf utbuf;
-
- rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
-
- tv = rb_time_timeval(atime);
- utbuf.actime = tv.tv_sec;
- tv = rb_time_timeval(mtime);
- utbuf.modtime = tv.tv_sec;
-
- n = apply2files(utime_internal, rest, &utbuf);
- return LONG2FIX(n);
-}
-
-#endif
-
-NORETURN(static void sys_fail2 _((VALUE,VALUE)));
-static void
-sys_fail2(s1, s2)
- VALUE s1, s2;
-{
- char *buf;
- int len;
-
- len = RSTRING(s1)->len + RSTRING(s2)->len + 5;
- buf = ALLOCA_N(char, len);
- snprintf(buf, len, "%s or %s", RSTRING(s1)->ptr, RSTRING(s2)->ptr);
- rb_sys_fail(buf);
-}
-
-/*
- * call-seq:
- * File.link(old_name, new_name) => 0
- *
- * Creates a new name for an existing file using a hard link. Will not
- * overwrite <i>new_name</i> if it already exists (raising a subclass
- * of <code>SystemCallError</code>). Not available on all platforms.
- *
- * File.link("testfile", ".testfile") #=> 0
- * IO.readlines(".testfile")[0] #=> "This is line one\n"
- */
-
-static VALUE
-rb_file_s_link(klass, from, to)
- VALUE klass, from, to;
-{
-#ifdef HAVE_LINK
- rb_secure(2);
- FilePathValue(from);
- FilePathValue(to);
-
- if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
- sys_fail2(from, to);
- }
- return INT2FIX(0);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-/*
- * call-seq:
- * File.symlink(old_name, new_name) => 0
- *
- * Creates a symbolic link called <i>new_name</i> for the existing file
- * <i>old_name</i>. Raises a <code>NotImplemented</code> exception on
- * platforms that do not support symbolic links.
- *
- * File.symlink("testfile", "link2test") #=> 0
- *
- */
-
-static VALUE
-rb_file_s_symlink(klass, from, to)
- VALUE klass, from, to;
-{
-#ifdef HAVE_SYMLINK
- rb_secure(2);
- FilePathValue(from);
- FilePathValue(to);
-
- if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
- sys_fail2(from, to);
- }
- return INT2FIX(0);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-/*
- * call-seq:
- * File.readlink(link_name) -> file_name
- *
- * Returns the name of the file referenced by the given link.
- * Not available on all platforms.
- *
- * File.symlink("testfile", "link2test") #=> 0
- * File.readlink("link2test") #=> "testfile"
- */
-
-static VALUE
-rb_file_s_readlink(klass, path)
- VALUE klass, path;
-{
-#ifdef HAVE_READLINK
- char *buf;
- int size = 100;
- int rv;
- VALUE v;
-
- rb_secure(2);
- FilePathValue(path);
- buf = xmalloc(size);
- while ((rv = readlink(StringValueCStr(path), buf, size)) == size) {
- size *= 2;
- buf = xrealloc(buf, size);
- }
- if (rv < 0) {
- free(buf);
- rb_sys_fail(RSTRING(path)->ptr);
- }
- v = rb_tainted_str_new(buf, rv);
- free(buf);
-
- return v;
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
-}
-
-static void
-unlink_internal(path)
- const char *path;
-{
- if (unlink(path) < 0)
- rb_sys_fail(path);
-}
-
-/*
- * call-seq:
- * File.delete(file_name, ...) => integer
- * File.unlink(file_name, ...) => integer
- *
- * Deletes the named files, returning the number of names
- * passed as arguments. Raises an exception on any error.
- * See also <code>Dir::rmdir</code>.
- */
-
-static VALUE
-rb_file_s_unlink(klass, args)
- VALUE klass, args;
-{
- long n;
-
- rb_secure(2);
- n = apply2files(unlink_internal, args, 0);
- return LONG2FIX(n);
-}
-
-/*
- * call-seq:
- * File.rename(old_name, new_name) => 0
- *
- * Renames the given file to the new name. Raises a
- * <code>SystemCallError</code> if the file cannot be renamed.
- *
- * File.rename("afile", "afile.bak") #=> 0
- */
-
-static VALUE
-rb_file_s_rename(klass, from, to)
- VALUE klass, from, to;
-{
- const char *src, *dst;
-
- rb_secure(2);
- FilePathValue(from);
- FilePathValue(to);
- src = StringValueCStr(from);
- dst = StringValueCStr(to);
- if (rename(src, dst) < 0) {
-#if defined __CYGWIN__
- extern unsigned long __attribute__((stdcall)) GetLastError();
- errno = GetLastError(); /* This is a Cygwin bug */
-#elif defined DOSISH && !defined _WIN32
- if (errno == EEXIST
-#if defined (__EMX__)
- || errno == EACCES
-#endif
- ) {
- if (chmod(dst, 0666) == 0 &&
- unlink(dst) == 0 &&
- rename(src, dst) == 0)
- return INT2FIX(0);
- }
-#endif
- sys_fail2(from, to);
- }
-
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * File.umask() => integer
- * File.umask(integer) => integer
- *
- * Returns the current umask value for this process. If the optional
- * argument is given, set the umask to that value and return the
- * previous value. Umask values are <em>subtracted</em> from the
- * default permissions, so a umask of <code>0222</code> would make a
- * file read-only for everyone.
- *
- * File.umask(0006) #=> 18
- * File.umask #=> 6
- */
-
-static VALUE
-rb_file_s_umask(argc, argv)
- int argc;
- VALUE *argv;
-{
- int omask = 0;
-
- rb_secure(2);
- if (argc == 0) {
- omask = umask(0);
- umask(omask);
- }
- else if (argc == 1) {
- omask = umask(NUM2INT(argv[0]));
- }
- else {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- return INT2FIX(omask);
-}
-
-#if defined DOSISH
-#define DOSISH_UNC
-#define isdirsep(x) ((x) == '/' || (x) == '\\')
-#else
-#define isdirsep(x) ((x) == '/')
-#endif
-#ifndef CharNext /* defined as CharNext[AW] on Windows. */
-# if defined(DJGPP)
-# define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-# else
-# define CharNext(p) ((p) + 1)
-# endif
-#endif
-
-#ifdef __CYGWIN__
-#undef DOSISH
-#define DOSISH_UNC
-#define DOSISH_DRIVE_LETTER
-#endif
-
-#ifdef DOSISH_DRIVE_LETTER
-static inline int
-has_drive_letter(buf)
- const char *buf;
-{
- if (ISALPHA(buf[0]) && buf[1] == ':') {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-static char*
-getcwdofdrv(drv)
- int drv;
-{
- char drive[4];
- char *drvcwd, *oldcwd;
-
- drive[0] = drv;
- drive[1] = ':';
- drive[2] = '\0';
-
- /* the only way that I know to get the current directory
- of a particular drive is to change chdir() to that drive,
- so save the old cwd before chdir()
- */
- oldcwd = my_getcwd();
- if (chdir(drive) == 0) {
- drvcwd = my_getcwd();
- chdir(oldcwd);
- free(oldcwd);
- }
- else {
- /* perhaps the drive is not exist. we return only drive letter */
- drvcwd = strdup(drive);
- }
- return drvcwd;
-}
-#endif
-
-static inline char *
-skiproot(path)
- const char *path;
-{
-#ifdef DOSISH_DRIVE_LETTER
- if (has_drive_letter(path)) path += 2;
-#endif
- while (isdirsep(*path)) path++;
- return (char *)path;
-}
-
-#define nextdirsep rb_path_next
-char *
-rb_path_next(s)
- const char *s;
-{
- while (*s && !isdirsep(*s)) {
- s = CharNext(s);
- }
- return (char *)s;
-}
-
-#define skipprefix rb_path_skip_prefix
-char *
-rb_path_skip_prefix(path)
- const char *path;
-{
-#if defined(DOSISH_UNC) || defined(DOSISH_DRIVE_LETTER)
-#ifdef DOSISH_UNC
- if (isdirsep(path[0]) && isdirsep(path[1])) {
- if (*(path = nextdirsep(path + 2)))
- path = nextdirsep(path + 1);
- return (char *)path;
- }
-#endif
-#ifdef DOSISH_DRIVE_LETTER
- if (has_drive_letter(path))
- return (char *)(path + 2);
-#endif
-#endif
- return (char *)path;
-}
-
-#define strrdirsep rb_path_last_separator
-char *
-rb_path_last_separator(path)
- const char *path;
-{
- char *last = NULL;
- while (*path) {
- if (isdirsep(*path)) {
- const char *tmp = path++;
- while (isdirsep(*path)) path++;
- if (!*path) break;
- last = (char *)tmp;
- }
- else {
- path = CharNext(path);
- }
- }
- return last;
-}
-
-#define chompdirsep rb_path_end
-char *
-rb_path_end(path)
- const char *path;
-{
- while (*path) {
- if (isdirsep(*path)) {
- const char *last = path++;
- while (isdirsep(*path)) path++;
- if (!*path) return (char *)last;
- }
- else {
- path = CharNext(path);
- }
- }
- return (char *)path;
-}
-
-#define BUFCHECK(cond) do {\
- long bdiff = p - buf;\
- while (cond) {\
- buflen *= 2;\
- }\
- rb_str_resize(result, buflen);\
- buf = RSTRING(result)->ptr;\
- p = buf + bdiff;\
- pend = buf + buflen;\
-} while (0)
-
-#define BUFINIT() (\
- p = buf = RSTRING(result)->ptr,\
- buflen = RSTRING(result)->len,\
- pend = p + buflen)
-
-#if !defined(TOLOWER)
-#define TOLOWER(c) (ISUPPER(c) ? tolower(c) : (c))
-#endif
-
-static int is_absolute_path _((const char*));
-
-static VALUE
-file_expand_path(fname, dname, result)
- VALUE fname, dname, result;
-{
- char *s, *buf, *b, *p, *pend, *root;
- long buflen, dirlen;
- int tainted;
-
- s = StringValuePtr(fname);
- BUFINIT();
- tainted = OBJ_TAINTED(fname);
-
- if (s[0] == '~') {
- if (isdirsep(s[1]) || s[1] == '\0') {
- char *dir = getenv("HOME");
-
- if (!dir) {
- rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `%s'", s);
- }
- dirlen = strlen(dir);
- BUFCHECK(dirlen > buflen);
- strcpy(buf, dir);
-#if defined DOSISH || defined __CYGWIN__
- for (p = buf; *p; p = CharNext(p)) {
- if (*p == '\\') {
- *p = '/';
- }
- }
-#else
- p = buf + strlen(dir);
-#endif
- s++;
- tainted = 1;
- }
- else {
-#ifdef HAVE_PWD_H
- struct passwd *pwPtr;
- s++;
-#endif
- s = nextdirsep(b = s);
- BUFCHECK(bdiff + (s-b) >= buflen);
- memcpy(p, b, s-b);
- p += s-b;
- *p = '\0';
-#ifdef HAVE_PWD_H
- pwPtr = getpwnam(buf);
- if (!pwPtr) {
- endpwent();
- rb_raise(rb_eArgError, "user %s doesn't exist", buf);
- }
- dirlen = strlen(pwPtr->pw_dir);
- BUFCHECK(dirlen > buflen);
- strcpy(buf, pwPtr->pw_dir);
- p = buf + strlen(pwPtr->pw_dir);
- endpwent();
-#endif
- }
- }
-#ifdef DOSISH_DRIVE_LETTER
- /* skip drive letter */
- else if (has_drive_letter(s)) {
- if (isdirsep(s[2])) {
- /* specified drive letter, and full path */
- /* skip drive letter */
- BUFCHECK(bdiff + 2 >= buflen);
- memcpy(p, s, 2);
- p += 2;
- s += 2;
- }
- else {
- /* specified drive, but not full path */
- int same = 0;
- if (!NIL_P(dname)) {
- file_expand_path(dname, Qnil, result);
- BUFINIT();
- if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) {
- /* ok, same drive */
- same = 1;
- }
- }
- if (!same) {
- char *dir = getcwdofdrv(*s);
-
- tainted = 1;
- dirlen = strlen(dir);
- BUFCHECK(dirlen > buflen);
- strcpy(buf, dir);
- free(dir);
- }
- p = chompdirsep(skiproot(buf));
- s += 2;
- }
- }
-#endif
- else if (!is_absolute_path(s)) {
- if (!NIL_P(dname)) {
- file_expand_path(dname, Qnil, result);
- BUFINIT();
- }
- else {
- char *dir = my_getcwd();
-
- tainted = 1;
- dirlen = strlen(dir);
- BUFCHECK(dirlen > buflen);
- strcpy(buf, dir);
- free(dir);
- }
-#if defined DOSISH || defined __CYGWIN__
- if (isdirsep(*s)) {
- /* specified full path, but not drive letter nor UNC */
- /* we need to get the drive letter or UNC share name */
- p = skipprefix(buf);
- }
- else
-#endif
- p = chompdirsep(skiproot(buf));
- }
- else {
- b = s;
- do s++; while (isdirsep(*s));
- p = buf + (s - b);
- BUFCHECK(bdiff >= buflen);
- memset(buf, '/', p - buf);
- }
- if (p > buf && p[-1] == '/')
- --p;
- else
- *p = '/';
-
- p[1] = 0;
- root = skipprefix(buf);
-
- b = s;
- while (*s) {
- switch (*s) {
- case '.':
- if (b == s++) { /* beginning of path element */
- switch (*s) {
- case '\0':
- b = s;
- break;
- case '.':
- if (*(s+1) == '\0' || isdirsep(*(s+1))) {
- /* We must go back to the parent */
- *p = '\0';
- if (!(b = strrdirsep(root))) {
- *p = '/';
- }
- else {
- p = b;
- }
- b = ++s;
- }
- break;
- case '/':
-#if defined DOSISH || defined __CYGWIN__
- case '\\':
-#endif
- b = ++s;
- break;
- default:
- /* ordinary path element, beginning don't move */
- break;
- }
- }
- break;
- case '/':
-#if defined DOSISH || defined __CYGWIN__
- case '\\':
-#endif
- if (s > b) {
- long rootdiff = root - buf;
- BUFCHECK(bdiff + (s-b+1) >= buflen);
- root = buf + rootdiff;
- memcpy(++p, b, s-b);
- p += s-b;
- *p = '/';
- }
- b = ++s;
- break;
- default:
- s = CharNext(s);
- break;
- }
- }
-
- if (s > b) {
- BUFCHECK(bdiff + (s-b) >= buflen);
- memcpy(++p, b, s-b);
- p += s-b;
- }
- if (p == skiproot(buf) - 1) p++;
-
- if (tainted) OBJ_TAINT(result);
- RSTRING(result)->len = p - buf;
- *p = '\0';
- return result;
-}
-
-VALUE
-rb_file_expand_path(fname, dname)
- VALUE fname, dname;
-{
- return file_expand_path(fname, dname, rb_str_new(0, MAXPATHLEN + 2));
-}
-
-/*
- * call-seq:
- * File.expand_path(file_name [, dir_string] ) -> abs_file_name
- *
- * Converts a pathname to an absolute pathname. Relative paths are
- * referenced from the current working directory of the process unless
- * <i>dir_string</i> is given, in which case it will be used as the
- * starting point. The given pathname may start with a
- * ``<code>~</code>'', which expands to the process owner's home
- * directory (the environment variable <code>HOME</code> must be set
- * correctly). ``<code>~</code><i>user</i>'' expands to the named
- * user's home directory.
- *
- * File.expand_path("~oracle/bin") #=> "/home/oracle/bin"
- * File.expand_path("../../bin", "/tmp/x") #=> "/bin"
- */
-
-VALUE
-rb_file_s_expand_path(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fname, dname;
-
- if (argc == 1) {
- return rb_file_expand_path(argv[0], Qnil);
- }
- rb_scan_args(argc, argv, "11", &fname, &dname);
-
- return rb_file_expand_path(fname, dname);
-}
-
-static int
-rmext(p, e)
- const char *p, *e;
-{
- int l1, l2;
-
- if (!e) return 0;
-
- l1 = chompdirsep(p) - p;
- l2 = strlen(e);
- if (l2 == 2 && e[1] == '*') {
- e = strrchr(p, *e);
- if (!e) return 0;
- return e - p;
- }
- if (l1 < l2) return l1;
-
- if (strncmp(p+l1-l2, e, l2) == 0) {
- return l1-l2;
- }
- return 0;
-}
-
-/*
- * call-seq:
- * File.basename(file_name [, suffix] ) -> base_name
- *
- * Returns the last component of the filename given in <i>file_name</i>,
- * which must be formed using forward slashes (``<code>/</code>'')
- * regardless of the separator used on the local file system. If
- * <i>suffix</i> is given and present at the end of <i>file_name</i>,
- * it is removed.
- *
- * File.basename("/home/gumby/work/ruby.rb") #=> "ruby.rb"
- * File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby"
- */
-
-static VALUE
-rb_file_s_basename(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE fname, fext, basename;
- char *name, *p;
- int f;
-
- if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
- StringValue(fext);
- }
- StringValue(fname);
- if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr))
- return fname;
- if (!*(name = skiproot(name))) {
- p = name - 1;
- f = 1;
-#ifdef DOSISH_DRIVE_LETTER
- if (*p == ':') {
- p++;
- f = 0;
- }
-#endif
- }
- else if (!(p = strrdirsep(name))) {
- if (NIL_P(fext) || !(f = rmext(name, StringValueCStr(fext)))) {
- f = chompdirsep(name) - name;
- if (f == RSTRING(fname)->len) return fname;
- }
- p = name;
- }
- else {
- while (isdirsep(*p)) p++; /* skip last / */
- if (NIL_P(fext) || !(f = rmext(p, StringValueCStr(fext)))) {
- f = chompdirsep(p) - p;
- }
- }
- basename = rb_str_new(p, f);
- OBJ_INFECT(basename, fname);
- return basename;
-}
-
-/*
- * call-seq:
- * File.dirname(file_name ) -> dir_name
- *
- * Returns all components of the filename given in <i>file_name</i>
- * except the last one. The filename must be formed using forward
- * slashes (``<code>/</code>'') regardless of the separator used on the
- * local file system.
- *
- * File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
- */
-
-static VALUE
-rb_file_s_dirname(klass, fname)
- VALUE klass, fname;
-{
- char *name, *root, *p;
- VALUE dirname;
-
- name = StringValueCStr(fname);
- root = skiproot(name);
-#ifdef DOSISH_UNC
- if (root > name + 2 && isdirsep(*name))
- name = root - 2;
-#else
- if (root > name + 1)
- name = root - 1;
-#endif
- p = strrdirsep(root);
- if (!p) {
- p = root;
- }
- if (p == name)
- return rb_str_new2(".");
- dirname = rb_str_new(name, p - name);
-#ifdef DOSISH_DRIVE_LETTER
- if (root == name + 2 && name[1] == ':')
- rb_str_cat(dirname, ".", 1);
-#endif
- OBJ_INFECT(dirname, fname);
- return dirname;
-}
-
-/*
- * call-seq:
- * File.extname(path) -> string
- *
- * Returns the extension (the portion of file name in <i>path</i>
- * after the period).
- *
- * File.extname("test.rb") #=> ".rb"
- * File.extname("a/b/d/test.rb") #=> ".rb"
- * File.extname("test") #=> ""
- * File.extname(".profile") #=> ""
- *
- */
-
-static VALUE
-rb_file_s_extname(klass, fname)
- VALUE klass, fname;
-{
- char *name, *p, *e;
- VALUE extname;
-
- name = StringValueCStr(fname);
- p = strrdirsep(name); /* get the last path component */
- if (!p)
- p = name;
- else
- p++;
-
- e = strrchr(p, '.'); /* get the last dot of the last component */
- if (!e || e == p) /* no dot, or the only dot is first? */
- return rb_str_new2("");
- extname = rb_str_new(e, chompdirsep(e) - e); /* keep the dot, too! */
- OBJ_INFECT(extname, fname);
- return extname;
-}
-
-/*
- * call-seq:
- * File.path(path) -> string
- *
- * Returns the string representation of the path
- *
- * File.path("/dev/null") #=> "/dev/null"
- * File.path(Pathname.new("/tmp")) #=> "/tmp"
- *
- */
-
-static VALUE
-rb_file_s_path(klass, fname)
- VALUE klass, fname;
-{
- return rb_get_path(fname);
-}
-
-/*
- * call-seq:
- * File.split(file_name) => array
- *
- * Splits the given string into a directory and a file component and
- * returns them in a two-element array. See also
- * <code>File::dirname</code> and <code>File::basename</code>.
- *
- * File.split("/home/gumby/.profile") #=> ["/home/gumby", ".profile"]
- */
-
-static VALUE
-rb_file_s_split(klass, path)
- VALUE klass, path;
-{
- StringValue(path); /* get rid of converting twice */
- return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
-}
-
-static VALUE separator;
-
-static VALUE rb_file_join _((VALUE ary, VALUE sep));
-
-static VALUE
-file_inspect_join(ary, arg, recur)
- VALUE ary;
- VALUE *arg;
-{
- if (recur) return rb_str_new2("[...]");
- return rb_file_join(arg[0], arg[1]);
-}
-
-static VALUE
-rb_file_join(ary, sep)
- VALUE ary, sep;
-{
- long len, i;
- int taint = 0;
- VALUE result, tmp;
- char *name;
-
- if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
- if (OBJ_TAINTED(ary)) taint = 1;
- if (OBJ_TAINTED(sep)) taint = 1;
-
- len = 1;
- for (i=0; i<RARRAY(ary)->len; i++) {
- if (TYPE(RARRAY(ary)->ptr[i]) == T_STRING) {
- len += RSTRING(RARRAY(ary)->ptr[i])->len;
- }
- else {
- len += 10;
- }
- }
- if (!NIL_P(sep) && TYPE(sep) == T_STRING) {
- len += RSTRING(sep)->len * RARRAY(ary)->len - 1;
- }
- result = rb_str_buf_new(len);
- for (i=0; i<RARRAY(ary)->len; i++) {
- tmp = RARRAY(ary)->ptr[i];
- switch (TYPE(tmp)) {
- case T_STRING:
- break;
- case T_ARRAY:
- {
- VALUE args[2];
-
- args[0] = tmp;
- args[1] = sep;
- tmp = rb_exec_recursive(file_inspect_join, ary, (VALUE)args);
- }
- break;
- default:
- tmp = rb_obj_as_string(tmp);
- }
- name = StringValueCStr(result);
- if (i > 0 && !NIL_P(sep) && !*chompdirsep(name))
- rb_str_buf_append(result, sep);
- rb_str_buf_append(result, tmp);
- if (OBJ_TAINTED(tmp)) taint = 1;
- }
-
- if (taint) OBJ_TAINT(result);
- return result;
-}
-
-/*
- * call-seq:
- * File.join(string, ...) -> path
- *
- * Returns a new string formed by joining the strings using
- * <code>File::SEPARATOR</code>.
- *
- * File.join("usr", "mail", "gumby") #=> "usr/mail/gumby"
- *
- */
-
-static VALUE
-rb_file_s_join(klass, args)
- VALUE klass, args;
-{
- return rb_file_join(args, separator);
-}
-
-/*
- * call-seq:
- * File.truncate(file_name, integer) => 0
- *
- * Truncates the file <i>file_name</i> to be at most <i>integer</i>
- * bytes long. Not available on all platforms.
- *
- * f = File.new("out", "w")
- * f.write("1234567890") #=> 10
- * f.close #=> nil
- * File.truncate("out", 5) #=> 0
- * File.size("out") #=> 5
- *
- */
-
-static VALUE
-rb_file_s_truncate(klass, path, len)
- VALUE klass, path, len;
-{
- off_t pos;
-
- rb_secure(2);
- pos = NUM2OFFT(len);
- FilePathValue(path);
-#ifdef HAVE_TRUNCATE
- if (truncate(StringValueCStr(path), pos) < 0)
- rb_sys_fail(RSTRING(path)->ptr);
-#else
-# ifdef HAVE_CHSIZE
- {
- int tmpfd;
-
-# ifdef _WIN32
- if ((tmpfd = open(StringValueCStr(path), O_RDWR)) < 0) {
- rb_sys_fail(RSTRING(path)->ptr);
- }
-# else
- if ((tmpfd = open(StringValueCStr(path), 0)) < 0) {
- rb_sys_fail(RSTRING(path)->ptr);
- }
-# endif
- if (chsize(tmpfd, pos) < 0) {
- close(tmpfd);
- rb_sys_fail(RSTRING(path)->ptr);
- }
- close(tmpfd);
- }
-# else
- rb_notimplement();
-# endif
-#endif
- return INT2FIX(0);
-}
-
-/*
- * call-seq:
- * file.truncate(integer) => 0
- *
- * Truncates <i>file</i> to at most <i>integer</i> bytes. The file
- * must be opened for writing. Not available on all platforms.
- *
- * f = File.new("out", "w")
- * f.syswrite("1234567890") #=> 10
- * f.truncate(5) #=> 0
- * f.close() #=> nil
- * File.size("out") #=> 5
- */
-
-static VALUE
-rb_file_truncate(obj, len)
- VALUE obj, len;
-{
- OpenFile *fptr;
- off_t pos;
-
- rb_secure(2);
- pos = NUM2OFFT(len);
- GetOpenFile(obj, fptr);
- if (!(fptr->mode & FMODE_WRITABLE)) {
- rb_raise(rb_eIOError, "not opened for writing");
- }
- rb_io_flush(obj);
-#ifdef HAVE_TRUNCATE
- if (ftruncate(fptr->fd, pos) < 0)
- rb_sys_fail(fptr->path);
-#else
-# ifdef HAVE_CHSIZE
- if (chsize(fptr->fd, pos) < 0)
- rb_sys_fail(fptr->path);
-# else
- rb_notimplement();
-# endif
-#endif
- return INT2FIX(0);
-}
-
-# ifndef LOCK_SH
-# define LOCK_SH 1
-# endif
-# ifndef LOCK_EX
-# define LOCK_EX 2
-# endif
-# ifndef LOCK_NB
-# define LOCK_NB 4
-# endif
-# ifndef LOCK_UN
-# define LOCK_UN 8
-# endif
-
-#if 1
-static int
-rb_thread_flock(fd, op, fptr)
- int fd, op;
- OpenFile *fptr;
-{
- if (rb_thread_alone() || (op & LOCK_NB)) {
- return flock(fd, op);
- }
- op |= LOCK_NB;
- while (flock(fd, op) < 0) {
- switch (errno) {
- case EAGAIN:
- case EACCES:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- rb_thread_polling(); /* busy wait */
- rb_io_check_closed(fptr);
- continue;
- default:
- return -1;
- }
- }
- return 0;
-}
-#define flock(fd, op) rb_thread_flock(fd, op, fptr)
-#endif
-
-/*
- * call-seq:
- * file.flock (locking_constant ) => 0 or false
- *
- * Locks or unlocks a file according to <i>locking_constant</i> (a
- * logical <em>or</em> of the values in the table below).
- * Returns <code>false</code> if <code>File::LOCK_NB</code> is
- * specified and the operation would otherwise have blocked. Not
- * available on all platforms.
- *
- * Locking constants (in class File):
- *
- * LOCK_EX | Exclusive lock. Only one process may hold an
- * | exclusive lock for a given file at a time.
- * ----------+------------------------------------------------
- * LOCK_NB | Don't block when locking. May be combined
- * | with other lock options using logical or.
- * ----------+------------------------------------------------
- * LOCK_SH | Shared lock. Multiple processes may each hold a
- * | shared lock for a given file at the same time.
- * ----------+------------------------------------------------
- * LOCK_UN | Unlock.
- *
- * Example:
- *
- * File.new("testfile").flock(File::LOCK_UN) #=> 0
- *
- */
-
-static VALUE
-rb_file_flock(obj, operation)
- VALUE obj;
- VALUE operation;
-{
-#ifndef __CHECKER__
- OpenFile *fptr;
- int op;
-
- rb_secure(2);
- op = NUM2INT(operation);
- GetOpenFile(obj, fptr);
-
- if (fptr->mode & FMODE_WRITABLE) {
- rb_io_flush(obj);
- }
- retry:
- if (flock(fptr->fd, op) < 0) {
- switch (errno) {
- case EAGAIN:
- case EACCES:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- return Qfalse;
- case EINTR:
-#if defined(ERESTART)
- case ERESTART:
-#endif
- goto retry;
- }
- rb_sys_fail(fptr->path);
- }
-#endif
- return INT2FIX(0);
-}
-#undef flock
-
-static void
-test_check(n, argc, argv)
- int n, argc;
- VALUE *argv;
-{
- int i;
-
- rb_secure(2);
- n+=1;
- if (n != argc) rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
- for (i=1; i<n; i++) {
- switch (TYPE(argv[i])) {
- case T_STRING:
- default:
- FilePathValue(argv[i]);
- break;
- case T_FILE:
- break;
- }
- }
-}
-
-#define CHECK(n) test_check((n), argc, argv)
-
-/*
- * call-seq:
- * test(int_cmd, file1 [, file2] ) => obj
- *
- * Uses the integer <i>aCmd</i> to perform various tests on
- * <i>file1</i> (first table below) or on <i>file1</i> and
- * <i>file2</i> (second table).
- *
- * File tests on a single file:
- *
- * Test Returns Meaning
- * ?A | Time | Last access time for file1
- * ?b | boolean | True if file1 is a block device
- * ?c | boolean | True if file1 is a character device
- * ?C | Time | Last change time for file1
- * ?d | boolean | True if file1 exists and is a directory
- * ?e | boolean | True if file1 exists
- * ?f | boolean | True if file1 exists and is a regular file
- * ?g | boolean | True if files has the \CF{setgid} bit
- * | | set (false under NT)
- * ?G | boolean | True if file1 exists and has a group
- * | | ownership equal to the caller's group
- * ?k | boolean | True if file1 exists and has the sticky bit set
- * ?l | boolean | True if files exists and is a symbolic link
- * ?M | Time | Last modification time for file1
- * ?o | boolean | True if files exists and is owned by
- * | | the caller's effective uid
- * ?O | boolean | True if file1 exists and is owned by
- * | | the caller's real uid
- * ?p | boolean | True if file1 exists and is a fifo
- * ?r | boolean | True if file1 is readable by the effective
- * | | uid/gid of the caller
- * ?R | boolean | True if file is readable by the real
- * | | uid/gid of the caller
- * ?s | int/nil | If files has nonzero size, return the size,
- * | | otherwise return nil
- * ?S | boolean | True if file1 exists and is a socket
- * ?u | boolean | True if file1 has the setuid bit set
- * ?w | boolean | True if file1 exists and is writable by
- * | | the effective uid/gid
- * ?W | boolean | True if file1 exists and is writable by
- * | | the real uid/gid
- * ?x | boolean | True if file1 exists and is executable by
- * | | the effective uid/gid
- * ?X | boolean | True if file1 exists and is executable by
- * | | the real uid/gid
- * ?z | boolean | True if file1 exists and has a zero length
- *
- * Tests that take two files:
- *
- * ?- | boolean | True if file1 is a hard link to file2
- * ?= | boolean | True if the modification times of file1
- * | | and file2 are equal
- * ?< | boolean | True if the modification time of file1
- * | | is prior to that of file2
- * ?> | boolean | True if the modification time of file1
- * | | is after that of file2
- */
-
-static VALUE
-rb_f_test(argc, argv)
- int argc;
- VALUE *argv;
-{
- int cmd;
-
- if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments");
-#if 0 /* 1.7 behavior? */
- if (argc == 1) {
- return RTEST(argv[0]) ? Qtrue : Qfalse;
- }
-#endif
- cmd = NUM2CHR(argv[0]);
- if (cmd == 0) return Qfalse;
- if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
- CHECK(1);
- switch (cmd) {
- case 'b':
- return test_b(0, argv[1]);
-
- case 'c':
- return test_c(0, argv[1]);
-
- case 'd':
- return test_d(0, argv[1]);
-
- case 'a':
- case 'e':
- return test_e(0, argv[1]);
-
- case 'f':
- return test_f(0, argv[1]);
-
- case 'g':
- return test_sgid(0, argv[1]);
-
- case 'G':
- return test_grpowned(0, argv[1]);
-
- case 'k':
- return test_sticky(0, argv[1]);
-
- case 'l':
- return test_l(0, argv[1]);
-
- case 'o':
- return test_owned(0, argv[1]);
-
- case 'O':
- return test_rowned(0, argv[1]);
-
- case 'p':
- return test_p(0, argv[1]);
-
- case 'r':
- return test_r(0, argv[1]);
-
- case 'R':
- return test_R(0, argv[1]);
-
- case 's':
- return test_s(0, argv[1]);
-
- case 'S':
- return test_S(0, argv[1]);
-
- case 'u':
- return test_suid(0, argv[1]);
-
- case 'w':
- return test_w(0, argv[1]);
-
- case 'W':
- return test_W(0, argv[1]);
-
- case 'x':
- return test_x(0, argv[1]);
-
- case 'X':
- return test_X(0, argv[1]);
-
- case 'z':
- return test_z(0, argv[1]);
- }
- }
-
- if (strchr("MAC", cmd)) {
- struct stat st;
-
- CHECK(1);
- if (rb_stat(argv[1], &st) == -1) {
- rb_sys_fail(RSTRING(argv[1])->ptr);
- }
-
- switch (cmd) {
- case 'A':
- return rb_time_new(st.st_atime, 0);
- case 'M':
- return rb_time_new(st.st_mtime, 0);
- case 'C':
- return rb_time_new(st.st_ctime, 0);
- }
- }
-
- if (strchr("-=<>", cmd)) {
- struct stat st1, st2;
-
- CHECK(2);
- if (rb_stat(argv[1], &st1) < 0) return Qfalse;
- if (rb_stat(argv[2], &st2) < 0) return Qfalse;
-
- switch (cmd) {
- case '-':
- if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
- return Qtrue;
- return Qfalse;
-
- case '=':
- if (st1.st_mtime == st2.st_mtime) return Qtrue;
- return Qfalse;
-
- case '>':
- if (st1.st_mtime > st2.st_mtime) return Qtrue;
- return Qfalse;
-
- case '<':
- if (st1.st_mtime < st2.st_mtime) return Qtrue;
- return Qfalse;
- }
- }
- /* unknown command */
- rb_raise(rb_eArgError, "unknown command ?%c", cmd);
- return Qnil; /* not reached */
-}
-
-
-
-/*
- * Document-class: File::Stat
- *
- * Objects of class <code>File::Stat</code> encapsulate common status
- * information for <code>File</code> objects. The information is
- * recorded at the moment the <code>File::Stat</code> object is
- * created; changes made to the file after that point will not be
- * reflected. <code>File::Stat</code> objects are returned by
- * <code>IO#stat</code>, <code>File::stat</code>,
- * <code>File#lstat</code>, and <code>File::lstat</code>. Many of these
- * methods return platform-specific values, and not all values are
- * meaningful on all systems. See also <code>Kernel#test</code>.
- */
-
-static VALUE rb_stat_s_alloc _((VALUE));
-static VALUE
-rb_stat_s_alloc(klass)
- VALUE klass;
-{
- return stat_new_0(klass, 0);
-}
-
-/*
- * call-seq:
- *
- * File::Stat.new(file_name) => stat
- *
- * Create a File::Stat object for the given file name (raising an
- * exception if the file doesn't exist).
- */
-
-static VALUE
-rb_stat_init(obj, fname)
- VALUE obj, fname;
-{
- struct stat st, *nst;
-
- rb_secure(2);
- FilePathValue(fname);
- if (stat(StringValueCStr(fname), &st) == -1) {
- rb_sys_fail(RSTRING(fname)->ptr);
- }
- if (DATA_PTR(obj)) {
- free(DATA_PTR(obj));
- DATA_PTR(obj) = NULL;
- }
- nst = ALLOC(struct stat);
- *nst = st;
- DATA_PTR(obj) = nst;
-
- return Qnil;
-}
-
-/* :nodoc: */
-static VALUE
-rb_stat_init_copy(copy, orig)
- VALUE copy, orig;
-{
- struct stat *nst;
-
- if (copy == orig) return orig;
- rb_check_frozen(copy);
- /* need better argument type check */
- if (!rb_obj_is_instance_of(orig, rb_obj_class(copy))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
- if (DATA_PTR(copy)) {
- free(DATA_PTR(copy));
- DATA_PTR(copy) = 0;
- }
- if (DATA_PTR(orig)) {
- nst = ALLOC(struct stat);
- *nst = *(struct stat*)DATA_PTR(orig);
- DATA_PTR(copy) = nst;
- }
-
- return copy;
-}
-
-/*
- * call-seq:
- * stat.ftype => string
- *
- * Identifies the type of <i>stat</i>. The return string is one of:
- * ``<code>file</code>'', ``<code>directory</code>'',
- * ``<code>characterSpecial</code>'', ``<code>blockSpecial</code>'',
- * ``<code>fifo</code>'', ``<code>link</code>'',
- * ``<code>socket</code>'', or ``<code>unknown</code>''.
- *
- * File.stat("/dev/tty").ftype #=> "characterSpecial"
- *
- */
-
-static VALUE
-rb_stat_ftype(obj)
- VALUE obj;
-{
- return rb_file_ftype(get_stat(obj));
-}
-
-/*
- * call-seq:
- * stat.directory? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is a directory,
- * <code>false</code> otherwise.
- *
- * File.stat("testfile").directory? #=> false
- * File.stat(".").directory? #=> true
- */
-
-static VALUE
-rb_stat_d(obj)
- VALUE obj;
-{
- if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.pipe? => true or false
- *
- * Returns <code>true</code> if the operating system supports pipes and
- * <i>stat</i> is a pipe; <code>false</code> otherwise.
- */
-
-static VALUE
-rb_stat_p(obj)
- VALUE obj;
-{
-#ifdef S_IFIFO
- if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;
-
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.symlink? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is a symbolic link,
- * <code>false</code> if it isn't or if the operating system doesn't
- * support this feature. As <code>File::stat</code> automatically
- * follows symbolic links, <code>symlink?</code> will always be
- * <code>false</code> for an object returned by
- * <code>File::stat</code>.
- *
- * File.symlink("testfile", "alink") #=> 0
- * File.stat("alink").symlink? #=> false
- * File.lstat("alink").symlink? #=> true
- *
- */
-
-static VALUE
-rb_stat_l(obj)
- VALUE obj;
-{
-#ifdef S_ISLNK
- if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
-#endif
- return Qfalse;
-}
-
-/*
- * call-seq:
- * stat.socket? => true or false
- *
- * Returns <code>true</code> if <i>stat</i> is a socket,
- * <code>false</code> if it isn't or if the operating system doesn't
- * support this feature.
- *
- * File.stat("testfile").socket? #=> false
- *
- */
-
-static VALUE
-rb_stat_S(obj)
- VALUE obj;
-{
-#ifdef S_ISSOCK
- if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;
-
-#endif
- return Qfalse;
-}
-
diff --git a/tests/examplefiles/example.cpp b/tests/examplefiles/example.cpp
index 316c1420..4dffc3f7 100644
--- a/tests/examplefiles/example.cpp
+++ b/tests/examplefiles/example.cpp
@@ -6242,7303 +6242,3 @@ void CodeGenerator::openKWTag(unsigned int kwClassID){
currentState=KEYWORD;
}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void CodeGenerator::processRootState()
-{
- if (langInfo.highlightingDisabled()){
- string line;
- while (getline(*in, line)){
- *out << maskString(line) << getNewLine();
- }
- *out << flush;
- return;
- }
-
- State state=STANDARD;
-
- bool eof=false,
- firstLine=true; // avoid newline before printing the first output line
- openTag(STANDARD);
- do {
- // determine next state
- state= getCurrentState(state==NUMBER);
- // handle current state
- switch(state)
- {
- case KEYWORD:
- case KEYWORD_BEGIN:
- closeTag(STANDARD);
- eof=processKeywordState(state);
- openTag(STANDARD);
- break;
- case NUMBER:
- closeTag(STANDARD);
- eof=processNumberState();
- openTag(STANDARD);
- break;
- case ML_COMMENT_BEGIN:
- closeTag(STANDARD);
- eof=processMultiLineCommentState();
- openTag(STANDARD);
- break;
- case SL_COMMENT:
- closeTag(STANDARD);
- eof=processSingleLineCommentState();
- openTag(STANDARD);
- break;
- case STRING:
- closeTag(STANDARD);
- eof=processStringState(STANDARD);
- openTag(STANDARD);
- break;
- case DIRECTIVE_LINE:
- closeTag(STANDARD);
- eof=processDirectiveState();
- openTag(STANDARD);
- break;
- case TAG_BEGIN:
- closeTag(STANDARD);
- eof=processTagState();
- openTag(STANDARD);
- break;
- case ESC_CHAR:
- if (langInfo.allowExtEscSeq()){
- closeTag(STANDARD);
- eof=processEscapeCharState();
- openTag(STANDARD);
- } else {
- printMaskedToken();
- }
- break;
- case SYMBOL:
- closeTag(STANDARD);
- eof=processSymbolState();
- openTag(STANDARD);
- break;
- case _EOL:
- insertLineNumber(!firstLine);
- firstLine=false;
- break;
- case _EOF:
- eof=true;
- break;
- case _WS:
- processWsState();
- break;
- default:
- printMaskedToken();
- break;
- }
- }
- while (!eof);
- closeTag(STANDARD);
- *out << getNewLine();
- *out << flush;
-}
-
-bool CodeGenerator::processKeywordState(State myState){
- State newState=STANDARD;
- unsigned int myClassID=currentKeywordClass;
- bool eof=false,
- exitState=false;
-
- openKWTag(myClassID);
- do {
- printMaskedToken(newState!=_WS);
- newState= getCurrentState();
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- insertLineNumber();
- exitState=true;
- break;
- case _EOF:
- eof = true;
- break;
- case KEYWORD_END:
- if (myState==KEYWORD_BEGIN){
- printMaskedToken();
- }
- exitState=true;
- break;
- default:
- exitState= myState!=KEYWORD_BEGIN
- &&((myClassID!=currentKeywordClass)||(myState!=newState));
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeKWTag(myClassID);
-
- currentKeywordClass=0;
- return eof;
-}
-
-bool CodeGenerator::processNumberState(){
- State newState=STANDARD;
- bool eof=false,
- exitState=false;
-
- openTag(NUMBER);
- do {
- printMaskedToken(newState!=_WS);
- newState= getCurrentState(true);
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- insertLineNumber();
- exitState=true;
- break;
- case _EOF:
- eof = true;
- break;
- default:
- exitState=newState!=NUMBER;
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(NUMBER);
- return eof;
-}
-
-bool CodeGenerator::processMultiLineCommentState()
-{
- int commentCount=1;
- State newState=STANDARD;
- bool eof=false, exitState=false;
-
- openTag(ML_COMMENT_BEGIN);
- do {
- printMaskedToken(newState!=_WS);
- newState= getCurrentState();
-
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- wsBuffer += styleTagClose[ML_COMMENT_BEGIN];
- insertLineNumber();
- wsBuffer += styleTagOpen[ML_COMMENT_BEGIN];
- break;
- case _EOF:
- eof = true;
- break;
- case ML_COMMENT_BEGIN:
- if (langInfo.allowNestedMLComments()) {
- ++commentCount;
- }
- break;
- case ML_COMMENT_END:
- commentCount--;
- if (!commentCount){
- printMaskedToken();
- exitState=true;
- }
- break;
- default:
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(ML_COMMENT_BEGIN);
- return eof;
-}
-
-bool CodeGenerator::processSingleLineCommentState()
-{
-
- //if ( checkSpecialCmd()) return false;
-
- State newState=STANDARD;
- bool eof=false, exitState=false;
-
- openTag(SL_COMMENT);
- do {
- printMaskedToken(newState!=_WS);
- newState= getCurrentState();
-
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- printMaskedToken();
- insertLineNumber();
- exitState=true;
- break;
- case _EOF:
- eof = true;
- break;
- default:
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(SL_COMMENT);
- return eof;
-}
-
-bool CodeGenerator::processDirectiveState()
-{
- State newState=STANDARD;
- bool eof=false, exitState=false;
-
- openTag(DIRECTIVE_LINE);
- do {
- printMaskedToken(newState!=_WS);
- newState= getCurrentState();
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case DIRECTIVE_LINE_END:
- printMaskedToken();
- exitState=true;
- break;
- case _EOL:
- printMaskedToken();
- exitState=(terminatingChar!=langInfo.getContinuationChar());
- if (!exitState) wsBuffer += styleTagClose[DIRECTIVE_LINE];
- insertLineNumber();
- if (!exitState) wsBuffer += styleTagOpen[DIRECTIVE_LINE];
- break;
- case ML_COMMENT_BEGIN:
- closeTag(DIRECTIVE_LINE);
- eof= processMultiLineCommentState();
- openTag(DIRECTIVE_LINE);
- break;
- case SL_COMMENT:
- closeTag(DIRECTIVE_LINE);
- eof= processSingleLineCommentState();
- openTag(DIRECTIVE_LINE);
- exitState=true;
- break;
- case STRING:
- closeTag(DIRECTIVE_LINE);
- eof=processStringState(DIRECTIVE_LINE);
- openTag(DIRECTIVE_LINE);
- break;
- case _EOF:
- eof = true;
- break;
- default:
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(DIRECTIVE_LINE);
- return eof;
-}
-
-bool CodeGenerator::processStringState(State oldState)
-{
- State newState=STANDARD;
- bool eof=false, exitState=false;
- bool returnedFromOtherState=false;
- // Test if character before string open delimiter token equals to the
- // raw string prefix (Example: r" ", r""" """ in Python)
- bool isRawString=
- line[lineIndex-token.length()-1]==langInfo.getRawStringPrefix();
-
- string openStringDelimiter=token;
-
- State myState= (oldState==DIRECTIVE_LINE) ? DIRECTIVE_STRING : STRING;
- openTag(myState);
- do {
- // true if last token was an escape char
- if (!returnedFromOtherState) {
- printMaskedToken(newState!=_WS);
- }
- returnedFromOtherState=false;
- newState= getCurrentState();
-
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- wsBuffer += styleTagClose[myState];
- insertLineNumber();
- wsBuffer += styleTagOpen[myState];
- //exitState=true;
- break;
- case ML_COMMENT_END:
- printMaskedToken();
- break;
- case STRING:
- exitState= openStringDelimiter==token;
- printMaskedToken();
- break;
- case ESC_CHAR:
- if (!isRawString){
- closeTag(myState);
- eof=processEscapeCharState();
- openTag(myState);
- returnedFromOtherState=true;
- }
- break;
- case _EOF:
- eof = true;
- break;
- default:
- printMaskedToken();
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(myState);
- return eof;
-}
-
-bool CodeGenerator::processTagState()
-{
- State newState=STANDARD;
- bool eof=false, exitState=false, returnedFromOtherState=false;
- unsigned int myKeywordClass=currentKeywordClass;
-
- openTag(KEYWORD);
- do {
- if (!returnedFromOtherState) {
- printMaskedToken(newState!=_WS);
- }
- returnedFromOtherState = false;
- newState= getCurrentState();
-
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- insertLineNumber();
- exitState=true;
- break;
- case TAG_END:
- printMaskedToken();
- exitState=true;
- break;
- case STRING:
- closeTag(KEYWORD);
- eof=processStringState(KEYWORD);
- currentKeywordClass=myKeywordClass;
- openTag(KEYWORD);
- returnedFromOtherState = true;
- break;
- case ESC_CHAR:
- closeTag(KEYWORD);
- eof=processEscapeCharState();
- currentKeywordClass=myKeywordClass;
- openTag(KEYWORD);
- returnedFromOtherState = true;
- break;
- case NUMBER:
- closeTag(KEYWORD);
- eof=processNumberState();
- currentKeywordClass=myKeywordClass;
- openTag(KEYWORD);
- returnedFromOtherState = true;
- break;
- case _EOF:
- eof = true;
- break;
- default:
- printMaskedToken();
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(KEYWORD);
- currentKeywordClass=0;
-
- return eof;
-}
-
-bool CodeGenerator::processSymbolState(){
-
- State newState=STANDARD;
- bool eof=false,
- exitState=false;
-
- openTag(SYMBOL);
- do {
- printMaskedToken(newState!=_WS);
- newState= getCurrentState(true);
- switch(newState)
- {
- case _WS:
- processWsState();
- break;
- case _EOL:
- insertLineNumber();
- exitState=true;
- break;
- case _EOF:
- eof = true;
- break;
- default:
- exitState=newState!=SYMBOL;
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(SYMBOL);
- return eof;
-}
-
-bool CodeGenerator::processEscapeCharState()
-{
- State newState=STANDARD;
- bool eof=false, exitState=false;
-
- openTag(ESC_CHAR);
- do {
- printMaskedToken(newState!=_WS);
- skipEscapeSequence();
- newState= getCurrentState();
- switch(newState)
- {
- case _EOL:
- insertLineNumber();
- exitState=true;
- break;
- case _WS:
- processWsState();
- --lineIndex;
- break;
- case _EOF:
- eof = true;
- break;
- default:
- exitState=newState!=ESC_CHAR;
- break;
- }
- } while ((!exitState) && (!eof));
-
- closeTag(ESC_CHAR);
- return eof;
-}
-
-void CodeGenerator::skipEscapeSequence(){
- if (lineIndex<line.length()){
- char c=line[lineIndex];
- int charsToSkip=1;
- // Escape Sequenz /ooo Oktal, /x000 hex, /u00xx Java unicode
- if (isdigit(c) ){
- // \0 abfangen
- while ( isdigit(line[lineIndex+charsToSkip]) && charsToSkip<4) {
- ++charsToSkip;
- }
- } else if (tolower(c)=='x'){
- charsToSkip=langInfo.isJava() ? 4 : 3;
- } else if (tolower(c)=='u'){
- charsToSkip=5;
- }
- while (charsToSkip-- && lineIndex++<line.length()){
- *out <<maskCharacter(line[lineIndex-1]);
- }
- }
-}
-
-
-void CodeGenerator::processWsState()
-{
- if (!maskWs) {
- wsBuffer += token;
- token.clear();
- return;
- }
- flushWs();
- int cntWs=0;
- lineIndex--;
-
- while (isspace(line[lineIndex]) ) {
- ++cntWs;
- ++lineIndex;
- }
-
- if (cntWs>1) {
- unsigned int styleID=getStyleID(currentState, currentKeywordClass);
- if (excludeWs && styleID!=_UNKNOWN) {
- *out << styleTagClose[styleID];
- }
- *out << maskWsBegin;
- for (int i=0; i<cntWs; i++){
- *out << spacer;
- }
- *out << maskWsEnd;
- if (excludeWs && styleID!=_UNKNOWN){
- *out << styleTagOpen[styleID];
- }
- } else {
- *out << token;
- }
- token.clear();
-}
-
-void CodeGenerator::flushWs(){
- *out<<wsBuffer;
- wsBuffer.clear();
-}
-
-bool CodeGenerator::isFirstNonWsChar() {
- unsigned int i=lineIndex-1;
- while (i--){
- if (!isspace(line[i])){
- return false;
- }
- }
- return true;
-}
-
-string CodeGenerator::getNewLine(){
- return newLineTag;
-}
-
-void CodeGenerator::insertLineNumber(bool insertNewLine) {
- if (insertNewLine){
- wsBuffer += getNewLine();
- }
- if (showLineNumbers) {
- ostringstream os;
- ostringstream numberPrefix;
- if (lineNumberFillZeroes) {
- os.fill('0');
- }
- os <<setw(LINE_NUMBER_WIDTH) << right << lineNumber;
-
- numberPrefix << styleTagOpen[LINENUMBER]
- << maskString(os.str()) << spacer
- << styleTagClose[LINENUMBER];
-
- wsBuffer += numberPrefix.str();
- }
-}
-
-unsigned int CodeGenerator::getLineIndex(){
- return lineIndex;
-}
-
-bool CodeGenerator::printExternalStyle(const string &outFile)
-{
- if (!includeStyleDef && langInfo.getSyntaxHighlight()) {
- ofstream cssOutFile(outFile.c_str());
- if (cssOutFile) {
- cssOutFile << styleCommentOpen
- <<" Style definition file generated by highlight "
- << HIGHLIGHT_VERSION << ", " << HIGHLIGHT_URL
- << " " << styleCommentClose << "\n";
- cssOutFile << "\n"<<styleCommentOpen<<" Highlighting theme definition: "
- << styleCommentClose << "\n\n"
- << getStyleDefinition()
- << "\n";
- cssOutFile << readUserStyleDef();
- cssOutFile.close();
- } else {
- return false;
- }
- }
- return true;
-}
-
-string CodeGenerator::readUserStyleDef(){
- ostringstream ostr;
- if (!styleInputPath.empty()){
- ifstream userStyleDef(styleInputPath.c_str());
- if (userStyleDef) {
- ostr << "\n"<<styleCommentOpen<<" Content of "<<styleInputPath<<": "<<styleCommentClose<<"\n";
- string line;
- while (getline(userStyleDef, line)){
- ostr << line << "\n";
- }
- userStyleDef.close();
- } else {
- ostr << styleCommentOpen<<" ERROR: Could not include "
- << styleInputPath
- << "."<<styleCommentClose<<"\n";
- }
- }
- return ostr.str();
-}
-
-bool CodeGenerator::checkSpecialCmd(){
- bool insertNL = (lineIndex-token.length());
- cerr << "token: "<<token<< " index"<< lineIndex << " "<<line [ lineIndex ]<<endl;
-
- if (line [ lineIndex ]=='!'){
- // find cmd
- size_t cmdPos1 = line.find('@', lineIndex+1);
-
- cerr << "cmdPos"<<cmdPos1<<endl;
- if(cmdPos1==string::npos) return false;
- size_t cmdPos2=cmdPos1+1;
- while (cmdPos2 < line.length() && StringTools::isAlpha(line[cmdPos2])) cmdPos2++;
- cerr << "cmdPos2"<<cmdPos2<<endl;
- cerr << line.substr(cmdPos1, cmdPos2)<<endl;
-
- // hide comment line
- token.clear();
- lineIndex=line.length();
- getInputChar(); lineNumber--;
- if (insertNL) { lineNumber++;insertLineNumber();};
- // end hide
-
- return true;
- }
-
- return false;
-}
-
-}
-/***************************************************************************
- codeparser.h - description
- -------------------
- begin : Die Jul 9 2002
- copyright : (C) 2002 by Andre 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 CODEPARSER_H
-#define CODEPARSER_H
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <iomanip>
-#include <cctype>
-
-#include "languagedefinition.h"
-#include "documentstyle.h"
-#include "ASFormatter.h"
-#include "preformatter.h"
-#include "enums.h"
-
-
-#define NUMBER_BUILTIN_STYLES 10
-#define LINE_NUMBER_WIDTH 5
-#define MAX_LINE__WIDTH 80
-
-#define OUTPUT_FLAG_LN 1
-#define OUTPUT_FLAG_LNZ 2
-#define OUTPUT_FLAG_FRAG 4
-
-/** The highlight namespace contains all classes and data structures
- needed for parsing input data.
-*/
-namespace highlight {
-
-/** \brief Base class for parsing. Works similar to a Turing machine.
-
- The virtual class provides source code parsing functioality, based on
- information stored in language definitions.<br>
- Deriving classes have to define the output format.<br>
- Codegenerator is a singleton class.
-
-* @author Andre Simon
-*/
-
-class CodeGenerator
- {
-
- public:
-
- virtual ~CodeGenerator();
-
- /**
- Get appropriate Codegenerator instance
- \param type Output file type (HTML, XHTML, RTF, LATEX, TEX, XSLFO, ANSI)
- \param styleInfoPath Path to formatting style information
- \param styleInPath Path to style definition input file (to be included in styleOutPath)
- \param styleOutPath Path to style definition output file (CSS path for HTML output)
- \param encoding Output file encoding name
- \param includeStyle Switch to include style information in output file (only XHTML, HTML)
- \param attachAnchors Switch to attach anchors to line numbers (only XHTML, HTML)
- \param replaceQuotes Switch to replace quotes by \dq{} (only LATEX)
- \param fopCompatible Switch to generate FO for Apache FOP (only XSLFO)
- \param omitEncoding Switch to omit encoding info in output document
- \param ln Set true if line numbers should be printed
- \param lnz Set true if leading space of line numbers should be filled with 0's
- \param fragment Set true if document header and footer should be omitted
- \param numSpaces Number of spaces which replace a tab
- \param lineWrappingMode Line wrapping mode
- */
- static 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 );
-
- /** Deletes the singleton CodeGenerator instance.
- Call this method if getInstance was already called, or if you want to
- free the momory after usage.*/
- static void deleteInstance();
-
- /**
- Generates output
- \param inFileName Path of input file (if empty use stdin)
- \param outFileName Path of input file (if empty use stdout)
-
- \return ParseError
- */
- ParseError printOutput(const string &inFileName, const string &outFileName);
-
- /** \return True if document style was found */
- bool styleFound();
-
- /** \return True if reformatting of current input is disabled */
- bool formattingDisabled();
-
- /** \return True if reformatting of current input is possible */
- bool formattingIsPossible();
-
- /** \param langDefPath Absolute path to language definition
- \return Failure: LOAD_FAILED; Reload necessary: LOAD_NEW,
- no reload necessary: LOAD_NONE */
- LoadResult initLanguage(const string& langDefPath);
-
- /** \return Language definition*/
- LanguageDefinition &getLanguage();
-
- /** tell parser to output line numbers
- \param flag true if line numbers should be printed
- */
- void setPrintLineNumbers(bool flag);
-
- /** \return line number flag */
- bool getPrintLineNumbers();
-
-
- /** tell parser to output line numbers filled with zeroes
- \param flag true if zeroes should be printed
- */
- void setPrintZeroes(bool flag);
-
- /** \return print zeroes flag */
- bool getPrintZeroes();
-
- /** tell parser to omit document header and footer
- \param flag true if output should be fragmented
- */
- void setFragmentCode(bool flag);
-
- /** \return fragment flag */
- bool getFragmentCode();
-
- /** tell parser the style name
- \param s path to style definition
- */
- void setStyleName(const string& s);
-
- /** \return style path */
- const string& getStyleName();
-
- /** tell parser the wrapping mode
- \param lineWrappingStyle wrapping style
- \param lineLength max line length
- \param numberSpaces number of spaces which replace a tab
- */
- void setPreformatting(WrapMode lineWrappingStyle, unsigned int lineLength,int numberSpaces);
-
- /** \return wrapping style */
- WrapMode getLineWrapping();
-
- /** tell parser the include style definition in output
- \param flag true if style should be included
- */
- void setIncludeStyle(bool flag);
-
- /** Print style definitions to external file
- \param outFile Path of external style definition
- */
- bool printExternalStyle(const string &outFile);
-
- /** Print index file with all input file names
- \param fileList List of output file names
- \param outPath Output path
- */
- virtual bool printIndexFile(const vector<string> & fileList,
- const string &outPath);
-
- /** initialize source code indentation
- \param indentSchemePath Path of indentation scheme
- \return true id successfull
- */
- bool initIndentationScheme(const string&indentSchemePath);
-
- /** Set style input path
- \param s path to style input file
- */
- void setStyleInputPath(const string& path);
-
- /** Set style output path
- \param s path to style output file
- */
- void setStyleOutputPath(const string& path);
-
-/** Set output type
- \param s output type
- */
- void setType(OutputType t);
-
- /**
- \return style input file path
- */
- const string& getStyleInputPath();
-
- /**
- \return style output file path
- */
- const string& getStyleOutputPath();
-
-protected:
-
- CodeGenerator();
-
- //! CodeGenerator Constructor
- /**
- \param colourTheme Name of coloring style being used
- */
- CodeGenerator(const string &colourTheme);
-
- /** \param c Character to be masked
- \return Escape sequence of output format */
- virtual string maskCharacter(unsigned char c) = 0;
-
- /** \param s string
- \return Copy of s with all escaped characters */
- string maskString(const string &s ) ;
-
- /** \param s Symbol string
- \param searchPos Position where search starts
- \return Found state (integer value) */
- State getState(const string &s, unsigned int searchPos);
-
- /** \return Next identifier in current line of code */
- string getIdentifier();
-
- /** \return Next number in current line of code */
- string getNumber();
-
- /** Insert line number at the beginning of current output line */
- virtual void insertLineNumber(bool insertNewLine=true);
-
- /** Prints document footer*/
- virtual string getFooter() = 0;
-
- /** Prints document body*/
- virtual void printBody() = 0;
-
- /** prints document header
- \param title Title of the document
- */
- virtual string getHeader(const string &title) = 0;
-
- /** Get current line number
- \return line number */
- unsigned int getLineNumber();
-
-
- /** Tag Delimiters for every colour style*/
- vector <string> styleTagOpen, styleTagClose;
-
- /** Description of document colour style*/
- DocumentStyle docStyle;
-
- /** Language definition*/
- LanguageDefinition langInfo;
-
- /** Tag for inserting line feeds*/
- string newLineTag;
-
- /** String that represents a white space in output */
- string spacer;
-
- /** file input*/
- istream *in;
-
- /** file output*/
- ostream *out;
-
- /** Tags which enclose white space indentation blocks */
- string maskWsBegin, maskWsEnd;
-
- /** Style comment delimiters */
- string styleCommentOpen, styleCommentClose;
-
- /** Test if maskWsBegin and maskWsEnd should be applied */
- bool maskWs;
-
- /** Test if whitespace sould always be separated from enclosing tokens */
- bool excludeWs;
-
- /** Test if header and footer should be omitted */
- bool fragmentOutput;
-
- /** Test if line numbers should be printed */
- bool showLineNumbers;
-
- /** Test if leading spyce of line number should be filled with zeroes*/
- bool lineNumberFillZeroes;
-
- /** Current line of input file*/
- string line;
-
- /** Current line number */
- unsigned int lineNumber;
-
- // Zeigt den aktuellen Zustand an
- // wird nicht in getCurrentState gesetzt, da nur Zustände interessant
- // sind, die als Index auf die styleCloseTags und styleOpenTags verwendet
- // werden können
- /** Current state*/
- State currentState;
-
- /** keyword class id, used to apply the corresponding keyword style*/
- unsigned int currentKeywordClass;
-
- /** Processes origin state */
- void processRootState();
-
- /** return line break sequence */
- virtual string getNewLine();
-
- /**
- \param s current state
- \return Index of style tag corresponding to the states
- */
- unsigned int getStyleID(State s, unsigned int kwClassID = 0);
-
- /** \return line index */
- unsigned int getLineIndex();
-
- /** print all remaining white space*/
- void flushWs();
-
- /**
- \return Content of user defined input style
- */
- string readUserStyleDef();
-
- /**
- \return Style definition of the chosen output format
- */
- virtual string getStyleDefinition() {return "";};
-
- /** contains white space, which will be printed after a closing tag */
- string wsBuffer;
-
- /**
- Flag to test if style definition should be included in output document
- */
- bool includeStyleDef;
-
-private:
-
- CodeGenerator(const CodeGenerator&){}
- CodeGenerator& operator=(CodeGenerator&){ return *this;}
-
- static CodeGenerator* generator;
-
- /** return matching open and close tags of the given state */
- virtual string getMatchingOpenTag(unsigned int) = 0;
- virtual string getMatchingCloseTag(unsigned int) = 0;
-
- /** open a new tag, set current state to s*/
- void openTag(State s);
-
- /** close opened tag, clear current state */
- void closeTag(State s);
-
- void closeTag(unsigned int styleID);
-
- void openTag(unsigned int styleID);
-
- // path to style definition file
- string stylePath;
-
- // contains current position in line
- unsigned int lineIndex;
-
- /**last character of the last line*/
- unsigned char terminatingChar;
-
- /** Class for reformatting */
- astyle::ASFormatter *formatter;
-
- /** Class for line wrapping and tab replacement*/
- PreFormatter *preFormatter;
-
- /** Flag to test if formatting is enabled with current input document*/
- bool formattingEnabled;
-
-
- /** Flag to test if formatting is possible with current input document*/
- bool formattingPossible;
-
- /** contains the current token*/
- string token;
-
- string styleInputPath, styleOutputPath;
-
- /** Resets parser to origin state, call this after every file conversion */
- void reset();
-
- /** read new line from in stream */
- bool readNewLine(string &newLine);
-
- /** return next character from in stream */
- unsigned char getInputChar();
-
- OutputType outputType;
-
- /** return new state */
- State getCurrentState ( bool lastStateWasNumber=false);
-
- /** Methods that represent a parsing state */
- bool processKeywordState(State myState) ;
- bool processNumberState() ;
- bool processMultiLineCommentState();
- bool processSingleLineCommentState();
- bool processStringState(State oldState);
- bool processEscapeCharState();
- bool processDirectiveState();
- bool processTagState();
- bool processSymbolState();
- void processWsState();
-
- /** gibt true zurck, falls c ein erlaubter Character innerhalb von Keyword
- oder Typbezeichner ist */
- bool isAllowedChar(char c) ;
-
- /** returns true if curret token is the first in line and no whitespace */
- bool isFirstNonWsChar() ;
-
- /** print escaped token and clears it */
- void printMaskedToken(bool flushWhiteSpace=true);
-
- /** print escape sequence */
- void skipEscapeSequence();
-
- void closeKWTag(unsigned int styleID);
- void openKWTag(unsigned int styleID);
-
- /** look for special commands in comments, take action in derived class
- \return true if command was found
- */
- bool checkSpecialCmd();
-
- };
-}
-
-#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.
- */
-
-
-
-
-
-/*
- * comment out the line below if your compiler does NOT understand NAMESPACES
- */
-#define USES_NAMESPACE
-
-
-#if defined(__GNUC__) && __GNUC__ < 3
-// for G++ implementation of string.compare:
-#define COMPARE(place, length, str) compare((str), (place), (length))
-#else
-// for standard implementation of string.compare:
-#define COMPARE(place, length, str) compare((place), (length), (str))
-#endif
-
-
-// Fix by John A. McNamara
-// Get rid of annoying MSVC warnings on debug builds about lengths of
-// identifiers in template instantiations.
-#ifdef _MSC_VER
-#pragma warning( disable:4786 )
-#endif
-
-/***************************************************************************
- configurationreader.cpp - description
- -------------------
- begin : Son Nov 10 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 "configurationreader.h"
-
-using namespace std;
-
-ConfigurationReader::ConfigurationReader(const string & configuration_path)
-{
- ifstream in (configuration_path.c_str());
- fileFound=in;
- if (fileFound) {
- string line;
- line.reserve(500);
- unsigned int lineBegin;
- size_t delimPos;
- string paramName, paramValue;
- while (getline(in, line)) {
- lineBegin=line.find_first_not_of("\t ");
- if ((line.size()>2) && (lineBegin!=string::npos)
- && (line.at(lineBegin)!='#')) { //comment?
- if (line[lineBegin]=='$') { // neuer Parametername?
- delimPos=line.find("=",lineBegin)-1;
- if (delimPos!=string::npos) {
- paramName=StringTools::trimRight(
- StringTools::lowerCase(line.substr(lineBegin+1, delimPos)));
- parameterNames.push_back(paramName);
- paramValue=line.substr(delimPos+2, line.length());
- }
- } else { // line belongs to last parameter
- paramValue=line;
- }
- if (parameterMap[paramName].empty()) {
- parameterMap[paramName] = paramValue;
- } else {
- parameterMap[paramName]+= (" "+paramValue);
- }
- } //if ((lineBegin!=string::npos) && (line.at(lineBegin)!='#'))
- } //while
- in.close();
- } //if (in)
-}
-
-ConfigurationReader::~ConfigurationReader()
-{
-}
-
-bool ConfigurationReader::found()
-{
- return fileFound;
-}
-
-string &ConfigurationReader::getParameter(const string & paramName)
-{
- return parameterMap[paramName] ;
-}
-
-const char* ConfigurationReader::getCParameter(const string & paramName)
-{
- return parameterMap[paramName].c_str() ;
-}
-
-vector<string> &ConfigurationReader::getParameterNames()
-{
- return parameterNames;
-}
-/***************************************************************************
- configurationreader.h - description
- -------------------
- begin : Son Nov 10 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. *
- * *
- ***************************************************************************/
-
-#ifndef CONFIGURATIONREADER_H
-#define CONFIGURATIONREADER_H
-
-#include <string>
-#include <sstream>
-#include <map>
-#include <iostream>
-#include <fstream>
-#include <vector>
-
-#include "stringtools.h"
-
-using namespace std;
-
-/** Maps parameter keys to values*/
-typedef map<string, string> ParameterMap;
-
-
-/** \brief Class to handle ASCII config files
-
- Configuration file format:<br>
- $ParamName=ParamValue<br>
- ParamValue may be splittet over multiple lines<br>
- ParamName is not case sensitive<br>
- Comments start with # as the first character of a line
-
- **/
-
-class ConfigurationReader
- {
- public:
- /** Constructor
- \param configuration_path Path to configuration file
- */
- ConfigurationReader(const string & configuration_path);
- ~ConfigurationReader();
-
- /** \param paramName Name of parameter
- \return Value of parameter */
- string &getParameter(const string & paramName);
-
- /** \param paramName Name of parameter
- \return Value of parameter */
- const char* getCParameter(const string & paramName);
-
- /** \return True if config file exists */
- bool found();
-
- /** \return List of parameter names */
- vector<string> &getParameterNames();
-
- private:
- ParameterMap parameterMap;
- bool fileFound;
- vector<string> parameterNames;
- };
-
-#endif
-/***************************************************************************
- dataDir.cpp - description
- -------------------
- begin : Sam M� 1 2003
- copyright : (C) 2003 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 "datadir.h"
-
-using namespace std;
-
-bool DataDir::searchDataDir(const string &userDefinedDir){
-#ifndef _WIN32
-
- bool found = false;
- //falls kein Datenverzeichnis angegeben, startIndex auf 1 setzen
- int searchStartIndex=(userDefinedDir.empty());
-
- string possibleDirs[] ={ userDefinedDir,
- #ifdef HL_DATA_DIR
- HL_DATA_DIR,
- #endif
- "/usr/share/highlight/"
- };
-
- for (int i=searchStartIndex;i<
- #ifdef HL_DATA_DIR
- 3
- #else
- 2
- #endif
- ;i++)
- {
- if (fileExists(possibleDirs[i]))
- {
- dataDir=possibleDirs[i];
- found = true;
- }
- if (found) {
- break;
- }
- else {
- if (!searchStartIndex)
- cerr << "highlight: directory "
- << userDefinedDir
- << " specified by data-dir option not found.\n"
- << " Searching another standard directory.\n";
-
- }
- }
- return found;
-#else
- dataDir=userDefinedDir;
- return true;
-#endif
-
-}
-
-DataDir::DataDir()
-{
-}
-
-void DataDir::setAdditionalDataDir(const string& dir){
- additionalDataDir=dir;
-}
-
-const string &DataDir::getDir()
-{
- return dataDir;
-}
-
-const string DataDir::getLangDefDir()
-{
- return dataDir+"langDefs"+Platform::pathSeparator;
-}
-
-const string DataDir::getThemeDir()
-{
- return dataDir+"themes"+Platform::pathSeparator;
-}
-
-const string DataDir::getIndentSchemesDir()
-{
- return dataDir+"indentSchemes"+Platform::pathSeparator;
-}
-
-
-const string DataDir::getAdditionalLangDefDir()
-{
- return additionalDataDir+"langDefs"+Platform::pathSeparator;
-}
-
-const string DataDir::getAdditionalThemeDir()
-{
- return additionalDataDir+"themes"+Platform::pathSeparator;
-}
-const string DataDir::getAdditionalIndentSchemesDir()
-{
- return additionalDataDir+"indentSchemes"+Platform::pathSeparator;
-}
-
-
-const string DataDir::getHelpMsgDir()
-{
- return dataDir+"helpmsg"+Platform::pathSeparator;
-}
-
-const string DataDir::searchForLangDef(const string & langDef){
- if (!additionalDataDir.empty()){
- string path=getAdditionalLangDefDir()+langDef;
- if (fileExists(path)){
- return path;
- }
- }
- return getLangDefDir()+langDef;
-}
-
-const string DataDir::searchForTheme(const string & theme){
- if (!additionalDataDir.empty()){
- string path=getAdditionalThemeDir()+theme;
- if (fileExists(path)){
- return path;
- }
- }
- return getThemeDir()+theme;
-}
-
-const string DataDir::searchForIndentScheme(const string & scheme){
- if (!additionalDataDir.empty()){
- string path=getAdditionalIndentSchemesDir()+scheme;
- if (fileExists(path)){
- return path;
- }
- }
- return getIndentSchemesDir()+scheme;
-}
-
-
-bool DataDir::fileExists(const string&f){
- ifstream file(f.c_str());
- bool exists=!file.fail();
- file.close();
- return exists;
-}
-/***************************************************************************
- datadir.h - description
- -------------------
- begin : Sam M� 1 2003
- copyright : (C) 2003 by Andre 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 DATADIR_H
-#define DATADIR_H
-
-#include <string>
-#include <fstream>
-#include <iostream>
-//#include "stringtools.h"
-#include "platform_fs.h"
-
-using namespace std;
-
- /** \brief Manages access to installation directories.
-
- Apart from the standard installation directory, one can define additional
- search paths.
- **/
-
-class DataDir
- {
- string dataDir;
- string additionalDataDir;
- bool fileExists(const string&f);
-
- public:
-
- DataDir();
-
- /** search for a valid installation directory
- \param userDefinedDir Directory defined by user
- \return True if directory was found */
- bool searchDataDir(const string &userDefinedDir);
-
- /** add another installation directory, which is added to search path
- \param dir Directory defined by user */
- void setAdditionalDataDir(const string& dir);
-
- /** \return Data installation directory */
- const string & getDir() ;
-
- /** \return Location of languafe definitions */
- const string getLangDefDir() ;
-
- /** \return Location of themes */
- const string getThemeDir() ;
-
- /** \return Location of indentation schemes */
- const string getIndentSchemesDir();
-
- /** \return User defined location of indentation schemes */
- const string getAdditionalIndentSchemesDir();
-
- /** \return User defined location of languafe definitions */
- const string getAdditionalLangDefDir() ;
-
- /** \return User defined location of themes */
- const string getAdditionalThemeDir() ;
-
- /** \return Location of help files */
- const string getHelpMsgDir() ;
-
- /** \param langDef Name of language definition
- \return Absolute path of definiton found in a data directory */
- const string searchForLangDef(const string & langDef);
-
- /** \param theme Name of colour theme file
- \return Absolute path of theme found in a data directory */
- const string searchForTheme(const string & theme);
-
- /** \param scheme Name of indent scheme file
- \return Absolute path of theme found in a data directory */
- const string searchForIndentScheme(const string & scheme);
- };
-
-#endif
-/***************************************************************************
- documentstyle.cpp - description
- -------------------
- begin : Son Nov 10 2002
- copyright : (C) 2002 by Andre 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 "documentstyle.h"
-
-namespace highlight {
-
-DocumentStyle::DocumentStyle(const string &styleDefinitionFile)
-{
- fileFound=load(styleDefinitionFile);
-}
-DocumentStyle::DocumentStyle():fileFound(false)
-{}
-
-bool DocumentStyle::load(const string &styleDefinitionPath)
-{
- ConfigurationReader styleConfig(styleDefinitionPath);
- if (styleConfig.found()){
- fontsize = styleConfig.getParameter("fontsize");
- bgColour.setRGBValues(styleConfig.getParameter("bgcolour"));
- defaultElem.set(styleConfig.getParameter("defaultcolour"));
- comment.set(styleConfig.getParameter("comment"));
- directive.set(styleConfig.getParameter("directive"));
- str.set(styleConfig.getParameter("string"));
- escapeChar.set(styleConfig.getParameter("escapechar"));
- number.set(styleConfig.getParameter("number"));
- dstr.set(styleConfig.getParameter("string_directive"));
- line.set(styleConfig.getParameter("line"));
-
-
- string tmpstr;
- // TODO: Remove this check as soon as all themes have a brackets attribute
- tmpstr=styleConfig.getParameter("symbol");
- if (tmpstr.empty()) {
- tmpstr=styleConfig.getParameter("defaultcolour");
- }
- symbol.set(tmpstr);
-
-// TODO: Remove this check as soon as all themes have a sl-comment attribute
- tmpstr=styleConfig.getParameter("sl-comment");
- if (tmpstr.empty()) {
- tmpstr=styleConfig.getParameter("comment");
- }
- slcomment.set(tmpstr);
-
- string paramVal;
- vector<string> paramNames=styleConfig.getParameterNames();
-
- //collect keyword classes, save corresponding style definition
- for (unsigned int i=0;i<paramNames.size();i++){
- paramVal=paramNames[i];
- if (paramVal.find("kw_class") != string::npos){
- keywordStyles.insert(make_pair(StringTools::getParantheseVal(paramVal),
- new ElementStyle(styleConfig.getParameter(paramVal))));
- }
- }
-
- fileFound = true;
- }
- else {
- fileFound = false;
- }
- return fileFound;
-}
-
-DocumentStyle::~DocumentStyle()
-{
- for(KSIterator iter = keywordStyles.begin(); iter != keywordStyles.end(); iter++){
- delete (*iter).second; //remove ElementStyle*
- }
-}
-
-string& DocumentStyle::getFontSize()
- {
- return fontsize;
- }
-StyleColour& DocumentStyle::getBgColour()
- {
- return bgColour;
- }
-ElementStyle& DocumentStyle::getDefaultStyle()
- {
- return defaultElem;
- }
-ElementStyle& DocumentStyle::getCommentStyle()
- {
- return comment;
- }
-ElementStyle& DocumentStyle::getSingleLineCommentStyle()
- {
- return slcomment;
- }
-
-
-ElementStyle& DocumentStyle::getStringStyle()
- {
- return str;
- }
-ElementStyle& DocumentStyle::getDirectiveStringStyle()
- {
- return dstr;
- }
-ElementStyle& DocumentStyle::getEscapeCharStyle()
- {
- return escapeChar;
- }
-ElementStyle& DocumentStyle::getNumberStyle()
- {
- return number;
- }
-ElementStyle& DocumentStyle::getDirectiveStyle()
- {
- return directive;
- }
-ElementStyle& DocumentStyle::getLineStyle()
- {
- return line;
- }
-ElementStyle& DocumentStyle::getSymbolStyle()
- {
- return symbol;
- }
-bool DocumentStyle::found () const
- {
- return fileFound;
- }
-ElementStyle& DocumentStyle::getKeywordStyle(const string &className){
- if (!keywordStyles.count(className)) return defaultElem;
- return *keywordStyles[className];
-}
-
-vector <string> DocumentStyle::getClassNames(){
- vector <string> kwClassNames;
- for(KSIterator iter = keywordStyles.begin(); iter != keywordStyles.end(); iter++){
- kwClassNames.push_back( (*iter).first);
- }
- return kwClassNames;
-}
-
-KeywordStyles& DocumentStyle::getKeywordStyles(){
- return keywordStyles;
-}
-
-}
-/***************************************************************************
- documentstyle.h - description
- -------------------
- begin : Son Nov 10 2002
- copyright : (C) 2002 by Andre 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 DOCUMENTSTYLE_H
-#define DOCUMENTSTYLE_H
-
-#include <string>
-#include <iostream>
-#include "configurationreader.h"
-#include "elementstyle.h"
-#include "stylecolour.h"
-
-using namespace std;
-
-namespace highlight {
-
-/** maps keyword class names and the corresponding formatting information*/
-typedef map <string, ElementStyle*> KeywordStyles;
-
-/** iterator for keyword styles*/
-typedef KeywordStyles::iterator KSIterator;
-
-/** \brief Contains information about document formatting properties.
-
-* @author Andre Simon
-*/
-
-class DocumentStyle
- {
- private:
- ElementStyle comment, slcomment, str, dstr,
- escapeChar, number, directive, line, symbol;
- ElementStyle defaultElem;
- StyleColour bgColour;
-
- string fontsize;
- bool fileFound;
-
- KeywordStyles keywordStyles;
-
- public:
- /** Constructor
- \param styleDefinitionPath Style definition path */
- DocumentStyle(const string & styleDefinitionPath);
- DocumentStyle();
- ~DocumentStyle();
-
- /** load sytle definition
- \param styleDefinitionFile Style definition path
- \return True if successfull */
- bool load(const string & styleDefinitionFile);
-
- /** \return class names defined in the theme file */
- vector <string> getClassNames();
-
- /** \return keyword styles */
- KeywordStyles& getKeywordStyles();
-
- /** \return Font size */
- string &getFontSize() ;
-
- /** \return Background colour*/
- StyleColour& getBgColour();
-
- /** \return Style of default (unrecognized) strings */
- ElementStyle & getDefaultStyle() ;
-
- /** \return Comment style*/
- ElementStyle & getCommentStyle() ;
-
- /** \return Single line comment style*/
- ElementStyle& getSingleLineCommentStyle() ;
-
- /** \return Keyword style*/
- ElementStyle & getKeywordStyle() ;
-
- /** \return String style*/
- ElementStyle & getStringStyle() ;
-
- /** \return Directive line string style*/
- ElementStyle & getDirectiveStringStyle() ;
-
- /** \return Escape character style*/
- ElementStyle & getEscapeCharStyle() ;
-
- /** \return Number style*/
- ElementStyle & getNumberStyle() ;
-
- /** \return Directive style*/
- ElementStyle & getDirectiveStyle() ;
-
- /** \return Type style*/
- ElementStyle & getTypeStyle() ;
-
- /** \return Line number style*/
- ElementStyle & getLineStyle() ;
-
- /** \return Bracket style*/
- ElementStyle & getSymbolStyle() ;
-
- /**
- \param className Name of keyword class
- \return keyword style of the given className
- */
- ElementStyle & getKeywordStyle(const string &className);
-
- /** \return True if language definition was found */
- bool found() const ;
- };
-
-}
-
-#endif
-/***************************************************************************
- elementstyle.cpp - description
- -------------------
- begin : Son Nov 10 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 "elementstyle.h"
-
-namespace highlight {
-
-ElementStyle::ElementStyle(StyleColour col, bool b, bool i, bool u)
- : colour(col) , bold(b), italic(i), underline(u)
-{}
-
-ElementStyle:: ElementStyle(const string & elementStyleString)
- : bold(false), italic(false), underline(false)
-{
- set(elementStyleString);
-}
-
-ElementStyle::ElementStyle()
- : bold(false), italic(false), underline(false)
-{}
-
-void ElementStyle::set(const string & elementStyleString){
-
- istringstream valueStream(elementStyleString.c_str());
- string r, g, b, attr;
- valueStream >> r;
- valueStream >> g;
- valueStream >> b;
- colour.setRedValue(r);
- colour.setGreenValue(g);
- colour.setBlueValue(b);
- while ( valueStream >> attr)
- {
- if (attr=="italic")
- {
- italic = true;
- }
- else if (attr=="bold")
- {
- bold = true;
- }
- else if (attr=="underline")
- {
- underline = true;
- }
- }
-}
-
-ElementStyle::~ElementStyle()
-{}
-
-bool ElementStyle::isItalic() const
-{
- return italic;
-}
-bool ElementStyle::isBold() const
-{
- return bold;
-}
-bool ElementStyle::isUnderline() const
-{
- return underline;
-}
-StyleColour ElementStyle::getColour() const
-{
- return colour;
-}
-
-}
-/***************************************************************************
- elementstyle.h - description
- -------------------
- begin : Son Nov 10 2002
- copyright : (C) 2002 by Andre 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 ELEMENTSTYLE_H
-#define ELEMENTSTYLE_H
-
-#include <sstream>
-
-#include "stylecolour.h"
-
-using namespace std;
-
-namespace highlight {
-
-/** \brief The class stores the basic text formatting properties.
-
-* @author Andre Simon
-*/
-
-class ElementStyle {
- public:
-
- /** Constructor
- \param col Style colour
- \param b Bold flag
- \param i Italic flag
- \param u Underline flag */
- ElementStyle(StyleColour col, bool b, bool i, bool u);
-
- /** Constuctor
- \param elementStyleString String with fotmatting information */
- ElementStyle(const string & elementStyleString);
-
- ElementStyle();
-
- ~ElementStyle();
-
- /** initialize object
- \param elementStyleString String which contains formatting attributes
- */
- void set(const string & elementStyleString);
-
- /** \return True if italic */
- bool isItalic() const;
-
- /** \return True if bold */
- bool isBold() const;
-
- /** \return True if underline */
- bool isUnderline() const;
-
- /** \return Element colour */
- StyleColour getColour() const;
-
- private:
- StyleColour colour;
- bool bold, italic, underline;
- };
-
-}
-
-#endif
-//
-// C++ Interface: enums
-//
-// Description:
-//
-//
-// Author: Andre Simon <andre.simon1@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#ifndef ENUMS_H
-#define ENUMS_H
-
-namespace highlight {
-
-/** states which may occour during input file parsing*/
-enum State {
- STANDARD=0,
- STRING,
- NUMBER,
- SL_COMMENT,
- ML_COMMENT_BEGIN,
- ESC_CHAR,
- DIRECTIVE_LINE,
- DIRECTIVE_STRING,
- LINENUMBER,
- SYMBOL,
-
- // Konstanten ab hier duefen nicht mehr als Array-Indizes benutzt werden!!
- KEYWORD,
- ML_COMMENT_END,
- DIRECTIVE_LINE_END,
- TAG_BEGIN,
- TAG_END,
- KEYWORD_BEGIN,
- KEYWORD_END,
-
- _UNKNOWN=100,
- _EOL,
- _EOF,
- _WS
-} ;
-
-/** Parser return values*/
-enum ParseError{
- PARSE_OK,
- BAD_INPUT=1,
- BAD_OUTPUT=2,
- BAD_STYLE=4
-};
-
-/** line wrapping modes*/
-enum WrapMode {
- WRAP_DISABLED,
- WRAP_SIMPLE,
- WRAP_DEFAULT
-};
-
-/** language definition loading results*/
-enum LoadResult{
- LOAD_FAILED,
- LOAD_NEW,
- LOAD_NONE
-};
-
-/** output formats */
-enum OutputType {
- HTML,
- XHTML,
- TEX,
- LATEX,
- RTF,
- XSLFO,
- XML,
- ANSI
-};
-
-}
-
-#endif
-/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
- Free Software Foundation, Inc.
-
- 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, 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. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef __STDC__
-# ifndef const
-# define const
-# endif
-#endif
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
-#include <cstdio>
-#include <cstring>
-//#include "tailor.h"
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
-#include <stdlib.h>
-#endif /* GNU C library. */
-
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
- long-named option. Because this is not POSIX.2 compliant, it is
- being phased out. */
-/* #define GETOPT_COMPAT */
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-char *optarg = 0;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns EOF, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-/* XXX 1003.2 says this must be 1 before any call. */
-int optind = 0;
-
-/* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
- for unrecognized options. */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
- This must be initialized on some systems to avoid linking in the
- system's own getopt implementation. */
-
-#define BAD_OPTION '\0'
-int optopt = BAD_OPTION;
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return EOF with `optind' != ARGC. */
-
-static enum
-{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
- because there are many ways it can cause trouble.
- On some systems, it contains special magic macros that don't work
- in GCC. */
-#include <string.h>
-#define my_index strchr
-#define my_strlen strlen
-#else
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-#if __STDC__ || defined(PROTO)
- #ifndef _WIN32
- // Solaris compilation fix
- extern "C" {
- char *getenv(const char *name);
- int strncmp(const char *s1, const char *s2, int n);
- }
- // extern char *getenv(const char *name);
- // extern int strncmp(const char *s1, const char *s2, int n);
- #endif
- extern int strcmp (const char *s1, const char *s2);
- static int my_strlen(const char *s);
- static char *my_index (const char *str, int chr);
-#else
- #ifndef _WIN32
- extern char *getenv ();
- #endif
-#endif
-
-static int
-my_strlen (const char *str)
-
-{
- int n = 0;
- while (*str++)
- n++;
- return n;
-}
-
-static char *
-my_index ( const char *str,
- int chr)
-
-{
- while (*str)
- {
- if (*str == chr)
- return (char *) str;
- str++;
- }
- return 0;
-}
-
-#endif /* GNU C library. */
-
-/* Handle permutation of arguments. */
-
-/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
-static int first_nonopt;
-static int last_nonopt;
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,optind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved.
-
- To perform the swap, we first reverse the order of all elements. So
- all options now come before all non options, but they are in the
- wrong order. So we put back the options and non options in original
- order by reversing them again. For example:
- original input: a b c -x -y
- reverse all: -y -x c b a
- reverse options: -x -y c b a
- reverse non options: -x -y a b c
-*/
-
-#if __STDC__ || defined(PROTO)
-static void exchange (char **argv);
-#endif
-
-static void
-exchange (char **argv)
-
-{
- char *temp, **first, **last;
-
- /* Reverse all the elements [first_nonopt, optind) */
- first = &argv[first_nonopt];
- last = &argv[optind-1];
- while (first < last) {
- temp = *first; *first = *last; *last = temp; first++; last--;
- }
- /* Put back the options in order */
- first = &argv[first_nonopt];
- first_nonopt += (optind - last_nonopt);
- last = &argv[first_nonopt - 1];
- while (first < last) {
- temp = *first; *first = *last; *last = temp; first++; last--;
- }
-
- /* Put back the non options in order */
- first = &argv[first_nonopt];
- last_nonopt = optind;
- last = &argv[last_nonopt-1];
- while (first < last) {
- temp = *first; *first = *last; *last = temp; first++; last--;
- }
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns `EOF'.
- Then `optind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return BAD_OPTION after printing an error message. If you set `opterr' to
- zero, the error message is suppressed but we still return BAD_OPTION.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- The elements of ARGV aren't really const, because we permute them.
- But we pretend they're const in the prototype to be compatible
- with other systems.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-int
-_getopt_internal ( int argc,
- char *const *argv,
- const char *optstring,
- const struct option *longopts,
- int *longind,
- int long_only)
-
-{
- int option_index;
-
- optarg = 0;
-
- /* Initialize the internal data when the first call is made.
- Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
-
- if (optind == 0)
- {
- first_nonopt = last_nonopt = optind = 1;
-
- nextchar = NULL;
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- #ifndef _WIN32
- else if (getenv ("POSIXLY_CORRECT") != NULL)
- ordering = REQUIRE_ORDER;
- #endif
- else
- ordering = PERMUTE;
- }
-
- if (nextchar == NULL || *nextchar == '\0')
- {
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
-
- /* Now skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
- optind++;
- last_nonopt = optind;
- }
-
- /* Special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (optind != argc && !strcmp (argv[optind], "--"))
- {
- optind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
-
- optind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
-
- if (optind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return EOF;
- }
-
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
- {
- if (ordering == REQUIRE_ORDER)
- return EOF;
- optarg = argv[optind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element.
- Start decoding its characters. */
-
- nextchar = (argv[optind] + 1
- + (longopts != NULL && argv[optind][1] == '-'));
- }
-
- if (longopts != NULL
- && ((argv[optind][0] == '-'
- && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- ))
- {
- const struct option *p;
- char *s = nextchar;
- int exact = 0;
- int ambig = 0;
- const struct option *pfound = NULL;
- int indfound = 0;
-
- while (*s && *s != '=')
- s++;
-
- /* Test all options for either exact match or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name;
- p++, option_index++)
- if (!strncmp (p->name, nextchar, s - nextchar))
- {
- if (s - nextchar == my_strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- if (opterr)
- fprintf (stderr, "%s: option `%s' is ambiguous\n",
- argv[0], argv[optind]);
- nextchar += my_strlen (nextchar);
- optind++;
- return BAD_OPTION;
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- optind++;
- if (*s)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = s + 1;
- else
- {
- if (opterr)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- "%s: option `--%s' doesn't allow an argument\n",
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- "%s: option `%c%s' doesn't allow an argument\n",
- argv[0], argv[optind - 1][0], pfound->name);
- }
- nextchar += my_strlen (nextchar);
- return BAD_OPTION;
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (opterr)
- fprintf (stderr, "%s: option `%s' requires an argument\n",
- argv[0], argv[optind - 1]);
- nextchar += my_strlen (nextchar);
- return optstring[0] == ':' ? ':' : BAD_OPTION;
- }
- }
- nextchar += my_strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- || my_index (optstring, *nextchar) == NULL)
- {
- if (opterr)
- {
- if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, "%s: unrecognized option `--%s'\n",
- argv[0], nextchar);
- else
- /* +option or -option */
- fprintf (stderr, "%s: unrecognized option `%c%s'\n",
- argv[0], argv[optind][0], nextchar);
- }
- nextchar = (char *) "";
- optind++;
- return BAD_OPTION;
- }
- }
-
- /* Look at and handle the next option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index (optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':')
- {
- if (opterr)
- {
-#if 0
- if (c < 040 || c >= 0177)
- fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
- argv[0], c);
- else
- fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
-#else
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
-#endif
- }
- optopt = c;
- return BAD_OPTION;
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- optind++;
- }
- else
- optarg = 0;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (opterr)
- {
-#if 0
- fprintf (stderr, "%s: option `-%c' requires an argument\n",
- argv[0], c);
-#else
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: option requires an argument -- %c\n",
- argv[0], c);
-#endif
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = BAD_OPTION;
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
-}
-
-int
-getopt ( int argc,
- char *const *argv,
- const char *optstring)
-
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0);
-}
-
-int
-getopt_long ( int argc,
- char *const *argv,
- const char *options,
- const struct option *long_options,
- int *opt_index)
-
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-#endif /* _LIBC or not __GNU_LIBRARY__. */
-
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
- the above definition of `getopt'. */
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
-
- c = getopt (argc, argv, "abc:d:0123456789");
- if (c == EOF)
- break;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case BAD_OPTION:
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
-
-/* Declarations for getopt.
- Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library 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. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _GETOPT_H
-
-#ifndef __need_getopt
-# define _GETOPT_H 1
-#endif
-
-/* If __GNU_LIBRARY__ is not already defined, either we are being used
- standalone, or this is the first header included in the source file.
- If we are being used with glibc, we need to include <features.h>, but
- that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
- not defined, include <ctype.h>, which will pull in <features.h> for us
- if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
- doesn't flood the namespace with stuff the way some other headers do.) */
-#if !defined __GNU_LIBRARY__
-# include <ctype.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized. */
-
-extern int optopt;
-
-#ifndef __need_getopt
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct option
-{
-# if (defined __STDC__ && __STDC__) || defined __cplusplus
- const char *name;
-# else
- char *name;
-# endif
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-# define no_argument 0
-# define required_argument 1
-# define optional_argument 2
-#endif /* need getopt */
-
-
-/* Get definitions and prototypes for functions to process the
- arguments in ARGV (ARGC of them, minus the program name) for
- options given in OPTS.
-
- Return the option character from OPTS just read. Return -1 when
- there are no more options. For unrecognized options, or options
- missing arguments, `optopt' is set to the option letter, and '?' is
- returned.
-
- The OPTS string is a list of characters which are recognized option
- letters, optionally followed by colons, specifying that that letter
- takes an argument, to be placed in `optarg'.
-
- If a letter in OPTS is followed by two colons, its argument is
- optional. This behavior is specific to the GNU `getopt'.
-
- The argument `--' causes premature termination of argument
- scanning, explicitly telling `getopt' that there are no more
- options.
-
- If OPTS begins with `--', then non-option arguments are treated as
- arguments to the option '\0'. This behavior is specific to the GNU
- `getopt'. */
-
-#if (defined __STDC__ && __STDC__) || defined __cplusplus
-# ifdef __GNU_LIBRARY__
-/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
- errors, only prototype getopt for the GNU C library. */
-extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
-# else /* not __GNU_LIBRARY__ */
-// Solaris compilation fix
-//extern int getopt ();
-# endif /* __GNU_LIBRARY__ */
-
-# ifndef __need_getopt
-extern int getopt_long (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind);
-extern int getopt_long_only (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind);
-
-/* Internal only. Users should not call this directly. */
-extern int _getopt_internal (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind,
- int __long_only);
-# endif
-#else /* not __STDC__ */
-extern int getopt ();
-# ifndef __need_getopt
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-# endif
-#endif /* __STDC__ */
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Make sure we later can get all the definitions and declarations. */
-#undef __need_getopt
-
-#endif /* getopt.h */
-/***************************************************************************
- help.cpp - description
- -------------------
- begin : Die Apr 23 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 "help.h"
-
-namespace Help
- {
-
-/** gibt Hilfetext auf Konsole aus */
-
- void printHelp(const std::string & helpFilePath)
- {
- std::ifstream helpFile(helpFilePath.c_str());
- std::string line;
- if (helpFile){
- while (getline(helpFile, line))
- std::cout << line << "\n";
- helpFile.close();
- }
- else {
- std::cerr <<"highlight: Could not read "<< helpFilePath << "\n";
- }
- }
-
-}
-/***************************************************************************
- help.h - description
- -------------------
- begin : Die Apr 23 2002
- copyright : (C) 2002 by Andé 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 HELP_H
-#define HELP_H
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-/**\ brief COntains methods for printing help messages
- *@author Andre Simon
- */
-namespace Help
- {
- /** print help message to stdout */
- void printHelp(const std::string &);
- }
-
-#endif
-/***************************************************************************
- htmlcode.cpp - description
- -------------------
- begin : Wed Nov 28 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 "htmlgenerator.h"
-
-using namespace std;
-
-namespace highlight {
-
-
-HtmlGenerator::HtmlGenerator(void)
-{}
-
-string HtmlGenerator::formatStyleAttributes(const string & elemName,
- const ElementStyle & elem)
-{
- ostringstream s;
- s << "."<<elemName<<"\t{ color:#"
- << (elem.getColour().getHexRedValue())
- << (elem.getColour().getHexGreenValue())
- << (elem.getColour().getHexBlueValue() )
- << ( elem.isBold() ?"; font-weight:bold" :"" )
- << ( elem.isItalic() ?"; font-style:italic" :"" )
- << ( elem.isUnderline() ?"; text-decoration:underline" :"" )
- << "; }\n" ;
- return s.str();
-}
-
-string HtmlGenerator::getOpenTag(const string& styleName ){
- return "<span class=\""+styleName+"\">";
-}
-
-HtmlGenerator::HtmlGenerator (
- const string &cssStyle,
- const string &enc,
- bool omitEnc,
- bool withAnchors)
- : CodeGenerator( cssStyle),
- brTag("<br>"),
- hrTag("<hr>"),
- idAttr("name"),
- fileSuffix(".html"),
- encoding(enc),
- omitEncoding(omitEnc),
- HTML_FOOTER(
- "\n</body>\n</html>\n<!--HTML generated by highlight "
- HIGHLIGHT_VERSION
- ", "
- HIGHLIGHT_URL
- "-->\n"),
- attachAnchors(withAnchors)
-{
- styleTagOpen.push_back("");
- styleTagOpen.push_back(getOpenTag("str"));
- styleTagOpen.push_back(getOpenTag("num"));
- styleTagOpen.push_back(getOpenTag("slc"));
- styleTagOpen.push_back(getOpenTag("com"));
- styleTagOpen.push_back(getOpenTag("esc"));
- styleTagOpen.push_back(getOpenTag("dir"));
- styleTagOpen.push_back(getOpenTag("dstr"));
- styleTagOpen.push_back(getOpenTag("line"));
- styleTagOpen.push_back(getOpenTag("sym"));
-
- styleTagClose.push_back("");
- for (int i=1;i<NUMBER_BUILTIN_STYLES; i++) {
- styleTagClose.push_back("</span>");
- }
-
- /*assert (styleTagOpen.size()==styleTagClose.size());
- assert (styleTagOpen.size()==NUMBER_BUILTIN_STYLES);
-*/
- newLineTag = "\n";
- spacer = " ";
- styleCommentOpen="/*";
- styleCommentClose="*/";
-}
-
-string HtmlGenerator::getStyleDefinition()
-{
- if (styleDefinitionCache.empty()){
- ostringstream os;
- os << "body.hl\t{ background-color:#"
- << (docStyle.getBgColour().getHexRedValue())
- << (docStyle.getBgColour().getHexGreenValue())
- << (docStyle.getBgColour().getHexBlueValue())
- << "; }\n";
- os << "pre.hl\t{ color:#"
- << (docStyle.getDefaultStyle().getColour().getHexRedValue())
- << (docStyle.getDefaultStyle().getColour().getHexGreenValue())
- << (docStyle.getDefaultStyle().getColour().getHexBlueValue() )
- << "; background-color:#"
- << (docStyle.getBgColour().getHexRedValue())
- << (docStyle.getBgColour().getHexGreenValue())
- << (docStyle.getBgColour().getHexBlueValue())
- << "; font-size:"
- << docStyle.getFontSize()
- << "pt; font-family:Courier;}\n";
- os << formatStyleAttributes("num", docStyle.getNumberStyle())
- << formatStyleAttributes("esc", docStyle.getEscapeCharStyle())
- << formatStyleAttributes("str", docStyle.getStringStyle())
- << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle())
- << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle())
- << formatStyleAttributes("com", docStyle.getCommentStyle())
- << formatStyleAttributes("dir", docStyle.getDirectiveStyle())
- << formatStyleAttributes("sym", docStyle.getSymbolStyle())
- << formatStyleAttributes("line", docStyle.getLineStyle());
-
- KeywordStyles styles = docStyle.getKeywordStyles();
- for (KSIterator it=styles.begin(); it!=styles.end(); it++){
- os << formatStyleAttributes(it->first, *(it->second));
- }
- styleDefinitionCache=os.str();
- }
- return styleDefinitionCache;
-}
-
-string HtmlGenerator::getHeader(const string &title)
-{
- ostringstream os;
- os << getHeaderStart((title.empty())?"Source file":title );
- if (langInfo.getSyntaxHighlight())
- {
- if (includeStyleDef) //CSS-Definition in HTML-<head> einfuegen
- {
- os << "<style type=\"text/css\">\n";
- os << "<!--\n";
- os << getStyleDefinition();
- os << CodeGenerator::readUserStyleDef();
- os << "//-->\n";
- os << "</style>" << endl;
- }
- else //Referenz auf CSS-Datei einfuegen
- {
- os << "<link rel=\"stylesheet\" type=\"text/css\" href=\""
- << getStyleOutputPath()
- << "\""
- << ">\n";
- }
- }
- os << "</head>\n<body class=\"hl\">\n<pre class=\"hl\">";
- return os.str();
-}
-
-string HtmlGenerator::getFooter()
-{
- return "</pre>" + HTML_FOOTER;
-}
-
-
-void HtmlGenerator::printBody()
-{
- processRootState();
-}
-
-
-
-string HtmlGenerator::maskCharacter(unsigned char c)
-{
- switch (c) {
- case '<' :
- return "&lt;";
- break;
- case '>' :
- return "&gt;";
- break;
- case '&' :
- return "&amp;";
- break;
- case '\"' :
- return "&quot;";
- break;
-
- case '@' :
- return "&#64;";
- break;
-
- default :
- string m;
- return m += c;
- }
-}
-
-void HtmlGenerator::insertLineNumber (bool insertNewLine)
-{
- if (insertNewLine){
- //*out << getNewLine();
- wsBuffer += getNewLine();
- }
- if (showLineNumbers) {
- ostringstream numberPrefix;
- if (attachAnchors) {
- numberPrefix << "<a "
- << idAttr
- << "=\"l_"
- << lineNumber
- << "\">";
- }
- ostringstream os;
- if (lineNumberFillZeroes) os.fill('0');
- os <<setw(LINE_NUMBER_WIDTH)<<right<< lineNumber;
- numberPrefix<< styleTagOpen[LINENUMBER]
- << os.str()
- << spacer
- << styleTagClose[LINENUMBER];
-
- if (attachAnchors) {
- numberPrefix << "</a>";
- }
-
- wsBuffer += numberPrefix.str();
- }
-}
-
-string HtmlGenerator::getHeaderStart(const string &title){
- ostringstream header;
- header<< "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">"
- << "\n<html>\n<head>\n";
- if (!omitEncoding){
- header << "<meta http-equiv=\"content-type\" content=\"text/html; charset="<<encoding<<"\">\n";
- }
- header << "<title>" << title <<"</title>\n";
- return header.str();
-}
-
-bool HtmlGenerator::printIndexFile(const vector<string> &fileList,
- const string &outPath ){
- string suffix = fileSuffix;
- string outFilePath = outPath + "index" + suffix;
- ofstream indexfile(outFilePath.c_str());
-
- if (!indexfile.fail()){
- string inFileName;
- string inFilePath, newInFilePath;
- indexfile << getHeaderStart("Source Index" );
- indexfile << "</head>\n<body>\n<h1> Source Index</h1>\n"
- << hrTag
- << "\n<ul>\n";
- string::size_type pos;
- for (unsigned int i=0; i < fileList.size(); i++){
- pos=(fileList[i]).find_last_of(Platform::pathSeparator);
- if (pos!=string::npos){
- newInFilePath = (fileList[i]).substr(0, pos+1);
- } else {
- newInFilePath=Platform::pathSeparator;
- }
- if (newInFilePath!=inFilePath){
- indexfile << "</ul>\n<h2>";
- indexfile << newInFilePath;
- indexfile << "</h2>\n<ul>\n";
- inFilePath=newInFilePath;
- }
- inFileName = (fileList[i]).substr(pos+1);
- indexfile << "<li><a href=\"" << inFileName << suffix << "\">";
- indexfile << inFileName << suffix <<"</a></li>\n";
- }
-
- indexfile << "</ul>\n"
- << hrTag << brTag
- << "<small>Generated by highlight "
- << HIGHLIGHT_VERSION
- << ", <a href=\"" << HIGHLIGHT_URL << "\" target=\"new\">"
- << HIGHLIGHT_URL << "</a></small>";
- indexfile << HTML_FOOTER;
- } else {
- return false;
- }
- return true;
-}
-
-string HtmlGenerator::getMatchingOpenTag(unsigned int styleID){
- return getOpenTag(langInfo.getKeywordClasses()[styleID]);
- }
-
-string HtmlGenerator::getMatchingCloseTag(unsigned int styleID){
- return "</span>";
-}
-
-}
-/***************************************************************************
- htmlgenerator.h - description
- -------------------
- begin : Wed Nov 28 2001
- copyright : (C) 2001 by Andre 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 HTMLGENERATOR_H
-#define HTMLGENERATOR_H
-
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <sstream>
-
-#include "codegenerator.h"
-#include "version.h"
-#include "stylecolour.h"
-#include "elementstyle.h"
-#include "platform_fs.h"
-
-namespace highlight {
-
-/**
- \brief This class generates HTML.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-class HtmlGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- \param enc encoding name
- \param omitEnc switch to omit encoding information
- \param withAnchors Test if HTML anchors should be attached to line numbers
- */
- HtmlGenerator(const string &colourTheme,
- const string &enc,
- bool omitEnc=false,
- bool withAnchors = false);
-
- HtmlGenerator();
-
- /** Destructor*/
- virtual ~HtmlGenerator() {};
-
- /** insert line number in the beginning of the new line
- */
- virtual void insertLineNumber(bool insertNewLine=true);
-
- /** Print document header
- \param title Title of the document
- */
- string getHeader(const string &title);
-
- /** Print document body*/
- void printBody();
-
- /** Print document footer*/
- string getFooter();
-
- /** Print style definitions to external file
- \param outFile Path of external style definition
- */
- bool printExternalStyle(const string &outFile);
-
- /** Print index file with all input file names
- \param fileList List of output file names
- \param outPath Output path
- */
- bool printIndexFile(const vector<string> & fileList, const string &outPath);
-
- protected:
-
- /** some strings which are similar in HTML and XHTML*/
- string brTag, hrTag, idAttr, fileSuffix;
-
- /** Output encoding name */
- string encoding;
-
- /** switch to omit encoding name in file header */
- bool omitEncoding;
-
- /** HTML footer */
- string HTML_FOOTER;
-
- /** caches style definition */
- string styleDefinitionCache;
-
- /** \return CSS definition */
- string getStyleDefinition();
-
- /** \return Content of user defined style file */
- string readUserStyleDef();
-
- /** \param title Dociment title
- \return Start of file header */
- virtual string getHeaderStart(const string &title);
-
- private:
-
- /** \param styleName Style name
- \return Opening tag of the given style
- */
- string getOpenTag(const string& styleName);
-
- /** \return escaped character*/
- virtual string maskCharacter(unsigned char );
-
- /** test if anchors should be appied to line numbers*/
- bool attachAnchors;
-
- /**\return text formatting attributes in HTML format */
- string formatStyleAttributes(const string & elemName, const ElementStyle & elem);
-
- /** \param styleID Style ID
- \return Opening tag of the given style
- */
- string getMatchingOpenTag(unsigned int styleID);
-
- /** \param styleID Style ID
- \return Closing tag of the given style
- */
- string getMatchingCloseTag(unsigned int styleID);
- };
-
-}
-
-#endif
-/***************************************************************************
- languagedefinition.cpp - description
- -------------------
- begin : Wed Nov 28 2001
- copyright : (C) 2001 by Andre 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. *
- * *
- ***************************************************************************/
-
-#include "languagedefinition.h"
-
-using namespace std;
-
-namespace highlight {
-
-LanguageDefinition::LanguageDefinition():
- ignoreCase(false),
- disableHighlighting(false),
- allowExtEscape(false),
- vhdl_mode(false),
- java_mode(false),
- allowNestedComments(true),
- fullLineComment(false),
- reformatCode(false)
-{}
-
-int LanguageDefinition::isKeyword(const string &s)
-{
- if (s.length())
- {
- if (keywords.count(s)){
- return keywords[s];
- }
- else if (prefixes.count(s[0])){
- return prefixes[s[0]];
- }
- }
- return 0;
-}
-
-bool LanguageDefinition::isPrefix(unsigned char c)
-{
- return ( prefixes.count(c));
-}
-
-void LanguageDefinition::addSimpleSymbol(stringstream& symbolStream,
- State state,
- const string& paramValues ) {
- istringstream valueStream(paramValues);
- bool valExists=false;
- string value;
- while (valueStream >> value)
- {
- symbolStream << " " << value;
- valExists = true;
- }
- if (valExists)
- {
- symbolStream << " " << state;
- }
-}
-
-void LanguageDefinition::addDelimiterSymbol(stringstream& symbolStream,
- State stateBegin, State stateEnd,
- const string& paramValues,
- unsigned int classID) {
- istringstream valueStream(paramValues);
- string delimPrefix, delimSuffix;
- while (valueStream>>delimPrefix){
- valueStream >> delimSuffix;
- symbolStream << " "<<delimPrefix <<" " << stateBegin;
- symbolStream <<" "<< delimSuffix<<" "<< stateEnd;
- delimiterPrefixes.insert(make_pair(delimPrefix, classID));
- };
-}
-
-bool LanguageDefinition::getFlag( string& paramValue){
- return (StringTools::lowerCase(paramValue)=="true");
-}
-
-unsigned char LanguageDefinition::getSymbol(const string& paramValue){
- istringstream valueStream(paramValue);
- unsigned char symbol;
- valueStream >> symbol;
- return symbol;
-}
-
-void LanguageDefinition::addKeywords(const string &kwList,
- int classID){
- istringstream valueStream(kwList);
- string keyword;
- while (valueStream >> keyword){
- keywords.insert(make_pair(keyword, classID));
- }
-}
-
-unsigned int LanguageDefinition::generateNewKWClass(const string& newClassName){
- unsigned int newClassID=0;
- bool found=false;
- while (newClassID<keywordClasses.size() && !found){
- found= (newClassName==keywordClasses[newClassID++]);
- }
- if (!found){
- newClassID++;
- keywordClasses.push_back(newClassName);
- }
- return newClassID;
-}
-
-unsigned int LanguageDefinition::getDelimPrefixClassID(const string& prefix){
- if (delimiterPrefixes.count(prefix)){
- return delimiterPrefixes[prefix];
- }
- return 0;
-}
-
-bool LanguageDefinition::load(const string& langDefPath, bool clear)
-{
- if (clear) reset();
-
- ConfigurationReader langDef(langDefPath);
- if (langDef.found())
- {
- currentPath=langDefPath;
- disableHighlighting=false;
- string token;
- stringstream symbolStrStream;
-
- //Stringstream zum Einlesen der Token:
- istringstream valueStream;
-
- addDelimiterSymbol(symbolStrStream, ML_COMMENT_BEGIN, ML_COMMENT_END,
- langDef.getParameter("ml_comment"));
-
- addSimpleSymbol(symbolStrStream, SL_COMMENT,
- langDef.getParameter("sl_comment"));
-
- addSimpleSymbol(symbolStrStream, ESC_CHAR,
- langDef.getParameter("escchar"));
-
- addSimpleSymbol(symbolStrStream, DIRECTIVE_LINE,
- langDef.getParameter("directive"));
-
- addSimpleSymbol(symbolStrStream, DIRECTIVE_LINE_END,
- langDef.getParameter("directiveend"));
-
- addSimpleSymbol(symbolStrStream, STRING,
- langDef.getParameter("stringdelimiters"));
-
- ignoreCase=getFlag(langDef.getParameter("ignorecase"));
- allowNestedComments=getFlag(langDef.getParameter("allownestedcomments"));
- vhdl_mode=getFlag(langDef.getParameter("vhdl_mode"));
- java_mode=getFlag(langDef.getParameter("java_mode"));
- disableHighlighting=getFlag(langDef.getParameter("disablehighlighting"));
- fullLineComment=getFlag(langDef.getParameter("fl_comment"));
- reformatCode=getFlag(langDef.getParameter("reformatting"));
- rawStringPrefix=getSymbol(langDef.getParameter("rawstringprefix"));
- continuationChar=getSymbol(langDef.getParameter("continuationsymbol"));
- allowExtEscape=getFlag(langDef.getParameter("allowextescape"));
-
- string paramName, className, classValue;
- vector<string> paramNames=langDef.getParameterNames();
- for (unsigned int i=0;i<paramNames.size();i++){
- paramName=paramNames[i];
- className=StringTools::getParantheseVal(paramName);
- classValue=langDef.getParameter(paramName);
- if (paramName.find("kw_list") != string::npos ){
- addKeywords(classValue, generateNewKWClass(className));
- }
- if (paramName.find("kw_prefix") != string::npos){
- prefixes.insert(make_pair(classValue[0], generateNewKWClass(className)));
- }
- if (paramName.find("kw_delim") != string::npos ){
- addDelimiterSymbol(symbolStrStream, KEYWORD_BEGIN, KEYWORD_END,
- classValue, generateNewKWClass(className));
- }
- if (paramName.find("tag_delim") != string::npos ){
- addDelimiterSymbol(symbolStrStream, TAG_BEGIN, TAG_END,
- classValue, generateNewKWClass(className));
- }
- }
-
- // zuletzt einlesen, um Probleme mit Delimitern, die Zeichen der
- // Symbolliste enthalten, zu vermeiden
- addSimpleSymbol(symbolStrStream, SYMBOL, langDef.getParameter("symbols"));
-
- valueStream.str(langDef.getParameter("allowedchars"));
- while (valueStream >> token )
- {
- allowedChars += token;
- }
- symbolString = symbolStrStream.str();
-
- string fileToInclude=langDef.getParameter("include");
- if (!fileToInclude.empty()){
- string::size_type Pos = langDefPath.find_last_of(Platform::pathSeparator);
- string includeLangDefPath = langDefPath.substr(0, Pos+1) + fileToInclude;
- load(includeLangDefPath, false);
- }
- return true;
- }
- else
- {
- currentPath.clear();
- return false;
- }
-}
-
-void LanguageDefinition::reset()
-{
- keywords.clear();
- keywordClasses.clear();
- delimiterPrefixes.clear();;
- prefixes.clear();
- allowedChars.clear();
- ignoreCase= false;
- java_mode= vhdl_mode= false;
- allowNestedComments= reformatCode = false;
- rawStringPrefix = continuationChar = '\0';
- disableHighlighting=false;
- fullLineComment=false;
-}
-
-bool LanguageDefinition::isVHDL()
-{
- return vhdl_mode;
-}
-
-bool LanguageDefinition::isJava()
-{
- return java_mode;
-}
-
-bool LanguageDefinition::allowNestedMLComments(){
- return allowNestedComments;
-}
-
-bool LanguageDefinition::highlightingDisabled(){
- return disableHighlighting;
-}
-
-bool LanguageDefinition::isFullLineComment(){
- return fullLineComment;
-}
-
-bool LanguageDefinition::needsReload(const string &langDefPath){
- return currentPath!=langDefPath;
-}
-
-bool LanguageDefinition::enableReformatting(){
- return reformatCode;
-}
-
-const KeywordMap& LanguageDefinition::getKeywords() const{
- return keywords;
-}
-
-string &LanguageDefinition::getSymbolString() {
- return symbolString;
-}
-
-unsigned char LanguageDefinition::getRawStringPrefix(){
- return rawStringPrefix;
-}
-
-unsigned char LanguageDefinition::getContinuationChar(){
- return continuationChar;
-}
-
-string &LanguageDefinition::getAllowedChars() {
- return allowedChars;
-}
-
-bool LanguageDefinition::getSyntaxHighlight() {
- return !disableHighlighting;
-}
-
-bool LanguageDefinition::isIgnoreCase() {
- return ignoreCase;
-}
-
-const vector<string>&LanguageDefinition::getKeywordClasses() const{
- return keywordClasses;
-}
-
-bool LanguageDefinition::allowExtEscSeq() {
- return allowExtEscape;
-}
-
-}
-/***************************************************************************
- languagedefinition.h - description
- -------------------
- begin : Wed Nov 28 2001
- copyright : (C) 2001 by Andre 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 LANGUAGEDEFINITION_H
-#define LANGUAGEDEFINITION_H
-
-#include <string>
-#include <map>
-#include <iostream>
-#include <fstream>
-#include <iterator>
-#include <sstream>
-
-#include "configurationreader.h"
-//#include "stringtools.h"
-#include "platform_fs.h"
-#include "enums.h"
-
-
-namespace highlight {
-
-/** maps keywords and the corresponding class IDs*/
-typedef map <string, int> KeywordMap;
-
-/** maps keyword prefixes and the corresponding class IDs*/
-typedef map <unsigned char, int> PrefixMap;
-
-/**\brief Contains specific data of the programming language being processed.
-
- The load() method will only read a new language definition if the given
- file path is not equal to the path of the current language definition.
-
-* @author Andre Simon
-*/
-
-class LanguageDefinition {
-
- public:
-
- LanguageDefinition();
-
- /**\return Symbol string, containg all known symbols with the referencing state ids*/
- string &getSymbolString();
-
- /** \return Prefix of raw strings */
- unsigned char getRawStringPrefix();
-
- /** \return Continuation Character */
- unsigned char getContinuationChar();
-
- /** \return List of characters allowed within identifiers */
- string &getAllowedChars();
-
- /** \return true if syntax highlighting is enabled*/
- bool getSyntaxHighlight();
-
- /** \return True if language is case sensitive */
- bool isIgnoreCase();
-
- /** \param s String
- \return class id of keyword, 0 if s is not a keyword */
- int isKeyword(const string &s);
-
-
- /** \return true if c is member of prefix list*/
- bool isPrefix(unsigned char c);
-
- /** Load new language definition
- \param langDefPath Path of language definition
- \param clear Test if former data should be deleted
- \return True if successfull */
- bool load(const string& langDefPath, bool clear=true);
-
- /** \return True if programming language is VHDL */
- bool isVHDL();
-
- /** \return True if programming language is Java */
- bool isJava();
-
- /** \return True if multi line comments may be nested */
- bool allowNestedMLComments();
-
- /** \return True if highlighting is disabled */
- bool highlightingDisabled();
-
- /** \return True if single line comments must start at coloumn 1 */
- bool isFullLineComment();
-
- /** \return True the next load() call will load a new language definition
- \param langDefPath Path to language definition */
- bool needsReload(const string &langDefPath);
-
- /** \return True if current language may be reformatted (c, c++, c#, java) */
- bool enableReformatting();
-
- /** \return True if escape sequences are allowed outsde of strings */
- bool allowExtEscSeq();
-
- /** \return Class ID of given keyword delimiter prefix
- \param prefix Keyword delimiter prefix */
- unsigned int getDelimPrefixClassID(const string& prefix);
-
- /** \return keywords*/
- const KeywordMap& getKeywords() const;
-
- /** \return keyword classes*/
- const vector<string>& getKeywordClasses() const;
-
- private:
- // string containing symbols and their IDs of the programming language
- string symbolString;
-
- // string with special characters that may occour in keywords
- string allowedChars;
-
- // path to laoed language definition
- string currentPath;
-
- KeywordMap keywords;
-
- vector <string> keywordClasses;
-
- KeywordMap delimiterPrefixes;
-
- PrefixMap prefixes;
-
- // keywords are not case sensitive if set
- bool ignoreCase,
- disableHighlighting,
- allowExtEscape,
-
- // switch to enable VHDL workarounds
- vhdl_mode,
-
- // switch to enable Java workarounds
- java_mode,
-
- // allow nested multi line comment blocks
- allowNestedComments,
-
- // single line comments have to start in coloumn 1 if set
- fullLineComment,
-
- // code formatting is enabled if set
- reformatCode;
-
- // Character, die eine Variable bzw. ein Keyword kennzeichnen
- unsigned char rawStringPrefix,
- continuationChar;
-
- /** setzt Membervariablen auf Defaultwerte */
- void reset();
-
- // add a symbol sequencs to the symbolStream
- void addSimpleSymbol(stringstream& symbolStream, State state,
- const string& paramValues );
-
- // add a delimiter symbol sequencs to the symbolStream
- void addDelimiterSymbol(stringstream& symbolStream,
- State stateBegin, State stateEnd,
- const string& paramValues,
- unsigned int classID=0);
-
- bool getFlag( string& paramValue);
-
- unsigned char getSymbol(const string& paramValue);
-
- // generate a unique class ID if the class name
- unsigned int generateNewKWClass(const string& newClassName);
-
- // add keywords to the given class
- void addKeywords(const string &kwList, int classID);
-
- };
-
-}
-#endif
-/***************************************************************************
- LatexCode.cpp - description
- -------------------
- begin : Mit Jul 24 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 "latexgenerator.h"
-
-namespace highlight {
-
-LatexGenerator::LatexGenerator(const string &colourTheme,
- bool replQuotes)
- : CodeGenerator(colourTheme),
- replaceQuotes(replQuotes)
-{
- styleTagOpen.push_back( "\\hlstd{");
- styleTagOpen.push_back( "\\hlstr{");
- styleTagOpen.push_back( "\\hlnum{");
- styleTagOpen.push_back( "\\hlslc{");
- styleTagOpen.push_back( "\\hlcom{");
- styleTagOpen.push_back( "\\hlesc{");
- styleTagOpen.push_back( "\\hldir{");
- styleTagOpen.push_back( "\\hldstr{");
- styleTagOpen.push_back( "\\hlline{");
- styleTagOpen.push_back( "\\hlsym{");
-
- for (int i=0;i<NUMBER_BUILTIN_STYLES; i++){
- styleTagClose.push_back( "}");
- }
-
- // avoid "Underfull \hbox (badness 10000)" warnings
- newLineTag = "\\\\\n";
- longLineTag = "\\hspace*{\\fill}" + newLineTag;
-
- spacer = "\\ ";
-
- maskWs=true;
- maskWsBegin = "\\hlstd{";
- maskWsEnd = "}";
-
- excludeWs=true;
-
- styleCommentOpen="%";
-}
-
-LatexGenerator::LatexGenerator()
-{}
-LatexGenerator::~LatexGenerator()
-{}
-
-string LatexGenerator::formatStyleAttributes(const string & elemName,
- const ElementStyle &elem)
-{
- ostringstream s;
- s << "\\newcommand{\\hl"
- << elemName
- << "}[1]{\\textcolor[rgb]{"
- << elem.getColour().getLatexRedValue() << ","
- << elem.getColour().getLatexGreenValue() << ","
- << elem.getColour().getLatexBlueValue()
- << "}{";
-
- if (elem.isBold())
- s << "\\bf{";
- if (elem.isItalic())
- s << "\\it{";
-
- s <<"#1";
-
- if (elem.isBold())
- s << "}";
- if (elem.isItalic())
- s << "}";
-
- s <<"}}\n";
- return s.str();
-}
-
-void LatexGenerator::printBody()
-{
- *out << "\\noindent\n"
- << "\\ttfamily\n";
-
- processRootState();
-
- *out << "\\mbox{}\n"
- << "\n\\normalfont\n";
-}
-
-string LatexGenerator::getHeader(const string & title)
-{
- ostringstream os;
- os << "\\documentclass{article}\n"
- << "\\usepackage{color}\n"
- << "\\usepackage{alltt}\n";
-
- if (langInfo.getSyntaxHighlight()) {
- if (includeStyleDef) {
- os << "\n"<<getStyleDefinition();
- os << CodeGenerator::readUserStyleDef();
- } else {
- os << "\n\\input {"
- << getStyleOutputPath()
- << "}\n";
- }
- }
-
- os << "\n\\title{" << title << "}\n"
- << "\\begin{document}\n"
- << "\\pagecolor{bgcolor}\n";
- return os.str();
-}
-
-string LatexGenerator::getFooter()
-{
- ostringstream os;
- os << "\\end {document}\n"
- << "(* LaTeX generated by highlight "
- << HIGHLIGHT_VERSION
- << ", "
- << HIGHLIGHT_URL
- << " *)\n";
- return os.str();
-}
-
-string LatexGenerator::getNewLine(){
- return (showLineNumbers)? newLineTag:longLineTag;
-}
-
-string LatexGenerator::maskCharacter(unsigned char c)
-{
- switch (c)
- {
- case '<' :
- return "$<$";
- break;
- case '>' :
- return "$>$";
- break;
- case '{':
- case '}':
- case '&':
- case '$':
- case '#':
- case '%':
- {
- string m;
- m ="\\";
- m += c;
- return m;
- }
- break;
- case '\"':
- return (fragmentOutput && replaceQuotes)?"\\dq{}":"\"";
- break;
- case '_':
- return "\\textunderscore ";
- break;
- case '^':
- return "\\textasciicircum ";
- break;
- case '\\':
- return "$\\backslash$";
- break;
- case '~':
- return "$\\sim$";
- break;
- case '|':
- return "\\textbar ";
- break;
- // avoid latex compilation failure if [ or * follows a line break (\\)
- case '*':
- case '[':
- case ']':
- // avoid "merging" of consecutive '-' chars when included in bold font ( \bf )
- case '-':
- {
- string m;
- m= "{";
- m+= c;
- m+= "}";
- return m;
- }
- break;
- case ' ':
- return spacer;
- break;
- case AUML_LC:
- return "\\\"a";
- break;
- case OUML_LC:
- return "\\\"o";
- break;
- case UUML_LC:
- return "\\\"u";
- break;
- case AUML_UC:
- return "\\\"A";
- break;
- case OUML_UC:
- return "\\\"O";
- break;
- case UUML_UC:
- return "\\\"U";
- break;
- case AACUTE_LC:
- return "\\'a";
- break;
- case EACUTE_LC:
- return "\\'e";
- break;
- case OACUTE_LC:
- return "\\'o";
- break;
- case UACUTE_LC:
- return "\\'u";
- break;
- case AGRAVE_LC:
- return "\\`a";
- break;
- case EGRAVE_LC:
- return "\\`e";
- break;
- case OGRAVE_LC:
- return "\\`o";
- break;
- case UGRAVE_LC:
- return "\\`u";
- break;
- case AACUTE_UC:
- return "\\'A";
- break;
- case EACUTE_UC:
- return "\\'E";
- break;
- case OACUTE_UC:
- return "\\'O";
- break;
- case UACUTE_UC:
- return "\\'U";
- break;
- case AGRAVE_UC:
- return "\\`A";
- break;
- case EGRAVE_UC:
- return "\\`E";
- break;
- case UGRAVE_UC:
- return "\\`O";
- break;
- case OGRAVE_UC:
- return "\\`U";
- break;
- case SZLIG:
- return "\\ss ";
- break;
- /* #ifndef _WIN32
- // skip first byte of multibyte chracters
- case 195:
- return string("");
- break;
-#endif*/
-
- default :
- {
- string m;
- return m+=c;
- }
- }
-}
-
-string LatexGenerator::getMatchingOpenTag(unsigned int styleID){
- return "\\hl"+langInfo.getKeywordClasses()[styleID]+"{";
- }
-
-string LatexGenerator::getMatchingCloseTag(unsigned int styleID){
- return "}";
-}
-
-
-string LatexGenerator::getStyleDefinition()
-{
- if (styleDefinitionCache.empty()){
- ostringstream os;
- os << formatStyleAttributes("std", docStyle.getDefaultStyle());
- os << formatStyleAttributes("num", docStyle.getNumberStyle());
- os << formatStyleAttributes("esc", docStyle.getEscapeCharStyle());
- os << formatStyleAttributes("str", docStyle.getStringStyle());
- os << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle());
- os << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle());
- os << formatStyleAttributes("com", docStyle.getCommentStyle());
- os << formatStyleAttributes("dir", docStyle.getDirectiveStyle());
- os << formatStyleAttributes("sym", docStyle.getSymbolStyle());
- os << formatStyleAttributes("line", docStyle.getLineStyle());
-
- KeywordStyles styles = docStyle.getKeywordStyles();
- for (KSIterator it=styles.begin(); it!=styles.end(); it++){
- os << formatStyleAttributes(it->first, *(it->second));
- }
- os << "\\definecolor{bgcolor}{rgb}{"
- << docStyle.getBgColour().getLatexRedValue() << ","
- << docStyle.getBgColour().getLatexGreenValue() << ","
- << docStyle.getBgColour().getLatexBlueValue()
- << "}\n";
- os << "\\oddsidemargin -3mm\n\\textwidth 165,2truemm\n"
- << "\\topmargin 0truept\n\\headheight 0truept\n"
- << "\\headsep 0truept\n\\textheight 230truemm\n";
-
- styleDefinitionCache=os.str();
- }
- return styleDefinitionCache;
-}
-
-
-}
-/***************************************************************************
- latexgenerator.h - description
- -------------------
- begin : Mit Jul 24 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. *
- * *
- ***************************************************************************/
-
-#ifndef LATEXGENERATOR_H
-#define LATEXGENERATOR_H
-
-#include <string>
-#include <iostream>
-#include <sstream>
-
-#include "codegenerator.h"
-#include "version.h"
-#include "charcodes.h"
-
-
-namespace highlight {
-
-/**
- \brief This class generates LaTeX.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-class LatexGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- \param replQuotes Test if quotes shold be replaced by \ dq
- */
- LatexGenerator(const string &colourTheme,
- bool replQuotes=false);
- LatexGenerator();
- ~LatexGenerator();
-
- /** prints document header
- \param title Title of the document
- */
- string getHeader(const string & title);
-
- /** Prints document footer*/
- string getFooter();
-
- /** Prints document body*/
- void printBody();
-
- private:
-
- string styleDefinitionCache;
- string longLineTag;
-
- /** \return escaped character*/
- virtual string maskCharacter(unsigned char );
-
- /**\return text formatting attributes in LaTeX format */
- string formatStyleAttributes(const string & elemName,
- const ElementStyle & elem);
-
- /** test if double quotes should be replaced by \dq{} */
- bool replaceQuotes;
-
- string getNewLine();
-
- string getStyleDefinition();
-
- string getMatchingOpenTag(unsigned int styleID);
- string getMatchingCloseTag(unsigned int styleID);
- };
-
-}
-
-#endif
-/***************************************************************************
- main.cpp - description
- -------------------
- begin : Die Apr 23 22:16:35 CEST 2002
- copyright : (C) 2002-2004 by André Simon
- email : andre.simon1@gmx.de
-
-
- Highlight is a universal source code to HTML converter. Syntax highlighting
- is formatted by Cascading Style Sheets. It's possible to easily enhance
- highlight's parsing database.
-
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * 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 "main.h"
-
-using namespace std;
-
-void HighlightApp::printVersionInfo()
-{
- cout << "\n highlight version "
- << HIGHLIGHT_VERSION
- << "\n Copyright (C) 2002-2005 Andre Simon <andre.simon1@gmx.de>"
- << "\n\n Artistic Style Classes (1.15.3)"
- << "\n Copyright (C) 1998-2002 Tal Davidson <davidsont@bigfoot.com>"
- << "\n\n Dirstream Classes (0.4)"
- << "\n Copyright (C) 2002-2004 Benjamin Kaufmann <hume@c-plusplus.de>"
- << "\n\n This software is released under the terms of the GNU General "
- << "Public License."
- << "\n For more information about these matters, see the file named "
- << "COPYING.\n\n";
- #ifdef USE_LOCAL_GETOPT
- cout << " (Built with USE_LOCAL_GETOPT flag set.)\n";
- #endif
- #ifdef HL_DATA_DIR
- cout << " (HL_DATA_DIR: \"" <<HL_DATA_DIR<< "\" )\n";
- #endif
-}
-
-void HighlightApp::printBadInstallationInfo()
-{
- cerr << "highlight: Data directory not found. Bad installation or wrong "
- << OPT_DATADIR << " parameter."
- << "\n\nCopy the highlight files into one of the directories listed "
- << "in INSTALL.\nYou may also set the data directory with "
- << OPT_DATADIR << " and " << OPT_ADDDATADIR << ".\n";
-}
-
-bool HighlightApp::listInstalledFiles(bool showThemes)
-{
- vector <string> filePaths;
- string wildcard=(showThemes)? "*.style":"*.lang";
- unsigned int suffixLength=wildcard.length()-1;
-
- string searchDir = ((showThemes) ? dataDir.getThemeDir():
- dataDir.getLangDefDir()) + wildcard;
-
- bool directoryOK = Platform::getDirectoryEntries(filePaths, searchDir, true);
- if (!directoryOK) {
- cerr << "highlight: Could not access directory "
- << searchDir
- << ", aborted.\n";
- return false;
- }
-
- cout << "\n Installed "
- << ((showThemes)? "themes":"language definitions ")
- << "(located in "
- << ((showThemes)?dataDir.getThemeDir():dataDir.getLangDefDir())
- << ") :\n"
- << endl;
-
- sort(filePaths.begin(), filePaths.end());
- string temp;
-
- for (unsigned int i=0;i< filePaths.size(); i++){
- if (showThemes)
- temp = (filePaths[i]).substr(dataDir.getThemeDir().length());
- else
- temp = (filePaths[i]).substr(dataDir.getLangDefDir().length());
- cout << " "<<temp.substr(0, temp.length()- suffixLength) << endl;
- }
- cout <<"\n Use name of the desired "
- << ((showThemes)?"theme":"language")
- << " with the --"
- << ((showThemes)? OPT_STYLE : OPT_SYNTAX)
- << " option.\n" << endl;
- return true;
-}
-
-void HighlightApp::printDebugInfo(highlight::LanguageDefinition &lang,
- const string & langDefPath)
-{
- cerr << "\nLoading language definition: " << langDefPath;
- cerr << "\n\nSYMBOLS: "
- << lang.getSymbolString();
- cerr << "\n\nKEYWORDS: ";
- highlight::KeywordMap::iterator it;
- highlight::KeywordMap keys=lang.getKeywords();
- cerr << "\n\nID Keyword \n";
- for (it=keys.begin(); it!=keys.end();it++){
- cerr << it->second
- << " <- \""
- << it->first <<"\"\n";
- }
- cerr <<"\n";
-}
-
-string HighlightApp::getFileSuffix(const string &fileName) {
- size_t ptPos=fileName.rfind(".");
- return (ptPos == string::npos) ?
- "" : fileName.substr(ptPos+1, fileName.length());
-}
-
-bool HighlightApp::loadMapConfig(const string& name, StringMap* map){
- string extPath=dataDir.getDir() + name + ".conf";
- ConfigurationReader config(extPath);
- if (config.found() )
- {
- stringstream values;
- string paramName, paramVal;
- for (unsigned int i=0;i<config.getParameterNames().size();i++){
- paramName = config.getParameterNames()[i];
- values.str(config.getParameter(paramName)) ;
- while (values >> paramVal) {
- map->insert(make_pair( paramVal, paramName));
- }
- values.clear();
- }
- return true;
- } else {
- cerr << "highlight: Configuration file "<< extPath << " not found.\n";
- return false;
- }
-}
-
-
-int HighlightApp::getNumDigits(int i){
- int res=0;
- while (i){
- i/=10;
- ++res;
- }
- return res;
-}
-
-void HighlightApp::printProgressBar(int total, int count){
- if (!total) return;
- int p=100*count / total;
- int numProgressItems=p/10;
- cout << "\r[";
- for (int i=0;i<10;i++){
- cout <<((i<numProgressItems)?"#":" ");
- }
- cout<< "] " <<setw(3)<<p<<"%, "<<count << " / " << total << " " <<flush;
- if (p==100) {
- cout << endl;
- }
-}
-
-void HighlightApp::printCurrentAction(const string&outfilePath,
- int total, int count, int countWidth){
- cout << "Writing file "
- << setw(countWidth)<< count
- << " of "
- << total
- << ": "
- << outfilePath
- << "\n";
-}
-
-void HighlightApp::printIOErrorReport(unsigned int numberErrorFiles,
- vector<string> & fileList,
- const string &action){
- cerr << "highlight: Could not "
- << action
- << " file"
- << ((numberErrorFiles>1)?"s":"")<<":\n";
- copy (fileList.begin(), fileList.end(), ostream_iterator<string>(cerr, "\n"));
- if (fileList.size() < numberErrorFiles) {
- cerr << "... ["
- << (numberErrorFiles - fileList.size() )
- << " of "
- << numberErrorFiles
- << " failures not shown, use --"
- << OPT_VERBOSE
- << " switch to print all paths]\n";
- }
-}
-
-string HighlightApp::analyzeShebang(const string& file){
- if (scriptShebangs.empty()) loadMapConfig("scriptre", &scriptShebangs);
- ifstream inFile(file.c_str());
- string firstLine;
- getline (inFile, firstLine);
- return scriptShebangs[StringTools::trimRight(firstLine)];
-}
-
-string HighlightApp::guessFileType(const string& suffix, const string &inputFile)
-{
- if (extensions.empty()) loadMapConfig("extensions", &extensions);
- string fileType = (extensions.count(suffix)) ? extensions[suffix] : suffix ;
- if (!fileType.empty()) return fileType;
- return analyzeShebang(inputFile);
-}
-
-
-int HighlightApp::run(int argc, char**argv){
-
- //get command line options
- CmdLineOptions options(argc, argv);
-
- // set data directory path, where /langDefs and /themes reside
- string highlightRootDir = Platform::getAppPath();
-
- // determine highlight data directory
- if (! dataDir.searchDataDir((options.dataDirGiven())?
- options.getDataDir(): highlightRootDir)){
- printBadInstallationInfo();
- return EXIT_FAILURE;
- }
-
- if (options.additionalDataDirGiven()){
- dataDir.setAdditionalDataDir(options.getAdditionalDataDir());
- }
-
- if (options.printVersion()) {
- printVersionInfo();
- return EXIT_SUCCESS;
- }
-
- if (options.printHelp()) {
- Help::printHelp(dataDir.getHelpMsgDir() + options.getHelpLang());
- return EXIT_SUCCESS;
- }
-
- if (options.showThemes() || options.showLangdefs()) {
- return listInstalledFiles(options.showThemes())?EXIT_SUCCESS:EXIT_FAILURE;
- }
-
- // list of input files
- const vector <string> inFileList=options.getInputFileNames();
-
- string stylePath=dataDir.searchForTheme(options.getStyleName());
-
- highlight::CodeGenerator *generator =
- highlight::CodeGenerator::getInstance(options.getOutputType(),
- stylePath,
- options.getStyleInFilename(),
- options.getStyleOutFilename(),
- options.getCharSet(),
- options.includeStyleDef(),
- options.attachLineAnchors(),
- options.replaceQuotes(),
- options.fopCompatible(),
- options.getNumberSpaces(),
- options.getWrappingStyle(),
- options.printLineNumbers(),
- options.fillLineNrZeroes(),
- options.fragmentOutput(),
- options.omitEncodingName() );
-
- assert (generator!=NULL);
-
- bool styleFileWanted = !options.fragmentOutput() || options.styleOutPathDefined();
-
- if (!generator->styleFound() ) {
- cerr << "highlight: Could not find style "
- << stylePath
- << ".\n";
- highlight::CodeGenerator::deleteInstance();
- return EXIT_FAILURE;
- }
-
- if (!options.getIndentScheme().empty()){
- string indentSchemePath =
- dataDir.searchForIndentScheme(options.getIndentScheme()+".indent");
- if (!generator->initIndentationScheme(indentSchemePath)){
- cerr << "highlight: Could not find indentation scheme "
- << indentSchemePath
- << ".\n";
- highlight::CodeGenerator::deleteInstance();
- return EXIT_FAILURE;
- }
- }
-
- string outDirectory = options.getOutDirectory();
- if (!outDirectory.empty() && !options.quietMode() && !dirstr::directory_exists(outDirectory) ){
- cerr << "highlight: Output directory \""
- << outDirectory
- << "\" does not exist.\n";
- return EXIT_FAILURE;
- }
-
- bool initError=false, IOError=false;
-
- if ( !options.includeStyleDef()
- && (styleFileWanted)
- && options.formatSupportsExtStyle()) {
- string cssOutFile=outDirectory + options.getStyleOutFilename();
- bool success=generator->printExternalStyle (cssOutFile);
- if (!success){
- cerr << "highlight: Could not write " << cssOutFile <<".\n";
- IOError = true;
- }
- }
-
- if (options.printIndexFile()){
- bool success=generator -> printIndexFile(inFileList, outDirectory);
- if (!success){
- cerr << "highlight: Could not write index file.\n";
- IOError = true;
- }
- }
-
- unsigned int fileCount=inFileList.size(),
- fileCountWidth=getNumDigits(fileCount),
- i=0,
- numBadFormatting=0,
- numBadInput=0,
- numBadOutput=0;
-
- vector<string> badFormattedFiles, badInputFiles, badOutputFiles;
- string outFilePath;
- string suffix, lastSuffix;
-
- if (options.syntaxGiven()) { // user defined language definition, valid for all files
- suffix = guessFileType(options.getLanguage());
- }
-
- while (i < fileCount && !initError) {
- if (!options.syntaxGiven()) { // determine file type for each file
- suffix = guessFileType(getFileSuffix(inFileList[i]), inFileList[i]);
- }
- if (suffix.empty()) {
- if (!options.enableBatchMode() && !styleFileWanted)
- cerr << "highlight: Undefined language definition. Use --"
- << OPT_SYNTAX << " option.\n";
- if (!options.forceOutput()){
- initError = true;
- break;
- }
- }
-
- if (suffix != lastSuffix) {
- string langDefPath=dataDir.searchForLangDef(suffix+".lang");
- highlight::LoadResult loadRes= generator->initLanguage(langDefPath);
- if (loadRes==highlight::LOAD_FAILED){
- cerr << "highlight: Unknown source file extension \""
- << suffix
- << "\".\n";
- if (!options.forceOutput()){
- initError = true;
- break;
- }
- }
- if (options.printDebugInfo() && loadRes==highlight::LOAD_NEW){
- printDebugInfo(generator->getLanguage(), langDefPath);
- }
- lastSuffix = suffix;
- }
-
- if (options.enableBatchMode()){
- string::size_type pos=(inFileList[i]).find_last_of(Platform::pathSeparator);
- outFilePath = outDirectory;
- outFilePath += inFileList[i].substr(pos+1);
- outFilePath += options.getOutFileSuffix();
-
- if (!options.quietMode()) {
- if (options.printProgress()){
- printProgressBar(fileCount, i+1);
- } else {
- printCurrentAction(outFilePath, fileCount, i+1, fileCountWidth);
- }
- }
- } else {
- outFilePath = options.getSingleOutFilename();
- }
-
- highlight::ParseError error = generator->printOutput(inFileList[i], outFilePath);
- if (error==highlight::BAD_INPUT){
- if (numBadInput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo()) {
- badInputFiles.push_back(inFileList[i]);
- }
- } else if (error==highlight::BAD_OUTPUT){
- if (numBadOutput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo()) {
- badOutputFiles.push_back(outFilePath);
- }
- }
- if (options.formattingEnabled() && !generator->formattingIsPossible()){
- if (numBadFormatting++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo()) {
- badFormattedFiles.push_back(outFilePath);
- }
- }
- ++i;
- }
-
- if (numBadInput){
- printIOErrorReport(numBadInput, badInputFiles, "read input");
- IOError = true;
- }
- if (numBadOutput){
- printIOErrorReport(numBadOutput, badOutputFiles, "write output");
- IOError = true;
- }
- if (numBadFormatting){
- printIOErrorReport(numBadFormatting, badFormattedFiles, "reformat");
- }
-
- highlight::CodeGenerator::deleteInstance();
- return (initError || IOError) ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-
-int main(int argc, char **argv) {
- HighlightApp app;
- return app.run(argc, argv);
-}
-//
-// C++ Interface: main
-//
-// Description:
-//
-//
-// Author: Andre Simon <andre.simon1@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#ifndef HIGHLIGHT_APP
-#define HIGHLIGHT_APP
-
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <vector>
-#include <map>
-#include <iomanip>
-#include <cassert>
-
-#include "./dirstream0.4/dirstream.h"
-#include "cmdlineoptions.h"
-#include "configurationreader.h"
-#include "codegenerator.h"
-#include "help.h"
-#include "datadir.h"
-#include "version.h"
-#include "platform_fs.h"
-
-#define IO_ERROR_REPORT_LENGTH 5
-#define SHEBANG_CNT 12
-
-typedef map<string, string> StringMap;
-
-/** Main application class
- @author Andre Simon
-*/
-
-class HighlightApp {
-
-public:
-
- HighlightApp(){};
- ~HighlightApp(){};
-
- /** Start application
- \param argc Number of command line arguments
- \param argv values of command line arguments
- \return EXIT_SUCCESS or EXIT_FAILURE
- */
- int run(int argc, char **argv);
-
-private:
-
- DataDir dataDir;
- StringMap extensions;
- StringMap scriptShebangs;
-
- /** print version info*/
- void printVersionInfo();
-
- /** print error message*/
- void printBadInstallationInfo();
-
- /** print input and output errors */
- void printIOErrorReport(unsigned int numberErrorFiles, vector<string> & fileList, const string &action);
-
- /** print installed files
- \param showThemes Print installed themes if true, language definitions otherwise
- */
- bool listInstalledFiles(bool showThemes);
-
- void printDebugInfo(highlight::LanguageDefinition &lang,
- const string &langDefPath);
-
- string getFileSuffix(const string &fileName);
-
- string guessFileType(const string &suffix, const string &inputFile="");
-
- int getNumDigits(int i);
-
- void printProgressBar(int total, int count);
- void printCurrentAction(const string&outfilePath,
- int total, int count, int countWidth);
-
- bool readInputFilePaths(vector<string> &fileList, string wildcard,
- bool recursiveSearch);
-
- string analyzeShebang(const string& file);
- bool loadMapConfig(const string& name, StringMap* map);
-
-};
-
-#endif
-//
-// C++ Implementation: platform_fs
-//
-// Description:
-//
-//
-// Author: André Simon <andre.simon1@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include "platform_fs.h"
-#include "./dirstream0.4/dirstream.h"
-
-#include <iostream>
-
-using namespace std;
-
-namespace Platform {
-
-#ifdef _WIN32
- #include <windows.h>
-
- const char pathSeparator = '\\';
- //const std::string pathSeparatorStr = "\\";
-
- std::string getAppPath()
- {
- char pathAndName[MAX_PATH], path[MAX_PATH], drive[3];
- GetModuleFileName(NULL, pathAndName, MAX_PATH);
- _splitpath(pathAndName, drive, path, 0, 0);
- return std::string(drive)+path;
- }
-
-#else
- const char pathSeparator = '/';
- // const std::string pathSeparatorStr = "/";
-
- std::string getAppPath()
- {
- return "";
- }
-
-#endif
-
-bool getDirectoryEntries(vector<string> &fileList,
- string wildcard,
- bool recursiveSearch)
-{
- if (!wildcard.empty()) {
- string directory_path;
- string::size_type Pos = wildcard.find_last_of(pathSeparator);
- if (Pos == string::npos) {
- directory_path = ".";
- } else {
- directory_path = wildcard.substr(0, Pos + 1);
- wildcard = wildcard.substr(Pos + 1);
- }
-
- dirstr::dirstream str( directory_path.c_str(),
- #ifdef USE_FN_MATCH
- dirstr::pred_f(FnMatcher(wildcard.c_str(), 0)),
- #else
- dirstr::pattern_f(wildcard.c_str()),
- #endif
- (recursiveSearch)?dirstr::recursive_yes:dirstr::recursive_no);
-
-
- for(string entry; str >> entry;) {
- fileList.push_back(dirstr::full_path(entry));
- //std::cout << "Entry " <<entry<<"\n";
- }
- }
- return !(fileList.empty());
-}
-
-}
-
-//
-// C++ Interface: platform_fs
-//
-// Description:
-//
-//
-// Author: André Simon <andre.simon1@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-#ifndef PLATFORM_FS__H__INCLUDED
-#define PLATFORM_FS__H__INCLUDED
-
-#include <string>
-#include <iostream>
-#include <vector>
-
-#ifdef USE_FN_MATCH
- #include <fnmatch.h>
-#endif
-
-namespace Platform
-{
- extern const char pathSeparator;
- //extern const std::string pathSeparatorStr;
-
- std::string getAppPath();
-
- /** \param fileList Vector where found entries will be stored
- \param wildcard Directory path and wildcard
- \param recursiveSearch Test if directory should be searched recursively */
- bool getDirectoryEntries(std::vector<std::string> &fileList,
- std::string wildcard,
- bool recursiveSearch=false);
-
-#ifdef USE_FN_MATCH
- struct FnMatcher
- {
- FnMatcher(const char* pattern, int flags)
- : pattern_(pattern)
- , flags_(flags)
- {}
- bool operator()(const std::string& e) const {
- // std::cout << "pattern: "<<pattern_<< " entry: "<<e.c_str()<< " Res fn: " <<::fnmatch(pattern_, e.c_str(), FNM_PATHNAME)<< " \n";
- return ! ::fnmatch(pattern_, e.c_str(), flags_);
- }
- private:
- const char* pattern_;
- int flags_;
- };
-#endif
-}
-#endif
-/***************************************************************************
- PreFormatter.cpp - description
- -------------------
- begin : Mo Jan 03 2005
- copyright : (C) 2005 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 "preformatter.h"
-
-namespace highlight {
-
-PreFormatter::PreFormatter(bool wrap, bool replTabs):
- maxLineLength(80),
- index(0),
- numberSpaces(0),
- wsPrefixLength(string::npos),
- hasMore(false),
- indentAfterOpenBraces(true),
- redefineWsPrefix(false),
- wrapLines(wrap),
- replaceTabs(replTabs)
-{
-}
-
-PreFormatter::PreFormatter():
- maxLineLength(80),
- index(0),
- numberSpaces(0),
- wsPrefixLength(string::npos),
- hasMore(false),
- indentAfterOpenBraces(true),
- redefineWsPrefix(false),
- wrapLines(false),
- replaceTabs(false)
-{
-}
-
-PreFormatter::~PreFormatter()
-{
-}
-
-bool PreFormatter::hasMoreLines(){
- return hasMore;
-}
-
-bool PreFormatter::indentCode(){
- return indentAfterOpenBraces;
-}
-
-void PreFormatter::setLine(const std::string newLine){
-
- line=newLine;
-
- if (replaceTabs && numberSpaces) {
- size_t tabPos=line.find('\t');
- while (tabPos!=string::npos){
- line.replace(tabPos , 1, numberSpaces - (tabPos % numberSpaces) , ' ');
- tabPos = line.find('\t', tabPos+1);
- }
- }
-
- if (wrapLines){
- wsPrefix.clear();
- index=0;
- wsPrefixLength=string::npos;
- hasMore=true;
- redefineWsPrefix=false;
- }
-}
-
-std::string PreFormatter::getNextLine(){
-
- if (!wrapLines){
- hasMore = false;
- return line;
- }
-
- if (!index && line.length() > maxLineLength){ // erster Durchlauf...
- // wenn möglich an öffnender Klammer oder Geichheitszeichen ausrichten
- if (indentAfterOpenBraces){
- wsPrefixLength=line.find_first_of(INDENT_MARKERS);
- }
- // sonst die Einrückung der Originalzeile beibehalten
- if (wsPrefixLength==string::npos || wsPrefixLength-index>maxLineLength){
- wsPrefixLength=line.find_first_not_of(WS_CHARS);
- }
- else {
- // wsPrefix in allen neu umgebrochenen Zeilen durch Spaces ersetzen
- redefineWsPrefix=true;
- // Position hinter öffnende Klammer springen
- wsPrefixLength=line.find_first_not_of(WS_CHARS,wsPrefixLength+1);
- }
-
- if (wsPrefixLength!=string::npos){
- index = wsPrefixLength;
- // Falls Anzahl der Whitespaces am beginn der ersten zeile größer
- // als Max. Zeilenlänge, Whitespaces verwerfen
- if (wsPrefixLength>maxLineLength){
- wsPrefixLength=0;
- return string();
- }
- else{
- wsPrefix=line.substr(0, wsPrefixLength);
- }
- }
- // Zeile enthaelt nur Whitespace; verwerfen
- else {
- hasMore= false;
- return string();
- }
- } else {
- if (redefineWsPrefix){
- wsPrefix.clear();
- wsPrefix.append(wsPrefixLength, ' ');
- }
- redefineWsPrefix=false;
- }
-
- string resultString;
-
- // Position, ab der rckwaerts nach Umbruchmglichkeit gesucht wird
- unsigned int searchEndPos = maxLineLength - wsPrefixLength;
-
- // letztes Teilstueck der Zeile ausgeben; Parsen beenden
- if (line.length()-index < searchEndPos) {
- hasMore=false;
- resultString=(index>0) ? wsPrefix + line.substr(index) : line.substr(index);
- return resultString;
- }
-
- // Umbrechposition suchen
- size_t lbPos = line.find_last_of(LB_CHARS, index+searchEndPos);
- if (lbPos <= index || lbPos == string::npos) {
- // nichts gefunden, hart umbrechen
- lbPos = index + searchEndPos;
- }
- // Einrückung der Originalzeile erhalten
- resultString+=wsPrefix;
- // Neue Zeile erzeugen
- resultString += line.substr(index, lbPos-index+1);
-
- // Whitespace am neuen Zeilenbeginn ignorieren, ausser beim ersten Durchlauf
- //unsigned int newIndex=StringTools::getNextNonWsPos(line,lbPos+1);
- size_t newIndex=line.find_first_not_of(WS_CHARS, lbPos+1);
- index=(newIndex!=string::npos)?newIndex:line.length();
-
- hasMore=index!=line.length(); // unnoetigen Leerstring vermeiden
-
- return resultString;
-}
-
-void PreFormatter::setWrappingProperties(unsigned int maxLineLength, bool indentAfterOpenBraces){
- this->maxLineLength = maxLineLength;
- this->indentAfterOpenBraces = indentAfterOpenBraces;
-}
-
-void PreFormatter::setNumberSpaces(unsigned int num){
- numberSpaces = num;
-}
-
-}
-/***************************************************************************
- PreFormatter.cpp - description
- -------------------
- begin : Mo Jan 03 2005
- copyright : (C) 2005 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 PreFormatter_H
-#define PreFormatter_H
-
-#define LB_CHARS " \t[](){}-+<>.:,;"
-#define WS_CHARS " \n\r\t"
-#define INDENT_MARKERS "{(="
-
-#include <string>
-#include <iostream>
-
-#include "stringtools.h"
-
-namespace highlight {
-
-/** \brief Class which provides intelligent line wrapping.
-* @author Andre Simon
-*/
-
-class PreFormatter{
-public:
- /** Constructor
- */
- PreFormatter(bool wrap, bool replTabs);
-
- PreFormatter();
-
- ~PreFormatter();
-
- /**
- \return True if current line can be wrapped again
- */
- bool hasMoreLines();
-
- /**
- Sets new line to be wrapped
- \param newline New line
- */
- void setLine(const std::string newline);
-
- /**
- The method will indent function calls and statements
- \return Next line
- */
- std::string getNextLine();
-
- /**
- \return True if lines following open braces should be indented
- */
- bool indentCode();
-
- /**
- \param maxlength max. length of output lines
- \param indentAfterOpenBraces set true if lines should be indented after braces
- */
- void setWrappingProperties(unsigned int maxlength=80, bool indentAfterOpenBraces=true);
-
- /**
- \param num number of spaces which replace a tab
- */
-
- void setNumberSpaces(unsigned int num);
-
- /**
- \return true if preformatting is enabled
- */
- bool isEnabled(){
- return wrapLines || replaceTabs;
- }
-
-private:
-
- unsigned int maxLineLength;
-
- std::string line, wsPrefix;
- unsigned int index;
- unsigned int numberSpaces;
- size_t wsPrefixLength;
- bool hasMore, indentAfterOpenBraces;
- bool redefineWsPrefix;
- bool wrapLines, replaceTabs;
-};
-
-}
-
-#endif
-/***************************************************************************
- rtfcode.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 "rtfgenerator.h"
-
-using namespace std;
-
-namespace highlight {
-
-string RtfGenerator::formatStyleAttributes( const ElementStyle & col)
-{
- stringstream s;
- s << "\\red"<< col.getColour().getRTFRedValue()
- << "\\green"<<col.getColour().getRTFGreenValue()
- << "\\blue"<<col.getColour().getRTFBlueValue()
- << ";";
-
- return s.str();
-}
-
-string RtfGenerator::getOpenTag(int styleNumber,const ElementStyle & elem)
-{
- ostringstream s;
- s << "{\\cf"<<(styleNumber+1)<<"{";
- if (elem.isBold()) s << "\\b ";
- if (elem.isItalic()) s << "\\i ";
- if (elem.isUnderline()) s << "\\ul ";
- return s.str();
-}
-
-string RtfGenerator::getCloseTag(const ElementStyle &elem)
-{
- ostringstream s;
- if (elem.isBold()) s << "\\b0 ";
- if (elem.isItalic()) s << "\\i0 ";
- if (elem.isUnderline()) s << "\\ul0 ";
- s << "}}";
- return s.str();
-}
-
-RtfGenerator::RtfGenerator(const string &colourTheme)
- : CodeGenerator( colourTheme)
-{
- styleTagOpen.push_back(getOpenTag(STANDARD, docStyle.getDefaultStyle()));
- styleTagOpen.push_back(getOpenTag(STRING, docStyle.getStringStyle()));
- styleTagOpen.push_back(getOpenTag(NUMBER, docStyle.getNumberStyle()));
- styleTagOpen.push_back(getOpenTag(SL_COMMENT, docStyle.getSingleLineCommentStyle()));
- styleTagOpen.push_back(getOpenTag(ML_COMMENT_BEGIN,docStyle.getCommentStyle()));
- styleTagOpen.push_back(getOpenTag(ESC_CHAR, docStyle.getEscapeCharStyle()));
- styleTagOpen.push_back(getOpenTag(DIRECTIVE_LINE, docStyle.getDirectiveStyle()));
- styleTagOpen.push_back(getOpenTag(DIRECTIVE_STRING, docStyle.getDirectiveStringStyle()));
- styleTagOpen.push_back(getOpenTag(LINENUMBER, docStyle.getLineStyle()));
- styleTagOpen.push_back(getOpenTag(SYMBOL, docStyle.getSymbolStyle()));
-
- styleTagClose.push_back(getCloseTag(docStyle.getDefaultStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getStringStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getNumberStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getSingleLineCommentStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getCommentStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getEscapeCharStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getDirectiveStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getDirectiveStringStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getLineStyle()));
- styleTagClose.push_back(getCloseTag(docStyle.getSymbolStyle()));
-
- newLineTag = "\\par\\pard\n";
- spacer = " ";
-}
-
-RtfGenerator::RtfGenerator()
-{}
-RtfGenerator::~RtfGenerator()
-{}
-
-string RtfGenerator::getHeader(const string & title)
-{
- return string();
-}
-
-void RtfGenerator::printBody()
-{
- *out << "{\\rtf1\\ansi\\uc0 \\deff1"
- << "{\\fonttbl{\\f1\\fmodern\\fprq1\\fcharset0 Courier;}}"
- << "{\\colortbl;";
-
- *out << formatStyleAttributes(docStyle.getDefaultStyle());
-
- *out << formatStyleAttributes(docStyle.getStringStyle());
- *out << formatStyleAttributes(docStyle.getNumberStyle());
- *out << formatStyleAttributes(docStyle.getSingleLineCommentStyle());
-
- *out << formatStyleAttributes(docStyle.getCommentStyle());
- *out << formatStyleAttributes(docStyle.getEscapeCharStyle());
- *out << formatStyleAttributes(docStyle.getDirectiveStyle());
-
- *out << formatStyleAttributes(docStyle.getDirectiveStringStyle());
- *out << formatStyleAttributes(docStyle.getLineStyle());
- *out << formatStyleAttributes(docStyle.getSymbolStyle());
-
- /* For output formats which can refer to external styles it is more safe
- to use the colour theme's keyword class names, since the language
- definitions (which may change during a batch conversion) do not have to define
- all keyword classes, that are needed to highlight all input files correctly.
- It is ok for RTF to use the language definition's class names, because RTF
- does not refer to external styles.
- We cannot use the theme's class names, because KSIterator returns an
- alphabetically ordered list, which is not good because RTF is dependent
- on the order. We access the keyword style with an ID, which is calculated
- ignoring the alphabetic order.
- */
- vector<string> keywordClasses = langInfo.getKeywordClasses();
- for (unsigned int i=0;i<keywordClasses.size();i++){
- *out << formatStyleAttributes(docStyle.getKeywordStyle(keywordClasses[i]));
- }
-
- *out << "}\n{\\info }\\paperw11900\\paperh16820\\margl560\\margr560\\margt840"
- << "\\margb840\\widowctrl\\ftnbj\\aenddoc\\formshade \\fet0\\sectd"
- << "\\linex0\\endnhere\\plain\\f1\\fs20\n\\pard ";
- processRootState();
- *out << "}}"<<endl;
-}
-
-
-string RtfGenerator::getFooter()
-{
- return string();
-}
-
-/** Gibt RTF-Code der Sonderzeichen zurueck */
-string RtfGenerator::maskCharacter(unsigned char c)
-{
- switch (c)
- {
- case '}' :
- case '{' :
- case '\\' :
- {
- string m;
- m="\\";
- return m+=c;
- }
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- string m;
- m="{";
- m+=c;
- m+="}";
- return m;
- }
- break;
- case AUML_LC:
- return "\\'e4";
- break;
- case OUML_LC:
- return "\\'f6";
- break;
- case UUML_LC:
- return "\\'fc";
- break;
- case AUML_UC:
- return "\\'c4";
- break;
- case OUML_UC:
- return "\\'d6";
- break;
- case UUML_UC:
- return "\\'dc";
- break;
-
- case AACUTE_LC:
- return "\\'e1";
- break;
- case EACUTE_LC:
- return "\\'e9";
- break;
- case OACUTE_LC:
- return "\\'f3";
- break;
- case UACUTE_LC:
- return "\\'fa";
- break;
-
- case AGRAVE_LC:
- return "\\'e0";
- break;
- case EGRAVE_LC:
- return "\\'e8";
- break;
- case OGRAVE_LC:
- return "\\'f2";
- break;
- case UGRAVE_LC:
- return "\\'f9";
- break;
-
- case AACUTE_UC:
- return "\\'c1";
- break;
- case EACUTE_UC:
- return "\\'c9";
- break;
- case OACUTE_UC:
- return "\\'d3";
- break;
- case UACUTE_UC:
- return "\\'da";
- break;
- case AGRAVE_UC:
- return "\\'c0";
- break;
- case EGRAVE_UC:
- return "\\'c8";
- break;
- case OGRAVE_UC:
- return "\\'d2";
- break;
- case UGRAVE_UC:
- return "\\'d9";
- break;
-
- case SZLIG:
- return "\\'df";
- break;
- // skip first byte of multibyte chracters
- /* #ifndef _WIN32
- case 195:
- return string("");
- break;
-#endif*/
-
- default :
- {
- string m;
- return m += c;
- }
- }
-}
-
-string RtfGenerator::getMatchingOpenTag(unsigned int styleID){
- return getOpenTag(KEYWORD+styleID,
- docStyle.getKeywordStyle(langInfo.getKeywordClasses()[styleID]));
-}
-
-string RtfGenerator::getMatchingCloseTag(unsigned int styleID){
- return getCloseTag(docStyle.getKeywordStyle(langInfo.getKeywordClasses()[styleID]));
-}
-
-
-}
-/***************************************************************************
- rtfcode.h - description
- -------------------
- begin : Die Jul 9 2002
- copyright : (C) 2002 by Andre 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 RTFGENERATOR_H
-#define RTFGENERATOR_H
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <sstream>
-
-#include "codegenerator.h"
-#include "charcodes.h"
-#include "version.h"
-
-namespace highlight {
-
-/**
- \brief This class generates RTF.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-class RtfGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- */
- RtfGenerator( const string &colourTheme);
- RtfGenerator();
- ~RtfGenerator();
-
- /** prints document header
- \param title Title of the document
- */
- string getHeader(const string & title);
-
- /** Prints document footer*/
- string getFooter();
-
- /** Prints document body*/
- void printBody();
-
- private:
-
- /** \return escaped character*/
- virtual string maskCharacter(unsigned char );
-
- /**\return text formatting attributes in RTF format */
- string formatStyleAttributes( const ElementStyle & col);
-
- /** gibt RTF-"Tags" zurueck (Farbindex+bold+kursiv)*/
- string getOpenTag(int styleNumber,const ElementStyle &);
-
- string getCloseTag(const ElementStyle &);
-
- string getMatchingOpenTag(unsigned int styleID);
- string getMatchingCloseTag(unsigned int styleID);
- };
-
-}
-#endif
-/***************************************************************************
- stringtools.cpp - description
- -------------------
- begin : Mon Dec 10 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 "stringtools.h"
-
-#include <sstream>
-#include <iostream>
-#include <cctype>
-
-using namespace std;
-
-namespace StringTools
- {
-// Make a lowercase copy of s:
-// (C) Bruce Eckel, Thinking in C++ Vol 2
-
-string lowerCase(const string& s)
-{
- char* buf = new char[s.length()];
- s.copy(buf, s.length());
- for(unsigned int i = 0; i < s.length(); i++)
- buf[i] = tolower(buf[i]);
- string r(buf, s.length());
- delete buf;
- return r;
-}
-
-int str2int(string s)
-{
- istringstream os(s);
- int intVal;
- os >> intVal;
- return intVal;
-}
-
- bool isAlpha(unsigned char c)
- {
- return (isalpha(c) || c == '_');
- }
-
-string trimRight(const string &value)
- {
- string::size_type where = value.find_last_not_of(" \t\r");
-
- if (where == string::npos)
- // string has nothing but space
- return string();
-
- if (where == (value.length() - 1))
- // string has no trailing space, don't copy its contents
- return value;
-
- return value.substr(0, where + 1);
- }
-
-unsigned char getNextNonWs(const string &line, int index)
-{
- unsigned char c;
- do
- {
- c=line[index++];
- }
- while (isspace(c));
- return c;
-}
-
-string getParantheseVal(const string &s){
- string::size_type openPos=s.find('(');
- string::size_type closePos=s.rfind(')');
- if (openPos ==string::npos || closePos==string::npos){
- return string();
- }
- return s.substr(openPos+1, closePos-openPos-1);
-
-}
-
-}
-/***************************************************************************
- stringtools.h - description
- -------------------
- begin : Mon Dec 10 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 STRINGTOOLS_H
-#define STRINGTOOLS_H
-
-#include <string>
-
-using namespace std;
-
-/**\brief Contains methods for string manipulation
- *@author Andre Simon
- */
-
-namespace StringTools
- {
-
- /** \param s String
- \returns lowercase string */
- string lowerCase(const string &s);
-
- /** \param s String
- \returns Integer value */
- int str2int(string s);
-
- /** \return true if c is alpa or underscore */
- bool isAlpha(unsigned char c);
-
- /** \param value String
- \return string trimmed on the left side
- */
- string trimRight(const string &value);
-
- /** \return next character in line starting from index, which is no whitespace*/
- unsigned char getNextNonWs(const string &line, int index=0);
-
- /** \param s String, containing a opening and a closing paranthesis
- \return value between "(", ")" */
- string getParantheseVal(const string &s);
-
-}
-
-#endif
-/***************************************************************************
- stylecolour.cpp - description
- -------------------
- begin : Die Nov 5 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 "stylecolour.h"
-
-using std::string;
-
-namespace highlight {
-
-StyleColour::StyleColour(const string & r_hex, const string & g_hex, const string & b_hex)
- : r(r_hex), g(g_hex), b(b_hex)
-{}
-StyleColour::StyleColour()
- : r("00"), g("00"), b("00")
-{}
-
-//Parst PArameter aus style-Datei
-StyleColour::StyleColour(const string & styleColourString)
-{
- setRGBValues(styleColourString);
-}
-
-void StyleColour::setRGBValues(const string & styleColourString){
- //Stringstream zum Einlesen der Tokens:
- istringstream valueStream(styleColourString.c_str());
- valueStream >> r;
- valueStream >> g;
- valueStream >> b;
-}
-
-void StyleColour::setRedValue(const string & r_hex)
-{
- r = r_hex;
-}
-
-void StyleColour::setGreenValue(const string & g_hex)
-{
- g = g_hex;
-}
-
-void StyleColour::setBlueValue(const string & b_hex)
-{
- b = b_hex;
-}
-
-string& StyleColour::getHexRedValue()
-{
- return r;
-}
-string& StyleColour::getHexGreenValue()
-{
- return g;
-}
-string& StyleColour::getHexBlueValue()
-{
- return b;
-}
-
-
-string StyleColour::getRTFRedValue()
-{
- return int2str(hex2dec(r));
-}
-string StyleColour::getRTFGreenValue()
-{
- return int2str(hex2dec(g));
-}
-string StyleColour::getRTFBlueValue()
-{
- return int2str(hex2dec(b));
-}
-
-
-string StyleColour::getLatexRedValue()
-{
- return float2str((float)hex2dec(r)/255);
-}
-string StyleColour::getLatexGreenValue()
-{
- return float2str((float)hex2dec(g)/255);
-}
-string StyleColour::getLatexBlueValue()
-{
- return float2str((float)hex2dec(b)/255);
-}
-
-// Konvertieren von RGB nach CYM
-string StyleColour::getTexRedValue()
-{
- return float2str(1-(float)hex2dec(r)/255);
-}
-string StyleColour::getTexGreenValue()
-{
- return float2str(1-(float)hex2dec(g)/255);
-}
-string StyleColour::getTexBlueValue()
-{
- return float2str(1-(float)hex2dec(b)/255);
-}
-
-
-string StyleColour::int2str(const int num)
-{
- std::ostringstream outStream;
- outStream << num;
-
- return outStream.str();
-}
-
-string StyleColour::float2str(const double num)
-{
- std::ostringstream outStream;
- outStream << ( floor ( num * 100 + .5 ) / 100);
-
- return outStream.str();
-}
-
-int StyleColour::hex2dec(const string &hexVal)
-{
-
- if (hexVal.length() != 2)
- return 0;
-
- unsigned int decVal=0, koeff=16;
-
- for (int i=0; i<2;i++ )
- {
- if ((hexVal[i] >= '0')&& (hexVal[i]<= '9' ))
- {
- decVal += (koeff * (hexVal[i]-'0'));
-
- }
- if ((hexVal[i] >= 'a')&& (hexVal[i]<= 'f' ))
- {
- decVal +=( koeff * (hexVal[i]-87));
- }
- if ((hexVal[i] >= 'A')&& (hexVal[i]<= 'F' ))
- {
- decVal += (koeff * (hexVal[i]-55));
- }
- koeff=1;
- }
- return decVal;
-}
-
-}
-
-/***************************************************************************
- stylecolour.h - description
- -------------------
- begin : Die Nov 5 2002
- copyright : (C) 2002 by Andre 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 STYLECOLOUR_H
-#define STYLECOLOUR_H
-
-#include <string>
-#include <sstream>
-#include <fstream>
-#include <cmath>
-#include <sstream>
-
-using namespace std;
-
-namespace highlight {
-
-/**\brief Stores colours and returns red, green and blue values in different formats
-* @author Andre Simon
- */
-
-class StyleColour
- {
- public:
- /** Constructor
- \param r_hex Red value in hex notation
- \param g_hex Blue value in hex notation
- \param b_hex Green value in hex notation
- */
- StyleColour(const string & r_hex, const string & g_hex, const string & b_hex);
-
- /** Constructor
- \param styleColourString String with rgb values
- */
- StyleColour(const string & styleColourString);
-
- StyleColour();
- ~StyleColour(){};
-
- /** Sets red, green and blue values
- \param styleColourString String containing colour attributes
- */
- void setRGBValues(const string & styleColourString);
-
- /** Sets red value
- \param r_hex New red value */
- void setRedValue(const string & r_hex);
-
- /** Sets green value
- \param g_hex New green value */
- void setGreenValue(const string & g_hex);
-
- /** Sets blue value
- \param b_hex New blue value */
- void setBlueValue(const string & b_hex);
-
- /** \return Red value in hex format */
- string& getHexRedValue();
- /** \return Green value in hex format */
- string& getHexGreenValue();
- /** \return Blue value in hex format */
- string& getHexBlueValue();
-
- /** \return Red value in latex format */
- string getLatexRedValue();
- /** \return Green value in latex format */
- string getLatexGreenValue();
- /** \return Blue value in latex format */
- string getLatexBlueValue();
-
- /** \return Red value in tex format */
- string getTexRedValue();
- /** \return Green value in tex format */
- string getTexGreenValue();
- /** \return Blue value in tex format */
- string getTexBlueValue();
-
- /** \return Red value in RTF format */
- string getRTFRedValue();
- /** \return Green value in RTF format */
- string getRTFGreenValue();
- /** \return Blue value in RTF format */
- string getRTFBlueValue();
-
- private:
- string r, g, b;
- string int2str(int);
- string float2str(double);
- int hex2dec(const string &hexVal);
- };
-
-}
-
-#endif
-/***************************************************************************
- TexGenerator.cpp - description
- -------------------
- begin : Mit Jul 24 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 "texgenerator.h"
-
-namespace highlight {
-
-TexGenerator::TexGenerator(const string &colourTheme):
- CodeGenerator( colourTheme)
-{
- styleTagOpen.push_back( "{\\hlstd ");
- styleTagOpen.push_back( "{\\hlstr ");
- styleTagOpen.push_back( "{\\hlnum ");
- styleTagOpen.push_back( "{\\hlslc ");
- styleTagOpen.push_back( "{\\hlcom ");
- styleTagOpen.push_back( "{\\hlesc ");
- styleTagOpen.push_back( "{\\hldir ");
- styleTagOpen.push_back( "{\\hldstr ");
- styleTagOpen.push_back( "{\\hlline ");
- styleTagOpen.push_back( "{\\hlsym ");
- for (int i=0;i<NUMBER_BUILTIN_STYLES; i++) {
- styleTagClose.push_back( "}");
- }
-
- /*This makes TeX to use every par it encounters (the \\leavevmode has
- no effect when TeX is in horizontal mode and when TeX is in vertical
- mode, it switches it to horizontal mode).*/
- newLineTag="\\leavevmode\\par\n";
-
- spacer = "\\ ";
- maskWs=true;
- excludeWs=true;
- maskWsBegin = "{\\hlstd";
- maskWsEnd = "}";
- styleCommentOpen="%";
-}
-
-TexGenerator::TexGenerator()
-{}
-TexGenerator::~TexGenerator()
-{}
-
-string TexGenerator::formatStyleAttributes(const string & elemName,const ElementStyle & elem)
-{
- ostringstream s;
- s << "\\def\\hl"
- << elemName
- << "{";
- if (elem.isBold())
- s << "\\bf";
- if (elem.isItalic())
- s << "\\it";
- s << "\\textColor{"
- << (elem.getColour().getTexRedValue())<<" "
- << (elem.getColour().getTexGreenValue())<<" "
- << (elem.getColour().getTexBlueValue())<<" 0.0}}\n";
- return s.str();
-}
-
-string TexGenerator::getHeader(const string & title)
-{
- ostringstream os;
-
- if (langInfo.getSyntaxHighlight()) {
- if (includeStyleDef) {
- os << "\n"<<getStyleDefinition();
- os << CodeGenerator::readUserStyleDef();
- } else {
- os << "\\input "
- << getStyleOutputPath()
- << "\n\n";
- }
- }
-
- return os.str();
-}
-
-void TexGenerator::printBody()
-{
- *out << "{\n\\tt\n";
-
- processRootState();
- *out << "}\n";
-}
-
-string TexGenerator::getFooter()
-{
- ostringstream os;
- os << "\\bye\n"
- << "% TeX generated by Highlight "
- << HIGHLIGHT_VERSION
- << ", "
- << HIGHLIGHT_URL
- << endl;
- return os.str();
-}
-
-string TexGenerator:: maskCharacter(unsigned char c)
-{
- switch (c)
- {
- case '{':
- case '}':
- {
- string m;
- m = "$\\";
- m += c;
- m += "$";
- return m;
- }
- break;
- case '^':
- return "{\\bf\\^{}}";
- break;
- case '_':
- return "\\_{}";
- break;
- case '&':
- case '$':
- case '#':
- case '%':
- {
- string m;
- m = "\\";
- m += c;
- return m;
- }
- break;
- case '\\':
- return "$\\backslash$";
- break;
- case ' ':
- return spacer;
- break;
- case '+':
- case '-':
- case '<':
- case '>':
- case '=':
- {
- string m;
- m = "$\\mathord{";
- m += c;
- m += "}$";
- return m;
- }
- break;
- case AUML_LC:
- return "\\\"a";
- break;
- case OUML_LC:
- return "\\\"o";
- break;
- case UUML_LC:
- return "\\\"u";
- break;
- case AUML_UC:
- return "\\\"A";
- break;
- case OUML_UC:
- return "\\\"O";
- break;
- case UUML_UC:
- return "\\\"U";
- break;
- case AACUTE_LC:
- return "\\'a";
- break;
- case EACUTE_LC:
- return "\\'e";
- break;
- case OACUTE_LC:
- return "\\'o";
- break;
- case UACUTE_LC:
- return "\\'u";
- break;
- case AGRAVE_LC:
- return "\\`a";
- break;
- case EGRAVE_LC:
- return "\\`e";
- break;
- case OGRAVE_LC:
- return "\\`o";
- break;
- case UGRAVE_LC:
- return "\\`u";
- break;
- case AACUTE_UC:
- return "\\'A";
- break;
- case EACUTE_UC:
- return "\\'E";
- break;
- case OACUTE_UC:
- return "\\'O";
- break;
- case UACUTE_UC:
- return "\\'U";
- break;
- case AGRAVE_UC:
- return "\\`A";
- break;
- case EGRAVE_UC:
- return "\\`E";
- break;
- case UGRAVE_UC:
- return "\\`O";
- break;
- case OGRAVE_UC:
- return "\\`U";
- break;
- case SZLIG:
- return "\\ss ";
- break;
- /* #ifndef _WIN32
- // skip first byte of multibyte chracters
- case 195:
- return string("");
- break;
-#endif*/
-
- default :
- string m;
- return m += c;
- }
-}
-
-string TexGenerator::getMatchingOpenTag(unsigned int styleID){
- return "{\\hl"+langInfo.getKeywordClasses()[styleID]+" ";
- }
-
-string TexGenerator::getMatchingCloseTag(unsigned int styleID){
- return "}";
-}
-
-
-string TexGenerator::getStyleDefinition()
-{
- if (styleDefinitionCache.empty()){
- ostringstream os;
- os << formatStyleAttributes("std", docStyle.getDefaultStyle());
- os << formatStyleAttributes("num", docStyle.getNumberStyle());
- os << formatStyleAttributes("esc", docStyle.getEscapeCharStyle());
- os << formatStyleAttributes("str", docStyle.getStringStyle());
- os << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle());
- os << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle());
- os << formatStyleAttributes("com", docStyle.getCommentStyle());
- os << formatStyleAttributes("dir", docStyle.getDirectiveStyle());
- os << formatStyleAttributes("line", docStyle.getLineStyle());
- os << formatStyleAttributes("sym", docStyle.getSymbolStyle());
-
- KeywordStyles styles = docStyle.getKeywordStyles();
- for (KSIterator it=styles.begin(); it!=styles.end(); it++){
- os << formatStyleAttributes(it->first, *(it->second));
- }
-
- os << "% The special option is not supported by all dvi drivers\n"
- << "\\special{background rgb "
- << docStyle.getBgColour().getLatexRedValue() << " "
- << docStyle.getBgColour().getLatexGreenValue() << " "
- << docStyle.getBgColour().getLatexBlueValue() << "}";
- os << "\n\\nopagenumbers\n"
- << "\\input colordvi\n";
- styleDefinitionCache=os.str();
- }
- return styleDefinitionCache;
-}
-
-
-}
-/***************************************************************************
- texcode.h - description
- -------------------
- begin : Mit Jul 24 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. *
- * *
- ***************************************************************************/
-
-#ifndef TEXGENERATOR_H
-#define TEXGENERATOR_H
-
-#include <string>
-#include <iostream>
-#include <sstream>
-
-#include "charcodes.h"
-#include "version.h"
-#include "codegenerator.h"
-
-
-namespace highlight {
-
-/**
- \brief This class generates TeX.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-class TexGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- */
- TexGenerator(const string &colourTheme);
- TexGenerator();
- ~TexGenerator();
-
- /** prints document header
- \param title Title of the document
- */
- string getHeader(const string & title);
-
- /** Prints document footer*/
- string getFooter();
-
- /** Prints document body*/
- void printBody();
-
- private:
-
- string styleDefinitionCache;
-
- string getStyleDefinition();
-
- /** \return escaped character*/
- virtual string maskCharacter(unsigned char );
-
- /**\return text formatting attributes in RTF format */
- string formatStyleAttributes(const string & elemName, const ElementStyle & elem);
-
- string getMatchingOpenTag(unsigned int styleID);
- string getMatchingCloseTag(unsigned int styleID);
-
- };
-
-}
-
-#endif
-/***************************************************************************
- version.h - description
- -------------------
- begin : Mon March 3 2003
- copyright : (C) 2003 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 VERSION_H
-#define VERSION_H
-
-#define HIGHLIGHT_VERSION "2.2-10"
-
-#define HIGHLIGHT_URL "http://www.andre-simon.de/"
-#define HIGHLIGHT_EMAIL "andre.simon1@gmx.de"
-
-#endif
-/***************************************************************************
- htmlcode.cpp - description
- -------------------
- begin : Wed Nov 28 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 "xhtmlgenerator.h"
-
-using namespace std;
-
-namespace highlight {
-
-XHtmlGenerator::XHtmlGenerator(void)
-{}
-
-XHtmlGenerator::XHtmlGenerator (
- const string &cssStyle,
- const string &enc,
- bool omitEnc,
- bool withAnchors)
- : HtmlGenerator(cssStyle, enc, omitEnc, withAnchors)
-{
- fileSuffix=".xhtml";
- brTag="<br />";
- hrTag="<hr />";
- idAttr="id";
-
- HTML_FOOTER=
- "\n</body>\n</html>\n<!--XHTML generated by highlight "
- HIGHLIGHT_VERSION
- ", "
- HIGHLIGHT_URL
- "-->\n";
-}
-
-string XHtmlGenerator::getHeaderStart(const string &title){
- ostringstream header;
- header << "<?xml version=\"1.0\"";
- if (!omitEncoding) {
- header << " encoding=\"" << encoding << "\"";
- }
- header << "?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\""
- << " \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
- << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
- << "<head>\n<title>" << title << "</title>\n";
-
- return header.str();
-}
-
-
-string XHtmlGenerator::getHeader(const string &title)
-{
- ostringstream osPart1;
- osPart1 << getHeaderStart((title.empty())?"Source file":title );
-
- if (langInfo.getSyntaxHighlight())
- {
- if (includeStyleDef) //CSS-Definition in HTML-<head> einfuegen
- {
- osPart1 << "<style type=\"text/css\">\n";
- osPart1 << "<![CDATA[\n";
- osPart1 << getStyleDefinition();
- osPart1 << CodeGenerator::readUserStyleDef();
- osPart1 << "]]>\n";
- osPart1 << "</style>\n";
- }
- else //Referenz auf CSS-Datei einfuegen
- {
- osPart1 << "<link rel=\"stylesheet\" type=\"text/css\" href=\""
- << getStyleOutputPath()
- << "\""
- << "/"
- << ">\n";
- }
- }
- osPart1 << "</head>\n<body class=\"hl\">\n<pre class=\"hl\">";
-
- return osPart1.str();
-}
-
-}
-/***************************************************************************
- xhtmlgenerator.h - description
- -------------------
- begin : Mo Jun 21 2004
- copyright : (C) 2004 by Andre 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 XHTMLGENERATOR_H
-#define XHTMLGENERATOR_H
-
-#include "htmlgenerator.h"
-
-namespace highlight {
-
-/**
- \brief This class generates XHTML.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-
-class XHtmlGenerator : public highlight::HtmlGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- \param enc encoding name
- \param omitEnc switch to omit encoding information
- \param withAnchors Test if HTML anchors should be attached to line numbers
- */
- XHtmlGenerator(const string &colourTheme,
- const string &enc,
- bool omitEnc=false,
- bool withAnchors = false);
-
- XHtmlGenerator();
-
- /** Destructor*/
- virtual ~XHtmlGenerator() {};
-
- private:
-
- /** prints document header
- \param title Title of the document
- */
- string getHeader(const string &title);
-
- string getHeaderStart(const string &title);
-
- };
-
-}
-
-#endif
-/***************************************************************************
- xmlcode.cpp - description
- -------------------
- begin : Do 20.01.2005
- copyright : (C) 2005 by Andre 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 "xmlgenerator.h"
-
-using namespace std;
-namespace highlight {
-
- XmlGenerator::XmlGenerator(const string &colourTheme,const string &enc, bool omitEnc)
- : CodeGenerator(colourTheme),
- encoding(enc), omitEncoding(omitEnc)
-{
- styleTagOpen.push_back(getOpenTag("def"));
- styleTagOpen.push_back(getOpenTag("str"));
- styleTagOpen.push_back(getOpenTag("num"));
- styleTagOpen.push_back(getOpenTag("slc"));
- styleTagOpen.push_back(getOpenTag("com"));
- styleTagOpen.push_back(getOpenTag("esc"));
- styleTagOpen.push_back(getOpenTag("dir"));
- styleTagOpen.push_back(getOpenTag("dstr"));
- styleTagOpen.push_back(getOpenTag("line"));
- styleTagOpen.push_back(getOpenTag("sym"));
-
- styleTagClose.push_back(getCloseTag("def"));
- styleTagClose.push_back(getCloseTag("str"));
- styleTagClose.push_back(getCloseTag("num"));
- styleTagClose.push_back(getCloseTag("slc"));
- styleTagClose.push_back(getCloseTag("com"));
- styleTagClose.push_back(getCloseTag("esc"));
- styleTagClose.push_back(getCloseTag("dir"));
- styleTagClose.push_back(getCloseTag("dstr"));
- styleTagClose.push_back(getCloseTag("line"));
- styleTagClose.push_back(getCloseTag("sym"));
-
- spacer = " ";
- newLineTag = "<br />\n";
-}
-
-string XmlGenerator::getStyleDefinition()
-{
- if (styleDefinitionCache.empty()) {
- ostringstream os;
- os << "\n<style>\n"
- << "\t<bgcolor value=\""
- << (docStyle.getBgColour().getHexRedValue())
- << (docStyle.getBgColour().getHexGreenValue())
- << (docStyle.getBgColour().getHexBlueValue())
- << "\" />\n"
- << "\t<font size=\""
- << docStyle.getFontSize()
- << "\" family=\"Courier\" />\n";
-
- os << formatStyleAttributes("def", docStyle.getDefaultStyle())
- << formatStyleAttributes("num", docStyle.getNumberStyle())
- << formatStyleAttributes("esc", docStyle.getEscapeCharStyle())
- << formatStyleAttributes("str", docStyle.getStringStyle())
- << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle())
- << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle())
- << formatStyleAttributes("com", docStyle.getCommentStyle())
- << formatStyleAttributes("dir", docStyle.getDirectiveStyle())
- << formatStyleAttributes("sym", docStyle.getSymbolStyle())
- << formatStyleAttributes("line", docStyle.getLineStyle());
-
- KeywordStyles styles = docStyle.getKeywordStyles();
- for (KSIterator it=styles.begin(); it!=styles.end(); it++){
- os << formatStyleAttributes(it->first, *(it->second));
- }
- os << "</style>\n";
- styleDefinitionCache=os.str();
- }
- return styleDefinitionCache;
-}
-
-
-string XmlGenerator::formatStyleAttributes(const string & elemName,
- const ElementStyle & elem)
-{
- ostringstream s;
- s << "\t<class name=\""
- << elemName
- <<"\" color=\""
- << (elem.getColour().getHexRedValue())
- << (elem.getColour().getHexGreenValue())
- << (elem.getColour().getHexBlueValue() )
- << "\" bold=\""
- << ( elem.isBold() ? "true" :"false" )
- << "\" italic=\""
- << ( elem.isItalic() ? "true" :"false" )
- << "\" underline=\""
- << ( elem.isUnderline() ? "true" :"false" )
- << "\" />\n" ;
- return s.str();
-}
-
-
-XmlGenerator::XmlGenerator()
-{}
-XmlGenerator::~XmlGenerator()
-{}
-
-string XmlGenerator::getOpenTag(const string& styleName ){
- return "<"+styleName+">";
-}
-
-string XmlGenerator::getCloseTag(const string& styleName ){
- return "</"+styleName+">";
-}
-
-string XmlGenerator::getHeader(const string & title)
-{
- ostringstream header;
- header << "<?xml version=\"1.0\"";
- if (!omitEncoding) {
- header << " encoding=\"" << encoding << "\"";
- }
- header << "?>\n<document>" << getStyleDefinition();
- return header.str();
-}
-
-void XmlGenerator::printBody()
-{
- *out << "<source>\n";
- processRootState();
- *out << "</source>\n";
-}
-
-
-string XmlGenerator::getFooter()
-{
- ostringstream os;
- os <<"</document>\n";
- os<< "<!-- XML generated by Highlight "
- << HIGHLIGHT_VERSION
- << ", "
- << HIGHLIGHT_URL
- <<" -->\n";
- return os.str();
-}
-
-string XmlGenerator::maskCharacter(unsigned char c)
-{
- switch (c)
- {
- case '<' :
- return "&lt;";
- break;
- case '>' :
- return "&gt;";
- break;
- case '&' :
- return "&amp;";
- break;
- case '\"' :
- return "&quot;";
- break;
-
-// skip first byte of multibyte chracters
- /* #ifndef _WIN32
- case 195:
- return string("");
- break;
-#endif*/
-
- default:
- string m;
- m += c;
- return m;
- }
-}
-
-/*string XmlGenerator::getNewLine(){
- string nlStr;
- if (currentState!=_UNKNOWN){
- nlStr+=styleTagClose[getStyleID(currentState, currentKeywordClass)];
- }
- nlStr += newLineTag;
- if (currentState!=_UNKNOWN){
- nlStr+=styleTagOpen[getStyleID(currentState, currentKeywordClass)];
- }
- return nlStr;
-}
-*/
-string XmlGenerator::getMatchingOpenTag(unsigned int styleID){
- return getOpenTag(langInfo.getKeywordClasses()[styleID]);
-}
-
-string XmlGenerator::getMatchingCloseTag(unsigned int styleID){
- return getCloseTag(langInfo.getKeywordClasses()[styleID]);
-}
-
-}
-/***************************************************************************
- xmlcode.h - description
- -------------------
- begin : Do 20.01.2005
- copyright : (C) 2005 by Andre 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 XMLGENERATOR_H
-#define XMLGENERATOR_H
-
-#include <string>
-#include <sstream>
-#include <iostream>
-
-#include "codegenerator.h"
-#include "version.h"
-
-namespace highlight {
-
-/**
- \brief This class generates XML.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-class XmlGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- \param enc encoding name
- \param omitEnc switch to omit encoding information
- */
- XmlGenerator( const string &colourTheme,const string &enc, bool omitEnc=false);
-
- XmlGenerator();
-
- ~XmlGenerator();
-
- /** prints document header
- \param title Title of the document
- */
- string getHeader(const string & title);
-
- /** Prints document footer*/
- string getFooter();
-
- /** Prints document body*/
- void printBody();
-
- private:
-
- string styleDefinitionCache, encoding;
-
- bool omitEncoding;
-
- string getStyleDefinition();
-
- string formatStyleAttributes(const string &, const ElementStyle &);
-
- /** \return escaped character*/
- virtual string maskCharacter(unsigned char );
-
-
-// string getNewLine();
-
- string getOpenTag(const string& );
- string getCloseTag(const string& );
-
- string getMatchingOpenTag(unsigned int styleID);
- string getMatchingCloseTag(unsigned int styleID);
- };
-
-}
-
-#endif
-/***************************************************************************
- xslfocode.cpp - description
- -------------------
- begin : Do 11.12.2003
- copyright : (C) 2003 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 "xslfogenerator.h"
-
-using namespace std;
-namespace highlight {
-
-XslFoGenerator::XslFoGenerator(const string &colourTheme,
- const string &enc,
- bool omitEnc,
- bool fopCompatible)
- : CodeGenerator(colourTheme),
- encoding(enc),
- fopOutput(fopCompatible),
- omitEncoding(omitEnc)
-{
- styleTagOpen.push_back( getOpenTag(docStyle.getDefaultStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getStringStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getNumberStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getSingleLineCommentStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getCommentStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getEscapeCharStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getDirectiveStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getDirectiveStringStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getLineStyle()));
- styleTagOpen.push_back( getOpenTag(docStyle.getSymbolStyle()));
- snl << " <fo:block font-size=\""
- << docStyle.getFontSize()
- << "pt\" font-family=\"Courier\" white-space-collapse=\"false\" "
- << "wrap-option=\"wrap\" line-height=\"12pt\" background-color=\"#"
- << (docStyle.getBgColour().getHexRedValue())
- << (docStyle.getBgColour().getHexGreenValue())
- << (docStyle.getBgColour().getHexBlueValue())
- << "\">";
-
- for (int i=0;i<NUMBER_BUILTIN_STYLES; i++)
- {
- styleTagClose.push_back( "</fo:inline>");
- }
- if (fopOutput)
- newLineTag ="</fo:block>\n<fo:block>";
- else
- newLineTag ="</fo:block>\n"+ snl.str();
-
- spacer = " ";
-}
-
-XslFoGenerator::XslFoGenerator()
-{}
-XslFoGenerator::~XslFoGenerator()
-{}
-
-string XslFoGenerator::getOpenTag(const ElementStyle &elem)
-{
- ostringstream s;
- s << "<fo:inline color=\"#"
- << (elem.getColour().getHexRedValue())
- << (elem.getColour().getHexGreenValue())
- << (elem.getColour().getHexBlueValue())
- << "\"";
- s << ( elem.isBold() ?" font-weight=\"bold\"" :"" )
- << ( elem.isItalic() ?" font-style=\"italic\"" :"" )
- << ( elem.isUnderline() ?" text-decoration=\"underline\"" :"" );
- s << ">";
- return s.str();
-}
-
-string XslFoGenerator::getHeader(const string & title)
-{
- ostringstream os;
- os << "<?xml version=\"1.0\"";
- if (!omitEncoding) {
- os << " encoding=\"" << encoding << "\"";
- }
- os << "?>\n<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
- << "<fo:layout-master-set>\n"
- << "<fo:simple-page-master master-name=\"DINA4\"\n"
- << " page-height=\"29.7cm\"\n"
- << " page-width=\"21cm\"\n"
- << " margin-top=\"1cm\"\n"
- << " margin-bottom=\"2cm\"\n"
- << " margin-left=\"2.5cm\"\n"
- << " margin-right=\"2.5cm\">\n"
- << "<fo:region-body />\n"
- << "</fo:simple-page-master>\n"
- << "<fo:page-sequence-master master-name=\"basic\">\n"
- << "<fo:repeatable-page-master-alternatives>\n"
- << "<fo:conditional-page-master-reference master-reference=\"DINA4\" />\n"
- << "</fo:repeatable-page-master-alternatives>\n"
- << "</fo:page-sequence-master>\n"
- << "</fo:layout-master-set>\n\n"
- << "<fo:page-sequence master-reference=\"basic\">\n"
- << " <fo:flow flow-name=\"xsl-region-body\">\n";
- if (fopOutput)
- os << snl.str()<< "<fo:block>";
- else
- os << snl.str();
-
- return os.str();
-}
-
-/** gibt RTF-Text aus */
-void XslFoGenerator::printBody()
-{
- processRootState();
-}
-
-
-string XslFoGenerator::getFooter()
-{
- ostringstream os;
- if (fopOutput)
- os <<"\n</fo:block>";
- os <<"\n</fo:block>\n </fo:flow>\n</fo:page-sequence>\n</fo:root>"<<endl
- << "<!-- XSL-FO generated by Highlight "
- << HIGHLIGHT_VERSION
- << ", "
- << HIGHLIGHT_URL
- <<" -->\n";
- return os.str();
-}
-
-/** Gibt RTF-Code der Sonderzeichen zurueck */
-string XslFoGenerator::maskCharacter(unsigned char c)
-{
- switch (c)
- {
- case '<' :
- return "&lt;";
- break;
- case '>' :
- return "&gt;";
- break;
- case '&' :
- return "&amp;";
- break;
- case '\"' :
- return "&quot;";
- break;
-
-// skip first byte of multibyte chracters
- /*#ifndef _WIN32
- case 195:
- return string("");
- break;
-#endif*/
-
- default:
- string m;
- m += c;
- return m;
- }
-}
-
-/*string XslFoGenerator::getNewLine(){
- string nlStr;
-
- if (currentState!=_UNKNOWN){
- nlStr+=styleTagClose[getStyleID(currentState, currentKeywordClass)];
-}
- nlStr += newLineTag;
- if (currentState!=_UNKNOWN){
- nlStr+=styleTagOpen[getStyleID(currentState, currentKeywordClass)];
-}
- return nlStr;
-}*/
-
-string XslFoGenerator::getMatchingOpenTag(unsigned int styleID){
- return getOpenTag(docStyle.getKeywordStyle(langInfo.getKeywordClasses()[styleID]));
-}
-
-string XslFoGenerator::getMatchingCloseTag(unsigned int styleID){
- return "</fo:inline>";
-}
-
-}
-/***************************************************************************
- xslfocode.h - description
- -------------------
- begin : Do 11.12.2003
- copyright : (C) 2003 by Andre 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 XSLFOGENERATOR_H
-#define XSLFOGENERATOR_H
-
-
-#include <string>
-#include <sstream>
-#include <iostream>
-#include <fstream>
-
-#include "codegenerator.h"
-#include "version.h"
-
-namespace highlight {
-
-/**
- \brief This class generates XSL-FO.
-
- It contains information about the resulting document structure (document
- header and footer), the colour system, white space handling and text
- formatting attributes.
-
-* @author Andre Simon
-*/
-
-class XslFoGenerator : public highlight::CodeGenerator
- {
- public:
-
- /** Constructor
- \param colourTheme Name of Colour theme to use
- \param enc encoding name
- \param omitEnc switch to omit encoding information
- \param fopCompatible Test if output should be compatible with Apache FOP 0.20.5
- */
- XslFoGenerator( const string &colourTheme,
- const string &enc,
- bool omitEnc=false,
- bool fopCompatible=false);
-
- XslFoGenerator();
-
- ~XslFoGenerator();
-
- /** prints document header
- \param title Title of the document
- */
- string getHeader(const string & title);
-
- /** Prints document footer*/
- string getFooter();
-
- /** Prints document body*/
- void printBody();
-
- private:
- ostringstream snl;
-
- string styleDefinition, encoding;
- bool fopOutput, omitEncoding;
-
- /** \return escaped character*/
- virtual string maskCharacter(unsigned char );
-
- string getOpenTag(const ElementStyle &);
-
- // string getNewLine();
-
- string getMatchingOpenTag(unsigned int styleID);
- string getMatchingCloseTag(unsigned int styleID);
- };
-
-}
-
-#endif
diff --git a/tests/examplefiles/example.rb b/tests/examplefiles/example.rb
index 53c89efe..8a3304ba 100644
--- a/tests/examplefiles/example.rb
+++ b/tests/examplefiles/example.rb
@@ -7554,2517 +7554,3 @@ trunc_em(nums)
# ``chomp'' chomps the record separator and returns what's expected
# ``chomp!'' does the same but also modifies the parameter object
-
-# @@PLEAC@@_10.2
-def somefunc
- variable = something # variable is local by default
-end
-
-name, age = ARGV
-start = fetch_time
-
-a, b = pair # will succeed if pair is an Array object (like ARGV is)
-c = fetch_time
-
-# In ruby, run_check can't access a, b, or c until they are
-# explicitely defined global (using leading $), even if they are
-# both defined in the same scope
-
-def check_x(x)
- y = "whatever"
- run_check
- if $condition
- puts "got $x"
- end
-end
-
-# The following will keep a reference to the array, though the
-# results will be slightly different from perl: the last element
-# of $global_array will be itself an array
-def save_array(ary)
- $global_array << ary
-end
-
-# The following gives the same results as in Perl for $global_array,
-# though it doesn't illustrate anymore the way to keep a reference
-# to an object: $global_array is extended with the elements of ary
-def save_array(ary)
- $global_array += ary
-end
-
-
-# @@PLEAC@@_10.3
-# In Ruby, AFAIK a method cannot access "local variables" defined
-# upper scope; mostly because everything is an object, so you'll
-# do the same by defining an attribute or a static attribute
-
-# In Ruby the BEGIN also exists:
-BEGIN { puts "hello from BEGIN" }
-puts "hello from main"
-BEGIN { puts "hello from 2nd BEGIN" }
-# gives:
-# hello from BEGIN
-# hello from 2nd BEGIN
-# hello from main
-
-# In Ruby, it can be written as a static method and a static
-# variable
-class Counter
- @@counter = 0
- def Counter.next_counter; @@counter += 1; end
-end
-
-# There is no need of BEGIN since the variable will get
-# initialized when parsing
-class Counter
- @@counter = 42
- def Counter.next_counter; @@counter += 1; end
- def Counter.prev_counter; @@counter -= 1; end
-end
-
-
-# @@PLEAC@@_10.4
-# You can either get the whole trace as an array of strings, each
-# string telling which file, line and method is calling:
-caller
-
-# ...or only the last caller
-caller[0]
-
-# We need to extract just the method name of the backtrace:
-def whoami; caller()[0] =~ /in `([^']+)'/ ? $1 : '(anonymous)'; end
-def whowasi; caller()[1] =~ /in `([^']+)'/ ? $1 : '(anonymous)'; end
-
-
-# @@PLEAC@@_10.5
-# In Ruby, every value is a reference on an object, thus there is
-# no such problem
-array_diff(array1, array2)
-
-def add_vecpair(a1, a2)
- results = []
- a1.each_index { |i| results << (a1[i] + a2[i]) }
- results
-end
-a = [1, 2]
-b = [5, 8]
-c = add_vecpair(a, b)
-p c
-
-# Add this to the beginning of the function to check if we were
-# given two arrays
-a1.type == Array && a2.type == Array or
- raise "usage: add_vecpair array1 array2 (was used with: #{a1.type} #{a2.type})"
-
-
-# @@PLEAC@@_10.6
-# There is no return context in Ruby
-
-
-# @@PLEAC@@_10.7
-# Like in Perl, we need to fake with a hash, but it's dirty :-(
-def thefunc(param_args)
- args = { 'INCREMENT' => '10s', 'FINISH' => '0', 'START' => 0 }
- args.update(param_args)
- if (args['INCREMENT'] =~ /m$/ )
- # .....
- end
-end
-
-thefunc({ 'INCREMENT' => '20s', 'START' => '+5m', 'FINISH' => '+30m' })
-thefunc({})
-
-
-# @@PLEAC@@_10.8
-# there is no "undef" direct equivalent but there is the slice equiv:
-a, c = func.indexes(0, 2)
-
-
-# @@PLEAC@@_10.9
-# Ruby has no such limitation:
-def somefunc
- ary = []
- hash = {}
- # ...
- return ary, hash
-end
-arr, dict = somefunc
-
-array_of_hashes = fn
-h1, h2, h3 = fn
-
-
-# @@PLEAC@@_10.10
-return
-# or (equivalent)
-return nil
-
-
-# @@PLEAC@@_10.11
-# You can't prototype in Ruby regarding types :-(
-# Though, you can force the number of arguments:
-def func_with_no_arg; end
-def func_with_no_arg(); end
-def func_with_one_arg(a1); end
-def func_with_two_args(a1, a2); end
-def func_with_any_number_of_args(*args); end
-
-
-# @@PLEAC@@_10.12
-raise "some message" # raise exception
-
-begin
- val = func
-rescue Exception => msg
- $stderr.puts "func raised an exception: #{msg}"
-end
-
-# In Ruby the rescue statement uses an exception class, every
-# exception which is not matched is still continuing
-begin
- val = func
-rescue FullMoonError
- ...
-end
-
-
-# @@PLEAC@@_10.13
-# Saving Global Values
-# Of course we can just save the value and restore it later:
-def print_age
- puts "Age is #{$age}"
-end
-
-$age = 18 # global variable
-print_age()
-if condition
- safeage = $age
- $age = 23
- print_age()
- $age = safeage
-end
-
-# We can also use a method that saves the global variable and
-# restores it automatically when the block is left:
-
-def local(var)
- eval("save = #{var.id2name}")
- begin
- result = yield
- ensure
- # we want to call this even if we got an exception
- eval("#{var.id2name} = save")
- end
- result
-end
-
-condition = true
-$age = 18
-print_age()
-if condition
- local(:$age) {
- $age = 23
- print_age()
- }
-end
-print_age()
-
-# There is no need to use local() for filehandles or directory
-# handles in ruby because filehandles are normal objects.
-
-
-# @@PLEAC@@_10.14
-# In Ruby you may redefine a method [but not overload it :-(]
-# just by defining again with the same name.
-def foo; puts 'foo'; end
-def foo; puts 'bar'; end
-foo
-#=> bar
-
-# You can also take a reference to an existing method before
-# redefining a new one, using the `alias' keyword
-def foo; puts 'foo'; end
-alias foo_orig foo
-def foo; puts 'bar'; end
-foo_orig
-foo
-#=> foo
-#=> bar
-
-# AFAIK, there is no direct way to create a new method whose name
-# comes from a variable, so use "eval"
-colors = %w(red blue green yellow orange purple violet)
-colors.each { |c|
- eval <<-EOS
- def #{c}(*a)
- "<FONT COLOR='#{c}'>" + a.to_s + "</FONT>"
- end
- EOS
-}
-
-
-# @@PLEAC@@_10.15
-def method_missing(name, *args)
- "<FONT COLOR='#{name}'>" + args.join(' ') + "</FONT>"
-end
-puts chartreuse("stuff")
-
-
-# @@PLEAC@@_10.16
-def outer(arg)
- x = arg + 35
- inner = proc { x * 19 }
- x + inner.call()
-end
-
-
-# @@PLEAC@@_10.17
-#!/usr/bin/ruby -w
-# mailsort - sort mbox by different criteria
-require 'English'
-require 'Date'
-
-# Objects of class Mail represent a single mail.
-class Mail
- attr_accessor :no
- attr_accessor :subject
- attr_accessor :fulltext
- attr_accessor :date
-
- def initialize
- @fulltext = ""
- @subject = ""
- end
-
- def append(para)
- @fulltext << para
- end
-
- # this is called if you call puts(mail)
- def to_s
- @fulltext
- end
-end
-
-# represents a list of mails.
-class Mailbox < Array
-
- Subjectpattern = Regexp.new('Subject:\s*(?:Re:\s*)*(.*)\n')
- Datepattern = Regexp.new('Date:\s*(.*)\n')
-
- # reads mails from open file and stores them
- def read(file)
- $INPUT_RECORD_SEPARATOR = '' # paragraph reads
- msgno = -1
- file.each { |para|
- if para =~ /^From/
- mail = Mail.new
- mail.no = (msgno += 1)
- md = Subjectpattern.match(para)
- if md
- mail.subject = md[1]
- end
- md = Datepattern.match(para)
- if md
- mail.date = DateTime.parse(md[1])
- else
- mail.date = DateTime.now
- end
- self.push(mail)
- end
- mail.append(para) if mail
- }
- end
-
- def sort_by_subject_and_no
- self.sort_by { |m|
- [m.subject, m.no]
- }
- end
-
- # sorts by a list of attributs of mail, given as symbols
- def sort_by_attributs(*attrs)
- # you can sort an Enumerable by an array of
- # values, they would be compared
- # from ary[0] to ary[n]t, say:
- # ['b',1] > ['a',10] > ['a',9]
- self.sort_by { |elem|
- attrs.map { |attr|
- elem.send(attr)
- }
- }
- end
-
-end
-
-mailbox = Mailbox.new
-mailbox.read(ARGF)
-
-# print only subjects sorted by subject and number
-for m in mailbox.sort_by_subject_and_no
- puts(m.subject)
-end
-
-# print complete mails sorted by date, then subject, then number
-for m in mailbox.sort_by_attributs(:date, :subject)
- puts(m)
-end
-
-
-# @@PLEAC@@_11.7
-def mkcounter(count)
- start = count
- bundle = {
- "NEXT" => proc { count += 1 },
- "PREV" => proc { count -= 1 },
- "RESET" => proc { count = start }
- }
- bundle["LAST"] = bundle["PREV"]
- return bundle
-end
-
-c1 = mkcounter(20)
-c2 = mkcounter(77)
-
-puts "next c1: #{c1["NEXT"].call}" # 21
-puts "next c2: #{c2["NEXT"].call}" # 78
-puts "next c1: #{c1["NEXT"].call}" # 22
-puts "last c1: #{c1["PREV"].call}" # 21
-puts "last c1: #{c1["LAST"].call}" # 20
-puts "old c2: #{c2["RESET"].call}" # 77
-
-
-# @@PLEAC@@_11.15
-class Binary_tree
- def initialize(val)
- @value = val
- @left = nil
- @right = nil
- end
-
- # insert given value into proper point of
- # provided tree. If no tree provided,
- # use implicit pass by reference aspect of @_
- # to fill one in for our caller.
- def insert(val)
- if val < @value then
- if @left then
- @left.insert(val)
- else
- @left = Binary_tree.new(val)
- end
- elsif val > @value then
- if @right then
- @right.insert(val)
- else
- @right = Binary_tree.new(val)
- end
- else
- puts "double"
- # do nothing, no double values
- end
- end
-
- # recurse on left child,
- # then show current value,
- # then recurse on right child.
- def in_order
- @left.in_order if @left
- print @value, " "
- @right.in_order if @right
- end
-
- # show current value,
- # then recurse on left child,
- # then recurse on right child.
- def pre_order
- print @value, " "
- @left.pre_order if @left
- @right.pre_order if @right
- end
-
- # recurse on left child,
- # then recurse on right child,
- # then show current value.
- def post_order
- @left.post_order if @left
- @right.post_order if @right
- print @value, " "
- end
-
- # find out whether provided value is in the tree.
- # if so, return the node at which the value was found.
- # cut down search time by only looking in the correct
- # branch, based on current value.
- def search(val)
- if val == @value then
- return self
- elsif val < @value then
- return @left.search(val) if @left
- return nil
- else
- return @right.search(val) if @right
- return nil
- end
- end
-end
-
-# first generate 20 random inserts
-test = Binary_tree.new(0)
-for a in 0..20
- test.insert(rand(1000))
-end
-
-# now dump out the tree all three ways
-print "Pre order: "; test.pre_order; puts ""
-print "In order: "; test.in_order; puts ""
-print "Post order: "; test.post_order; puts ""
-
-print "search?"
-while gets
- print test.search($_.to_i)
- print "\nsearch?"
-end
-
-
-# @@PLEAC@@_12.0
-# class and module names need to have the first letter capitalized
-module Alpha
- NAME = 'first'
-end
-module Omega
- NAME = 'last'
-end
-puts "Alpha is #{Alpha::NAME}, Omega is #{Omega::NAME}"
-
-# ruby doesn't differentiate beteen compile-time and run-time
-require 'getoptlong.rb'
-require 'getoptlong' # assumes the .rb
-require 'cards/poker.rb'
-require 'cards/poker' # assumes the .rb
-load 'cards/poker' # require only loads the file once
-
-module Cards
- module Poker
- @card_deck = Array.new # or @card_deck = []
- def shuffle
- end
- end
-end
-
-
-# @@PLEAC@@_12.1
-# a module exports all of its functions
-module Your_Module
- def self.function
- # this would be called as Your_Module.function
- end
-
- def Your_Module.another
- # this is the same as above, but more specific
- end
-end
-
-# @@PLEAC@@_12.2
-begin
- require 'nonexistent'
-rescue LoadError
- puts "Couldn't load #{$!}" # $! contains the last error string
-end
-
-# @@PLEAC@@_12.4
-# module variables are private unless access functions are defined
-module Alpha
- @aa = 10
- @bb = 11
-
- def self.put_aa
- puts @aa
- end
-
- def self.bb=(val)
- @bb = val
- end
-end
-
-Alpha.bb = 12
-# Alpha.aa = 10 # error, no aa=method
-
-
-# @@PLEAC@@_12.5
-# caller provides a backtrace of the call stack
-module MyModule
- def find_caller
- caller
- end
-
- def find_caller2(i)
- caller(i) # an argument limits the size of the stack returned
- end
-end
-
-
-# @@PLEAC@@_12.6
-BEGIN {
- $logfile = '/tmp/mylog' unless defined? $logfile
- $LF = File.open($logfile, 'a')
-}
-
-module Logger
- def self.logmsg(msg)
- $LF.puts msg
- end
-
- logmsg('startup')
-end
-
-END {
- Logger::logmsg('shutdown')
- $LF.close
-}
-
-
-# @@PLEAC@@_12.7
-#-----------------------------
-# results may be different on your system
-# % ruby -e "$LOAD_PATH.each_index { |i| printf("%d %s\n", i, $LOAD_PATH[i] }
-#0 /usr/local/lib/site_ruby/1.6
-#1 /usr/local/lib/site_ruby/1.6/i386-linux
-#2 /usr/local/lib/site_ruby/
-#3 /usr/lib/ruby/1.6
-#4 /usr/lib/ruby/1.6/i136-linux
-#5 .
-#-----------------------------
-# syntax for sh, bash, ksh, or zsh
-#$ export RUBYLIB=$HOME/rubylib
-
-# syntax for csh or tcsh
-# % setenv RUBYLIB ~/rubylib
-#-----------------------------
-$LOAD_PATH.unshift "/projects/spectre/lib";
-
-
-# @@PLEAC@@_12.8
-# equivalents in ruby are mkmf, SWIG, or Ruby/DL depending on usage
-
-
-# @@PLEAC@@_12.9
-# no equivalent in ruby
-
-
-# @@PLEAC@@_12.10
-# no equivalent in ruby
-
-
-# @@PLEAC@@_12.11
-module FineTime
- def self.time
- # to be defined later
- end
-end
-
-
-module FineTime
- def self.time
- "its a fine time"
- end
-end
-
-puts FineTime.time #=> "its a fine time"
-
-
-# @@PLEAC@@_12.12
-def even_only(n)
- raise "#{n} is not even" if (n & 1) != 0 # one way to test
- # ...
-end
-def even_only(n)
- $stderr.puts "#{n} is not even" if (n & 1) != 0
- # ...
-end
-
-
-# @@PLEAC@@_12.17
-# The library archive for ruby is called Ruby Application archive,
-# or shorter RAA, and can be found at http://raa.ruby-lang.org.
-# A typical library is installed like this:
-# % gunzip some-module-4.54.tar.gz
-# % tar xf some-module-4.54.tar
-# % cd some-module-4.54.tar
-# % ruby install.rb config
-# % ruby install.rb setup
-# get superuser previleges here if needed for next step
-# % ruby install.rb install
-
-# Some modules use a different process,
-# you should find details in the documentation
-# Here is an example of such a different process
-# % ruby extconf.rb
-# % make
-# % make install
-
-# If you want the module installed in your own directory:
-# For ruby version specific libraries
-# % ruby install.rb config --site-ruby=~/lib
-# For version independent libraries
-# % ruby install.rb config --site-ruby-common=~/lib
-
-# Information about possible options for config
-# % ruby install.rb --help
-
-# If you have your own complete distribution
-# % ruby install.rb --prefix=path=~/ruby-private
-
-
-# @@PLEAC@@_13.0
-# Classes and objects in Ruby are rather straigthforward
-class Person
- # Class variables (also called static attributes) are prefixed by @@
- @@person_counter=0
-
- # object constructor
- def initialize(age, name, alive = true) # Default arg like in C++
- @age, @name, @alive = age, name, alive # Object attributes are prefixed by '@'
- @@person_counter += 1
- # There is no '++' operator in Ruby. The '++'/'--' operators are in fact
- # hidden assignments which affect variables, not objects. You cannot accomplish
- # assignment via method. Since everything in Ruby is object, '++' and '--'
- # contradict Ruby OO ideology. Instead '-=' and '+=' are used.
- end
-
- attr_accessor :name, :age # This creates setter and getter methods for @name
- # and @age. See 13.3 for detailes.
-
- # methods modifying the receiver object usually have the '!' suffix
- def die!
- @alive = false
- puts "#{@name} has died at the age of #{@age}."
- @alive
- end
-
- def kill(anotherPerson)
- print @name, ' is killing ', anotherPerson.name, ".\n"
- anotherPerson.die!
- end
-
- # methods used as queries
- # usually have the '?' suffix
- def alive?
- @alive && true
- end
-
- def year_of_birth
- Time.now.year - @age
- end
-
- # Class method (also called static method)
- def Person.number_of_people
- @@person_counter
- end
-end
-
-# Using the class:
-# Create objects of class Person
-lecter = Person.new(47, 'Hannibal')
-starling = Person.new(29, 'Clarice', true)
-pazzi = Person.new(40, 'Rinaldo', true)
-
-# Calling a class method
-print "There are ", Person.number_of_people, " Person objects\n"
-
-print pazzi.name, ' is ', (pazzi.alive?) ? 'alive' : 'dead', ".\n"
-lecter.kill(pazzi)
-print pazzi.name, ' is ', (pazzi.alive?) ? 'alive' : 'dead', ".\n"
-
-print starling.name , ' was born in ', starling.year_of_birth, "\n"
-
-
-# @@PLEAC@@_13.1
-# If you don't need any initialisation in the constructor,
-# you don't need to write a constructor.
-class MyClass
-end
-
-class MyClass
- def initialize
- @start = Time.new
- @age = 0
- end
-end
-
-class MyClass
- def initialize(inithash)
- @start = Time.new
- @age = 0
- for key, value in inithash
- instance_variable_set("@#{key}", value)
- end
- end
-end
-
-# @@PLEAC@@_13.2
-# Objects are destroyed by the garbage collector.
-# The time of destroying is not predictable.
-# The ruby garbage collector can handle circular references,
-# so there is no need to write destructor for that.
-
-# There is no direct support for destructor.
-# You can call a custom function, or more specific a proc object, when the
-# garbage collector is about to destruct the object, but it is unpredictable
-# when this occurs.
-# Also if such a finalizer object has a reference to the orignal object,
-# this may prevent the original object to get garbage collected.
-# Because of this problem the finalize method below is
-# a class method and not a instance method.
-# So if you need to free resources for an object, like
-# closing a socket or kill a spawned subprocess,
-# you should do it explicitly.
-
-class MyClass
- def initialize
- ObjectSpace.define_finalizer(self,
- self.class.method(:finalize).to_proc)
- end
- def MyClass.finalize(id)
- puts "Object #{id} dying at #{Time.new}"
- end
-end
-
-# test code
-3.times {
- MyClass.new
-}
-ObjectSpace.garbage_collect
-
-
-# @@PLEAC@@_13.3
-# You can write getter and setter methods in a natural way:
-class Person
- def name
- @name
- end
- def name=(name)
- @name = name
- end
-end
-
-# But there is a better and shorter way
-class Person
- attr_reader :age
- attr_writer :name
- # attr_reader and attr_writer are actually methods in class Class
- # which set getter and setter methods for you.
-end
-
-# There is also attr_accessor to create both setters and getters
-class Person
- attr_accessor :age, :name
-end
-
-
-# @@PLEAC@@_13.4
-class Person
- # Class variables (also called static attributes) are prefixed by @@
- @@person_counter = 0
-
- def Person.population
- @@person_counter
- end
- def initialize
- @@person_counter += 1
- ObjectSpace.define_finalizer(self,
- self.class.method(:finalize).to_proc)
- end
- def Person.finalize(id)
- @@person_counter -= 1
- end
-end
-people = []
-10.times {
- people.push(Person.new)
-}
-printf("There are %d people alive", Person.population)
-
-
-FixedArray.class_max_bounds = 100
-alpha = FixedArray.new
-puts "Bound on alpha is #{alpha.max_bounds}"
-
-beta = FixedArray.new
-beta.max_bounds = 50 # calls the instance method
-beta.class.class_max_bounds = 50 # alternative, calls the class method
-puts "Bound on alpha is #{alpha.max_bounds}"
-
-class FixedArray
- @@bounds = 7
-
- def max_bounds
- @@max_bounds
- end
- # instance method, which sets the class variable
- def max_bounds=(value)
- @@max_bounds = value
- end
- # class method. This can only be called on a class,
- # but not on the instances
- def FixedArray.class_max_bounds=(value)
- @@max_bounds = value
- end
-end
-
-
-# @@PLEAC@@_13.5
-PersonStruct = Struct.new("Person", :name, :age, :peers)
-# creates a class "Person::Struct", which is accessiable with the
-# constant "PersonStruct"
-p = PersonStruct.new
-p = Struct::Person.new # alternative using the classname
-p.name = "Jason Smythe"
-p.age = 13
-p.peers = ["Wilbur", "Ralph", "Fred"]
-p[:peers] = ["Wilbur", "Ralph", "Fred"] # alternative access using symbol
-p["peers"] = ["Wilbur", "Ralph", "Fred"] # alternative access using name of field
-p[2] = ["Wilbur", "Ralph", "Fred"] # alternative access using index of field
-puts "At age #{p.age}, #{p.name}'s first friend is #{p.peers[0]}"
-
-# The fields of a struct have no special type, like other ruby variables
-# you can put any objects in. Therefore the discussions how to specify
-# the types of the fields do not apply to ruby.
-
-FamilyStruct = Struct.new("Family", :head, :address, :members)
-folks = FamilyStruct.new
-folks.head = PersonStruct.new
-dad = folks.head
-dad.name = "John"
-dad.age = 34
-
-# supply of own accessor method for the struct for error checking
-class PersonStruct
- def age=(value)
- if !value.kind_of?(Integer)
- raise(ArgumentError, "Age #{value} isn't an Integer")
- elsif value > 150
- raise(ArgumentError, "Age #{value} is unreasonable")
- end
- @age = value
- end
-end
-
-
-# @@PLEAC@@_13.6
-# The ruby Object class defines a dup and a clone method.
-# The dup method is recommended for prototype object creation.
-# The default implementation makes a shallow copy,
-# but each class can override it, for example to make a deep copy.
-
-# If you want to call 'new' directly on the instances,
-# you can create a instance method "new", which returns a new duplicate.
-# This method is distinct from the class method new.
-#
-class A
- def new
- dup
- end
-end
-
-ob1 = A.new
-# later on
-ob2 = ob1.new
-
-
-# @@PLEAC@@_13.7
-methname = 'flicker'
-obj.send(methname, 10) # calls obj.flicker(10)
-
-# call three methods on the object, by name
-['start', 'run', 'stop'].each do |method_string|
- obj.send(method_string)
-end
-
-# Another way is to create a Method object
-method_obj = obj.method('flicker')
-# And then call it
-method_obj.call(10)
-
-
-# @@PLEAC@@_13.8
-# All classes in Ruby inherit from class Object
-# and thus all objects share methods defined in this class
-
-# the class of the object
-puts any_object.type
-
-# Ruby classes are actually objects of class Class and they
-# respond to methods defined in Object class as well
-
-# the superclass of this class
-puts any_object.class.superclass
-
-# ask an object whether it is an instance of particular class
-n = 4.7
-puts n.instance_of?(Float) # true
-puts n.instance_of?(Numeric) # false
-
-# ask an object whether it is an instance of class, one of the
-# superclasses of the object, or modules included in it
-puts n.kind_of?(Float) # true (the class)
-puts n.kind_of?(Numeric) # true (an ancestor class)
-puts n.kind_of?(Comparable) # true (a mixin module)
-puts n.kind_of?(String) # false
-
-# ask an object whether it can respond to a particular method
-puts n.respond_to?('+') # true
-puts n.respond_to?('length') # false
-
-# all methods an object can respond to
-'just a string'.methods.each { |m| puts m }
-
-
-# @@PLEAC@@_13.9
-# Actually any class in Ruby is inheritable
-class Person
- attr_accessor :age, :name
- def initialize
- @name
- @age
- end
-end
-#-----------------------------
-dude = Person.new
-dude.name = 'Jason'
-dude.age = 23
-printf "%s is age %d.\n", dude.name, dude.age
-#-----------------------------
-# Inheriting from Person
-class Employee < Person
- attr_accessor :salary
-end
-#-----------------------------
-empl = Employee.new
-empl.name = 'Jason'
-empl.age = 23
-empl.salary = 200
-printf "%s is age %d, the salary is %d.\n", empl.name, empl.age, empl.salary
-#-----------------------------
-# Any built-in class can be inherited the same way
-class WeirdString < String
- def initialize(obj)
- super obj
- end
- def +(anotherObj) # + method in this class is overridden
- # to return the sum of string lengths
- self.length + anotherObj.length # 'self' can be omitted
- end
-end
-#-----------------------------
-a = WeirdString.new('hello')
-b = WeirdString.new('bye')
-
-puts a + b # the overridden +
-#=> 8
-puts a.length # method from the superclass, String
-#=> 5
-
-
-# @@PLEAC@@_13.11
-# In ruby you can override the method_missing method
-# to have a solution similar to perls AUTOLOAD.
-class Person
-
- def initialize
- @ok_fields = %w(name age peers parent)
- end
-
- def valid_attribute?(name)
- @ok_fields.include?(name)
- end
-
- def method_missing(namesymbol, *params)
- name = namesymbol.to_s
- return if name =~ /^A-Z/
- if name.to_s[-1] == ('='[0]) # we have a setter
- isSetter = true
- name.sub!(/=$/, '')
- end
- if valid_attribute?(name)
- if isSetter
- instance_variable_set("@#{name}", *params)
- else
- instance_variable_get("@#{name}", *params)
- end
- else
- # if no annestor is responsible,
- # the Object class will throw a NoMethodError exception
- super(namesymbol, *params)
- end
- end
-
- def new
- kid = Person.new
- kid.parent = self
- kid
- end
-
-end
-
-dad = Person.new
-dad.name = "Jason"
-dad.age = 23
-kid = dad.new
-kid.name = "Rachel"
-kid.age = 2
-puts "Kid's parent is #{kid.parent.name}"
-puts dad
-puts kid
-
-class Employee < Person
- def initialize
- super
- @ok_fields.push("salary", "boss")
- end
- def ok_fields
- @ok_fields
- end
-end
-
-
-# @@PLEAC@@_13.13
-# The ruby garbage collector pretends to cope with circular structures.
-# You can test it with this code:
-class RingNode
- attr_accessor :next
- attr_accessor :prev
- attr_reader :name
-
- def initialize(aName)
- @name = aName
- ObjectSpace.define_finalizer(self,
- self.class.method(:finalize).to_proc)
- end
-
- def RingNode.finalize(id)
- puts "Node #{id} dying"
- end
-
- def RingNode.show_all_objects
- ObjectSpace.each_object {|id|
- puts id.name if id.class == RingNode
- }
- end
-end
-
-def create_test
- a = RingNode.new("Node A")
- b = RingNode.new("Node B")
- c = RingNode.new("Node C")
- a.next = b
- b.next = c
- c.next = a
- a.prev = c
- c.prev = b
- b.prev = a
-
- a = nil
- b = nil
- c = nil
-end
-
-create_test
-RingNode.show_all_objects
-ObjectSpace.garbage_collect
-puts "After garbage collection"
-RingNode.show_all_objects
-
-
-# @@PLEAC@@_13.14
-class String
- def <=>(other)
- self.casecmp other
- end
-end
-
-# There is no way to directly overload the '""' (stringify)
-# operator in Ruby. However, by convention, classes which
-# can reasonably be converted to a String will define a
-# 'to_s' method as in the TimeNumber class defined below.
-# The 'puts' method will automatcally call an object's
-# 'to_s' method as is demonstrated below.
-# Furthermore, if a class defines a to_str method, an object of that
-# class can be used most any place where the interpreter is looking
-# for a String value.
-
-#---------------------------------------
-# NOTE: Ruby has a builtin Time class which would usually be used
-# to manipulate time objects, the following is supplied for
-# educational purposes to demonstrate operator overloading.
-#
-class TimeNumber
- attr_accessor :hours,:minutes,:seconds
- def initialize( hours, minutes, seconds)
- @hours = hours
- @minutes = minutes
- @seconds = seconds
- end
-
- def to_s
- return sprintf( "%d:%02d:%02d", @hours, @minutes, @seconds)
- end
-
- def to_str
- to_s
- end
-
- def +( other)
- seconds = @seconds + other.seconds
- minutes = @minutes + other.minutes
- hours = @hours + other.hours
- if seconds >= 60
- seconds %= 60
- minutes += 1
- end
- if minutes >= 60
- minutes %= 60
- hours += 1
- end
- return TimeNumber.new(hours, minutes, seconds)
- end
-
- def -(other)
- raise NotImplementedError
- end
-
- def *(other)
- raise NotImplementedError
- end
-
- def /( other)
- raise NotImplementedError
- end
-end
-
-t1 = TimeNumber.new(0, 58, 59)
-sec = TimeNumber.new(0, 0, 1)
-min = TimeNumber.new(0, 1, 0)
-puts t1 + sec + min + min
-
-#-----------------------------
-# StrNum class example: Ruby's builtin String class already has the
-# capabilities outlined in StrNum Perl example, however the '*' operator
-# on Ruby's String class acts differently: It creates a string which
-# is the original string repeated N times.
-#
-# Using Ruby's String class as is in this example:
-x = "Red"; y = "Black"
-z = x+y
-r = z*3 # r is "RedBlackRedBlackRedBlack"
-puts "values are #{x}, #{y}, #{z}, and #{r}"
-print "#{x} is ", x < y ? "LT" : "GE", " #{y}\n"
-# prints:
-# values are Red, Black, RedBlack, and RedBlackRedBlackRedBlack
-# Red is GE Black
-
-#-----------------------------
-class FixNum
- REGEX = /(\.\d*)/
- DEFAULT_PLACES = 0
- attr_accessor :value, :places
- def initialize(value, places = nil)
- @value = value
- if places
- @places = places
- else
- m = REGEX.match(value.to_s)
- if m
- @places = m[0].length - 1
- else
- @places = DEFAULT_PLACES
- end
- end
- end
-
- def +(other)
- FixNum.new(@value + other.value, max(@places, other.places))
- end
-
- def *(other)
- FixNum.new(@value * other.value, max(@places, other.places))
- end
-
- def /(other)
- puts "Divide: #{@value.to_f/other.value.to_f}"
- result = FixNum.new(@value.to_f/other.value.to_f)
- result.places = max(result.places,other.places)
- result
- end
-
- def to_s
- sprintf("STR%s: %.*f", self.class.to_s , @places, @value) #.
- end
-
- def to_str
- to_s
- end
-
- def to_i #convert to int
- @value.to_i
- end
-
- def to_f #convert to float`
- @value.to_f
- end
-
- private
- def max(a,b)
- a > b ? a : b
- end
-end
-
-def demo()
- x = FixNum.new(40)
- y = FixNum.new(12, 0)
-
- puts "sum of #{x} and #{y} is #{x+y}"
- puts "product of #{x} and #{y} is #{x*y}"
-
- z = x/y
- puts "#{z} has #{z.places} places"
- unless z.places
- z.places = 2
- end
-
- puts "div of #{x} by #{y} is #{z}"
- puts "square of that is #{z*z}"
-end
-
-if __FILE__ == $0
- demo()
-end
-
-
-# @@PLEAC@@_14.1
-# There are dbm, sdbm, gdbm modules
-# and the bdb module for accessing the berkeley db
-# sdbm seem to be available on the most systems,
-# so we use it here
-#
-require "sdbm"
-SDBM.open("filename", 0666) { |dbobj|
- # raises exception if open error
-
- # the returned sdbm-dbobj has most of the methods of a hash
- v = dbobj["key"]
- dbobj["key"] = "newvalue"
- if dbobj.has_key?("key")
- # ...
- end
- dbobj.delete("key2")
-}
-# database is open only inside the block.
-
-# It is also possible to use a open .. close pair:
-dbobj = SDBM.open("filename", 0666)
-#.. do something with dbobj
-dbobj.close
-
-#!/usr/bin/ruby -w
-# userstats - generate statistics on who is logged in
-# call with usernames as argument to display the totals
-# for the given usernames, call with "ALL" to display all users
-
-require "sdbm"
-filename = '/tmp/userstats.db'
-SDBM.open(filename, 0666) { |dbobj|
- if ARGV.length > 0
- if ARGV[0] == "ALL"
- # ARGV is constant, so we need the variable userlist
- userlist = dbobj.keys().sort()
- else
- userlist = ARGV
- end
- userlist.each { |user|
- print "#{user}\t#{dbobj[user]}\n"
- }
- else
- who = `who`
- who.split("\n").each { |line|
- md = /^(\S+)/.match(line)
- raise "Bad line from who: #{line}" unless md
- # sdbm stores only strings, so "+=" doesn't work,
- # we need to convert them expicitly back to integer.
- if dbobj.has_key?(md[0])
- dbobj[md[0]] = dbobj[md[0]].to_i + 1
- else
- dbobj[md[0]] = "1"
- end
- }
- end
-}
-
-
-# @@PLEAC@@_14.2
-# using open and clear
-dbobj = SDBM.open("filename", 0666)
-dbobj.clear()
-dbobj.close()
-# deleting file and recreating it
-# the filenames depend on the flavor of dbm you use,
-# for example sdbm has two files named filename.pag and filename.dir,
-# so you need to delete both files
-begin
- File.delete("filename")
- # raises Exception if not exist
- dbobj = SDBM.open("filename", 0666)
-rescue
- # add error handling here
-end
-
-
-# @@PLEAC@@_14.3
-# sdbm2gdbm: converts sdbm database to a gdbm database
-require "sdbm"
-require "gdbm"
-
-unless ARGV.length == 2
- fail "usage: sdbm2gdbm infile outfile"
-end
-infile = ARGV[0]
-outfile = ARGV[1]
-
-sdb = SDBM.open(infile)
-gdb = GDBM.open(outfile, 0666)
-sdb.each { |key, val|
- gdb[key] = val
-}
-gdb.close
-sdb.close
-
-
-# @@PLEAC@@_14.4
-#!/usr/bin/ruby -w
-# dbmmerge: merges two dbm databases
-require "sdbm"
-
-unless ARGV.length == 3
- fail "usage: dbmmerge indb1 indb2 outdb"
-end
-infile1 = ARGV[0]
-infile2 = ARGV[0]
-outfile = ARGV[2]
-
-in1 = SDBM.open(infile1, nil)
-in2 = SDBM.open(infile2, nil)
-outdb = SDBM.open(outfile, 0666)
-
-[in1, in2].each { |indb|
- indb.each { |key, val|
- if outdb.has_key?(key)
- # decide which value to set.
- # set outdb[key] if necessary
- else
- outdb[key] = val
- end
- }
-}
-in1.close
-in2.close
-outdb.close
-
-
-# @@PLEAC@@_14.7
-# we write a tie method that extends the Array class.
-# It reads the file into the memory, executes the code block
-# in which you can manipulate the array as needed, and writes
-# the array back to the file after the end of the block execution
-class Array
- def tie(filename, flags)
- File.open(filename, flags) { |f|
- f.each_line { |line|
- self.push(line.chomp)
- }
- yield
- f.rewind
- each { |line|
- if line
- f.puts(line)
- else
- f.puts ""
- end
- }
- }
- end
-end
-
-array = Array.new
-array.tie("/tmp/textfile.txt", File::RDWR|File::CREAT) {
- array[4] = "a new line 4"
-}
-
-# The tied array can be manipulated like a normal array,
-# so there is no need for a special API, and the recno_demo program
-# to demonstrate is API is useless
-
-
-# tied array demo: show how to use array with a tied file
-filename = "db_file.txt"
-lines = Array.new
-File.unlink(filename) if File.exists?(filename)
-lines.tie(filename, File::RDWR | File::CREAT) {
- # first create a textfile to play with
- lines[0] = "zero"
- lines[1] = "one"
- lines[2] = "two"
- lines[3] = "three"
- lines[4] = "four"
-
- # print the records in order.
- # Opposed to perl, the tied array behaves exactly as a normal array
- puts "\nOriginal"
- for i in 0..(lines.length-1)
- puts "#{i}: #{lines[i]}"
- end
-
- #use push and pop
- a = lines.pop
- lines.push("last")
- puts("The last line was [#{a}]")
-
- #use shift and unshift
- a = lines.shift
- lines.unshift("first")
- puts("The first line was [#{a}]")
-
- # add record after record 2
- i = 2
- lines.insert(i + 1, "Newbie")
-
- # add record before record one
- i = 1
- lines.insert(i, "New One")
-
- # delete record 3
- lines.delete_at(3)
-
- #now print the records in reverse order
- puts "\nReverse"
- (lines.length - 1).downto(0){ |i|
- puts "#{i}: #{lines[i]}"
- }
-
-}
-
-
-# @@PLEAC@@_14.8
-# example to store complex data in a database
-# uses marshall from the standard library
-require "sdbm"
-db = SDBM.open("pleac14-8-database", 0666)
-
-# convert the Objects into strings and back by using the Marshal module.
-# Most normal objects can be converted out of the box,
-# but not special things like procedure objects,
-# IO instance variables, singleton objects
-
-db["Tom Christiansen"] = Marshal.dump(["book author", "tchrist@perl.com"])
-db["Tom Boutell"] = Marshal.dump(["shareware author",
-"boutell@boutell.com"])
-
-name1 = "Tom Christiansen"
-name2 = "Tom Boutell"
-
-tom1 = Marshal.load(db[name1])
-tom2 = Marshal.load(db[name2])
-
-puts "Two Toming: #{tom1} #{tom2}"
-
-if tom1[0] == tom2[0] && tom1[1] == tom2[1]
- puts "You're having runtime fun with one Tom made two."
-else
- puts "No two Toms are ever alike"
-end
-
-# To change parts of an entry, get the whole entry, change the parts,
-# and save the whole entry back
-entry = Marshal.load(db["Tom Boutell"])
-entry[0] = "Poet Programmer"
-db["Tom Boutell"] = Marshal.dump(entry)
-db.close
-
-
-# @@PLEAC@@_14.9
-# example to make data persistent
-# uses Marshal from the standard lib
-# Stores the data in a simple file,
-# see 14.8 on how to store it in a dbm file
-
-# The BEGIN block is executed before the rest of the script
-# we use global variables here because local variables
-# will go out of scope and are not accessible from the main script
-
-BEGIN {
- $persistent_store = "persitence.dat"
- begin
- File.open($persistent_store) do |f|
- $stringvariable1 = Marshal.load(f)
- $arrayvariable2 = Marshal.load(f)
- end
- rescue
- puts "Can not open #{$persistent_store}"
- # Initialisation if this script runs the first time
- $stringvariable1 = ""
- $arrayvariable2 = []
- end
-}
-
-END {
- File.open($persistent_store, "w+") do |f|
- Marshal.dump($stringvariable1, f)
- Marshal.dump($arrayvariable2, f)
- end
-}
-
-# simple test program
-puts $stringvariable1
-puts $arrayvariable2
-$stringvariable1 = "Hello World"
-$arrayvariable2.push(5)
-puts $stringvariable1
-puts $arrayvariable2
-
-
-# @@PLEAC@@_14.10
-#!/usr/bin/ruby -w
-# Ruby has a dbi module with an architecture similar
-# to the Perl dbi module: the dbi module provides an unified
-# interface and uses specialized drivers for each dbms vendor
-#
-begin
- DBI.connect("DBI:driver:driverspecific", "username", "auth") {
- |dbh|
-
- dbh.do(SQL1)
-
- dbh.prepare(SQL2){ |sth|
- sth.execute
- sth.fetch {|row|
- # ...
- }
- } # end of block finishes the statement handle
- } # end of block closes the database connection
-rescue DBI::DatabaseError => e
- puts "dbi error occurred"
- puts "Error code: #{e.err}"
- puts "Error message: #{e.errstr}"
-end
-
-#!/usr/bin/ruby -w
-# dbusers - example for mysql which creates a table,
-# fills it with values, retrieves the values back,
-# and finally destroys the table.
-
-require "dbi"
-
-# replacement for the User::pwnt module
-def getpwent
- result = []
- File.open("/etc/passwd") {|file|
- file.each_line {|line|
- next if line.match(/^#/)
- cols = line.split(":")
- result.push([cols[2], cols[0]])
- }
- }
- result
-end
-
-begin
- DBI.connect("DBI:Mysql:pleacdatabase", "pleac", "pleacpassword") {
- |conn|
-
- conn.do("CREATE TABLE users (uid INT, login CHAR(8))")
-
- users = getpwent
-
- conn.prepare("INSERT INTO users VALUES (?,?)") {|sth|
- users.each {|entry|
- sth.execute(entry[0], entry[1])
- }
- }
-
- conn.execute("SELECT uid, login FROM users WHERE uid < 50") {|sth|
- sth.fetch {|row|
- puts row.collect {|col|
- if col.nil?
- "(null)"
- else
- col
- end
- }.join(", ")
- }
- }
-
- conn.do("DROP TABLE users")
- }
-rescue DBI::DatabaseError => e
- puts "dbi error occurred"
- puts "Error code: #{e.err}"
- puts "Error message: #{e.errstr}"
-end
-
-
-# @@PLEAC@@_15.1
-# This test program demonstrates parsing program arguments.
-# It uses the optparse library, which is included with ruby 1.8
-# It handles classic unix style and gnu style options
-require 'optparse'
-
-@debugmode = false
-@verbose = false
-
-ARGV.options do |opts|
- opts.banner = "Usage: ruby #{$0} [OPTIONS] INPUTFILES"
-
- opts.on("-h", "--help", "show this message") {
- puts opts
- exit
- }
- # The OptionParser#on method is called with a specification of short
- # options, of long options, a data type spezification and user help
- # messages for this option.
- # The method analyses the given parameter and decides what it is,
- # so you can leave out the long option if you don't need it
- opts.on("-v", "--[no-]verbose=[FLAG]", TrueClass, "run verbosly") {
- |@verbose| # sets @verbose to true or false
- }
- opts.on("-D", "--DEBUG", TrueClass, "turns on debug mode" ){
- |@debugmode| # sets @debugmode to true
- }
- opts.on("-c", "--count=NUMBER", Integer, "how many times we do it" ){
- |@count| # sets @count to given integer
- }
- opts.on("-o", "--output=FILE", String, "file to write output to"){
- |@outputfile| # sets @outputfile to given string
- }
- opts.parse!
-end
-
-# example to use the options in the main program
-puts "Verbose is on" if @verbose
-puts "Debugmode is on" if @debugmode
-puts "Outfile is #{@outputfile}" if defined? @outputfile
-puts "Count is #{@count}" if defined? @count
-ARGV.each { |param|
- puts "Got parameter #{param}"
-}
-
-
-# @@PLEAC@@_15.4
-buf = "\0" * 8
-$stdout.ioctl(0x5413, buf)
-ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("S4")
-
-raise "You must have at least 20 characters" unless ws_col >= 20
-max = 0
-values = (1..5).collect { rand(20) } # generate an array[5] of rand values
-for i in values
- max = i if max < i
-end
-ratio = Float(ws_col-12)/max # chars per unit
-for i in values
- printf "%8.1f %s\n", i, "*" * (ratio*i)
-end
-
-# gives, for example:
-# 15.0 *******************************
-# 10.0 *********************
-# 5.0 **********
-# 14.0 *****************************
-# 18.0 **************************************
-
-
-# @@PLEAC@@_16.1
-output = `program args` # collect output into one multiline string
-output = `program args`.split # collect output into array, one line per
-element
-
-readme = IO.popen("ls")
-output = ""
-while readme.gets do
- output += $_
-end
-readme.close
-
-`fsck -y /dev/rsd1a` # BAD AND SCARY in Perl because it's managed by the shell
- # I donna in Ruby ...
-
-# so the "clean and secure" version
-readme, writeme = IO.pipe
-pid = fork {
- # child
- $stdout = writeme
- readme.close
- exec('find', '..')
-}
-# parent
-Process.waitpid(pid, 0)
-writeme.close
-while readme.gets do
- # do something with $_
-end
-
-
-# @@PLEAC@@_16.2
-status = system("xemacs #{myfile}")
-
-status = system("xemacs", myfile)
-
-system("cmd1 args | cmd2 | cmd3 >outfile")
-system("cmd args <infile >outfile 2>errfile")
-
-# stop if the command fails
-raise "$program exited funny: #{$?}" unless system("cmd", "args1", "args2")
-
-# get the value of the signal sent to the child
-# even if it is a SIGINT or SIGQUIT
-system(arglist)
-raise "program killed by signal #{$?}" if ($? & 127) != 0
-
-pid = fork {
- trap("SIGINT", "IGNORE")
- exec("sleep", "10")
-}
-trap ("SIGINT") {
- puts "Tsk tsk, no process interruptus"
-}
-Process.waitpid(pid, 0)
-
-# Ruby doesn't permit to lie to the program called by a 'system'.
-# (ie specify what return argv[0] in C, $0 in Perl/Ruby ...)
-# A (dirty) way is to create a link (under Unix), run this link and
-# erase it. Somebody has a best idea ?
-
-
-# @@PLEAC@@_16.3
-exec("archive *.data")
-
-exec("archive", "accounting.data")
-
-exec("archive accounting.data")
-
-
-# @@PLEAC@@_16.4
-# read the output of a program
-IO.popen("ls") {|readme|
- while readme.gets do
- # ...
- end
-}
-# or
-readme = IO.popen("ls")
-while readme.gets do
- # ...
-end
-readme.close
-
-# "write" in a program
-IO.popen("cmd args","w") {|pipe|
- pipe.puts("data")
- pipe.puts("foo")
-}
-
-# close wait for the end of the process
-read = IO.popen("sleep 10000") # child goes to sleep
-read.close # and the parent goes to lala land
-
-writeme = IO.popen("cmd args", "w")
-writeme.puts "hello" # program will get hello\n on STDIN
-writeme.close # program will get EOF on STDIN
-
-# send in a pager (eg less) all output
-$stdout = IO.popen("/usr/bin/less","w")
-print "huge string\n" * 10000
-
-
-# @@PLEAC@@_16.5
-#-----------------------------
-def head(lines = 20)
- pid = open("|-","w")
- if pid == nil
- return
- else
- while gets() do
- pid.print
- lines -= 1
- break if lines == 0
- end
- end
- exit
-end
-
-head(100)
-while gets() do
- print
-end
-#-----------------------------
-1: > Welcome to Linux, version 2.0.33 on a i686
-
-2: >
-
-3: > "The software required `Windows 95 or better',
-
-4: > so I installed Linux."
-#-----------------------------
-> 1: Welcome to Linux, Kernel version 2.0.33 on a i686
-
-> 2:
-
-> 3: "The software required `Windows 95 or better',
-
-> 4: so I installed Linux."
-#-----------------------------
-#!/usr/bin/ruby
-# qnumcat - demo additive output filters
-
-def number()
- pid = open("|-","w")
- if pid == nil
- return
- else
- while gets() do pid.printf("%d: %s", $., $_); end
- end
- exit
-end
-
-def quote()
- pid = open("|-","w")
- if pid == nil
- return
- else
- while gets() do pid.print "> #{$_}" end
- end
- exit
-end
-
-number()
-quote()
-
-while gets() do
- print
-end
-$stdout.close
-exit
-
-
-# @@PLEAC@@_16.6
-ARGV.map! { |arg|
- arg =~ /\.(gz|Z)$/ ? "|gzip -dc #{arg}" : arg
-}
-for file in ARGV
- fh = open(file)
- while fh.gets() do
- # .......
- end
-end
-#-----------------------------
-ARGV.map! { |arg|
- arg =~ %r#^\w+://# ? "|GET #{arg}" : arg #
-}
-for file in ARGV
- fh = open(file)
- while fh.gets() do
- # .......
- end
-end
-#-----------------------------
-pwdinfo = (`domainname` =~ /^(\(none\))?$/) ? '/etc/passwd' : '|ypcat passwd';
-pwd = open(pwdinfo);
-#-----------------------------
-puts "File, please? ";
-file = gets().chomp();
-fh = open(file);
-
-
-# @@PLEAC@@_16.7
-output = `cmd 2>&1` # with backticks
-# or
-ph = open("|cmd 2>&1") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-output = `cmd 2>/dev/null` # with backticks
-# or
-ph = open("|cmd 2>/dev/null") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-output = `cmd 2>&1 1>/dev/null` # with backticks
-# or
-ph = open("|cmd 2>&1 1>/dev/null") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-output = `cmd 3>&1 1>&2 2>&3 3>&-` # with backticks
-# or
-ph = open("|cmd 3>&1 1>&2 2>&3 3>&-") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr")
-#-----------------------------
-output = `cmd 3>&1 1>&2 2>&3 3>&-`
-#-----------------------------
-fd3 = fd1
-fd1 = fd2
-fd2 = fd3
-fd3 = undef
-#-----------------------------
-system("prog args 1>tmpfile 2>&1")
-system("prog args 2>&1 1>tmpfile")
-#-----------------------------
-# system ("prog args 1>tmpfile 2>&1")
-fd1 = "tmpfile" # change stdout destination first
-fd2 = fd1 # now point stderr there, too
-#-----------------------------
-# system("prog args 2>&1 1>tmpfile")
-fd2 = fd1 # stderr same destination as stdout
-fd1 = "tmpfile" # but change stdout destination
-#-----------------------------
-# It is often better not to rely on the shell,
-# because of portability, possible security problems
-# and bigger resource usage. So, it is often better to use the open3 library.
-# See below for an example.
-# opening stdin, stdout, stderr
-require "open3"
-stdin, stdout, stderr = Open3.popen('cmd')
-
-
-# @@PLEAC@@_16.8
-#-----------------------------
-# Contrary to perl, we don't need to use a module in Ruby
-fh = Kernel.open("|" + program, "w+")
-fh.puts "here's your input\n"
-output = fh.gets()
-fh.close()
-#-----------------------------
-Kernel.open("|program"),"w+") # RIGHT !
-#-----------------------------
-# Ruby has already object methods for I/O handles
-#-----------------------------
-begin
- fh = Kernel.open("|" + program_and_options, "w+")
-rescue
- if ($@ ~= /^open/)
- $stderr.puts "open failed : #{$!} \n #{$@} \n"
- break
- end
- raise # reraise unforseen exception
-end
-
-
-# @@PLEAC@@_16.13
-#% kill -l
-#HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE
-#ALRM TERM CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM
-#PROF WINCH POLL PWR
-#-----------------------------
-#% ruby -e 'puts Signal.list.keys.join(" ")'
-#PWR USR1 BUS USR2 TERM SEGV KILL POLL STOP SYS TRAP IOT HUP INT #
-#WINCH XCPU TTIN CLD TSTP FPE IO TTOU PROF CHLD CONT PIPE ABRT
-#VTALRM QUIT ILL XFSZ URG ALRM
-#-----------------------------
-# After that, the perl script create an hash equivalent to Signal.list,
-# and an array. The array can be obtained by :
-signame = []
-Signal.list.each { |name, i| signame[i] = name }
-
-
-# @@PLEAC@@_16.14
-Process.kill(9, pid) # send $pid a signal 9
-Process.kill(-1, Process.getpgrp()) # send whole job a signal 1
-Process.kill("USR1", $$) # send myself a SIGUSR1
-Process.kill("HUP", pid1, pid2, pid3) # send a SIGHUP to processes in @pids
-#-----------------------------
-begin
- Process.kill(0, minion)
- puts "#{minion} is alive!"
-rescue Errno::EPERM # changed uid
- puts "#{minion} has escaped my control!";
-rescue Errno::ESRCH
- puts "#{minion} is deceased."; # or zombied
-rescue
- puts "Odd; I couldn't check the status of #{minion} : #{$!}"
-end
-
-
-# @@PLEAC@@_16.15
-Kernel.trap("QUIT", got_sig_quit) # got_sig_quit = Proc.new { puts "Quit\n" }
-trap("PIPE", "got_sig_quit") # def got_sig_pipe ...
-trap("INT") { ouch++ } # increment ouch for every SIGINT
-#-----------------------------
-trap("INT", "IGNORE") # ignore the signal INT
-#-----------------------------
-trap("STOP", "DEFAULT") # restore default STOP signal handling
-
-
-# @@PLEAC@@_16.16
-# the signal handler
-def ding
- trap("INT", "ding")
- puts "\aEnter your name!"
-end
-
-# prompt for name, overriding SIGINT
-def get_name
- save = trap("INT", "ding")
-
- puts "Kindly Stranger, please enter your name: "
- name = gets().chomp()
- trap("INT", save)
- name
-end
-
-
-# @@PLEAC@@_16.21
-# implemented thanks to http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/1760
-require 'timeout'
-
-# we'll do something vastly more useful than cookbook to demonstrate timeouts
-begin
- timeout(5) {
- waitsec = rand(10)
- puts "Let's see if a sleep of #{waitsec} seconds is longer than 5 seconds..."
- system("sleep #{waitsec}")
- }
- puts "Timeout didn't occur"
-rescue Timeout::Error
- puts "Timed out!"
-end
-
-
-# @@PLEAC@@_17.1
-# A basic TCP client connection
-require 'socket'
-begin
- t = TCPSocket.new('www.ruby-lang.org', 'www')
-rescue
- puts "error: #{$!}"
-else
- # ... do something with the socket
- t.print "GET / HTTP/1.0\n\n"
- answer = t.gets(nil)
- # and terminate the connection when we're done
- t.close
-end
-
-# Using the evil low level socket API
-require 'socket'
-# create a socket
-s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
-# build the address of the remote machine
-sockaddr_server = [Socket::AF_INET, 80,
- Socket.gethostbyname('www.ruby-lang.org')[3],
- 0, 0].pack("snA4NN")
-# connect
-begin
- s.connect(sockaddr_server)
-rescue
- puts "error: #{$!}"
-else
- # ... do something with the socket
- s.print "GET / HTTP/1.0\n\n"
- # and terminate the connection when we're done
- s.close
-end
-
-# TCP connection with management of error (DNS)
-require 'socket'
-begin
- client = TCPSocket.new('does not exists', 'www')
-rescue
- puts "error: #{$!}"
-end
-
-# TCP connection with a time out
-require 'socket'
-require 'timeout'
-begin
- timeout(1) do #the server has one second to answer
- client = TCPSocket.new('www.host.com', 'www')
- end
-rescue
- puts "error: #{$!}"
-end
-
-
-# @@PLEAC@@_17.12
-require 'socket'
-
-class Preforker
- attr_reader (:child_count)
-
- def initialize(prefork, max_clients_per_child, port, client_handler)
- @prefork = prefork
- @max_clients_per_child = max_clients_per_child
- @port = port
- @child_count = 0
-
- @reaper = proc {
- trap('CHLD', @reaper)
- pid = Process.wait
- @child_count -= 1
- }
-
- @huntsman = proc {
- trap('CHLD', 'IGNORE')
- trap('INT', 'IGNORE')
- Process.kill('INT', 0)
- exit
- }
-
- @client_handler=client_handler
- end
-
- def child_handler
- trap('INT', 'EXIT')
- @client_handler.setUp
- # wish: sigprocmask UNblock SIGINT
- @max_clients_per_child.times {
- client = @server.accept or break
- @client_handler.handle_request(client)
- client.close
- }
- @client_handler.tearDown
- end
-
- def make_new_child
- # wish: sigprocmask block SIGINT
- @child_count += 1
- pid = fork do
- child_handler
- end
- # wish: sigprocmask UNblock SIGINT
- end
-
- def run
- @server = TCPserver.open(@port)
- trap('CHLD', @reaper)
- trap('INT', @huntsman)
- loop {
- (@prefork - @child_count).times { |i|
- make_new_child
- }
- sleep .1
- }
- end
-end
-
-#-----------------------------
-#!/usr/bin/ruby
-
-require 'Preforker'
-
-class ClientHandler
- def setUp
- end
-
- def tearDown
- end
-
- def handle_request(client)
- # do stuff
- end
-end
-
-server = Preforker.new(1, 100, 3102, ClientHandler.new)
-server.run
-
-
-# @@PLEAC@@_18.2
-require 'net/ftp'
-
-begin
- ftp = Net::FTP::new("ftp.host.com")
- ftp.login(username,password)
- ftp.chdir(directory)
- ftp.get(filename)
- ftp.put(filename)
-rescue Net::FTPError
- $stderr.print "FTP failed: " + $!
-ensure
- ftp.close() if ftp
-end
-
-# A better solution for a local use could be :
-Net::FTP::new("ftp.host.com") do |ftp|
- ftp.login(username,password)
- ftp.chdir(directory)
- ftp.get(filename)
- ftp.put(filename)
-end
-
-# If you have only one file to get, there is a simple solution :
-require 'open-uri'
-open("ftp://www.ruby-lang.org/path/filename") do |fh|
- # read from filehandle fh
-end
-#--------------------------------------------
-# to wait a defined time for the connection,
-# use the timeout module
-require 'timeout'
-begin
- timeout(30){
- ftp = Net::FTP::new("ftp.host.com")
- ftp.debug_mode = true
- }
-rescue Net::FTPError
- $stderr.puts "Couldn't connect."
-rescue Timeout::Error
- $stderr.puts "Timeout while connecting to server."
-end
-
-begin
- ftp.login()
-rescue Net::FTPError
- $stderr.print "Couldn't authentificate.\n"
-end
-
-begin
- ftp.login(username)
-rescue Net::FTPError
- $stderr.print "Still couldn't authenticate.\n"
-end
-
-begin
- ftp.login(username, password)
-rescue Net::FTPError
- $stderr.print "Couldn't authenticate, even with explicit
- username and password.\n"
-end
-
-begin
- ftp.login(username, password, account)
-rescue Net::FTPError
- $stderr.print "No dice. It hates me.\n"
-end
-#-----------------------------
-ftp.put(localfile, remotefile)
-#-----------------------------
-# Sending data from STDIN is not directly supported
-# by the ftp library module. A possible way to do it is to use the
-# storlines method directly to send raw commands to the ftp server.
-#-----------------------------
-ftp.get(remotefile, localfile)
-#-----------------------------
-ftp.get(remotefile) { |data| puts data }
-#-----------------------------
-ftp.chdir("/pub/ruby")
-print "I'm in the directory ", ftp.pwd(), "\n"
-#-----------------------------
-ftp.mkdir("/pub/ruby/new_dir")
-#-----------------------------
-lines = ftp.ls("/pub/ruby/")
-# => ["drwxr-xr-x 2 matz users 4096 July 17 1998 1.0", ... ]
-
-latest = ftp.dir("/pub/ruby/*.tgz").sort.last
-
-ftp.nlst("/pub/ruby")
-# => ["/pub/ruby/1.0", ... ]
-#-----------------------------
-ftp.quit()
-
-
-# @@PLEAC@@_18.6
-require 'net/telnet'
-t = Net::Telnet::new( "Timeout" => 10,
- "Prompt" => /%/,
- "Host" => host )
-t.login(username, password)
-files = t.cmd("ls")
-t.print("top")
-process_string = t.waitfor(/\d+ processes/)
-t.close
-#-----------------------------
-/[$%#>] \z/n
-#-----------------------------
-# In case of an error, the telnet module throws an exception.
-# For control of the behavior in case of an error,
-# you just need to catch the exceptions and do your custom
-# error handling.
-#-----------------------------
-begin
- telnet.login(username, password)
-rescue TimeoutError
- fail "Login failed !\n"
-end
-#-----------------------------
-telnet.waitfor('/--more--/')
-#-----------------------------
-telnet.waitfor(String => 'greasy smoke', Timeout => 30)
-
-
-# @@PLEAC@@_18.7
-require 'ping'
-
-puts "#{host} is alive.\n" if Ping.pingecho(host);
-#-----------------------------
-# the ping module only use TCP ping, not ICMP even if we are root
-if Ping.pingecho("kingkong.com")
- puts "The giant ape lives!\n";
-else
- puts "All hail mighty Gamera, friend of children!\n";
-end
-
-
-# @@PLEAC@@_19.1
-#!/usr/local/bin/ruby -w
-# hiweb - load CGI class to decode information given by web server
-
-require 'cgi'
-
-cgi = CGI.new('html3')
-
-# get a parameter from a form
-value = cgi.params['PARAM_NAME'][0]
-
-# output a document
-cgi.out {
- cgi.html {
- cgi.head { cgi.title { "Howdy there!" } } +
- cgi.body { cgi.p { "You typed: " + cgi.tt {
- CGI.escapeHTML(value) } } }
- }
-}
-
-require 'cgi'
-cgi = CGI.new
-who = cgi.param["Name"][0] # first param in list
-phone = cgi.param["Number"][0]
-picks = cgi.param["Choices"] # complete list
-
-print cgi.header( 'type' => 'text/plain',
- 'expires' => Time.now + (3 * 24 * 60 * 60) )
-
-
-# @@PLEAC@@_19.3
-#!/usr/local/bin/ruby -w
-# webwhoami - show web user's id
-require 'etc'
-print "Content-Type: text/plain\n\n"
-print "Running as " + Etc.getpwuid.name + "\n"
-
-# % ruby -wc cgi-script # just check syntax
-
-# % ruby -w cgi-script # params from stdin
-# (offline mode: enter name=value pairs on standard input)
-# name=joe
-# number=10
-# ^D
-
-# % ruby -w cgi-script name=joe number=10 # run with mock form input
-# % ruby -d cgi-script name=joe number=10 # ditto, under the debugger
-
-# POST method script in csh
-# % (setenv HTTP_METHOD POST; ruby -w cgi-script name=joe number=10)
-# POST method script in sh
-# % HTTP_METHOD=POST perl -w cgi-script name=joe number=10
-
-
-# @@PLEAC@@_19.4
-# ruby has several security levels, the level "1" is similar to perls taint mode.
-# It can be switched on by providing the -T command line parameter
-# or by setting $SAFE to 1. Setting $SAFE to 2,3 or 4 restricts possible
-# harmful operations further.
-
-#!/usr/bin/ruby -T
-$SAFE = 1
-File.open(ARGV[0], "w")
-# ruby warns with:
-# taint1.rb:2:in `initialize': Insecure operation - initialize (SecurityError)
-
-$SAFE = 1
-file = ARGV[0]
-unless /^([\w.-]+)$/.match(file)
- raise "filename #{file} has invalid characters"
-end
-file = $1
-# In ruby, even the back reference from a regular expression stays tainted.
-# you need to explicitly untaint the variable:
-file.untaint
-File.open(file, "w")
-
-# Race condition exists like in perl:
-unless File.exists(filename) # Wrong because of race condition
- File.open(filename, "w")
-end
-
-
-
-# @@PLEAC@@_19.10
-preference_value = cgi.cookies["preference name"][0]
-
-packed_cookie = CGI::Cookie.new("name" => "preference name",
- "value" => "whatever you'd like",
- "expires" => Time.local(Time.now.year + 2,
- Time.now.mon, Time.now.day, Time.now.hour, Time.now.min, Time.now.sec) )
-
-cgi.header("cookie" => [packed_cookie])
-
-#!/usr/local/bin/ruby -w
-# ic_cookies - sample CGI script that uses a cookie
-require 'cgi'
-
-cgi = CGI.new('html3')
-
-cookname = "favorite ice cream"
-favorite = cgi.params["flavor"][0]
-tasty = cgi.cookies[cookname][0] || 'mint'
-
-unless favorite
- cgi.out {
- cgi.html {
- cgi.head { cgi.title { "Ice Cookies" } } +
- cgi.body {
- cgi.h1 { "Hello Ice Cream" } +
- cgi.hr +
- cgi.form {
- cgi.p { "Please select a flavor: " +
- cgi.text_field("flavor", tasty ) }
- } +
- cgi.hr
- }
- }
- }
-else
- cookie = CGI::Cookie.new( "name" => cookname,
- "value" => favorite,
- "expires" => Time.local(Time.now.year + 2,
-Time.now.mon, Time.now.day, Time.now.hour, Time.now.min, Time.now.sec) )
- cgi.out("cookie" => [cookie]) {
- cgi.html {
- cgi.head { cgi.title { "Ice Cookies" } } +
- cgi.body {
- cgi.h1 { "Hello Ice Cream" } +
- cgi.p { "You chose as your favorite flavor `#{favorite}'." }
- }
- }
- }
-end
-
-
-# @@PLEAC@@_20.9
-def templatefile(filename, fillings)
- aFile = File.new(filename, "r")
- text = aFile.read()
- aFile.close()
- pattern = Regexp.new('%%(.*?)%%')
- text.gsub!(pattern) {
- fillings[$1] || ""
- }
- text
-end
-
-fields = {
- 'username' => whats_his_name,
- 'count' => login_count,
- 'total' => minutes_used
-}
-puts templatefile('simple.template', fields)
-
-# @@INCOMPLETE@@
-# An example using databases is missing
-
diff --git a/tests/examplefiles/pleac.in.rb b/tests/examplefiles/pleac.in.rb
index 0f967b9b..d74944ad 100644
--- a/tests/examplefiles/pleac.in.rb
+++ b/tests/examplefiles/pleac.in.rb
@@ -2957,3412 +2957,3 @@ end
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
-
-
-# @@PLEAC@@_10.2
-def somefunc
- variable = something # variable is local by default
-end
-
-name, age = ARGV
-start = fetch_time
-
-a, b = pair # will succeed if pair is an Array object (like ARGV is)
-c = fetch_time
-
-# In ruby, run_check can't access a, b, or c until they are
-# explicitely defined global (using leading $), even if they are
-# both defined in the same scope
-
-def check_x(x)
- y = "whatever"
- run_check
- if $condition
- puts "got $x"
- end
-end
-
-# The following will keep a reference to the array, though the
-# results will be slightly different from perl: the last element
-# of $global_array will be itself an array
-def save_array(ary)
- $global_array << ary
-end
-
-# The following gives the same results as in Perl for $global_array,
-# though it doesn't illustrate anymore the way to keep a reference
-# to an object: $global_array is extended with the elements of ary
-def save_array(ary)
- $global_array += ary
-end
-
-
-# @@PLEAC@@_10.3
-# In Ruby, AFAIK a method cannot access "local variables" defined
-# upper scope; mostly because everything is an object, so you'll
-# do the same by defining an attribute or a static attribute
-
-# In Ruby the BEGIN also exists:
-BEGIN { puts "hello from BEGIN" }
-puts "hello from main"
-BEGIN { puts "hello from 2nd BEGIN" }
-# gives:
-# hello from BEGIN
-# hello from 2nd BEGIN
-# hello from main
-
-# In Ruby, it can be written as a static method and a static
-# variable
-class Counter
- @@counter = 0
- def Counter.next_counter; @@counter += 1; end
-end
-
-# There is no need of BEGIN since the variable will get
-# initialized when parsing
-class Counter
- @@counter = 42
- def Counter.next_counter; @@counter += 1; end
- def Counter.prev_counter; @@counter -= 1; end
-end
-
-
-# @@PLEAC@@_10.4
-# You can either get the whole trace as an array of strings, each
-# string telling which file, line and method is calling:
-caller
-
-# ...or only the last caller
-caller[0]
-
-# We need to extract just the method name of the backtrace:
-def whoami; caller()[0] =~ /in `([^']+)'/ ? $1 : '(anonymous)'; end
-def whowasi; caller()[1] =~ /in `([^']+)'/ ? $1 : '(anonymous)'; end
-
-
-# @@PLEAC@@_10.5
-# In Ruby, every value is a reference on an object, thus there is
-# no such problem
-array_diff(array1, array2)
-
-def add_vecpair(a1, a2)
- results = []
- a1.each_index { |i| results << (a1[i] + a2[i]) }
- results
-end
-a = [1, 2]
-b = [5, 8]
-c = add_vecpair(a, b)
-p c
-
-# Add this to the beginning of the function to check if we were
-# given two arrays
-a1.type == Array && a2.type == Array or
- raise "usage: add_vecpair array1 array2 (was used with: #{a1.type} #{a2.type})"
-
-
-# @@PLEAC@@_10.6
-# There is no return context in Ruby
-
-
-# @@PLEAC@@_10.7
-# Like in Perl, we need to fake with a hash, but it's dirty :-(
-def thefunc(param_args)
- args = { 'INCREMENT' => '10s', 'FINISH' => '0', 'START' => 0 }
- args.update(param_args)
- if (args['INCREMENT'] =~ /m$/ )
- # .....
- end
-end
-
-thefunc({ 'INCREMENT' => '20s', 'START' => '+5m', 'FINISH' => '+30m' })
-thefunc({})
-
-
-# @@PLEAC@@_10.8
-# there is no "undef" direct equivalent but there is the slice equiv:
-a, c = func.indexes(0, 2)
-
-
-# @@PLEAC@@_10.9
-# Ruby has no such limitation:
-def somefunc
- ary = []
- hash = {}
- # ...
- return ary, hash
-end
-arr, dict = somefunc
-
-array_of_hashes = fn
-h1, h2, h3 = fn
-
-
-# @@PLEAC@@_10.10
-return
-# or (equivalent)
-return nil
-
-
-# @@PLEAC@@_10.11
-# You can't prototype in Ruby regarding types :-(
-# Though, you can force the number of arguments:
-def func_with_no_arg; end
-def func_with_no_arg(); end
-def func_with_one_arg(a1); end
-def func_with_two_args(a1, a2); end
-def func_with_any_number_of_args(*args); end
-
-
-# @@PLEAC@@_10.12
-raise "some message" # raise exception
-
-begin
- val = func
-rescue Exception => msg
- $stderr.puts "func raised an exception: #{msg}"
-end
-
-# In Ruby the rescue statement uses an exception class, every
-# exception which is not matched is still continuing
-begin
- val = func
-rescue FullMoonError
- ...
-end
-
-
-# @@PLEAC@@_10.13
-# Saving Global Values
-# Of course we can just save the value and restore it later:
-def print_age
- puts "Age is #{$age}"
-end
-
-$age = 18 # global variable
-print_age()
-if condition
- safeage = $age
- $age = 23
- print_age()
- $age = safeage
-end
-
-# We can also use a method that saves the global variable and
-# restores it automatically when the block is left:
-
-def local(var)
- eval("save = #{var.id2name}")
- begin
- result = yield
- ensure
- # we want to call this even if we got an exception
- eval("#{var.id2name} = save")
- end
- result
-end
-
-condition = true
-$age = 18
-print_age()
-if condition
- local(:$age) {
- $age = 23
- print_age()
- }
-end
-print_age()
-
-# There is no need to use local() for filehandles or directory
-# handles in ruby because filehandles are normal objects.
-
-
-# @@PLEAC@@_10.14
-# In Ruby you may redefine a method [but not overload it :-(]
-# just by defining again with the same name.
-def foo; puts 'foo'; end
-def foo; puts 'bar'; end
-foo
-#=> bar
-
-# You can also take a reference to an existing method before
-# redefining a new one, using the `alias' keyword
-def foo; puts 'foo'; end
-alias foo_orig foo
-def foo; puts 'bar'; end
-foo_orig
-foo
-#=> foo
-#=> bar
-
-# AFAIK, there is no direct way to create a new method whose name
-# comes from a variable, so use "eval"
-colors = %w(red blue green yellow orange purple violet)
-colors.each { |c|
- eval <<-EOS
- def #{c}(*a)
- "<FONT COLOR='#{c}'>" + a.to_s + "</FONT>"
- end
- EOS
-}
-
-
-# @@PLEAC@@_10.15
-def method_missing(name, *args)
- "<FONT COLOR='#{name}'>" + args.join(' ') + "</FONT>"
-end
-puts chartreuse("stuff")
-
-
-# @@PLEAC@@_10.16
-def outer(arg)
- x = arg + 35
- inner = proc { x * 19 }
- x + inner.call()
-end
-
-
-# @@PLEAC@@_10.17
-#!/usr/bin/ruby -w
-# mailsort - sort mbox by different criteria
-require 'English'
-require 'Date'
-
-# Objects of class Mail represent a single mail.
-class Mail
- attr_accessor :no
- attr_accessor :subject
- attr_accessor :fulltext
- attr_accessor :date
-
- def initialize
- @fulltext = ""
- @subject = ""
- end
-
- def append(para)
- @fulltext << para
- end
-
- # this is called if you call puts(mail)
- def to_s
- @fulltext
- end
-end
-
-# represents a list of mails.
-class Mailbox < Array
-
- Subjectpattern = Regexp.new('Subject:\s*(?:Re:\s*)*(.*)\n')
- Datepattern = Regexp.new('Date:\s*(.*)\n')
-
- # reads mails from open file and stores them
- def read(file)
- $INPUT_RECORD_SEPARATOR = '' # paragraph reads
- msgno = -1
- file.each { |para|
- if para =~ /^From/
- mail = Mail.new
- mail.no = (msgno += 1)
- md = Subjectpattern.match(para)
- if md
- mail.subject = md[1]
- end
- md = Datepattern.match(para)
- if md
- mail.date = DateTime.parse(md[1])
- else
- mail.date = DateTime.now
- end
- self.push(mail)
- end
- mail.append(para) if mail
- }
- end
-
- def sort_by_subject_and_no
- self.sort_by { |m|
- [m.subject, m.no]
- }
- end
-
- # sorts by a list of attributs of mail, given as symbols
- def sort_by_attributs(*attrs)
- # you can sort an Enumerable by an array of
- # values, they would be compared
- # from ary[0] to ary[n]t, say:
- # ['b',1] > ['a',10] > ['a',9]
- self.sort_by { |elem|
- attrs.map { |attr|
- elem.send(attr)
- }
- }
- end
-
-end
-
-mailbox = Mailbox.new
-mailbox.read(ARGF)
-
-# print only subjects sorted by subject and number
-for m in mailbox.sort_by_subject_and_no
- puts(m.subject)
-end
-
-# print complete mails sorted by date, then subject, then number
-for m in mailbox.sort_by_attributs(:date, :subject)
- puts(m)
-end
-
-
-# @@PLEAC@@_11.7
-def mkcounter(count)
- start = count
- bundle = {
- "NEXT" => proc { count += 1 },
- "PREV" => proc { count -= 1 },
- "RESET" => proc { count = start }
- }
- bundle["LAST"] = bundle["PREV"]
- return bundle
-end
-
-c1 = mkcounter(20)
-c2 = mkcounter(77)
-
-puts "next c1: #{c1["NEXT"].call}" # 21
-puts "next c2: #{c2["NEXT"].call}" # 78
-puts "next c1: #{c1["NEXT"].call}" # 22
-puts "last c1: #{c1["PREV"].call}" # 21
-puts "last c1: #{c1["LAST"].call}" # 20
-puts "old c2: #{c2["RESET"].call}" # 77
-
-
-# @@PLEAC@@_11.15
-class Binary_tree
- def initialize(val)
- @value = val
- @left = nil
- @right = nil
- end
-
- # insert given value into proper point of
- # provided tree. If no tree provided,
- # use implicit pass by reference aspect of @_
- # to fill one in for our caller.
- def insert(val)
- if val < @value then
- if @left then
- @left.insert(val)
- else
- @left = Binary_tree.new(val)
- end
- elsif val > @value then
- if @right then
- @right.insert(val)
- else
- @right = Binary_tree.new(val)
- end
- else
- puts "double"
- # do nothing, no double values
- end
- end
-
- # recurse on left child,
- # then show current value,
- # then recurse on right child.
- def in_order
- @left.in_order if @left
- print @value, " "
- @right.in_order if @right
- end
-
- # show current value,
- # then recurse on left child,
- # then recurse on right child.
- def pre_order
- print @value, " "
- @left.pre_order if @left
- @right.pre_order if @right
- end
-
- # recurse on left child,
- # then recurse on right child,
- # then show current value.
- def post_order
- @left.post_order if @left
- @right.post_order if @right
- print @value, " "
- end
-
- # find out whether provided value is in the tree.
- # if so, return the node at which the value was found.
- # cut down search time by only looking in the correct
- # branch, based on current value.
- def search(val)
- if val == @value then
- return self
- elsif val < @value then
- return @left.search(val) if @left
- return nil
- else
- return @right.search(val) if @right
- return nil
- end
- end
-end
-
-# first generate 20 random inserts
-test = Binary_tree.new(0)
-for a in 0..20
- test.insert(rand(1000))
-end
-
-# now dump out the tree all three ways
-print "Pre order: "; test.pre_order; puts ""
-print "In order: "; test.in_order; puts ""
-print "Post order: "; test.post_order; puts ""
-
-print "search?"
-while gets
- print test.search($_.to_i)
- print "\nsearch?"
-end
-
-
-# @@PLEAC@@_12.0
-# class and module names need to have the first letter capitalized
-module Alpha
- NAME = 'first'
-end
-module Omega
- NAME = 'last'
-end
-puts "Alpha is #{Alpha::NAME}, Omega is #{Omega::NAME}"
-
-# ruby doesn't differentiate beteen compile-time and run-time
-require 'getoptlong.rb'
-require 'getoptlong' # assumes the .rb
-require 'cards/poker.rb'
-require 'cards/poker' # assumes the .rb
-load 'cards/poker' # require only loads the file once
-
-module Cards
- module Poker
- @card_deck = Array.new # or @card_deck = []
- def shuffle
- end
- end
-end
-
-
-# @@PLEAC@@_12.1
-# a module exports all of its functions
-module Your_Module
- def self.function
- # this would be called as Your_Module.function
- end
-
- def Your_Module.another
- # this is the same as above, but more specific
- end
-end
-
-# @@PLEAC@@_12.2
-begin
- require 'nonexistent'
-rescue LoadError
- puts "Couldn't load #{$!}" # $! contains the last error string
-end
-
-# @@PLEAC@@_12.4
-# module variables are private unless access functions are defined
-module Alpha
- @aa = 10
- @bb = 11
-
- def self.put_aa
- puts @aa
- end
-
- def self.bb=(val)
- @bb = val
- end
-end
-
-Alpha.bb = 12
-# Alpha.aa = 10 # error, no aa=method
-
-
-# @@PLEAC@@_12.5
-# caller provides a backtrace of the call stack
-module MyModule
- def find_caller
- caller
- end
-
- def find_caller2(i)
- caller(i) # an argument limits the size of the stack returned
- end
-end
-
-
-# @@PLEAC@@_12.6
-BEGIN {
- $logfile = '/tmp/mylog' unless defined? $logfile
- $LF = File.open($logfile, 'a')
-}
-
-module Logger
- def self.logmsg(msg)
- $LF.puts msg
- end
-
- logmsg('startup')
-end
-
-END {
- Logger::logmsg('shutdown')
- $LF.close
-}
-
-
-# @@PLEAC@@_12.7
-#-----------------------------
-# results may be different on your system
-# % ruby -e "$LOAD_PATH.each_index { |i| printf("%d %s\n", i, $LOAD_PATH[i] }
-#0 /usr/local/lib/site_ruby/1.6
-#1 /usr/local/lib/site_ruby/1.6/i386-linux
-#2 /usr/local/lib/site_ruby/
-#3 /usr/lib/ruby/1.6
-#4 /usr/lib/ruby/1.6/i136-linux
-#5 .
-#-----------------------------
-# syntax for sh, bash, ksh, or zsh
-#$ export RUBYLIB=$HOME/rubylib
-
-# syntax for csh or tcsh
-# % setenv RUBYLIB ~/rubylib
-#-----------------------------
-$LOAD_PATH.unshift "/projects/spectre/lib";
-
-
-# @@PLEAC@@_12.8
-# equivalents in ruby are mkmf, SWIG, or Ruby/DL depending on usage
-
-
-# @@PLEAC@@_12.9
-# no equivalent in ruby
-
-
-# @@PLEAC@@_12.10
-# no equivalent in ruby
-
-
-# @@PLEAC@@_12.11
-module FineTime
- def self.time
- # to be defined later
- end
-end
-
-
-module FineTime
- def self.time
- "its a fine time"
- end
-end
-
-puts FineTime.time #=> "its a fine time"
-
-
-# @@PLEAC@@_12.12
-def even_only(n)
- raise "#{n} is not even" if (n & 1) != 0 # one way to test
- # ...
-end
-def even_only(n)
- $stderr.puts "#{n} is not even" if (n & 1) != 0
- # ...
-end
-
-
-# @@PLEAC@@_12.17
-# The library archive for ruby is called Ruby Application archive,
-# or shorter RAA, and can be found at http://raa.ruby-lang.org.
-# A typical library is installed like this:
-# % gunzip some-module-4.54.tar.gz
-# % tar xf some-module-4.54.tar
-# % cd some-module-4.54.tar
-# % ruby install.rb config
-# % ruby install.rb setup
-# get superuser previleges here if needed for next step
-# % ruby install.rb install
-
-# Some modules use a different process,
-# you should find details in the documentation
-# Here is an example of such a different process
-# % ruby extconf.rb
-# % make
-# % make install
-
-# If you want the module installed in your own directory:
-# For ruby version specific libraries
-# % ruby install.rb config --site-ruby=~/lib
-# For version independent libraries
-# % ruby install.rb config --site-ruby-common=~/lib
-
-# Information about possible options for config
-# % ruby install.rb --help
-
-# If you have your own complete distribution
-# % ruby install.rb --prefix=path=~/ruby-private
-
-
-# @@PLEAC@@_13.0
-# Classes and objects in Ruby are rather straigthforward
-class Person
- # Class variables (also called static attributes) are prefixed by @@
- @@person_counter=0
-
- # object constructor
- def initialize(age, name, alive = true) # Default arg like in C++
- @age, @name, @alive = age, name, alive # Object attributes are prefixed by '@'
- @@person_counter += 1
- # There is no '++' operator in Ruby. The '++'/'--' operators are in fact
- # hidden assignments which affect variables, not objects. You cannot accomplish
- # assignment via method. Since everything in Ruby is object, '++' and '--'
- # contradict Ruby OO ideology. Instead '-=' and '+=' are used.
- end
-
- attr_accessor :name, :age # This creates setter and getter methods for @name
- # and @age. See 13.3 for detailes.
-
- # methods modifying the receiver object usually have the '!' suffix
- def die!
- @alive = false
- puts "#{@name} has died at the age of #{@age}."
- @alive
- end
-
- def kill(anotherPerson)
- print @name, ' is killing ', anotherPerson.name, ".\n"
- anotherPerson.die!
- end
-
- # methods used as queries
- # usually have the '?' suffix
- def alive?
- @alive && true
- end
-
- def year_of_birth
- Time.now.year - @age
- end
-
- # Class method (also called static method)
- def Person.number_of_people
- @@person_counter
- end
-end
-
-# Using the class:
-# Create objects of class Person
-lecter = Person.new(47, 'Hannibal')
-starling = Person.new(29, 'Clarice', true)
-pazzi = Person.new(40, 'Rinaldo', true)
-
-# Calling a class method
-print "There are ", Person.number_of_people, " Person objects\n"
-
-print pazzi.name, ' is ', (pazzi.alive?) ? 'alive' : 'dead', ".\n"
-lecter.kill(pazzi)
-print pazzi.name, ' is ', (pazzi.alive?) ? 'alive' : 'dead', ".\n"
-
-print starling.name , ' was born in ', starling.year_of_birth, "\n"
-
-
-# @@PLEAC@@_13.1
-# If you don't need any initialisation in the constructor,
-# you don't need to write a constructor.
-class MyClass
-end
-
-class MyClass
- def initialize
- @start = Time.new
- @age = 0
- end
-end
-
-class MyClass
- def initialize(inithash)
- @start = Time.new
- @age = 0
- for key, value in inithash
- instance_variable_set("@#{key}", value)
- end
- end
-end
-
-# @@PLEAC@@_13.2
-# Objects are destroyed by the garbage collector.
-# The time of destroying is not predictable.
-# The ruby garbage collector can handle circular references,
-# so there is no need to write destructor for that.
-
-# There is no direct support for destructor.
-# You can call a custom function, or more specific a proc object, when the
-# garbage collector is about to destruct the object, but it is unpredictable
-# when this occurs.
-# Also if such a finalizer object has a reference to the orignal object,
-# this may prevent the original object to get garbage collected.
-# Because of this problem the finalize method below is
-# a class method and not a instance method.
-# So if you need to free resources for an object, like
-# closing a socket or kill a spawned subprocess,
-# you should do it explicitly.
-
-class MyClass
- def initialize
- ObjectSpace.define_finalizer(self,
- self.class.method(:finalize).to_proc)
- end
- def MyClass.finalize(id)
- puts "Object #{id} dying at #{Time.new}"
- end
-end
-
-# test code
-3.times {
- MyClass.new
-}
-ObjectSpace.garbage_collect
-
-
-# @@PLEAC@@_13.3
-# You can write getter and setter methods in a natural way:
-class Person
- def name
- @name
- end
- def name=(name)
- @name = name
- end
-end
-
-# But there is a better and shorter way
-class Person
- attr_reader :age
- attr_writer :name
- # attr_reader and attr_writer are actually methods in class Class
- # which set getter and setter methods for you.
-end
-
-# There is also attr_accessor to create both setters and getters
-class Person
- attr_accessor :age, :name
-end
-
-
-# @@PLEAC@@_13.4
-class Person
- # Class variables (also called static attributes) are prefixed by @@
- @@person_counter = 0
-
- def Person.population
- @@person_counter
- end
- def initialize
- @@person_counter += 1
- ObjectSpace.define_finalizer(self,
- self.class.method(:finalize).to_proc)
- end
- def Person.finalize(id)
- @@person_counter -= 1
- end
-end
-people = []
-10.times {
- people.push(Person.new)
-}
-printf("There are %d people alive", Person.population)
-
-
-FixedArray.class_max_bounds = 100
-alpha = FixedArray.new
-puts "Bound on alpha is #{alpha.max_bounds}"
-
-beta = FixedArray.new
-beta.max_bounds = 50 # calls the instance method
-beta.class.class_max_bounds = 50 # alternative, calls the class method
-puts "Bound on alpha is #{alpha.max_bounds}"
-
-class FixedArray
- @@bounds = 7
-
- def max_bounds
- @@max_bounds
- end
- # instance method, which sets the class variable
- def max_bounds=(value)
- @@max_bounds = value
- end
- # class method. This can only be called on a class,
- # but not on the instances
- def FixedArray.class_max_bounds=(value)
- @@max_bounds = value
- end
-end
-
-
-# @@PLEAC@@_13.5
-PersonStruct = Struct.new("Person", :name, :age, :peers)
-# creates a class "Person::Struct", which is accessiable with the
-# constant "PersonStruct"
-p = PersonStruct.new
-p = Struct::Person.new # alternative using the classname
-p.name = "Jason Smythe"
-p.age = 13
-p.peers = ["Wilbur", "Ralph", "Fred"]
-p[:peers] = ["Wilbur", "Ralph", "Fred"] # alternative access using symbol
-p["peers"] = ["Wilbur", "Ralph", "Fred"] # alternative access using name of field
-p[2] = ["Wilbur", "Ralph", "Fred"] # alternative access using index of field
-puts "At age #{p.age}, #{p.name}'s first friend is #{p.peers[0]}"
-
-# The fields of a struct have no special type, like other ruby variables
-# you can put any objects in. Therefore the discussions how to specify
-# the types of the fields do not apply to ruby.
-
-FamilyStruct = Struct.new("Family", :head, :address, :members)
-folks = FamilyStruct.new
-folks.head = PersonStruct.new
-dad = folks.head
-dad.name = "John"
-dad.age = 34
-
-# supply of own accessor method for the struct for error checking
-class PersonStruct
- def age=(value)
- if !value.kind_of?(Integer)
- raise(ArgumentError, "Age #{value} isn't an Integer")
- elsif value > 150
- raise(ArgumentError, "Age #{value} is unreasonable")
- end
- @age = value
- end
-end
-
-
-# @@PLEAC@@_13.6
-# The ruby Object class defines a dup and a clone method.
-# The dup method is recommended for prototype object creation.
-# The default implementation makes a shallow copy,
-# but each class can override it, for example to make a deep copy.
-
-# If you want to call 'new' directly on the instances,
-# you can create a instance method "new", which returns a new duplicate.
-# This method is distinct from the class method new.
-#
-class A
- def new
- dup
- end
-end
-
-ob1 = A.new
-# later on
-ob2 = ob1.new
-
-
-# @@PLEAC@@_13.7
-methname = 'flicker'
-obj.send(methname, 10) # calls obj.flicker(10)
-
-# call three methods on the object, by name
-['start', 'run', 'stop'].each do |method_string|
- obj.send(method_string)
-end
-
-# Another way is to create a Method object
-method_obj = obj.method('flicker')
-# And then call it
-method_obj.call(10)
-
-
-# @@PLEAC@@_13.8
-# All classes in Ruby inherit from class Object
-# and thus all objects share methods defined in this class
-
-# the class of the object
-puts any_object.type
-
-# Ruby classes are actually objects of class Class and they
-# respond to methods defined in Object class as well
-
-# the superclass of this class
-puts any_object.class.superclass
-
-# ask an object whether it is an instance of particular class
-n = 4.7
-puts n.instance_of?(Float) # true
-puts n.instance_of?(Numeric) # false
-
-# ask an object whether it is an instance of class, one of the
-# superclasses of the object, or modules included in it
-puts n.kind_of?(Float) # true (the class)
-puts n.kind_of?(Numeric) # true (an ancestor class)
-puts n.kind_of?(Comparable) # true (a mixin module)
-puts n.kind_of?(String) # false
-
-# ask an object whether it can respond to a particular method
-puts n.respond_to?('+') # true
-puts n.respond_to?('length') # false
-
-# all methods an object can respond to
-'just a string'.methods.each { |m| puts m }
-
-
-# @@PLEAC@@_13.9
-# Actually any class in Ruby is inheritable
-class Person
- attr_accessor :age, :name
- def initialize
- @name
- @age
- end
-end
-#-----------------------------
-dude = Person.new
-dude.name = 'Jason'
-dude.age = 23
-printf "%s is age %d.\n", dude.name, dude.age
-#-----------------------------
-# Inheriting from Person
-class Employee < Person
- attr_accessor :salary
-end
-#-----------------------------
-empl = Employee.new
-empl.name = 'Jason'
-empl.age = 23
-empl.salary = 200
-printf "%s is age %d, the salary is %d.\n", empl.name, empl.age, empl.salary
-#-----------------------------
-# Any built-in class can be inherited the same way
-class WeirdString < String
- def initialize(obj)
- super obj
- end
- def +(anotherObj) # + method in this class is overridden
- # to return the sum of string lengths
- self.length + anotherObj.length # 'self' can be omitted
- end
-end
-#-----------------------------
-a = WeirdString.new('hello')
-b = WeirdString.new('bye')
-
-puts a + b # the overridden +
-#=> 8
-puts a.length # method from the superclass, String
-#=> 5
-
-
-# @@PLEAC@@_13.11
-# In ruby you can override the method_missing method
-# to have a solution similar to perls AUTOLOAD.
-class Person
-
- def initialize
- @ok_fields = %w(name age peers parent)
- end
-
- def valid_attribute?(name)
- @ok_fields.include?(name)
- end
-
- def method_missing(namesymbol, *params)
- name = namesymbol.to_s
- return if name =~ /^A-Z/
- if name.to_s[-1] == ('='[0]) # we have a setter
- isSetter = true
- name.sub!(/=$/, '')
- end
- if valid_attribute?(name)
- if isSetter
- instance_variable_set("@#{name}", *params)
- else
- instance_variable_get("@#{name}", *params)
- end
- else
- # if no annestor is responsible,
- # the Object class will throw a NoMethodError exception
- super(namesymbol, *params)
- end
- end
-
- def new
- kid = Person.new
- kid.parent = self
- kid
- end
-
-end
-
-dad = Person.new
-dad.name = "Jason"
-dad.age = 23
-kid = dad.new
-kid.name = "Rachel"
-kid.age = 2
-puts "Kid's parent is #{kid.parent.name}"
-puts dad
-puts kid
-
-class Employee < Person
- def initialize
- super
- @ok_fields.push("salary", "boss")
- end
- def ok_fields
- @ok_fields
- end
-end
-
-
-# @@PLEAC@@_13.13
-# The ruby garbage collector pretends to cope with circular structures.
-# You can test it with this code:
-class RingNode
- attr_accessor :next
- attr_accessor :prev
- attr_reader :name
-
- def initialize(aName)
- @name = aName
- ObjectSpace.define_finalizer(self,
- self.class.method(:finalize).to_proc)
- end
-
- def RingNode.finalize(id)
- puts "Node #{id} dying"
- end
-
- def RingNode.show_all_objects
- ObjectSpace.each_object {|id|
- puts id.name if id.class == RingNode
- }
- end
-end
-
-def create_test
- a = RingNode.new("Node A")
- b = RingNode.new("Node B")
- c = RingNode.new("Node C")
- a.next = b
- b.next = c
- c.next = a
- a.prev = c
- c.prev = b
- b.prev = a
-
- a = nil
- b = nil
- c = nil
-end
-
-create_test
-RingNode.show_all_objects
-ObjectSpace.garbage_collect
-puts "After garbage collection"
-RingNode.show_all_objects
-
-
-# @@PLEAC@@_13.14
-class String
- def <=>(other)
- self.casecmp other
- end
-end
-
-# There is no way to directly overload the '""' (stringify)
-# operator in Ruby. However, by convention, classes which
-# can reasonably be converted to a String will define a
-# 'to_s' method as in the TimeNumber class defined below.
-# The 'puts' method will automatcally call an object's
-# 'to_s' method as is demonstrated below.
-# Furthermore, if a class defines a to_str method, an object of that
-# class can be used most any place where the interpreter is looking
-# for a String value.
-
-#---------------------------------------
-# NOTE: Ruby has a builtin Time class which would usually be used
-# to manipulate time objects, the following is supplied for
-# educational purposes to demonstrate operator overloading.
-#
-class TimeNumber
- attr_accessor :hours,:minutes,:seconds
- def initialize( hours, minutes, seconds)
- @hours = hours
- @minutes = minutes
- @seconds = seconds
- end
-
- def to_s
- return sprintf( "%d:%02d:%02d", @hours, @minutes, @seconds)
- end
-
- def to_str
- to_s
- end
-
- def +( other)
- seconds = @seconds + other.seconds
- minutes = @minutes + other.minutes
- hours = @hours + other.hours
- if seconds >= 60
- seconds %= 60
- minutes += 1
- end
- if minutes >= 60
- minutes %= 60
- hours += 1
- end
- return TimeNumber.new(hours, minutes, seconds)
- end
-
- def -(other)
- raise NotImplementedError
- end
-
- def *(other)
- raise NotImplementedError
- end
-
- def /( other)
- raise NotImplementedError
- end
-end
-
-t1 = TimeNumber.new(0, 58, 59)
-sec = TimeNumber.new(0, 0, 1)
-min = TimeNumber.new(0, 1, 0)
-puts t1 + sec + min + min
-
-#-----------------------------
-# StrNum class example: Ruby's builtin String class already has the
-# capabilities outlined in StrNum Perl example, however the '*' operator
-# on Ruby's String class acts differently: It creates a string which
-# is the original string repeated N times.
-#
-# Using Ruby's String class as is in this example:
-x = "Red"; y = "Black"
-z = x+y
-r = z*3 # r is "RedBlackRedBlackRedBlack"
-puts "values are #{x}, #{y}, #{z}, and #{r}"
-print "#{x} is ", x < y ? "LT" : "GE", " #{y}\n"
-# prints:
-# values are Red, Black, RedBlack, and RedBlackRedBlackRedBlack
-# Red is GE Black
-
-#-----------------------------
-class FixNum
- REGEX = /(\.\d*)/
- DEFAULT_PLACES = 0
- attr_accessor :value, :places
- def initialize(value, places = nil)
- @value = value
- if places
- @places = places
- else
- m = REGEX.match(value.to_s)
- if m
- @places = m[0].length - 1
- else
- @places = DEFAULT_PLACES
- end
- end
- end
-
- def +(other)
- FixNum.new(@value + other.value, max(@places, other.places))
- end
-
- def *(other)
- FixNum.new(@value * other.value, max(@places, other.places))
- end
-
- def /(other)
- puts "Divide: #{@value.to_f/other.value.to_f}"
- result = FixNum.new(@value.to_f/other.value.to_f)
- result.places = max(result.places,other.places)
- result
- end
-
- def to_s
- sprintf("STR%s: %.*f", self.class.to_s , @places, @value) #.
- end
-
- def to_str
- to_s
- end
-
- def to_i #convert to int
- @value.to_i
- end
-
- def to_f #convert to float`
- @value.to_f
- end
-
- private
- def max(a,b)
- a > b ? a : b
- end
-end
-
-def demo()
- x = FixNum.new(40)
- y = FixNum.new(12, 0)
-
- puts "sum of #{x} and #{y} is #{x+y}"
- puts "product of #{x} and #{y} is #{x*y}"
-
- z = x/y
- puts "#{z} has #{z.places} places"
- unless z.places
- z.places = 2
- end
-
- puts "div of #{x} by #{y} is #{z}"
- puts "square of that is #{z*z}"
-end
-
-if __FILE__ == $0
- demo()
-end
-
-
-# @@PLEAC@@_14.1
-# There are dbm, sdbm, gdbm modules
-# and the bdb module for accessing the berkeley db
-# sdbm seem to be available on the most systems,
-# so we use it here
-#
-require "sdbm"
-SDBM.open("filename", 0666) { |dbobj|
- # raises exception if open error
-
- # the returned sdbm-dbobj has most of the methods of a hash
- v = dbobj["key"]
- dbobj["key"] = "newvalue"
- if dbobj.has_key?("key")
- # ...
- end
- dbobj.delete("key2")
-}
-# database is open only inside the block.
-
-# It is also possible to use a open .. close pair:
-dbobj = SDBM.open("filename", 0666)
-#.. do something with dbobj
-dbobj.close
-
-#!/usr/bin/ruby -w
-# userstats - generate statistics on who is logged in
-# call with usernames as argument to display the totals
-# for the given usernames, call with "ALL" to display all users
-
-require "sdbm"
-filename = '/tmp/userstats.db'
-SDBM.open(filename, 0666) { |dbobj|
- if ARGV.length > 0
- if ARGV[0] == "ALL"
- # ARGV is constant, so we need the variable userlist
- userlist = dbobj.keys().sort()
- else
- userlist = ARGV
- end
- userlist.each { |user|
- print "#{user}\t#{dbobj[user]}\n"
- }
- else
- who = `who`
- who.split("\n").each { |line|
- md = /^(\S+)/.match(line)
- raise "Bad line from who: #{line}" unless md
- # sdbm stores only strings, so "+=" doesn't work,
- # we need to convert them expicitly back to integer.
- if dbobj.has_key?(md[0])
- dbobj[md[0]] = dbobj[md[0]].to_i + 1
- else
- dbobj[md[0]] = "1"
- end
- }
- end
-}
-
-
-# @@PLEAC@@_14.2
-# using open and clear
-dbobj = SDBM.open("filename", 0666)
-dbobj.clear()
-dbobj.close()
-# deleting file and recreating it
-# the filenames depend on the flavor of dbm you use,
-# for example sdbm has two files named filename.pag and filename.dir,
-# so you need to delete both files
-begin
- File.delete("filename")
- # raises Exception if not exist
- dbobj = SDBM.open("filename", 0666)
-rescue
- # add error handling here
-end
-
-
-# @@PLEAC@@_14.3
-# sdbm2gdbm: converts sdbm database to a gdbm database
-require "sdbm"
-require "gdbm"
-
-unless ARGV.length == 2
- fail "usage: sdbm2gdbm infile outfile"
-end
-infile = ARGV[0]
-outfile = ARGV[1]
-
-sdb = SDBM.open(infile)
-gdb = GDBM.open(outfile, 0666)
-sdb.each { |key, val|
- gdb[key] = val
-}
-gdb.close
-sdb.close
-
-
-# @@PLEAC@@_14.4
-#!/usr/bin/ruby -w
-# dbmmerge: merges two dbm databases
-require "sdbm"
-
-unless ARGV.length == 3
- fail "usage: dbmmerge indb1 indb2 outdb"
-end
-infile1 = ARGV[0]
-infile2 = ARGV[0]
-outfile = ARGV[2]
-
-in1 = SDBM.open(infile1, nil)
-in2 = SDBM.open(infile2, nil)
-outdb = SDBM.open(outfile, 0666)
-
-[in1, in2].each { |indb|
- indb.each { |key, val|
- if outdb.has_key?(key)
- # decide which value to set.
- # set outdb[key] if necessary
- else
- outdb[key] = val
- end
- }
-}
-in1.close
-in2.close
-outdb.close
-
-
-# @@PLEAC@@_14.7
-# we write a tie method that extends the Array class.
-# It reads the file into the memory, executes the code block
-# in which you can manipulate the array as needed, and writes
-# the array back to the file after the end of the block execution
-class Array
- def tie(filename, flags)
- File.open(filename, flags) { |f|
- f.each_line { |line|
- self.push(line.chomp)
- }
- yield
- f.rewind
- each { |line|
- if line
- f.puts(line)
- else
- f.puts ""
- end
- }
- }
- end
-end
-
-array = Array.new
-array.tie("/tmp/textfile.txt", File::RDWR|File::CREAT) {
- array[4] = "a new line 4"
-}
-
-# The tied array can be manipulated like a normal array,
-# so there is no need for a special API, and the recno_demo program
-# to demonstrate is API is useless
-
-
-# tied array demo: show how to use array with a tied file
-filename = "db_file.txt"
-lines = Array.new
-File.unlink(filename) if File.exists?(filename)
-lines.tie(filename, File::RDWR | File::CREAT) {
- # first create a textfile to play with
- lines[0] = "zero"
- lines[1] = "one"
- lines[2] = "two"
- lines[3] = "three"
- lines[4] = "four"
-
- # print the records in order.
- # Opposed to perl, the tied array behaves exactly as a normal array
- puts "\nOriginal"
- for i in 0..(lines.length-1)
- puts "#{i}: #{lines[i]}"
- end
-
- #use push and pop
- a = lines.pop
- lines.push("last")
- puts("The last line was [#{a}]")
-
- #use shift and unshift
- a = lines.shift
- lines.unshift("first")
- puts("The first line was [#{a}]")
-
- # add record after record 2
- i = 2
- lines.insert(i + 1, "Newbie")
-
- # add record before record one
- i = 1
- lines.insert(i, "New One")
-
- # delete record 3
- lines.delete_at(3)
-
- #now print the records in reverse order
- puts "\nReverse"
- (lines.length - 1).downto(0){ |i|
- puts "#{i}: #{lines[i]}"
- }
-
-}
-
-
-# @@PLEAC@@_14.8
-# example to store complex data in a database
-# uses marshall from the standard library
-require "sdbm"
-db = SDBM.open("pleac14-8-database", 0666)
-
-# convert the Objects into strings and back by using the Marshal module.
-# Most normal objects can be converted out of the box,
-# but not special things like procedure objects,
-# IO instance variables, singleton objects
-
-db["Tom Christiansen"] = Marshal.dump(["book author", "tchrist@perl.com"])
-db["Tom Boutell"] = Marshal.dump(["shareware author",
-"boutell@boutell.com"])
-
-name1 = "Tom Christiansen"
-name2 = "Tom Boutell"
-
-tom1 = Marshal.load(db[name1])
-tom2 = Marshal.load(db[name2])
-
-puts "Two Toming: #{tom1} #{tom2}"
-
-if tom1[0] == tom2[0] && tom1[1] == tom2[1]
- puts "You're having runtime fun with one Tom made two."
-else
- puts "No two Toms are ever alike"
-end
-
-# To change parts of an entry, get the whole entry, change the parts,
-# and save the whole entry back
-entry = Marshal.load(db["Tom Boutell"])
-entry[0] = "Poet Programmer"
-db["Tom Boutell"] = Marshal.dump(entry)
-db.close
-
-
-# @@PLEAC@@_14.9
-# example to make data persistent
-# uses Marshal from the standard lib
-# Stores the data in a simple file,
-# see 14.8 on how to store it in a dbm file
-
-# The BEGIN block is executed before the rest of the script
-# we use global variables here because local variables
-# will go out of scope and are not accessible from the main script
-
-BEGIN {
- $persistent_store = "persitence.dat"
- begin
- File.open($persistent_store) do |f|
- $stringvariable1 = Marshal.load(f)
- $arrayvariable2 = Marshal.load(f)
- end
- rescue
- puts "Can not open #{$persistent_store}"
- # Initialisation if this script runs the first time
- $stringvariable1 = ""
- $arrayvariable2 = []
- end
-}
-
-END {
- File.open($persistent_store, "w+") do |f|
- Marshal.dump($stringvariable1, f)
- Marshal.dump($arrayvariable2, f)
- end
-}
-
-# simple test program
-puts $stringvariable1
-puts $arrayvariable2
-$stringvariable1 = "Hello World"
-$arrayvariable2.push(5)
-puts $stringvariable1
-puts $arrayvariable2
-
-
-# @@PLEAC@@_14.10
-#!/usr/bin/ruby -w
-# Ruby has a dbi module with an architecture similar
-# to the Perl dbi module: the dbi module provides an unified
-# interface and uses specialized drivers for each dbms vendor
-#
-begin
- DBI.connect("DBI:driver:driverspecific", "username", "auth") {
- |dbh|
-
- dbh.do(SQL1)
-
- dbh.prepare(SQL2){ |sth|
- sth.execute
- sth.fetch {|row|
- # ...
- }
- } # end of block finishes the statement handle
- } # end of block closes the database connection
-rescue DBI::DatabaseError => e
- puts "dbi error occurred"
- puts "Error code: #{e.err}"
- puts "Error message: #{e.errstr}"
-end
-
-#!/usr/bin/ruby -w
-# dbusers - example for mysql which creates a table,
-# fills it with values, retrieves the values back,
-# and finally destroys the table.
-
-require "dbi"
-
-# replacement for the User::pwnt module
-def getpwent
- result = []
- File.open("/etc/passwd") {|file|
- file.each_line {|line|
- next if line.match(/^#/)
- cols = line.split(":")
- result.push([cols[2], cols[0]])
- }
- }
- result
-end
-
-begin
- DBI.connect("DBI:Mysql:pleacdatabase", "pleac", "pleacpassword") {
- |conn|
-
- conn.do("CREATE TABLE users (uid INT, login CHAR(8))")
-
- users = getpwent
-
- conn.prepare("INSERT INTO users VALUES (?,?)") {|sth|
- users.each {|entry|
- sth.execute(entry[0], entry[1])
- }
- }
-
- conn.execute("SELECT uid, login FROM users WHERE uid < 50") {|sth|
- sth.fetch {|row|
- puts row.collect {|col|
- if col.nil?
- "(null)"
- else
- col
- end
- }.join(", ")
- }
- }
-
- conn.do("DROP TABLE users")
- }
-rescue DBI::DatabaseError => e
- puts "dbi error occurred"
- puts "Error code: #{e.err}"
- puts "Error message: #{e.errstr}"
-end
-
-
-# @@PLEAC@@_15.1
-# This test program demonstrates parsing program arguments.
-# It uses the optparse library, which is included with ruby 1.8
-# It handles classic unix style and gnu style options
-require 'optparse'
-
-@debugmode = false
-@verbose = false
-
-ARGV.options do |opts|
- opts.banner = "Usage: ruby #{$0} [OPTIONS] INPUTFILES"
-
- opts.on("-h", "--help", "show this message") {
- puts opts
- exit
- }
- # The OptionParser#on method is called with a specification of short
- # options, of long options, a data type spezification and user help
- # messages for this option.
- # The method analyses the given parameter and decides what it is,
- # so you can leave out the long option if you don't need it
- opts.on("-v", "--[no-]verbose=[FLAG]", TrueClass, "run verbosly") {
- |@verbose| # sets @verbose to true or false
- }
- opts.on("-D", "--DEBUG", TrueClass, "turns on debug mode" ){
- |@debugmode| # sets @debugmode to true
- }
- opts.on("-c", "--count=NUMBER", Integer, "how many times we do it" ){
- |@count| # sets @count to given integer
- }
- opts.on("-o", "--output=FILE", String, "file to write output to"){
- |@outputfile| # sets @outputfile to given string
- }
- opts.parse!
-end
-
-# example to use the options in the main program
-puts "Verbose is on" if @verbose
-puts "Debugmode is on" if @debugmode
-puts "Outfile is #{@outputfile}" if defined? @outputfile
-puts "Count is #{@count}" if defined? @count
-ARGV.each { |param|
- puts "Got parameter #{param}"
-}
-
-
-# @@PLEAC@@_15.4
-buf = "\0" * 8
-$stdout.ioctl(0x5413, buf)
-ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("S4")
-
-raise "You must have at least 20 characters" unless ws_col >= 20
-max = 0
-values = (1..5).collect { rand(20) } # generate an array[5] of rand values
-for i in values
- max = i if max < i
-end
-ratio = Float(ws_col-12)/max # chars per unit
-for i in values
- printf "%8.1f %s\n", i, "*" * (ratio*i)
-end
-
-# gives, for example:
-# 15.0 *******************************
-# 10.0 *********************
-# 5.0 **********
-# 14.0 *****************************
-# 18.0 **************************************
-
-
-# @@PLEAC@@_16.1
-output = `program args` # collect output into one multiline string
-output = `program args`.split # collect output into array, one line per
-element
-
-readme = IO.popen("ls")
-output = ""
-while readme.gets do
- output += $_
-end
-readme.close
-
-`fsck -y /dev/rsd1a` # BAD AND SCARY in Perl because it's managed by the shell
- # I donna in Ruby ...
-
-# so the "clean and secure" version
-readme, writeme = IO.pipe
-pid = fork {
- # child
- $stdout = writeme
- readme.close
- exec('find', '..')
-}
-# parent
-Process.waitpid(pid, 0)
-writeme.close
-while readme.gets do
- # do something with $_
-end
-
-
-# @@PLEAC@@_16.2
-status = system("xemacs #{myfile}")
-
-status = system("xemacs", myfile)
-
-system("cmd1 args | cmd2 | cmd3 >outfile")
-system("cmd args <infile >outfile 2>errfile")
-
-# stop if the command fails
-raise "$program exited funny: #{$?}" unless system("cmd", "args1", "args2")
-
-# get the value of the signal sent to the child
-# even if it is a SIGINT or SIGQUIT
-system(arglist)
-raise "program killed by signal #{$?}" if ($? & 127) != 0
-
-pid = fork {
- trap("SIGINT", "IGNORE")
- exec("sleep", "10")
-}
-trap ("SIGINT") {
- puts "Tsk tsk, no process interruptus"
-}
-Process.waitpid(pid, 0)
-
-# Ruby doesn't permit to lie to the program called by a 'system'.
-# (ie specify what return argv[0] in C, $0 in Perl/Ruby ...)
-# A (dirty) way is to create a link (under Unix), run this link and
-# erase it. Somebody has a best idea ?
-
-
-# @@PLEAC@@_16.3
-exec("archive *.data")
-
-exec("archive", "accounting.data")
-
-exec("archive accounting.data")
-
-
-# @@PLEAC@@_16.4
-# read the output of a program
-IO.popen("ls") {|readme|
- while readme.gets do
- # ...
- end
-}
-# or
-readme = IO.popen("ls")
-while readme.gets do
- # ...
-end
-readme.close
-
-# "write" in a program
-IO.popen("cmd args","w") {|pipe|
- pipe.puts("data")
- pipe.puts("foo")
-}
-
-# close wait for the end of the process
-read = IO.popen("sleep 10000") # child goes to sleep
-read.close # and the parent goes to lala land
-
-writeme = IO.popen("cmd args", "w")
-writeme.puts "hello" # program will get hello\n on STDIN
-writeme.close # program will get EOF on STDIN
-
-# send in a pager (eg less) all output
-$stdout = IO.popen("/usr/bin/less","w")
-print "huge string\n" * 10000
-
-
-# @@PLEAC@@_16.5
-#-----------------------------
-def head(lines = 20)
- pid = open("|-","w")
- if pid == nil
- return
- else
- while gets() do
- pid.print
- lines -= 1
- break if lines == 0
- end
- end
- exit
-end
-
-head(100)
-while gets() do
- print
-end
-#-----------------------------
-1: > Welcome to Linux, version 2.0.33 on a i686
-
-2: >
-
-3: > "The software required `Windows 95 or better',
-
-4: > so I installed Linux."
-#-----------------------------
-> 1: Welcome to Linux, Kernel version 2.0.33 on a i686
-
-> 2:
-
-> 3: "The software required `Windows 95 or better',
-
-> 4: so I installed Linux."
-#-----------------------------
-#!/usr/bin/ruby
-# qnumcat - demo additive output filters
-
-def number()
- pid = open("|-","w")
- if pid == nil
- return
- else
- while gets() do pid.printf("%d: %s", $., $_); end
- end
- exit
-end
-
-def quote()
- pid = open("|-","w")
- if pid == nil
- return
- else
- while gets() do pid.print "> #{$_}" end
- end
- exit
-end
-
-number()
-quote()
-
-while gets() do
- print
-end
-$stdout.close
-exit
-
-
-# @@PLEAC@@_16.6
-ARGV.map! { |arg|
- arg =~ /\.(gz|Z)$/ ? "|gzip -dc #{arg}" : arg
-}
-for file in ARGV
- fh = open(file)
- while fh.gets() do
- # .......
- end
-end
-#-----------------------------
-ARGV.map! { |arg|
- arg =~ %r#^\w+://# ? "|GET #{arg}" : arg #
-}
-for file in ARGV
- fh = open(file)
- while fh.gets() do
- # .......
- end
-end
-#-----------------------------
-pwdinfo = (`domainname` =~ /^(\(none\))?$/) ? '/etc/passwd' : '|ypcat passwd';
-pwd = open(pwdinfo);
-#-----------------------------
-puts "File, please? ";
-file = gets().chomp();
-fh = open(file);
-
-
-# @@PLEAC@@_16.7
-output = `cmd 2>&1` # with backticks
-# or
-ph = open("|cmd 2>&1") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-output = `cmd 2>/dev/null` # with backticks
-# or
-ph = open("|cmd 2>/dev/null") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-output = `cmd 2>&1 1>/dev/null` # with backticks
-# or
-ph = open("|cmd 2>&1 1>/dev/null") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-output = `cmd 3>&1 1>&2 2>&3 3>&-` # with backticks
-# or
-ph = open("|cmd 3>&1 1>&2 2>&3 3>&-") # with an open pipe
-while ph.gets() { } # plus a read
-#-----------------------------
-system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr")
-#-----------------------------
-output = `cmd 3>&1 1>&2 2>&3 3>&-`
-#-----------------------------
-fd3 = fd1
-fd1 = fd2
-fd2 = fd3
-fd3 = nil
-#-----------------------------
-system("prog args 1>tmpfile 2>&1")
-system("prog args 2>&1 1>tmpfile")
-#-----------------------------
-# system ("prog args 1>tmpfile 2>&1")
-fd1 = "tmpfile" # change stdout destination first
-fd2 = fd1 # now point stderr there, too
-#-----------------------------
-# system("prog args 2>&1 1>tmpfile")
-fd2 = fd1 # stderr same destination as stdout
-fd1 = "tmpfile" # but change stdout destination
-#-----------------------------
-# It is often better not to rely on the shell,
-# because of portability, possible security problems
-# and bigger resource usage. So, it is often better to use the open3 library.
-# See below for an example.
-# opening stdin, stdout, stderr
-require "open3"
-stdin, stdout, stderr = Open3.popen('cmd')
-
-
-# @@PLEAC@@_16.8
-#-----------------------------
-# Contrary to perl, we don't need to use a module in Ruby
-fh = Kernel.open("|" + program, "w+")
-fh.puts "here's your input\n"
-output = fh.gets()
-fh.close()
-#-----------------------------
-Kernel.open("|program"),"w+") # RIGHT !
-#-----------------------------
-# Ruby has already object methods for I/O handles
-#-----------------------------
-begin
- fh = Kernel.open("|" + program_and_options, "w+")
-rescue
- if ($@ ~= /^open/)
- $stderr.puts "open failed : #{$!} \n #{$@} \n"
- break
- end
- raise # reraise unforseen exception
-end
-
-
-# @@PLEAC@@_16.13
-#% kill -l
-#HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE
-#ALRM TERM CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM
-#PROF WINCH POLL PWR
-#-----------------------------
-#% ruby -e 'puts Signal.list.keys.join(" ")'
-#PWR USR1 BUS USR2 TERM SEGV KILL POLL STOP SYS TRAP IOT HUP INT #
-#WINCH XCPU TTIN CLD TSTP FPE IO TTOU PROF CHLD CONT PIPE ABRT
-#VTALRM QUIT ILL XFSZ URG ALRM
-#-----------------------------
-# After that, the perl script create an hash equivalent to Signal.list,
-# and an array. The array can be obtained by :
-signame = []
-Signal.list.each { |name, i| signame[i] = name }
-
-
-# @@PLEAC@@_16.14
-Process.kill(9, pid) # send $pid a signal 9
-Process.kill(-1, Process.getpgrp()) # send whole job a signal 1
-Process.kill("USR1", $$) # send myself a SIGUSR1
-Process.kill("HUP", pid1, pid2, pid3) # send a SIGHUP to processes in @pids
-#-----------------------------
-begin
- Process.kill(0, minion)
- puts "#{minion} is alive!"
-rescue Errno::EPERM # changed uid
- puts "#{minion} has escaped my control!";
-rescue Errno::ESRCH
- puts "#{minion} is deceased."; # or zombied
-rescue
- puts "Odd; I couldn't check the status of #{minion} : #{$!}"
-end
-
-
-# @@PLEAC@@_16.15
-Kernel.trap("QUIT", got_sig_quit) # got_sig_quit = Proc.new { puts "Quit\n" }
-trap("PIPE", "got_sig_quit") # def got_sig_pipe ...
-trap("INT") { ouch++ } # increment ouch for every SIGINT
-#-----------------------------
-trap("INT", "IGNORE") # ignore the signal INT
-#-----------------------------
-trap("STOP", "DEFAULT") # restore default STOP signal handling
-
-
-# @@PLEAC@@_16.16
-# the signal handler
-def ding
- trap("INT", "ding")
- puts "\aEnter your name!"
-end
-
-# prompt for name, overriding SIGINT
-def get_name
- save = trap("INT", "ding")
-
- puts "Kindly Stranger, please enter your name: "
- name = gets().chomp()
- trap("INT", save)
- name
-end
-
-
-# @@PLEAC@@_16.21
-# implemented thanks to http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/1760
-require 'timeout'
-
-# we'll do something vastly more useful than cookbook to demonstrate timeouts
-begin
- timeout(5) {
- waitsec = rand(10)
- puts "Let's see if a sleep of #{waitsec} seconds is longer than 5 seconds..."
- system("sleep #{waitsec}")
- }
- puts "Timeout didn't occur"
-rescue Timeout::Error
- puts "Timed out!"
-end
-
-
-# @@PLEAC@@_17.1
-# A basic TCP client connection
-require 'socket'
-begin
- t = TCPSocket.new('www.ruby-lang.org', 'www')
-rescue
- puts "error: #{$!}"
-else
- # ... do something with the socket
- t.print "GET / HTTP/1.0\n\n"
- answer = t.gets(nil)
- # and terminate the connection when we're done
- t.close
-end
-
-# Using the evil low level socket API
-require 'socket'
-# create a socket
-s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
-# build the address of the remote machine
-sockaddr_server = [Socket::AF_INET, 80,
- Socket.gethostbyname('www.ruby-lang.org')[3],
- 0, 0].pack("snA4NN")
-# connect
-begin
- s.connect(sockaddr_server)
-rescue
- puts "error: #{$!}"
-else
- # ... do something with the socket
- s.print "GET / HTTP/1.0\n\n"
- # and terminate the connection when we're done
- s.close
-end
-
-# TCP connection with management of error (DNS)
-require 'socket'
-begin
- client = TCPSocket.new('does not exists', 'www')
-rescue
- puts "error: #{$!}"
-end
-
-# TCP connection with a time out
-require 'socket'
-require 'timeout'
-begin
- timeout(1) do #the server has one second to answer
- client = TCPSocket.new('www.host.com', 'www')
- end
-rescue
- puts "error: #{$!}"
-end
-
-
-# @@PLEAC@@_17.12
-require 'socket'
-
-class Preforker
- attr_reader (:child_count)
-
- def initialize(prefork, max_clients_per_child, port, client_handler)
- @prefork = prefork
- @max_clients_per_child = max_clients_per_child
- @port = port
- @child_count = 0
-
- @reaper = proc {
- trap('CHLD', @reaper)
- pid = Process.wait
- @child_count -= 1
- }
-
- @huntsman = proc {
- trap('CHLD', 'IGNORE')
- trap('INT', 'IGNORE')
- Process.kill('INT', 0)
- exit
- }
-
- @client_handler=client_handler
- end
-
- def child_handler
- trap('INT', 'EXIT')
- @client_handler.setUp
- # wish: sigprocmask UNblock SIGINT
- @max_clients_per_child.times {
- client = @server.accept or break
- @client_handler.handle_request(client)
- client.close
- }
- @client_handler.tearDown
- end
-
- def make_new_child
- # wish: sigprocmask block SIGINT
- @child_count += 1
- pid = fork do
- child_handler
- end
- # wish: sigprocmask UNblock SIGINT
- end
-
- def run
- @server = TCPserver.open(@port)
- trap('CHLD', @reaper)
- trap('INT', @huntsman)
- loop {
- (@prefork - @child_count).times { |i|
- make_new_child
- }
- sleep .1
- }
- end
-end
-
-#-----------------------------
-#!/usr/bin/ruby
-
-require 'Preforker'
-
-class ClientHandler
- def setUp
- end
-
- def tearDown
- end
-
- def handle_request(client)
- # do stuff
- end
-end
-
-server = Preforker.new(1, 100, 3102, ClientHandler.new)
-server.run
-
-
-# @@PLEAC@@_18.2
-require 'net/ftp'
-
-begin
- ftp = Net::FTP::new("ftp.host.com")
- ftp.login(username,password)
- ftp.chdir(directory)
- ftp.get(filename)
- ftp.put(filename)
-rescue Net::FTPError
- $stderr.print "FTP failed: " + $!
-ensure
- ftp.close() if ftp
-end
-
-# A better solution for a local use could be :
-Net::FTP::new("ftp.host.com") do |ftp|
- ftp.login(username,password)
- ftp.chdir(directory)
- ftp.get(filename)
- ftp.put(filename)
-end
-
-# If you have only one file to get, there is a simple solution :
-require 'open-uri'
-open("ftp://www.ruby-lang.org/path/filename") do |fh|
- # read from filehandle fh
-end
-#--------------------------------------------
-# to wait a defined time for the connection,
-# use the timeout module
-require 'timeout'
-begin
- timeout(30){
- ftp = Net::FTP::new("ftp.host.com")
- ftp.debug_mode = true
- }
-rescue Net::FTPError
- $stderr.puts "Couldn't connect."
-rescue Timeout::Error
- $stderr.puts "Timeout while connecting to server."
-end
-
-begin
- ftp.login()
-rescue Net::FTPError
- $stderr.print "Couldn't authentificate.\n"
-end
-
-begin
- ftp.login(username)
-rescue Net::FTPError
- $stderr.print "Still couldn't authenticate.\n"
-end
-
-begin
- ftp.login(username, password)
-rescue Net::FTPError
- $stderr.print "Couldn't authenticate, even with explicit
- username and password.\n"
-end
-
-begin
- ftp.login(username, password, account)
-rescue Net::FTPError
- $stderr.print "No dice. It hates me.\n"
-end
-#-----------------------------
-ftp.put(localfile, remotefile)
-#-----------------------------
-# Sending data from STDIN is not directly supported
-# by the ftp library module. A possible way to do it is to use the
-# storlines method directly to send raw commands to the ftp server.
-#-----------------------------
-ftp.get(remotefile, localfile)
-#-----------------------------
-ftp.get(remotefile) { |data| puts data }
-#-----------------------------
-ftp.chdir("/pub/ruby")
-print "I'm in the directory ", ftp.pwd(), "\n"
-#-----------------------------
-ftp.mkdir("/pub/ruby/new_dir")
-#-----------------------------
-lines = ftp.ls("/pub/ruby/")
-# => ["drwxr-xr-x 2 matz users 4096 July 17 1998 1.0", ... ]
-
-latest = ftp.dir("/pub/ruby/*.tgz").sort.last
-
-ftp.nlst("/pub/ruby")
-# => ["/pub/ruby/1.0", ... ]
-#-----------------------------
-ftp.quit()
-
-
-# @@PLEAC@@_18.6
-require 'net/telnet'
-t = Net::Telnet::new( "Timeout" => 10,
- "Prompt" => /%/,
- "Host" => host )
-t.login(username, password)
-files = t.cmd("ls")
-t.print("top")
-process_string = t.waitfor(/\d+ processes/)
-t.close
-#-----------------------------
-/[$%#>] \z/n
-#-----------------------------
-# In case of an error, the telnet module throws an exception.
-# For control of the behavior in case of an error,
-# you just need to catch the exceptions and do your custom
-# error handling.
-#-----------------------------
-begin
- telnet.login(username, password)
-rescue TimeoutError
- fail "Login failed !\n"
-end
-#-----------------------------
-telnet.waitfor('/--more--/')
-#-----------------------------
-telnet.waitfor(String => 'greasy smoke', Timeout => 30)
-
-
-# @@PLEAC@@_18.7
-require 'ping'
-
-puts "#{host} is alive.\n" if Ping.pingecho(host);
-#-----------------------------
-# the ping module only use TCP ping, not ICMP even if we are root
-if Ping.pingecho("kingkong.com")
- puts "The giant ape lives!\n";
-else
- puts "All hail mighty Gamera, friend of children!\n";
-end
-
-
-# @@PLEAC@@_19.0
-#-----------------------------
-# http://www.perl.com/CPAN/
-# http://www.perl.com:8001/bad/mojo.html
-# ftp://gatekeeper.dec.com/pub/misc/netlib.tar.Z
-# ftp://anonymous@myplace:gatekeeper.dec.com/pub/misc/netlib.tar.Z
-# file:///etc/motd
-#-----------------------------
-# http://mox.perl.com/cgi-bin/program?name=Johann&born=1685
-#-----------------------------
-# http://mox.perl.com/cgi-bin/program
-#-----------------------------
-
-
-# @@PLEAC@@_19.1
-#!/usr/local/bin/ruby -w
-# hiweb - load CGI class to decode information given by web server
-
-require 'cgi'
-
-cgi = CGI.new('html3')
-
-# get a parameter from a form
-value = cgi.params['PARAM_NAME'][0]
-
-# output a document
-cgi.out {
- cgi.html {
- cgi.head { cgi.title { "Howdy there!" } } +
- cgi.body { cgi.p { "You typed: " + cgi.tt {
- CGI.escapeHTML(value) } } }
- }
-}
-
-require 'cgi'
-cgi = CGI.new
-who = cgi.param["Name"][0] # first param in list
-phone = cgi.param["Number"][0]
-picks = cgi.param["Choices"] # complete list
-
-print cgi.header( 'type' => 'text/plain',
- 'expires' => Time.now + (3 * 24 * 60 * 60) )
-
-
-# @@PLEAC@@_19.3
-#!/usr/local/bin/ruby -w
-# webwhoami - show web user's id
-require 'etc'
-print "Content-Type: text/plain\n\n"
-print "Running as " + Etc.getpwuid.name + "\n"
-
-# % ruby -wc cgi-script # just check syntax
-
-# % ruby -w cgi-script # params from stdin
-# (offline mode: enter name=value pairs on standard input)
-# name=joe
-# number=10
-# ^D
-
-# % ruby -w cgi-script name=joe number=10 # run with mock form input
-# % ruby -d cgi-script name=joe number=10 # ditto, under the debugger
-
-# POST method script in csh
-# % (setenv HTTP_METHOD POST; ruby -w cgi-script name=joe number=10)
-# POST method script in sh
-# % HTTP_METHOD=POST perl -w cgi-script name=joe number=10
-
-
-# @@PLEAC@@_19.4
-# ruby has several security levels, the level "1" is similar to perls taint mode.
-# It can be switched on by providing the -T command line parameter
-# or by setting $SAFE to 1. Setting $SAFE to 2,3 or 4 restricts possible
-# harmful operations further.
-
-#!/usr/bin/ruby -T
-$SAFE = 1
-File.open(ARGV[0], "w")
-# ruby warns with:
-# taint1.rb:2:in `initialize': Insecure operation - initialize (SecurityError)
-
-$SAFE = 1
-file = ARGV[0]
-unless /^([\w.-]+)$/.match(file)
- raise "filename #{file} has invalid characters"
-end
-file = $1
-# In ruby, even the back reference from a regular expression stays tainted.
-# you need to explicitly untaint the variable:
-file.untaint
-File.open(file, "w")
-
-# Race condition exists like in perl:
-unless File.exists(filename) # Wrong because of race condition
- File.open(filename, "w")
-end
-
-
-# @@PLEAC@@_19.8
-url = "http://pleac.sourceforge.net/pleac_ruby/"
-print "Location: #{url}\r\n\r\n"
-exit
-
-#!/usr/bin/ruby
-require 'cgi'
-
-cgi = CGI.new
-oreo = CGI::Cookie.new('name' => 'filling',
- 'value' => 'vanilla creme',
- 'expires' => Time.now + (3 * 30 * 24 * 60 * 60),
- 'domain' => '.pleac.sourceforge.net')
-
-whither = 'http://pleac.sourceforge.net/pleac_ruby/cgiprogramming.html'
-
-cgi.out('cookie' => oreo,
- 'Location' => whither){""}
-
-#!/usr/bin/ruby
-# os_snipe - redirect to a Jargon File entry about current OS
-dir = 'http://www.elsewhere.org/jargon/html/entry'
-
-agent = ENV['HTTP_USER_AGENT']
-
-page = case
- when agent =~ /Mac/: 'Macintrash.html'
- when agent =~ /Win(dows )?NT/: 'evil_and_rude.html'
- when agent =~ /Win|MSIE|WebTV/: 'Microsloth_Windows.html'
- when agent =~ /Linux/: 'Linux.html'
- when agent =~ /HP-UX/: 'HP-SUX.html'
- when agent =~ /SunOS/: 'ScumOS.html'
- else 'Appendix_B.html'
-end
-
-print "Location: #{dir}/#{page}\n\n"
-
-require 'cgi'
-cgi = CGI.new
-cgi.out('status' => '204 No response'){""}
-# this produces:
-# Status: 204 No response
-# Content-Type: text/html
-# Content-Length: 0
-# <blank line here>
-
-
-# @@PLEAC@@_19.10
-preference_value = cgi.cookies["preference name"][0]
-
-packed_cookie = CGI::Cookie.new("name" => "preference name",
- "value" => "whatever you'd like",
- "expires" => Time.local(Time.now.year + 2,
- Time.now.mon, Time.now.day, Time.now.hour, Time.now.min, Time.now.sec) )
-
-cgi.header("cookie" => [packed_cookie])
-
-#!/usr/local/bin/ruby -w
-# ic_cookies - sample CGI script that uses a cookie
-require 'cgi'
-
-cgi = CGI.new('html3')
-
-cookname = "favorite ice cream"
-favorite = cgi.params["flavor"][0]
-tasty = cgi.cookies[cookname][0] || 'mint'
-
-unless favorite
- cgi.out {
- cgi.html {
- cgi.head { cgi.title { "Ice Cookies" } } +
- cgi.body {
- cgi.h1 { "Hello Ice Cream" } +
- cgi.hr +
- cgi.form {
- cgi.p { "Please select a flavor: " +
- cgi.text_field("flavor", tasty ) }
- } +
- cgi.hr
- }
- }
- }
-else
- cookie = CGI::Cookie.new( "name" => cookname,
- "value" => favorite,
- "expires" => Time.local(Time.now.year + 2,
-Time.now.mon, Time.now.day, Time.now.hour, Time.now.min, Time.now.sec) )
- cgi.out("cookie" => [cookie]) {
- cgi.html {
- cgi.head { cgi.title { "Ice Cookies" } } +
- cgi.body {
- cgi.h1 { "Hello Ice Cream" } +
- cgi.p { "You chose as your favorite flavor `#{favorite}'." }
- }
- }
- }
-end
-
-
-# @@PLEAC@@_20.9
-def templatefile(filename, fillings)
- aFile = File.new(filename, "r")
- text = aFile.read()
- aFile.close()
- pattern = Regexp.new('%%(.*?)%%')
- text.gsub!(pattern) {
- fillings[$1] || ""
- }
- text
-end
-
-fields = {
- 'username' => whats_his_name,
- 'count' => login_count,
- 'total' => minutes_used
-}
-puts templatefile('simple.template', fields)
-
-# @@INCOMPLETE@@
-# An example using databases is missing
-
-
diff --git a/tests/examplefiles/test.html b/tests/examplefiles/test.html
index 4527a3fb..52adca81 100644
--- a/tests/examplefiles/test.html
+++ b/tests/examplefiles/test.html
@@ -2783,3559 +2783,6 @@ pre.syntax { padding: 5px; margin-top: 0px; }
)
<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.i18n
- ~~~~~~~~~~~~~~~~~~~
-
- Pocoo internationalization components.
-
- :copyright: 2006 by Armin Ronacher.
- :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">gettext</span>
-<span class="kw">from </span><span class="cls">pocoo.application</span><span class="kw"> import</span> <span class="name">RequestWrapper</span>
-
-<span class="kw">from </span><span class="cls">jinja.nodes</span><span class="kw"> import</span> <span class="name">Node</span>, <span class="name">KeywordNode</span>, <span class="name">VariableNode</span>, <span class="name">ValueNode</span>, <span class="name">CollectionNode</span>
-<span class="kw">from </span><span class="cls">jinja.base</span><span class="kw"> import</span> <span class="name">TOKEN_TEXT</span>, <span class="name">TOKEN_VAR</span>
-
-<span class="kw">from </span><span class="cls">jinja.exceptions</span><span class="kw"> import</span> <span class="name">TemplateSyntaxError</span>
-<span class="kw">from </span><span class="cls">cStringIO</span><span class="kw"> import</span> <span class="name">StringIO</span>
-
-
-<span class="kw">class </span><span class="cls">TranslatableTag</span>(<span class="name">Node</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Translatable Tag
- ================
-
- Usage::
-
- {% trans %}
- somestring
- {% trans %}
-
- Or::
-
- {% trans &quot;string&quot; %}
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">rules</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">long</span><span class="st st-sg">&#39;</span>: [<span class="name">KeywordNode</span>(<span class="st st-sg">&#39;</span><span class="st">trans</span><span class="st st-sg">&#39;</span>)],
- <span class="st st-sg">&#39;</span><span class="st">plural</span><span class="st st-sg">&#39;</span>: [<span class="name">KeywordNode</span>(<span class="st st-sg">&#39;</span><span class="st">trans</span><span class="st st-sg">&#39;</span>), <span class="name">KeywordNode</span>(<span class="st st-sg">&#39;</span><span class="st">pluralizing</span><span class="st st-sg">&#39;</span>),
- <span class="name">VariableNode</span>()],
- <span class="st st-sg">&#39;</span><span class="st">short</span><span class="st st-sg">&#39;</span>: [<span class="name">KeywordNode</span>(<span class="st st-sg">&#39;</span><span class="st">trans</span><span class="st st-sg">&#39;</span>), <span class="name">ValueNode</span>(), <span class="name">CollectionNode</span>()]
- }
-
- <span class="kw">def </span><span class="fun">__init__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">parser</span>, <span class="name">matched_tag</span>, <span class="name">handler_args</span>, <span class="name">stack</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">_body_pl</span> <span class="op">=</span> []
- <span class="bn bn-pseudo">self</span>.<span class="name">_vars_pl</span> <span class="op">=</span> {}
- <span class="kw">if</span> <span class="name">matched_tag</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">short</span><span class="st st-sg">&#39;</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">_body_sg</span> <span class="op">=</span> [<span class="name">handler_args</span>[<span class="nb nb-int">1</span>].<span class="name">resolve</span>()]
- <span class="bn bn-pseudo">self</span>.<span class="name">_vars_sg</span> <span class="op">=</span> <span class="name">handler_args</span>[<span class="nb nb-int">2</span>]
- <span class="kw">else</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">_body_sg</span>, <span class="bn bn-pseudo">self</span>.<span class="name">_vars_sg</span>, <span class="bn bn-pseudo">self</span>.<span class="name">_body_pl</span>, <span class="bn bn-pseudo">self</span>.<span class="name">_vars_pl</span> <span class="op">=</span> \
- <span class="bn bn-pseudo">self</span>.<span class="name">_forkparse</span>(<span class="name">parser</span>)
- <span class="kw">if</span> <span class="name">matched_tag</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">plural</span><span class="st st-sg">&#39;</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">_indicator</span> <span class="op">=</span> <span class="name">handler_args</span>[<span class="nb nb-int">2</span>]
- <span class="bn bn-pseudo">self</span>.<span class="name">msgid</span> <span class="op">=</span> (<span class="st st-sg">&#39;&#39;</span>.<span class="name">join</span>(<span class="bn bn-pseudo">self</span>.<span class="name">_body_sg</span>)).<span class="name">strip</span>()
- <span class="bn bn-pseudo">self</span>.<span class="name">msgid_plural</span> <span class="op">=</span> (<span class="st st-sg">&#39;&#39;</span>.<span class="name">join</span>(<span class="bn bn-pseudo">self</span>.<span class="name">_body_pl</span>)).<span class="name">strip</span>()
- <span class="name">Node</span>.<span class="name">__init__</span>(<span class="bn bn-pseudo">self</span>)
-
- <span class="kw">def </span><span class="fun">_forkparse</span>(<span class="bn bn-pseudo">self</span>, <span class="name">parser</span>):
- <span class="name">lib</span> <span class="op">=</span> <span class="name">parser</span>.<span class="name">library</span>
-
- <span class="name">sg</span> <span class="op">=</span> []; <span class="name">vars_sg</span> <span class="op">=</span> {}
- <span class="name">pl</span> <span class="op">=</span> []; <span class="name">vars_pl</span> <span class="op">=</span> {}
- <span class="name">out</span> <span class="op">=</span> <span class="name">sg</span>; <span class="name">vars_out</span> <span class="op">=</span> <span class="name">vars_sg</span>
-
- <span class="kw">while</span> <span class="name">parser</span>.<span class="name">tokens</span>:
- <span class="name">token</span> <span class="op">=</span> <span class="name">parser</span>.<span class="name">pop_token</span>()
- <span class="kw">if</span> <span class="name">token</span>.<span class="name">token_type</span> <span class="op">==</span> <span class="name">TOKEN_VAR</span>:
- <span class="name">var</span> <span class="op">=</span> <span class="name">lib</span>.<span class="name">parse</span>(<span class="name">parser</span>, <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st">print </span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">token</span>.<span class="name">contents</span>)
- <span class="name">var_key</span> <span class="op">=</span> <span class="name">token</span>.<span class="name">contents</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">0</span>].<span class="name">strip</span>()
- <span class="name">vars_out</span>[<span class="name">var_key</span>] <span class="op">=</span> <span class="name">var</span>
-
- <span class="name">out</span>.<span class="name">append</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%%</span><span class="st">(</span><span class="st st-int">%s</span><span class="st">)s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">var_key</span>)
- <span class="kw">elif</span> <span class="name">token</span>.<span class="name">token_type</span> <span class="op">==</span> <span class="name">TOKEN_TEXT</span>:
- <span class="name">lines</span> <span class="op">=</span> <span class="name">token</span>.<span class="name">contents</span>.<span class="name">splitlines</span>()
- <span class="cm"># XXX: this protects whitespaces between different tokens (really?)</span>
-
- <span class="name">text</span> <span class="op">=</span> <span class="name">u</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="nb nb-int">1</span>] <span class="op">+</span> [<span class="name">line</span>.<span class="name">lstrip</span>() <span class="kw">for</span> <span class="name">line</span> <span class="op op-word">in</span> <span class="name">lines</span>[<span class="nb nb-int">1</span>:]])
- <span class="name">out</span>.<span class="name">append</span>(<span class="name">text</span>)
- <span class="kw">else</span>:
- <span class="kw">if</span> <span class="name">token</span>.<span class="name">contents</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">plural</span><span class="st st-sg">&#39;</span>:
- <span class="kw">if</span> <span class="name">out</span> <span class="op op-word">is</span> <span class="name">sg</span>:
- <span class="name">out</span> <span class="op">=</span> <span class="name">pl</span>
-
- <span class="name">vars_out</span> <span class="op">=</span> <span class="name">vars_pl</span>
- <span class="kw">else</span>:
- <span class="kw">raise</span> <span class="name">TemplateSyntaxError</span>(<span class="st st-sg">&#39;</span><span class="st">plural used twice</span><span class="st st-sg">&#39;</span>)
- <span class="kw">elif</span> <span class="name">token</span>.<span class="name">contents</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">endtrans</span><span class="st st-sg">&#39;</span>:
- <span class="kw">break</span>
-
- <span class="kw">else</span>:
- <span class="kw">raise</span> <span class="name">TemplateSyntaxError</span>(<span class="st st-sg">&#39;</span><span class="st">you can</span><span class="st st-esc">\&#39;</span><span class="st">t use blocks inside of a </span><span class="st st-sg">&#39;</span>
- <span class="st st-sg">&#39;</span><span class="st">`trans` tag.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">sg</span>, <span class="name">vars_sg</span>, <span class="name">pl</span>, <span class="name">vars_pl</span>
-
- <span class="kw">def </span><span class="fun">render</span>(<span class="bn bn-pseudo">self</span>, <span class="name">context</span>):
- <span class="name">req</span> <span class="op">=</span> <span class="name">context</span>[<span class="st st-sg">&#39;</span><span class="st">REQUEST</span><span class="st st-sg">&#39;</span>]
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">msgid_plural</span>:
- <span class="name">var</span> <span class="op">=</span> <span class="nb nb-int">1</span>
-
- <span class="kw">if</span> <span class="bn">hasattr</span>(<span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">_indicator</span><span class="st st-sg">&#39;</span>):
- <span class="name">var</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_indicator</span>.<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="name">rv</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>(<span class="bn bn-pseudo">self</span>.<span class="name">msgid</span>, <span class="bn bn-pseudo">self</span>.<span class="name">msgid_plural</span>, <span class="name">var</span>)
- <span class="kw">else</span>:
- <span class="name">rv</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>(<span class="bn bn-pseudo">self</span>.<span class="name">msgid</span>)
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="bn bn-pseudo">self</span>.<span class="name">_vars_sg</span>, <span class="bn">list</span>):
- <span class="kw">return</span> <span class="name">rv</span> <span class="op">%</span> <span class="bn">tuple</span>(<span class="name">v</span>.<span class="name">render</span>(<span class="name">context</span>) <span class="kw">for</span> <span class="name">v</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">_vars_sg</span>)
- <span class="name">args</span> <span class="op">=</span> <span class="bn">dict</span>((<span class="name">n</span>, <span class="name">v</span>.<span class="name">render</span>(<span class="name">context</span>)) <span class="kw">for</span> <span class="name">n</span>, <span class="name">v</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">_vars_sg</span>.<span class="name">iteritems</span>())
- <span class="name">args</span>.<span class="name">update</span>(<span class="bn bn-pseudo">self</span>.<span class="name">_vars_pl</span>)
- <span class="kw">return</span> <span class="name">rv</span> <span class="op">%</span> <span class="name">args</span>
-
-
-<span class="kw">def </span><span class="fun">load_translations</span>(<span class="name">ctx</span>, <span class="name">lng</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- loads all available translations for the given language.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">result</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">res</span> <span class="op op-word">in</span> <span class="name">ctx</span>.<span class="name">pkgmanager</span>.<span class="name">get_resources</span>(<span class="st st-sg">&#39;</span><span class="st">i18n</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;&#39;</span>, <span class="name">lng</span>):
- <span class="name">f</span> <span class="op">=</span> <span class="name">StringIO</span>(<span class="name">res</span>)
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">gettext</span>.<span class="name">GNUTranslations</span>(<span class="name">f</span>))
- <span class="kw">return</span> <span class="name">result</span>
-
-
-<span class="kw">def </span><span class="fun">parse_http_accept_language</span>(<span class="name">s</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the accepted languages as set in the user browser.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">result</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">item</span> <span class="op op-word">in</span> <span class="name">s</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="name">lng</span> <span class="op">=</span> <span class="name">item</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="nb nb-int">0</span>]
- <span class="name">lng</span> <span class="op">=</span> <span class="name">lng</span>.<span class="name">lower</span>()
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">lng</span>)
- <span class="kw">if</span> <span class="st st-sg">&#39;</span><span class="st">-</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">lng</span>:
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">lng</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">0</span>])
- <span class="kw">return</span> <span class="name">result</span>
-
-
-<span class="kw">def </span><span class="fun">get_request_languages</span>(<span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the list of languages a request could handle.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">if</span> <span class="bn">hasattr</span>(<span class="name">req</span>, <span class="st st-sg">&#39;</span><span class="st">user</span><span class="st st-sg">&#39;</span>) <span class="op op-word">and</span> <span class="name">req</span>.<span class="name">user</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">req</span>.<span class="name">user</span>.<span class="name">language</span>:
- <span class="name">lng</span> <span class="op">=</span> [<span class="name">req</span>.<span class="name">user</span>.<span class="name">language</span>]
- <span class="kw">else</span>:
- <span class="name">lng</span> <span class="op">=</span> []
- <span class="cm"># before checking the HTTP_ACCEPT_LANGUAGE check for</span>
-
- <span class="cm"># a forced language.</span>
- <span class="name">forced</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">general</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">language</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;&#39;</span>)
- <span class="kw">if</span> <span class="name">forced</span> <span class="op op-word">and</span> <span class="name">forced</span> <span class="op">!=</span> <span class="st st-sg">&#39;</span><span class="st">auto</span><span class="st st-sg">&#39;</span> <span class="op op-word">and</span> <span class="name">forced</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="name">lng</span>:
- <span class="name">lng</span>.<span class="name">append</span>(<span class="name">forced</span>)
- <span class="cm"># now prase the HTTP_ACCEPT_LANGUAGE string and add</span>
-
- <span class="cm"># the languages to the list of accepted languages.</span>
- <span class="name">language_string</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">environ</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">HTTP_ACCEPT_LANGUAGE</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">en</span><span class="st st-sg">&#39;</span>)
- <span class="kw">for</span> <span class="name">item</span> <span class="op op-word">in</span> <span class="name">parse_http_accept_language</span>(<span class="name">language_string</span>):
- <span class="kw">if</span> <span class="name">item</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="name">lng</span>:
- <span class="name">lng</span>.<span class="name">append</span>(<span class="name">item</span>)
- <span class="cm"># add &quot;en&quot; if not set</span>
-
- <span class="kw">if</span> <span class="st st-sg">&#39;</span><span class="st">en</span><span class="st st-sg">&#39;</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="name">lng</span>:
- <span class="name">lng</span>.<span class="name">append</span>(<span class="st st-sg">&#39;</span><span class="st">en</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">lng</span>
-
-
-<span class="kw">class </span><span class="cls">Translator</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- A callable that allows you to use pluralized and
- non pluralized strings. A translator instance always
- exists on the request object as ``req.gettext``::
-
- _ = req.gettext
- _(&#39;Hello World!&#39;, &#39;Hello Worlds!&#39;, 2)
-
- The example above defines a singular and pluralized
- version of &quot;Hello World&quot;. The number two tells the
- gettext system that we have two worlds in that case.
- Some languages provide more than just one plural form
- so this number allows it to decide which plural form
- to use.
-
- If you just have a singular string you can use this::
-
- _ = req.gettext
- _(&#39;This is just a small example&#39;)
-
- Strings marked as ``_()`` automagically get tracked
- by the gettext translation generator script.
- </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">translations</span>, <span class="name">languages</span>):
- <span class="cm">#XXX: should we cache that?</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">translator</span> <span class="op">=</span> <span class="name">gettext</span>.<span class="name">NullTranslations</span>()
- <span class="kw">for</span> <span class="name">lng</span> <span class="op op-word">in</span> <span class="name">languages</span>:
- <span class="kw">for</span> <span class="name">translation</span> <span class="op op-word">in</span> <span class="name">translations</span>[<span class="name">lng</span>]:
- <span class="bn bn-pseudo">self</span>.<span class="name">translator</span>.<span class="name">add_fallback</span>(<span class="name">translation</span>)
- <span class="bn bn-pseudo">self</span>.<span class="name">languages</span> <span class="op">=</span> <span class="name">languages</span>
-
- <span class="kw">def </span><span class="fun">__call__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">msg</span>, <span class="name">plural</span><span class="op">=</span><span class="bn bn-pseudo">None</span>, <span class="name">n</span><span class="op">=</span><span class="nb nb-int">1</span>):
- <span class="kw">if</span> <span class="name">plural</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">translator</span>.<span class="name">ugettext</span>(<span class="name">msg</span>)
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">translator</span>.<span class="name">ungettext</span>(<span class="name">msg</span>, <span class="name">plural</span>, <span class="name">n</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">%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">languages</span>
-
- )
-
-
-<span class="name">dummy_translate</span> <span class="op">=</span> <span class="name">Translator</span>({}, [])
-
-
-<span class="kw">class </span><span class="cls">I18nWrapper</span>(<span class="name">RequestWrapper</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="bn">super</span>(<span class="name">I18nWrapper</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">ctx</span>)
- <span class="bn bn-pseudo">self</span>.<span class="name">translations</span> <span class="op">=</span> {}
-
- <span class="kw">def </span><span class="fun">get_priority</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="nb nb-int">4</span>
-
- <span class="kw">def </span><span class="fun">process_request</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Attach a gettext and dummy translate method to the request.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">languages</span> <span class="op">=</span> <span class="name">get_request_languages</span>(<span class="name">req</span>)
- <span class="name">req</span>.<span class="name">accept_languages</span> <span class="op">=</span> <span class="name">languages</span>
-
- <span class="kw">for</span> <span class="name">lng</span> <span class="op op-word">in</span> <span class="name">languages</span>:
- <span class="kw">if</span> <span class="name">lng</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">translations</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">translations</span>[<span class="name">lng</span>] <span class="op">=</span> <span class="name">load_translations</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">lng</span>)
- <span class="name">req</span>.<span class="name">gettext</span> <span class="op">=</span> <span class="name">Translator</span>(<span class="bn bn-pseudo">self</span>.<span class="name">translations</span>, <span class="name">languages</span>)
- <span class="name">req</span>.<span class="name">dummy_translate</span> <span class="op">=</span> <span class="name">dummy_translate</span>
-
- <span class="kw">def </span><span class="fun">process_response</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">resp</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
- ~~~~~~~~~~~~~~
-
- The Pocoo core component.
-
- :copyright: 2006 by the Pocoo team.
- :license: GNU GPL, see LICENSE for more details.
-</span><span class="st st-db">&quot;&quot;&quot;</span>
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.l10n
- ~~~~~~~~~~~~~~~~~~~
-
- Pocoo localisation module.
-
- :copyright: 2006 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.utils.text</span><span class="kw"> import</span> <span class="name">split_format</span>
-
-<span class="kw">from </span><span class="cls">datetime</span><span class="kw"> import</span> <span class="name">datetime</span>
-<span class="kw">import </span><span class="cls">time</span>
-<span class="kw">from </span><span class="cls">calendar</span><span class="kw"> import</span> <span class="name">monthrange</span>
-
-<span class="cm"># Dateformat Constants</span>
-<span class="name">DEFAULT_DATE_FORMAT</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">%a, </span><span class="st st-int">%d</span><span class="st"> %b %Y</span><span class="st st-sg">&#39;</span>
-<span class="name">DEFAULT_TIME_FORMAT</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">%H:%M</span><span class="st st-sg">&#39;</span>
-
-<span class="name">DEFAULT_DATETIME_FORMAT</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">%a, </span><span class="st st-int">%d</span><span class="st"> %b %Y %H:%M</span><span class="st st-sg">&#39;</span>
-
-<span class="cm"># Timedelta Constants</span>
-<span class="name">TIME_DELTA_UNITS</span> <span class="op">=</span> [
- (<span class="nb nb-int">3600</span> <span class="op">*</span> <span class="nb nb-int">24</span> <span class="op">*</span> <span class="nb nb-int">365</span>, <span class="st st-sg">&#39;</span><span class="st">y</span><span class="st st-sg">&#39;</span>),
- (<span class="nb nb-int">3600</span> <span class="op">*</span> <span class="nb nb-int">24</span> <span class="op">*</span> <span class="nb nb-int">30</span>, <span class="st st-sg">&#39;</span><span class="st">M</span><span class="st st-sg">&#39;</span>),
- (<span class="nb nb-int">3600</span> <span class="op">*</span> <span class="nb nb-int">24</span> <span class="op">*</span> <span class="nb nb-int">7</span>, <span class="st st-sg">&#39;</span><span class="st">w</span><span class="st st-sg">&#39;</span>),
- (<span class="nb nb-int">3600</span> <span class="op">*</span> <span class="nb nb-int">24</span>, <span class="st st-sg">&#39;</span><span class="st">d</span><span class="st st-sg">&#39;</span>),
- (<span class="nb nb-int">3600</span>, <span class="st st-sg">&#39;</span><span class="st">h</span><span class="st st-sg">&#39;</span>),
- (<span class="nb nb-int">60</span>, <span class="st st-sg">&#39;</span><span class="st">m</span><span class="st st-sg">&#39;</span>)
-]
-
-
-<span class="cm"># Gettext Helper</span>
-<span class="name">_</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">x</span>: <span class="name">x</span>
-
-<span class="kw">class </span><span class="cls">DateFormatter</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- TODO: write documentation about the various format codes.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="cm"># XXX: use &quot;caching&quot; of lists with static strings (weekdays...)</span>
-
- <span class="cm"># allow format_X method names</span>
- <span class="cm"># pylint: disable-msg=C0103</span>
-
- <span class="name">WEEKDAYS_ABBR</span> <span class="op">=</span> [<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Mon</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Tue</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Wed</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Thu</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Fri</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Sat</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Sun</span><span class="st st-sg">&#39;</span>)]
- <span class="name">WEEKDAYS_FULL</span> <span class="op">=</span> [<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Monday</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Tuesday</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Wednesday</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Thursday</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Friday</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Saturday</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Sunday</span><span class="st st-sg">&#39;</span>)]
- <span class="name">MONTHS_ABBR</span> <span class="op">=</span> [<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Jan</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Feb</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Mar</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Apr</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">May:abbr</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Jun</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Jul</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Aug</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Sep</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Oct</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Nov</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Dec</span><span class="st st-sg">&#39;</span>)]
- <span class="name">MONTHS_FULL</span> <span class="op">=</span> [<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">January</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">February</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">March</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">April</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">May:full</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">June</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">July</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">August</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">September</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">October</span><span class="st st-sg">&#39;</span>), <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">November</span><span class="st st-sg">&#39;</span>),
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">December</span><span class="st st-sg">&#39;</span>)]
-
- <span class="kw">def </span><span class="fun">__init__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">dateobj</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">req</span> <span class="op">=</span> <span class="name">req</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">dateobj</span>, <span class="name">datetime</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">date</span> <span class="op">=</span> <span class="name">dateobj</span>
-
- <span class="kw">elif</span> <span class="bn">isinstance</span>(<span class="name">dateobj</span>, <span class="bn">int</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">date</span> <span class="op">=</span> <span class="name">datetime</span>.<span class="name">utcfromtimestamp</span>(<span class="name">dateobj</span>)
- <span class="kw">elif</span> <span class="bn">isinstance</span>(<span class="name">dateobj</span>, <span class="name">time</span>.<span class="name">struct_time</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">date</span> <span class="op">=</span> <span class="name">datetime</span>(<span class="name">dateobj</span>[:<span class="nb nb-int">7</span>])
- <span class="kw">elif</span> <span class="name">dateobj</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">date</span> <span class="op">=</span> <span class="name">datetime</span>(<span class="nb nb-int">1</span>, <span class="nb nb-int">1</span>, <span class="nb nb-int">1</span>)
- <span class="kw">else</span>:
- <span class="kw">raise</span> <span class="exc">TypeError</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%r</span><span class="st"> is not a valid time object</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">dateobj</span>)
-
- <span class="kw">def </span><span class="fun">format</span>(<span class="bn bn-pseudo">self</span>, <span class="name">formatstring</span>):
- <span class="name">bits</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">bit</span> <span class="op op-word">in</span> <span class="name">split_format</span>(<span class="name">formatstring</span>):
- <span class="kw">if</span> <span class="name">bit</span>.<span class="name">startswith</span>(<span class="st st-sg">&#39;</span><span class="st">%</span><span class="st st-sg">&#39;</span>):
- <span class="name">handler</span> <span class="op">=</span> <span class="bn">getattr</span>(<span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">format_</span><span class="st st-sg">&#39;</span> <span class="op">+</span> <span class="name">bit</span>[<span class="nb nb-int">1</span>], <span class="bn bn-pseudo">None</span>)
- <span class="kw">if</span> <span class="name">handler</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">bits</span>.<span class="name">append</span>(<span class="name">handler</span>())
- <span class="kw">else</span>:
- <span class="name">bits</span>.<span class="name">append</span>(<span class="name">bit</span>)
- <span class="kw">else</span>:
- <span class="name">bits</span>.<span class="name">append</span>(<span class="name">bit</span>)
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>.<span class="name">join</span>(<span class="name">bits</span>)
-
- <span class="kw">def </span><span class="fun">format_a</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">abbreviated weekday name.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="bn bn-pseudo">self</span>.<span class="name">WEEKDAYS_ABBR</span>[<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">weekday</span>()])
-
- <span class="kw">def </span><span class="fun">format_A</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">full weekday name.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="bn bn-pseudo">self</span>.<span class="name">WEEKDAYS_FULL</span>[<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">weekday</span>()])
-
- <span class="kw">def </span><span class="fun">format_b</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">abbreviated month name.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="bn bn-pseudo">self</span>.<span class="name">MONTHS_ABBR</span>[<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">month</span> <span class="op">-</span> <span class="nb nb-int">1</span>])
-
- <span class="kw">def </span><span class="fun">format_B</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">full month name.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="bn bn-pseudo">self</span>.<span class="name">MONTHS_FULL</span>[<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">month</span> <span class="op">-</span> <span class="nb nb-int">1</span>])
-
- <span class="kw">def </span><span class="fun">format_d</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Day of the month as a decimal number [01,31].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">day</span>)
-
- <span class="kw">def </span><span class="fun">format_H</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Hour (24-hour clock) as a decimal number [00,23].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">hour</span>)
-
- <span class="kw">def </span><span class="fun">format_I</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Hour (12-hour clock) as a decimal number [01,12].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">hour</span> <span class="op">%</span> <span class="nb nb-int">12</span>)
-
- <span class="kw">def </span><span class="fun">format_j</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Day of the year as a decimal number [001,366].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%j</span><span class="st st-sg">&#39;</span>))
-
- <span class="kw">def </span><span class="fun">format_J</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Day of the year as decimal number [1,366].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn">int</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%j</span><span class="st st-sg">&#39;</span>)))
-
- <span class="kw">def </span><span class="fun">format_m</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Month as a decimal number [01,12].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st st-int">%02d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">month</span>
-
- <span class="kw">def </span><span class="fun">format_n</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Month as a decimal number [1,12].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">month</span>)
-
- <span class="kw">def </span><span class="fun">format_M</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Minute as a decimal number [00,59].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st st-int">%02d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">minute</span>
-
- <span class="kw">def </span><span class="fun">format_N</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Minute as a decimal number [0,59].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">minute</span>)
-
- <span class="kw">def </span><span class="fun">format_p</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Locale&#39;s equivalent of either AM or PM.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">hour</span> <span class="op">&gt;</span> <span class="nb nb-int">11</span>:
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">PM</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">AM</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">format_P</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Locale&#39;s equivalent of either a.m. or p.m.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">hour</span> <span class="op">&gt;</span> <span class="nb nb-int">11</span>:
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">p.m.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">a.m.</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">format_s</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Second as a decimal number [0,61].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">second</span>)
-
- <span class="kw">def </span><span class="fun">format_S</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Second as a decimal number [00,61].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st st-int">%02d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">second</span>
-
- <span class="kw">def </span><span class="fun">format_U</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Week number of the year (Sunday as the first day of the week)
- as a decimal number [00,53]. All days in a new year preceding the
- first Sunday are considered to be in week 0.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%U</span><span class="st st-sg">&#39;</span>))
-
- <span class="kw">def </span><span class="fun">format_u</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Week number of the year (Sunday as the first day of the week)
- as a decimal number [0,53]. All days in a new year preceding the
- first Sunday are considered to be in week 0.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn">int</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%U</span><span class="st st-sg">&#39;</span>)))
-
- <span class="kw">def </span><span class="fun">format_w</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Weekday as a decimal number [0(Sunday),6].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%w</span><span class="st st-sg">&#39;</span>))
-
- <span class="kw">def </span><span class="fun">format_z</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Weekday as a decimal number [0(Monday),6].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="cm">#XXX: anyone something better than z?</span>
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">weekday</span>)
-
- <span class="kw">def </span><span class="fun">format_W</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Week number of the year (Monday as the first day of the week)
- as a decimal number [00,53]. All days in a new year preceding the
- first Monday are considered to be in week 0.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%W</span><span class="st st-sg">&#39;</span>))
-
- <span class="kw">def </span><span class="fun">format_v</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Week number of the year (Monday as the first day of the week)
- as a decimal number [0,53]. All days in a new year preceding the
- first Monday are considered to be in week 0.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn">int</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%W</span><span class="st st-sg">&#39;</span>)))
-
- <span class="kw">def </span><span class="fun">format_y</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Year without century as a decimal number [00,99].</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">strftime</span>(<span class="st st-sg">&#39;</span><span class="st">%y</span><span class="st st-sg">&#39;</span>))
-
- <span class="kw">def </span><span class="fun">format_Y</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Year with century as a decimal number.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">unicode</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">year</span>)
-
- <span class="kw">def </span><span class="fun">format_r</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">English ordinal suffix for the day of the month, 2 characters;
- i.e. &#39;st&#39;, &#39;nd&#39;, &#39;rd&#39; or &#39;th&#39;</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">gettext</span>
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">day</span> <span class="op op-word">in</span> (<span class="nb nb-int">11</span>, <span class="nb nb-int">12</span>, <span class="nb nb-int">13</span>):
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">th</span><span class="st st-sg">&#39;</span>)
- <span class="name">last</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">day</span> <span class="op">%</span> <span class="nb nb-int">10</span>
-
- <span class="kw">if</span> <span class="name">last</span> <span class="op">==</span> <span class="nb nb-int">1</span>:
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">st</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">last</span> <span class="op">==</span> <span class="nb nb-int">2</span>:
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">nd</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">last</span> <span class="op">==</span> <span class="nb nb-int">3</span>:
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">rd</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">th</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">format_t</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Number of days in the given month; i.e. &#39;28&#39; to &#39;31&#39;</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st st-int">%02d</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">monthrange</span>(<span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">year</span>, <span class="bn bn-pseudo">self</span>.<span class="name">date</span>.<span class="name">month</span>)[<span class="nb nb-int">1</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">%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="st st-sg">&#39;</span><span class="st">, </span><span class="st st-sg">&#39;</span>.<span class="name">join</span>(<span class="bn">str</span>(<span class="name">i</span>[<span class="nb nb-int">7</span>:]) <span class="kw">for</span> <span class="name">i</span> <span class="op op-word">in</span> <span class="bn">dir</span>(<span class="bn bn-pseudo">self</span>) <span class="kw">if</span> <span class="name">i</span>.<span class="name">startswith</span>(<span class="st st-sg">&#39;</span><span class="st">format_</span><span class="st st-sg">&#39;</span>))
- )
-
-
-
-<span class="kw">def </span><span class="fun">format_timedelta</span>(<span class="name">req</span>, <span class="name">time1</span><span class="op">=</span><span class="bn bn-pseudo">None</span>, <span class="name">time2</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Format the difference between two datetime or unix timestamp objects::
-
- &gt;&gt;&gt; from pocoo.pkg.core.l10n import timedeltaformat
- &gt;&gt;&gt; now = datetime.now()
- &gt;&gt;&gt; timedeltaformat(req, now)
- u&#39;6 seconds ago&#39;
-
- </span><span class="st st-db">&quot;&quot;&quot;</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">time1</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">time1</span> <span class="op">=</span> <span class="name">datetime</span>.<span class="name">utcnow</span>()
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">time1</span>, <span class="name">datetime</span>):
- <span class="name">time1</span> <span class="op">=</span> <span class="name">time</span>.<span class="name">mktime</span>(<span class="name">time1</span>.<span class="name">timetuple</span>()) <span class="op">+</span> <span class="name">time1</span>.<span class="name">microsecond</span> <span class="op">/</span> <span class="nb nb-int">1</span><span class="name">e6</span>
-
- <span class="kw">if</span> <span class="name">time2</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">time2</span> <span class="op">=</span> <span class="name">datetime</span>.<span class="name">utcnow</span>()
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">time2</span>, <span class="name">datetime</span>):
- <span class="name">time2</span> <span class="op">=</span> <span class="name">time</span>.<span class="name">mktime</span>(<span class="name">time2</span>.<span class="name">timetuple</span>()) <span class="op">+</span> <span class="name">time2</span>.<span class="name">microsecond</span> <span class="op">/</span> <span class="nb nb-int">1</span><span class="name">e6</span>
-
- <span class="kw">if</span> <span class="name">time1</span> <span class="op">&gt;</span> <span class="name">time2</span>:
- <span class="name">tmpl</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%d</span><span class="st"> </span><span class="st st-int">%s</span><span class="st"> in the future</span><span class="st st-sg">&#39;</span>)
- <span class="kw">else</span>:
- <span class="name">tmpl</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%d</span><span class="st"> </span><span class="st st-int">%s</span><span class="st"> ago</span><span class="st st-sg">&#39;</span>)
- <span class="kw">def </span><span class="fun">trans</span>(<span class="name">s</span>, <span class="name">entity</span>):
- <span class="kw">if</span> <span class="name">entity</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">s</span><span class="st st-sg">&#39;</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">second</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">seconds</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">elif</span> <span class="name">entity</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">m</span><span class="st st-sg">&#39;</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">minute</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">minutes</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">elif</span> <span class="name">entity</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">h</span><span class="st st-sg">&#39;</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">hour</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">hours</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">elif</span> <span class="name">entity</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">d</span><span class="st st-sg">&#39;</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">day</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">days</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">elif</span> <span class="name">entity</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">w</span><span class="st st-sg">&#39;</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">week</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">weeks</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">elif</span> <span class="name">entity</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">M</span><span class="st st-sg">&#39;</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">month</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">months</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">else</span>:
- <span class="name">e</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">year</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">years</span><span class="st st-sg">&#39;</span>, <span class="name">s</span>)
- <span class="kw">return</span> <span class="name">tmpl</span> <span class="op">%</span> (<span class="name">s</span>, <span class="name">e</span>)
- <span class="name">diff</span> <span class="op">=</span> <span class="bn">abs</span>(<span class="bn">int</span>(<span class="name">time2</span> <span class="op">-</span> <span class="name">time1</span>))
- <span class="kw">for</span> <span class="name">u</span>, <span class="name">e</span> <span class="op op-word">in</span> <span class="name">TIME_DELTA_UNITS</span>:
- <span class="name">r</span> <span class="op">=</span> <span class="name">diff</span> <span class="op">/</span> <span class="bn">float</span>(<span class="name">u</span>)
- <span class="kw">if</span> <span class="name">r</span> <span class="op">&gt;=</span> <span class="nb nb-flt">0.9</span>:
- <span class="name">s</span> <span class="op">=</span> <span class="bn">int</span>(<span class="bn">round</span>(<span class="name">r</span>))
- <span class="kw">return</span> <span class="name">trans</span>(<span class="name">s</span>, <span class="name">e</span>)
- <span class="kw">return</span> <span class="name">trans</span>(<span class="name">diff</span>, <span class="st st-sg">&#39;</span><span class="st">s</span><span class="st st-sg">&#39;</span>)
-
-
-
-<span class="kw">def </span><span class="fun">dateformat</span>(<span class="name">date</span>, <span class="name">context</span>):
- <span class="cm">#XXX: load default string from i10n language file</span>
- <span class="name">req</span> <span class="op">=</span> <span class="name">context</span>[<span class="st st-sg">&#39;</span><span class="st">REQUEST</span><span class="st st-sg">&#39;</span>]
- <span class="name">formatstr</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">dateformat</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">formatstr</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">formatstr</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">general</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">dateformat</span><span class="st st-sg">&#39;</span>,
- <span class="name">DEFAULT_DATE_FORMAT</span>)
- <span class="name">f</span> <span class="op">=</span> <span class="name">DateFormatter</span>(<span class="name">req</span>, <span class="name">date</span> <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>)
- <span class="kw">return</span> <span class="name">f</span>.<span class="name">format</span>(<span class="name">formatstr</span>)
-
-
-
-<span class="kw">def </span><span class="fun">timeformat</span>(<span class="name">date</span>, <span class="name">context</span>):
- <span class="cm">#XXX: load default string from l10n language file</span>
- <span class="name">req</span> <span class="op">=</span> <span class="name">context</span>[<span class="st st-sg">&#39;</span><span class="st">REQUEST</span><span class="st st-sg">&#39;</span>]
- <span class="name">formatstr</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">timeformat</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">formatstr</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">formatstr</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">general</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">timeformat</span><span class="st st-sg">&#39;</span>,
- <span class="name">DEFAULT_TIME_FORMAT</span>)
- <span class="name">f</span> <span class="op">=</span> <span class="name">DateFormatter</span>(<span class="name">req</span>, <span class="name">date</span> <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>)
- <span class="kw">return</span> <span class="name">f</span>.<span class="name">format</span>(<span class="name">formatstr</span>)
-
-
-
-<span class="kw">def </span><span class="fun">datetimeformat</span>(<span class="name">date</span>, <span class="name">context</span>):
- <span class="cm">#XXX: load default string from l10n language file</span>
- <span class="name">req</span> <span class="op">=</span> <span class="name">context</span>[<span class="st st-sg">&#39;</span><span class="st">REQUEST</span><span class="st st-sg">&#39;</span>]
- <span class="name">formatstr</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">datetimeformat</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">formatstr</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">formatstr</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">general</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">datetimeformat</span><span class="st st-sg">&#39;</span>,
- <span class="name">DEFAULT_DATETIME_FORMAT</span>)
- <span class="name">f</span> <span class="op">=</span> <span class="name">DateFormatter</span>(<span class="name">req</span>, <span class="name">date</span> <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>)
- <span class="kw">return</span> <span class="name">f</span>.<span class="name">format</span>(<span class="name">formatstr</span>)
-
-
-
-<span class="kw">def </span><span class="fun">timedeltaformat</span>(<span class="name">date</span>, <span class="name">context</span>, <span class="name">obj2</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="name">req</span> <span class="op">=</span> <span class="name">context</span>[<span class="st st-sg">&#39;</span><span class="st">REQUEST</span><span class="st st-sg">&#39;</span>]
- <span class="kw">return</span> <span class="name">format_timedelta</span>(<span class="name">req</span>, <span class="name">date</span> <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>, <span class="name">obj2</span> <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>)
-
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.pages
- ~~~~~~~~~~~~~~~~~~~~
-
- Pocoo core pages.
-
- :copyright: 2006 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">pocoo.http</span><span class="kw"> import</span> <span class="name">Response</span>, <span class="name">HttpRedirect</span>, <span class="name">TemplateResponse</span>, \
- <span class="name">AccessDeniedResponse</span>, <span class="name">PageNotFound</span>
-
-<span class="kw">from </span><span class="cls">pocoo.settings</span><span class="kw"> import</span> <span class="name">cfg</span>
-<span class="kw">from </span><span class="cls">pocoo.template</span><span class="kw"> import</span> <span class="name">PagePublisher</span>, <span class="name">render_template</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.utils.mail</span><span class="kw"> import</span> <span class="name">Email</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.net</span><span class="kw"> import</span> <span class="name">make_url_context_external</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.form</span><span class="kw"> import</span> <span class="name">Form</span>, <span class="name">TextField</span>, <span class="name">TextArea</span>, <span class="name">SelectBox</span>, <span class="name">CheckBox</span>
-
-<span class="kw">from </span><span class="cls">pocoo.utils.validators</span><span class="kw"> import</span> <span class="name">isNotEmpty</span>, <span class="name">isSameValue</span>, <span class="name">isEmail</span>, \
- <span class="name">checkTextLength</span>, <span class="name">isOneLetter</span>, <span class="name">mayEmpty</span>, <span class="name">coppaIsChecked</span>
-
-<span class="kw">from </span><span class="cls">pocoo.utils.json</span><span class="kw"> import</span> <span class="name">parse_datetime</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.remotecall</span><span class="kw"> import</span> <span class="name">RemoteCallable</span>, <span class="name">export</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.validators</span><span class="kw"> import</span> <span class="name">isAvailableUsername</span>, <span class="name">isStrongPassword</span>, \
- <span class="name">isExistingUsername</span>, <span class="name">isAnonymousUsername</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.usersettings</span><span class="kw"> import</span> <span class="name">UserSettingsPage</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.db</span><span class="kw"> import</span> <span class="name">users</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.forum</span><span class="kw"> import</span> <span class="name">get_forum_index</span>, <span class="name">get_forum</span>, <span class="name">get_post_tree</span>, \
- <span class="name">get_forum_pathbar</span>, <span class="name">get_view_mode</span>, <span class="name">get_flat_view</span>, <span class="name">quote_post</span>, <span class="name">edit_post</span>, \
- <span class="name">get_post</span>, <span class="name">Thread</span>, <span class="name">get_last_posts</span>, <span class="name">get_last_thread_change</span>, <span class="name">get_post_pathbar</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="name">get_user_list</span>, \
- <span class="name">get_user</span>, <span class="name">get_user_avatar</span>, <span class="name">reset_password</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.session</span><span class="kw"> import</span> <span class="name">get_active_sessions</span>, <span class="name">get_sessions_by_action</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">get_editor</span>
-
-<span class="name">_</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">x</span>: <span class="name">x</span>
-
-
-<span class="kw">class </span><span class="cls">IndexPage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>, <span class="name">RemoteCallable</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">index</span><span class="st st-sg">&#39;</span>
-
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;&#39;</span>
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="name">u</span><span class="st st-sg">&#39;</span><span class="st">$</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">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">index.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">categories</span><span class="op">=</span><span class="name">get_forum_index</span>(<span class="name">req</span>),
- <span class="name">feed_url</span><span class="op">=</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/recent.xml</span><span class="st st-sg">&#39;</span>)
- )
-
-
-
-<span class="kw">class </span><span class="cls">ForumPage</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">forum/(?P&lt;forum_id&gt;\d+)$</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">forum_id</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">try</span>:
- <span class="name">page</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">req</span>.<span class="name">args</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">page</span><span class="st st-sg">&#39;</span>))
- <span class="kw">except</span> (<span class="exc">TypeError</span>, <span class="exc">ValueError</span>):
- <span class="name">page</span> <span class="op">=</span> <span class="nb nb-int">1</span>
-
- <span class="name">forum</span> <span class="op">=</span> <span class="name">get_forum</span>(<span class="name">req</span>, <span class="name">forum_id</span>, <span class="name">page</span>)
- <span class="kw">if</span> <span class="name">forum</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="cm"># Redirect if the forum is a link</span>
-
- <span class="kw">if</span> <span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">is_external_url</span><span class="st st-sg">&#39;</span>]:
- <span class="kw">return</span> <span class="name">HttpRedirect</span>(<span class="name">forum</span>[<span class="st st-sg">&#39;</span><span class="st">link</span><span class="st st-sg">&#39;</span>], <span class="name">local</span><span class="op">=</span><span class="bn bn-pseudo">False</span>)
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">viewforum.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">forum</span><span class="op">=</span><span class="name">forum</span>,
- <span class="name">pathbar</span><span class="op">=</span><span class="name">get_forum_pathbar</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">forum_id</span>),
- <span class="name">feed_url</span><span class="op">=</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/forum/</span><span class="st st-int">%d</span><span class="st">.xml</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">forum_id</span>)
- )
-
-
-
-<span class="kw">class </span><span class="cls">PostPage</span>(<span class="name">RequestHandler</span>, <span class="name">RemoteCallable</span>):
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">r&#39;</span><span class="st">post/(?P&lt;post_id&gt;\d+)$</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">post_id</span>):
- <span class="name">view</span> <span class="op">=</span> <span class="name">get_view_mode</span>(<span class="name">req</span>)
- <span class="kw">if</span> <span class="name">view</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">flat</span><span class="st st-sg">&#39;</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">_flat_view</span>(<span class="name">req</span>, <span class="bn">int</span>(<span class="name">post_id</span>))
- <span class="kw">else</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">_threaded_view</span>(<span class="name">req</span>, <span class="bn">int</span>(<span class="name">post_id</span>))
-
- <span class="kw">def </span><span class="fun">_flat_view</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">post_id</span>):
- <span class="name">topic</span> <span class="op">=</span> <span class="name">get_flat_view</span>(<span class="name">req</span>, <span class="name">post_id</span>)
- <span class="kw">if</span> <span class="name">topic</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">viewtopic.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">topic</span><span class="op">=</span><span class="name">topic</span>,
- <span class="name">pathbar</span><span class="op">=</span><span class="name">get_post_pathbar</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">topic</span>[<span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>][<span class="nb nb-int">0</span>][<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>]),
- <span class="name">feed_url</span><span class="op">=</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/thread/</span><span class="st st-int">%d</span><span class="st">.xml</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">post_id</span>)
- )
-
- <span class="kw">def </span><span class="fun">_threaded_view</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">post_id</span>):
- <span class="name">thread</span> <span class="op">=</span> <span class="name">get_post_tree</span>(<span class="name">req</span>, <span class="name">post_id</span>)
- <span class="kw">if</span> <span class="name">thread</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">viewthread.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">thread</span><span class="op">=</span><span class="name">thread</span>,
- <span class="name">pathbar</span><span class="op">=</span><span class="name">get_post_pathbar</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">thread</span>[<span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>][<span class="nb nb-int">0</span>][<span class="st st-sg">&#39;</span><span class="st">post_id</span><span class="st st-sg">&#39;</span>]),
- <span class="name">feed_url</span><span class="op">=</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/thread/</span><span class="st st-int">%d</span><span class="st">.xml</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">post_id</span>)
- )
-
- <span class="deco">@export</span>(<span class="st st-sg">&#39;</span><span class="st">thread.get_post</span><span class="st st-sg">&#39;</span>)
- <span class="kw">def </span><span class="fun">_get_post</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">post_id</span>):
- <span class="name">post</span> <span class="op">=</span> <span class="name">get_post</span>(<span class="name">req</span>, <span class="name">post_id</span>)
- <span class="kw">if</span> <span class="name">post</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">render_template</span>(<span class="name">req</span>, <span class="st st-sg">&#39;</span><span class="st">partial/post.html</span><span class="st st-sg">&#39;</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="deco">@export</span>(<span class="st st-sg">&#39;</span><span class="st">thread.tree_requires_update</span><span class="st st-sg">&#39;</span>)
- <span class="kw">def </span><span class="fun">_tree_requires_update</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">post_id</span>, <span class="name">last_update</span>):
- <span class="name">last_update</span> <span class="op">=</span> <span class="name">parse_datetime</span>(<span class="name">last_update</span>)
- <span class="name">last_thread_change</span> <span class="op">=</span> <span class="name">get_last_thread_change</span>(<span class="name">req</span>, <span class="name">post_id</span>)
- <span class="kw">print</span> <span class="name">last_thread_change</span>, <span class="name">last_update</span>
-
- <span class="kw">return</span> <span class="name">last_thread_change</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">last_thread_change</span> <span class="op">&gt;</span> <span class="name">last_update</span>
-
- <span class="deco">@export</span>(<span class="st st-sg">&#39;</span><span class="st">thread.get_tree</span><span class="st st-sg">&#39;</span>)
- <span class="kw">def </span><span class="fun">_get_tree</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">post_id</span>):
- <span class="kw">return</span> <span class="name">render_template</span>(<span class="name">req</span>, <span class="st st-sg">&#39;</span><span class="st">partial/tree.html</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">get_post_tree</span>(<span class="name">req</span>, <span class="name">post_id</span>)[<span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>]
- })
-
-
-
-<span class="kw">class </span><span class="cls">LoginPage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">login</span><span class="st st-sg">&#39;</span>
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">login</span><span class="st st-sg">&#39;</span>
-
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">&#39;</span><span class="st">^login$</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">next</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">values</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">next</span><span class="st st-sg">&#39;</span>, <span class="bn bn-pseudo">None</span>)
- <span class="kw">if</span> <span class="name">next</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">next</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">environ</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">HTTP_REFERER</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">next</span>:
- <span class="name">next</span> <span class="op">=</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
- <span class="name">msg</span> <span class="op">=</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>:
- <span class="kw">return</span> <span class="name">HttpRedirect</span>(<span class="name">next</span>)
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isNotEmpty</span>()),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">password</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isNotEmpty</span>())
- )
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="name">login</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">auth</span>.<span class="name">do_login</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="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">password</span><span class="st st-sg">&#39;</span>])
- <span class="kw">if</span> <span class="name">login</span>:
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">login</span>, <span class="name">Response</span>):
- <span class="kw">return</span> <span class="name">login</span>
-
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/login.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">username</span><span class="op">=</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="name">next</span><span class="op">=</span><span class="name">next</span>
-
- )
- <span class="kw">else</span>:
- <span class="name">msg</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Login failed. You may have entered an invalid </span><span class="st st-sg">&#39;</span>
- <span class="st st-sg">&#39;</span><span class="st">username or password or your account is not </span><span class="st st-sg">&#39;</span>
- <span class="st st-sg">&#39;</span><span class="st">activated yet.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">login.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">msg</span><span class="op">=</span><span class="name">msg</span>,
- <span class="name">form</span><span class="op">=</span><span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="name">next</span><span class="op">=</span><span class="name">next</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">LogoutPage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">logout</span><span class="st st-sg">&#39;</span>
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">logout</span><span class="st st-sg">&#39;</span>
-
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">r&#39;</span><span class="st">logout$</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">back</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">environ</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">HTTP_REFERER</span><span class="st st-sg">&#39;</span>, <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>)
- <span class="kw">try</span>:
- <span class="name">back</span> <span class="op">=</span> <span class="name">make_url_context_external</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">back</span>)
- <span class="kw">except</span> <span class="exc">ValueError</span>:
- <span class="name">back</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">username</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">username</span>
- <span class="name">req</span>.<span class="name">auth</span>.<span class="name">do_logout</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/logout.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">username</span><span class="op">=</span><span class="name">username</span>,
- <span class="name">back</span><span class="op">=</span><span class="name">back</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">RegisterPage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">register</span><span class="st st-sg">&#39;</span>
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">register</span><span class="st st-sg">&#39;</span>
-
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">&#39;</span><span class="st">register$</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">coppa</span> <span class="op">=</span> <span class="name">req</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">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">enable_coppa</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>:
- <span class="kw">return</span> <span class="name">HttpRedirect</span>(<span class="st st-sg">&#39;&#39;</span>)
- <span class="kw">if</span> <span class="st st-sg">&#39;</span><span class="st">activate</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">args</span> <span class="op op-word">and</span> <span class="st st-sg">&#39;</span><span class="st">user</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">args</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">activation</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="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isAvailableUsername</span>()),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">password</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isStrongPassword</span>()),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">password2</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isSameValue</span>(<span class="st st-sg">&#39;</span><span class="st">password</span><span class="st st-sg">&#39;</span>,
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The passwords don</span><span class="st st-esc">\&#39;</span><span class="st">t match.</span><span class="st st-sg">&#39;</span>))),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isEmail</span>()),
- <span class="name">CheckBox</span>(<span class="st st-sg">&#39;</span><span class="st">coppa</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">coppaIsChecked</span>(<span class="name">coppa</span>)),
- )
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">requires_activation</span> <span class="op">=</span> <span class="name">req</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">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">email_verification</span><span class="st st-sg">&#39;</span>)
- <span class="name">user</span> <span class="op">=</span> <span class="name">User</span>.<span class="name">create</span>(<span class="name">req</span>.<span class="name">ctx</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="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">password</span><span class="st st-sg">&#39;</span>],
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>],
- <span class="name">requires_activation</span>
-
- )
- <span class="kw">if</span> <span class="name">requires_activation</span>:
- <span class="name">link</span> <span class="op">=</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;</span><span class="st">register?user=</span><span class="st st-int">%s</span><span class="st">&amp;key</span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span>
-
- (<span class="name">user</span>.<span class="name">user_id</span>, <span class="name">user</span>.<span class="name">act_key</span>))
- <span class="name">txt</span> <span class="op">=</span> <span class="name">render_template</span>(<span class="name">req</span>, <span class="st st-sg">&#39;</span><span class="st">mails/welcome_verification.txt</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="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">password</span><span class="st st-sg">&#39;</span>: <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">password</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">forum_name</span><span class="st st-sg">&#39;</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">title</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">activate_link</span><span class="st st-sg">&#39;</span>: <span class="name">link</span>
-
- })
- <span class="name">mail</span> <span class="op">=</span> <span class="name">Email</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Welcome to the </span><span class="st st-int">%s</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">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">title</span><span class="st st-sg">&#39;</span>),
- <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>], <span class="name">txt</span>)
- <span class="name">mail</span>.<span class="name">send</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/register.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">requires_activation</span><span class="op">=</span><span class="name">requires_activation</span>,
- <span class="name">username</span><span class="op">=</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="name">email</span><span class="op">=</span><span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>]
- )
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">register.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">form</span><span class="op">=</span><span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- )
-
- <span class="kw">def </span><span class="fun">activation</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="name">uid</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">req</span>.<span class="name">args</span>[<span class="st st-sg">&#39;</span><span class="st">user</span><span class="st st-sg">&#39;</span>])
- <span class="name">activated</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="name">username</span> <span class="op">=</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>
- <span class="kw">try</span>:
- <span class="name">user</span> <span class="op">=</span> <span class="name">User</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">uid</span>)
- <span class="name">key</span> <span class="op">=</span> <span class="name">user</span>.<span class="name">act_key</span>
-
- <span class="kw">except</span> <span class="exc">KeyError</span>:
- <span class="kw">pass</span>
- <span class="kw">else</span>:
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">user</span>.<span class="name">active</span> <span class="op op-word">and</span> <span class="name">req</span>.<span class="name">args</span>[<span class="st st-sg">&#39;</span><span class="st">activate</span><span class="st st-sg">&#39;</span>] <span class="op">==</span> <span class="name">key</span>:
- <span class="name">user</span>.<span class="name">activate</span>()
- <span class="name">activated</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="name">username</span> <span class="op">=</span> <span class="name">user</span>.<span class="name">username</span>
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/activation.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">username</span><span class="op">=</span><span class="name">username</span>,
- <span class="name">activated</span><span class="op">=</span><span class="name">activated</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">NewPostPage</span>(<span class="name">RequestHandler</span>, <span class="name">RemoteCallable</span>):
- <span class="name">handler_regexes</span> <span class="op">=</span> [
- (<span class="st st-sg">r&#39;</span><span class="st">post/(?P&lt;post_id&gt;\d+)/reply$</span><span class="st st-sg">&#39;</span>,
- {<span class="st st-sg">&#39;</span><span class="st">action</span><span class="st st-sg">&#39;</span>:<span class="st st-sg">&#39;</span><span class="st">reply</span><span class="st st-sg">&#39;</span>}),
- (<span class="st st-sg">r&#39;</span><span class="st">post/(?P&lt;post_id&gt;\d+)/quote$</span><span class="st st-sg">&#39;</span>,
- {<span class="st st-sg">&#39;</span><span class="st">action</span><span class="st st-sg">&#39;</span>:<span class="st st-sg">&#39;</span><span class="st">quote</span><span class="st st-sg">&#39;</span>}),
- (<span class="st st-sg">r&#39;</span><span class="st">post/(?P&lt;post_id&gt;\d+)/edit$</span><span class="st st-sg">&#39;</span>,
- {<span class="st st-sg">&#39;</span><span class="st">action</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="kw">def </span><span class="fun">handle_request</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">action</span>, <span class="name">post_id</span>):
- <span class="kw">try</span>:
- <span class="name">thread</span> <span class="op">=</span> <span class="name">Thread</span>.<span class="name">by_child</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">post_id</span>)
- <span class="kw">except</span> <span class="exc">ValueError</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="cm"># note: quote_post can raise a ValueError when a post does</span>
- <span class="cm"># not exist. but since we check for that by calling</span>
- <span class="cm"># Thread.by_child this shouldn&#39;t happen.</span>
- <span class="name">username</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">anonymous</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">action</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">reply</span><span class="st st-sg">&#39;</span>:
- <span class="name">mode</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">reply</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">acl</span>.<span class="name">can_access</span>(<span class="st st-sg">&#39;</span><span class="st">REPLY_POST</span><span class="st st-sg">&#39;</span>, <span class="name">thread</span>):
- <span class="kw">return</span> <span class="name">AccessDeniedResponse</span>()
- <span class="name">text</span> <span class="op">=</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>
-
- <span class="name">_</span>, <span class="name">title</span> <span class="op">=</span> <span class="name">quote_post</span>(<span class="name">req</span>, <span class="name">post_id</span>)
- <span class="kw">elif</span> <span class="name">action</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">quote</span><span class="st st-sg">&#39;</span>:
- <span class="name">mode</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">reply</span><span class="st st-sg">&#39;</span>
-
- <span class="cm">#XXX: maybe we could use REPLY_POST here too</span>
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">acl</span>.<span class="name">can_access</span>(<span class="st st-sg">&#39;</span><span class="st">QUOTE_POST</span><span class="st st-sg">&#39;</span>, <span class="name">thread</span>):
- <span class="kw">return</span> <span class="name">AccessDeniedResponse</span>()
- <span class="name">text</span>, <span class="name">title</span> <span class="op">=</span> <span class="name">quote_post</span>(<span class="name">req</span>, <span class="name">post_id</span>)
- <span class="kw">else</span>:
- <span class="name">mode</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">edit</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">acl</span>.<span class="name">can_access</span>(<span class="st st-sg">&#39;</span><span class="st">EDIT_POST</span><span class="st st-sg">&#39;</span>, <span class="name">thread</span>):
- <span class="kw">return</span> <span class="name">AccessDeniedResponse</span>()
- <span class="name">text</span>, <span class="name">title</span>, <span class="name">username</span> <span class="op">=</span> <span class="name">edit_post</span>(<span class="name">req</span>, <span class="name">post_id</span>)
-
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="name">req</span>.<span class="name">environ</span>[<span class="st st-sg">&#39;</span><span class="st">APPLICATION_REQUEST</span><span class="st st-sg">&#39;</span>], <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isAnonymousUsername</span>(),
- <span class="name">default</span><span class="op">=</span><span class="name">username</span>),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">3</span>, <span class="nb nb-int">60</span>),
- <span class="name">default</span><span class="op">=</span><span class="name">title</span>),
- <span class="name">TextArea</span>(<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">3</span>, <span class="nb nb-int">10000</span>),
- <span class="name">default</span><span class="op">=</span><span class="name">text</span>)
- )
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>:
- <span class="name">author</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="kw">else</span>:
- <span class="name">author</span> <span class="op">=</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="kw">if</span> <span class="name">action</span> <span class="op op-word">in</span> (<span class="st st-sg">&#39;</span><span class="st">quote</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">reply</span><span class="st st-sg">&#39;</span>):
- <span class="name">new_post_id</span> <span class="op">=</span> <span class="name">thread</span>.<span class="name">reply</span>(
- <span class="name">post_id</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">post_id</span>),
- <span class="name">author</span> <span class="op">=</span> <span class="name">author</span>,
- <span class="name">title</span> <span class="op">=</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="name">text</span> <span class="op">=</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">elif</span> <span class="name">action</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">edit</span><span class="st st-sg">&#39;</span>:
- <span class="name">new_post_id</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">post_id</span>)
- <span class="name">thread</span>.<span class="name">edit_reply</span>(
- <span class="name">post_id</span> <span class="op">=</span> <span class="name">new_post_id</span>,
- <span class="name">author</span> <span class="op">=</span> <span class="name">author</span>,
- <span class="name">title</span> <span class="op">=</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="name">text</span> <span class="op">=</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">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/post.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">mode</span> <span class="op">=</span> <span class="name">mode</span>,
- <span class="name">post</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">id</span><span class="st st-sg">&#39;</span>: <span class="name">new_post_id</span>,
- <span class="st st-sg">&#39;</span><span class="st">title</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">url</span><span class="st st-sg">&#39;</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">post</span><span class="st st-sg">&#39;</span>, <span class="name">new_post_id</span>),
- }
- )
- <span class="name">js</span>, <span class="name">options</span> <span class="op">=</span> <span class="name">get_editor</span>(<span class="name">req</span>)
- <span class="name">latest_posts</span> <span class="op">=</span> <span class="name">get_last_posts</span>(<span class="name">req</span>, <span class="name">thread</span>.<span class="name">root_post_id</span>, <span class="nb nb-int">5</span>)
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">newpost.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">mode</span> <span class="op">=</span> <span class="name">mode</span>,
- <span class="name">form</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="name">show_username_entry</span> <span class="op">=</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>,
- <span class="name">editor_options</span> <span class="op">=</span> <span class="name">options</span>,
- <span class="name">editor_javascript</span> <span class="op">=</span> <span class="name">js</span>,
- <span class="name">post_id</span> <span class="op">=</span> <span class="name">thread</span>.<span class="name">root_post_id</span>,
- <span class="name">pathbar</span><span class="op">=</span><span class="name">get_post_pathbar</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">post_id</span>),
- <span class="name">latest_posts</span> <span class="op">=</span> <span class="name">latest_posts</span>
-
- )
-
- <span class="deco">@export</span>(<span class="st st-db">&quot;</span><span class="st">newpost.preview</span><span class="st st-db">&quot;</span>)
- <span class="kw">def </span><span class="fun">preview</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">text</span>):
- <span class="kw">return</span> <span class="name">parse_and_render</span>(<span class="name">req</span>, <span class="name">text</span>)
-
- <span class="deco">@export</span>(<span class="st st-db">&quot;</span><span class="st">newpost.check</span><span class="st st-db">&quot;</span>)
- <span class="kw">def </span><span class="fun">check</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">root_post_id</span>, <span class="name">latest_post</span>, <span class="name">path</span>):
- <span class="cm"># check for new posts</span>
-
- <span class="name">new_posts</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
- <span class="name">post</span> <span class="op">=</span> <span class="name">get_last_posts</span>(<span class="name">req</span>, <span class="name">root_post_id</span>, <span class="nb nb-int">1</span>)[<span class="nb nb-int">0</span>]
- <span class="name">post_list</span> <span class="op">=</span> []
- <span class="kw">if</span> <span class="name">latest_post</span> <span class="op">!=</span> <span class="name">post</span>[<span class="st st-db">&quot;</span><span class="st">post_id</span><span class="st st-db">&quot;</span>]:
- <span class="name">z</span> <span class="op">=</span> <span class="nb nb-int">1</span>
-
- <span class="kw">while</span> <span class="name">post</span>[<span class="st st-db">&quot;</span><span class="st">post_id</span><span class="st st-db">&quot;</span>] <span class="op">!=</span> <span class="name">latest_post</span> <span class="op op-word">and</span> <span class="name">z</span> <span class="op">&lt;</span> <span class="nb nb-int">5</span>:
- <span class="name">post_list</span>.<span class="name">append</span>(<span class="name">post</span>)
- <span class="name">post</span> <span class="op">=</span> <span class="name">get_last_posts</span>(<span class="name">req</span>, <span class="name">root_post_id</span>, <span class="nb nb-int">1</span>, <span class="name">z</span>)[<span class="nb nb-int">0</span>]
- <span class="name">z</span> <span class="op">+=</span> <span class="nb nb-int">1</span>
-
- <span class="name">new_posts</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">html</span><span class="st st-sg">&#39;</span>: <span class="name">render_template</span>(<span class="name">req</span>, <span class="st st-sg">&#39;</span><span class="st">latestposts.html</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">post_list</span>}),
- <span class="st st-sg">&#39;</span><span class="st">last_post</span><span class="st st-sg">&#39;</span>: <span class="name">post_list</span>[<span class="nb nb-int">0</span>][<span class="st st-db">&quot;</span><span class="st">post_id</span><span class="st st-db">&quot;</span>]
- }
-
- <span class="cm"># check for new editors</span>
-
- <span class="name">new_editors</span> <span class="op">=</span> <span class="name">get_sessions_by_action</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">path</span>) <span class="op op-word">or</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">return</span> (<span class="name">post_list</span> <span class="op op-word">or</span> <span class="name">new_editors</span>) <span class="op op-word">and</span> {
- <span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>: <span class="name">new_posts</span>,
- <span class="st st-sg">&#39;</span><span class="st">editors</span><span class="st st-sg">&#39;</span>: <span class="name">new_editors</span>
-
- } <span class="op op-word">or</span> <span class="bn bn-pseudo">False</span>
-
-
-<span class="kw">class </span><span class="cls">NewThreadPage</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">forum/(?P&lt;forum_id&gt;\d+)/new$</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">forum_id</span>):
- <span class="cm"># TODO: Check whether user is allowed to do this</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
- <span class="name">forum_id</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">forum_id</span>)
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="name">req</span>.<span class="name">environ</span>[<span class="st st-sg">&#39;</span><span class="st">APPLICATION_REQUEST</span><span class="st st-sg">&#39;</span>], <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isAnonymousUsername</span>(),
- <span class="name">default</span><span class="op">=</span><span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">anonymous</span><span class="st st-sg">&#39;</span>)),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">3</span>, <span class="nb nb-int">60</span>)),
- <span class="name">TextArea</span>(<span class="st st-sg">&#39;</span><span class="st">text</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">3</span>, <span class="nb nb-int">10000</span>))
- )
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>:
- <span class="name">author</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="kw">else</span>:
- <span class="name">author</span> <span class="op">=</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="name">thread</span> <span class="op">=</span> <span class="name">Thread</span>.<span class="name">create</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">forum_id</span>, <span class="name">author</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="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">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/thread.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">thread</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>: <span class="name">thread</span>.<span class="name">title</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">post</span><span class="st st-sg">&#39;</span>, <span class="name">thread</span>.<span class="name">root_post_id</span>),
- }
- )
-
- <span class="name">js</span>, <span class="name">options</span> <span class="op">=</span> <span class="name">get_editor</span>(<span class="name">req</span>)
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">newthread.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">form</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="name">show_username_entry</span> <span class="op">=</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>,
- <span class="name">editor_options</span> <span class="op">=</span> <span class="name">options</span>,
- <span class="name">editor_javascript</span> <span class="op">=</span> <span class="name">js</span>,
- <span class="name">pathbar</span> <span class="op">=</span> <span class="name">get_forum_pathbar</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">forum_id</span>)
- )
-
-
-
-<span class="kw">class </span><span class="cls">MemberListPage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">memberlist</span><span class="st st-sg">&#39;</span>
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">users/</span><span class="st st-sg">&#39;</span>
-
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">r&#39;</span><span class="st">users/$</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">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">generate</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">GET</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">letter</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isOneLetter</span>())),
- <span class="name">SelectBox</span>(<span class="st st-sg">&#39;</span><span class="st">order_by</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">_</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">_</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">register_date</span><span class="st st-sg">&#39;</span>, <span class="name">_</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">post_count</span><span class="st st-sg">&#39;</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Number of Posts</span><span class="st st-sg">&#39;</span>))
- ], <span class="name">default</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">SelectBox</span>(<span class="st st-sg">&#39;</span><span class="st">direction</span><span class="st st-sg">&#39;</span>, [
- (<span class="st st-sg">&#39;</span><span class="st">desc</span><span class="st st-sg">&#39;</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Descending</span><span class="st st-sg">&#39;</span>)),
- (<span class="st st-sg">&#39;</span><span class="st">asc</span><span class="st st-sg">&#39;</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Ascending</span><span class="st st-sg">&#39;</span>))
- ], <span class="name">default</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="kw">if</span> <span class="st st-sg">&#39;</span><span class="st">letter</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">args</span> <span class="op op-word">or</span> <span class="st st-sg">&#39;</span><span class="st">order_by</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">args</span> \
- <span class="op op-word">or</span> <span class="st st-sg">&#39;</span><span class="st">direction</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">args</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">args</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">generate</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="kw">else</span>:
- <span class="name">generate</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
- <span class="kw">if</span> <span class="name">generate</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="name">userlist</span> <span class="op">=</span> <span class="name">get_user_list</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>,
- <span class="name">order_by</span><span class="op">=</span><span class="bn">getattr</span>(<span class="name">users</span>.<span class="name">c</span>, <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">order_by</span><span class="st st-sg">&#39;</span>]),
- <span class="name">order</span><span class="op">=</span><span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">direction</span><span class="st st-sg">&#39;</span>],
- <span class="name">letter</span><span class="op">=</span><span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">letter</span><span class="st st-sg">&#39;</span>] <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>,
- <span class="name">hide_internal</span><span class="op">=</span><span class="bn bn-pseudo">True</span>
-
- )
- <span class="kw">else</span>:
- <span class="name">userlist</span> <span class="op">=</span> []
-
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">memberlist.html</span><span class="st st-sg">&#39;</span>,
- <span class="bn">list</span><span class="op">=</span><span class="name">userlist</span>,
- <span class="name">form</span><span class="op">=</span><span class="name">form</span>.<span class="name">generate</span>()
- )
-
-
-
-<span class="kw">class </span><span class="cls">UserPage</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">users/(?P&lt;username&gt;.+)$</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">username</span>):
- <span class="cm"># TODO: add a permission CAN_VIEW_PROFILE</span>
-
- <span class="cm"># check avatar</span>
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">args</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">show</span><span class="st st-sg">&#39;</span>) <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>:
- <span class="name">avatar</span> <span class="op">=</span> <span class="name">get_user_avatar</span>(<span class="name">req</span>, <span class="name">username</span>)
- <span class="kw">if</span> <span class="name">avatar</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</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">avatar</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">image/png</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">return</span> <span class="name">resp</span>
- <span class="cm"># display user</span>
- <span class="name">user</span> <span class="op">=</span> <span class="name">get_user</span>(<span class="name">req</span>, <span class="name">username</span>)
- <span class="kw">if</span> <span class="name">user</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">user.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">person</span> <span class="op">=</span> <span class="name">user</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">GotoPage</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">goto$</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">if</span> <span class="st st-sg">&#39;</span><span class="st">post</span><span class="st st-sg">&#39;</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">args</span>:
- <span class="name">post_id</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">args</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="op">=</span> <span class="name">get_post</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">post_id</span>)
- <span class="kw">while</span> <span class="name">post</span>.<span class="name">parent</span>: <span class="cm">#get root_post</span>
-
- <span class="name">post</span> <span class="op">=</span> <span class="name">post</span>.<span class="name">parent</span> <span class="op op-word">or</span> <span class="name">post</span>
- <span class="name">thread</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">db</span>.<span class="name">get</span>(<span class="name">Thread</span>, <span class="name">Thread</span>.<span class="name">c</span>.<span class="name">root_post_id</span> <span class="op">==</span> <span class="name">post</span>.<span class="name">post_id</span>)
- <span class="kw">return</span> <span class="name">HttpRedirect</span>(<span class="name">thread</span>.<span class="name">url</span>)
- <span class="kw">else</span>:
- <span class="kw">return</span> <span class="name">HttpRedirect</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;</span><span class="st">/</span><span class="st st-sg">&#39;</span>))
-
-
-
-<span class="kw">class </span><span class="cls">SplitPage</span>(<span class="name">RequestHandler</span>, <span class="name">RemoteCallable</span>):
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">r&#39;</span><span class="st">post/(?P&lt;post_id&gt;\d+)/split$</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">post_id</span>):
- <span class="kw">try</span>:
- <span class="name">thread</span> <span class="op">=</span> <span class="name">Thread</span>.<span class="name">by_child</span>(<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">post_id</span>)
- <span class="kw">except</span> <span class="exc">ValueError</span>:
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">acl</span>.<span class="name">can_access</span>(<span class="st st-sg">&#39;</span><span class="st">MODERATOR</span><span class="st st-sg">&#39;</span>, <span class="name">thread</span>.<span class="name">forum_id</span>):
- <span class="kw">return</span> <span class="name">AccessDeniedResponse</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">split.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">thread</span> <span class="op">=</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">thread</span>.<span class="name">root_post_id</span>, <span class="st st-sg">&#39;</span><span class="st">title</span><span class="st st-sg">&#39;</span>:<span class="name">thread</span>.<span class="name">title</span>}
- )
-
- <span class="deco">@export</span>(<span class="st st-sg">&#39;</span><span class="st">split.get_post_tree</span><span class="st st-sg">&#39;</span>)
- <span class="kw">def </span><span class="fun">split</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">root_post_id</span>):
- <span class="kw">def </span><span class="fun">iterate_items</span>(<span class="name">post_list</span>):
- <span class="name">tmp</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">post</span> <span class="op op-word">in</span> <span class="name">post_list</span>:
- <span class="name">tmp</span>.<span class="name">append</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-db">&quot;</span><span class="st">post_id</span><span class="st st-db">&quot;</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-db">&quot;</span><span class="st">title</span><span class="st st-db">&quot;</span>],
- <span class="st st-sg">&#39;</span><span class="st">children</span><span class="st st-sg">&#39;</span>: <span class="st st-db">&quot;</span><span class="st">children</span><span class="st st-db">&quot;</span> <span class="op op-word">in</span> <span class="name">post</span> <span class="op op-word">and</span> \
- <span class="name">iterate_items</span>(<span class="name">post</span>[<span class="st st-db">&quot;</span><span class="st">children</span><span class="st st-db">&quot;</span>]) <span class="op op-word">or</span> [],
- <span class="st st-sg">&#39;</span><span class="st">parent_id</span><span class="st st-sg">&#39;</span>: <span class="name">post</span>[<span class="st st-db">&quot;</span><span class="st">parent_id</span><span class="st st-db">&quot;</span>]
- })
- <span class="kw">return</span> <span class="name">tmp</span>
-
- <span class="name">post_tree</span> <span class="op">=</span> <span class="name">get_post_tree</span>(<span class="name">req</span>, <span class="name">root_post_id</span>)
-
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">acl</span>.<span class="name">can_access</span>(<span class="st st-sg">&#39;</span><span class="st">MODERATOR</span><span class="st st-sg">&#39;</span>, <span class="name">post_tree</span>[<span class="st st-db">&quot;</span><span class="st">forum</span><span class="st st-db">&quot;</span>][<span class="st st-db">&quot;</span><span class="st">forum_id</span><span class="st st-db">&quot;</span>]):
- <span class="kw">return</span> <span class="name">AccessDeniedResponse</span>()
-
- <span class="kw">return</span> {
- <span class="st st-sg">&#39;</span><span class="st">posts</span><span class="st st-sg">&#39;</span>:<span class="name">iterate_items</span>(<span class="name">post_tree</span>[<span class="st st-db">&quot;</span><span class="st">posts</span><span class="st st-db">&quot;</span>]),
- <span class="st st-sg">&#39;</span><span class="st">thread</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">post_tree</span>[<span class="st st-db">&quot;</span><span class="st">forum</span><span class="st st-db">&quot;</span>][<span class="st st-db">&quot;</span><span class="st">forum_id</span><span class="st st-db">&quot;</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">post_tree</span>[<span class="st st-db">&quot;</span><span class="st">post_id</span><span class="st st-db">&quot;</span>]
- }
- }
-
- <span class="deco">@export</span>(<span class="st st-sg">&#39;</span><span class="st">split.commit</span><span class="st st-sg">&#39;</span>)
- <span class="kw">def </span><span class="fun">commit</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">changes</span>):
- <span class="cm"># TODO: Check whether operation is allowed at every subforum of a thread</span>
-
- <span class="cm"># the user changes</span>
- <span class="kw">for</span> <span class="name">tmp</span> <span class="op op-word">in</span> <span class="name">changes</span>.<span class="name">iteritems</span>():
- <span class="name">change</span> <span class="op">=</span> <span class="name">tmp</span>[<span class="nb nb-int">1</span>]
- <span class="bn">id</span> <span class="op">=</span> <span class="name">change</span>[<span class="st st-sg">&#39;</span><span class="st">id</span><span class="st st-sg">&#39;</span>]
- <span class="name">new_pid</span> <span class="op">=</span> <span class="name">change</span>[<span class="st st-sg">&#39;</span><span class="st">new_pid</span><span class="st st-sg">&#39;</span>]
- <span class="name">old_pid</span> <span class="op">=</span> <span class="name">change</span>[<span class="st st-sg">&#39;</span><span class="st">old_pid</span><span class="st st-sg">&#39;</span>]
- <span class="name">act_tid</span> <span class="op">=</span> <span class="name">change</span>[<span class="st st-sg">&#39;</span><span class="st">act_tid</span><span class="st st-sg">&#39;</span>]
- <span class="name">old_tid</span> <span class="op">=</span> <span class="name">change</span>[<span class="st st-sg">&#39;</span><span class="st">old_tid</span><span class="st st-sg">&#39;</span>]
- <span class="name">post</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">db</span>.<span class="name">get</span>(<span class="name">Post</span>, <span class="name">Post</span>.<span class="name">c</span>.<span class="name">post_id</span> <span class="op">==</span> <span class="bn">id</span>)
- <span class="kw">if</span> <span class="name">new_pid</span> <span class="op">!=</span> <span class="op">-</span><span class="nb nb-int">1</span>:
- <span class="name">post</span>.<span class="name">parent_id</span> <span class="op">=</span> <span class="name">new_pid</span>
-
- <span class="kw">else</span>:
- <span class="kw">if</span> <span class="name">act_tid</span> <span class="op">==</span> <span class="op">-</span><span class="nb nb-int">1</span>:
- <span class="cm">#XXX: forum_id</span>
- <span class="name">thread</span> <span class="op">=</span> <span class="name">Thread</span>(
- <span class="name">name</span> <span class="op">=</span> <span class="name">post</span>.<span class="name">name</span>,
- <span class="name">forum_id</span> <span class="op">=</span> <span class="nb nb-int">1</span>,
- <span class="name">root_post_id</span> <span class="op">=</span> <span class="name">post</span>.<span class="name">post_id</span>
-
- )
- <span class="name">req</span>.<span class="name">db</span>.<span class="name">save</span>(<span class="name">thread</span>)
- <span class="kw">else</span>:
- <span class="name">thread</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">db</span>.<span class="name">get</span>(<span class="name">Thread</span>, <span class="name">Thread</span>.<span class="name">c</span>.<span class="name">thread_id</span> <span class="op">==</span> <span class="name">act_tid</span>)
- <span class="name">thread</span>.<span class="name">name</span> <span class="op">=</span> <span class="name">post</span>.<span class="name">name</span>
-
- <span class="name">post</span>.<span class="name">parent_id</span> <span class="op">=</span> <span class="name">thread</span>.<span class="name">thread_id</span>
- <span class="name">req</span>.<span class="name">db</span>.<span class="name">flush</span>()
- <span class="kw">return</span> <span class="st st-db">&quot;&quot;</span>
-
-
-<span class="kw">class </span><span class="cls">WhoIsOnlinePage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">whoisonline</span><span class="st st-sg">&#39;</span>
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">whoisonline</span><span class="st st-sg">&#39;</span>
-
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">r&#39;</span><span class="st">whoisonline$</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">sessions</span>, <span class="name">users</span>, <span class="name">guests</span>, <span class="name">total</span> <span class="op">=</span> <span class="name">get_active_sessions</span>(<span class="name">req</span>.<span class="name">ctx</span>)
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">whoisonline.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">sessions</span><span class="op">=</span><span class="name">sessions</span>,
- <span class="name">user_count</span><span class="op">=</span><span class="name">users</span>,
- <span class="name">guest_count</span><span class="op">=</span><span class="name">guests</span>,
- <span class="name">total_count</span><span class="op">=</span><span class="name">total</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">UserSettings</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">settings</span><span class="st st-sg">&#39;</span>
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">settings/</span><span class="st st-sg">&#39;</span>
-
- <span class="name">handler_regexes</span> <span class="op">=</span> [
- <span class="st st-sg">r&#39;</span><span class="st">settings/$</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">r&#39;</span><span class="st">settings/(?P&lt;page&gt;.+?)$</span><span class="st st-sg">&#39;</span>
- ]
- <span class="name">allow_username_change</span> <span class="op">=</span> <span class="name">cfg</span>.<span class="name">bool</span>(<span class="st st-sg">&#39;</span><span class="st">security</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">username_change</span><span class="st st-sg">&#39;</span>, <span class="bn bn-pseudo">False</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">page</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">assert_logged_in</span>()
- <span class="name">sidebar</span> <span class="op">=</span> []
- <span class="name">missing</span> <span class="op">=</span> <span class="bn">object</span>()
- <span class="name">page_result</span> <span class="op">=</span> <span class="name">missing</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">UserSettingsPage</span>):
- <span class="name">caption</span> <span class="op">=</span> <span class="name">comp</span>.<span class="name">get_settings_link_title</span>(<span class="name">req</span>)
- <span class="cm"># if the caption is None the plugin doesn&#39;t want to</span>
-
- <span class="cm"># be visible in the sidebar, skip</span>
- <span class="kw">if</span> <span class="name">caption</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">continue</span>
- <span class="name">active</span> <span class="op">=</span> <span class="name">comp</span>.<span class="name">settings_page_identifier</span> <span class="op">==</span> <span class="name">page</span>
-
- <span class="kw">if</span> <span class="name">active</span>:
- <span class="name">page_result</span> <span class="op">=</span> <span class="name">comp</span>.<span class="name">get_settings_page</span>(<span class="name">req</span>)
- <span class="cm"># the page really wants to output data on its own</span>
-
- <span class="cm"># we don&#39;t need to create a sidebar, stop here</span>
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">page_result</span>, <span class="name">Response</span>):
- <span class="kw">return</span> <span class="name">page_result</span>
-
- <span class="name">sidebar</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">comp</span>.<span class="name">url</span>,
- <span class="st st-sg">&#39;</span><span class="st">caption</span><span class="st st-sg">&#39;</span>: <span class="name">caption</span>,
- <span class="st st-sg">&#39;</span><span class="st">active</span><span class="st st-sg">&#39;</span>: <span class="name">active</span>,
- <span class="st st-sg">&#39;</span><span class="st">identifier</span><span class="st st-sg">&#39;</span>: <span class="name">comp</span>.<span class="name">settings_page_identifier</span>
-
- })
- <span class="cm"># display error page</span>
- <span class="kw">if</span> <span class="name">page_result</span> <span class="op op-word">is</span> <span class="name">missing</span> <span class="op op-word">and</span> <span class="name">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">PageNotFound</span>()
- <span class="cm"># we have found a page, display it, but first sort the sidebar</span>
-
- <span class="name">sidebar</span>.<span class="name">sort</span>(<span class="name">key</span><span class="op">=</span><span class="kw">lambda</span> <span class="name">x</span>: <span class="name">x</span>[<span class="st st-sg">&#39;</span><span class="st">caption</span><span class="st st-sg">&#39;</span>].<span class="name">lower</span>())
- <span class="kw">if</span> <span class="name">page</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">settings/index.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">setting_pages</span> <span class="op">=</span> <span class="name">sidebar</span>
-
- )
- <span class="name">template</span>, <span class="name">context</span> <span class="op">=</span> <span class="name">page_result</span>
- <span class="name">context</span>[<span class="st st-sg">&#39;</span><span class="st">setting_pages</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="name">sidebar</span>
-
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="name">template</span>, <span class="op">**</span><span class="name">context</span>)
-
-
-<span class="kw">class </span><span class="cls">LostPasswordPage</span>(<span class="name">RequestHandler</span>, <span class="name">PagePublisher</span>):
- <span class="name">page_name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">lostpassword</span><span class="st st-sg">&#39;</span>
-
- <span class="name">relative_url</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">lostpassword</span><span class="st st-sg">&#39;</span>
- <span class="name">handler_regexes</span> <span class="op">=</span> [<span class="st st-sg">&#39;</span><span class="st">lostpassword$</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="cm"># if the user is identified he has probably not lost has password ;)</span>
-
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">identified</span>:
- <span class="kw">return</span> <span class="name">HttpRedirect</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="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">ctx</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>
- <span class="name">msg</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isExistingUsername</span>()),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>, <span class="name">validator</span><span class="op">=</span><span class="name">isEmail</span>())
- )
-
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="name">password</span> <span class="op">=</span> <span class="name">reset_password</span>(<span class="name">ctx</span>, <span class="op">**</span><span class="name">d</span>)
- <span class="kw">if</span> <span class="name">password</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">text</span> <span class="op">=</span> <span class="name">render_template</span>(<span class="name">req</span>, <span class="st st-sg">&#39;</span><span class="st">mails/new_password.txt</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="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">password</span><span class="st st-sg">&#39;</span>: <span class="name">password</span>
-
- })
- <span class="name">mail</span> <span class="op">=</span> <span class="name">Email</span>(<span class="name">ctx</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">New password</span><span class="st st-sg">&#39;</span>), <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>], <span class="name">text</span>)
- <span class="name">mail</span>.<span class="name">send</span>()
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">messages/password.html</span><span class="st st-sg">&#39;</span>, <span class="op">**</span><span class="name">d</span>)
- <span class="kw">else</span>:
- <span class="name">msg</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Creation of a new password failed. Username </span><span class="st st-sg">&#39;</span>
-
- <span class="st st-sg">&#39;</span><span class="st">or email address is invalid.</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">return</span> <span class="name">TemplateResponse</span>(<span class="st st-sg">&#39;</span><span class="st">lostpassword.html</span><span class="st st-sg">&#39;</span>,
- <span class="name">form</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="name">msg</span> <span class="op">=</span> <span class="name">msg</span>
-
- )
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.remotecall
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Pocoo remote call support.
-
-
- Remote Call Implementation
- ==========================
-
- The Pocoo XMLRPC/JSONRPC interface works like this::
-
- import time
- from pocoo.pkg.core.remotecall import RemoteCallable, export
-
- class MyClass(RemoteCallable):
-
- @export(&quot;test.hello_world&quot;)
- def say(self, req, name=&#39;World&#39;):
- return &#39;Hello </span><span class="st st-int">%s</span><span class="st">!&#39; % name
-
- @export(&quot;test.get_servertime&quot;)
- def servertime(self, req):
- return time.time()
-
- By now only jsonrpc is available. You can query the jsonrpc interface
- under ``/!jsonrpc``. The exported names are ``packagename.&lt;name&gt;``.
- So for the example above the method names are (assumed that the module
- is in package ``core``)::
-
- core.test.hello_world
-
- and::
-
- core.test.get_servertime
-
-
- JavaScript Query
- =================
-
- You can query those functions using the following syntax::
-
- var rpc = new pocoo.lib.async.RPC(&#39;!jsonrpc&#39;);
- var method = rpc.getMethod(&#39;methodname&#39;);
- method(arguments, kwarguments, callback);
-
- The query for the example above would be::
-
- var rpc = new pocoo.lib.async.RPC(&#39;!jsonrpc&#39;);
- var method = rpc.getMethod(&#39;core.test.hello_world&#39;);
- method([&quot;Benjamin&quot;], {}, function (result) {
- alert(result);
- // alerts &quot;Hello Benjamin!&quot;
-
- });
-
-
- :copyright: 2006 by Armin Ronacher.
- :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">new</span>
-<span class="kw">from </span><span class="cls">types</span><span class="kw"> import</span> <span class="name">FunctionType</span>
-<span class="kw">from </span><span class="cls">pocoo</span><span class="kw"> import</span> <span class="name">Component</span>, <span class="name">ComponentMeta</span>
-
-<span class="kw">from </span><span class="cls">pocoo.http</span><span class="kw"> import</span> <span class="name">DirectResponse</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">from </span><span class="cls">pocoo.utils</span><span class="kw"> import</span> <span class="name">json</span>
-
-
-<span class="kw">class </span><span class="cls">_RemoteCallableMeta</span>(<span class="name">ComponentMeta</span>):
-
- <span class="kw">def </span><span class="fun">__new__</span>(<span class="name">cls</span>, <span class="name">name</span>, <span class="name">bases</span>, <span class="name">dct</span>):
- <span class="name">rpc_exports</span> <span class="op">=</span> {}
- <span class="name">result</span> <span class="op">=</span> <span class="name">ComponentMeta</span>.<span class="name">__new__</span>(<span class="name">cls</span>, <span class="name">name</span>, <span class="name">bases</span>, <span class="name">dct</span>)
- <span class="kw">for</span> <span class="name">name</span>, <span class="name">ref</span> <span class="op op-word">in</span> <span class="name">dct</span>.<span class="name">iteritems</span>():
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">ref</span>, <span class="name">FunctionType</span>) <span class="op op-word">and</span> \
- <span class="bn">getattr</span>(<span class="name">ref</span>, <span class="st st-sg">&#39;</span><span class="st">rpc_exported</span><span class="st st-sg">&#39;</span>, <span class="bn bn-pseudo">False</span>):
- <span class="name">name</span> <span class="op">=</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">ref</span>.<span class="name">__module__</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">2</span>],
- <span class="name">ref</span>.<span class="name">rpc_name</span>)
- <span class="name">rpc_exports</span>[<span class="name">name</span>] <span class="op">=</span> <span class="name">ref</span>
-
- <span class="name">result</span>.<span class="name">rpc_exports</span> <span class="op">=</span> <span class="name">rpc_exports</span>
- <span class="kw">return</span> <span class="name">result</span>
-
-
-<span class="kw">class </span><span class="cls">RemoteCallable</span>(<span class="name">Component</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Components inheriting from this base component can export methods
- for jsonrpc if they are decorated using `export`.
-
- Example::
-
- from pocoo.pkg.core.remotecall import RemoteCallable, export
-
- class MyExport(RemoteCallable):
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">__metaclass__</span> <span class="op">=</span> <span class="name">_RemoteCallableMeta</span>
-
-
-<span class="kw">class </span><span class="cls">RemoteCallManager</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">!jsonrpc$</span><span class="st st-sg">&#39;</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="bn">super</span>(<span class="name">RemoteCallManager</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">ctx</span>)
- <span class="bn bn-pseudo">self</span>.<span class="name">_mapping</span> <span class="op">=</span> <span class="bn bn-pseudo">None</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="cm"># TODO: once jsonrpc1.1 is finished: update error codes</span>
- <span class="kw">if</span> <span class="bn bn-pseudo">self</span>.<span class="name">_mapping</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">_mapping</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">RemoteCallable</span>):
- <span class="kw">for</span> <span class="name">name</span>, <span class="name">ref</span> <span class="op op-word">in</span> <span class="name">comp</span>.<span class="name">rpc_exports</span>.<span class="name">iteritems</span>():
- <span class="name">handler</span> <span class="op">=</span> <span class="name">new</span>.<span class="name">instancemethod</span>(<span class="name">ref</span>, <span class="name">comp</span>, <span class="name">comp</span>.<span class="name">__class__</span>)
- <span class="bn bn-pseudo">self</span>.<span class="name">_mapping</span>[<span class="name">name</span>] <span class="op">=</span> <span class="name">handler</span>
-
- <span class="bn">id</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
- <span class="kw">try</span>:
- <span class="name">method</span>, <span class="name">args</span>, <span class="name">kwargs</span>, <span class="bn">id</span> <span class="op">=</span> <span class="name">json</span>.<span class="name">parse_jsonrpc_request</span>(<span class="name">req</span>.<span class="name">data</span>)
- <span class="name">handler</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_mapping</span>[<span class="name">method</span>]
- <span class="name">json_data</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">version</span><span class="st st-sg">&#39;</span>: <span class="st st-sg">&#39;</span><span class="st">1.1</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">result</span><span class="st st-sg">&#39;</span>: <span class="name">handler</span>(<span class="name">req</span>, <span class="op">*</span><span class="name">args</span>, <span class="op">**</span><span class="name">kwargs</span>)
- }
- <span class="kw">if</span> <span class="bn">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">json_data</span>[<span class="st st-sg">&#39;</span><span class="st">id</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">id</span>
-
- <span class="kw">except</span> <span class="name">DirectResponse</span>, <span class="name">e</span>:
- <span class="kw">return</span> <span class="name">e</span>.<span class="name">args</span>[<span class="nb nb-int">0</span>]
- <span class="kw">except</span> <span class="exc">Exception</span>, <span class="name">e</span>:
- <span class="name">error</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">msg</span><span class="st st-sg">&#39;</span>: <span class="bn">str</span>(<span class="name">e</span>),
- <span class="st st-sg">&#39;</span><span class="st">type</span><span class="st st-sg">&#39;</span>: <span class="name">e</span>.<span class="name">__class__</span>.<span class="name">__name__</span>
-
- }
- <span class="kw">for</span> <span class="name">name</span>, <span class="name">ref</span> <span class="op op-word">in</span> <span class="name">e</span>.<span class="name">__dict__</span>.<span class="name">iteritems</span>():
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">name</span>.<span class="name">startswith</span>(<span class="st st-sg">&#39;</span><span class="st">_</span><span class="st st-sg">&#39;</span>) <span class="op op-word">and</span>\
- <span class="bn">isinstance</span>(<span class="name">ref</span>, (<span class="bn">str</span>, <span class="bn">unicode</span>, <span class="bn">int</span>, <span class="bn">float</span>, <span class="bn">tuple</span>,
- <span class="bn">list</span>, <span class="bn">dict</span>)):
- <span class="name">error</span>[<span class="name">name</span>] <span class="op">=</span> <span class="name">ref</span>
-
- <span class="name">json_data</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">version</span><span class="st st-sg">&#39;</span>: <span class="st st-sg">&#39;</span><span class="st">1.1</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">error</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="st st-sg">&#39;</span><span class="st">JSONRPCError</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">code</span><span class="st st-sg">&#39;</span>: <span class="nb nb-oct">000</span>,
- <span class="st st-sg">&#39;</span><span class="st">message</span><span class="st st-sg">&#39;</span>: <span class="st st-sg">&#39;</span><span class="st">An error occurred parsing the request object.</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">error</span><span class="st st-sg">&#39;</span>: <span class="name">error</span>
-
- }
- }
- <span class="kw">if</span> <span class="bn">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">json_data</span>[<span class="st st-sg">&#39;</span><span class="st">id</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn">id</span>
-
- <span class="kw">return</span> <span class="name">Response</span>(<span class="name">json</span>.<span class="name">dumps</span>(<span class="name">json_data</span>),
- [(<span class="st st-sg">&#39;</span><span class="st">Content-Type</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">text/javascript</span><span class="st st-sg">&#39;</span>)])
-
-
-<span class="kw">def </span><span class="fun">export</span>(<span class="name">name</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Exports a function in a RemoteCallable component.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">wrapped</span>(<span class="name">f</span>):
- <span class="name">f</span>.<span class="name">rpc_exported</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="name">f</span>.<span class="name">rpc_name</span> <span class="op">=</span> <span class="name">name</span>
- <span class="kw">return</span> <span class="name">f</span>
- <span class="kw">return</span> <span class="name">wrapped</span>
-
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.restformat
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Pocoo ReST Parser.
-
- A thin wrapper around the docutils ReST parser.
-
- :copyright: 2006 by 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.pkg.core.textfmt</span><span class="kw"> import</span> <span class="name">MarkupFormat</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.html</span><span class="kw"> import</span> <span class="name">escape_html</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.smilies</span><span class="kw"> import</span> <span class="name">replace_smilies</span>
-
-
-<span class="kw">class </span><span class="cls">ReST</span>(<span class="name">MarkupFormat</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- ReST markup format.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">rest</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">parse</span>(<span class="bn bn-pseudo">self</span>, <span class="name">text</span>, <span class="name">signature</span>):
- <span class="kw">from </span><span class="cls">docutils.core</span><span class="kw"> import</span> <span class="name">publish_parts</span>
-
- <span class="kw">try</span>:
- <span class="name">parts</span> <span class="op">=</span> <span class="name">publish_parts</span>(<span class="name">source</span><span class="op">=</span><span class="name">text</span>, <span class="name">writer_name</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">html4css1</span><span class="st st-sg">&#39;</span>)
- <span class="name">text</span> <span class="op">=</span> <span class="name">parts</span>[<span class="st st-sg">&#39;</span><span class="st">fragment</span><span class="st st-sg">&#39;</span>].<span class="name">strip</span>()
- <span class="kw">except</span> <span class="exc">Exception</span>:
- <span class="cm"># TODO: figure out which exceptions this can raise</span>
-
- <span class="name">text</span> <span class="op">=</span> <span class="name">escape_html</span>(<span class="name">text</span>).<span class="name">strip</span>()
- <span class="cm">#XXX: render smilies just in text blocks</span>
- <span class="kw">return</span> <span class="name">replace_smilies</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">text</span>)
-
- <span class="kw">def </span><span class="fun">quote_text</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">text</span>, <span class="name">username</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="name">lines</span> <span class="op">=</span> [<span class="name">u</span><span class="st st-sg">&#39;</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">line</span> <span class="kw">for</span> <span class="name">line</span> <span class="op op-word">in</span> <span class="name">text</span>.<span class="name">splitlines</span>()]
- <span class="kw">if</span> <span class="name">username</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">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">lines</span>.<span class="name">insert</span>(<span class="nb nb-int">0</span>, (<span class="name">u</span><span class="st st-sg">&#39;</span><span class="st"> **</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="name">_</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%s</span><span class="st"> wrote</span><span class="st st-sg">&#39;</span>)) <span class="op">%</span> <span class="name">username</span>)
- <span class="kw">return</span> <span class="name">u</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="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.search
- ~~~~~~~~~~~~~~~~~~~~~
-
- Pocoo Search System
-
- :copyright: 2006 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.application</span><span class="kw"> import</span> <span class="name">LinkableMixin</span>
-
-<span class="kw">from </span><span class="cls">shlex</span><span class="kw"> import</span> <span class="name">split</span>
-
-
-<span class="cm">#XXX: some kind of early draft</span>
-<span class="kw">class </span><span class="cls">Query</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Search Query Object
- </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">rule</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">text</span> <span class="op">=</span> <span class="name">rule</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">required</span> <span class="op">=</span> []
- <span class="bn bn-pseudo">self</span>.<span class="name">unwanted</span> <span class="op">=</span> []
- <span class="bn bn-pseudo">self</span>.<span class="name">optional</span> <span class="op">=</span> []
- <span class="name">next</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">first</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
- <span class="kw">for</span> <span class="name">token</span> <span class="op op-word">in</span> <span class="name">split</span>(<span class="name">rule</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">next</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="bn">getattr</span>(<span class="bn bn-pseudo">self</span>, <span class="name">next</span>).<span class="name">append</span>(<span class="name">token</span>)
- <span class="name">next</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="name">token</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">NOT</span><span class="st st-sg">&#39;</span>:
- <span class="name">next</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">unwanted</span><span class="st st-sg">&#39;</span>
- <span class="kw">elif</span> <span class="name">token</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">AND</span><span class="st st-sg">&#39;</span>:
- <span class="name">next</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">required</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">elif</span> <span class="name">token</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">OR</span><span class="st st-sg">&#39;</span>:
- <span class="name">next</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">optional</span><span class="st st-sg">&#39;</span>
- <span class="kw">else</span>:
- <span class="kw">if</span> <span class="name">token</span>.<span class="name">startswith</span>(<span class="st st-sg">&#39;</span><span class="st">+</span><span class="st st-sg">&#39;</span>):
- <span class="name">token</span> <span class="op">=</span> <span class="name">token</span>[<span class="nb nb-int">1</span>:]
- <span class="bn bn-pseudo">self</span>.<span class="name">required</span>.<span class="name">append</span>(<span class="name">token</span>)
- <span class="kw">elif</span> <span class="name">token</span>.<span class="name">startswith</span>(<span class="st st-sg">&#39;</span><span class="st">-</span><span class="st st-sg">&#39;</span>):
- <span class="name">token</span> <span class="op">=</span> <span class="name">token</span>[<span class="nb nb-int">1</span>:]
- <span class="bn bn-pseudo">self</span>.<span class="name">unwanted</span>.<span class="name">append</span>(<span class="name">token</span>)
- <span class="kw">elif</span> <span class="name">first</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">required</span>.<span class="name">append</span>(<span class="name">token</span>)
- <span class="name">first</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">else</span>:
- <span class="bn bn-pseudo">self</span>.<span class="name">optional</span>.<span class="name">append</span>(<span class="name">token</span>)
- <span class="name">first</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">words</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">required</span> <span class="op">+</span> <span class="bn bn-pseudo">self</span>.<span class="name">unwanted</span> <span class="op">+</span> <span class="bn bn-pseudo">self</span>.<span class="name">optional</span>
-
- <span class="kw">def </span><span class="fun">__iter__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn">iter</span>(<span class="bn bn-pseudo">self</span>.<span class="name">words</span>)
-
- <span class="kw">def </span><span class="fun">__len__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn">len</span>(<span class="bn bn-pseudo">self</span>.<span class="name">words</span>)
-
- <span class="kw">def </span><span class="fun">is_required</span>(<span class="bn bn-pseudo">self</span>, <span class="name">word</span>):
- <span class="kw">return</span> <span class="name">word</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">required</span>
-
- <span class="kw">def </span><span class="fun">is_unwanted</span>(<span class="bn bn-pseudo">self</span>, <span class="name">word</span>):
- <span class="kw">return</span> <span class="name">word</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">unwanted</span>
-
- <span class="kw">def </span><span class="fun">is_optional</span>(<span class="bn bn-pseudo">self</span>, <span class="name">word</span>):
- <span class="kw">return</span> <span class="name">word</span> <span class="op op-word">in</span> <span class="bn bn-pseudo">self</span>.<span class="name">optional</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">%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">text</span>
-
- )
-
-
-<span class="cm">#XXX: early draft</span>
-<span class="kw">class </span><span class="cls">Result</span>(<span class="bn">object</span>, <span class="name">LinkableMixin</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Search result object.
- </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">title</span>, <span class="name">relative_url</span>, <span class="name">description</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">title</span> <span class="op">=</span> <span class="name">title</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">relative_url</span> <span class="op">=</span> <span class="name">relative_url</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">description</span> <span class="op">=</span> <span class="name">description</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">%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">title</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">SearchProvider</span>(<span class="name">Component</span>):
- <span class="cm">#: name of the search provider</span>
- <span class="name">name</span> <span class="op">=</span> <span class="bn bn-pseudo">None</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="st st-db">&quot;&quot;&quot;</span><span class="st">Return a translated version of the search provider name.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>
-
- <span class="kw">def </span><span class="fun">can_search</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return True if a user is allowed to use this search provider.</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">query</span>(<span class="bn bn-pseudo">self</span>, <span class="name">query</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Perform a query, has to return an iterable of result objects.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> ()
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- pocoo.pkg.core.session
- ~~~~~~~~~~~~~~~~~~~~~~
-
- Pocoo session handling.
-
- :copyright: 2006 by Georg Brandl, Armin Ronacher.
- :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">md5</span>
-<span class="kw">import </span><span class="cls">time</span>
-<span class="kw">import </span><span class="cls">random</span>
-
-<span class="kw">from </span><span class="cls">datetime</span><span class="kw"> import</span> <span class="name">datetime</span>, <span class="name">timedelta</span>
-
-<span class="kw">from </span><span class="cls">pocoo.application</span><span class="kw"> import</span> <span class="name">RequestWrapper</span>
-<span class="kw">from </span><span class="cls">pocoo.settings</span><span class="kw"> import</span> <span class="name">cfg</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.uri</span><span class="kw"> import</span> <span class="name">urlencode</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.db</span><span class="kw"> import</span> <span class="name">sessions</span>, <span class="name">users</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.auth</span><span class="kw"> import</span> <span class="name">get_auth_provider</span>
-
-
-<span class="kw">def </span><span class="fun">get_active_sessions</span>(<span class="name">ctx</span>, <span class="name">delta</span><span class="op">=</span><span class="name">timedelta</span>(<span class="name">minutes</span><span class="op">=</span><span class="nb nb-int">5</span>)):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a tuple in the following form::
-
- (sessions, user_count, guest_count, total)
-
- sessions is a dict for the template with all relevant
- information about the sessions, user_count is the
- amount of all logged in users, guest_count is the
- amount of all anonymous users and total is the total
- number of all sessions being active.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">provider</span> <span class="op">=</span> <span class="name">get_auth_provider</span>(<span class="name">ctx</span>)
- <span class="name">now</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">session_list</span> <span class="op">=</span> []
- <span class="name">user_count</span> <span class="op">=</span> <span class="nb nb-int">0</span>
-
- <span class="name">guest_count</span> <span class="op">=</span> <span class="nb nb-int">0</span>
- <span class="name">r</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">sessions</span>.<span class="name">select</span>(
- <span class="name">sessions</span>.<span class="name">c</span>.<span class="name">last_reload</span> <span class="op">&gt;</span> <span class="name">now</span> <span class="op">-</span> <span class="name">delta</span>
-
- ))
- <span class="kw">while</span> <span class="bn bn-pseudo">True</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">break</span>
-
- <span class="name">user</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">users</span>.<span class="name">c</span>.<span class="name">user_id</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">provider</span>.<span class="name">get_user_id</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">data</span><span class="st st-sg">&#39;</span>])
- )).<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">user</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">user</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>] <span class="op">&lt;</span> <span class="nb nb-int">1</span>:
- <span class="name">guest_count</span> <span class="op">+=</span> <span class="nb nb-int">1</span>
-
- <span class="name">user_data</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
- <span class="kw">else</span>:
- <span class="name">user_data</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">user</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">user_id</span><span class="st st-sg">&#39;</span>: <span class="name">user</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">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">user</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])),
- }
- <span class="name">user_count</span> <span class="op">+=</span> <span class="nb nb-int">1</span>
-
- <span class="name">session_list</span>.<span class="name">append</span>({
- <span class="st st-sg">&#39;</span><span class="st">last_reload</span><span class="st st-sg">&#39;</span>: <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">last_reload</span><span class="st st-sg">&#39;</span>],
- <span class="st st-sg">&#39;</span><span class="st">user</span><span class="st st-sg">&#39;</span>: <span class="name">user_data</span>
- })
- <span class="name">session_list</span>.<span class="name">sort</span>(<span class="name">key</span><span class="op">=</span><span class="kw">lambda</span> <span class="name">x</span>: <span class="name">x</span>[<span class="st st-sg">&#39;</span><span class="st">last_reload</span><span class="st st-sg">&#39;</span>])
- <span class="kw">return</span> <span class="name">session_list</span>, <span class="name">user_count</span>, <span class="name">guest_count</span>, <span class="name">user_count</span> <span class="op">+</span> <span class="name">guest_count</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_sessions_by_action</span>(<span class="name">ctx</span>, <span class="name">url</span>):
- <span class="name">provider</span> <span class="op">=</span> <span class="name">get_auth_provider</span>(<span class="name">ctx</span>)
- <span class="kw">def </span><span class="fun">do</span>(<span class="name">con</span>):
- <span class="name">session_list</span> <span class="op">=</span> []
- <span class="name">r</span> <span class="op">=</span> <span class="name">con</span>.<span class="name">execute</span>(<span class="name">sessions</span>.<span class="name">select</span>(
- <span class="name">sessions</span>.<span class="name">c</span>.<span class="name">action</span> <span class="op">==</span> <span class="name">url</span>
-
- ))
- <span class="kw">while</span> <span class="bn bn-pseudo">True</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">break</span>
-
- <span class="name">user</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">users</span>.<span class="name">c</span>.<span class="name">user_id</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">provider</span>.<span class="name">get_user_id</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">data</span><span class="st st-sg">&#39;</span>])
- )).<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">user</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">user</span>[<span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>] <span class="op">&lt;</span> <span class="nb nb-int">1</span>:
- <span class="name">user_data</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">else</span>:
- <span class="name">user_data</span> <span class="op">=</span> {
- <span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>: <span class="name">user</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">user</span>[<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>])),
- }
- <span class="name">session_list</span>.<span class="name">append</span>(<span class="name">user_data</span>)
- <span class="kw">return</span> <span class="name">session_list</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">class </span><span class="cls">Session</span>(<span class="bn">dict</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Session Model</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">sid</span>, <span class="name">ip</span>, <span class="name">path</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">path</span> <span class="op">=</span> <span class="name">path</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">sessions</span>.<span class="name">select</span>(
- (<span class="name">sessions</span>.<span class="name">c</span>.<span class="name">session_key</span> <span class="op">==</span> <span class="name">sid</span>) <span class="op">&amp;</span>
-
- (<span class="name">sessions</span>.<span class="name">c</span>.<span class="name">ip_addr</span> <span class="op">==</span> <span class="name">ip</span>) <span class="op">&amp;</span>
- (<span class="name">sessions</span>.<span class="name">c</span>.<span class="name">expires</span> <span class="op">&gt;=</span> <span class="name">datetime</span>.<span class="name">utcnow</span>())
- ))
- <span class="name">data</span> <span class="op">=</span> <span class="name">r</span>.<span class="name">fetchone</span>()
- <span class="kw">if</span> <span class="name">data</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="bn">super</span>(<span class="name">Session</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>()
- <span class="bn bn-pseudo">self</span>.<span class="name">sid</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">else</span>:
- <span class="bn">super</span>(<span class="name">Session</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">data</span>[<span class="st st-sg">&#39;</span><span class="st">data</span><span class="st st-sg">&#39;</span>])
- <span class="bn bn-pseudo">self</span>.<span class="name">sid</span> <span class="op">=</span> <span class="name">sid</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">ip</span> <span class="op">=</span> <span class="name">ip</span>
-
- <span class="kw">def </span><span class="fun">__hash__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn">hash</span>(<span class="bn bn-pseudo">self</span>.<span class="name">sid</span>)
-
- <span class="kw">def </span><span class="fun">to_dict</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return the session data as normal dict.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn">dict</span>(<span class="bn bn-pseudo">self</span>)
-
- <span class="kw">def </span><span class="fun">save</span>(<span class="bn bn-pseudo">self</span>, <span class="name">cookie_expire</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Save changes back to the database and updates
- expires and last_reload. Returns a datetime object
- with the time of the session expire.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">now</span> <span class="op">=</span> <span class="name">datetime</span>.<span class="name">utcnow</span>()
- <span class="name">expires</span> <span class="op">=</span> <span class="name">now</span> <span class="op">+</span> <span class="name">timedelta</span>(<span class="name">seconds</span><span class="op">=</span><span class="name">cookie_expire</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">sid</span>:
- <span class="kw">while</span> <span class="bn bn-pseudo">True</span>:
- <span class="name">hashval</span> <span class="op">=</span> <span class="name">md5</span>.<span class="name">new</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">random</span>.<span class="name">random</span>(), <span class="name">time</span>.<span class="name">time</span>()))
- <span class="name">sid</span> <span class="op">=</span> <span class="name">hashval</span>.<span class="name">hexdigest</span>()
- <span class="name">r</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">sessions</span>.<span class="name">select</span>(
- <span class="name">sessions</span>.<span class="name">c</span>.<span class="name">session_key</span> <span class="op">==</span> <span class="name">sid</span>
-
- ))
- <span class="kw">if</span> <span class="name">r</span>.<span class="name">fetchone</span>() <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="kw">break</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">sid</span> <span class="op">=</span> <span class="name">sid</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">sessions</span>.<span class="name">insert</span>(),
- <span class="name">session_key</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">sid</span>,
- <span class="name">ip_addr</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">ip</span>,
- <span class="name">expires</span> <span class="op">=</span> <span class="name">expires</span>,
- <span class="name">last_reload</span> <span class="op">=</span> <span class="name">now</span>,
- <span class="name">action</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">path</span>,
- <span class="name">data</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">to_dict</span>()
- )
- <span class="kw">else</span>:
- <span class="name">q</span> <span class="op">=</span> <span class="name">sessions</span>.<span class="name">c</span>.<span class="name">session_key</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">sid</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">sessions</span>.<span class="name">update</span>(<span class="name">q</span>),
- <span class="name">expires</span> <span class="op">=</span> <span class="name">expires</span>,
- <span class="name">last_reload</span> <span class="op">=</span> <span class="name">now</span>,
- <span class="name">action</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">path</span>,
- <span class="name">data</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">to_dict</span>()
- )
- <span class="kw">return</span> <span class="name">expires</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">%s</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">sid</span>,
- <span class="bn">dict</span>.<span class="name">__repr__</span>(<span class="bn bn-pseudo">self</span>)
- )
-
-
-
-<span class="kw">class </span><span class="cls">SessionWrapper</span>(<span class="name">RequestWrapper</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- SessionWrapper loads/stores request.session.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">cookie_name</span> <span class="op">=</span> <span class="name">cfg</span>.<span class="name">str</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">cookiename</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">SESSION</span><span class="st st-sg">&#39;</span>)
- <span class="name">cookie_expires</span> <span class="op">=</span> <span class="name">cfg</span>.<span class="name">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">cookieexpires</span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">7200</span>)
-
- <span class="kw">def </span><span class="fun">get_priority</span>(<span class="bn bn-pseudo">self</span>):
- <span class="cm"># request.session should be set before anything else,</span>
-
- <span class="cm"># but after a possible caching system.</span>
- <span class="kw">return</span> <span class="nb nb-int">2</span>
-
- <span class="kw">def </span><span class="fun">process_request</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="name">cookie</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">cookies</span>.<span class="name">get</span>(<span class="bn bn-pseudo">self</span>.<span class="name">cookie_name</span>, <span class="bn bn-pseudo">None</span>)
- <span class="name">sid</span> <span class="op">=</span> <span class="name">cookie</span> <span class="op op-word">and</span> <span class="name">cookie</span>.<span class="name">value</span> <span class="op op-word">or</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">ip</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">environ</span>[<span class="st st-sg">&#39;</span><span class="st">REMOTE_ADDR</span><span class="st st-sg">&#39;</span>]
- <span class="name">req</span>.<span class="name">session</span> <span class="op">=</span> <span class="name">Session</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">sid</span>, <span class="name">ip</span>, <span class="name">req</span>.<span class="name">path</span>)
-
- <span class="kw">def </span><span class="fun">process_response</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">resp</span>):
- <span class="name">expires</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">session</span>.<span class="name">save</span>(<span class="bn bn-pseudo">self</span>.<span class="name">cookie_expires</span>)
- <span class="name">resp</span>.<span class="name">set_cookie</span>(<span class="bn">str</span>(<span class="bn bn-pseudo">self</span>.<span class="name">cookie_name</span>), <span class="name">req</span>.<span class="name">session</span>.<span class="name">sid</span>,
- <span class="name">max_age</span><span class="op">=</span><span class="bn bn-pseudo">self</span>.<span class="name">cookie_expires</span>, <span class="name">expires</span><span class="op">=</span><span class="name">expires</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.simplehtml
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-
- This module provides a MarkupFormat that allows the user to use
- HTML as markup but strips dangerous tags like ``&lt;script&gt;`` and others.
-
- It uses the ``secure_html`` method from the ``html`` util.
-
- :copyright: 2006 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.utils.html</span><span class="kw"> import</span> <span class="name">secure_html</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.textfmt</span><span class="kw"> import</span> <span class="name">MarkupFormat</span>
-
-
-<span class="kw">class </span><span class="cls">SimpleHTML</span>(<span class="name">MarkupFormat</span>):
- <span class="name">name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">simplehtml</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">parse</span>(<span class="bn bn-pseudo">self</span>, <span class="name">text</span>):
- <span class="kw">return</span> <span class="name">secure_html</span>(<span class="name">text</span>)
-
- <span class="kw">def </span><span class="fun">quote_text</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">text</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">username</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">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">text</span> <span class="op">=</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st">&lt;em&gt;</span><span class="st st-int">%s</span><span class="st">:&lt;/em&gt;&lt;br /&gt;</span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> ((<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%s</span><span class="st"> wrote</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">username</span>), <span class="name">text</span>)
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st">&lt;blockquote&gt;</span><span class="st st-int">%s</span><span class="st">&lt;/blockquote&gt;</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">text</span>
-
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.smilies
- ~~~~~~~~~~~~~~~~~~~~~~
-
- Pocoo smilies parser.
-
- :copyright: 2006 by Benjamin Wiegand, 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</span><span class="kw"> import</span> <span class="name">Component</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.html</span><span class="kw"> import</span> <span class="name">escape_html</span>
-
-
-<span class="kw">def </span><span class="fun">replace_smilies</span>(<span class="name">ctx</span>, <span class="name">text</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Replace smilies in ``text``, using all providers listed in the
- board config.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">smiley_providers</span> <span class="op">=</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">smiley_providers</span><span class="st st-sg">&#39;</span>, [<span class="st st-sg">&#39;</span><span class="st">default</span><span class="st st-sg">&#39;</span>])
- <span class="kw">for</span> <span class="name">provider</span> <span class="op op-word">in</span> <span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">SmileyProvider</span>):
- <span class="kw">if</span> <span class="name">provider</span>.<span class="name">name</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="name">smiley_providers</span>:
- <span class="kw">continue</span>
-
- <span class="kw">for</span> <span class="name">smiley</span> <span class="op op-word">in</span> <span class="name">provider</span>.<span class="name">smilies</span>:
- <span class="name">text</span> <span class="op">=</span> <span class="name">text</span>.<span class="name">replace</span>(<span class="name">smiley</span>[<span class="nb nb-int">0</span>], <span class="name">provider</span>.<span class="name">render_smiley</span>(<span class="name">smiley</span>))
- <span class="kw">return</span> <span class="name">text</span>
-
-
-<span class="kw">def </span><span class="fun">get_smiley_buttons</span>(<span class="name">ctx</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a list of button dictionaries usable for the BBCodeEditor
- JavaScript app.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">res</span> <span class="op">=</span> []
- <span class="name">smiley_providers</span> <span class="op">=</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">smiley_providers</span><span class="st st-sg">&#39;</span>, [<span class="st st-sg">&#39;</span><span class="st">default</span><span class="st st-sg">&#39;</span>])
- <span class="kw">for</span> <span class="name">provider</span> <span class="op op-word">in</span> <span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">SmileyProvider</span>):
- <span class="kw">if</span> <span class="name">provider</span>.<span class="name">name</span> <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="name">smiley_providers</span>:
- <span class="kw">continue</span>
-
- <span class="kw">for</span> <span class="name">smiley</span> <span class="op op-word">in</span> <span class="name">provider</span>.<span class="name">smilies</span>:
- <span class="name">res</span>.<span class="name">append</span>(<span class="name">smiley</span> <span class="op">+</span> (<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="name">provider</span>.<span class="name">smiley_dir</span>),))
- <span class="kw">return</span> <span class="name">res</span>
-
-
-<span class="kw">class </span><span class="cls">SmileyProvider</span>(<span class="name">Component</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- A SmileyProvider maps small text strings to images.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="cm">#: List of smilies this component provides, in the form</span>
- <span class="cm">#: ``(&#39;textform&#39;, &#39;imagename&#39;)``.</span>
-
- <span class="cm">#: ``imagename`` is relative to the ``smiley_dir`` below.</span>
- <span class="name">smilies</span> <span class="op">=</span> []
-
- <span class="cm">#: Directory where smilies of this provider can be found.</span>
- <span class="cm">#: Must be relative to the forum root, e.g.</span>
- <span class="cm">#: ``!cobalt/pkgname/default/img/smilies/``.</span>
-
- <span class="name">smiley_dir</span> <span class="op">=</span> <span class="st st-db">&quot;&quot;</span>
-
- <span class="cm">#: Name (can be overwritten, must be lowercase).</span>
- <span class="cm">#: Used for the configuration setting.</span>
- <span class="deco">@property</span>
- <span class="kw">def </span><span class="fun">name</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>.<span class="name">lower</span>()
-
- <span class="kw">def </span><span class="fun">render_smiley</span>(<span class="bn bn-pseudo">self</span>, <span class="name">smiley</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Render a smiley. This doesn&#39;t need to be overridden in normal
- cases.
-
- :return: HTML for the smiley image.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">&lt;img src=&quot;</span><span class="st st-int">%s</span><span class="st">&quot; alt=&quot;</span><span class="st st-int">%s</span><span class="st">&quot; /&gt;</span><span class="st st-sg">&#39;</span> <span class="op">%</span> (
- <span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="bn bn-pseudo">self</span>.<span class="name">smiley_dir</span>, <span class="name">smiley</span>[<span class="nb nb-int">1</span>]),
- <span class="name">escape_html</span>(<span class="name">smiley</span>[<span class="nb nb-int">0</span>])
- )
-
-
-
-<span class="kw">class </span><span class="cls">Default</span>(<span class="name">SmileyProvider</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Default Pocoo smilies.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">smilies</span> <span class="op">=</span> [
- (<span class="st st-sg">&#39;</span><span class="st">;-)</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">wink.png</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="st st-sg">&#39;</span><span class="st">sad.png</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="st st-sg">&#39;</span><span class="st">smile.png</span><span class="st st-sg">&#39;</span>),
- (<span class="st st-sg">&#39;</span><span class="st">:D</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">grin.png</span><span class="st st-sg">&#39;</span>),
- ]
-
- <span class="name">smiley_dir</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">!cobalt/core/default/img/smilies/</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.template
- ~~~~~~~~~~~~~~~~~~~~~~~
-
- Templating helpers.
-
- :copyright: 2006 by Georg Brandl, Armin Ronacher.
- :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">math</span>
-<span class="kw">import </span><span class="cls">jinja.exceptions</span>
-<span class="kw">from </span><span class="cls">jinja.nodes</span><span class="kw"> import</span> <span class="name">Node</span>, <span class="name">KeywordNode</span>, <span class="name">VariableNode</span>, <span class="name">CollectionNode</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">BaseThemeRequirements</span>(<span class="name">FileRequirements</span>):
-
- <span class="kw">def </span><span class="fun">get_javascript_imports</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> (
- <span class="st st-sg">&#39;</span><span class="st">AJS/AJS.js</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">pocoo/lib/async.js</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">pocoo/lib/dom.js</span><span class="st st-sg">&#39;</span>,
- <span class="st st-sg">&#39;</span><span class="st">pocoo/lib/effects.js</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">return</span> (
- <span class="st st-sg">&#39;</span><span class="st">default/style/screen.css</span><span class="st st-sg">&#39;</span>,
- )
-
-
-
-<span class="kw">class </span><span class="cls">Pagination</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Pagination Controller. Push this into the template so that
- the template designer has an object he can use for generating
- an pagination.
-
- Normally you are looking for the ``LazyPagination`` class, this
- one is just for posts or if you have many single items which
- are combined to a thread etc. The idea is that you don&#39;t have
- and offset information in the url.
- </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">req</span>, <span class="name">idlist</span>, <span class="name">start</span>, <span class="name">per_page</span>, <span class="name">link</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- :param req: the request
- :param idlist: a list of all ids for the pagination
- :param start: the position of the first item on the page
- :param per_page: number of items on each page
- :param link: function which takes one id and returns a link for it
-
- Example::
-
- p = Pagination(req, range(50), 20, 20, lambda x: &#39;post/</span><span class="st st-int">%d</span><span class="st">&#39; </span><span class="st st-int">% x</span><span class="st">)
-
- In this example the first page would contain the posts 0-19,
- the second 20-39 and the first 40-50.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">req</span> <span class="op">=</span> <span class="name">req</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">idlist</span> <span class="op">=</span> <span class="name">idlist</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">start</span> <span class="op">=</span> <span class="name">start</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">per_page</span> <span class="op">=</span> <span class="name">per_page</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">link</span> <span class="op">=</span> <span class="name">link</span>
-
- <span class="kw">def </span><span class="fun">generate</span>(<span class="bn bn-pseudo">self</span>, <span class="name">normal</span>, <span class="name">active</span>, <span class="name">commata</span>, <span class="name">ellipsis</span>, <span class="name">threshold</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Generate a Pagination of the data defined in the constructor.
-
- :param normal: inserted string when the page isn&#39;t active
- :param active: inserted string when the page is active
- :param commata: inserted between links
- :param ellipsis: inserted as space indicator for skiped links
- :param threshold: number of links around start/current page and
- end before they will be replaced by an ellipsis
-
- ``normal`` and ``active`` can contain out of the following formatting
- chars:
-
- ====================== ==================================
- ``</span><span class="st st-int">%(page)s</span><span class="st">`` number of the current page
- ``</span><span class="st st-int">%(url)s</span><span class="st">`` absolute url of the current page
- ====================== ==================================
-
- Example::
-
- p.generate(&#39;&lt;a href=&quot;</span><span class="st st-int">%(url)s</span><span class="st">&quot;&gt;</span><span class="st st-int">%(page)s</span><span class="st">&lt;/a&gt;&#39;,
- &#39;&lt;strong&gt;</span><span class="st st-int">%(page)s</span><span class="st">&lt;/strong&gt;&#39;,
- &#39;, &#39;,
- &#39; ... &#39;,
- 3)
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">current_page_number</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">start</span> <span class="op">/</span> <span class="bn bn-pseudo">self</span>.<span class="name">per_page</span> <span class="op">+</span> <span class="nb nb-int">1</span>
-
- <span class="name">number_of_pages</span> <span class="op">=</span> <span class="bn">int</span>(<span class="name">math</span>.<span class="name">ceil</span>(<span class="bn">len</span>(<span class="bn bn-pseudo">self</span>.<span class="name">idlist</span>) <span class="op">/</span> (<span class="bn bn-pseudo">self</span>.<span class="name">per_page</span> <span class="op">*</span> <span class="nb nb-flt">1.0</span>)))
- <span class="name">was_space</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="name">result</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">idx</span> <span class="op op-word">in</span> <span class="bn">range</span>(<span class="nb nb-int">1</span>, <span class="name">number_of_pages</span> <span class="op">+</span> <span class="nb nb-int">1</span>):
- <span class="kw">if</span> <span class="name">idx</span> <span class="op">&lt;=</span> <span class="name">threshold</span> <span class="op op-word">or</span> <span class="name">idx</span> <span class="op">&gt;</span> <span class="name">number_of_pages</span> <span class="op">-</span> <span class="name">threshold</span> <span class="op op-word">or</span>\
- <span class="bn">abs</span>(<span class="name">current_page_number</span> <span class="op">-</span> <span class="name">idx</span>) <span class="op">&lt;</span> <span class="name">math</span>.<span class="name">ceil</span>(<span class="name">threshold</span> <span class="op">/</span> <span class="nb nb-flt">2.0</span>):
- <span class="kw">if</span> <span class="name">result</span> <span class="op op-word">and</span> <span class="name">result</span>[<span class="op">-</span><span class="nb nb-int">1</span>] <span class="op">!=</span> <span class="name">ellipsis</span>:
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">commata</span>)
- <span class="name">was_space</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">if</span> <span class="name">idx</span> <span class="op">==</span> <span class="name">current_page_number</span>:
- <span class="name">schema</span> <span class="op">=</span> <span class="name">active</span>
- <span class="kw">else</span>:
- <span class="name">schema</span> <span class="op">=</span> <span class="name">normal</span>
-
- <span class="name">url</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">link</span>(<span class="bn bn-pseudo">self</span>.<span class="name">idlist</span>[(<span class="name">idx</span> <span class="op">-</span> <span class="nb nb-int">1</span>) <span class="op">*</span> <span class="bn bn-pseudo">self</span>.<span class="name">per_page</span>])
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">schema</span> <span class="op">%</span> {
- <span class="st st-sg">&#39;</span><span class="st">page</span><span class="st st-sg">&#39;</span>: <span class="name">idx</span>,
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="name">url</span>),
- })
- <span class="kw">else</span>:
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">was_space</span>:
- <span class="name">was_space</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">ellipsis</span>)
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>.<span class="name">join</span>(<span class="name">result</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">%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">str</span>(<span class="bn bn-pseudo">self</span>)
- )
-
- <span class="kw">def </span><span class="fun">__str__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">generate</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%(page)s</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">[</span><span class="st st-int">%(page)s</span><span class="st">]</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="st st-sg">&#39;</span><span class="st"> ... </span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">3</span>)
-
-
-
-<span class="kw">class </span><span class="cls">LazyPagination</span>(<span class="bn">object</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- A lazy pagination controller. Doesn&#39;t require a id list like
- the ``Pagination`` controller.
-
- The ``LazyPagination`` is a cheep to calculate pagination based
- on the current page, the total amount of pages and the information
- about what a link looks like and how many items you have per page.
- </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">req</span>, <span class="name">page</span>, <span class="name">per_page</span>, <span class="name">pages</span>, <span class="name">link</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">req</span> <span class="op">=</span> <span class="name">req</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">page</span> <span class="op">=</span> <span class="name">page</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">per_page</span> <span class="op">=</span> <span class="name">per_page</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">pages</span> <span class="op">=</span> <span class="name">pages</span>
- <span class="bn bn-pseudo">self</span>.<span class="name">link</span> <span class="op">=</span> <span class="name">link</span>
-
- <span class="kw">def </span><span class="fun">generate</span>(<span class="bn bn-pseudo">self</span>, <span class="name">normal</span>, <span class="name">active</span>, <span class="name">commata</span>, <span class="name">ellipsis</span>, <span class="name">threshold</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Generate a Pagination of the data defined in the constructor.
-
- :param normal: inserted string when the page isn&#39;t active
- :param active: inserted string when the page is active
- :param commata: inserted between links
- :param ellipsis: inserted as space indicator for skiped links
- :param threshold: number of links around start/current page and
- end before they will be replaced by an ellipsis
-
- ``normal`` and ``active`` can contain out of the following formatting
- chars:
-
- ====================== ==================================
- ``</span><span class="st st-int">%(page)s</span><span class="st">`` number of the current page
- ``</span><span class="st st-int">%(url)s</span><span class="st">`` absolute url of the current page
- ====================== ==================================
-
- Example::
-
- p.generate(&#39;&lt;a href=&quot;</span><span class="st st-int">%(url)s</span><span class="st">&quot;&gt;</span><span class="st st-int">%(page)s</span><span class="st">&lt;/a&gt;&#39;,
- &#39;&lt;strong&gt;</span><span class="st st-int">%(page)s</span><span class="st">&lt;/strong&gt;&#39;,
- &#39;, &#39;,
- &#39; ... &#39;,
- 3)
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">was_space</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
- <span class="name">result</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">idx</span> <span class="op op-word">in</span> <span class="bn">range</span>(<span class="nb nb-int">1</span>, <span class="bn bn-pseudo">self</span>.<span class="name">pages</span> <span class="op">+</span> <span class="nb nb-int">1</span>):
- <span class="kw">if</span> <span class="name">idx</span> <span class="op">&lt;=</span> <span class="name">threshold</span> <span class="op op-word">or</span> <span class="name">idx</span> <span class="op">&gt;</span> <span class="bn bn-pseudo">self</span>.<span class="name">pages</span> <span class="op">-</span> <span class="name">threshold</span> <span class="op op-word">or</span>\
- <span class="bn">abs</span>(<span class="bn bn-pseudo">self</span>.<span class="name">page</span> <span class="op">-</span> <span class="name">idx</span>) <span class="op">&lt;</span> <span class="name">math</span>.<span class="name">ceil</span>(<span class="name">threshold</span> <span class="op">/</span> <span class="nb nb-flt">2.0</span>):
- <span class="kw">if</span> <span class="name">result</span> <span class="op op-word">and</span> <span class="name">result</span>[<span class="op">-</span><span class="nb nb-int">1</span>] <span class="op">!=</span> <span class="name">ellipsis</span>:
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">commata</span>)
- <span class="name">was_space</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">if</span> <span class="name">idx</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">page</span>:
- <span class="name">schema</span> <span class="op">=</span> <span class="name">active</span>
-
- <span class="kw">else</span>:
- <span class="name">schema</span> <span class="op">=</span> <span class="name">normal</span>
- <span class="name">url</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">link</span>(<span class="name">idx</span>)
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">schema</span> <span class="op">%</span> {
- <span class="st st-sg">&#39;</span><span class="st">page</span><span class="st st-sg">&#39;</span>: <span class="name">idx</span>,
- <span class="st st-sg">&#39;</span><span class="st">url</span><span class="st st-sg">&#39;</span>: <span class="bn bn-pseudo">self</span>.<span class="name">req</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="name">url</span>),
- })
- <span class="kw">else</span>:
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">was_space</span>:
- <span class="name">was_space</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="name">result</span>.<span class="name">append</span>(<span class="name">ellipsis</span>)
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>.<span class="name">join</span>(<span class="name">result</span>)
-
- <span class="kw">def </span><span class="fun">__str__</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">generate</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%(page)s</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">[</span><span class="st st-int">%(page)s</span><span class="st">]</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="st st-sg">&#39;</span><span class="st"> ... </span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">3</span>)
-
-
-
-<span class="kw">class </span><span class="cls">PaginationTag</span>(<span class="name">Node</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Generates a pagination. requires a Pagination object at first
- argument::
-
- {% paginate forum.pagination
- &#39;&lt;a href=&quot;</span><span class="st st-int">%(link)s</span><span class="st">&quot;&gt;</span><span class="st st-int">%(page)s</span><span class="st">&lt;/a&gt;&#39;,
- &#39;&lt;strong&gt;</span><span class="st st-int">%(page)s</span><span class="st">&lt;/strong&gt;&#39;,
- &#39;, &#39;,
- &#39;...&#39;
-
- %}
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">rules</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="name">KeywordNode</span>(<span class="st st-sg">&#39;</span><span class="st">paginate</span><span class="st st-sg">&#39;</span>), <span class="name">VariableNode</span>(),
- <span class="name">CollectionNode</span>()]
- }
- <span class="kw">def </span><span class="fun">__init__</span>(<span class="bn bn-pseudo">self</span>, <span class="name">parser</span>, <span class="name">matched_tag</span>, <span class="name">handler_args</span>, <span class="name">stack</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">_variable</span> <span class="op">=</span> <span class="name">handler_args</span>[<span class="nb nb-int">1</span>]
- <span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span> <span class="op">=</span> <span class="name">handler_args</span>[<span class="nb nb-int">2</span>]
- <span class="name">Node</span>.<span class="name">__init__</span>(<span class="bn bn-pseudo">self</span>)
-
- <span class="kw">def </span><span class="fun">render</span>(<span class="bn bn-pseudo">self</span>, <span class="name">context</span>):
- <span class="name">pagination_controller</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_variable</span>.<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="kw">if</span> <span class="bn">len</span>(<span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>) <span class="op">&lt;</span> <span class="nb nb-int">4</span>:
- <span class="kw">raise</span> <span class="name">jinja</span>.<span class="name">exceptions</span>.<span class="name">TemplateRuntimeError</span>(<span class="st st-sg">&#39;</span><span class="st">invalid argument count </span><span class="st st-sg">&#39;</span>
-
- <span class="st st-sg">&#39;</span><span class="st">for {% paginate %}</span><span class="st st-sg">&#39;</span>)
- <span class="name">link_scheme</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>[<span class="nb nb-int">0</span>].<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="name">active_scheme</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>[<span class="nb nb-int">1</span>].<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="name">commata</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>[<span class="nb nb-int">2</span>].<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="name">ellipsis</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>[<span class="nb nb-int">3</span>].<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="kw">if</span> <span class="bn">len</span>(<span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>) <span class="op">==</span> <span class="nb nb-int">5</span>:
- <span class="name">threshold</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">_arguments</span>[<span class="nb nb-int">4</span>].<span class="name">resolve</span>(<span class="name">context</span>)
- <span class="kw">else</span>:
- <span class="name">threshold</span> <span class="op">=</span> <span class="nb nb-int">3</span>
-
- <span class="kw">return</span> <span class="name">pagination_controller</span>.<span class="name">generate</span>(<span class="name">link_scheme</span>, <span class="name">active_scheme</span>,
- <span class="name">commata</span>, <span class="name">ellipsis</span>, <span class="name">threshold</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="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.textfmt
- ~~~~~~~~~~~~~~~~~~~~~~
-
- Pocoo text processing interfaces.
-
- :copyright: 2006 by Georg Brandl, Armin Ronacher.
- :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">re</span>
-<span class="kw">from </span><span class="cls">xml.sax.saxutils</span><span class="kw"> import</span> <span class="name">quoteattr</span>
-
-<span class="kw">from </span><span class="cls">pocoo.http</span><span class="kw"> import</span> <span class="name">Request</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.html</span><span class="kw"> import</span> <span class="name">nl2br</span>, <span class="name">escape_html</span>, <span class="name">unescape_html</span>, <span class="name">urlize</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.pkg.core.smilies</span><span class="kw"> import</span> <span class="name">replace_smilies</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.activecache</span><span class="kw"> import</span> <span class="name">Node</span>, <span class="name">load_cache</span>, <span class="name">generate_cache</span>
-
-<span class="kw">from </span><span class="cls">pocoo.utils</span><span class="kw"> import</span> <span class="name">json</span>
-
-
-<span class="name">frozen_translation_re</span> <span class="op">=</span> <span class="name">re</span>.<span class="name">compile</span>(<span class="st st-sg">r&#39;</span><span class="st">&lt;trans(?: value=&quot;(.*?)&quot;)?&gt;(.*?)&lt;/trans&gt;</span><span class="st st-sg">&#39;</span>)
-
-
-
-<span class="kw">class </span><span class="cls">MarkupFormat</span>(<span class="name">Component</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- A text markup format, such as BBCode or HTML.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="cm">#: The relative path to the javascript file for the editor.</span>
- <span class="name">editor_javascript</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">!cobalt/core/PocooLib/BaseEditor.js</span><span class="st st-sg">&#39;</span>
-
- <span class="cm">#: Name for this format. must be lowercase</span>
- <span class="deco">@property</span>
- <span class="kw">def </span><span class="fun">name</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>.<span class="name">lower</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="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Title of this formatter.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">name</span>.<span class="name">title</span>()
-
- <span class="kw">def </span><span class="fun">parse</span>(<span class="bn bn-pseudo">self</span>, <span class="name">text</span>, <span class="name">signature</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- This method has to return either an activecache Node or an
- string/Unicode object.
-
- :param signature: If this is ``True`` the pocoo wants to parse
- a signature. For BBCode there could be special
- rules like allowed and disallowed tags etc.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">render_callback</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">callback</span>, <span class="name">data</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- If the ``parse`` method returns an activecache `CallbackNode`
- this method will be called for the define callback.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>
-
- <span class="kw">def </span><span class="fun">quote_text</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">text</span>, <span class="name">username</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- This has to quote a given text. For example a BBCode
- Markup Formatter should wrap the text in [quote].
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> <span class="name">text</span>
-
- <span class="kw">def </span><span class="fun">get_editor_options</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">signature</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- This method has to return a dict of JSON
- serializable values which get passed to the
- function ``initEditor()`` which is defined
- in the editor javascript file.
-
- If `signature` is ``True`` pocoo requested an editor for the
- signature and wants just the editor definitions which are
- relevant for an working signature editor. See the ``BBCode``
- text formatter for an example.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">return</span> {}
-
-
-<span class="kw">class </span><span class="cls">PlainText</span>(<span class="name">MarkupFormat</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This parser just breaks lines and creates links.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">name</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">plain</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">parse</span>(<span class="bn bn-pseudo">self</span>, <span class="name">text</span>, <span class="name">signature</span>):
- <span class="name">text</span> <span class="op">=</span> <span class="name">escape_html</span>(<span class="name">text</span>)
- <span class="name">text</span> <span class="op">=</span> <span class="name">nl2br</span>(<span class="name">text</span>)
- <span class="name">text</span> <span class="op">=</span> <span class="name">replace_smilies</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">text</span>)
- <span class="kw">return</span> <span class="name">urlize</span>(<span class="name">text</span>, <span class="nb nb-int">50</span>, <span class="bn bn-pseudo">True</span>)
-
- <span class="kw">def </span><span class="fun">quote_text</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>, <span class="name">text</span>, <span class="name">username</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="name">lines</span> <span class="op">=</span> [<span class="name">u</span><span class="st st-sg">&#39;</span><span class="st">&gt; </span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">line</span> <span class="kw">for</span> <span class="name">line</span> <span class="op op-word">in</span> <span class="name">text</span>.<span class="name">splitlines</span>()]
- <span class="kw">if</span> <span class="name">username</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">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">lines</span>.<span class="name">insert</span>(<span class="nb nb-int">0</span>, (<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st st-int">%s</span><span class="st"> wrote</span><span class="st st-sg">&#39;</span>) <span class="op">+</span> <span class="name">u</span><span class="st st-sg">&#39;</span><span class="st">:</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">username</span>)
- <span class="kw">return</span> <span class="name">u</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">def </span><span class="fun">parse</span>(<span class="name">ctx</span>, <span class="name">text</span>, <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">False</span>, <span class="name">syntax_parser</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Parses an text and returns a marshalled object. You then can
- put such an string into the database or push it to the
- render function.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn">isinstance</span>(<span class="name">text</span>, <span class="bn">unicode</span>):
- <span class="name">text</span> <span class="op">=</span> <span class="bn">unicode</span>(<span class="name">text</span>)
- <span class="kw">if</span> <span class="name">syntax_parser</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">syntax_parser</span> <span class="op">=</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">syntax_parser</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">plain</span><span class="st st-sg">&#39;</span>)
- <span class="name">syntax_parser</span> <span class="op">=</span> <span class="name">syntax_parser</span>.<span class="name">lower</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">MarkupFormat</span>):
- <span class="kw">if</span> <span class="name">comp</span>.<span class="name">name</span> <span class="op">==</span> <span class="name">syntax_parser</span>:
- <span class="name">node</span> <span class="op">=</span> <span class="name">comp</span>.<span class="name">parse</span>(<span class="name">text</span>, <span class="name">signature</span>)
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">node</span>, <span class="bn">basestring</span>):
- <span class="name">node</span> <span class="op">=</span> <span class="name">Node</span>(<span class="name">node</span>)
- <span class="kw">return</span> <span class="name">generate_cache</span>(<span class="name">node</span>, <span class="name">syntax_parser</span>)
- <span class="kw">else</span>:
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">Parser &quot;</span><span class="st st-int">%s</span><span class="st">&quot; not found</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">syntax_parser</span>)
-
-
-
-<span class="kw">def </span><span class="fun">render</span>(<span class="name">req</span>, <span class="name">data</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Renders a parsed data
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">node</span>, <span class="name">syntax_parser</span> <span class="op">=</span> <span class="name">load_cache</span>(<span class="name">data</span>)
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">MarkupFormat</span>):
- <span class="kw">if</span> <span class="name">comp</span>.<span class="name">name</span> <span class="op">==</span> <span class="name">syntax_parser</span>:
- <span class="kw">break</span>
-
- <span class="kw">else</span>:
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">syntax parser </span><span class="st st-int">%r</span><span class="st"> not found</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">syntax_parser</span>)
- <span class="kw">return</span> <span class="name">node</span>.<span class="name">render</span>(<span class="name">req</span>, <span class="name">comp</span>)
-
-
-
-<span class="kw">def </span><span class="fun">parse_and_render</span>(<span class="name">req</span>, <span class="name">text</span>, <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">False</span>, <span class="name">syntax_parser</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Parses and renders a text.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn">isinstance</span>(<span class="name">text</span>, <span class="bn">unicode</span>):
- <span class="name">text</span> <span class="op">=</span> <span class="bn">unicode</span>(<span class="name">text</span>)
- <span class="kw">if</span> <span class="name">syntax_parser</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">syntax_parser</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">syntax_parser</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">plain</span><span class="st st-sg">&#39;</span>)
- <span class="name">syntax_parser</span> <span class="op">=</span> <span class="name">syntax_parser</span>.<span class="name">lower</span>()
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">MarkupFormat</span>):
- <span class="kw">if</span> <span class="name">comp</span>.<span class="name">name</span> <span class="op">==</span> <span class="name">syntax_parser</span>:
- <span class="name">node</span> <span class="op">=</span> <span class="name">comp</span>.<span class="name">parse</span>(<span class="name">text</span>, <span class="name">signature</span>)
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">node</span>, <span class="bn">basestring</span>):
- <span class="name">node</span> <span class="op">=</span> <span class="name">Node</span>(<span class="name">node</span>)
- <span class="kw">return</span> <span class="name">node</span>.<span class="name">render</span>(<span class="name">req</span>, <span class="name">comp</span>)
- <span class="kw">else</span>:
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">Parser &quot;</span><span class="st st-int">%s</span><span class="st">&quot; not found</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">syntax_parser</span>)
-
-
-
-<span class="kw">def </span><span class="fun">get_editor</span>(<span class="name">req</span>, <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">False</span>, <span class="name">syntax_parser</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a tuple in the form (javascript_file, options)
- for the template. Both of them are strings which can be
- used directly in the template::
-
- &lt;script type=&quot;text/javascript&quot; src=&quot;{{ editorjs }}&quot;&gt;&lt;/script&gt;
-
- &lt;script type=&quot;text/javascript&quot;&gt;
- initEditor(&#39;id_of_textarea&#39;, &#39;id_of_toolbar&#39;, {{ options }});
- &lt;/script&gt;
-
- If you set `signature` to ``True`` it will just display the
- buttons which are relevant for the signature editor.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">if</span> <span class="name">syntax_parser</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">syntax_parser</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">syntax_parser</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">plain</span><span class="st st-sg">&#39;</span>).<span class="name">lower</span>()
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">MarkupFormat</span>):
- <span class="kw">if</span> <span class="name">comp</span>.<span class="name">name</span> <span class="op">==</span> <span class="name">syntax_parser</span>:
- <span class="name">js</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">make_url</span>(<span class="name">comp</span>.<span class="name">editor_javascript</span>)
- <span class="name">options</span> <span class="op">=</span> <span class="name">json</span>.<span class="name">dumps</span>(<span class="name">comp</span>.<span class="name">get_editor_options</span>(<span class="name">req</span>, <span class="name">signature</span>))
- <span class="kw">return</span> <span class="name">js</span>, <span class="name">options</span>
-
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">Parser &quot;</span><span class="st st-int">%s</span><span class="st">&quot; not found</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">syntax_parser</span>)
-
-
-<span class="kw">def </span><span class="fun">quote_text</span>(<span class="name">req</span>, <span class="name">text</span>, <span class="name">username</span><span class="op">=</span><span class="bn bn-pseudo">None</span>, <span class="name">syntax_parser</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Quote ``text`` with the style defined in the markup parser.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="name">syntax_parser</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">syntax_parser</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">syntax_parser</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">plain</span><span class="st st-sg">&#39;</span>).<span class="name">lower</span>()
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">MarkupFormat</span>):
- <span class="kw">if</span> <span class="name">comp</span>.<span class="name">name</span> <span class="op">==</span> <span class="name">syntax_parser</span>:
- <span class="kw">return</span> <span class="name">comp</span>.<span class="name">quote_text</span>(<span class="name">req</span>, <span class="name">text</span>, <span class="name">username</span>)
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">Parser &quot;</span><span class="st st-int">%s</span><span class="st">&quot; not found</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">syntax_parser</span>)
-
-
-
-<span class="kw">def </span><span class="fun">get_markup_formatters</span>(<span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return a list of known formatters
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">result</span> <span class="op">=</span> []
- <span class="kw">for</span> <span class="name">comp</span> <span class="op op-word">in</span> <span class="name">req</span>.<span class="name">ctx</span>.<span class="name">get_components</span>(<span class="name">MarkupFormat</span>):
- <span class="name">result</span>.<span class="name">append</span>((<span class="name">comp</span>.<span class="name">name</span>, <span class="name">comp</span>.<span class="name">get_title</span>(<span class="name">req</span>)))
- <span class="name">result</span>.<span class="name">sort</span>(<span class="name">key</span><span class="op">=</span><span class="kw">lambda</span> <span class="name">x</span>: <span class="name">x</span>[<span class="nb nb-int">1</span>].<span class="name">lower</span>())
- <span class="kw">return</span> <span class="name">result</span>
-
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.user
- ~~~~~~~~~~~~~~~~~~~
-
- User model and utilities.
-
- :copyright: 2006 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">os</span><span class="kw"> import</span> <span class="name">path</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">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.http</span><span class="kw"> import</span> <span class="name">DirectResponse</span>, <span class="name">AccessDeniedResponse</span>
-
-<span class="kw">from </span><span class="cls">pocoo.application</span><span class="kw"> import</span> <span class="name">LinkableMixin</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.text</span><span class="kw"> import</span> <span class="name">gen_password</span>, <span class="name">gen_activation_key</span>, <span class="name">gen_pwhash</span>, \
- <span class="name">check_pwhash</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.pkg.core.db</span><span class="kw"> import</span> <span class="name">users</span>, <span class="name">groups</span>, <span class="name">posts</span>, <span class="name">group_members</span>
-
-
-<span class="kw">def </span><span class="fun">get_all_usernames</span>(<span class="name">ctx</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return a list of all usernames.</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">users</span>.<span class="name">c</span>.<span class="name">username</span>]))
- <span class="kw">return</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="kw">def </span><span class="fun">get_id_username_mapping</span>(<span class="name">ctx</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return a ``user_id`` -&gt; ``username`` mapping.</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">users</span>.<span class="name">c</span>.<span class="name">user_id</span>, <span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span>]))
- <span class="kw">return</span> <span class="bn">dict</span>(<span class="bn">tuple</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">def </span><span class="fun">get_user_list</span>(<span class="name">ctx</span>, <span class="name">order_by</span><span class="op">=</span><span class="name">users</span>.<span class="name">c</span>.<span class="name">username</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="name">letter</span><span class="op">=</span><span class="bn bn-pseudo">None</span>,
- <span class="name">hide_internal</span><span class="op">=</span><span class="bn bn-pseudo">False</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return a list of all users with public details.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="cm">#XXX: sorting with databases sucks :-/ if sorted by username, resort</span>
- <span class="cm"># with python, and btw, this is ugly</span>
- <span class="name">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
- <span class="name">q</span> <span class="op">=</span> []
- <span class="kw">if</span> <span class="name">letter</span>:
- <span class="name">q</span>.<span class="name">append</span>(<span class="name">u</span>.<span class="name">username</span>.<span class="name">startswith</span>(<span class="name">letter</span>))
- <span class="kw">if</span> <span class="name">hide_internal</span>:
- <span class="name">q</span>.<span class="name">append</span>((<span class="name">u</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="op">&amp;</span> (<span class="name">u</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="kw">try</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="name">meta</span>.<span class="name">desc</span>,
- <span class="st st-sg">&#39;</span><span class="st">asc</span><span class="st st-sg">&#39;</span>: <span class="name">meta</span>.<span class="name">asc</span>
-
- }[<span class="name">order</span>]
- <span class="kw">except</span> <span class="exc">KeyError</span>:
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">order must be either </span><span class="st st-esc">\&#39;</span><span class="st">asc</span><span class="st st-esc">\&#39;</span><span class="st"> or </span><span class="st st-esc">\&#39;</span><span class="st">desc</span><span class="st st-esc">\&#39;</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">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">email</span>,
- <span class="name">u</span>.<span class="name">profile</span>, <span class="name">u</span>.<span class="name">last_login</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">meta</span>.<span class="name">and_</span>(<span class="op">*</span><span class="name">q</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">order</span>(<span class="name">order_by</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">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">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="kw">return</span> <span class="name">d</span>
-
- <span class="kw">return</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">def </span><span class="fun">get_all_groupnames</span>(<span class="name">ctx</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return a list of groupnames.</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">groups</span>.<span class="name">c</span>.<span class="name">name</span>]))
- <span class="kw">return</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="kw">def </span><span class="fun">get_id_groupname_mapping</span>(<span class="name">ctx</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return a group_id -&gt; groupname mapping.</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">groups</span>.<span class="name">c</span>.<span class="name">group_id</span>, <span class="name">groups</span>.<span class="name">c</span>.<span class="name">name</span>]))
- <span class="kw">return</span> <span class="bn">dict</span>(<span class="bn">tuple</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">def </span><span class="fun">get_group_list</span>(<span class="name">ctx</span>, <span class="name">order_by</span><span class="op">=</span><span class="name">groups</span>.<span class="name">c</span>.<span class="name">name</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="name">letter</span><span class="op">=</span><span class="bn bn-pseudo">None</span>,
- <span class="name">show_hidden</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 list of all groups with public details.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">g</span> <span class="op">=</span> <span class="name">groups</span>.<span class="name">c</span>
- <span class="name">q</span> <span class="op">=</span> []
- <span class="kw">if</span> <span class="name">letter</span>:
- <span class="name">q</span>.<span class="name">append</span>(<span class="name">g</span>.<span class="name">name</span>.<span class="name">startswith</span>(<span class="name">letter</span>))
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">show_hidden</span>:
- <span class="name">q</span>.<span class="name">append</span>(<span class="name">g</span>.<span class="name">hidden</span> <span class="op">==</span> <span class="bn bn-pseudo">True</span>)
- <span class="kw">try</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="name">meta</span>.<span class="name">desc</span>,
- <span class="st st-sg">&#39;</span><span class="st">asc</span><span class="st st-sg">&#39;</span>: <span class="name">meta</span>.<span class="name">asc</span>
-
- }[<span class="name">order</span>]
- <span class="kw">except</span> <span class="exc">KeyError</span>:
- <span class="kw">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">order must be either </span><span class="st st-esc">\&#39;</span><span class="st">asc</span><span class="st st-esc">\&#39;</span><span class="st"> or </span><span class="st st-esc">\&#39;</span><span class="st">desc</span><span class="st st-esc">\&#39;</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">g</span>.<span class="name">group_id</span>, <span class="name">g</span>.<span class="name">name</span>, <span class="name">g</span>.<span class="name">public</span>,
- <span class="name">g</span>.<span class="name">hidden</span>], <span class="name">meta</span>.<span class="name">and_</span>(<span class="op">*</span><span class="name">q</span>),
- <span class="name">order_by</span><span class="op">=</span>[<span class="name">order</span>(<span class="name">order_by</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">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">groups</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">name</span><span class="st st-sg">&#39;</span>]))
- <span class="kw">return</span> <span class="name">d</span>
-
- <span class="kw">return</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">def </span><span class="fun">get_user</span>(<span class="name">req</span>, <span class="name">user_id_or_name</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Return a dict of user information for the template.
- </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">u</span> <span class="op">=</span> <span class="name">users</span>.<span class="name">c</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">user_id_or_name</span>, (<span class="bn">int</span>, <span class="bn">long</span>)):
- <span class="name">q</span> <span class="op">=</span> (<span class="name">u</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id_or_name</span>)
- <span class="kw">else</span>:
- <span class="name">q</span> <span class="op">=</span> (<span class="name">u</span>.<span class="name">username</span> <span class="op">==</span> <span class="name">user_id_or_name</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">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">email</span>,
- <span class="name">u</span>.<span class="name">profile</span>, <span class="name">u</span>.<span class="name">settings</span>, <span class="name">u</span>.<span class="name">last_login</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">q</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: error return needed</span>
-
- <span class="kw">return</span>
- <span class="name">user</span> <span class="op">=</span> <span class="bn">dict</span>(<span class="name">row</span>)
- <span class="name">user</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">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="kw">return</span> <span class="name">user</span>
-
-
-<span class="kw">def </span><span class="fun">get_user_avatar</span>(<span class="name">req</span>, <span class="name">user_id_or_name</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Return the user avatar.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">user_id_or_name</span>, (<span class="bn">int</span>, <span class="bn">long</span>)):
- <span class="name">q</span> <span class="op">=</span> (<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id_or_name</span>)
- <span class="kw">else</span>:
- <span class="name">q</span> <span class="op">=</span> (<span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span> <span class="op">==</span> <span class="name">user_id_or_name</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">users</span>.<span class="name">c</span>.<span class="name">user_id</span>], <span class="name">q</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="op op-word">not</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">fn</span> <span class="op">=</span> <span class="name">path</span>.<span class="name">join</span>(<span class="name">req</span>.<span class="name">ctx</span>.<span class="name">cfg</span>.<span class="name">root</span>, <span class="st st-sg">&#39;</span><span class="st">avatars</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st st-int">%d</span><span class="st">.png</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">row</span>[<span class="nb nb-int">0</span>])
- <span class="kw">if</span> <span class="name">path</span>.<span class="name">exists</span>(<span class="name">fn</span>):
- <span class="name">f</span> <span class="op">=</span> <span class="bn">file</span>(<span class="name">fn</span>, <span class="st st-sg">&#39;</span><span class="st">rb</span><span class="st st-sg">&#39;</span>)
- <span class="name">result</span> <span class="op">=</span> <span class="name">f</span>.<span class="name">read</span>()
- <span class="name">f</span>.<span class="name">close</span>()
- <span class="kw">return</span> <span class="name">result</span>
-
-
-<span class="kw">def </span><span class="fun">get_id_by_name</span>(<span class="name">ctx</span>, <span class="name">name</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">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">u</span>.<span class="name">user_id</span>],
- <span class="name">u</span>.<span class="name">username</span> <span class="op">==</span> <span class="name">name</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="op op-word">not</span> <span class="name">row</span>:
- <span class="kw">raise</span> <span class="name">UserNotFound</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">check_login_data</span>(<span class="name">ctx</span>, <span class="name">username</span>, <span class="name">password</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Check if a username and password was found in the
- database. Returns None if the user does not exist
- or the password is incorrect, otherwise it returns
- the user id.
- </span><span class="st st-db">&quot;&quot;&quot;</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">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">u</span>.<span class="name">user_id</span>, <span class="name">u</span>.<span class="name">pwhash</span>, <span class="name">u</span>.<span class="name">act_key</span>],
- <span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span> <span class="op">==</span> <span class="name">username</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="op op-word">not</span> <span class="bn bn-pseudo">None</span> <span class="op op-word">and</span> <span class="op op-word">not</span> <span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">act_key</span><span class="st st-sg">&#39;</span>] <span class="op op-word">and</span> \
- <span class="name">check_pwhash</span>(<span class="name">row</span>[<span class="st st-sg">&#39;</span><span class="st">pwhash</span><span class="st st-sg">&#39;</span>], <span class="name">password</span>):
- <span class="kw">return</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="kw">def </span><span class="fun">sync_post_count</span>(<span class="name">ctx</span>, <span class="name">user_id</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Sync the user post count with the post tables.</span><span class="st st-db">&quot;&quot;&quot;</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">meta</span>.<span class="name">func</span>.<span class="name">count</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">author_id</span> <span class="op">==</span> <span class="name">user_id</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">user_id</span>),
- <span class="name">post_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="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">reset_password</span>(<span class="name">ctx</span>, <span class="name">username</span>, <span class="name">email</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- Reset the password and returns the new password
- if the email matched the username.
- If not it will return None.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">password</span> <span class="op">=</span> <span class="name">gen_password</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">users</span>.<span class="name">update</span>((<span class="name">users</span>.<span class="name">c</span>.<span class="name">username</span> <span class="op">==</span> <span class="name">username</span>) <span class="op">&amp;</span>
-
- (<span class="name">users</span>.<span class="name">c</span>.<span class="name">email</span> <span class="op">==</span> <span class="name">email</span>)),
- <span class="name">pwhash</span> <span class="op">=</span> <span class="name">gen_pwhash</span>(<span class="name">password</span>)
- )
- <span class="kw">if</span> <span class="name">result</span>.<span class="name">rowcount</span>:
- <span class="kw">return</span> <span class="name">password</span>
-
-
-<span class="kw">class </span><span class="cls">UserNotFound</span>(<span class="exc">Exception</span>):
- <span class="kw">pass</span>
-
-
-<span class="kw">class </span><span class="cls">User</span>(<span class="name">DatabaseModel</span>, <span class="name">LinkableMixin</span>):
- <span class="name">NotFound</span> <span class="op">=</span> <span class="name">UserNotFound</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">user_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">user_id</span> <span class="op">=</span> <span class="name">user_id</span>
- <span class="bn">super</span>(<span class="name">User</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">ctx</span>, <span class="name">users</span>, <span class="st st-sg">&#39;</span><span class="st">user_id</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">from </span><span class="cls">pocoo.pkg.core.acl</span><span class="kw"> import</span> <span class="name">AclManager</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">acl</span> <span class="op">=</span> <span class="name">AclManager</span>(<span class="name">ctx</span>, <span class="bn bn-pseudo">self</span>)
-
- <span class="name">subject_id</span> <span class="op">=</span> <span class="name">lazy_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">username</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">username</span><span class="st st-sg">&#39;</span>)
- <span class="name">email</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>)
- <span class="name">pwhash</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">pwhash</span><span class="st st-sg">&#39;</span>)
- <span class="name">act_key</span> <span class="op">=</span> <span class="name">lazy_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">language</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">language</span><span class="st st-sg">&#39;</span>)
- <span class="name">profile</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>)
- <span class="name">settings</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">settings</span><span class="st st-sg">&#39;</span>)
- <span class="name">last_login</span> <span class="op">=</span> <span class="name">lazy_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">register_date</span> <span class="op">=</span> <span class="name">lazy_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">post_count</span> <span class="op">=</span> <span class="name">lazy_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">read_threads</span> <span class="op">=</span> <span class="name">lazy_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">read_posts</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">read_posts</span><span class="st st-sg">&#39;</span>)
-
- <span class="deco">@property</span>
-
- <span class="kw">def </span><span class="fun">relative_url</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">users/</span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">username</span>
-
- <span class="deco">@staticmethod</span>
- <span class="kw">def </span><span class="fun">create</span>(<span class="name">ctx</span>, <span class="name">username</span>, <span class="name">password</span>, <span class="name">email</span>, <span class="name">activate</span><span class="op">=</span><span class="bn bn-pseudo">False</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Creates a new user.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="name">activate</span>:
- <span class="name">act_key</span> <span class="op">=</span> <span class="name">gen_activation_key</span>()
- <span class="kw">else</span>:
- <span class="name">act_key</span> <span class="op">=</span> <span class="bn bn-pseudo">None</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">users</span>.<span class="name">insert</span>(),
- <span class="name">username</span><span class="op">=</span><span class="name">username</span>,
- <span class="name">email</span><span class="op">=</span><span class="name">email</span>,
- <span class="name">act_key</span><span class="op">=</span><span class="name">act_key</span>,
- <span class="name">pwhash</span><span class="op">=</span><span class="name">gen_pwhash</span>(<span class="name">password</span>),
- <span class="name">register_date</span><span class="op">=</span><span class="name">datetime</span>.<span class="name">utcnow</span>(),
- <span class="name">post_count</span><span class="op">=</span><span class="nb nb-int">0</span>
-
- )
- <span class="kw">return</span> <span class="name">User</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">check_password</span>(<span class="bn bn-pseudo">self</span>, <span class="name">password</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">exists</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">return</span> <span class="name">check_pwhash</span>(<span class="bn bn-pseudo">self</span>.<span class="name">pwhash</span>, <span class="name">password</span>)
-
- <span class="kw">def </span><span class="fun">set_password</span>(<span class="bn bn-pseudo">self</span>, <span class="name">password</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">pwhash</span> <span class="op">=</span> <span class="name">gen_pwhash</span>(<span class="name">password</span>)
-
- <span class="kw">def </span><span class="fun">assert_logged_in</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Check if the user is logged in and raise a DirectResponse
- exception with an AccessDeniedResponse to display the user a
- login or &quot;missing permission&quot; page.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">identified</span>:
- <span class="kw">raise</span> <span class="name">DirectResponse</span>(<span class="name">AccessDeniedResponse</span>())
-
- <span class="kw">def </span><span class="fun">iter_groups</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
-
- Return a generator for all groups this user has joined.
- </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">groups</span>.<span class="name">c</span>.<span class="name">group_id</span>],
- (<span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">user_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="name">groups</span>.<span class="name">c</span>.<span class="name">group_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</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">yield</span> <span class="name">Group</span>(<span class="bn bn-pseudo">self</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">activate</span>(<span class="bn bn-pseudo">self</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">act_key</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">def </span><span class="fun">deactivate</span>(<span class="bn bn-pseudo">self</span>):
- <span class="bn bn-pseudo">self</span>.<span class="name">act_key</span> <span class="op">=</span> <span class="name">gen_activation_key</span>()
-
- <span class="deco">@property</span>
-
- <span class="kw">def </span><span class="fun">identified</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">user_id</span> <span class="op">&gt;</span> <span class="nb nb-int">0</span>
-
- <span class="deco">@property</span>
-
- <span class="kw">def </span><span class="fun">active</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="op op-word">not</span> <span class="bn bn-pseudo">self</span>.<span class="name">act_key</span>
-
- <span class="deco">@property</span>
-
- <span class="kw">def </span><span class="fun">groups</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn">list</span>(<span class="bn bn-pseudo">self</span>.<span class="name">iter_groups</span>())
-
- <span class="deco">@property</span>
- <span class="kw">def </span><span class="fun">admin</span>(<span class="bn bn-pseudo">self</span>):
- <span class="cm">#TODO: from ACL</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">True</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">user_id</span> <span class="op">==</span> <span class="name">other</span>.<span class="name">user_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">user_id</span>,
- <span class="bn bn-pseudo">self</span>.<span class="name">username</span>
-
- )
-
-
-<span class="kw">class </span><span class="cls">GroupNotFound</span>(<span class="exc">Exception</span>):
- <span class="kw">pass</span>
-
-
-<span class="kw">class </span><span class="cls">Group</span>(<span class="name">DatabaseModel</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">group_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">group_id</span> <span class="op">=</span> <span class="name">group_id</span>
- <span class="bn">super</span>(<span class="name">Group</span>, <span class="bn bn-pseudo">self</span>).<span class="name">__init__</span>(<span class="name">ctx</span>, <span class="name">groups</span>, <span class="st st-sg">&#39;</span><span class="st">group_id</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">from </span><span class="cls">pocoo.pkg.core.acl</span><span class="kw"> import</span> <span class="name">AclManager</span>
-
- <span class="bn bn-pseudo">self</span>.<span class="name">acl</span> <span class="op">=</span> <span class="name">AclManager</span>(<span class="name">ctx</span>, <span class="bn bn-pseudo">self</span>)
-
- <span class="name">subject_id</span> <span class="op">=</span> <span class="name">lazy_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">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">public</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">public</span><span class="st st-sg">&#39;</span>)
- <span class="name">hidden</span> <span class="op">=</span> <span class="name">lazy_column</span>(<span class="st st-sg">&#39;</span><span class="st">hidden</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">public</span><span class="op">=</span><span class="bn bn-pseudo">True</span>, <span class="name">hidden</span><span class="op">=</span><span class="bn bn-pseudo">False</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Create a new usergroup.</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">groups</span>.<span class="name">insert</span>(),
- <span class="name">name</span><span class="op">=</span><span class="name">name</span>,
- <span class="name">public</span><span class="op">=</span><span class="name">public</span>,
- <span class="name">hidden</span><span class="op">=</span><span class="name">hidden</span>
-
- )
- <span class="kw">return</span> <span class="name">Group</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="deco">@property</span>
- <span class="kw">def </span><span class="fun">members</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="bn">list</span>(<span class="bn bn-pseudo">self</span>.<span class="name">iter_members</span>())
-
- <span class="kw">def </span><span class="fun">iter_members</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Return a generator for all group members.</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">users</span>.<span class="name">c</span>.<span class="name">user_id</span>],
- (<span class="name">groups</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">group_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="name">groups</span>.<span class="name">c</span>.<span class="name">group_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">users</span>.<span class="name">c</span>.<span class="name">user_id</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">yield</span> <span class="name">User</span>(<span class="bn bn-pseudo">self</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">add_member</span>(<span class="bn bn-pseudo">self</span>, <span class="name">user</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Add a new member to the group.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">user</span>, <span class="name">User</span>):
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="kw">else</span>:
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">User</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">user</span>).<span class="name">user_id</span>
-
- <span class="cm"># check if the user is already a member of the group</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">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span>],
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">group_id</span>)
- ))
- <span class="kw">if</span> <span class="name">result</span>.<span class="name">fetchone</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">raise</span> <span class="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">The user </span><span class="st st-int">%d</span><span class="st"> is alreay a member of this group</span><span class="st st-sg">&#39;</span> <span class="op">%</span>
-
- <span class="name">user_id</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">group_members</span>.<span class="name">insert</span>(),
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">user_id</span>,
- <span class="name">group_id</span> <span class="op">=</span> <span class="bn bn-pseudo">self</span>.<span class="name">group_id</span>
-
- )
-
- <span class="kw">def </span><span class="fun">remove_member</span>(<span class="bn bn-pseudo">self</span>, <span class="name">user</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Remove a member from the group.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">user</span>, <span class="name">User</span>):
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="kw">else</span>:
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">User</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">user</span>).<span class="name">user_id</span>
-
- <span class="cm"># check if the user is not in the group</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">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span>],
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">group_id</span>)
- ))
- <span class="kw">if</span> <span class="name">result</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="exc">ValueError</span>(<span class="st st-sg">&#39;</span><span class="st">The user </span><span class="st st-int">%d</span><span class="st"> is not a member of this group</span><span class="st st-sg">&#39;</span> <span class="op">%</span>
-
- <span class="name">user_id</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">group_members</span>.<span class="name">delete</span>(
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">group_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id</span>)
- ))
-
- <span class="kw">def </span><span class="fun">is_member</span>(<span class="bn bn-pseudo">self</span>, <span class="name">user</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Check if a user is a member of this group.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">if</span> <span class="bn">isinstance</span>(<span class="name">user</span>, <span class="name">User</span>):
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="kw">else</span>:
- <span class="name">user_id</span> <span class="op">=</span> <span class="name">User</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>, <span class="name">user</span>).<span class="name">user_id</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">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span>],
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">user_id</span> <span class="op">==</span> <span class="name">user_id</span>) <span class="op">&amp;</span>
-
- (<span class="name">group_members</span>.<span class="name">c</span>.<span class="name">group_id</span> <span class="op">==</span> <span class="bn bn-pseudo">self</span>.<span class="name">group_id</span>)
- ))
- <span class="kw">return</span> <span class="name">result</span>.<span class="name">fetchone</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">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">group_id</span> <span class="op">==</span> <span class="name">other</span>.<span class="name">group_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">group_id</span>,
- <span class="bn bn-pseudo">self</span>.<span class="name">name</span>
-
- )
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.usersettings
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- User Settings support.
-
- :copyright: 2006 by Armin Ronacher, Lukas Meuser.
- :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">from </span><span class="cls">os</span><span class="kw"> import</span> <span class="name">path</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="kw">from </span><span class="cls">pocoo.application</span><span class="kw"> import</span> <span class="name">LinkableMixin</span>
-
-<span class="kw">from </span><span class="cls">pocoo.utils.image</span><span class="kw"> import</span> <span class="name">resize_image</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.form</span><span class="kw"> import</span> <span class="name">Form</span>, <span class="name">TextField</span>, <span class="name">FileField</span>, <span class="name">TextArea</span>, <span class="name">CheckBox</span>, \
- <span class="name">SelectBox</span>
-
-<span class="kw">from </span><span class="cls">pocoo.utils.validators</span><span class="kw"> import</span> <span class="name">isSameValue</span>, <span class="name">isEmail</span>, <span class="name">isExistingUrl</span>, \
- <span class="name">checkTextLength</span>, <span class="name">mayEmpty</span>, <span class="name">checkIfOtherNotBlank</span>, <span class="name">isSupportedImage</span>, \
- <span class="name">doMultiCheck</span>, <span class="name">isInRange</span>, <span class="name">isInteger</span>
-
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.validators</span><span class="kw"> import</span> <span class="name">isStrongPassword</span>, <span class="name">isIcqMessengerId</span>, \
- <span class="name">isMsnMessengerId</span>, <span class="name">isJabberMessengerId</span>
-<span class="kw">from </span><span class="cls">pocoo.pkg.core.textfmt</span><span class="kw"> import</span> <span class="name">get_editor</span>
-
-
-<span class="kw">class </span><span class="cls">UserSettingsPage</span>(<span class="name">Component</span>, <span class="name">LinkableMixin</span>):
-
- <span class="deco">@property</span>
- <span class="kw">def </span><span class="fun">settings_page_identifier</span>(<span class="bn bn-pseudo">self</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">The name of the page which is also the url
- under which the page will be visible::
-
- /settings/$SETTINGS_PAGE_IDENTIFIER$</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">self</span>.<span class="name">__class__</span>.<span class="name">__name__</span>
-
- <span class="deco">@property</span>
- <span class="kw">def </span><span class="fun">relative_url</span>(<span class="bn bn-pseudo">self</span>):
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">settings/</span><span class="st st-int">%s</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="bn bn-pseudo">self</span>.<span class="name">settings_page_identifier</span>
-
- <span class="kw">def </span><span class="fun">get_settings_link_title</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Has to return a text for the link title in the
- settings sidebar (this musn&#39;t be a sidebar, in fact
- it depends on the template.
-
- If the method returns ``None`` the template wont
- render this link.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">get_settings_page</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">This method automatically gets called when a
- user requests this settings page. It must either
- return a valid Response object or a tuple in the
- form (template, context) where template is a string
- with the template filename and context is a dict
- which automatically gets updated with the generated
- sidebar so that templates can access it.</span><span class="st st-db">&quot;&quot;&quot;</span>
-
-
-
-<span class="kw">class </span><span class="cls">UserSignatureSettings</span>(<span class="name">UserSettingsPage</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This page allows the user to create / edit his signature
- using an editor.
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">settings_page_identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_settings_link_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">Signature</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_settings_page</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="name">get_setting</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">x</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>.<span class="name">get</span>(<span class="name">x</span>, <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>)
- <span class="name">msg</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextArea</span>(<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">signature</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">0</span>, <span class="nb nb-int">255</span>) <span class="cm"># from config!</span>
-
- )
- )
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>.<span class="name">update</span>(<span class="name">d</span>)
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">save</span>()
- <span class="name">msg</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Signature saved</span><span class="st st-sg">&#39;</span>)
-
- <span class="name">js</span>, <span class="name">options</span> <span class="op">=</span> <span class="name">get_editor</span>(<span class="name">req</span>, <span class="name">signature</span><span class="op">=</span><span class="bn bn-pseudo">True</span>)
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">settings/signature.html</span><span class="st st-sg">&#39;</span>, {
- <span class="st st-sg">&#39;</span><span class="st">form</span><span class="st st-sg">&#39;</span>: <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">msg</span><span class="st st-sg">&#39;</span>: <span class="name">msg</span>,
- <span class="st st-sg">&#39;</span><span class="st">editor_options</span><span class="st st-sg">&#39;</span>: <span class="name">options</span>,
- <span class="st st-sg">&#39;</span><span class="st">editor_javascript</span><span class="st st-sg">&#39;</span>:<span class="name">js</span>
-
- }
-
-
-<span class="kw">class </span><span class="cls">UserProfileSettings</span>(<span class="name">UserSettingsPage</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This page allows the user to edit his public information.
-
- XXX: make this more flexible -- later (LATER!!!!)
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">settings_page_identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">profile</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_settings_link_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">Profile</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_settings_page</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="name">get_setting</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">x</span>: <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>.<span class="name">get</span>(<span class="name">x</span>, <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>)
- <span class="name">msg</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="cm"># general information</span>
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">new_password</span><span class="st st-sg">&#39;</span>,
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isStrongPassword</span>())
- ),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">new_password2</span><span class="st st-sg">&#39;</span>,
- <span class="name">validator</span><span class="op">=</span><span class="name">checkIfOtherNotBlank</span>(<span class="st st-sg">&#39;</span><span class="st">new_password</span><span class="st st-sg">&#39;</span>,
- <span class="name">isSameValue</span>(<span class="st st-sg">&#39;</span><span class="st">new_password</span><span class="st st-sg">&#39;</span>,
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The two passwords must match</span><span class="st st-sg">&#39;</span>))
- )
- ),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">email</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">req</span>.<span class="name">user</span>.<span class="name">email</span>,
- <span class="name">validator</span><span class="op">=</span><span class="name">isEmail</span>()
- ),
- <span class="name">CheckBox</span>(<span class="st st-sg">&#39;</span><span class="st">show_email</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</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">show_email</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="bn bn-pseudo">False</span>
-
- ),
- <span class="cm"># instant messengers</span>
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">aol</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">aol</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>()
- ), <span class="cm"># need a validator</span>
-
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">icq</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">icq</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isIcqMessengerId</span>())
- ), <span class="cm"># need a validator</span>
-
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">jabber</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">jabber</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isJabberMessengerId</span>())
- ), <span class="cm"># need a validator</span>
-
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">msn</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">msn</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isMsnMessengerId</span>())
- ), <span class="cm"># need a validator</span>
-
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">yahoo</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">yahoo</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>()
- ), <span class="cm"># need a validator</span>
-
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">website</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">website</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isExistingUrl</span>())
- ),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">location</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">location</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">0</span>, <span class="nb nb-int">255</span>),
- ),
- <span class="name">TextArea</span>(<span class="st st-sg">&#39;</span><span class="st">interests</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</span><span class="op">=</span><span class="name">get_setting</span>(<span class="st st-sg">&#39;</span><span class="st">interests</span><span class="st st-sg">&#39;</span>),
- <span class="name">validator</span><span class="op">=</span><span class="name">checkTextLength</span>(<span class="nb nb-int">0</span>, <span class="nb nb-int">512</span>)
- )
- )
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="cm"># set special setting values</span>
-
- <span class="kw">if</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">new_password</span><span class="st st-sg">&#39;</span>]:
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">set_password</span>(<span class="name">d</span>.<span class="name">pop</span>(<span class="st st-sg">&#39;</span><span class="st">new_password</span><span class="st st-sg">&#39;</span>))
- <span class="kw">else</span>:
- <span class="kw">del</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">new_password</span><span class="st st-sg">&#39;</span>]
- <span class="kw">del</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">new_password2</span><span class="st st-sg">&#39;</span>]
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">email</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">email</span><span class="st st-sg">&#39;</span>)
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">settings</span>.<span class="name">update</span>({<span class="st st-sg">&#39;</span><span class="st">show_email</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">show_email</span><span class="st st-sg">&#39;</span>)})
- <span class="cm"># update other profile fields</span>
-
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>.<span class="name">update</span>(<span class="name">d</span>)
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">save</span>()
- <span class="name">msg</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Settings saved</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">settings/profile.html</span><span class="st st-sg">&#39;</span>, {
- <span class="st st-sg">&#39;</span><span class="st">form</span><span class="st st-sg">&#39;</span>: <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">msg</span><span class="st st-sg">&#39;</span>: <span class="name">msg</span>
-
- }
-
-
-<span class="kw">class </span><span class="cls">AvatarSettings</span>(<span class="name">UserSettingsPage</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This page allows the user to update his avatar
- </span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="name">settings_page_identifier</span> <span class="op">=</span> <span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>
-
- <span class="kw">def </span><span class="fun">get_settings_link_title</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="kw">if</span> <span class="name">req</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">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">allow_avatars</span><span class="st st-sg">&#39;</span>, <span class="bn bn-pseudo">True</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">Avatar</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_settings_page</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">req</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">board</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">allow_avatars</span><span class="st st-sg">&#39;</span>, <span class="bn bn-pseudo">True</span>):
- <span class="kw">return</span> <span class="name">PageNotFound</span>()
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="name">msg</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">def </span><span class="fun">make_small_thumbnail</span>(<span class="name">value</span>):
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">value</span>:
- <span class="kw">return</span>
-
- <span class="name">dim</span> <span class="op">=</span> <span class="bn bn-pseudo">self</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">avatar_dimension</span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">80</span>)
- <span class="kw">return</span> <span class="name">resize_image</span>(<span class="name">value</span>, <span class="name">dim</span>, <span class="name">dim</span>, <span class="st st-sg">&#39;</span><span class="st">image/png</span><span class="st st-sg">&#39;</span>)
-
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">FileField</span>(<span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>,
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">isSupportedImage</span>()),
- <span class="name">manipulator</span><span class="op">=</span><span class="name">make_small_thumbnail</span>
-
- ),
- <span class="name">CheckBox</span>(<span class="st st-sg">&#39;</span><span class="st">delete_avatar</span><span class="st st-sg">&#39;</span>)
- )
- <span class="name">avatar</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">files</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="name">uid</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="name">fn</span> <span class="op">=</span> <span class="name">path</span>.<span class="name">join</span>(<span class="bn bn-pseudo">self</span>.<span class="name">ctx</span>.<span class="name">cfg</span>.<span class="name">root</span>, <span class="st st-sg">&#39;</span><span class="st">avatars</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st st-int">%d</span><span class="st">.png</span><span class="st st-sg">&#39;</span> <span class="op">%</span> <span class="name">uid</span>)
- <span class="kw">if</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">delete_avatar</span><span class="st st-sg">&#39;</span>]:
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>[<span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>] <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="kw">if</span> <span class="name">path</span>.<span class="name">exists</span>(<span class="name">fn</span>):
- <span class="name">os</span>.<span class="name">unlink</span>(<span class="name">fn</span>)
- <span class="kw">elif</span> <span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>]:
- <span class="name">uid</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">user_id</span>
-
- <span class="name">f</span> <span class="op">=</span> <span class="bn">file</span>(<span class="name">fn</span>, <span class="st st-sg">&#39;</span><span class="st">wb</span><span class="st st-sg">&#39;</span>)
- <span class="name">f</span>.<span class="name">write</span>(<span class="name">d</span>[<span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>])
- <span class="name">f</span>.<span class="name">close</span>()
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>[<span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>] <span class="op">=</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">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">req</span>.<span class="name">user</span>.<span class="name">username</span>), <span class="name">show</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>)
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">save</span>()
- <span class="name">msg</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Settings saved</span><span class="st st-sg">&#39;</span>)
- <span class="cm"># TODO: support for linked avatars and gravatars</span>
-
- <span class="kw">elif</span> <span class="name">req</span>.<span class="name">user</span>.<span class="name">profile</span>.<span class="name">get</span>(<span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>):
- <span class="name">avatar</span> <span class="op">=</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">users</span><span class="st st-sg">&#39;</span>, <span class="name">urlencode</span>(<span class="name">req</span>.<span class="name">user</span>.<span class="name">username</span>),
- <span class="name">show</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>)
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">settings/avatar.html</span><span class="st st-sg">&#39;</span>, {
- <span class="st st-sg">&#39;</span><span class="st">form</span><span class="st st-sg">&#39;</span>: <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">avatar</span><span class="st st-sg">&#39;</span>: <span class="name">avatar</span>,
- <span class="st st-sg">&#39;</span><span class="st">msg</span><span class="st st-sg">&#39;</span>: <span class="name">msg</span>
-
- }
-
-
-<span class="kw">class </span><span class="cls">UserForumSettings</span>(<span class="name">UserSettingsPage</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- This page allows the user to update his forum view settings
- (ie. view mode and posts and threads per page)
- </span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="name">settings_page_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_settings_link_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">Forum Settings</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">def </span><span class="fun">get_settings_page</span>(<span class="bn bn-pseudo">self</span>, <span class="name">req</span>):
- <span class="kw">def </span><span class="fun">int_or_none</span>(<span class="name">x</span>):
- <span class="st st-db">&quot;</span><span class="st">manipulator which returns an int or None</span><span class="st st-db">&quot;</span>
-
- <span class="kw">try</span>:
- <span class="kw">return</span> <span class="bn">int</span>(<span class="name">x</span>)
- <span class="kw">except</span> <span class="exc">ValueError</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="name">req</span>.<span class="name">gettext</span>
- <span class="name">msg</span> <span class="op">=</span> <span class="bn bn-pseudo">None</span>
-
- <span class="name">form</span> <span class="op">=</span> <span class="name">Form</span>(<span class="name">req</span>, <span class="bn bn-pseudo">self</span>, <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>,
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">posts_per_page</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</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">posts_per_page</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>,
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">doMultiCheck</span>(<span class="name">isInteger</span>(), <span class="name">isInRange</span>(<span class="nb nb-int">5</span>, <span class="nb nb-int">50</span>))),
- <span class="name">manipulator</span><span class="op">=</span><span class="name">int_or_none</span>
-
- ),
- <span class="name">TextField</span>(<span class="st st-sg">&#39;</span><span class="st">threads_per_page</span><span class="st st-sg">&#39;</span>,
- <span class="name">default</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">threads_per_page</span><span class="st st-sg">&#39;</span>) <span class="op op-word">or</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>,
- <span class="name">validator</span><span class="op">=</span><span class="name">mayEmpty</span>(<span class="name">doMultiCheck</span>(<span class="name">isInteger</span>(), <span class="name">isInRange</span>(<span class="nb nb-int">10</span>, <span class="nb nb-int">80</span>))),
- <span class="name">manipulator</span><span class="op">=</span><span class="name">int_or_none</span>
-
- ),
- <span class="name">SelectBox</span>(<span class="st st-sg">&#39;</span><span class="st">view_mode</span><span class="st st-sg">&#39;</span>, [
- (<span class="st st-sg">&#39;&#39;</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">default</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="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">threaded</span><span class="st st-sg">&#39;</span>)),
- (<span class="st st-sg">&#39;</span><span class="st">flat</span><span class="st st-sg">&#39;</span>, <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">flat</span><span class="st st-sg">&#39;</span>))
- ], <span class="name">default</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="op op-word">or</span> <span class="name">u</span><span class="st st-sg">&#39;&#39;</span>
-
- )
- )
-
- <span class="kw">if</span> <span class="name">req</span>.<span class="name">method</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">POST</span><span class="st st-sg">&#39;</span>:
- <span class="name">form</span>.<span class="name">update</span>(<span class="name">req</span>.<span class="name">form</span>, <span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">form</span>.<span class="name">has_errors</span>:
- <span class="name">d</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">to_dict</span>()
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">settings</span>.<span class="name">update</span>(<span class="name">d</span>)
- <span class="name">req</span>.<span class="name">user</span>.<span class="name">save</span>()
- <span class="name">msg</span> <span class="op">=</span> <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Forum settings saved</span><span class="st st-sg">&#39;</span>)
-
- <span class="kw">return</span> <span class="st st-sg">&#39;</span><span class="st">settings/forumsettings.html</span><span class="st st-sg">&#39;</span>, {
- <span class="st st-sg">&#39;</span><span class="st">form</span><span class="st st-sg">&#39;</span>: <span class="name">form</span>.<span class="name">generate</span>(<span class="name">prefix</span><span class="op">=</span><span class="st st-sg">&#39;</span><span class="st">f_</span><span class="st st-sg">&#39;</span>),
- <span class="st st-sg">&#39;</span><span class="st">msg</span><span class="st st-sg">&#39;</span>: <span class="name">msg</span>
-
- }
-<span class="cm"># -*- coding: utf-8 -*-</span>
-<span class="st st-db">&quot;&quot;&quot;</span><span class="st">
- pocoo.pkg.core.validators
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Special validation, in addition to `pocoo.utils.validators`.
-
- For a general explanation of the validators system, please
- see `pocoo.utils.form`.
-
-
- :copyright: 2006 by Armin Ronacher.
- :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">re</span>
-<span class="kw">import </span><span class="cls">unicodedata</span>
-<span class="kw">from </span><span class="cls">pocoo.utils.validators</span><span class="kw"> import</span> <span class="name">ValidationError</span>, <span class="name">_mail_re</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="name">get_id_by_name</span>
-
-<span class="name">_icq_re</span> <span class="op">=</span> <span class="name">re</span>.<span class="name">compile</span>(<span class="st st-sg">r&#39;</span><span class="st">^\d{6,9}$</span><span class="st st-sg">&#39;</span>)
-
-
-
-<span class="cm"># pylint: disable-msg=C0103</span>
-
-<span class="kw">def </span><span class="fun">isValidUsername</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the given string looks like a valid username.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_valid_username</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="name">errors</span> <span class="op">=</span> []
- <span class="name">_</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">s</span>: <span class="name">errors</span>.<span class="name">append</span>(<span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="name">s</span>))
- <span class="name">value</span> <span class="op">=</span> <span class="name">field</span>.<span class="name">value</span>.<span class="name">strip</span>()
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">value</span>) <span class="op">&lt;</span> <span class="nb nb-int">2</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a username that is at least 2 characters long.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">value</span>) <span class="op">&gt;</span> <span class="nb nb-int">30</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a username that is no longer than 30 characters.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">for</span> <span class="name">char</span> <span class="op op-word">in</span> <span class="name">value</span>:
- <span class="kw">if</span> <span class="name">char</span> <span class="op op-word">in</span> <span class="st st-sg">&#39;</span><span class="st">_-. </span><span class="st st-sg">&#39;</span>:
- <span class="kw">continue</span>
-
- <span class="kw">if</span> <span class="name">unicodedata</span>.<span class="name">category</span>(<span class="name">char</span>)[<span class="nb nb-int">0</span>] <span class="op op-word">not</span> <span class="op op-word">in</span> <span class="st st-sg">&#39;</span><span class="st">LN</span><span class="st st-sg">&#39;</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a username without special characters </span><span class="st st-sg">&#39;</span>
-
- <span class="st st-sg">&#39;</span><span class="st">except &quot;_&quot;, &quot;-&quot;, &quot;.&quot;.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">break</span>
- <span class="kw">if</span> <span class="name">errors</span>:
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="op">*</span><span class="name">errors</span>)
- <span class="kw">return</span> <span class="name">is_valid_username</span>
-
-
-<span class="kw">def </span><span class="fun">isAvailableUsername</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the username is valid and available.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_available_username</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="name">isValidUsername</span>()(<span class="name">field</span>, <span class="name">form</span>)
- <span class="kw">try</span>:
- <span class="name">get_id_by_name</span>(<span class="name">form</span>.<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">field</span>.<span class="name">value</span>)
- <span class="kw">except</span> <span class="name">User</span>.<span class="name">NotFound</span>:
- <span class="kw">return</span>
-
- <span class="name">_</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The username is already in use.</span><span class="st st-sg">&#39;</span>))
- <span class="kw">return</span> <span class="name">is_available_username</span>
-
-
-<span class="kw">def </span><span class="fun">isAnonymousUsername</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if this is a valid username for anonymous usage.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_anonymous_username</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="kw">if</span> <span class="name">field</span>.<span class="name">value</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">isAvailableUsername</span>()(<span class="name">field</span>, <span class="name">form</span>)
- <span class="kw">return</span> <span class="name">is_anonymous_username</span>
-
-
-<span class="kw">def </span><span class="fun">isExistingUsername</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the username does exist.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_existing_username</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="kw">try</span>:
- <span class="name">get_id_by_name</span>(<span class="name">form</span>.<span class="name">req</span>.<span class="name">ctx</span>, <span class="name">field</span>.<span class="name">value</span>)
- <span class="kw">return</span>
-
- <span class="kw">except</span> <span class="name">User</span>.<span class="name">NotFound</span>:
- <span class="name">_</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">The user </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">field</span>.<span class="name">value</span>)
- <span class="kw">return</span> <span class="name">is_existing_username</span>
-
-
-<span class="kw">def </span><span class="fun">isStrongPassword</span>(<span class="name">strength</span><span class="op">=</span><span class="bn bn-pseudo">None</span>):
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the password is strong enough</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_strong_password</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="name">errors</span> <span class="op">=</span> []
- <span class="name">_</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">s</span>: <span class="name">errors</span>.<span class="name">append</span>(<span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="name">s</span>))
- <span class="kw">if</span> <span class="name">strength</span> <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">s</span> <span class="op">=</span> <span class="name">form</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">security</span><span class="st st-sg">&#39;</span>, <span class="st st-sg">&#39;</span><span class="st">password_strength</span><span class="st st-sg">&#39;</span>, <span class="nb nb-int">3</span>)
- <span class="kw">else</span>:
- <span class="name">s</span> <span class="op">=</span> <span class="name">strength</span>
-
- <span class="name">s</span> <span class="op">=</span> <span class="bn">max</span>(<span class="nb nb-int">0</span>, <span class="bn">min</span>(<span class="nb nb-int">4</span>, <span class="name">s</span>))
- <span class="kw">if</span> <span class="op op-word">not</span> <span class="name">s</span> <span class="op op-word">and</span> <span class="op op-word">not</span> <span class="name">field</span>.<span class="name">value</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please fill out the password field.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">elif</span> <span class="name">s</span> <span class="op">==</span> <span class="nb nb-int">1</span>:
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op">&lt;</span> <span class="nb nb-int">4</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a password with at least 4 characters.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">elif</span> <span class="name">s</span> <span class="op">==</span> <span class="nb nb-int">2</span>:
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op">&lt;</span> <span class="nb nb-int">6</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a password with at least 6 characters.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">elif</span> <span class="name">s</span> <span class="op">==</span> <span class="nb nb-int">3</span>:
- <span class="kw">def </span><span class="fun">test</span>():
- <span class="name">have_letter</span> <span class="op">=</span> <span class="name">have_number</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">for</span> <span class="name">char</span> <span class="op op-word">in</span> <span class="name">field</span>.<span class="name">value</span>:
- <span class="name">c</span> <span class="op">=</span> <span class="name">unicodedata</span>.<span class="name">category</span>(<span class="name">char</span>)[<span class="nb nb-int">0</span>]
- <span class="kw">if</span> <span class="name">c</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">L</span><span class="st st-sg">&#39;</span>:
- <span class="name">have_letter</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="kw">elif</span> <span class="name">c</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">N</span><span class="st st-sg">&#39;</span>:
- <span class="name">have_number</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
- <span class="kw">if</span> <span class="name">have_letter</span> <span class="op op-word">and</span> <span class="name">have_number</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">True</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">False</span>
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op">&lt;</span> <span class="nb nb-int">6</span> <span class="op op-word">or</span> <span class="op op-word">not</span> <span class="name">test</span>():
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a password with at least 6 characters which </span><span class="st st-sg">&#39;</span>
-
- <span class="st st-sg">&#39;</span><span class="st">contains both letters and numbers.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">elif</span> <span class="name">s</span> <span class="op">==</span> <span class="nb nb-int">4</span>:
- <span class="kw">def </span><span class="fun">test</span>():
- <span class="name">have_letter</span> <span class="op">=</span> <span class="name">have_number</span>, <span class="name">have_special</span> <span class="op">=</span> <span class="bn bn-pseudo">False</span>
-
- <span class="kw">for</span> <span class="name">char</span> <span class="op op-word">in</span> <span class="name">field</span>.<span class="name">value</span>:
- <span class="name">c</span> <span class="op">=</span> <span class="name">unicodedata</span>.<span class="name">category</span>(<span class="name">char</span>)[<span class="nb nb-int">0</span>]
- <span class="kw">if</span> <span class="name">c</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">L</span><span class="st st-sg">&#39;</span>:
- <span class="name">have_letter</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="kw">elif</span> <span class="name">c</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">N</span><span class="st st-sg">&#39;</span>:
- <span class="name">have_number</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
- <span class="kw">elif</span> <span class="name">c</span> <span class="op">==</span> <span class="st st-sg">&#39;</span><span class="st">S</span><span class="st st-sg">&#39;</span>:
- <span class="name">have_special</span> <span class="op">=</span> <span class="bn bn-pseudo">True</span>
-
- <span class="kw">if</span> <span class="name">have_letter</span> <span class="op op-word">and</span> <span class="name">have_number</span> <span class="op op-word">and</span> <span class="name">have_special</span>:
- <span class="kw">return</span> <span class="bn bn-pseudo">True</span>
-
- <span class="kw">return</span> <span class="bn bn-pseudo">False</span>
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op">&lt;</span> <span class="nb nb-int">6</span> <span class="op op-word">or</span> <span class="op op-word">not</span> <span class="name">test</span>():
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a password with at least 6 characters with </span><span class="st st-sg">&#39;</span>
-
- <span class="st st-sg">&#39;</span><span class="st">contains of letters, numbers and at least one special </span><span class="st st-sg">&#39;</span>
- <span class="st st-sg">&#39;</span><span class="st">character.</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="name">errors</span>:
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="op">*</span><span class="name">errors</span>)
- <span class="kw">return</span> <span class="name">is_strong_password</span>
-
-
-
-<span class="kw">def </span><span class="fun">isValidSignature</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the signature is valid.</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_valid_signature</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="name">errors</span> <span class="op">=</span> []
- <span class="name">_</span> <span class="op">=</span> <span class="kw">lambda</span> <span class="name">s</span>: <span class="name">errors</span>.<span class="name">append</span>(<span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>(<span class="name">s</span>))
- <span class="name">val</span> <span class="op">=</span> <span class="name">field</span>.<span class="name">value</span>.<span class="name">strip</span>()
- <span class="name">max_len</span> <span class="op">=</span> <span class="name">form</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">signature_length</span><span class="st st-sg">&#39;</span>)
- <span class="name">max_lines</span> <span class="op">=</span> <span class="name">form</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">signature_lines</span><span class="st st-sg">&#39;</span>)
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">val</span>) <span class="op">&gt;</span> <span class="name">max_len</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Your signature must not be longer than </span><span class="st st-int">%d</span><span class="st"> characters.</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">max_len</span>
-
- <span class="kw">if</span> <span class="bn">len</span>(<span class="name">val</span>.<span class="name">splitlines</span>()) <span class="op">&gt;</span> <span class="name">max_lines</span>:
- <span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Your signature must not be longer than </span><span class="st st-int">%d</span><span class="st"> lines.</span><span class="st st-sg">&#39;</span>) <span class="op">%</span> <span class="name">max_lines</span>
-
- <span class="kw">if</span> <span class="name">errors</span>:
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="op">*</span><span class="name">errors</span>)
- <span class="kw">return</span> <span class="name">is_valid_signature</span>
-
-<span class="kw">def </span><span class="fun">isIcqMessengerId</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the value is a valid ICQ ID</span><span class="st st-db">&quot;&quot;&quot;</span>
- <span class="kw">def </span><span class="fun">is_icq_messenger_id</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="kw">if</span> <span class="name">_icq_re</span>.<span class="name">search</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">_</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a valid ICQ ID</span><span class="st st-sg">&#39;</span>))
- <span class="kw">return</span> <span class="name">is_icq_messenger_id</span>
-
-
-<span class="kw">def </span><span class="fun">isJabberMessengerId</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the value is a valid jabber ID</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">is_jabber_messenger_id</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="kw">if</span> <span class="name">_mail_re</span>.<span class="name">search</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">_</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a valid jabber ID</span><span class="st st-sg">&#39;</span>))
- <span class="kw">return</span> <span class="name">is_jabber_messenger_id</span>
-
-
-<span class="kw">def </span><span class="fun">isMsnMessengerId</span>():
- <span class="st st-db">&quot;&quot;&quot;</span><span class="st">Checks if the value is a valid MSN ID</span><span class="st st-db">&quot;&quot;&quot;</span>
-
- <span class="kw">def </span><span class="fun">is_msn_messenger_id</span>(<span class="name">field</span>, <span class="name">form</span>):
- <span class="kw">if</span> <span class="name">_mail_re</span>.<span class="name">search</span>(<span class="name">field</span>.<span class="name">value</span>) <span class="op op-word">is</span> <span class="bn bn-pseudo">None</span>:
- <span class="name">_</span> <span class="op">=</span> <span class="name">form</span>.<span class="name">req</span>.<span class="name">gettext</span>
-
- <span class="kw">raise</span> <span class="name">ValidationError</span>(<span class="name">_</span>(<span class="st st-sg">&#39;</span><span class="st">Please enter a valid MSN ID.</span><span class="st st-sg">&#39;</span>))
- <span class="kw">return</span> <span class="name">is_msn_messenger_id</span>
-
-
-<span class="cm"># TODO: I don&#39;t know how valid AIM and Y!M IDs look, so I can&#39;t write validators</span>
-
-<span class="cm"># for them. It looks like they are simple strings, but I&#39;m not sure...</span>
</pre>
<script type="text/javascript">initCodeBlock('code-block')</script>
</body>
diff --git a/tests/test_basic_api.py b/tests/test_basic_api.py
index a4e55366..c929fde8 100644
--- a/tests/test_basic_api.py
+++ b/tests/test_basic_api.py
@@ -7,6 +7,82 @@
:license: GNU GPL, see LICENSE for more details.
"""
-from pygments import highlight
+import unittest
+import StringIO
+import random
-# ... TODO ...
+from pygments import lexers, formatters
+from pygments.token import _TokenType
+
+test_content = [chr(i) for i in xrange(33, 128)] * 5
+random.shuffle(test_content)
+test_content = ''.join(test_content) + '\n'
+
+class LexersTest(unittest.TestCase):
+
+ def test_lexer_classes(self):
+ a = self.assert_
+ ae = self.assertEquals
+ # test that every lexer class has the correct public API
+ for lexer in lexers._iter_lexerclasses():
+ for attr in 'name', 'aliases', 'filenames', 'alias_filenames', 'mimetypes':
+ a(hasattr(lexer, attr))
+ result = lexer.analyse_text("abc")
+ a(isinstance(result, float) and 0.0 <= result <= 1.0)
+
+ inst = lexer(opt1="val1", opt2="val2")
+ tokens = list(inst.get_tokens(test_content))
+ txt = ""
+ for token in tokens:
+ a(isinstance(token, tuple))
+ a(isinstance(token[0], _TokenType))
+ a(isinstance(token[1], str))
+ txt += token[1]
+ ae(txt, test_content, "%s lexer roundtrip failed: %r != %r" %
+ (lexer.name, test_content, txt))
+
+ def test_get_lexers(self):
+ a = self.assert_
+ ae = self.assertEquals
+ # test that the lexers functions work
+
+ for func, args in [(lexers.get_lexer_by_name, ("python",)),
+ (lexers.get_lexer_for_filename, ("test.py",)),
+ (lexers.get_lexer_for_mimetype, ("text/x-python",)),
+ (lexers.guess_lexer, ("#!/usr/bin/python -O\nprint",)),
+ (lexers.guess_lexer_for_filename, ("a.py", "<%= @foo %>"))
+ ]:
+ x = func(opt="val", *args)
+ a(isinstance(x, lexers.PythonLexer))
+ ae(x.options["opt"], "val")
+
+
+class FormattersTest(unittest.TestCase):
+
+ def test_public_api(self):
+ a = self.assert_
+ ae = self.assertEquals
+ ts = list(lexers.PythonLexer().get_tokens("def f(): pass"))
+ out = StringIO.StringIO()
+ # test that every formatter class has the correct public API
+ for formatter, info in formatters.FORMATTERS.iteritems():
+ a(len(info) == 4)
+ a(info[0]) # name
+ a(info[1]) # aliases
+ a(info[3]) # doc
+
+ inst = formatter(opt1="val1")
+ inst.get_style_defs()
+ inst.format(ts, out)
+
+ def test_get_formatters(self):
+ a = self.assert_
+ ae = self.assertEquals
+ # test that the formatters functions work
+ x = formatters.get_formatter_by_name("html", opt="val")
+ a(isinstance(x, formatters.HtmlFormatter))
+ ae(x.options["opt"], "val")
+
+ x = formatters.get_formatter_for_filename("a.html", opt="val")
+ a(isinstance(x, formatters.HtmlFormatter))
+ ae(x.options["opt"], "val")
diff --git a/tests/test_clexer.py b/tests/test_clexer.py
index 145c6510..ce757890 100644
--- a/tests/test_clexer.py
+++ b/tests/test_clexer.py
@@ -32,4 +32,4 @@ class CLexerTest(unittest.TestCase):
if __name__ == '__main__':
- unittest.main(CLexerTest)
+ unittest.main()